Skip to content

Commit

Permalink
Replaced the single static model vertex buffer with dynamically creat…
Browse files Browse the repository at this point in the history
…ed per-model VBs, to avoid large transfers on every model load.
apanteleev committed Jul 13, 2020
1 parent 294fcea commit aa06bcd
Showing 8 changed files with 311 additions and 174 deletions.
4 changes: 0 additions & 4 deletions src/refresh/models.c
Original file line number Diff line number Diff line change
@@ -414,10 +414,6 @@ qhandle_t R_RegisterModel(const char *name)

done:
index = (model - r_models) + 1;
#if USE_REF == REF_VKPT
extern int register_model_dirty;
register_model_dirty = 1;
#endif
return index;

fail2:
15 changes: 5 additions & 10 deletions src/refresh/vkpt/main.c
Original file line number Diff line number Diff line change
@@ -431,8 +431,6 @@ static const VkApplicationInfo vk_app_info = {
/* use this to override file names */
static const char *shader_module_file_names[NUM_QVK_SHADER_MODULES];

int register_model_dirty;

void
get_vk_extension_list(
const char *layer,
@@ -1332,8 +1330,10 @@ static inline uint32_t fill_model_instance(const entity_t* entity, const model_t
if (oldframe >= model->numframes) oldframe = 0;

memcpy(instance->M, transform, sizeof(float) * 16);
instance->offset_curr = mesh->vertex_offset + frame * mesh->numverts;
instance->offset_prev = mesh->vertex_offset + oldframe * mesh->numverts;
instance->idx_offset = mesh->idx_offset;
instance->model_index = model - r_models;
instance->offset_curr = mesh->vertex_offset + frame * mesh->numverts * (sizeof(model_vertex_t) / sizeof(uint32_t));
instance->offset_prev = mesh->vertex_offset + oldframe * mesh->numverts * (sizeof(model_vertex_t) / sizeof(uint32_t));
instance->backlerp = entity->backlerp;
instance->material = material_id;
instance->alpha = (entity->flags & RF_TRANSLUCENT) ? entity->alpha : 1.0f;
@@ -2733,12 +2733,7 @@ retry:;
vkpt_textures_end_registration();
vkpt_textures_update_descriptor_set();

/* cannot be called in R_EndRegistration as it would miss the initially textures (charset etc) */
if(register_model_dirty) {
_VK(vkpt_vertex_buffer_upload_models_to_staging());
_VK(vkpt_vertex_buffer_model_upload_staging());
register_model_dirty = 0;
}
vkpt_vertex_buffer_upload_models();
vkpt_draw_clear_stretch_pics();

SCR_SetHudAlpha(1.f);
24 changes: 20 additions & 4 deletions src/refresh/vkpt/shader/global_ubo.h
Original file line number Diff line number Diff line change
@@ -234,8 +234,16 @@ typedef uint32_t uint;

typedef struct {
float M[16]; // 16
uint32_t material; int offset_curr, offset_prev; float backlerp; // 4
float alpha; float padding[3];

uint32_t material;
int offset_curr;
int offset_prev;
float backlerp;

float alpha;
int idx_offset;
int model_index;
int pad;
} ModelInstance;

typedef struct {
@@ -261,8 +269,16 @@ typedef struct QVKInstanceBuffer_s {

struct ModelInstance {
mat4 M;
uvec4 mat_offset_backlerp;
vec4 alpha;

uint material;
int offset_curr;
int offset_prev;
float backlerp;

float alpha;
int idx_offset;
int model_index;
int pad;
};

struct BspMeshInstance {
96 changes: 81 additions & 15 deletions src/refresh/vkpt/shader/instance_geometry.comp
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,

#version 460
#extension GL_GOOGLE_include_directive : enable
#extension GL_EXT_nonuniform_qualifier : enable

#include "utils.glsl"

@@ -38,6 +39,75 @@ with this program; if not, write to the Free Software Foundation, Inc.,

#include "read_visbuf.glsl"

layout(set = 2, binding = 0) readonly buffer MODEL_VBO {
uint data[];
} model_vbos[];

vec2 get_model_float2(uint model_id, uint offset)
{
vec2 result;
result.x = uintBitsToFloat(model_vbos[nonuniformEXT(model_id)].data[offset + 0]);
result.y = uintBitsToFloat(model_vbos[nonuniformEXT(model_id)].data[offset + 1]);
return result;
}

vec3 get_model_float3(uint model_id, uint offset)
{
vec3 result;
result.x = uintBitsToFloat(model_vbos[nonuniformEXT(model_id)].data[offset + 0]);
result.y = uintBitsToFloat(model_vbos[nonuniformEXT(model_id)].data[offset + 1]);
result.z = uintBitsToFloat(model_vbos[nonuniformEXT(model_id)].data[offset + 2]);
return result;
}

vec4 get_model_float4(uint model_id, uint offset)
{
vec4 result;
result.x = uintBitsToFloat(model_vbos[nonuniformEXT(model_id)].data[offset + 0]);
result.y = uintBitsToFloat(model_vbos[nonuniformEXT(model_id)].data[offset + 1]);
result.z = uintBitsToFloat(model_vbos[nonuniformEXT(model_id)].data[offset + 2]);
result.w = uintBitsToFloat(model_vbos[nonuniformEXT(model_id)].data[offset + 3]);
return result;
}

Triangle
get_model_triangle(uint model_id, uint prim_id, uint idx_offset, uint vert_offset)
{
uint idx_base = idx_offset + prim_id * 3;

uvec3 idx;
idx.x = model_vbos[nonuniformEXT(model_id)].data[idx_base + 0];
idx.y = model_vbos[nonuniformEXT(model_id)].data[idx_base + 1];
idx.z = model_vbos[nonuniformEXT(model_id)].data[idx_base + 2];

idx = idx * MODEL_VERTEX_SIZE + vert_offset;

Triangle t;
t.positions[0] = get_model_float3(model_id, idx[0] + MODEL_VERTEX_POSITION);
t.positions[1] = get_model_float3(model_id, idx[1] + MODEL_VERTEX_POSITION);
t.positions[2] = get_model_float3(model_id, idx[2] + MODEL_VERTEX_POSITION);

t.normals[0] = get_model_float3(model_id, idx[0] + MODEL_VERTEX_NORMAL);
t.normals[1] = get_model_float3(model_id, idx[1] + MODEL_VERTEX_NORMAL);
t.normals[2] = get_model_float3(model_id, idx[2] + MODEL_VERTEX_NORMAL);

t.tex_coords[0] = get_model_float2(model_id, idx[0] + MODEL_VERTEX_TEXCOORD);
t.tex_coords[1] = get_model_float2(model_id, idx[1] + MODEL_VERTEX_TEXCOORD);
t.tex_coords[2] = get_model_float2(model_id, idx[2] + MODEL_VERTEX_TEXCOORD);

vec4 tangent = get_model_float4(model_id, idx[0] + MODEL_VERTEX_TANGENTS);
t.tangent = tangent.xyz;

t.material_id = 0; // needs to come from uniform buffer
if(tangent.w < 0)
t.material_id |= MATERIAL_FLAG_HANDEDNESS;

t.alpha = 1.0;
t.texel_density = 0;

return t;
}

#define LOCAL_SIZE_X 512

layout(local_size_x = LOCAL_SIZE_X, local_size_y = 1, local_size_z = 1) in;
@@ -51,7 +121,7 @@ main()

bool is_world = (model_index & 0x80000000) != 0;
uint buf_offset, num_triangles;

if(is_world)
{
instance_id = ~model_index;
@@ -110,19 +180,14 @@ main()
}
}
else { /* model */
/* idx_offset should stay the same across frames */
uint idx_offset = instance_buffer.model_idx_offset[instance_id];

{
/* read and interpolate triangles for model for _current_ frame */
ModelInstance mi_curr = instance_buffer.model_instances[instance_id];
uint vertex_off_curr = mi_curr.mat_offset_backlerp.y;
uint vertex_off_prev = mi_curr.mat_offset_backlerp.z; // referes to animation frame
Triangle t = get_model_triangle(idx, idx_offset, vertex_off_curr);
Triangle t_prev = get_model_triangle(idx, idx_offset, vertex_off_prev);
Triangle t = get_model_triangle(mi_curr.model_index, idx, mi_curr.idx_offset, mi_curr.offset_curr);
Triangle t_prev = get_model_triangle(mi_curr.model_index, idx, mi_curr.idx_offset, mi_curr.offset_prev);
M_curr = mi_curr.M;

float backlerp = uintBitsToFloat(mi_curr.mat_offset_backlerp.w);
float backlerp = mi_curr.backlerp;

t_i.positions[0] = mix(t.positions[0], t_prev.positions[0], backlerp);
t_i.positions[1] = mix(t.positions[1], t_prev.positions[1], backlerp);
@@ -139,30 +204,31 @@ main()

t_i.tex_coords = t.tex_coords;

t_i.material_id = t.material_id | mi_curr.mat_offset_backlerp.x;
t_i.material_id = t.material_id | mi_curr.material;
t_i.cluster = instance_buffer.model_cluster_id[instance_id];
}

{
uint id_prev = instance_buffer.model_current_to_prev[instance_id];

if(id_prev != ~0u)
{
ModelInstance mi_prev = instance_buffer.model_instances_prev[id_prev];
/* read and interpolate triangles for model for _previous_ frame */
uint vertex_off_curr = mi_prev.mat_offset_backlerp.y;
uint vertex_off_prev = mi_prev.mat_offset_backlerp.z; // referes to animation frame
Triangle t = get_model_triangle(idx, idx_offset, vertex_off_curr);
Triangle t_prev = get_model_triangle(idx, idx_offset, vertex_off_prev);
Triangle t = get_model_triangle(mi_prev.model_index, idx, mi_prev.idx_offset, mi_prev.offset_curr);
Triangle t_prev = get_model_triangle(mi_prev.model_index, idx, mi_prev.idx_offset, mi_prev.offset_prev);
M_prev = mi_prev.M;

float backlerp = uintBitsToFloat(mi_prev.mat_offset_backlerp.w);
float backlerp = mi_prev.backlerp;

t_i.positions_prev[0] = mix(t.positions[0], t_prev.positions[0], backlerp);
t_i.positions_prev[1] = mix(t.positions[1], t_prev.positions[1], backlerp);
t_i.positions_prev[2] = mix(t.positions[2], t_prev.positions[2], backlerp);
}
else
{
M_prev = M_curr;

t_i.positions_prev[0] = t_i.positions[0];
t_i.positions_prev[1] = t_i.positions[1];
t_i.positions_prev[2] = t_i.positions[2];
82 changes: 20 additions & 62 deletions src/refresh/vkpt/shader/vertex_buffer.h
Original file line number Diff line number Diff line change
@@ -43,14 +43,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define ALIGN_SIZE_4(x, n) ((x * n + 3) & (~3))

#define BSP_VERTEX_BUFFER_BINDING_IDX 0
#define MODEL_STATIC_VERTEX_BUFFER_BINDING_IDX 1
#define MODEL_DYNAMIC_VERTEX_BUFFER_BINDING_IDX 2
#define LIGHT_BUFFER_BINDING_IDX 3
#define READBACK_BUFFER_BINDING_IDX 4
#define TONE_MAPPING_BUFFER_BINDING_IDX 5
#define SUN_COLOR_BUFFER_BINDING_IDX 6
#define SUN_COLOR_UBO_BINDING_IDX 7
#define LIGHT_STATS_BUFFER_BINDING_IDX 8
#define MODEL_DYNAMIC_VERTEX_BUFFER_BINDING_IDX 1
#define LIGHT_BUFFER_BINDING_IDX 2
#define READBACK_BUFFER_BINDING_IDX 3
#define TONE_MAPPING_BUFFER_BINDING_IDX 4
#define SUN_COLOR_BUFFER_BINDING_IDX 5
#define SUN_COLOR_UBO_BINDING_IDX 6
#define LIGHT_STATS_BUFFER_BINDING_IDX 7

#define SUN_COLOR_ACCUMULATOR_FIXED_POINT_SCALE 0x100000
#define SKY_COLOR_ACCUMULATOR_FIXED_POINT_SCALE 0x100
@@ -68,13 +67,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
VERTEX_BUFFER_LIST_DO(float, 1, texel_density_bsp, (MAX_VERT_BSP / 3 )) \
VERTEX_BUFFER_LIST_DO(uint32_t, 1, sky_visibility, (MAX_LIGHT_LISTS / 32)) \

#define MODEL_STATIC_VERTEX_BUFFER_LIST \
VERTEX_BUFFER_LIST_DO(float, 3, positions_model, (MAX_VERT_MODEL )) \
VERTEX_BUFFER_LIST_DO(float, 3, normals_model, (MAX_VERT_MODEL )) \
VERTEX_BUFFER_LIST_DO(float, 2, tex_coords_model, (MAX_VERT_MODEL )) \
VERTEX_BUFFER_LIST_DO(float, 4, tangents_model, (MAX_VERT_MODEL )) \
VERTEX_BUFFER_LIST_DO(uint32_t, 3, idx_model, (MAX_IDX_MODEL )) \

#define MODEL_DYNAMIC_VERTEX_BUFFER_LIST \
VERTEX_BUFFER_LIST_DO(float, 3, positions_instanced, (MAX_VERT_MODEL )) \
VERTEX_BUFFER_LIST_DO(float, 3, pos_prev_instanced, (MAX_VERT_MODEL )) \
@@ -103,11 +95,6 @@ struct BspVertexBuffer
BSP_VERTEX_BUFFER_LIST
};

struct ModelStaticVertexBuffer
{
MODEL_STATIC_VERTEX_BUFFER_LIST
};

struct ModelDynamicVertexBuffer
{
MODEL_DYNAMIC_VERTEX_BUFFER_LIST
@@ -165,12 +152,24 @@ struct SunColorBuffer

#ifndef VKPT_SHADER
typedef struct BspVertexBuffer BspVertexBuffer;
typedef struct ModelStaticVertexBuffer ModelStaticVertexBuffer;
typedef struct ModelDynamicVertexBuffer ModelDynamicVertexBuffer;
typedef struct LightBuffer LightBuffer;
typedef struct ReadbackBuffer ReadbackBuffer;
typedef struct ToneMappingBuffer ToneMappingBuffer;
typedef struct SunColorBuffer SunColorBuffer;

typedef struct {
vec3_t position;
vec3_t normal;
vec2_t texcoord;
vec4_t tangents;
} model_vertex_t;
#else
#define MODEL_VERTEX_SIZE 12
#define MODEL_VERTEX_POSITION 0
#define MODEL_VERTEX_NORMAL 3
#define MODEL_VERTEX_TEXCOORD 6
#define MODEL_VERTEX_TANGENTS 8
#endif

#ifdef VKPT_SHADER
@@ -207,10 +206,6 @@ layout(set = VERTEX_BUFFER_DESC_SET_IDX, binding = BSP_VERTEX_BUFFER_BINDING_IDX
};
#endif

layout(set = VERTEX_BUFFER_DESC_SET_IDX, binding = MODEL_STATIC_VERTEX_BUFFER_BINDING_IDX) readonly buffer MODEL_STATIC_VERTEX_BUFFER {
ModelStaticVertexBuffer vbo_model_static;
};

#ifdef VERTEX_READONLY
layout(set = VERTEX_BUFFER_DESC_SET_IDX, binding = MODEL_DYNAMIC_VERTEX_BUFFER_BINDING_IDX) readonly buffer MODEL_DYNAMIC_VERTEX_BUFFER {
ModelDynamicVertexBuffer vbo_model_dynamic;
@@ -360,11 +355,6 @@ BSP_VERTEX_BUFFER_LIST
#undef VERTEX_BUFFER_LIST_DO
#endif

#define VERTEX_BUFFER_LIST_DO(type, dim, name, size) \
GET_##type##_##dim(vbo_model_static,name)
MODEL_STATIC_VERTEX_BUFFER_LIST
#undef VERTEX_BUFFER_LIST_DO

#ifdef VERTEX_READONLY
#define VERTEX_BUFFER_LIST_DO(type, dim, name, size) \
GET_##type##_##dim(vbo_model_dynamic,name)
@@ -431,38 +421,6 @@ get_bsp_triangle(uint prim_id)
return t;
}

Triangle
get_model_triangle(uint prim_id, uint idx_offset, uint vert_offset)
{
uvec3 idx = get_idx_model(prim_id + idx_offset / 3);
idx += vert_offset;

Triangle t;
t.positions[0] = get_positions_model(idx[0]);
t.positions[1] = get_positions_model(idx[1]);
t.positions[2] = get_positions_model(idx[2]);

t.normals[0] = get_normals_model(idx[0]);
t.normals[1] = get_normals_model(idx[1]);
t.normals[2] = get_normals_model(idx[2]);

t.tex_coords[0] = get_tex_coords_model(idx[0]);
t.tex_coords[1] = get_tex_coords_model(idx[1]);
t.tex_coords[2] = get_tex_coords_model(idx[2]);

vec4 tangent = get_tangents_model(idx[0]);
t.tangent = tangent.xyz;

t.material_id = 0; // needs to come from uniform buffer
if(tangent.w < 0)
t.material_id |= MATERIAL_FLAG_HANDEDNESS;

t.alpha = 1.0;
t.texel_density = 0;

return t;
}

Triangle
get_instanced_triangle(uint prim_id)
{
254 changes: 180 additions & 74 deletions src/refresh/vkpt/vertex_buffer.c
Original file line number Diff line number Diff line change
@@ -32,6 +32,15 @@ static VkPipeline pipeline_instance_geometry;
static VkPipeline pipeline_animate_materials;
static VkPipelineLayout pipeline_layout_instance_geometry;

typedef struct {
BufferResource_t buffer;
BufferResource_t staging_buffer;
int registration_sequence;
} model_vbo_t;

model_vbo_t model_vertex_data[MAX_MODELS];
static BufferResource_t null_buffer;

VkResult
vkpt_vertex_buffer_bsp_upload_staging()
{
@@ -65,24 +74,6 @@ vkpt_vertex_buffer_bsp_upload_staging()
return VK_SUCCESS;
}

VkResult
vkpt_vertex_buffer_model_upload_staging()
{
vkWaitForFences(qvk.device, 1, &qvk.fence_vertex_sync, VK_TRUE, ~((uint64_t)0));
vkResetFences(qvk.device, 1, &qvk.fence_vertex_sync);

VkCommandBuffer cmd_buf = vkpt_begin_command_buffer(&qvk.cmd_buffers_graphics);

VkBufferCopy copyRegion = {
.size = sizeof(ModelStaticVertexBuffer),
};
vkCmdCopyBuffer(cmd_buf, qvk.buf_vertex_model_static_staging.buffer, qvk.buf_vertex_model_static.buffer, 1, &copyRegion);

vkpt_submit_command_buffer(cmd_buf, qvk.queue_graphics, (1 << qvk.device_count) - 1, 0, NULL, NULL, NULL, 0, NULL, NULL, qvk.fence_vertex_sync);

return VK_SUCCESS;
}

VkResult
vkpt_light_buffer_upload_staging(VkCommandBuffer cmd_buf)
{
@@ -426,41 +417,109 @@ vkpt_light_buffer_upload_to_staging(qboolean render_world, bsp_mesh_t *bsp_mesh,
return VK_SUCCESS;
}

VkResult
vkpt_vertex_buffer_upload_models_to_staging()
static void write_model_vbo_descriptor(int index, VkBuffer buffer, VkDeviceSize size)
{
ModelStaticVertexBuffer *vbo = (ModelStaticVertexBuffer *) buffer_map(&qvk.buf_vertex_model_static_staging);
assert(vbo);
VkDescriptorBufferInfo descriptor_buffer_info = {
.buffer = buffer,
.offset = 0,
.range = size,
};

VkWriteDescriptorSet write_descriptor_set = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = qvk.desc_set_model_vbos,
.dstBinding = 0,
.dstArrayElement = index,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.descriptorCount = 1,
.pBufferInfo = &descriptor_buffer_info,
};

vkUpdateDescriptorSets(qvk.device, 1, &write_descriptor_set, 0, NULL);
}

VkResult
vkpt_vertex_buffer_upload_models()
{
int idx_offset = 0;
int vertex_offset = 0;
for(int i = 0; i < MAX_MODELS; i++) {
qboolean any_models_to_upload = qfalse;

for(int i = 0; i < MAX_MODELS; i++)
{
model_vbo_t* vbo = model_vertex_data + i;
if (!r_models[i].meshes && vbo->buffer.buffer) {
// model unloaded, destroy the VBO
write_model_vbo_descriptor(i, null_buffer.buffer, null_buffer.size);
buffer_destroy(&vbo->buffer);
vbo->registration_sequence = 0;
//Com_Printf("Unloaded model[%d]\n", i);
continue;
}

if(!r_models[i].meshes) {
// model does not exist
continue;
}

if (r_models[i].registration_sequence <= vbo->registration_sequence) {
// VBO is valid, nothing to do
continue;
}

//Com_Printf("Loading model[%d] %s\n", i, r_models[i].name);

assert(r_models[i].numframes > 0);

int model_vertices = 0;
int model_indices = 0;
for (int nmesh = 0; nmesh < r_models[i].nummeshes; nmesh++)
{
maliasmesh_t *m = r_models[i].meshes + nmesh;
int num_verts = r_models[i].numframes * m->numverts;

model_vertices += num_verts;
model_indices += m->numindices;
}

size_t vbo_size = model_vertices * sizeof(model_vertex_t) + model_indices * sizeof(uint32_t);
buffer_create(&vbo->buffer, vbo_size,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);

buffer_create(&vbo->staging_buffer, vbo_size,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);

uint32_t* staging_data = (uint32_t*)buffer_map(&vbo->staging_buffer);
int write_ptr = 0;

for (int nmesh = 0; nmesh < r_models[i].nummeshes; nmesh++)
{
maliasmesh_t *m = r_models[i].meshes + nmesh;

assert(m->numverts > 0);

m->vertex_offset = write_ptr;

int num_verts = r_models[i].numframes * m->numverts;

if (vertex_offset + num_verts > MAX_VERT_MODEL || idx_offset + m->numindices > MAX_IDX_MODEL)
for (int nvert = 0; nvert < num_verts; nvert++)
{
Com_EPrintf("Not enough VB/IB space for %s[%d] (%d verts, %d frames, %d idx)\n",
r_models[i].name, nmesh, m->numverts, r_models[i].numframes, m->numindices);

m->idx_offset = -1;
m->vertex_offset = -1;
continue; // maybe other models are smaller
model_vertex_t* vtx = (model_vertex_t*)(staging_data + write_ptr) + nvert;
memcpy(vtx->position, m->positions + nvert, sizeof(vec3_t));
memcpy(vtx->normal, m->normals + nvert, sizeof(vec3_t));
memcpy(vtx->texcoord, m->tex_coords + nvert, sizeof(vec2_t));
memcpy(vtx->tangents, m->tangents + nvert, sizeof(vec4_t));
}

m->idx_offset = idx_offset;
m->vertex_offset = vertex_offset;
write_ptr += num_verts * (sizeof(model_vertex_t) / sizeof(uint32_t));

m->idx_offset = write_ptr;

memcpy(staging_data + write_ptr, m->indices, sizeof(uint32_t) * m->numindices);

write_ptr += m->numindices;

#if 0
for (int j = 0; j < num_verts; j++)
@@ -495,25 +554,49 @@ vkpt_vertex_buffer_upload_models_to_staging()
}
fclose(f);
#endif
}

buffer_unmap(&vbo->staging_buffer);

vbo->registration_sequence = r_models[i].registration_sequence;
any_models_to_upload = qtrue;
}

if (any_models_to_upload)
{
VkCommandBuffer cmd_buf = vkpt_begin_command_buffer(&qvk.cmd_buffers_graphics);

memcpy(vbo->positions_model + vertex_offset * 3, m->positions, sizeof(float) * 3 * num_verts);
memcpy(vbo->normals_model + vertex_offset * 3, m->normals, sizeof(float) * 3 * num_verts);
memcpy(vbo->tex_coords_model + vertex_offset * 2, m->tex_coords, sizeof(float) * 2 * num_verts);
memcpy(vbo->tangents_model + vertex_offset * 4, m->tangents, sizeof(float) * 4 * num_verts);
memcpy(vbo->idx_model + idx_offset, m->indices, sizeof(uint32_t) * m->numindices);
for (int i = 0; i < MAX_MODELS; i++)
{
model_vbo_t* vbo = model_vertex_data + i;

vertex_offset += num_verts;
idx_offset += m->numindices;
if (vbo->staging_buffer.buffer)
{
VkBufferCopy copyRegion = {
.size = vbo->staging_buffer.size
};

assert(vertex_offset < MAX_VERT_MODEL);
assert(idx_offset < MAX_IDX_MODEL);
vkCmdCopyBuffer(cmd_buf, vbo->staging_buffer.buffer, vbo->buffer.buffer, 1, &copyRegion);
}
}
}

buffer_unmap(&qvk.buf_vertex_model_static_staging);
vbo = NULL;
vkpt_submit_command_buffer_simple(cmd_buf, qvk.queue_graphics, qtrue);
vkQueueWaitIdle(qvk.queue_graphics);

// Com_Printf("uploaded %d vert, %d idx\n", vertex_offset, idx_offset);
for (int i = 0; i < MAX_MODELS; i++)
{
model_vbo_t* vbo = model_vertex_data + i;

if (vbo->staging_buffer.buffer)
{
buffer_destroy(&vbo->staging_buffer);

// Just uploaded - create the descriptor, but after vkQueueWaitIdle:
// otherwise, the descriptor set might be still in use by in-flight shaders.
write_model_vbo_descriptor(i, vbo->buffer.buffer, vbo->buffer.size);
}
}
}

return VK_SUCCESS;
}
@@ -528,12 +611,6 @@ vkpt_vertex_buffer_create()
.binding = BSP_VERTEX_BUFFER_BINDING_IDX,
.stageFlags = VK_SHADER_STAGE_ALL,
},
{
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.descriptorCount = 1,
.binding = MODEL_STATIC_VERTEX_BUFFER_BINDING_IDX,
.stageFlags = VK_SHADER_STAGE_ALL,
},
{
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.descriptorCount = 1,
@@ -594,14 +671,6 @@ vkpt_vertex_buffer_create()
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);

buffer_create(&qvk.buf_vertex_model_static, sizeof(ModelStaticVertexBuffer),
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);

buffer_create(&qvk.buf_vertex_model_static_staging, sizeof(ModelStaticVertexBuffer),
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);

buffer_create(&qvk.buf_vertex_model_dynamic, sizeof(ModelDynamicVertexBuffer),
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
@@ -638,14 +707,14 @@ vkpt_vertex_buffer_create()

VkDescriptorPoolSize pool_size = {
.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.descriptorCount = LENGTH(vbo_layout_bindings),
.descriptorCount = LENGTH(vbo_layout_bindings) + MAX_MODELS,
};

VkDescriptorPoolCreateInfo pool_info = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.poolSizeCount = 1,
.pPoolSizes = &pool_size,
.maxSets = 1,
.maxSets = 2,
};

_VK(vkCreateDescriptorPool(qvk.device, &pool_info, NULL, &desc_pool_vertex_buffer));
@@ -677,11 +746,6 @@ vkpt_vertex_buffer_create()

vkUpdateDescriptorSets(qvk.device, 1, &output_buf_write, 0, NULL);

output_buf_write.dstBinding = MODEL_STATIC_VERTEX_BUFFER_BINDING_IDX;
buf_info.buffer = qvk.buf_vertex_model_static.buffer;
buf_info.range = sizeof(ModelStaticVertexBuffer);
vkUpdateDescriptorSets(qvk.device, 1, &output_buf_write, 0, NULL);

output_buf_write.dstBinding = MODEL_DYNAMIC_VERTEX_BUFFER_BINDING_IDX;
buf_info.buffer = qvk.buf_vertex_model_dynamic.buffer;
buf_info.range = sizeof(ModelDynamicVertexBuffer);
@@ -714,6 +778,39 @@ vkpt_vertex_buffer_create()
vkUpdateDescriptorSets(qvk.device, 1, &output_buf_write, 0, NULL);


VkDescriptorSetLayoutBinding model_vbo_layout_binding = {
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.descriptorCount = MAX_MODELS,
.binding = 0,
.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT
};

VkDescriptorSetLayoutCreateInfo model_vbo_layout_info = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = 1,
.pBindings = &model_vbo_layout_binding,
};

_VK(vkCreateDescriptorSetLayout(qvk.device, &model_vbo_layout_info, NULL, &qvk.desc_set_layout_model_vbos));

VkDescriptorSetAllocateInfo model_vbo_set_info = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.descriptorPool = desc_pool_vertex_buffer,
.descriptorSetCount = 1,
.pSetLayouts = &qvk.desc_set_layout_model_vbos,
};

_VK(vkAllocateDescriptorSets(qvk.device, &model_vbo_set_info, &qvk.desc_set_model_vbos));

memset(model_vertex_data, 0, sizeof(model_vertex_data));

buffer_create(&null_buffer, 4, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);

for (int i = 0; i < MAX_MODELS; i++)
{
write_model_vbo_descriptor(i, null_buffer.buffer, null_buffer.size);
}

return VK_SUCCESS;
}

@@ -741,12 +838,18 @@ vkpt_vertex_buffer_destroy()
desc_pool_vertex_buffer = VK_NULL_HANDLE;
qvk.desc_set_layout_vertex_buffer = VK_NULL_HANDLE;

buffer_destroy(&qvk.buf_vertex_bsp);
buffer_destroy(&qvk.buf_vertex_bsp_staging);
vkDestroyDescriptorSetLayout(qvk.device, qvk.desc_set_layout_model_vbos, NULL);
qvk.desc_set_layout_model_vbos = VK_NULL_HANDLE;

for (int model = 0; model < MAX_MODELS; model++)
{
buffer_destroy(&model_vertex_data[model].buffer);
}

buffer_destroy(&qvk.buf_vertex_model_static);
buffer_destroy(&qvk.buf_vertex_model_static_staging);
buffer_destroy(&null_buffer);

buffer_destroy(&qvk.buf_vertex_bsp);
buffer_destroy(&qvk.buf_vertex_bsp_staging);
buffer_destroy(&qvk.buf_vertex_model_dynamic);

buffer_destroy(&qvk.buf_light);
@@ -833,12 +936,14 @@ vkpt_vertex_buffer_create_pipelines()
assert(qvk.desc_set_layout_vertex_buffer);

VkDescriptorSetLayout desc_set_layouts[] = {
qvk.desc_set_layout_ubo, qvk.desc_set_layout_vertex_buffer
qvk.desc_set_layout_ubo,
qvk.desc_set_layout_vertex_buffer,
qvk.desc_set_layout_model_vbos
};

CREATE_PIPELINE_LAYOUT(qvk.device, &pipeline_layout_instance_geometry,
.setLayoutCount = LENGTH(desc_set_layouts),
.pSetLayouts = desc_set_layouts,
.setLayoutCount = LENGTH(desc_set_layouts),
.pSetLayouts = desc_set_layouts,
);

VkComputePipelineCreateInfo compute_pipeline_info[] = {
@@ -886,7 +991,8 @@ vkpt_instance_geometry(VkCommandBuffer cmd_buf, uint32_t num_instances, qboolean
{
VkDescriptorSet desc_sets[] = {
qvk.desc_set_ubo,
qvk.desc_set_vertex_buffer
qvk.desc_set_vertex_buffer,
qvk.desc_set_model_vbos
};
vkCmdBindPipeline(cmd_buf, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_instance_geometry);
vkCmdBindDescriptorSets(cmd_buf, VK_PIPELINE_BIND_POINT_COMPUTE,
2 changes: 1 addition & 1 deletion src/refresh/vkpt/vk_util.c
Original file line number Diff line number Diff line change
@@ -135,7 +135,7 @@ buffer_destroy(BufferResource_t *buf)
if(buf->memory != VK_NULL_HANDLE)
vkFreeMemory(qvk.device, buf->memory, NULL);
if(buf->buffer != VK_NULL_HANDLE)
vkDestroyBuffer(qvk.device, buf->buffer, NULL);
vkDestroyBuffer(qvk.device, buf->buffer, NULL);
buf->buffer = VK_NULL_HANDLE;
buf->memory = VK_NULL_HANDLE;
buf->size = 0;
8 changes: 4 additions & 4 deletions src/refresh/vkpt/vkpt.h
Original file line number Diff line number Diff line change
@@ -240,10 +240,11 @@ typedef struct QVK_s {
VkDescriptorSetLayout desc_set_layout_vertex_buffer;
VkDescriptorSet desc_set_vertex_buffer;

VkDescriptorSetLayout desc_set_layout_model_vbos;
VkDescriptorSet desc_set_model_vbos;

BufferResource_t buf_vertex_bsp;
BufferResource_t buf_vertex_bsp_staging;
BufferResource_t buf_vertex_model_static;
BufferResource_t buf_vertex_model_static_staging;
BufferResource_t buf_vertex_model_dynamic;

BufferResource_t buf_light;
@@ -582,9 +583,8 @@ VkResult vkpt_vertex_buffer_upload_bsp_mesh_to_staging(bsp_mesh_t *bsp_mesh);
VkResult vkpt_vertex_buffer_create_pipelines();
VkResult vkpt_vertex_buffer_destroy_pipelines();
VkResult vkpt_instance_geometry(VkCommandBuffer cmd_buf, uint32_t num_instances, qboolean update_world_animations);
VkResult vkpt_vertex_buffer_upload_models_to_staging();
VkResult vkpt_vertex_buffer_upload_models();
VkResult vkpt_vertex_buffer_bsp_upload_staging();
VkResult vkpt_vertex_buffer_model_upload_staging();
void vkpt_light_buffer_reset_counts();
VkResult vkpt_light_buffer_upload_to_staging(qboolean render_world, bsp_mesh_t *bsp_mesh, bsp_t* bsp, int num_model_lights, light_poly_t* transformed_model_lights, const float* sky_radiance);
VkResult vkpt_light_buffer_upload_staging(VkCommandBuffer cmd_buf);

0 comments on commit aa06bcd

Please sign in to comment.