[vulkan] Get particle compute pipelines running

I don't yet know whether they actually work (not rendering yet), but the
system isn't locking up, and shutdown is clean, so at least resources
are handled correctly.
This commit is contained in:
Bill Currie 2022-11-28 00:52:07 +09:00
parent dd1b15c92f
commit d9b0ee22e6
7 changed files with 288 additions and 73 deletions

View File

@ -101,12 +101,17 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkEndCommandBuffer)
DEVICE_LEVEL_VULKAN_FUNCTION (vkResetCommandBuffer) DEVICE_LEVEL_VULKAN_FUNCTION (vkResetCommandBuffer)
DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateSemaphore) DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateSemaphore)
DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateFence) DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateFence)
DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateEvent)
DEVICE_LEVEL_VULKAN_FUNCTION (vkWaitForFences) DEVICE_LEVEL_VULKAN_FUNCTION (vkWaitForFences)
DEVICE_LEVEL_VULKAN_FUNCTION (vkResetFences) DEVICE_LEVEL_VULKAN_FUNCTION (vkResetFences)
DEVICE_LEVEL_VULKAN_FUNCTION (vkGetFenceStatus) DEVICE_LEVEL_VULKAN_FUNCTION (vkGetFenceStatus)
DEVICE_LEVEL_VULKAN_FUNCTION (vkResetEvent)
DEVICE_LEVEL_VULKAN_FUNCTION (vkSetEvent)
DEVICE_LEVEL_VULKAN_FUNCTION (vkGetEventStatus)
DEVICE_LEVEL_VULKAN_FUNCTION (vkQueueSubmit) DEVICE_LEVEL_VULKAN_FUNCTION (vkQueueSubmit)
DEVICE_LEVEL_VULKAN_FUNCTION (vkQueueWaitIdle) DEVICE_LEVEL_VULKAN_FUNCTION (vkQueueWaitIdle)
DEVICE_LEVEL_VULKAN_FUNCTION (vkDeviceWaitIdle) DEVICE_LEVEL_VULKAN_FUNCTION (vkDeviceWaitIdle)
DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyEvent)
DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyFence) DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyFence)
DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroySemaphore) DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroySemaphore)
DEVICE_LEVEL_VULKAN_FUNCTION (vkFreeCommandBuffers) DEVICE_LEVEL_VULKAN_FUNCTION (vkFreeCommandBuffers)
@ -171,10 +176,15 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBeginRenderPass)
DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdNextSubpass) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdNextSubpass)
DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdEndRenderPass) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdEndRenderPass)
DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindPipeline) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindPipeline)
DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdDispatch)
DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdClearColorImage) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdClearColorImage)
DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdExecuteCommands) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdExecuteCommands)
DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdPushConstants) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdPushConstants)
DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdResetEvent)
DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdSetEvent)
DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdWaitEvents)
DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdSetViewport) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdSetViewport)
DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdSetScissor) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdSetScissor)
DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindVertexBuffers) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindVertexBuffers)

View File

