From d9b0ee22e68c6455dfac35c9d446098ddfb5b832 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 28 Nov 2022 00:52:07 +0900 Subject: [PATCH] [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. --- include/QF/Vulkan/funclist.h | 10 + include/QF/Vulkan/qf_particles.h | 15 +- include/QF/Vulkan/qf_vid.h | 1 + libs/video/renderer/vulkan/pl_quake_def.plist | 6 +- .../renderer/vulkan/shader/partupdate.comp | 47 +-- libs/video/renderer/vulkan/vulkan_particles.c | 280 +++++++++++++++--- .../video/renderer/vulkan/vulkan_vid_common.c | 2 + 7 files changed, 288 insertions(+), 73 deletions(-) diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 42da63794..1dedc4c5f 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -101,12 +101,17 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkEndCommandBuffer) DEVICE_LEVEL_VULKAN_FUNCTION (vkResetCommandBuffer) DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateSemaphore) DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateFence) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateEvent) DEVICE_LEVEL_VULKAN_FUNCTION (vkWaitForFences) DEVICE_LEVEL_VULKAN_FUNCTION (vkResetFences) 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 (vkQueueWaitIdle) DEVICE_LEVEL_VULKAN_FUNCTION (vkDeviceWaitIdle) +DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyEvent) DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyFence) DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroySemaphore) DEVICE_LEVEL_VULKAN_FUNCTION (vkFreeCommandBuffers) @@ -171,10 +176,15 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBeginRenderPass) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdNextSubpass) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdEndRenderPass) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindPipeline) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdDispatch) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdClearColorImage) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdExecuteCommands) 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 (vkCmdSetScissor) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindVertexBuffers) diff --git a/include/QF/Vulkan/qf_particles.h b/include/QF/Vulkan/qf_particles.h index 26feb51fb..9b90863a9 100644 --- a/include/QF/Vulkan/qf_particles.h +++ b/include/QF/Vulkan/qf_particles.h @@ -3,6 +3,7 @@ #include "QF/darray.h" #include "QF/image.h" +#include "QF/render.h" #include "QF/Vulkan/command.h" @@ -37,14 +38,15 @@ typedef enum { typedef struct particleframe_s { VkCommandBuffer compute; - VkSemaphore physSem; - VkSemaphore drawSem; - VkSemaphore updateSem; - VkBuffer state; + VkEvent physicsEvent; + VkEvent updateEvent; + VkBuffer states; VkBuffer params; VkBuffer system; - VkDescriptorSet descriptors; + VkDescriptorSet curDescriptors; + VkDescriptorSet inDescriptors; + VkDescriptorSet newDescriptors; qfv_cmdbufferset_t cmdSet; } particleframe_t; @@ -58,7 +60,7 @@ typedef struct particlectx_s { VkPipeline update; VkPipeline draw; - VkDeviceMemory memory; + struct qfv_resource_s *resources; struct qfv_stagebuf_s *stage; 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_Shutdown (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 diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index fed5e4928..1d74e90c1 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -39,6 +39,7 @@ */ enum { + QFV_rp_particles, QFV_rp_shadowmap, QFV_rp_preoutput, QFV_rp_main, diff --git a/libs/video/renderer/vulkan/pl_quake_def.plist b/libs/video/renderer/vulkan/pl_quake_def.plist index 389b31d34..7130ea6ac 100644 --- a/libs/video/renderer/vulkan/pl_quake_def.plist +++ b/libs/video/renderer/vulkan/pl_quake_def.plist @@ -178,11 +178,11 @@ }; particle_pool = { flags = 0; - maxSets = $frames.size; + maxSets = "3z * $frames.size"; bindings = ( { type = storage_buffer; - descriptorCount = 3; + descriptorCount = "3z * 3z * $frames.size"; }, ); }; @@ -499,7 +499,7 @@ { stageFlags = compute; offset = 0; - size = "16 * 4 + 4"; + size = "4 * 4 + 4"; }, ); }; diff --git a/libs/video/renderer/vulkan/shader/partupdate.comp b/libs/video/renderer/vulkan/shader/partupdate.comp index adce81094..5a5ccd56f 100644 --- a/libs/video/renderer/vulkan/shader/partupdate.comp +++ b/libs/video/renderer/vulkan/shader/partupdate.comp @@ -19,38 +19,38 @@ struct Parameters { vec4 ramp; // [rate, max, alpha rate, scale rate] }; -layout(std140, set = 0, binding = 0) buffer InStates { - 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 { +layout(std140, set = 0, binding = 0) buffer OutStates { Particle particles[]; } outStates; -layout(std140, set = 1, binding = 1) buffer OutParameters { +layout(std140, set = 0, binding = 1) buffer OutParameters { Parameters parameters[]; } outParameters; //doubles as VkDrawIndirectCommand -layout(std140, set = 1, binding = 2) buffer OutSystem { +layout(std140, set = 0, binding = 2) buffer OutSystem { uint vertexCount; uint particleCount; //instanceCount uint firstVertex; uint firstInstance; } 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 { Particle particles[]; } newStates; @@ -85,21 +85,24 @@ main () uint j = 0; // compact existing partles removing dead particles 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; } - outStates.particles[j] = inState.particles[i]; + outStates.particles[j] = inStates.particles[i]; outParameters.parameters[j] = inParameters.parameters[i]; j++; } // inject any new particles that aren't DOA 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; } outStates.particles[j] = newStates.particles[i]; outParameters.parameters[j] = newParameters.parameters[i]; j++; } + outSystem.vertexCount = newSystem.vertexCount; outSystem.particleCount = j; + outSystem.firstVertex = newSystem.firstVertex; + outSystem.firstInstance = newSystem.firstInstance; } diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index e2fe68ac7..ba712f256 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -44,16 +44,25 @@ #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/debug.h" +#include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/resource.h" #include "QF/Vulkan/staging.h" #include "QF/Vulkan/qf_particles.h" +#include "QF/Vulkan/qf_renderpass.h" +#include "r_internal.h" #include "vid_vulkan.h" //FIXME make dynamic #define MaxParticles 2048 +typedef struct { + vec4f_t gravity; + float dT; +} particle_push_constants_t; + static const char * __attribute__((used)) particle_pass_names[] = { "draw", }; @@ -69,48 +78,90 @@ create_buffers (vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; particlectx_t *pctx = ctx->particle_context; - size_t size = 0; size_t mp = MaxParticles; + size_t frames = ctx->frames.size; - VkMemoryRequirements stReq, parmReq, sysReq; - for (size_t i = 0; i < pctx->frames.size; i++) { - __auto_type pframe = &pctx->frames.a[i]; - pframe->state - = QFV_CreateBuffer (device, sizeof (qfv_particle_t) * mp, - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT - | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); - pframe->params - = QFV_CreateBuffer (device, sizeof (qfv_particle_t) * mp, - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); - pframe->system - = QFV_CreateBuffer (device, sizeof (qfv_particle_t) * mp, - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT - | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT); - dfunc->vkGetBufferMemoryRequirements (device->dev, pframe->state, - &stReq); - dfunc->vkGetBufferMemoryRequirements (device->dev, pframe->params, - &parmReq); - dfunc->vkGetBufferMemoryRequirements (device->dev, pframe->system, - &sysReq); - size = QFV_NextOffset (size + stReq.size, &stReq); - size = QFV_NextOffset (size + parmReq.size, &parmReq); - size = QFV_NextOffset (size + sysReq.size, &sysReq); + pctx->resources = malloc (sizeof (qfv_resource_t) + // states buffer + + frames * sizeof (qfv_resobj_t) + // params buffer + + frames * sizeof (qfv_resobj_t) + // system buffer + + frames * sizeof (qfv_resobj_t)); + __auto_type state_objs = (qfv_resobj_t *) &pctx->resources[1]; + __auto_type param_objs = &state_objs[frames]; + __auto_type system_objs = ¶m_objs[frames]; + pctx->resources[0] = (qfv_resource_t) { + .name = "particles", + .va_ctx = ctx->va_ctx, + .memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + .num_objects = 3 * frames, + .objects = state_objs, + }; + for (size_t i = 0; i < frames; i++) { + state_objs[i] = (qfv_resobj_t) { + .name = "states", + .type = qfv_res_buffer, + .buffer = { + .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, ctx->cmdpool); - pctx->memory = QFV_AllocBufferMemory (device, pctx->frames.a[0].state, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - size, 0); - size_t offset = 0; - 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]; - QFV_BindBufferMemory (device, pframe->state, pctx->memory, offset); - offset = QFV_NextOffset (offset + stReq.size, &parmReq); - QFV_BindBufferMemory (device, pframe->params, pctx->memory, offset); - offset = QFV_NextOffset (offset + parmReq.size, &sysReq); - QFV_BindBufferMemory (device, pframe->system, pctx->memory, offset); - offset = QFV_NextOffset (offset + sysReq.size, &stReq); + pframe->states = state_objs[i].buffer.buffer; + pframe->params = param_objs[i].buffer.buffer; + pframe->system = system_objs[i].buffer.buffer; + } + + 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) { qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; qfvPushDebug (ctx, "particles init"); @@ -141,9 +193,19 @@ Vulkan_Particles_Init (vulkan_ctx_t *ctx) pctx->pool = Vulkan_CreateDescriptorPool (ctx, "particle_pool"); 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++) { __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_RESIZE (&pframe->cmdSet, QFV_particleNumPasses); pframe->cmdSet.grow = 0; @@ -156,7 +218,18 @@ Vulkan_Particles_Init (vulkan_ctx_t *ctx) va (ctx->va_ctx, "cmd:particle:%zd:%s", i, 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); qfvPopDebug (ctx); } @@ -167,16 +240,17 @@ Vulkan_Particles_Shutdown (vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; 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]; - free (pframe->cmdSet.a); - dfunc->vkDestroyBuffer (device->dev, pframe->state, 0); - dfunc->vkDestroyBuffer (device->dev, pframe->params, 0); - dfunc->vkDestroyBuffer (device->dev, pframe->system, 0); + dfunc->vkDestroyEvent (device->dev, pframe->updateEvent, 0); + dfunc->vkDestroyEvent (device->dev, pframe->physicsEvent, 0); } - dfunc->vkFreeMemory (device->dev, pctx->memory, 0); + QFV_DestroyStagingBuffer (pctx->stage); + QFV_DestroyResource (device, pctx->resources); + free (pctx->resources); dfunc->vkDestroyPipeline (device->dev, pctx->physics, 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 } + +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); +} diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 9466fc92f..d1f5153e9 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -54,6 +54,7 @@ #include "QF/Vulkan/qf_lighting.h" #include "QF/Vulkan/qf_main.h" #include "QF/Vulkan/qf_output.h" +#include "QF/Vulkan/qf_particles.h" #include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_vid.h" @@ -166,6 +167,7 @@ Vulkan_CreateRenderPasses (vulkan_ctx_t *ctx) { Vulkan_Output_CreateRenderPasses (ctx); Vulkan_Main_CreateRenderPasses (ctx); + Vulkan_Particles_CreateRenderPasses (ctx); Vulkan_Lighting_CreateRenderPasses (ctx); heapsort (ctx->renderPasses.a, ctx->renderPasses.size,