[vulkan] Build particle buffers

This commit is contained in:
Bill Currie 2021-12-22 06:54:23 +09:00
parent a4c4155a51
commit 6d64b2c47c
3 changed files with 83 additions and 1 deletions

View file

@ -21,6 +21,14 @@ typedef struct qfv_parameters_s {
vec4f_t ramp; vec4f_t ramp;
} qfv_parameters_t; } qfv_parameters_t;
// Doubles as VkDrawIndirectCommand
typedef struct qfv_particle_system_s {
uint32_t vertexCount; // always 1
uint32_t particleCount;
uint32_t firstVertex; // always 0
uint32_t firstInstance; // always 0
} qfv_particle_system_t;
typedef enum { typedef enum {
QFV_particleTranslucent, QFV_particleTranslucent,
@ -50,6 +58,9 @@ typedef struct particlectx_s {
VkPipeline update; VkPipeline update;
VkPipeline draw; VkPipeline draw;
VkDeviceMemory memory;
struct qfv_stagebuf_s *stage;
VkDescriptorPool pool; VkDescriptorPool pool;
VkDescriptorSetLayout setLayout; VkDescriptorSetLayout setLayout;
VkPipelineLayout physics_layout; VkPipelineLayout physics_layout;

View file

@ -432,6 +432,14 @@
dstAccessMask = input_attachment_read|depth_stencil_attachment_read; dstAccessMask = input_attachment_read|depth_stencil_attachment_read;
dependencyFlags = by_region; dependencyFlags = by_region;
}, },
{
srcSubpass = ~0u; // external
dstSubpass = 1; // translucent
srcStageMask = compute_shader;
dstStageMask = vertex_input|draw_indirect;
srcAccessMask = shader_write;
dstAccessMask = vertex_attribute_read|indirect_command_read;
},
{ {
srcSubpass = 0; // depth srcSubpass = 0; // depth
dstSubpass = 2; // g-buffer dstSubpass = 2; // g-buffer

View file

@ -44,14 +44,20 @@
#include "QF/plugin/vid_render.h" #include "QF/plugin/vid_render.h"
#include "QF/Vulkan/qf_vid.h" //FIXME header issues
#include "QF/Vulkan/buffer.h"
#include "QF/Vulkan/debug.h" #include "QF/Vulkan/debug.h"
#include "QF/Vulkan/device.h" #include "QF/Vulkan/device.h"
#include "QF/Vulkan/instance.h" #include "QF/Vulkan/instance.h"
#include "QF/Vulkan/staging.h"
#include "QF/Vulkan/qf_particles.h" #include "QF/Vulkan/qf_particles.h"
#include "r_internal.h" #include "r_internal.h"
#include "vid_vulkan.h" #include "vid_vulkan.h"
//FIXME make dynamic
#define MaxParticles 2048
static const char * __attribute__((used)) particle_pass_names[] = { static const char * __attribute__((used)) particle_pass_names[] = {
"draw", "draw",
}; };
@ -61,6 +67,57 @@ Vulkan_DrawParticles (vulkan_ctx_t *ctx)
{ {
} }
static void
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;
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);
}
size_t stageSize = (size / pctx->frames.size)*(pctx->frames.size + 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++) {
__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);
}
}
void void
Vulkan_Particles_Init (vulkan_ctx_t *ctx) Vulkan_Particles_Init (vulkan_ctx_t *ctx)
{ {
@ -83,7 +140,7 @@ Vulkan_Particles_Init (vulkan_ctx_t *ctx)
"partphysics_layout"); "partphysics_layout");
pctx->update_layout = Vulkan_CreatePipelineLayout (ctx, pctx->update_layout = Vulkan_CreatePipelineLayout (ctx,
"partupdate_layout"); "partupdate_layout");
pctx->draw_layout = Vulkan_CreatePipelineLayout (ctx, "draw_layout"); pctx->draw_layout = Vulkan_CreatePipelineLayout (ctx, "partdraw_layout");
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");
@ -104,6 +161,7 @@ Vulkan_Particles_Init (vulkan_ctx_t *ctx)
particle_pass_names[j])); particle_pass_names[j]));
} }
} }
create_buffers (ctx);
qfvPopDebug (ctx); qfvPopDebug (ctx);
} }
@ -117,7 +175,12 @@ Vulkan_Particles_Shutdown (vulkan_ctx_t *ctx)
for (size_t i = 0; i < pctx->frames.size; i++) { for (size_t i = 0; i < pctx->frames.size; i++) {
__auto_type pframe = &pctx->frames.a[i]; __auto_type pframe = &pctx->frames.a[i];
free (pframe->cmdSet.a); 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->vkFreeMemory (device->dev, pctx->memory, 0);
QFV_DestroyStagingBuffer (pctx->stage);
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);