mirror of
https://github.com/w23/xash3d-fwgs
synced 2024-12-16 06:00:33 +01:00
do not overwrite ubo buffers being used
This commit is contained in:
parent
f8ea93656f
commit
c299ac9ccd
@ -125,3 +125,32 @@ void R_DEBuffer_Flip(r_debuffer_t* debuf) {
|
|||||||
debuf->frame_dynamic_offset[1] = ALO_ALLOC_FAILED;
|
debuf->frame_dynamic_offset[1] = ALO_ALLOC_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void R_FlippingBuffer_Init(r_flipping_buffer_t *flibuf, uint32_t size) {
|
||||||
|
aloRingInit(&flibuf->ring, size);
|
||||||
|
R_FlippingBuffer_Clear(flibuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void R_FlippingBuffer_Clear(r_flipping_buffer_t *flibuf) {
|
||||||
|
aloRingInit(&flibuf->ring, flibuf->ring.size);
|
||||||
|
flibuf->frame_offsets[0] = flibuf->frame_offsets[1] = ALO_ALLOC_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t R_FlippingBuffer_Alloc(r_flipping_buffer_t* flibuf, uint32_t size, uint32_t align) {
|
||||||
|
const uint32_t offset = aloRingAlloc(&flibuf->ring, size, align);
|
||||||
|
if (offset == ALO_ALLOC_FAILED)
|
||||||
|
return ALO_ALLOC_FAILED;
|
||||||
|
|
||||||
|
if (flibuf->frame_offsets[1] == ALO_ALLOC_FAILED)
|
||||||
|
flibuf->frame_offsets[1] = offset;
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void R_FlippingBuffer_Flip(r_flipping_buffer_t* flibuf) {
|
||||||
|
if (flibuf->frame_offsets[0] != ALO_ALLOC_FAILED)
|
||||||
|
aloRingFree(&flibuf->ring, flibuf->frame_offsets[0]);
|
||||||
|
|
||||||
|
flibuf->frame_offsets[0] = flibuf->frame_offsets[1];
|
||||||
|
flibuf->frame_offsets[1] = ALO_ALLOC_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -61,3 +61,14 @@ typedef enum {
|
|||||||
void R_DEBuffer_Init(r_debuffer_t *debuf, uint32_t static_size, uint32_t dynamic_size);
|
void R_DEBuffer_Init(r_debuffer_t *debuf, uint32_t static_size, uint32_t dynamic_size);
|
||||||
uint32_t R_DEBuffer_Alloc(r_debuffer_t* debuf, r_lifetime_t lifetime, uint32_t size, uint32_t align);
|
uint32_t R_DEBuffer_Alloc(r_debuffer_t* debuf, r_lifetime_t lifetime, uint32_t size, uint32_t align);
|
||||||
void R_DEBuffer_Flip(r_debuffer_t* debuf);
|
void R_DEBuffer_Flip(r_debuffer_t* debuf);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
alo_ring_t ring;
|
||||||
|
uint32_t frame_offsets[2];
|
||||||
|
} r_flipping_buffer_t;
|
||||||
|
|
||||||
|
void R_FlippingBuffer_Init(r_flipping_buffer_t *flibuf, uint32_t size);
|
||||||
|
void R_FlippingBuffer_Clear(r_flipping_buffer_t *flibuf);
|
||||||
|
uint32_t R_FlippingBuffer_Alloc(r_flipping_buffer_t* flibuf, uint32_t size, uint32_t align);
|
||||||
|
void R_FlippingBuffer_Flip(r_flipping_buffer_t* flibuf);
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#define MAX_BUFFER_INDICES_STATIC (MAX_BUFFER_VERTICES_STATIC * 3)
|
#define MAX_BUFFER_INDICES_STATIC (MAX_BUFFER_VERTICES_STATIC * 3)
|
||||||
#define GEOMETRY_BUFFER_STATIC_SIZE ALIGN_UP(MAX_BUFFER_VERTICES_STATIC * sizeof(vk_vertex_t) + MAX_BUFFER_INDICES_STATIC * sizeof(uint16_t), sizeof(vk_vertex_t))
|
#define GEOMETRY_BUFFER_STATIC_SIZE ALIGN_UP(MAX_BUFFER_VERTICES_STATIC * sizeof(vk_vertex_t) + MAX_BUFFER_INDICES_STATIC * sizeof(uint16_t), sizeof(vk_vertex_t))
|
||||||
|
|
||||||
#define MAX_BUFFER_VERTICES_DYNAMIC (128 * 1024)
|
#define MAX_BUFFER_VERTICES_DYNAMIC (128 * 1024 * 2)
|
||||||
#define MAX_BUFFER_INDICES_DYNAMIC (MAX_BUFFER_VERTICES_DYNAMIC * 3)
|
#define MAX_BUFFER_INDICES_DYNAMIC (MAX_BUFFER_VERTICES_DYNAMIC * 3)
|
||||||
#define GEOMETRY_BUFFER_DYNAMIC_SIZE ALIGN_UP(MAX_BUFFER_VERTICES_DYNAMIC * sizeof(vk_vertex_t) + MAX_BUFFER_INDICES_DYNAMIC * sizeof(uint16_t), sizeof(vk_vertex_t))
|
#define GEOMETRY_BUFFER_DYNAMIC_SIZE ALIGN_UP(MAX_BUFFER_VERTICES_DYNAMIC * sizeof(vk_vertex_t) + MAX_BUFFER_INDICES_DYNAMIC * sizeof(uint16_t), sizeof(vk_vertex_t))
|
||||||
|
|
||||||
@ -239,11 +239,57 @@ typedef struct {
|
|||||||
} light[MAX_DLIGHTS];
|
} light[MAX_DLIGHTS];
|
||||||
} vk_ubo_lights_t;
|
} vk_ubo_lights_t;
|
||||||
|
|
||||||
qboolean VK_RenderInit( void ) {
|
#define MAX_DRAW_COMMANDS 8192 // TODO estimate
|
||||||
uint32_t uniform_unit_size;
|
#define MAX_DEBUG_NAME_LENGTH 32
|
||||||
|
|
||||||
|
typedef struct render_draw_s {
|
||||||
|
int lightmap, texture;
|
||||||
|
int render_mode;
|
||||||
|
uint32_t element_count;
|
||||||
|
uint32_t index_offset, vertex_offset;
|
||||||
|
/* TODO this should be a separate thing? */ struct { float r, g, b; } emissive;
|
||||||
|
} render_draw_t;
|
||||||
|
|
||||||
|
enum draw_command_type_e {
|
||||||
|
DrawLabelBegin,
|
||||||
|
DrawLabelEnd,
|
||||||
|
DrawDraw
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
enum draw_command_type_e type;
|
||||||
|
union {
|
||||||
|
char debug_label[MAX_DEBUG_NAME_LENGTH];
|
||||||
|
struct {
|
||||||
|
render_draw_t draw;
|
||||||
|
uint32_t ubo_offset;
|
||||||
|
matrix3x4 transform;
|
||||||
|
} draw;
|
||||||
|
};
|
||||||
|
} draw_command_t;
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
int uniform_data_set_mask;
|
||||||
|
uniform_data_t current_uniform_data;
|
||||||
|
uniform_data_t dirty_uniform_data;
|
||||||
|
|
||||||
|
r_flipping_buffer_t uniform_alloc;
|
||||||
|
uint32_t current_ubo_offset_FIXME;
|
||||||
|
|
||||||
|
draw_command_t draw_commands[MAX_DRAW_COMMANDS];
|
||||||
|
int num_draw_commands;
|
||||||
|
|
||||||
|
matrix4x4 model, view, projection;
|
||||||
|
|
||||||
|
qboolean current_frame_is_ray_traced;
|
||||||
|
} g_render_state;
|
||||||
|
|
||||||
|
qboolean VK_RenderInit( void ) {
|
||||||
g_render.ubo_align = Q_max(4, vk_core.physical_device.properties.limits.minUniformBufferOffsetAlignment);
|
g_render.ubo_align = Q_max(4, vk_core.physical_device.properties.limits.minUniformBufferOffsetAlignment);
|
||||||
uniform_unit_size = ((sizeof(uniform_data_t) + g_render.ubo_align - 1) / g_render.ubo_align) * g_render.ubo_align;
|
|
||||||
|
const uint32_t uniform_unit_size = ((sizeof(uniform_data_t) + g_render.ubo_align - 1) / g_render.ubo_align) * g_render.ubo_align;
|
||||||
|
const uint32_t uniform_buffer_size = uniform_unit_size * MAX_UNIFORM_SLOTS;
|
||||||
|
R_FlippingBuffer_Init(&g_render_state.uniform_alloc, uniform_buffer_size);
|
||||||
|
|
||||||
// TODO device memory and friends (e.g. handle mobile memory ...)
|
// TODO device memory and friends (e.g. handle mobile memory ...)
|
||||||
|
|
||||||
@ -252,7 +298,7 @@ qboolean VK_RenderInit( void ) {
|
|||||||
(vk_core.rtx ? VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT : 0))) // TODO staging buffer?
|
(vk_core.rtx ? VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT : 0))) // TODO staging buffer?
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!VK_BufferCreate("render uniform_buffer", &g_render.uniform_buffer, uniform_unit_size * MAX_UNIFORM_SLOTS,
|
if (!VK_BufferCreate("render uniform_buffer", &g_render.uniform_buffer, uniform_buffer_size,
|
||||||
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
||||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | (vk_core.rtx ? VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT : 0))) // TODO staging buffer?
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | (vk_core.rtx ? VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT : 0))) // TODO staging buffer?
|
||||||
return false;
|
return false;
|
||||||
@ -315,9 +361,9 @@ qboolean R_GeometryBufferAllocAndLock( r_geometry_buffer_lock_t *lock, int verte
|
|||||||
const uint32_t alloc_offset = aloRingAlloc(ring, total_size, sizeof(vk_vertex_t));
|
const uint32_t alloc_offset = aloRingAlloc(ring, total_size, sizeof(vk_vertex_t));
|
||||||
const uint32_t offset = alloc_offset + ((lifetime == LifetimeSingleFrame) ? GEOMETRY_BUFFER_STATIC_SIZE : 0);
|
const uint32_t offset = alloc_offset + ((lifetime == LifetimeSingleFrame) ? GEOMETRY_BUFFER_STATIC_SIZE : 0);
|
||||||
if (alloc_offset == ALO_ALLOC_FAILED) {
|
if (alloc_offset == ALO_ALLOC_FAILED) {
|
||||||
gEngine.Con_Printf(S_ERROR "Cannot allocate %s geometry buffer for %d vertices (%d bytes) and %d indices (%d bytes)\n",
|
/* gEngine.Con_Printf(S_ERROR "Cannot allocate %s geometry buffer for %d vertices (%d bytes) and %d indices (%d bytes)\n", */
|
||||||
lifetime == LifetimeSingleFrame ? "dynamic" : "static",
|
/* lifetime == LifetimeSingleFrame ? "dynamic" : "static", */
|
||||||
vertex_count, vertices_size, index_count, indices_size);
|
/* vertex_count, vertices_size, index_count, indices_size); */
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -382,51 +428,6 @@ void XVK_RenderBufferPrintStats( void ) {
|
|||||||
g_geom.static_ring.head / 1024, g_geom.static_ring.size / 1024);
|
g_geom.static_ring.head / 1024, g_geom.static_ring.size / 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_DRAW_COMMANDS 8192 // TODO estimate
|
|
||||||
#define MAX_DEBUG_NAME_LENGTH 32
|
|
||||||
|
|
||||||
typedef struct render_draw_s {
|
|
||||||
int lightmap, texture;
|
|
||||||
int render_mode;
|
|
||||||
uint32_t element_count;
|
|
||||||
uint32_t index_offset, vertex_offset;
|
|
||||||
/* TODO this should be a separate thing? */ struct { float r, g, b; } emissive;
|
|
||||||
} render_draw_t;
|
|
||||||
|
|
||||||
enum draw_command_type_e {
|
|
||||||
DrawLabelBegin,
|
|
||||||
DrawLabelEnd,
|
|
||||||
DrawDraw
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
enum draw_command_type_e type;
|
|
||||||
union {
|
|
||||||
char debug_label[MAX_DEBUG_NAME_LENGTH];
|
|
||||||
struct {
|
|
||||||
render_draw_t draw;
|
|
||||||
uint32_t ubo_offset;
|
|
||||||
matrix3x4 transform;
|
|
||||||
} draw;
|
|
||||||
};
|
|
||||||
} draw_command_t;
|
|
||||||
|
|
||||||
static struct {
|
|
||||||
int uniform_data_set_mask;
|
|
||||||
uniform_data_t current_uniform_data;
|
|
||||||
uniform_data_t dirty_uniform_data;
|
|
||||||
|
|
||||||
uint32_t current_ubo_offset;
|
|
||||||
uint32_t uniform_free_offset;
|
|
||||||
|
|
||||||
draw_command_t draw_commands[MAX_DRAW_COMMANDS];
|
|
||||||
int num_draw_commands;
|
|
||||||
|
|
||||||
matrix4x4 model, view, projection;
|
|
||||||
|
|
||||||
qboolean current_frame_is_ray_traced;
|
|
||||||
} g_render_state;
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
UNIFORM_UNSET = 0,
|
UNIFORM_UNSET = 0,
|
||||||
UNIFORM_SET_COLOR = 1,
|
UNIFORM_SET_COLOR = 1,
|
||||||
@ -438,12 +439,11 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void VK_RenderBegin( qboolean ray_tracing ) {
|
void VK_RenderBegin( qboolean ray_tracing ) {
|
||||||
g_render_state.uniform_free_offset = 0; // FIXME multiple frames in flight
|
|
||||||
g_render_state.uniform_data_set_mask = UNIFORM_UNSET;
|
g_render_state.uniform_data_set_mask = UNIFORM_UNSET;
|
||||||
g_render_state.current_ubo_offset = UINT32_MAX;
|
g_render_state.current_ubo_offset_FIXME = UINT32_MAX;
|
||||||
|
|
||||||
memset(&g_render_state.current_uniform_data, 0, sizeof(g_render_state.current_uniform_data));
|
memset(&g_render_state.current_uniform_data, 0, sizeof(g_render_state.current_uniform_data));
|
||||||
memset(&g_render_state.dirty_uniform_data, 0, sizeof(g_render_state.dirty_uniform_data));
|
memset(&g_render_state.dirty_uniform_data, 0, sizeof(g_render_state.dirty_uniform_data));
|
||||||
|
R_FlippingBuffer_Flip(&g_render_state.uniform_alloc);
|
||||||
|
|
||||||
g_render_state.num_draw_commands = 0;
|
g_render_state.num_draw_commands = 0;
|
||||||
g_render_state.current_frame_is_ray_traced = ray_tracing;
|
g_render_state.current_frame_is_ray_traced = ray_tracing;
|
||||||
@ -514,11 +514,7 @@ void VK_RenderStateSetMatrixModel( const matrix4x4 model )
|
|||||||
static uint32_t allocUniform( uint32_t size, uint32_t alignment ) {
|
static uint32_t allocUniform( uint32_t size, uint32_t alignment ) {
|
||||||
// FIXME Q_max is not correct, we need NAIMENSCHEEE OBSCHEEE KRATNOE
|
// FIXME Q_max is not correct, we need NAIMENSCHEEE OBSCHEEE KRATNOE
|
||||||
const uint32_t align = Q_max(alignment, g_render.ubo_align);
|
const uint32_t align = Q_max(alignment, g_render.ubo_align);
|
||||||
const uint32_t offset = (((g_render_state.uniform_free_offset + align - 1) / align) * align);
|
const uint32_t offset = R_FlippingBuffer_Alloc(&g_render_state.uniform_alloc, size, align);
|
||||||
if (offset + size > g_render.uniform_buffer.size)
|
|
||||||
return UINT32_MAX;
|
|
||||||
|
|
||||||
g_render_state.uniform_free_offset = offset + size;
|
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -542,6 +538,27 @@ static void drawCmdPushDebugLabelEnd( void ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME get rid of this garbage
|
||||||
|
static uint32_t getUboOffset_FIXME( void ) {
|
||||||
|
// Figure out whether we need to update UBO data, and upload new data if we do
|
||||||
|
// TODO generally it's not safe to do memcmp for structures comparison
|
||||||
|
if (g_render_state.current_ubo_offset_FIXME == UINT32_MAX
|
||||||
|
|| ((g_render_state.uniform_data_set_mask & UNIFORM_UPLOADED) == 0)
|
||||||
|
|| memcmp(&g_render_state.current_uniform_data, &g_render_state.dirty_uniform_data, sizeof(g_render_state.current_uniform_data)) != 0) {
|
||||||
|
g_render_state.current_ubo_offset_FIXME = allocUniform(sizeof(uniform_data_t), 16 /* why 16? vec4? */);
|
||||||
|
|
||||||
|
if (g_render_state.current_ubo_offset_FIXME == ALO_ALLOC_FAILED)
|
||||||
|
return UINT32_MAX;
|
||||||
|
|
||||||
|
uniform_data_t *const ubo = (uniform_data_t*)((byte*)g_render.uniform_buffer.mapped + g_render_state.current_ubo_offset_FIXME);
|
||||||
|
memcpy(&g_render_state.current_uniform_data, &g_render_state.dirty_uniform_data, sizeof(g_render_state.dirty_uniform_data));
|
||||||
|
memcpy(ubo, &g_render_state.current_uniform_data, sizeof(*ubo));
|
||||||
|
g_render_state.uniform_data_set_mask |= UNIFORM_UPLOADED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_render_state.current_ubo_offset_FIXME;
|
||||||
|
}
|
||||||
|
|
||||||
static void drawCmdPushDraw( const render_draw_t *draw )
|
static void drawCmdPushDraw( const render_draw_t *draw )
|
||||||
{
|
{
|
||||||
draw_command_t *draw_command;
|
draw_command_t *draw_command;
|
||||||
@ -561,26 +578,16 @@ static void drawCmdPushDraw( const render_draw_t *draw )
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Figure out whether we need to update UBO data, and upload new data if we do
|
const uint32_t ubo_offset = getUboOffset_FIXME();
|
||||||
// TODO generally it's not safe to do memcmp for structures comparison
|
if (ubo_offset == ALO_ALLOC_FAILED) {
|
||||||
if (g_render_state.current_ubo_offset == UINT32_MAX || ((g_render_state.uniform_data_set_mask & UNIFORM_UPLOADED) == 0)
|
// TODO stagger this
|
||||||
|| memcmp(&g_render_state.current_uniform_data, &g_render_state.dirty_uniform_data, sizeof(g_render_state.current_uniform_data)) != 0) {
|
gEngine.Con_Printf( S_ERROR "Ran out of uniform slots\n" );
|
||||||
uniform_data_t *ubo;
|
return;
|
||||||
g_render_state.current_ubo_offset = allocUniform( sizeof(uniform_data_t), 16 );
|
|
||||||
if (g_render_state.current_ubo_offset == UINT32_MAX) {
|
|
||||||
gEngine.Con_Printf( S_ERROR "Ran out of uniform slots\n" );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ubo = (uniform_data_t*)((byte*)g_render.uniform_buffer.mapped + g_render_state.current_ubo_offset);
|
|
||||||
memcpy(&g_render_state.current_uniform_data, &g_render_state.dirty_uniform_data, sizeof(g_render_state.dirty_uniform_data));
|
|
||||||
memcpy(ubo, &g_render_state.current_uniform_data, sizeof(*ubo));
|
|
||||||
g_render_state.uniform_data_set_mask |= UNIFORM_UPLOADED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_command = drawCmdAlloc();
|
draw_command = drawCmdAlloc();
|
||||||
draw_command->draw.draw = *draw;
|
draw_command->draw.draw = *draw;
|
||||||
draw_command->draw.ubo_offset = g_render_state.current_ubo_offset;
|
draw_command->draw.ubo_offset = ubo_offset;
|
||||||
draw_command->type = DrawDraw;
|
draw_command->type = DrawDraw;
|
||||||
Matrix3x4_Copy(draw_command->draw.transform, g_render_state.model);
|
Matrix3x4_Copy(draw_command->draw.transform, g_render_state.model);
|
||||||
}
|
}
|
||||||
@ -658,6 +665,7 @@ void VK_RenderEnd( VkCommandBuffer cmdbuf )
|
|||||||
|
|
||||||
ASSERT(!g_render_state.current_frame_is_ray_traced);
|
ASSERT(!g_render_state.current_frame_is_ray_traced);
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
const VkDeviceSize offset = 0;
|
const VkDeviceSize offset = 0;
|
||||||
vkCmdBindVertexBuffers(cmdbuf, 0, 1, &g_geom.buffer.buffer, &offset);
|
vkCmdBindVertexBuffers(cmdbuf, 0, 1, &g_geom.buffer.buffer, &offset);
|
||||||
|
Loading…
Reference in New Issue
Block a user