From ed69eeb5afcc26bb88245e37a9e6f94d7b739109 Mon Sep 17 00:00:00 2001 From: LifeKILLED Date: Tue, 28 Feb 2023 22:30:54 +0400 Subject: [PATCH 1/4] vk rt: fix reprojection --- ref/vk/vk_previous_frame.c | 81 +++++++++++++++++++++++++------------- ref/vk/vk_ray_model.c | 3 +- ref/vk/vk_render.c | 2 +- ref/vk/vk_studio.c | 8 ++-- 4 files changed, 59 insertions(+), 35 deletions(-) diff --git a/ref/vk/vk_previous_frame.c b/ref/vk/vk_previous_frame.c index da8cbd55..1bb49d37 100644 --- a/ref/vk/vk_previous_frame.c +++ b/ref/vk/vk_previous_frame.c @@ -26,33 +26,35 @@ typedef struct { matrix3x4 bones_worldtransform[MAXSTUDIOBONES]; matrix4x4 model_transform; float time; - int bones_update_frame_index; + uint bones_frame_updated; + uint frame_updated; } prev_state_t; typedef struct { prev_state_t prev_states[PREV_FRAMES_COUNT][PREV_STATES_COUNT]; - int frame_index; - int current_frame_id; - int previous_frame_id; + uint frame_index; + uint prev_frame_index; + uint current_frame_id; + uint previous_frame_id; } prev_states_storage_t; prev_states_storage_t g_prev = { 0 }; -static inline int clampIndex( int index, int array_length ) -{ - if (index < 0) - return 0; - else if (index >= array_length) - return array_length - 1; - - return index; -} - prev_state_t* prevStateInArrayBounds( int frame_storage_id, int entity_id ) { - int clamped_frame_id = clampIndex( frame_storage_id, PREV_FRAMES_COUNT ); - int clamped_entity_id = clampIndex( entity_id, PREV_STATES_COUNT ); - return &g_prev.prev_states[clamped_frame_id][clamped_entity_id]; + int clamped_entity_id = entity_id; + + if (entity_id >= PREV_STATES_COUNT) + { + gEngine.Con_Printf("Previous frame states data for entity %d overflows storage (size is %d). Increase it\n", entity_id, PREV_STATES_COUNT); + clamped_entity_id = PREV_STATES_COUNT - 1; // fallback to last correct value + } + else if (entity_id < 0) + { + clamped_entity_id = 0; // fallback to correct value + } + + return &g_prev.prev_states[frame_storage_id][clamped_entity_id]; } #define PREV_FRAME() prevStateInArrayBounds( g_prev.previous_frame_id, entity_id ) @@ -62,42 +64,65 @@ void R_PrevFrame_StartFrame( void ) { g_prev.frame_index++; g_prev.current_frame_id = g_prev.frame_index % PREV_FRAMES_COUNT; - g_prev.previous_frame_id = g_prev.frame_index - 1; + g_prev.previous_frame_id = (g_prev.frame_index - 1) % PREV_FRAMES_COUNT; } void R_PrevFrame_SaveCurrentBoneTransforms( int entity_id, matrix3x4* bones_transforms ) { - prev_state_t *state = CURRENT_FRAME(); + prev_state_t *current_frame = CURRENT_FRAME(); - if (state->bones_update_frame_index == g_prev.frame_index) + if (current_frame->bones_frame_updated == g_prev.frame_index) return; // already updated for this entity - state->bones_update_frame_index = g_prev.frame_index; + current_frame->bones_frame_updated = g_prev.frame_index; for( int i = 0; i < MAXSTUDIOBONES; i++ ) { - Matrix3x4_Copy(state->bones_worldtransform[i], bones_transforms[i]); + Matrix3x4_Copy( current_frame->bones_worldtransform[i], bones_transforms[i] ); } } void R_PrevFrame_SaveCurrentState( int entity_id, matrix4x4 model_transform ) { - prev_state_t* state = CURRENT_FRAME(); - Matrix4x4_Copy( state->model_transform, model_transform ); - state->time = gpGlobals->time; + prev_state_t* current_frame = CURRENT_FRAME(); + + if (current_frame->frame_updated == g_prev.frame_index) + return; // already updated for this entity + + Matrix4x4_Copy( current_frame->model_transform, model_transform ); + current_frame->time = gpGlobals->time; + current_frame->frame_updated = g_prev.frame_index; } matrix3x4* R_PrevFrame_BoneTransforms( int entity_id ) { - return PREV_FRAME()->bones_worldtransform; + prev_state_t* prev_frame = PREV_FRAME(); + + // fallback to current frame if previous is outdated + if (prev_frame->bones_frame_updated != g_prev.frame_index - 1) + return CURRENT_FRAME()->bones_worldtransform; + + return prev_frame->bones_worldtransform; } void R_PrevFrame_ModelTransform( int entity_id, matrix4x4 model_matrix ) { - Matrix4x4_Copy(model_matrix, PREV_FRAME()->model_transform); + prev_state_t* prev_frame = PREV_FRAME(); + + // fallback to current frame if previous is outdated + if (prev_frame->frame_updated != g_prev.frame_index - 1) + prev_frame = CURRENT_FRAME(); + + Matrix4x4_Copy(model_matrix, prev_frame->model_transform); } float R_PrevFrame_Time( int entity_id ) { - return PREV_FRAME()->time; + prev_state_t* prev_frame = PREV_FRAME(); + + // fallback to current frame if previous is outdated + if (prev_frame->frame_updated != g_prev.frame_index - 1) + return gpGlobals->time; + + return prev_frame->time; } diff --git a/ref/vk/vk_ray_model.c b/ref/vk/vk_ray_model.c index f3ec813b..72ec8cc0 100644 --- a/ref/vk/vk_ray_model.c +++ b/ref/vk/vk_ray_model.c @@ -522,7 +522,8 @@ void VK_RayFrameAddModel( vk_ray_model_t *model, const vk_render_model_t *render } applyMaterialToKusok(kusochki + i, geom, render_model->color, HACK_reflective); - Matrix4x4_Copy((kusochki + i)->prev_transform, render_model->prev_transform); + + Matrix4x4_ToArrayFloatGL(render_model->prev_transform, (float*)(kusochki + i)->prev_transform); } /* gEngine.Con_Reportf("model %s: geom=%d kuoffs=%d kustoff=%d kustsz=%d sthndl=%d\n", */ diff --git a/ref/vk/vk_render.c b/ref/vk/vk_render.c index 224db005..2c41addd 100644 --- a/ref/vk/vk_render.c +++ b/ref/vk/vk_render.c @@ -688,8 +688,8 @@ void VK_RenderModelDraw( const cl_entity_t *ent, vk_render_model_t* model ) { if (g_render_state.current_frame_is_ray_traced) { if (ent != NULL && model != NULL) { - R_PrevFrame_ModelTransform( ent->index, model->prev_transform ); R_PrevFrame_SaveCurrentState( ent->index, g_render_state.model ); + R_PrevFrame_ModelTransform( ent->index, model->prev_transform ); } else { Matrix4x4_Copy( model->prev_transform, g_render_state.model ); diff --git a/ref/vk/vk_studio.c b/ref/vk/vk_studio.c index 0fb4f897..65e277f3 100644 --- a/ref/vk/vk_studio.c +++ b/ref/vk/vk_studio.c @@ -2129,6 +2129,7 @@ static void R_StudioDrawPoints( void ) R_LightStrength( pvertbone[i], pstudioverts[i], g_studio.lightpos[i] ); } + R_PrevFrame_SaveCurrentBoneTransforms( RI.currententity->index, g_studio.worldtransform ); matrix3x4* prev_bones_transforms = R_PrevFrame_BoneTransforms( RI.currententity->index ); for( i = 0; i < m_pSubModel->numverts; i++ ) { @@ -2141,11 +2142,10 @@ static void R_StudioDrawPoints( void ) R_StudioComputeSkinMatrix( &pnormweight[i], g_studio.worldtransform, skinMat ); Matrix3x4_VectorRotate( skinMat, pstudionorms[i], g_studio.norms[i] ); } - - R_PrevFrame_SaveCurrentBoneTransforms( RI.currententity->index, g_studio.worldtransform ); } else { + R_PrevFrame_SaveCurrentBoneTransforms( RI.currententity->index, g_studio.bonestransform ); matrix3x4* prev_bones_transforms = R_PrevFrame_BoneTransforms( RI.currententity->index ); for( i = 0; i < m_pSubModel->numverts; i++ ) { @@ -2153,8 +2153,6 @@ static void R_StudioDrawPoints( void ) Matrix3x4_VectorTransform( prev_bones_transforms[pvertbone[i]], pstudioverts[i], g_studio.prev_verts[i] ); R_LightStrength( pvertbone[i], pstudioverts[i], g_studio.lightpos[i] ); } - - R_PrevFrame_SaveCurrentBoneTransforms( RI.currententity->index, g_studio.bonestransform ); } // generate shared normals for properly scaling glowing shell @@ -2210,7 +2208,7 @@ static void R_StudioDrawPoints( void ) qsort( g_studio.meshes, m_pSubModel->nummesh, sizeof( sortedmesh_t ), R_StudioMeshCompare ); } - // NOTE: rewind normals at start + // NOTE: rewind normals at start pstudionorms = (vec3_t *)((byte *)m_pStudioHeader + m_pSubModel->normindex); for( j = 0; j < m_pSubModel->nummesh; j++ ) From 70c52622e7a205b5b11af190b7841a50e91595db Mon Sep 17 00:00:00 2001 From: LifeKILLED Date: Tue, 28 Feb 2023 22:48:20 +0400 Subject: [PATCH 2/4] vk rt: try to fix linux build --- ref/vk/vk_ray_model.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ref/vk/vk_ray_model.c b/ref/vk/vk_ray_model.c index 72ec8cc0..eb99c883 100644 --- a/ref/vk/vk_ray_model.c +++ b/ref/vk/vk_ray_model.c @@ -523,7 +523,7 @@ void VK_RayFrameAddModel( vk_ray_model_t *model, const vk_render_model_t *render applyMaterialToKusok(kusochki + i, geom, render_model->color, HACK_reflective); - Matrix4x4_ToArrayFloatGL(render_model->prev_transform, (float*)(kusochki + i)->prev_transform); + Matrix4x4_ToArrayFloatGL(render_model->prev_transform, (float*)((kusochki + i)->prev_transform)); } /* gEngine.Con_Reportf("model %s: geom=%d kuoffs=%d kustoff=%d kustsz=%d sthndl=%d\n", */ From 5fbee4a97a92542244c4123a2a1e41fecc76ef3c Mon Sep 17 00:00:00 2001 From: LifeKILLED Date: Tue, 28 Feb 2023 22:58:54 +0400 Subject: [PATCH 3/4] vk rt: fix linux build 2 --- ref/vk/vk_ray_model.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ref/vk/vk_ray_model.c b/ref/vk/vk_ray_model.c index eb99c883..8ef3a476 100644 --- a/ref/vk/vk_ray_model.c +++ b/ref/vk/vk_ray_model.c @@ -7,6 +7,7 @@ #include "vk_render.h" #include "vk_staging.h" #include "vk_light.h" +#include "vk_math.h" #include "eiface.h" #include "xash3d_mathlib.h" @@ -523,7 +524,7 @@ void VK_RayFrameAddModel( vk_ray_model_t *model, const vk_render_model_t *render applyMaterialToKusok(kusochki + i, geom, render_model->color, HACK_reflective); - Matrix4x4_ToArrayFloatGL(render_model->prev_transform, (float*)((kusochki + i)->prev_transform)); + Matrix4x4_ToArrayFloatGL(render_model->prev_transform, (float*)(kusochki + i)->prev_transform); } /* gEngine.Con_Reportf("model %s: geom=%d kuoffs=%d kustoff=%d kustsz=%d sthndl=%d\n", */ From f4b0f5016bb8fde7b6c5faf0a0c355d8a70a0d3e Mon Sep 17 00:00:00 2001 From: LifeKILLED Date: Tue, 28 Feb 2023 22:30:54 +0400 Subject: [PATCH 4/4] vk rt: fix reprojection --- ref/vk/vk_previous_frame.c | 81 +++++++++++++++++++++++++------------- ref/vk/vk_ray_model.c | 4 +- ref/vk/vk_render.c | 2 +- ref/vk/vk_studio.c | 8 ++-- 4 files changed, 60 insertions(+), 35 deletions(-) diff --git a/ref/vk/vk_previous_frame.c b/ref/vk/vk_previous_frame.c index da8cbd55..1bb49d37 100644 --- a/ref/vk/vk_previous_frame.c +++ b/ref/vk/vk_previous_frame.c @@ -26,33 +26,35 @@ typedef struct { matrix3x4 bones_worldtransform[MAXSTUDIOBONES]; matrix4x4 model_transform; float time; - int bones_update_frame_index; + uint bones_frame_updated; + uint frame_updated; } prev_state_t; typedef struct { prev_state_t prev_states[PREV_FRAMES_COUNT][PREV_STATES_COUNT]; - int frame_index; - int current_frame_id; - int previous_frame_id; + uint frame_index; + uint prev_frame_index; + uint current_frame_id; + uint previous_frame_id; } prev_states_storage_t; prev_states_storage_t g_prev = { 0 }; -static inline int clampIndex( int index, int array_length ) -{ - if (index < 0) - return 0; - else if (index >= array_length) - return array_length - 1; - - return index; -} - prev_state_t* prevStateInArrayBounds( int frame_storage_id, int entity_id ) { - int clamped_frame_id = clampIndex( frame_storage_id, PREV_FRAMES_COUNT ); - int clamped_entity_id = clampIndex( entity_id, PREV_STATES_COUNT ); - return &g_prev.prev_states[clamped_frame_id][clamped_entity_id]; + int clamped_entity_id = entity_id; + + if (entity_id >= PREV_STATES_COUNT) + { + gEngine.Con_Printf("Previous frame states data for entity %d overflows storage (size is %d). Increase it\n", entity_id, PREV_STATES_COUNT); + clamped_entity_id = PREV_STATES_COUNT - 1; // fallback to last correct value + } + else if (entity_id < 0) + { + clamped_entity_id = 0; // fallback to correct value + } + + return &g_prev.prev_states[frame_storage_id][clamped_entity_id]; } #define PREV_FRAME() prevStateInArrayBounds( g_prev.previous_frame_id, entity_id ) @@ -62,42 +64,65 @@ void R_PrevFrame_StartFrame( void ) { g_prev.frame_index++; g_prev.current_frame_id = g_prev.frame_index % PREV_FRAMES_COUNT; - g_prev.previous_frame_id = g_prev.frame_index - 1; + g_prev.previous_frame_id = (g_prev.frame_index - 1) % PREV_FRAMES_COUNT; } void R_PrevFrame_SaveCurrentBoneTransforms( int entity_id, matrix3x4* bones_transforms ) { - prev_state_t *state = CURRENT_FRAME(); + prev_state_t *current_frame = CURRENT_FRAME(); - if (state->bones_update_frame_index == g_prev.frame_index) + if (current_frame->bones_frame_updated == g_prev.frame_index) return; // already updated for this entity - state->bones_update_frame_index = g_prev.frame_index; + current_frame->bones_frame_updated = g_prev.frame_index; for( int i = 0; i < MAXSTUDIOBONES; i++ ) { - Matrix3x4_Copy(state->bones_worldtransform[i], bones_transforms[i]); + Matrix3x4_Copy( current_frame->bones_worldtransform[i], bones_transforms[i] ); } } void R_PrevFrame_SaveCurrentState( int entity_id, matrix4x4 model_transform ) { - prev_state_t* state = CURRENT_FRAME(); - Matrix4x4_Copy( state->model_transform, model_transform ); - state->time = gpGlobals->time; + prev_state_t* current_frame = CURRENT_FRAME(); + + if (current_frame->frame_updated == g_prev.frame_index) + return; // already updated for this entity + + Matrix4x4_Copy( current_frame->model_transform, model_transform ); + current_frame->time = gpGlobals->time; + current_frame->frame_updated = g_prev.frame_index; } matrix3x4* R_PrevFrame_BoneTransforms( int entity_id ) { - return PREV_FRAME()->bones_worldtransform; + prev_state_t* prev_frame = PREV_FRAME(); + + // fallback to current frame if previous is outdated + if (prev_frame->bones_frame_updated != g_prev.frame_index - 1) + return CURRENT_FRAME()->bones_worldtransform; + + return prev_frame->bones_worldtransform; } void R_PrevFrame_ModelTransform( int entity_id, matrix4x4 model_matrix ) { - Matrix4x4_Copy(model_matrix, PREV_FRAME()->model_transform); + prev_state_t* prev_frame = PREV_FRAME(); + + // fallback to current frame if previous is outdated + if (prev_frame->frame_updated != g_prev.frame_index - 1) + prev_frame = CURRENT_FRAME(); + + Matrix4x4_Copy(model_matrix, prev_frame->model_transform); } float R_PrevFrame_Time( int entity_id ) { - return PREV_FRAME()->time; + prev_state_t* prev_frame = PREV_FRAME(); + + // fallback to current frame if previous is outdated + if (prev_frame->frame_updated != g_prev.frame_index - 1) + return gpGlobals->time; + + return prev_frame->time; } diff --git a/ref/vk/vk_ray_model.c b/ref/vk/vk_ray_model.c index f3ec813b..8ef3a476 100644 --- a/ref/vk/vk_ray_model.c +++ b/ref/vk/vk_ray_model.c @@ -7,6 +7,7 @@ #include "vk_render.h" #include "vk_staging.h" #include "vk_light.h" +#include "vk_math.h" #include "eiface.h" #include "xash3d_mathlib.h" @@ -522,7 +523,8 @@ void VK_RayFrameAddModel( vk_ray_model_t *model, const vk_render_model_t *render } applyMaterialToKusok(kusochki + i, geom, render_model->color, HACK_reflective); - Matrix4x4_Copy((kusochki + i)->prev_transform, render_model->prev_transform); + + Matrix4x4_ToArrayFloatGL(render_model->prev_transform, (float*)(kusochki + i)->prev_transform); } /* gEngine.Con_Reportf("model %s: geom=%d kuoffs=%d kustoff=%d kustsz=%d sthndl=%d\n", */ diff --git a/ref/vk/vk_render.c b/ref/vk/vk_render.c index 224db005..2c41addd 100644 --- a/ref/vk/vk_render.c +++ b/ref/vk/vk_render.c @@ -688,8 +688,8 @@ void VK_RenderModelDraw( const cl_entity_t *ent, vk_render_model_t* model ) { if (g_render_state.current_frame_is_ray_traced) { if (ent != NULL && model != NULL) { - R_PrevFrame_ModelTransform( ent->index, model->prev_transform ); R_PrevFrame_SaveCurrentState( ent->index, g_render_state.model ); + R_PrevFrame_ModelTransform( ent->index, model->prev_transform ); } else { Matrix4x4_Copy( model->prev_transform, g_render_state.model ); diff --git a/ref/vk/vk_studio.c b/ref/vk/vk_studio.c index 0fb4f897..65e277f3 100644 --- a/ref/vk/vk_studio.c +++ b/ref/vk/vk_studio.c @@ -2129,6 +2129,7 @@ static void R_StudioDrawPoints( void ) R_LightStrength( pvertbone[i], pstudioverts[i], g_studio.lightpos[i] ); } + R_PrevFrame_SaveCurrentBoneTransforms( RI.currententity->index, g_studio.worldtransform ); matrix3x4* prev_bones_transforms = R_PrevFrame_BoneTransforms( RI.currententity->index ); for( i = 0; i < m_pSubModel->numverts; i++ ) { @@ -2141,11 +2142,10 @@ static void R_StudioDrawPoints( void ) R_StudioComputeSkinMatrix( &pnormweight[i], g_studio.worldtransform, skinMat ); Matrix3x4_VectorRotate( skinMat, pstudionorms[i], g_studio.norms[i] ); } - - R_PrevFrame_SaveCurrentBoneTransforms( RI.currententity->index, g_studio.worldtransform ); } else { + R_PrevFrame_SaveCurrentBoneTransforms( RI.currententity->index, g_studio.bonestransform ); matrix3x4* prev_bones_transforms = R_PrevFrame_BoneTransforms( RI.currententity->index ); for( i = 0; i < m_pSubModel->numverts; i++ ) { @@ -2153,8 +2153,6 @@ static void R_StudioDrawPoints( void ) Matrix3x4_VectorTransform( prev_bones_transforms[pvertbone[i]], pstudioverts[i], g_studio.prev_verts[i] ); R_LightStrength( pvertbone[i], pstudioverts[i], g_studio.lightpos[i] ); } - - R_PrevFrame_SaveCurrentBoneTransforms( RI.currententity->index, g_studio.bonestransform ); } // generate shared normals for properly scaling glowing shell @@ -2210,7 +2208,7 @@ static void R_StudioDrawPoints( void ) qsort( g_studio.meshes, m_pSubModel->nummesh, sizeof( sortedmesh_t ), R_StudioMeshCompare ); } - // NOTE: rewind normals at start + // NOTE: rewind normals at start pstudionorms = (vec3_t *)((byte *)m_pStudioHeader + m_pSubModel->normindex); for( j = 0; j < m_pSubModel->nummesh; j++ )