@ -3,6 +3,7 @@
#include "QF/darray.h" #include "QF/darray.h"
#include "QF/image.h" #include "QF/image.h"
#include "QF/render.h"
#include "QF/Vulkan/command.h" #include "QF/Vulkan/command.h"
@ -37,14 +38,15 @@ typedef enum {
typedef struct particleframe_s { typedef struct particleframe_s {
VkCommandBuffer compute; VkCommandBuffer compute;
VkSemaphore physSem; VkEvent physicsEvent;
VkSemaphore drawSem; VkEvent updateEvent;
VkSemaphore updateSem; VkBuffer states;
VkBuffer state;
VkBuffer params; VkBuffer params;
VkBuffer system; VkBuffer system;
VkDescriptorSet descriptors; VkDescriptorSet curDescriptors;
VkDescriptorSet inDescriptors;
VkDescriptorSet newDescriptors;
qfv_cmdbufferset_t cmdSet; qfv_cmdbufferset_t cmdSet;
} particleframe_t; } particleframe_t;
@ -58,7 +60,7 @@ typedef struct particlectx_s {
VkPipeline update; VkPipeline update;
VkPipeline draw; VkPipeline draw;
VkDeviceMemory memory; struct qfv_resource_s *resources;
struct qfv_stagebuf_s *stage; struct qfv_stagebuf_s *stage;
VkDescriptorPool pool; VkDescriptorPool pool;
@ -77,5 +79,6 @@ struct psystem_s *Vulkan_ParticleSystem (struct vulkan_ctx_s *ctx);
void Vulkan_Particles_Init (struct vulkan_ctx_s *ctx); void Vulkan_Particles_Init (struct vulkan_ctx_s *ctx);
void Vulkan_Particles_Shutdown (struct vulkan_ctx_s *ctx); void Vulkan_Particles_Shutdown (struct vulkan_ctx_s *ctx);
void Vulkan_DrawParticles (struct vulkan_ctx_s *ctx); void Vulkan_DrawParticles (struct vulkan_ctx_s *ctx);
void Vulkan_Particles_CreateRenderPasses (struct vulkan_ctx_s *ctx);
#endif//__QF_Vulkan_qf_particles_h #endif//__QF_Vulkan_qf_particles_h

View File

@ -39,6 +39,7 @@
*/ */
enum { enum {
QFV_rp_particles,
QFV_rp_shadowmap, QFV_rp_shadowmap,
QFV_rp_preoutput, QFV_rp_preoutput,
QFV_rp_main, QFV_rp_main,

View File

@ -178,11 +178,11 @@
}; };
particle_pool = { particle_pool = {
flags = 0; flags = 0;
maxSets = $frames.size; maxSets = "3z * $frames.size";
bindings = ( bindings = (
{ {
type = storage_buffer; type = storage_buffer;
descriptorCount = 3; descriptorCount = "3z * 3z * $frames.size";
}, },
); );
}; };
@ -499,7 +499,7 @@
{ {
stageFlags = compute; stageFlags = compute;
offset = 0; offset = 0;
size = "16 * 4 + 4"; size = "4 * 4 + 4";
}, },
); );
}; };

View File

