rt: update blas for brush water

Enable updating rt_blas, and use that for updating brush water models
This commit is contained in:
Ivan 'provod' Avdeev 2023-06-09 10:03:00 -07:00
parent 406a5f9d4b
commit cadf3dbdfc
8 changed files with 60 additions and 38 deletions

View File

@ -325,7 +325,7 @@ static void brushDrawWaterSurfaces( const cl_entity_t *ent, const vec4_t color,
}
#endif
static qboolean fillWaterSurfaces( const cl_entity_t *ent, vk_brush_model_t *bmodel, vk_render_geometry_t *geometries ) {
static void fillWaterSurfaces( const cl_entity_t *ent, vk_brush_model_t *bmodel, vk_render_geometry_t *geometries ) {
ASSERT(bmodel->water.surfaces_count > 0);
const r_geometry_range_lock_t geom_lock = R_GeometryRangeLock(&bmodel->water.geometry);
@ -363,7 +363,6 @@ static qboolean fillWaterSurfaces( const cl_entity_t *ent, vk_brush_model_t *bmo
}
R_GeometryRangeUnlock( &geom_lock );
return true;
}
static qboolean isSurfaceAnimated( const msurface_t *s, const struct texture_s *base_override ) {
@ -473,10 +472,11 @@ static qboolean brushCreateWaterModel(const model_t *mod, vk_brush_model_t *bmod
bmodel->water.geometry = geometry;
fillWaterSurfaces(NULL, bmodel, geometries);
if (!VK_RenderModelCreate(&bmodel->water.render_model, (vk_render_model_init_t){
if (!R_RenderModelCreate(&bmodel->water.render_model, (vk_render_model_init_t){
.name = mod->name,
.geometries = geometries,
.geometries_count = sizes.water_surfaces,
.dynamic = true,
})) {
gEngine.Con_Printf(S_ERROR "Could not create water render model for brush model %s\n", mod->name);
return false;
@ -489,7 +489,10 @@ static qboolean brushCreateWaterModel(const model_t *mod, vk_brush_model_t *bmod
static void brushDrawWater(vk_brush_model_t *bmodel, const cl_entity_t *ent, int render_type, const vec4_t color, const matrix4x4 transform) {
ASSERT(bmodel->water.surfaces_count > 0);
// TODO update
fillWaterSurfaces(NULL, bmodel, bmodel->water.render_model.geometries);
if (!R_RenderModelUpdate(&bmodel->water.render_model)) {
gEngine.Con_Printf(S_ERROR "Failed to update brush model \"%s\" water\n", bmodel->render_model.debug_name);
}
R_RenderModelDraw(&bmodel->water.render_model, (r_model_draw_t){
.render_type = render_type,
@ -948,10 +951,11 @@ static qboolean createRenderModel( const model_t *mod, vk_brush_model_t *bmodel,
return false;
}
if (!VK_RenderModelCreate(&bmodel->render_model, (vk_render_model_init_t){
if (!R_RenderModelCreate(&bmodel->render_model, (vk_render_model_init_t){
.name = mod->name,
.geometries = geometries,
.geometries_count = sizes.num_surfaces,
.dynamic = false,
})) {
gEngine.Con_Printf(S_ERROR "Could not create render model for brush model %s\n", mod->name);
return false;
@ -1011,13 +1015,13 @@ static void VK_BrushModelDestroy( vk_brush_model_t *bmodel ) {
ASSERT(bmodel->engine_model->type == mod_brush);
if (bmodel->water.surfaces_count) {
VK_RenderModelDestroy(&bmodel->water.render_model);
R_RenderModelDestroy(&bmodel->water.render_model);
Mem_Free((int*)bmodel->water.surfaces_indices);
Mem_Free(bmodel->water.render_model.geometries);
R_GeometryRangeFree(&bmodel->water.geometry);
}
VK_RenderModelDestroy(&bmodel->render_model);
R_RenderModelDestroy(&bmodel->render_model);
if (bmodel->animated_indexes)
Mem_Free(bmodel->animated_indexes);

View File

@ -105,14 +105,13 @@ static VkDeviceAddress getAccelAddress(VkAccelerationStructureKHR as) {
return vkGetAccelerationStructureDeviceAddressKHR(vk_core.device, &asdai);
}
static qboolean buildAccel(VkBuffer geometry_buffer, VkAccelerationStructureBuildGeometryInfoKHR *build_info, const VkAccelerationStructureBuildSizesInfoKHR *build_size, const VkAccelerationStructureBuildRangeInfoKHR *build_ranges) {
static qboolean buildAccel(VkBuffer geometry_buffer, VkAccelerationStructureBuildGeometryInfoKHR *build_info, uint32_t scratch_buffer_size, const VkAccelerationStructureBuildRangeInfoKHR *build_ranges) {
// FIXME this is definitely not the right place. We should upload everything in bulk, and only then build blases in bulk too
vk_combuf_t *const combuf = R_VkStagingCommit();
{
const VkBufferMemoryBarrier bmb[] = { {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
//.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, // FIXME
.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_SHADER_READ_BIT, // FIXME
.buffer = geometry_buffer,
.offset = 0, // FIXME
@ -125,8 +124,7 @@ static qboolean buildAccel(VkBuffer geometry_buffer, VkAccelerationStructureBuil
0, 0, NULL, ARRAYSIZE(bmb), bmb, 0, NULL);
}
// build blas
const uint32_t scratch_buffer_size = build_size->buildScratchSize; // TODO vs build_size.updateScratchSize
//gEngine.Con_Reportf("sratch offset = %d, req=%d\n", g_accel.frame.scratch_offset, scratch_buffer_size);
if (MAX_SCRATCH_BUFFER < g_accel.frame.scratch_offset + scratch_buffer_size) {
gEngine.Con_Printf(S_ERROR "Scratch buffer overflow: left %u bytes, but need %u\n",
@ -200,7 +198,7 @@ qboolean createOrUpdateAccelerationStructure(vk_combuf_t *combuf, const as_build
build_info.dstAccelerationStructure = *args->p_accel;
const VkBuffer geometry_buffer = R_GeometryBuffer_Get();
return buildAccel(geometry_buffer, &build_info, &build_size, args->build_ranges);
return buildAccel(geometry_buffer, &build_info, build_size.buildScratchSize, args->build_ranges);
}
static void createTlas( vk_combuf_t *combuf, VkDeviceAddress instances_addr ) {
@ -437,16 +435,6 @@ void RT_VkAccelFrameBegin(void) {
struct rt_blas_s* RT_BlasCreate(const char *name, rt_blas_usage_e usage) {
rt_blas_t *blas = Mem_Calloc(vk_core.pool, sizeof(*blas));
switch (usage) {
case kBlasBuildStatic:
break;
case kBlasBuildDynamicUpdate:
ASSERT(!"Not implemented");
break;
case kBlasBuildDynamicFast:
break;
}
blas->debug_name = name;
blas->usage = usage;
blas->blas_size = -1;
@ -547,22 +535,27 @@ qboolean RT_BlasBuild(struct rt_blas_s *blas, const struct vk_render_geometry_s
VkAccelerationStructureBuildGeometryInfoKHR build_info = {
.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR,
.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR,
.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR,
.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR,
.geometryCount = geoms_count,
.srcAccelerationStructure = VK_NULL_HANDLE,
};
qboolean is_update = false;
switch (blas->usage) {
case kBlasBuildStatic:
ASSERT(!blas->blas);
build_info.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
build_info.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
break;
case kBlasBuildDynamicUpdate:
ASSERT(!"Not implemented");
return false;
if (blas->blas) {
build_info.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR;
build_info.srcAccelerationStructure = blas->blas;
is_update = true;
}
build_info.flags |= VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR;
break;
case kBlasBuildDynamicFast:
build_info.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
build_info.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR;
break;
}
@ -620,7 +613,6 @@ qboolean RT_BlasBuild(struct rt_blas_s *blas, const struct vk_render_geometry_s
blas->blas_size = build_size.accelerationStructureSize;
blas->max_geoms = build_info.geometryCount;
// TODO handle lifetime blas->max_prim_counts = max_prim_counts;
} else {
if (blas->blas_size < build_size.accelerationStructureSize) {
gEngine.Con_Printf(S_ERROR "Fast dynamic BLAS %s size exceeded (need %dKiB, have %dKiB, geoms = %d)\n", blas->debug_name,
@ -634,7 +626,7 @@ qboolean RT_BlasBuild(struct rt_blas_s *blas, const struct vk_render_geometry_s
// Build
build_info.dstAccelerationStructure = blas->blas;
if (!buildAccel(geometry_buffer, &build_info, &build_size, build_ranges)) {
if (!buildAccel(geometry_buffer, &build_info, is_update ? build_size.updateScratchSize : build_size.buildScratchSize, build_ranges)) {
gEngine.Con_Printf(S_ERROR "Couldn't build BLAS %s\n", blas->debug_name);
goto finalize;
}

View File

@ -258,6 +258,12 @@ void RT_ModelDestroy(struct rt_model_s* model) {
Mem_Free(model);
}
qboolean RT_ModelUpdate(struct rt_model_s *model, const struct vk_render_geometry_s *geometries, int geometries_count) {
// TODO some updates, which change geometry location, textures, etc, might need kusochki update too
// TODO mark it with a flag or something
return RT_BlasBuild(model->blas, geometries, geometries_count);
}
rt_draw_instance_t *getDrawInstance(void) {
if (g_ray_model_state.frame.instances_count >= ARRAYSIZE(g_ray_model_state.frame.instances)) {
gEngine.Con_Printf(S_ERROR "Too many RT draw instances, max = %d\n", (int)(ARRAYSIZE(g_ray_model_state.frame.instances)));

View File

@ -641,7 +641,7 @@ void VK_RenderEndRTX( struct vk_combuf_s* combuf, VkImageView img_dst_view, VkIm
}
}
qboolean VK_RenderModelCreate( vk_render_model_t *model, vk_render_model_init_t args ) {
qboolean R_RenderModelCreate( vk_render_model_t *model, vk_render_model_init_t args ) {
memset(model, 0, sizeof(*model));
Q_strncpy(model->debug_name, args.name, sizeof(model->debug_name));
@ -655,12 +655,12 @@ qboolean VK_RenderModelCreate( vk_render_model_t *model, vk_render_model_init_t
.debug_name = model->debug_name,
.geometries = args.geometries,
.geometries_count = args.geometries_count,
.usage = kBlasBuildStatic, // TODO pass from caller
.usage = args.dynamic ? kBlasBuildDynamicUpdate : kBlasBuildStatic,
});
return !!model->rt_model;
}
void VK_RenderModelDestroy( vk_render_model_t* model ) {
void R_RenderModelDestroy( vk_render_model_t* model ) {
if (model->dynamic_polylights)
Mem_Free(model->dynamic_polylights);
@ -668,6 +668,16 @@ void VK_RenderModelDestroy( vk_render_model_t* model ) {
RT_ModelDestroy(model->rt_model);
}
qboolean R_RenderModelUpdate( vk_render_model_t *model ) {
// Non-RT rendering doesn't need to update anything, assuming that geometry regions offsets are not changed, and losing intermediate states is fine
if (!g_render_state.current_frame_is_ray_traced)
return true;
ASSERT(model->rt_model);
return RT_ModelUpdate(model->rt_model, model->geometries, model->num_geometries);
}
static void uboComputeAndSetMVPFromModel( const matrix4x4 model ) {
matrix4x4 mvp;
Matrix4x4_Concat(mvp, g_render_state.projection_view, model);

View File

@ -127,9 +127,15 @@ typedef struct {
const char *name;
vk_render_geometry_t *geometries;
int geometries_count;
// Geometry data can and will be updated
// Upading geometry locations is not supported though, only vertex/index values
qboolean dynamic;
} vk_render_model_init_t;
qboolean VK_RenderModelCreate( vk_render_model_t *model, vk_render_model_init_t args );
void VK_RenderModelDestroy( vk_render_model_t* model );
qboolean R_RenderModelCreate( vk_render_model_t *model, vk_render_model_init_t args );
void R_RenderModelDestroy( vk_render_model_t* model );
qboolean R_RenderModelUpdate( vk_render_model_t *model );
typedef struct {
vk_render_type_e render_type;

View File

@ -50,6 +50,8 @@ typedef struct {
struct rt_model_s *RT_ModelCreate(rt_model_create_t args);
void RT_ModelDestroy(struct rt_model_s *model);
qboolean RT_ModelUpdate(struct rt_model_s *model, const struct vk_render_geometry_s *geometries, int geometries_count);
typedef struct {
int render_type; // TODO material_mode
const matrix3x4 *transform, *prev_transform;

View File

@ -106,16 +106,17 @@ static qboolean createQuadModel(void) {
.emissive = {1,1,1},
};
return VK_RenderModelCreate(&g_sprite.quad.model, (vk_render_model_init_t){
return R_RenderModelCreate(&g_sprite.quad.model, (vk_render_model_init_t){
.name = "sprite",
.geometries = &g_sprite.quad.geometry,
.geometries_count = 1,
.dynamic = false,
});
}
static void destroyQuadModel(void) {
if (g_sprite.quad.model.num_geometries)
VK_RenderModelDestroy(&g_sprite.quad.model);
R_RenderModelDestroy(&g_sprite.quad.model);
if (g_sprite.quad.geom.block_handle.size)
R_GeometryRangeFree(&g_sprite.quad.geom);

View File

@ -164,7 +164,7 @@ void R_StudioCacheClear( void ) {
for (int i = 0; i < g_studio_cache.entries_count; ++i) {
r_studio_model_cache_entry_t *const entry = g_studio_cache.entries + i;
ASSERT(entry->key_submodel);
VK_RenderModelDestroy(&entry->render_model);
R_RenderModelDestroy(&entry->render_model);
R_GeometryRangeFree(&entry->geometry_range);
Mem_Free(entry->geometries);
entry->key_submodel = 0;
@ -2415,10 +2415,11 @@ static const r_studio_model_cache_entry_t *buildCachedStudioSubModel( const mstu
.geometry_range = geometry,
};
if (!VK_RenderModelCreate( &entry->render_model, (vk_render_model_init_t){
if (!R_RenderModelCreate( &entry->render_model, (vk_render_model_init_t){
.name = submodel->name,
.geometries = geometries,
.geometries_count = submodel->nummesh,
.dynamic = false,
})) {
gEngine.Con_Printf(S_ERROR "Unable to create render model for studio submodel %s", submodel->name);
Mem_Free(geometries);