rt: step even closer to explicit blas+kusochki management

- stop tracking color/xform/mmode with vk_ray_model
- do not expose model to things that don't need to know
This commit is contained in:
Ivan Avdeev 2023-05-22 11:02:40 -07:00
parent 8724efd748
commit 9200cbfc25
3 changed files with 71 additions and 65 deletions

View File

@ -157,7 +157,7 @@ static qboolean buildAccel(VkBuffer geometry_buffer, VkAccelerationStructureBuil
}
// TODO split this into smaller building blocks in a separate module
qboolean createOrUpdateAccelerationStructure(vk_combuf_t *combuf, const as_build_args_t *args, vk_ray_model_t *model) {
qboolean createOrUpdateAccelerationStructure(vk_combuf_t *combuf, const as_build_args_t *args) {
ASSERT(args->geoms);
ASSERT(args->n_geoms > 0);
ASSERT(args->p_accel);
@ -182,9 +182,11 @@ qboolean createOrUpdateAccelerationStructure(vk_combuf_t *combuf, const as_build
if (!args->p_accel)
return false;
if (model) {
model->cache.size = build_size.accelerationStructureSize;
}
if (args->out_accel_addr)
*args->out_accel_addr = getAccelAddress(*args->p_accel);
if (args->inout_size)
*args->inout_size = build_size.accelerationStructureSize;
// gEngine.Con_Reportf("AS=%p, n_geoms=%u, build: %#x %d %#x\n", *args->p_accel, args->n_geoms, buffer_offset, asci.size, buffer_offset + asci.size);
}
@ -193,9 +195,8 @@ qboolean createOrUpdateAccelerationStructure(vk_combuf_t *combuf, const as_build
if (!combuf || !args->build_ranges)
return true;
if (model) {
ASSERT(model->cache.size >= build_size.accelerationStructureSize);
}
if (args->inout_size)
ASSERT(*args->inout_size >= build_size.accelerationStructureSize);
build_info.dstAccelerationStructure = *args->p_accel;
const VkBuffer geometry_buffer = R_GeometryBuffer_Get();
@ -230,8 +231,10 @@ static void createTlas( vk_combuf_t *combuf, VkDeviceAddress instances_addr ) {
.dynamic = false,
.p_accel = &g_accel.tlas,
.debug_name = "TLAS",
.out_accel_addr = NULL,
.inout_size = NULL,
};
if (!createOrUpdateAccelerationStructure(combuf, &asrgs, NULL)) {
if (!createOrUpdateAccelerationStructure(combuf, &asrgs)) {
gEngine.Host_Error("Could not create/update TLAS\n");
return;
}
@ -260,12 +263,11 @@ vk_resource_t RT_VkAccelPrepareTlas(vk_combuf_t *combuf) {
VkAccelerationStructureInstanceKHR* inst = ((VkAccelerationStructureInstanceKHR*)g_accel.tlas_geom_buffer.mapped) + instance_offset;
for (int i = 0; i < g_ray_model_state.frame.instances_count; ++i) {
const rt_draw_instance_t* const instance = g_ray_model_state.frame.instances + i;
ASSERT(instance->model);
ASSERT(instance->model->as != VK_NULL_HANDLE);
ASSERT(instance->blas_addr != 0);
inst[i] = (VkAccelerationStructureInstanceKHR){
.instanceCustomIndex = instance->model->kusochki_offset,
.instanceCustomIndex = instance->kusochki_offset,
.instanceShaderBindingTableRecordOffset = 0,
.accelerationStructureReference = getAccelAddress(instance->model->as), // TODO cache this addr
.accelerationStructureReference = instance->blas_addr,
};
switch (instance->material_mode) {
case MATERIAL_MODE_OPAQUE:
@ -298,8 +300,8 @@ vk_resource_t RT_VkAccelPrepareTlas(vk_combuf_t *combuf) {
struct ModelHeader *const header = ((struct ModelHeader*)headers_lock.ptr) + i;
header->mode = instance->material_mode;
Vector4Copy(instance->model->color, header->color);
Matrix4x4_ToArrayFloatGL(instance->model->prev_transform, (float*)header->prev_transform);
Vector4Copy(instance->color, header->color);
Matrix4x4_ToArrayFloatGL(instance->prev_transform_row, (float*)header->prev_transform);
}
R_VkStagingUnlock(headers_lock.handle);
@ -398,9 +400,9 @@ void RT_VkAccelShutdown(void) {
for (int i = 0; i < COUNTOF(g_ray_model_state.models_cache); ++i) {
vk_ray_model_t *model = g_ray_model_state.models_cache + i;
if (model->as != VK_NULL_HANDLE)
vkDestroyAccelerationStructureKHR(vk_core.device, model->as, NULL);
model->as = VK_NULL_HANDLE;
if (model->blas != VK_NULL_HANDLE)
vkDestroyAccelerationStructureKHR(vk_core.device, model->blas, NULL);
model->blas = VK_NULL_HANDLE;
}
VK_BufferDestroy(&g_accel.scratch_buffer);

View File

@ -11,29 +11,30 @@
#include "shaders/ray_interop.h"
typedef struct vk_ray_model_s {
VkAccelerationStructureKHR as;
VkAccelerationStructureKHR blas;
VkDeviceAddress blas_addr;
uint32_t kusochki_offset;
qboolean dynamic;
// TODO remove
struct {
VkAccelerationStructureGeometryKHR *geoms;
int max_prims;
int num_geoms;
int size;
uint32_t size;
qboolean taken;
} cache;
uint32_t kusochki_offset;
qboolean dynamic;
// TODO remove with the split of Kusok in Model+Material+Kusok
vec4_t color;
matrix4x4 prev_transform;
} cache_toremove;
} vk_ray_model_t;
typedef struct Kusok vk_kusok_data_t;
typedef struct rt_draw_instance_s {
vk_ray_model_t *model_toremove;
VkDeviceAddress blas_addr;
uint32_t kusochki_offset;
matrix3x4 transform_row;
vk_ray_model_t *model;
matrix4x4 prev_transform_row;
vec4_t color;
uint32_t material_mode; // MATERIAL_MODE_ from ray_interop.h
} rt_draw_instance_t;
@ -46,10 +47,13 @@ typedef struct {
uint32_t n_geoms;
VkAccelerationStructureTypeKHR type;
qboolean dynamic;
VkDeviceAddress *out_accel_addr;
uint32_t *inout_size;
} as_build_args_t;
struct vk_combuf_s;
qboolean createOrUpdateAccelerationStructure(struct vk_combuf_s *combuf, const as_build_args_t *args, vk_ray_model_t *model);
qboolean createOrUpdateAccelerationStructure(struct vk_combuf_s *combuf, const as_build_args_t *args);
#define MAX_SCRATCH_BUFFER (32*1024*1024)
#define MAX_ACCELS_BUFFER (64*1024*1024)

View File

@ -18,8 +18,8 @@
xvk_ray_model_state_t g_ray_model_state;
static void returnModelToCache(vk_ray_model_t *model) {
ASSERT(model->cache.taken);
model->cache.taken = false;
ASSERT(model->cache_toremove.taken);
model->cache_toremove.taken = false;
}
static vk_ray_model_t *getModelFromCache(int num_geoms, int max_prims, const VkAccelerationStructureGeometryKHR *geoms) { //}, int size) {
@ -29,33 +29,33 @@ static vk_ray_model_t *getModelFromCache(int num_geoms, int max_prims, const VkA
{
int j;
model = g_ray_model_state.models_cache + i;
if (model->cache.taken)
if (model->cache_toremove.taken)
continue;
if (!model->as)
if (!model->blas)
break;
if (model->cache.num_geoms != num_geoms)
if (model->cache_toremove.num_geoms != num_geoms)
continue;
if (model->cache.max_prims != max_prims)
if (model->cache_toremove.max_prims != max_prims)
continue;
for (j = 0; j < num_geoms; ++j) {
if (model->cache.geoms[j].geometryType != geoms[j].geometryType)
if (model->cache_toremove.geoms[j].geometryType != geoms[j].geometryType)
break;
if (model->cache.geoms[j].flags != geoms[j].flags)
if (model->cache_toremove.geoms[j].flags != geoms[j].flags)
break;
if (geoms[j].geometryType == VK_GEOMETRY_TYPE_TRIANGLES_KHR) {
// TODO what else should we compare?
if (model->cache.geoms[j].geometry.triangles.maxVertex != geoms[j].geometry.triangles.maxVertex)
if (model->cache_toremove.geoms[j].geometry.triangles.maxVertex != geoms[j].geometry.triangles.maxVertex)
break;
ASSERT(model->cache.geoms[j].geometry.triangles.vertexStride == geoms[j].geometry.triangles.vertexStride);
ASSERT(model->cache.geoms[j].geometry.triangles.vertexFormat == geoms[j].geometry.triangles.vertexFormat);
ASSERT(model->cache.geoms[j].geometry.triangles.indexType == geoms[j].geometry.triangles.indexType);
ASSERT(model->cache_toremove.geoms[j].geometry.triangles.vertexStride == geoms[j].geometry.triangles.vertexStride);
ASSERT(model->cache_toremove.geoms[j].geometry.triangles.vertexFormat == geoms[j].geometry.triangles.vertexFormat);
ASSERT(model->cache_toremove.geoms[j].geometry.triangles.indexType == geoms[j].geometry.triangles.indexType);
} else {
PRINT_NOT_IMPLEMENTED_ARGS("Non-tri geometries are not implemented");
break;
@ -72,15 +72,15 @@ static vk_ray_model_t *getModelFromCache(int num_geoms, int max_prims, const VkA
// if (model->size > 0)
// ASSERT(model->size >= size);
if (!model->cache.geoms) {
if (!model->cache_toremove.geoms) {
const size_t size = sizeof(*geoms) * num_geoms;
model->cache.geoms = Mem_Malloc(vk_core.pool, size);
memcpy(model->cache.geoms, geoms, size);
model->cache.num_geoms = num_geoms;
model->cache.max_prims = max_prims;
model->cache_toremove.geoms = Mem_Malloc(vk_core.pool, size);
memcpy(model->cache_toremove.geoms, geoms, size);
model->cache_toremove.num_geoms = num_geoms;
model->cache_toremove.max_prims = max_prims;
}
model->cache.taken = true;
model->cache_toremove.taken = true;
return model;
}
@ -203,10 +203,12 @@ vk_ray_model_t* VK_RayModelCreate( vk_ray_model_init_t args ) {
gEngine.Con_Printf(S_ERROR "Ran out of model cache slots\n");
} else {
qboolean result;
asrgs.p_accel = &ray_model->as;
asrgs.p_accel = &ray_model->blas;
asrgs.out_accel_addr = &ray_model->blas_addr;
asrgs.inout_size = &ray_model->cache_toremove.size;
DEBUG_BEGINF(combuf->cmdbuf, "build blas for %s", args.model->debug_name);
result = createOrUpdateAccelerationStructure(combuf, &asrgs, ray_model);
result = createOrUpdateAccelerationStructure(combuf, &asrgs);
DEBUG_END(combuf->cmdbuf);
if (!result)
@ -217,8 +219,6 @@ vk_ray_model_t* VK_RayModelCreate( vk_ray_model_init_t args ) {
} else {
ray_model->kusochki_offset = ALO_ALLOC_FAILED;
ray_model->dynamic = args.model->dynamic;
Vector4Set(ray_model->color, 1, 1, 1, 1);
Matrix4x4_LoadIdentity(ray_model->prev_transform);
}
}
}
@ -234,11 +234,11 @@ vk_ray_model_t* VK_RayModelCreate( vk_ray_model_init_t args ) {
void VK_RayModelDestroy( struct vk_ray_model_s *model ) {
ASSERT(vk_core.rtx);
if (model->as != VK_NULL_HANDLE) {
if (model->blas != VK_NULL_HANDLE) {
//gEngine.Con_Reportf("Model %s destroying AS=%p blas_index=%d\n", model->debug_name, model->rtx.blas, blas_index);
vkDestroyAccelerationStructureKHR(vk_core.device, model->as, NULL);
Mem_Free(model->cache.geoms);
vkDestroyAccelerationStructureKHR(vk_core.device, model->blas, NULL);
Mem_Free(model->cache_toremove.geoms);
memset(model, 0, sizeof(*model));
}
}
@ -347,14 +347,14 @@ void VK_RayFrameAddModel( vk_ray_model_t *model, const vk_render_model_t *render
ASSERT(vk_core.rtx);
ASSERT(g_ray_model_state.frame.instances_count <= ARRAYSIZE(g_ray_model_state.frame.instances));
ASSERT(model->cache.num_geoms == render_model->num_geometries);
ASSERT(model->cache_toremove.num_geoms == render_model->num_geometries);
if (g_ray_model_state.frame.instances_count == ARRAYSIZE(g_ray_model_state.frame.instances)) {
gEngine.Con_Printf(S_ERROR "Ran out of AccelerationStructure slots\n");
return;
}
ASSERT(model->as != VK_NULL_HANDLE);
ASSERT(model->blas != VK_NULL_HANDLE);
// TODO this material mapping is context dependent. I.e. different entity types might need different ray tracing behaviours for
// same render_mode/type and even texture.
@ -401,10 +401,6 @@ void VK_RayFrameAddModel( vk_ray_model_t *model, const vk_render_model_t *render
return;
}
// TODO expunge
Vector4Copy(render_model->color, model->color);
Matrix4x4_Copy(model->prev_transform, render_model->prev_transform);
// TODO needed for brush models only
// (? TODO studio models?)
for (int i = 0; i < render_model->dynamic_polylights_count; ++i) {
@ -414,9 +410,13 @@ void VK_RayFrameAddModel( vk_ray_model_t *model, const vk_render_model_t *render
RT_LightAddPolygon(polylight);
}
draw_instance->model = model;
draw_instance->model_toremove = model;
draw_instance->blas_addr = model->blas_addr;
draw_instance->kusochki_offset = model->kusochki_offset;
draw_instance->material_mode = material_mode;
Vector4Copy(render_model->color, draw_instance->color);
Matrix3x4_Copy(draw_instance->transform_row, render_model->transform);
Matrix4x4_Copy(draw_instance->prev_transform_row, render_model->prev_transform);
g_ray_model_state.frame.instances_count++;
}
@ -432,13 +432,13 @@ void XVK_RayModel_ClearForNextFrame( void ) {
// destroy/reuse dynamic ASes from previous frame
for (int i = 0; i < g_ray_model_state.frame.instances_count; ++i) {
rt_draw_instance_t *instance = g_ray_model_state.frame.instances + i;
ASSERT(instance->model);
ASSERT(instance->model_toremove);
if (!instance->model->dynamic)
if (!instance->model_toremove->dynamic)
continue;
returnModelToCache(instance->model);
instance->model = NULL;
returnModelToCache(instance->model_toremove);
instance->model_toremove = NULL;
}
g_ray_model_state.frame.instances_count = 0;