@ -19,38 +19,38 @@ struct Parameters {
vec4 ramp; // [rate, max, alpha rate, scale rate] vec4 ramp; // [rate, max, alpha rate, scale rate]
}; };
layout(std140, set = 0, binding = 0) buffer InStates { layout(std140, set = 0, binding = 0) buffer OutStates {
Particle particles[];
} inState;
layout(std140, set = 0, binding = 1) buffer InParameters {
Parameters parameters[];
} inParameters;
//doubles as VkDrawIndirectCommand
layout(std140, set = 0, binding = 2) buffer InSystem {
uint vertexCount;
uint particleCount; //instanceCount
uint firstVertex;
uint firstInstance;
} inSystem;
layout(std140, set = 1, binding = 0) buffer OutStates {
Particle particles[]; Particle particles[];
} outStates; } outStates;
layout(std140, set = 1, binding = 1) buffer OutParameters { layout(std140, set = 0, binding = 1) buffer OutParameters {
Parameters parameters[]; Parameters parameters[];
} outParameters; } outParameters;
//doubles as VkDrawIndirectCommand //doubles as VkDrawIndirectCommand
layout(std140, set = 1, binding = 2) buffer OutSystem { layout(std140, set = 0, binding = 2) buffer OutSystem {
uint vertexCount; uint vertexCount;
uint particleCount; //instanceCount uint particleCount; //instanceCount
uint firstVertex; uint firstVertex;
uint firstInstance; uint firstInstance;
} outSystem; } outSystem;
layout(std140, set = 1, binding = 0) buffer InStates {
Particle particles[];
} inStates;
layout(std140, set = 1, binding = 1) buffer InParameters {
Parameters parameters[];
} inParameters;
//doubles as VkDrawIndirectCommand
layout(std140, set = 1, binding = 2) buffer InSystem {
uint vertexCount;
uint particleCount; //instanceCount
uint firstVertex;
uint firstInstance;
} inSystem;
layout(std140, set = 2, binding = 0) buffer NewStates { layout(std140, set = 2, binding = 0) buffer NewStates {
Particle particles[]; Particle particles[];
} newStates; } newStates;
@ -85,21 +85,24 @@ main ()
uint j = 0; uint j = 0;
// compact existing partles removing dead particles // compact existing partles removing dead particles
for (uint i = 0; i < inSystem.particleCount; i++) { for (uint i = 0; i < inSystem.particleCount; i++) {
if (is_dead (inState.particles[i], inParameters.parameters[i])) { if (is_dead (inStates.particles[i], inParameters.parameters[i])) {
continue; continue;
} }
outStates.particles[j] = inState.particles[i]; outStates.particles[j] = inStates.particles[i];
outParameters.parameters[j] = inParameters.parameters[i]; outParameters.parameters[j] = inParameters.parameters[i];
j++; j++;
} }
// inject any new particles that aren't DOA // inject any new particles that aren't DOA
for (uint i = 0; i < newSystem.particleCount && j < MaxParticles; i++) { for (uint i = 0; i < newSystem.particleCount && j < MaxParticles; i++) {
if (is_dead (inState.particles[i], inParameters.parameters[i])) { if (is_dead (newStates.particles[i], newParameters.parameters[i])) {
continue; continue;
} }
outStates.particles[j] = newStates.particles[i]; outStates.particles[j] = newStates.particles[i];
outParameters.parameters[j] = newParameters.parameters[i]; outParameters.parameters[j] = newParameters.parameters[i];
j++; j++;
} }
outSystem.vertexCount = newSystem.vertexCount;
outSystem.particleCount = j; outSystem.particleCount = j;
outSystem.firstVertex = newSystem.firstVertex;
outSystem.firstInstance = newSystem.firstInstance;
} }

View File

