vk: pass material reference explicitly in geom structure

This is needed to enable advanced material patching, where the material
can be picked up based on source type, render mode, surface number, etc
etc and all of the above combined if needed.

Previous scheme was picking up materials very late when all of this info
has been already lost.
This commit is contained in:
Ivan Avdeev 2023-09-19 13:05:12 -04:00
parent 258c3ec48e
commit 07f1bac938
13 changed files with 87 additions and 64 deletions

View File

@ -398,3 +398,17 @@ TODO: can we not have a BLAS/model for each submodel? Can it be per-model instea
# 2023-07-30
- ~~R_DrawStudioModel is the main func for drawing studio model. Called from scene code for each studio entity, with everything current (RI and stuff) set up~~
- `R_StudioDrawModelInternal()` is the main one. It is where it splits into renderer-vs-game rendering functions.
# 2023-09-19 E298
## SURF_DRAWSKY
- (context: want to remove kXVkMaterialSky, #474)
- qrad:
- uses textue name "sky" or "SKY" to check `IsSky()`. `IsSky()` surfaces do not get patches and do not participate in radiosity.
- uses CONTENTS_SKY node flag to detect whether a ray has hit skybox and can contribute sky light.
- xash/gl:
- CONTENTS_SKY is not used in any meaningful way
- sets SURF_DRAWSKY for surfaces with "sky" texture.
- uses SURF_DRAWSKY:
- to build skychain, and then draw it in Quake mode (the other branch does a bunch of math, which seemingly isn't used for anything at all).
- for dynamic lighting: if sky ray has hit sky surface then sky is contributing light

View File

@ -275,9 +275,10 @@ static void brushComputeWaterPolys( compute_water_polys_t args ) {
// Render
const int tex_id = args.warp->texinfo->texture->gl_texturenum;
const r_vk_material_ref_t material_ref = R_VkMaterialGetForTexture(tex_id);
*args.dst_geometry = (vk_render_geometry_t){
.texture = tex_id, // FIXME assert >= 0
.material = kXVkMaterialRegular,
.material = material_ref,
.material_type_deprecated = kXVkMaterialRegular,
.surf_deprecate = args.warp,
.max_vertex = vertices,
@ -704,7 +705,7 @@ void VK_BrushModelDraw( const cl_entity_t *ent, int render_mode, float blend, co
// TODO also it will break switching render type from TransColor to anyting else -- textures will be stuck at white
for (int i = 0; i < bmodel->render_model.num_geometries; ++i) {
vk_render_geometry_t *geom = bmodel->render_model.geometries + i;
geom->texture = tglob.whiteTexture;
geom->material = R_VkMaterialGetForTexture(tglob.whiteTexture);
}
} else {
APROF_SCOPE_DECLARE_BEGIN(brush_update_textures, "brush: update animated textures");
@ -719,10 +720,11 @@ void VK_BrushModelDraw( const cl_entity_t *ent, int render_mode, float blend, co
// Optionally patch by texture_s pointer and run animations
const struct texture_s *texture_override = patch_surface ? patch_surface->tex : NULL;
const texture_t *t = R_TextureAnimation(ent, geom->surf_deprecate, texture_override);
const int new_texture = t->gl_texturenum;
const int tex_id = t->gl_texturenum;
if (new_texture >= 0 && new_texture != geom->texture) {
geom->texture = t->gl_texturenum;
const r_vk_material_ref_t new_material = R_VkMaterialGetForTexture(tex_id);
if (new_material.index >= 0 && new_material.index != geom->material.index) {
geom->material = new_material;
if (updated_textures_count < MAX_ANIMATED_TEXTURES) {
g_brush.updated_textures[updated_textures_count++] = bmodel->animated_indexes[i];
}
@ -732,7 +734,7 @@ void VK_BrushModelDraw( const cl_entity_t *ent, int render_mode, float blend, co
// Add them as dynamic lights for now. It would probably be better if they were static lights (for worldmodel),
// but there's no easy way to do it for now.
vec3_t *emissive = &bmodel->render_model.geometries[geom_index].emissive;
if (RT_GetEmissiveForTexture(*emissive, geom->texture)) {
if (RT_GetEmissiveForTexture(*emissive, tex_id)) {
rt_light_add_polygon_t polylight = loadPolyLight(mod, surface_index, geom->surf_deprecate, *emissive);
polylight.dynamic = true;
polylight.transform_row = (const matrix3x4*)&transform;
@ -1075,7 +1077,7 @@ static qboolean fillBrushSurfaces(fill_geometries_args_t args) {
VectorClear(model_geometry->emissive);
model_geometry->surf_deprecate = surf;
model_geometry->texture = tex_id;
model_geometry->material = R_VkMaterialGetForTexture(tex_id);
model_geometry->vertex_offset = args.base_vertex_offset;
model_geometry->max_vertex = vertex_offset + surf->numedges;
@ -1083,9 +1085,9 @@ static qboolean fillBrushSurfaces(fill_geometries_args_t args) {
model_geometry->index_offset = index_offset;
if(type == BrushSurface_Sky) {
model_geometry->material = kXVkMaterialSky;
model_geometry->material_type_deprecated = kXVkMaterialSky;
} else {
model_geometry->material = kXVkMaterialRegular;
model_geometry->material_type_deprecated = kXVkMaterialRegular;
ASSERT(!FBitSet( surf->flags, SURF_DRAWTILED ));
VK_CreateSurfaceLightmap( surf, args.mod );
}

View File

@ -11,7 +11,7 @@
#define MAX_INCLUDE_DEPTH 4
static xvk_material_t k_default_material = {
static r_vk_material_t k_default_material = {
.tex_base_color = -1,
.tex_metalness = 0,
.tex_roughness = 0,
@ -26,7 +26,7 @@ static xvk_material_t k_default_material = {
};
static struct {
xvk_material_t materials[MAX_TEXTURES];
r_vk_material_t materials[MAX_TEXTURES];
} g_materials;
static struct {
@ -70,7 +70,7 @@ static void loadMaterialsFromFile( const char *filename, int depth ) {
g_stats.material_file_read_duration_ns += aprof_time_now_ns() - load_file_begin_ns;
char *pos = (char*)data;
xvk_material_t current_material = k_default_material;
r_vk_material_t current_material = k_default_material;
int current_material_index = -1;
qboolean force_reload = false;
qboolean create = false;
@ -215,7 +215,7 @@ static void loadMaterialsFromFileF( const char *fmt, ... ) {
loadMaterialsFromFile( buffer, MAX_INCLUDE_DEPTH );
}
void XVK_ReloadMaterials( void ) {
void R_VkMaterialsReload( void ) {
memset(&g_stats, 0, sizeof(g_stats));
const uint64_t begin_time_ns = aprof_time_now_ns();
@ -223,7 +223,7 @@ void XVK_ReloadMaterials( void ) {
k_default_material.tex_roughness = tglob.whiteTexture;
for (int i = 0; i < MAX_TEXTURES; ++i) {
xvk_material_t *const mat = g_materials.materials + i;
r_vk_material_t *const mat = g_materials.materials + i;
const vk_texture_t *const tex = findTexture( i );
*mat = k_default_material;
@ -264,14 +264,18 @@ void XVK_ReloadMaterials( void ) {
}
}
xvk_material_t* XVK_GetMaterialForTextureIndex( int tex_index ) {
xvk_material_t *mat = NULL;
r_vk_material_ref_t R_VkMaterialGetForTexture( int tex_index ) {
ASSERT(tex_index >= 0);
ASSERT(tex_index < MAX_TEXTURES);
mat = g_materials.materials + tex_index;
if (mat->base_color >= 0)
return mat;
return NULL;
// TODO add versioning to detect reloads?
return (r_vk_material_ref_t){ .index = tex_index, };
}
const r_vk_material_t* R_VkMaterialGet( r_vk_material_ref_t ref ) {
ASSERT(ref.index >= 0);
ASSERT(ref.index < MAX_TEXTURES);
// TODO verify version ?
return g_materials.materials + ref.index;
}

View File

@ -2,7 +2,7 @@
#include "xash3d_types.h"
typedef struct {
typedef struct r_vk_material_s {
int tex_base_color;
int tex_roughness;
int tex_metalness;
@ -14,8 +14,14 @@ typedef struct {
float normal_scale;
qboolean set;
} xvk_material_t;
} r_vk_material_t;
void XVK_ReloadMaterials( void );
typedef struct { int index; } r_vk_material_ref_t;
xvk_material_t* XVK_GetMaterialForTextureIndex( int tex_index );
// Note: invalidates all previously issued material refs
// TODO: track "version" in high bits?
void R_VkMaterialsReload( void );
r_vk_material_ref_t R_VkMaterialGetForTexture( int tex_id );
const r_vk_material_t* R_VkMaterialGet( r_vk_material_ref_t ref );

View File

@ -101,8 +101,8 @@ 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(uint32_t kusochki_offset, const struct vk_render_geometry_s *geoms, int geoms_count, int override_texture_id, const vec4_t *override_color);
//struct vk_render_geometry_s;
//qboolean RT_KusochkiUpload(uint32_t kusochki_offset, const struct vk_render_geometry_s *geoms, int geoms_count, int override_texture_id, const vec4_t *override_color);
qboolean RT_DynamicModelInit(void);
void RT_DynamicModelShutdown(void);

View File

@ -25,9 +25,8 @@ typedef struct rt_model_s {
rt_kusochki_t kusochki;
} rt_model_t;
static void applyMaterialToKusok(vk_kusok_data_t* kusok, const vk_render_geometry_t *geom, int override_texture_id, const vec4_t override_color) {
const int tex_id = override_texture_id > 0 ? override_texture_id : geom->texture;
const xvk_material_t *const mat = XVK_GetMaterialForTextureIndex( tex_id );
static void applyMaterialToKusok(vk_kusok_data_t* kusok, const vk_render_geometry_t *geom, const r_vk_material_t *override_material, const vec4_t override_color) {
const r_vk_material_t *const mat = override_material ? override_material : R_VkMaterialGet(geom->material);
ASSERT(mat);
// TODO split kusochki into static geometry data and potentially dynamic material data
@ -59,12 +58,12 @@ static void applyMaterialToKusok(vk_kusok_data_t* kusok, const vk_render_geometr
}
// TODO should be patched by the Chrome material source itself to generate a static chrome material
const qboolean HACK_chrome = geom->material == kXVkMaterialChrome;
const qboolean HACK_chrome = geom->material_type_deprecated == kXVkMaterialChrome;
if (!mat->set && HACK_chrome)
kusok->material.tex_roughness = tglob.grayTexture;
// Purely static. Once a sky forever a sky.
if (geom->material == kXVkMaterialSky)
if (geom->material_type_deprecated == kXVkMaterialSky)
kusok->material.tex_base_color = TEX_BASE_SKYBOX;
}
@ -180,7 +179,7 @@ void RT_KusochkiFree(const rt_kusochki_t *kusochki) {
}
// TODO this function can't really fail. It'd mean that staging is completely broken.
qboolean RT_KusochkiUpload(uint32_t kusochki_offset, const struct vk_render_geometry_s *geoms, int geoms_count, int override_texture_id, const vec4_t *override_colors) {
qboolean RT_KusochkiUpload(uint32_t kusochki_offset, const struct vk_render_geometry_s *geoms, int geoms_count, const r_vk_material_t *override_material, const vec4_t *override_colors) {
const vk_staging_buffer_args_t staging_args = {
.buffer = g_ray_model_state.kusochki_buffer.buffer,
.offset = kusochki_offset * sizeof(vk_kusok_data_t),
@ -197,7 +196,7 @@ qboolean RT_KusochkiUpload(uint32_t kusochki_offset, const struct vk_render_geom
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, override_texture_id, override_colors ? override_colors[i] : NULL);
applyMaterialToKusok(p + i, geom, override_material, override_colors ? override_colors[i] : NULL);
}
R_VkStagingUnlock(kusok_staging.handle);
@ -222,7 +221,7 @@ struct rt_model_s *RT_ModelCreate(rt_model_create_t args) {
goto fail;
}
RT_KusochkiUpload(kusochki.offset, args.geometries, args.geometries_count, -1, NULL);
RT_KusochkiUpload(kusochki.offset, args.geometries, args.geometries_count, NULL, NULL);
{
rt_model_t *const ret = Mem_Malloc(vk_core.pool, sizeof(*ret));
@ -275,7 +274,7 @@ qboolean RT_ModelUpdateMaterials(struct rt_model_s *model, const struct vk_rende
const int offset = geom_indices[begin];
const int count = i - begin;
ASSERT(offset + count <= geometries_count);
if (!RT_KusochkiUpload(model->kusochki.offset + offset, geometries + offset, count, -1, NULL)) {
if (!RT_KusochkiUpload(model->kusochki.offset + offset, geometries + offset, count, NULL, NULL)) {
APROF_SCOPE_END(update_materials);
return false;
}
@ -288,7 +287,7 @@ qboolean RT_ModelUpdateMaterials(struct rt_model_s *model, const struct vk_rende
const int offset = geom_indices[begin];
const int count = geom_indices_count - begin;
ASSERT(offset + count <= geometries_count);
if (!RT_KusochkiUpload(model->kusochki.offset + offset, geometries + offset, count, -1, NULL)) {
if (!RT_KusochkiUpload(model->kusochki.offset + offset, geometries + offset, count, NULL, NULL)) {
APROF_SCOPE_END(update_materials);
return false;
@ -314,12 +313,12 @@ void RT_FrameAddModel( struct rt_model_s *model, rt_frame_add_model_t args ) {
uint32_t kusochki_offset = model->kusochki.offset;
if (args.override.textures > 0) {
if (args.override.material != NULL) {
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, NULL)) {
if (!RT_KusochkiUpload(kusochki_offset, args.override.geoms, args.override.geoms_count, args.override.material, NULL)) {
gEngine.Con_Printf(S_ERROR "Couldn't upload kusochki for instanced model\n");
return;
}
@ -413,7 +412,7 @@ void RT_DynamicModelProcessFrame(void) {
}
// FIXME override color
if (!RT_KusochkiUpload(kusochki_offset, dyn->geometries, dyn->geometries_count, -1, dyn->colors)) {
if (!RT_KusochkiUpload(kusochki_offset, dyn->geometries, dyn->geometries_count, NULL, dyn->colors)) {
gEngine.Con_Printf(S_ERROR "Couldn't build blas for %d geoms of %s, skipping\n", dyn->geometries_count, group_names[i]);
goto tail;
}

View File

@ -723,7 +723,8 @@ static void submitToTraditionalRender( trad_submit_t args ) {
for (int i = 0; i < args.geometries_count; ++i) {
const vk_render_geometry_t *geom = args.geometries + i;
const int tex = args.textures_override > 0 ? args.textures_override : geom->texture;
const r_vk_material_t *material = R_VkMaterialGet(geom->material);
const int tex = args.textures_override > 0 ? args.textures_override : material->tex_base_color;
const qboolean split = current_texture != tex
|| vertex_offset != geom->vertex_offset
|| (index_offset + element_count) != geom->index_offset;
@ -788,7 +789,7 @@ void R_RenderModelDraw(const vk_render_model_t *model, r_model_draw_t args) {
.dynamic_polylights = model->dynamic_polylights,
.dynamic_polylights_count = model->dynamic_polylights_count,
.override = {
.textures = args.textures_override,
.material = args.material_override,
.geoms = model->geometries,
.geoms_count = model->num_geometries,
},
@ -802,7 +803,7 @@ void R_RenderModelDraw(const vk_render_model_t *model, r_model_draw_t args) {
.transform = args.transform,
.color = args.color,
.render_type = args.render_type,
.textures_override = args.textures_override
.textures_override = args.material_override ? args.material_override->tex_base_color : -1,
});
}
}
@ -820,8 +821,7 @@ void R_RenderDrawOnce(r_draw_once_t args) {
R_GeometryBufferUnlock( &buffer );
const vk_render_geometry_t geometry = {
.texture = args.texture,
.material = kXVkMaterialRegular,
.material = args.material, .material_type_deprecated = kXVkMaterialRegular,
.max_vertex = args.vertices_count,
.vertex_offset = buffer.vertices.unit_offset,

View File

@ -1,4 +1,5 @@
#pragma once
#include "vk_materials.h"
#include "vk_common.h"
#include "vk_const.h"
#include "vk_core.h"
@ -27,7 +28,7 @@ typedef enum {
// Used: ray tracing sets gray roughness texture to get smooth surface look.
// Remove: Have an explicit material for chrome surfaces.
kXVkMaterialChrome,
} XVkMaterialType;
} XVkMaterialType_Deprecated;
typedef struct vk_render_geometry_s {
int index_offset, vertex_offset;
@ -42,11 +43,9 @@ typedef struct vk_render_geometry_s {
// Remove: have an explicit list of surfaces with animated textures
const struct msurface_s *surf_deprecate;
// Animated textures will be dynamic and change between frames
int texture;
// If this geometry is special, it will have a material type override
XVkMaterialType material;
XVkMaterialType_Deprecated material_type_deprecated;
r_vk_material_ref_t material;
// for kXVkMaterialEmissive{,Glow} and others
vec3_t emissive;
@ -145,9 +144,7 @@ typedef struct {
const vec4_t *color;
const matrix4x4 *transform, *prev_transform;
// Global texture override if > 0
// Used by sprite+quad instancing
int textures_override;
const r_vk_material_t* material_override;
} r_model_draw_t;
void R_RenderModelDraw(const vk_render_model_t *model, r_model_draw_t args);
@ -159,7 +156,7 @@ typedef struct {
int vertices_count, indices_count;
int render_type;
int texture;
r_vk_material_ref_t material;
const vec4_t *emissive;
const vec4_t *color;
} r_draw_once_t;

View File

@ -34,6 +34,7 @@ void VK_RayShutdown( void );
struct vk_render_geometry_s;
struct rt_model_s;
struct r_vk_material_s;
typedef enum {
kBlasBuildStatic, // builds slow for fast trace
@ -63,7 +64,7 @@ typedef struct {
int dynamic_polylights_count;
struct {
int textures; // Override kusochki/material textures if > 0
const struct r_vk_material_s *material;
// These are needed in order to recreate kusochki geometry data
// TODO remove when material data is split from kusochki

View File

@ -148,7 +148,7 @@ static void loadMap(const model_t* const map) {
XVK_ParseMapEntities();
// Load PBR materials (depends on wadlist from parsed map entities)
XVK_ReloadMaterials();
R_VkMaterialsReload();
// Parse patch data
// Depends on loaded materials. Must preceed loading brush models.

View File

@ -103,8 +103,8 @@ static qboolean createQuadModel(void) {
.element_count = 6,
.index_offset = g_sprite.quad.geom.indices.unit_offset,
.material = kXVkMaterialRegular,
.texture = tglob.defaultTexture,
.material_type_deprecated = kXVkMaterialRegular,
.material = R_VkMaterialGetForTexture(tglob.defaultTexture),
.emissive = {1,1,1},
};
@ -804,7 +804,7 @@ static void R_DrawSpriteQuad( const char *debug_name, const mspriteframe_t *fram
.color = (const vec4_t*)color,
.transform = &transform,
.prev_transform = &transform,
.textures_override = texture,
.material_override = R_VkMaterialGet(R_VkMaterialGetForTexture(texture)),
});
}

View File

@ -1770,8 +1770,8 @@ static void buildSubmodelMeshGeometry( build_submodel_mesh_t args ) {
ASSERT(vertex_offset == num_vertices);
*args.out_geometry = (vk_render_geometry_t){
.texture = args.texture,
.material = FBitSet( args.face_flags, STUDIO_NF_CHROME ) ? kXVkMaterialChrome : kXVkMaterialRegular,
.material = R_VkMaterialGetForTexture(args.texture),
.material_type_deprecated = FBitSet( args.face_flags, STUDIO_NF_CHROME ) ? kXVkMaterialChrome : kXVkMaterialRegular,
.vertex_offset = args.vertices_offset,
.max_vertex = num_vertices,
@ -2304,7 +2304,7 @@ static void R_StudioDrawPoints( void ) {
.color = &color,
.transform = &g_studio_current.entmodel->transform,
.prev_transform = &g_studio_current.entmodel->prev_transform,
.textures_override = -1,
.material_override = NULL,
});
++g_studio_stats.submodels_total;

View File

@ -170,7 +170,7 @@ void TriEndEx( const vec4_t color, const char* name ) {
.vertices_count = g_triapi.num_vertices,
.indices_count = num_indices,
.render_type = g_triapi.render_type,
.texture = g_triapi.texture_index,
.material = R_VkMaterialGetForTexture(g_triapi.texture_index),
.emissive = (const vec4_t*)color,
.color = (const vec4_t*)color,
});