Merge pull request #671 from w23/stream-E338
Things committed during streams E338-E339 - [x] Allow patching rendermode for func_* entities, fixes #663 - [x] Print out screenshot timings - [x] Unsuccessfully reset denoiser statistics on discontinuities
This commit is contained in:
commit
c9b485f8a7
|
@ -1,3 +1,10 @@
|
||||||
|
# 2023-11-28 E338
|
||||||
|
- [x] rendertest
|
||||||
|
- [x] read imagecompare results
|
||||||
|
- [x] html report
|
||||||
|
- [-] rendermode patch
|
||||||
|
- [ ] track patch by boolean, not another field
|
||||||
|
|
||||||
# 2023-11-27 E337
|
# 2023-11-27 E337
|
||||||
- [x] make rendetest.py the central script
|
- [x] make rendetest.py the central script
|
||||||
- [x] parallelize/make gifs
|
- [x] parallelize/make gifs
|
||||||
|
@ -7,7 +14,6 @@
|
||||||
- [ ] consider passing a special flag for single-sided blended surfaces (i.e. brush surfaces)
|
- [ ] consider passing a special flag for single-sided blended surfaces (i.e. brush surfaces)
|
||||||
- [x] fix per-entity material mapping, #669
|
- [x] fix per-entity material mapping, #669
|
||||||
- [x] add to rendertest
|
- [x] add to rendertest
|
||||||
- [ ] html report
|
|
||||||
|
|
||||||
# 2023-11-24 E336
|
# 2023-11-24 E336
|
||||||
- reproducible rendering:
|
- reproducible rendering:
|
||||||
|
|
|
@ -46,6 +46,7 @@ typedef struct {
|
||||||
|
|
||||||
typedef struct vk_brush_model_s {
|
typedef struct vk_brush_model_s {
|
||||||
model_t *engine_model;
|
model_t *engine_model;
|
||||||
|
int patch_rendermode;
|
||||||
|
|
||||||
r_geometry_range_t geometry;
|
r_geometry_range_t geometry;
|
||||||
|
|
||||||
|
@ -428,57 +429,6 @@ static vk_render_type_e brushRenderModeToRenderType( int render_mode ) {
|
||||||
return kVkRenderTypeSolid;
|
return kVkRenderTypeSolid;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 // TOO OLD
|
|
||||||
static void brushDrawWaterSurfaces( const cl_entity_t *ent, const vec4_t color, const matrix4x4 transform ) {
|
|
||||||
const model_t *model = ent->model;
|
|
||||||
vec3_t mins, maxs;
|
|
||||||
|
|
||||||
if( !VectorIsNull( ent->angles ))
|
|
||||||
{
|
|
||||||
for( int i = 0; i < 3; i++ )
|
|
||||||
{
|
|
||||||
mins[i] = ent->origin[i] - model->radius;
|
|
||||||
maxs[i] = ent->origin[i] + model->radius;
|
|
||||||
}
|
|
||||||
//rotated = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
VectorAdd( ent->origin, model->mins, mins );
|
|
||||||
VectorAdd( ent->origin, model->maxs, maxs );
|
|
||||||
//rotated = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if( R_CullBox( mins, maxs ))
|
|
||||||
// return;
|
|
||||||
|
|
||||||
VK_RenderModelDynamicBegin( brushRenderModeToRenderType(ent->curstate.rendermode), color, transform, "%s water", model->name );
|
|
||||||
|
|
||||||
// Iterate through all surfaces, find *TURB*
|
|
||||||
for( int i = 0; i < model->nummodelsurfaces; i++ )
|
|
||||||
{
|
|
||||||
const msurface_t *surf = model->surfaces + model->firstmodelsurface + i;
|
|
||||||
|
|
||||||
if( !FBitSet( surf->flags, SURF_DRAWTURB ) && !FBitSet( surf->flags, SURF_DRAWTURB_QUADS) )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if( surf->plane->type != PLANE_Z && !FBitSet( ent->curstate.effects, EF_WATERSIDES ))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if( mins[2] + 1.0f >= surf->plane->dist )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
EmitWaterPolys( ent, surf, false );
|
|
||||||
}
|
|
||||||
|
|
||||||
// submit as dynamic model
|
|
||||||
VK_RenderModelDynamicCommit();
|
|
||||||
|
|
||||||
// TODO:
|
|
||||||
// - upload water geometry only once, animate in compute/vertex shader
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const cl_entity_t *ent;
|
const cl_entity_t *ent;
|
||||||
const msurface_t *surfaces;
|
const msurface_t *surfaces;
|
||||||
|
@ -857,6 +807,9 @@ void R_BrushModelDraw( const cl_entity_t *ent, int render_mode, float blend, con
|
||||||
else
|
else
|
||||||
Matrix4x4_LoadIdentity(transform);
|
Matrix4x4_LoadIdentity(transform);
|
||||||
|
|
||||||
|
if (bmodel->patch_rendermode >= 0)
|
||||||
|
render_mode = bmodel->patch_rendermode;
|
||||||
|
|
||||||
vec4_t color = {1, 1, 1, 1};
|
vec4_t color = {1, 1, 1, 1};
|
||||||
vk_render_type_e render_type = kVkRenderTypeSolid;
|
vk_render_type_e render_type = kVkRenderTypeSolid;
|
||||||
switch (render_mode) {
|
switch (render_mode) {
|
||||||
|
@ -1042,7 +995,7 @@ static model_sizes_t computeSizes( const model_t *mod, qboolean is_worldmodel )
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const model_t *mod;
|
const model_t *mod;
|
||||||
const vk_brush_model_t *bmodel;
|
vk_brush_model_t *bmodel;
|
||||||
model_sizes_t sizes;
|
model_sizes_t sizes;
|
||||||
uint32_t base_vertex_offset;
|
uint32_t base_vertex_offset;
|
||||||
uint32_t base_index_offset;
|
uint32_t base_index_offset;
|
||||||
|
@ -1302,8 +1255,14 @@ static qboolean fillBrushSurfaces(fill_geometries_args_t args) {
|
||||||
int index_offset = args.base_index_offset;
|
int index_offset = args.base_index_offset;
|
||||||
|
|
||||||
const xvk_mapent_func_any_t *const entity_patch = getModelFuncAnyPatch(args.mod);
|
const xvk_mapent_func_any_t *const entity_patch = getModelFuncAnyPatch(args.mod);
|
||||||
if (entity_patch)
|
if (entity_patch) {
|
||||||
DEBUG("Found entity_patch(matmap_count=%d) for model \"%s\"", entity_patch->matmap_count, args.mod->name);
|
DEBUG("Found entity_patch(matmap_count=%d, rendermode_patched=%d rendermode=%d) for model \"%s\"",
|
||||||
|
entity_patch->matmap_count, entity_patch->rendermode_patched, entity_patch->rendermode, args.mod->name);
|
||||||
|
|
||||||
|
if (entity_patch->rendermode_patched > 0)
|
||||||
|
args.bmodel->patch_rendermode = entity_patch->rendermode;
|
||||||
|
}
|
||||||
|
|
||||||
connectVertices(args.mod, entity_patch ? entity_patch->smooth_entire_model : false);
|
connectVertices(args.mod, entity_patch ? entity_patch->smooth_entire_model : false);
|
||||||
|
|
||||||
// Load sorted by gl_texturenum
|
// Load sorted by gl_texturenum
|
||||||
|
@ -1616,6 +1575,7 @@ qboolean R_BrushModelLoad( model_t *mod, qboolean is_worldmodel ) {
|
||||||
g_brush.models[g_brush.models_count++] = bmodel;
|
g_brush.models[g_brush.models_count++] = bmodel;
|
||||||
|
|
||||||
bmodel->engine_model = mod;
|
bmodel->engine_model = mod;
|
||||||
|
bmodel->patch_rendermode = -1;
|
||||||
mod->cache.data = bmodel;
|
mod->cache.data = bmodel;
|
||||||
|
|
||||||
Matrix4x4_LoadIdentity(bmodel->prev_transform);
|
Matrix4x4_LoadIdentity(bmodel->prev_transform);
|
||||||
|
|
|
@ -642,7 +642,10 @@ static rgbdata_t *R_VkReadPixels( void ) {
|
||||||
0, 0, NULL, 0, NULL, ARRAYSIZE(image_barrier), image_barrier);
|
0, 0, NULL, 0, NULL, ARRAYSIZE(image_barrier), image_barrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
submit( combuf, true, draw );
|
{
|
||||||
|
const qboolean wait = true;
|
||||||
|
submit( combuf, wait, draw );
|
||||||
|
}
|
||||||
|
|
||||||
// copy bytes to buffer
|
// copy bytes to buffer
|
||||||
{
|
{
|
||||||
|
@ -705,6 +708,8 @@ qboolean VID_ScreenShot( const char *filename, int shot_type )
|
||||||
int width = 0, height = 0;
|
int width = 0, height = 0;
|
||||||
qboolean result;
|
qboolean result;
|
||||||
|
|
||||||
|
const uint64_t start_ns = aprof_time_now_ns();
|
||||||
|
|
||||||
// get screen frame
|
// get screen frame
|
||||||
rgbdata_t *r_shot = R_VkReadPixels();
|
rgbdata_t *r_shot = R_VkReadPixels();
|
||||||
if (!r_shot)
|
if (!r_shot)
|
||||||
|
@ -745,10 +750,15 @@ qboolean VID_ScreenShot( const char *filename, int shot_type )
|
||||||
gEngine.Image_Process( &r_shot, width, height, flags, 0.0f );
|
gEngine.Image_Process( &r_shot, width, height, flags, 0.0f );
|
||||||
|
|
||||||
// write image
|
// write image
|
||||||
|
const uint64_t save_begin_ns = aprof_time_now_ns();
|
||||||
result = gEngine.FS_SaveImage( filename, r_shot );
|
result = gEngine.FS_SaveImage( filename, r_shot );
|
||||||
|
const uint64_t save_end_ns = aprof_time_now_ns();
|
||||||
|
|
||||||
gEngine.fsapi->AllowDirectPaths( false ); // always reset after store screenshot
|
gEngine.fsapi->AllowDirectPaths( false ); // always reset after store screenshot
|
||||||
gEngine.FS_FreeImage( r_shot );
|
gEngine.FS_FreeImage( r_shot );
|
||||||
|
|
||||||
gEngine.Con_Printf("Wrote screenshot %s\n", filename);
|
const uint64_t end_ns = aprof_time_now_ns();
|
||||||
|
gEngine.Con_Printf("Wrote screenshot %s. Saving file: %.03fms, total: %.03fms\n",
|
||||||
|
filename, (save_end_ns - save_begin_ns) / 1e6, (end_ns - start_ns) / 1e6);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -523,10 +523,15 @@ static void patchFuncAnyEntity( const entity_props_t *props, uint32_t have_field
|
||||||
if (have_fields & Field_origin) {
|
if (have_fields & Field_origin) {
|
||||||
VectorCopy(props->origin, e->origin);
|
VectorCopy(props->origin, e->origin);
|
||||||
e->origin_patched = true;
|
e->origin_patched = true;
|
||||||
|
|
||||||
DEBUG("Patching ent=%d func_any=%d %f %f %f", e->entity_index, index, e->origin[0], e->origin[1], e->origin[2]);
|
DEBUG("Patching ent=%d func_any=%d %f %f %f", e->entity_index, index, e->origin[0], e->origin[1], e->origin[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (have_fields & Field_rendermode) {
|
||||||
|
e->rendermode = props->rendermode;
|
||||||
|
e->rendermode_patched = true;
|
||||||
|
DEBUG("Patching ent=%d func_any=%d rendermode=%d", e->entity_index, index, e->rendermode);
|
||||||
|
}
|
||||||
|
|
||||||
if (have_fields & Field__xvk_smooth_entire_model) {
|
if (have_fields & Field__xvk_smooth_entire_model) {
|
||||||
DEBUG("Patching ent=%d func_any=%d smooth_entire_model =%d", e->entity_index, index, props->_xvk_smooth_entire_model);
|
DEBUG("Patching ent=%d func_any=%d smooth_entire_model =%d", e->entity_index, index, props->_xvk_smooth_entire_model);
|
||||||
e->smooth_entire_model = props->_xvk_smooth_entire_model;
|
e->smooth_entire_model = props->_xvk_smooth_entire_model;
|
||||||
|
|
|
@ -106,8 +106,6 @@ typedef struct {
|
||||||
string model;
|
string model;
|
||||||
vec3_t origin;
|
vec3_t origin;
|
||||||
|
|
||||||
qboolean origin_patched;
|
|
||||||
|
|
||||||
#define MAX_MATERIAL_MAPPINGS 8
|
#define MAX_MATERIAL_MAPPINGS 8
|
||||||
int matmap_count;
|
int matmap_count;
|
||||||
struct {
|
struct {
|
||||||
|
@ -125,6 +123,10 @@ typedef struct {
|
||||||
|
|
||||||
struct cl_entity_s *ent;
|
struct cl_entity_s *ent;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// TODO flags
|
||||||
|
qboolean origin_patched;
|
||||||
|
qboolean rendermode_patched;
|
||||||
} xvk_mapent_func_any_t;
|
} xvk_mapent_func_any_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -87,6 +87,7 @@ static struct {
|
||||||
rt_resource_t res[MAX_RESOURCES];
|
rt_resource_t res[MAX_RESOURCES];
|
||||||
|
|
||||||
qboolean reload_pipeline;
|
qboolean reload_pipeline;
|
||||||
|
qboolean discontinuity;
|
||||||
|
|
||||||
matrix4x4 prev_inv_proj, prev_inv_view;
|
matrix4x4 prev_inv_proj, prev_inv_view;
|
||||||
|
|
||||||
|
@ -318,7 +319,7 @@ static void performTracing( vk_combuf_t *combuf, const perform_tracing_args_t* a
|
||||||
src->image = tmp_img;
|
src->image = tmp_img;
|
||||||
|
|
||||||
// If there was no initial state, prepare it. (this should happen only for the first frame)
|
// If there was no initial state, prepare it. (this should happen only for the first frame)
|
||||||
if (res->resource.write.pipelines == 0) {
|
if (g_rtx.discontinuity || res->resource.write.pipelines == 0) {
|
||||||
// TODO is there a better way? Can image be cleared w/o explicit clear op?
|
// TODO is there a better way? Can image be cleared w/o explicit clear op?
|
||||||
R_VkImageClear( cmdbuf, res->image.image );
|
R_VkImageClear( cmdbuf, res->image.image );
|
||||||
res->resource.write.pipelines = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
res->resource.write.pipelines = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
@ -656,6 +657,7 @@ void VK_RayFrameEnd(const vk_ray_frame_render_args_t* args)
|
||||||
|
|
||||||
tail:
|
tail:
|
||||||
APROF_SCOPE_END(ray_frame_end);
|
APROF_SCOPE_END(ray_frame_end);
|
||||||
|
g_rtx.discontinuity = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reloadPipeline( void ) {
|
static void reloadPipeline( void ) {
|
||||||
|
@ -742,3 +744,7 @@ void VK_RayShutdown( void ) {
|
||||||
RT_VkAccelShutdown();
|
RT_VkAccelShutdown();
|
||||||
RT_DynamicModelShutdown();
|
RT_DynamicModelShutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RT_FrameDiscontinuity( void ) {
|
||||||
|
g_rtx.discontinuity = true;
|
||||||
|
}
|
||||||
|
|
|
@ -84,3 +84,7 @@ typedef struct {
|
||||||
} rt_frame_add_once_t;
|
} rt_frame_add_once_t;
|
||||||
|
|
||||||
void RT_FrameAddOnce( rt_frame_add_once_t args );
|
void RT_FrameAddOnce( rt_frame_add_once_t args );
|
||||||
|
|
||||||
|
// Signal that the next frame is discontinuous, and all accumulated screen-space
|
||||||
|
// statistics should be reset. Should help with newmap/saveload/teleport denoiser artifacts.
|
||||||
|
void RT_FrameDiscontinuity( void );
|
||||||
|
|
|
@ -252,6 +252,8 @@ void R_NewMap( void ) {
|
||||||
// Make sure that EntityData doesn't accidentally reference old pointers.
|
// Make sure that EntityData doesn't accidentally reference old pointers.
|
||||||
VK_EntityDataClear();
|
VK_EntityDataClear();
|
||||||
|
|
||||||
|
RT_FrameDiscontinuity();
|
||||||
|
|
||||||
// Skip clearing already loaded data if the map hasn't changed.
|
// Skip clearing already loaded data if the map hasn't changed.
|
||||||
if (is_save_load)
|
if (is_save_load)
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue