mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-11 07:42:18 +00:00
[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:
parent
dd1b15c92f
commit
d9b0ee22e6
7 changed files with 288 additions and 73 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
*/
|
||||
|
||||
enum {
|
||||
QFV_rp_particles,
|
||||
QFV_rp_shadowmap,
|
||||
QFV_rp_preoutput,
|
||||
QFV_rp_main,
|
||||
|
|
|
@ -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";
|
||||
},
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue