rt: apply instanced texture overrides to rt_model; makes sprites apply correct textures

This commit is contained in:
Ivan Avdeev 2023-06-01 10:15:30 -07:00
parent 8f47115a01
commit edb151bd1b
7 changed files with 69 additions and 33 deletions

View File

@ -260,3 +260,18 @@ RT model draw:
- NO similar calls for `*` brush submodels.
2. For the rest of studio and sprite models:
- Mod_ProcessRenderData(create=0)
# E274
rt_model:
- kusok/geom
- index_,vertex_offset (static, same as geom/blas lifetime)
- ref to material (static or dynamic)
- emissive (mostly static, independent to material)
- instanceCustomIndex (24 bits) = offset to kusochki buffer
- kusochki[G]
- geom data (index, vertex offsets)
- emissive
- material
- materials[M]
- kusochki[N] <- iCI

View File

@ -103,11 +103,10 @@ struct Kusok {
// Geometry data, static
uint index_offset;
uint vertex_offset;
uint triangles;
// material below consists of scalar fields only, so it's not aligned to vec4.
// Alignt it here to vec4 explicitly, so that later vector fields are properly aligned (for simplicity).
uint _padding0;
uint _padding0[2];
// Per-kusok because individual surfaces can be patched
// TODO? still move to material, or its own table? As this can be dynamic

View File

@ -463,7 +463,6 @@ struct rt_blas_s* RT_BlasCreate(const char *name, rt_blas_usage_e usage) {
blas->debug_name = name;
blas->usage = usage;
//blas->kusochki_offset = -1;
blas->blas_size = -1;
return blas;

View File

@ -64,10 +64,11 @@ qboolean createOrUpdateAccelerationStructure(struct vk_combuf_s *combuf, const a
typedef struct {
// Geometry metadata. Lifetime is similar to geometry lifetime itself.
// Semantically close to render buffer (describes layout for those objects)
// TODO unify with render buffer
// TODO unify with render buffer?
// Needs: STORAGE_BUFFER
vk_buffer_t kusochki_buffer;
r_debuffer_t kusochki_alloc;
// TODO when fully rt_model: r_blocks_t alloc;
// Model header
// Array of struct ModelHeader: color, material_mode, prev_transform
@ -112,12 +113,12 @@ typedef struct rt_kusochki_s {
int internal_index__;
} rt_kusochki_t;
// TODO lifetime arg here is KORYAVY
rt_kusochki_t RT_KusochkiAlloc(int count, r_geometry_lifetime_t lifetime);
rt_kusochki_t RT_KusochkiAllocLong(int count);
uint32_t RT_KusochkiAllocOnce(int count);
void RT_KusochkiFree(const rt_kusochki_t*);
struct vk_render_geometry_s;
qboolean RT_KusochkiUpload(const rt_kusochki_t *kusochki, const struct vk_render_geometry_s *geoms, int geoms_count, int override_texture_id);
qboolean RT_KusochkiUpload(uint32_t kusochki_offset, const struct vk_render_geometry_s *geoms, int geoms_count, int override_texture_id);
// Update animated materials
void RT_KusochkiUploadSubset(rt_kusochki_t *kusochki, const struct vk_render_geometry_s *geoms, const int *geoms_indices, int geoms_indices_count);

View File

@ -90,15 +90,15 @@ static vk_ray_model_t *getModelFromCache(int num_geoms, int max_prims, const VkA
return model;
}
static void applyMaterialToKusok(vk_kusok_data_t* kusok, const vk_render_geometry_t *geom) {
const xvk_material_t *const mat = XVK_GetMaterialForTextureIndex( geom->texture );
static void applyMaterialToKusok(vk_kusok_data_t* kusok, const vk_render_geometry_t *geom, int override_texture_id) {
const int tex_id = override_texture_id > 0 ? override_texture_id : geom->texture;
const xvk_material_t *const mat = XVK_GetMaterialForTextureIndex( tex_id );
ASSERT(mat);
// TODO split kusochki into static geometry data and potentially dynamic material data
// This data is static, should never change
kusok->vertex_offset = geom->vertex_offset;
kusok->index_offset = geom->index_offset;
kusok->triangles = geom->element_count / 3;
// Material data itself is mostly static. Except for animated textures, which just get a new material slot for each frame.
kusok->material = (struct Material){
@ -300,7 +300,7 @@ static qboolean uploadKusochkiSubset(const vk_ray_model_t *const model, const vk
vk_kusok_data_t *const kusochki = kusok_staging.ptr;
vk_render_geometry_t *geom = render_model->geometries + index;
applyMaterialToKusok(kusochki + 0, geom);
applyMaterialToKusok(kusochki + 0, geom, -1);
/* gEngine.Con_Reportf("model %s: geom=%d kuoffs=%d kustoff=%d kustsz=%d sthndl=%d\n", */
/* render_model->debug_name, */
@ -333,7 +333,7 @@ static qboolean uploadKusochki(const vk_ray_model_t *const model, const vk_rende
for (int i = 0; i < render_model->num_geometries; ++i) {
vk_render_geometry_t *geom = render_model->geometries + i;
applyMaterialToKusok(kusochki + i, geom);
applyMaterialToKusok(kusochki + i, geom, -1);
}
/* gEngine.Con_Reportf("model %s: geom=%d kuoffs=%d kustoff=%d kustsz=%d sthndl=%d\n", */
@ -463,10 +463,9 @@ void XVK_RayModel_ClearForNextFrame( void ) {
R_DEBuffer_Flip(&g_ray_model_state.kusochki_alloc);
}
rt_kusochki_t RT_KusochkiAlloc(int count, r_geometry_lifetime_t lifetime) {
rt_kusochki_t RT_KusochkiAllocLong(int count) {
// TODO Proper block allocator
const r_lifetime_t rlifetime = lifetime == LifetimeSingleFrame ? LifetimeDynamic : LifetimeStatic;
uint32_t kusochki_offset = R_DEBuffer_Alloc(&g_ray_model_state.kusochki_alloc, rlifetime, count, 1);
uint32_t kusochki_offset = R_DEBuffer_Alloc(&g_ray_model_state.kusochki_alloc, LifetimeStatic, count, 1);
if (kusochki_offset == ALO_ALLOC_FAILED) {
gEngine.Con_Printf(S_ERROR "Maximum number of kusochki exceeded\n");
@ -480,20 +479,27 @@ rt_kusochki_t RT_KusochkiAlloc(int count, r_geometry_lifetime_t lifetime) {
};
}
uint32_t RT_KusochkiAllocOnce(int count) {
// TODO Proper block allocator
uint32_t kusochki_offset = R_DEBuffer_Alloc(&g_ray_model_state.kusochki_alloc, LifetimeDynamic, count, 1);
if (kusochki_offset == ALO_ALLOC_FAILED) {
gEngine.Con_Printf(S_ERROR "Maximum number of kusochki exceeded\n");
return ALO_ALLOC_FAILED;
}
return kusochki_offset;
}
void RT_KusochkiFree(const rt_kusochki_t *kusochki) {
// TODO block alloc
PRINT_NOT_IMPLEMENTED();
}
qboolean RT_KusochkiUpload(const rt_kusochki_t *kusochki, const struct vk_render_geometry_s *geoms, int geoms_count, int override_texture_id) {
ASSERT(kusochki->count == geoms_count);
// TODO not implemented yet
ASSERT(override_texture_id < 0);
qboolean RT_KusochkiUpload(uint32_t kusochki_offset, const struct vk_render_geometry_s *geoms, int geoms_count, int override_texture_id) {
const vk_staging_buffer_args_t staging_args = {
.buffer = g_ray_model_state.kusochki_buffer.buffer,
.offset = kusochki->offset * sizeof(vk_kusok_data_t),
.offset = kusochki_offset * sizeof(vk_kusok_data_t),
.size = geoms_count * sizeof(vk_kusok_data_t),
.alignment = 16,
};
@ -507,7 +513,7 @@ qboolean RT_KusochkiUpload(const rt_kusochki_t *kusochki, const struct vk_render
vk_kusok_data_t *const p = kusok_staging.ptr;
for (int i = 0; i < geoms_count; ++i) {
const vk_render_geometry_t *geom = geoms + i;
applyMaterialToKusok(p + i, geom);
applyMaterialToKusok(p + i, geom, override_texture_id);
}
R_VkStagingUnlock(kusok_staging.handle);
@ -515,7 +521,7 @@ qboolean RT_KusochkiUpload(const rt_kusochki_t *kusochki, const struct vk_render
}
struct rt_model_s *RT_ModelCreate(rt_model_create_t args) {
const rt_kusochki_t kusochki = RT_KusochkiAlloc(args.geometries_count, LifetimeLong);
const rt_kusochki_t kusochki = RT_KusochkiAllocLong(args.geometries_count);
if (kusochki.count == 0) {
gEngine.Con_Printf(S_ERROR "Cannot allocate kusochki for %s\n", args.debug_name);
return NULL;
@ -532,7 +538,7 @@ struct rt_model_s *RT_ModelCreate(rt_model_create_t args) {
goto fail;
}
RT_KusochkiUpload(&kusochki, args.geometries, args.geometries_count, -1);
RT_KusochkiUpload(kusochki.offset, args.geometries, args.geometries_count, -1);
{
rt_model_t *const ret = Mem_Malloc(vk_core.pool, sizeof(*ret));
@ -574,15 +580,22 @@ void RT_FrameAddModel( struct rt_model_s *model, rt_frame_add_model_t args ) {
rt_draw_instance_t* draw_instance = g_ray_model_state.frame.instances + g_ray_model_state.frame.instances_count;
/* if (args.textures_override > 0) { */
/* // FIXME need geometries + count */
/* rt_kusochki_t temp_kusok = RT_KusochkiAlloc(int count, r_geometry_lifetime_t lifetime); */
/* qboolean RT_KusochkiUpload(const rt_kusochki_t *kusochki, const struct vk_render_geometry_s *geoms, int geoms_count, int override_texture_id); */
/* } */
uint32_t kusochki_offset = model->kusochki.offset;
if (args.override.textures > 0) {
kusochki_offset = RT_KusochkiAllocOnce(args.override.geoms_count);
if (kusochki_offset == ALO_ALLOC_FAILED)
return;
if (!RT_KusochkiUpload(kusochki_offset, args.override.geoms, args.override.geoms_count, args.override.textures)) {
gEngine.Con_Printf(S_ERROR "Couldn't upload kusochki for instanced model\n");
return;
}
}
draw_instance->model_toremove = NULL;
draw_instance->blas_addr = model->blas_addr;
draw_instance->kusochki_offset = model->kusochki.offset;
draw_instance->kusochki_offset = kusochki_offset;
draw_instance->material_mode = materialModeFromRenderType(args.render_type);
Vector4Copy(*args.color, draw_instance->color);
Matrix3x4_Copy(draw_instance->transform_row, args.transform);

View File

@ -809,7 +809,11 @@ void R_RenderModelDraw(const vk_render_model_t *model, r_model_draw_t args) {
.transform = (const matrix3x4*)args.transform,
.prev_transform = (const matrix3x4*)args.prev_transform,
.color = args.color,
.textures_override = args.textures_override,
.override = {
.textures = args.textures_override,
.geoms = model->geometries,
.geoms_count = model->num_geometries,
},
});
} else {
submitToTraditionalRender(model, *args.transform, *args.color, args.render_type, args.textures_override);

View File

@ -76,7 +76,12 @@ typedef struct {
int render_type; // TODO material_mode
const matrix3x4 *transform, *prev_transform;
const vec4_t *color;
int textures_override; // Override kusochki/material textures if > 0
struct {
int textures; // Override kusochki/material textures if > 0
int geoms_count;
const struct vk_render_geometry_s *geoms;
} override;
} rt_frame_add_model_t;
void RT_FrameAddModel( struct rt_model_s *model, rt_frame_add_model_t args );