@ -44,16 +44,25 @@
#include "QF/Vulkan/buffer.h" #include "QF/Vulkan/buffer.h"
#include "QF/Vulkan/debug.h" #include "QF/Vulkan/debug.h"
#include "QF/Vulkan/descriptor.h"
#include "QF/Vulkan/device.h" #include "QF/Vulkan/device.h"
#include "QF/Vulkan/instance.h" #include "QF/Vulkan/instance.h"
#include "QF/Vulkan/resource.h"
#include "QF/Vulkan/staging.h" #include "QF/Vulkan/staging.h"
#include "QF/Vulkan/qf_particles.h" #include "QF/Vulkan/qf_particles.h"
#include "QF/Vulkan/qf_renderpass.h"
#include "r_internal.h"
#include "vid_vulkan.h" #include "vid_vulkan.h"
//FIXME make dynamic //FIXME make dynamic
#define MaxParticles 2048 #define MaxParticles 2048
typedef struct {
vec4f_t gravity;
float dT;
} particle_push_constants_t;
static const char * __attribute__((used)) particle_pass_names[] = { static const char * __attribute__((used)) particle_pass_names[] = {
"draw", "draw",
}; };
@ -69,48 +78,90 @@ create_buffers (vulkan_ctx_t *ctx)
qfv_device_t *device = ctx->device; qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs; qfv_devfuncs_t *dfunc = device->funcs;
particlectx_t *pctx = ctx->particle_context; particlectx_t *pctx = ctx->particle_context;
size_t size = 0;
size_t mp = MaxParticles; size_t mp = MaxParticles;
size_t frames = ctx->frames.size;
VkMemoryRequirements stReq, parmReq, sysReq; pctx->resources = malloc (sizeof (qfv_resource_t)
for (size_t i = 0; i < pctx->frames.size; i++) { // states buffer
__auto_type pframe = &pctx->frames.a[i]; + frames * sizeof (qfv_resobj_t)
pframe->state // params buffer
= QFV_CreateBuffer (device, sizeof (qfv_particle_t) * mp, + frames * sizeof (qfv_resobj_t)
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT // system buffer
| VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + frames * sizeof (qfv_resobj_t));
pframe->params __auto_type state_objs = (qfv_resobj_t *) &pctx->resources[1];
= QFV_CreateBuffer (device, sizeof (qfv_particle_t) * mp, __auto_type param_objs = &state_objs[frames];
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); __auto_type system_objs = &param_objs[frames];
pframe->system pctx->resources[0] = (qfv_resource_t) {
= QFV_CreateBuffer (device, sizeof (qfv_particle_t) * mp, .name = "particles",
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT .va_ctx = ctx->va_ctx,
| VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT); .memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
dfunc->vkGetBufferMemoryRequirements (device->dev, pframe->state, .num_objects = 3 * frames,
&stReq); .objects = state_objs,
dfunc->vkGetBufferMemoryRequirements (device->dev, pframe->params, };
&parmReq); for (size_t i = 0; i < frames; i++) {
dfunc->vkGetBufferMemoryRequirements (device->dev, pframe->system, state_objs[i] = (qfv_resobj_t) {
&sysReq); .name = "states",
size = QFV_NextOffset (size + stReq.size, &stReq); .type = qfv_res_buffer,
size = QFV_NextOffset (size + parmReq.size, &parmReq); .buffer = {
size = QFV_NextOffset (size + sysReq.size, &sysReq); .size = mp * sizeof (qfv_particle_t),
.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
| VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
},
};
param_objs[i] = (qfv_resobj_t) {
.name = "params",
.type = qfv_res_buffer,
.buffer = {
.size = mp * sizeof (qfv_parameters_t),
.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
},
};
system_objs[i] = (qfv_resobj_t) {
.name = "system",
.type = qfv_res_buffer,
.buffer = {
.size = sizeof (qfv_particle_system_t),
.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
| VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT,
},
};
} }
size_t stageSize = (size / pctx->frames.size)*(pctx->frames.size + 1); QFV_CreateResource (device, pctx->resources);
size_t stageSize = (pctx->resources->size / frames)*(frames + 1);
pctx->stage = QFV_CreateStagingBuffer (device, "particles", stageSize, pctx->stage = QFV_CreateStagingBuffer (device, "particles", stageSize,
ctx->cmdpool); ctx->cmdpool);
pctx->memory = QFV_AllocBufferMemory (device, pctx->frames.a[0].state, for (size_t i = 0; i < frames; i++) {
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
size, 0);
size_t offset = 0;
for (size_t i = 0; i < pctx->frames.size; i++) {
__auto_type pframe = &pctx->frames.a[i]; __auto_type pframe = &pctx->frames.a[i];
QFV_BindBufferMemory (device, pframe->state, pctx->memory, offset); pframe->states = state_objs[i].buffer.buffer;
offset = QFV_NextOffset (offset + stReq.size, &parmReq); pframe->params = param_objs[i].buffer.buffer;
QFV_BindBufferMemory (device, pframe->params, pctx->memory, offset); pframe->system = system_objs[i].buffer.buffer;
offset = QFV_NextOffset (offset + parmReq.size, &sysReq); }
QFV_BindBufferMemory (device, pframe->system, pctx->memory, offset);
offset = QFV_NextOffset (offset + sysReq.size, &stReq); for (size_t i = 0; i < frames; i++) {
__auto_type curr = &pctx->frames.a[i];
__auto_type prev = &pctx->frames.a[(i + frames - 1) % frames];
VkDescriptorBufferInfo bufferInfo[] = {
{ curr->states, 0, VK_WHOLE_SIZE },
{ curr->params, 0, VK_WHOLE_SIZE },
{ curr->system, 0, VK_WHOLE_SIZE },
{ prev->states, 0, VK_WHOLE_SIZE },
{ prev->params, 0, VK_WHOLE_SIZE },
{ prev->system, 0, VK_WHOLE_SIZE },
};
VkWriteDescriptorSet write[] = {
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
curr->curDescriptors, 0, 0, 3,
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.pBufferInfo = bufferInfo + 0
},
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
curr->inDescriptors, 0, 0, 3,
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.pBufferInfo = bufferInfo + 3
},
};
dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0);
} }
} }
@ -118,6 +169,7 @@ void
Vulkan_Particles_Init (vulkan_ctx_t *ctx) Vulkan_Particles_Init (vulkan_ctx_t *ctx)
{ {
qfv_device_t *device = ctx->device; qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
qfvPushDebug (ctx, "particles init"); qfvPushDebug (ctx, "particles init");
@ -141,9 +193,19 @@ Vulkan_Particles_Init (vulkan_ctx_t *ctx)
pctx->pool = Vulkan_CreateDescriptorPool (ctx, "particle_pool"); pctx->pool = Vulkan_CreateDescriptorPool (ctx, "particle_pool");
pctx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "particle_set"); pctx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "particle_set");
__auto_type layouts = QFV_AllocDescriptorSetLayoutSet (3 * frames, alloca);
for (size_t i = 0; i < layouts->size; i++) {
layouts->a[i] = pctx->setLayout;
}
__auto_type sets = QFV_AllocateDescriptorSet (device, pctx->pool, layouts);
for (size_t i = 0; i < frames; i++) { for (size_t i = 0; i < frames; i++) {
__auto_type pframe = &pctx->frames.a[i]; __auto_type pframe = &pctx->frames.a[i];
pframe->curDescriptors = sets->a[i * 3 + 0];
pframe->inDescriptors = sets->a[i * 3 + 1];
pframe->newDescriptors = sets->a[i * 3 + 2];
DARRAY_INIT (&pframe->cmdSet, QFV_particleNumPasses); DARRAY_INIT (&pframe->cmdSet, QFV_particleNumPasses);
DARRAY_RESIZE (&pframe->cmdSet, QFV_particleNumPasses); DARRAY_RESIZE (&pframe->cmdSet, QFV_particleNumPasses);
pframe->cmdSet.grow = 0; pframe->cmdSet.grow = 0;
@ -156,7 +218,18 @@ Vulkan_Particles_Init (vulkan_ctx_t *ctx)
va (ctx->va_ctx, "cmd:particle:%zd:%s", i, va (ctx->va_ctx, "cmd:particle:%zd:%s", i,
particle_pass_names[j])); particle_pass_names[j]));
} }
VkEventCreateInfo event = { VK_STRUCTURE_TYPE_EVENT_CREATE_INFO };
dfunc->vkCreateEvent (device->dev, &event, 0, &pframe->physicsEvent);
dfunc->vkCreateEvent (device->dev, &event, 0, &pframe->updateEvent);
QFV_duSetObjectName (device, VK_OBJECT_TYPE_EVENT,
pframe->physicsEvent,
va (ctx->va_ctx, "event:particle:physics:%zd", i));
QFV_duSetObjectName (device, VK_OBJECT_TYPE_EVENT,
pframe->updateEvent,
va (ctx->va_ctx, "event:particle:update:%zd", i));
} }
free (sets);
create_buffers (ctx); create_buffers (ctx);
qfvPopDebug (ctx); qfvPopDebug (ctx);
} }
@ -167,16 +240,17 @@ Vulkan_Particles_Shutdown (vulkan_ctx_t *ctx)
qfv_device_t *device = ctx->device; qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs; qfv_devfuncs_t *dfunc = device->funcs;
particlectx_t *pctx = ctx->particle_context; particlectx_t *pctx = ctx->particle_context;
size_t frames = ctx->frames.size;
for (size_t i = 0; i < pctx->frames.size; i++) { for (size_t i = 0; i < frames; i++) {
__auto_type pframe = &pctx->frames.a[i]; __auto_type pframe = &pctx->frames.a[i];
free (pframe->cmdSet.a); dfunc->vkDestroyEvent (device->dev, pframe->updateEvent, 0);
dfunc->vkDestroyBuffer (device->dev, pframe->state, 0); dfunc->vkDestroyEvent (device->dev, pframe->physicsEvent, 0);
dfunc->vkDestroyBuffer (device->dev, pframe->params, 0);
dfunc->vkDestroyBuffer (device->dev, pframe->system, 0);
} }
dfunc->vkFreeMemory (device->dev, pctx->memory, 0);
QFV_DestroyStagingBuffer (pctx->stage); QFV_DestroyStagingBuffer (pctx->stage);
QFV_DestroyResource (device, pctx->resources);
free (pctx->resources);
dfunc->vkDestroyPipeline (device->dev, pctx->physics, 0); dfunc->vkDestroyPipeline (device->dev, pctx->physics, 0);
dfunc->vkDestroyPipeline (device->dev, pctx->update, 0); dfunc->vkDestroyPipeline (device->dev, pctx->update, 0);
@ -190,3 +264,125 @@ Vulkan_ParticleSystem (vulkan_ctx_t *ctx)
{ {
return &ctx->particle_context->psystem; //FIXME support more return &ctx->particle_context->psystem; //FIXME support more
} }
static void
particles_update (qfv_renderframe_t *rFrame)
{
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
particlectx_t *pctx = ctx->particle_context;
__auto_type pframe = &pctx->frames.a[ctx->curFrame];
qfv_packet_t *packet = QFV_PacketAcquire (pctx->stage);
__auto_type limits = &device->physDev->properties->limits;
VkMemoryRequirements req = {
.alignment = limits->minStorageBufferOffsetAlignment
};
uint32_t numParticles = min (MaxParticles, pctx->psystem.numparticles);
size_t syssize = sizeof (qfv_particle_system_t);
size_t partoffs = QFV_NextOffset (syssize, &req);
size_t partsize = sizeof (qfv_particle_t) * numParticles;
size_t paramoffs = QFV_NextOffset (partoffs + partsize, &req);
size_t paramsize = sizeof (qfv_parameters_t) * numParticles;
size_t size = paramoffs + paramsize;
qfv_particle_system_t *system = QFV_PacketExtend (packet, size);
*system = (qfv_particle_system_t) {
.vertexCount = 1,
.particleCount = numParticles,
};
__auto_type particles = (qfv_particle_t *) ((byte *)system + partoffs);
memcpy (particles, pctx->psystem.particles, partsize);
qfv_parameters_t *params = (qfv_parameters_t *)((byte *)system + paramoffs);
memcpy (params, pctx->psystem.partparams, paramsize);
VkDescriptorBufferInfo bufferInfo[] = {
{ packet->stage->buffer, 0, syssize },
{ packet->stage->buffer, partoffs, partsize ? partsize : 1},
{ packet->stage->buffer, paramoffs, paramsize ? paramsize : 1},
};
VkWriteDescriptorSet write[] = {
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
pframe->newDescriptors, 0, 0, 3,
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.pBufferInfo = bufferInfo
},
};
dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0);
dfunc->vkResetEvent (device->dev, pframe->updateEvent);
dfunc->vkResetEvent (device->dev, pframe->physicsEvent);
dfunc->vkCmdBindPipeline (packet->cmd, VK_PIPELINE_BIND_POINT_COMPUTE,
pctx->update);
VkDescriptorSet set[3] = {
pframe->curDescriptors,
pframe->inDescriptors,
pframe->newDescriptors,
};
dfunc->vkCmdBindDescriptorSets (packet->cmd, VK_PIPELINE_BIND_POINT_COMPUTE,
pctx->update_layout, 0, 3, set, 0, 0);
dfunc->vkCmdDispatch (packet->cmd, 1, 1, 1);
dfunc->vkCmdSetEvent (packet->cmd, pframe->updateEvent,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
VkBufferMemoryBarrier barrier[] = {
{ VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0,
VK_ACCESS_SHADER_WRITE_BIT,
VK_ACCESS_SHADER_READ_BIT
| VK_ACCESS_SHADER_WRITE_BIT,
0, 0,
pframe->states, 0, VK_WHOLE_SIZE },
{ VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0,
VK_ACCESS_SHADER_WRITE_BIT,
VK_ACCESS_SHADER_READ_BIT
| VK_ACCESS_SHADER_WRITE_BIT,
0, 0,
pframe->params, 0, VK_WHOLE_SIZE },
{ VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0,
VK_ACCESS_SHADER_WRITE_BIT,
VK_ACCESS_SHADER_READ_BIT
| VK_ACCESS_SHADER_WRITE_BIT,
0, 0,
pframe->system, 0, VK_WHOLE_SIZE },
};
dfunc->vkCmdWaitEvents (packet->cmd, 1, &pframe->updateEvent,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
0, 0,
3, barrier,
0, 0);
dfunc->vkCmdBindPipeline (packet->cmd, VK_PIPELINE_BIND_POINT_COMPUTE,
pctx->physics);
dfunc->vkCmdBindDescriptorSets (packet->cmd, VK_PIPELINE_BIND_POINT_COMPUTE,
pctx->physics_layout, 0, 1, set, 0, 0);
particle_push_constants_t constants = {
.gravity = pctx->psystem.gravity,
.dT = vr_data.frametime,
};
qfv_push_constants_t push_constants[] = {
{ VK_SHADER_STAGE_COMPUTE_BIT,
field_offset (particle_push_constants_t, gravity),
sizeof (vec4f_t), &constants.gravity },
{ VK_SHADER_STAGE_COMPUTE_BIT,
field_offset (particle_push_constants_t, dT),
sizeof (float), &constants.dT },
};
QFV_PushConstants (device, packet->cmd, pctx->physics_layout,
2, push_constants);
dfunc->vkCmdDispatch (packet->cmd, 8, 8, 8);
dfunc->vkCmdSetEvent (packet->cmd, pframe->physicsEvent,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
QFV_PacketSubmit (packet);
}
void
Vulkan_Particles_CreateRenderPasses (vulkan_ctx_t *ctx)
{
__auto_type rp = QFV_RenderPass_New (ctx, "particles", particles_update);
rp->order = QFV_rp_particles;
DARRAY_APPEND (&ctx->renderPasses, rp);
}

View File

@ -54,6 +54,7 @@
#include "QF/Vulkan/qf_lighting.h" #include "QF/Vulkan/qf_lighting.h"
#include "QF/Vulkan/qf_main.h" #include "QF/Vulkan/qf_main.h"
#include "QF/Vulkan/qf_output.h" #include "QF/Vulkan/qf_output.h"
#include "QF/Vulkan/qf_particles.h"
#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_renderpass.h"
#include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/qf_vid.h"
@ -166,6 +167,7 @@ Vulkan_CreateRenderPasses (vulkan_ctx_t *ctx)
{ {
Vulkan_Output_CreateRenderPasses (ctx); Vulkan_Output_CreateRenderPasses (ctx);
Vulkan_Main_CreateRenderPasses (ctx); Vulkan_Main_CreateRenderPasses (ctx);
Vulkan_Particles_CreateRenderPasses (ctx);
Vulkan_Lighting_CreateRenderPasses (ctx); Vulkan_Lighting_CreateRenderPasses (ctx);
heapsort (ctx->renderPasses.a, ctx->renderPasses.size, heapsort (ctx->renderPasses.a, ctx->renderPasses.size,