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.
  • Loading branch information
apanteleev committed Jul 13, 2020
1 parent 294fcea commit aa06bcd
Show file tree
Hide file tree
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
Expand Up @@ -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:
Expand Down
15 changes: 5 additions & 10 deletions src/refresh/vkpt/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
24 changes: 20 additions & 4 deletions src/refresh/vkpt/shader/global_ubo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down
96 changes: 81 additions & 15 deletions src/refresh/vkpt/shader/instance_geometry.comp
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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;
Expand All @@ -51,7 +121,7 @@ main()

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

if(is_world)
{
instance_id = ~model_index;
Expand Down Expand Up @@ -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);
Expand All @@ -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];
Expand Down
82 changes: 20 additions & 62 deletions src/refresh/vkpt/shader/vertex_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 )) \
Expand Down Expand Up @@ -103,11 +95,6 @@ struct BspVertexBuffer
BSP_VERTEX_BUFFER_LIST
};

struct ModelStaticVertexBuffer
{
MODEL_STATIC_VERTEX_BUFFER_LIST
};

struct ModelDynamicVertexBuffer
{
MODEL_DYNAMIC_VERTEX_BUFFER_LIST
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
{
Expand Down
Loading

0 comments on commit aa06bcd

Please sign in to comment.