removed screenshot/videoframe requests from the render command list

This commit is contained in:
myT 2023-11-23 19:59:39 +01:00
parent b91e20a1b9
commit 9a6e253dc3
5 changed files with 57 additions and 106 deletions

View file

@ -656,7 +656,7 @@ struct GRP : IRenderPipeline
void ProcessModel(model_t& model) override; void ProcessModel(model_t& model) override;
void ProcessShader(shader_t& shader) override; void ProcessShader(shader_t& shader) override;
void ExecuteRenderCommands(const byte* data) override; void ExecuteRenderCommands(const byte* data, bool readbackRequested) override;
void UISetColor(const uiSetColorCommand_t& cmd) override { ui.UISetColor(cmd); } void UISetColor(const uiSetColorCommand_t& cmd) override { ui.UISetColor(cmd); }
void UIDrawQuad(const uiDrawQuadCommand_t& cmd) override { ui.UIDrawQuad(cmd); } void UIDrawQuad(const uiDrawQuadCommand_t& cmd) override { ui.UIDrawQuad(cmd); }

View file

@ -884,11 +884,9 @@ uint32_t GRP::CreatePSO(CachedPSO& cache, const char* name)
return index; return index;
} }
void GRP::ExecuteRenderCommands(const byte* data) void GRP::ExecuteRenderCommands(const byte* data, bool readbackRequested)
{ {
updateReadbackTexture = updateReadbackTexture = readbackRequested;
R_FindRenderCommand(RC_SCREENSHOT) != NULL ||
R_FindRenderCommand(RC_VIDEOFRAME) != NULL;
for(;;) for(;;)
{ {
@ -940,12 +938,6 @@ void GRP::ExecuteRenderCommands(const byte* data)
case RC_END_SCENE: case RC_END_SCENE:
smaa.Draw(((const endSceneCommand_t*)data)->viewParms); smaa.Draw(((const endSceneCommand_t*)data)->viewParms);
break; break;
case RC_SCREENSHOT:
RB_TakeScreenshotCmd((const screenshotCommand_t*)data);
break;
case RC_VIDEOFRAME:
RB_TakeVideoFrameCmd((const videoFrameCommand_t*)data);
break;
default: default:
Q_assert(!"Unsupported render command type"); Q_assert(!"Unsupported render command type");

View file

@ -30,63 +30,42 @@ const int renderCommandSizes[RC_COUNT + 1] =
}; };
#undef RC #undef RC
// we reserve space for frame ending commands as well as transition commands (begin/end 2D/3D rendering) // we reserve space for frame ending commands as well as transition commands (begin/end 2D/3D rendering)
static const int CmdListReservedBytes = (int)(sizeof(swapBuffersCommand_t) + sizeof(screenshotCommand_t) + 16 * sizeof(void*)); static const int CmdListReservedBytes = (int)(sizeof(swapBuffersCommand_t) + sizeof(screenshotCommand_t) + 16 * sizeof(void*));
static qbool R_IsReadbackRequested( readbackCommands_t* readback )
{
Q_assert( readback );
return
readback->screenshot.requested != 0 ||
readback->videoFrame.requested != 0;
}
void R_IssueRenderCommands() void R_IssueRenderCommands()
{ {
renderCommandList_t* cmdList = &backEndData->commands;
// add an end-of-list command // add an end-of-list command
renderCommandList_t* cmdList = &backEndData->commands;
((renderCommandBase_t*)(cmdList->cmds + cmdList->used))->commandId = RC_END_OF_LIST; ((renderCommandBase_t*)(cmdList->cmds + cmdList->used))->commandId = RC_END_OF_LIST;
// clear it out, in case this is a sync and not a buffer flip // clear it out, in case this is a sync and not a buffer flip
cmdList->used = 0; cmdList->used = 0;
renderPipeline->ExecuteRenderCommands( cmdList->cmds ); // process render commands
} readbackCommands_t* const readback = &backEndData->readbackCommands;
renderPipeline->ExecuteRenderCommands( cmdList->cmds, R_IsReadbackRequested( readback ) );
// process readback commands
byte* R_FindRenderCommand( renderCommand_t type ) if ( readback->screenshot.requested ) {
{ RB_TakeScreenshotCmd( &readback->screenshot );
renderCommandList_t* cmdList = &backEndData->commands;
byte* data = cmdList->cmds;
byte* end = cmdList->cmds + cmdList->used;
for ( ;; ) {
const int commandId = ((const renderCommandBase_t*)data)->commandId;
if( commandId == type )
return (byte*)data;
if ( data >= end )
return NULL;
if ( commandId < 0 || commandId >= RC_COUNT ) {
Q_assert( !"Invalid render command type" );
return NULL;
}
if ( commandId == RC_END_OF_LIST )
return NULL;
data += renderCommandSizes[commandId];
} }
} if ( readback->videoFrame.requested ) {
RB_TakeVideoFrameCmd( &readback->videoFrame );
}
static void RemoveRenderCommand( byte* cmd, int cmdSize ) readback->screenshot.requested = qfalse;
{ readback->videoFrame.requested = qfalse;
renderCommandList_t* cmdList = &backEndData->commands;
const int endOffset = (cmd + cmdSize) - cmdList->cmds;
const int endBytes = cmdList->used - endOffset;
Q_assert( cmd >= cmdList->cmds );
Q_assert( cmd + cmdSize <= cmdList->cmds + cmdList->used );
memmove( cmd, cmd + cmdSize, endBytes );
cmdList->used -= cmdSize;
} }
@ -301,7 +280,7 @@ void RE_DrawTriangle( float x0, float y0, float x1, float y1, float x2, float y2
void RE_BeginFrame( stereoFrame_t stereoFrame ) void RE_BeginFrame( stereoFrame_t stereoFrame )
{ {
if (!tr.registered) if ( !tr.registered )
return; return;
tr.frameCount++; tr.frameCount++;
@ -311,13 +290,11 @@ void RE_BeginFrame( stereoFrame_t stereoFrame )
// delayed screenshot // delayed screenshot
if ( r_delayedScreenshotPending ) { if ( r_delayedScreenshotPending ) {
r_delayedScreenshotFrame++; r_delayedScreenshotFrame++;
if ( r_delayedScreenshotFrame >= 2 ) { if ( r_delayedScreenshotFrame >= 1 ) {
screenshotCommand_t* const cmd = AllocateRenderCommand<screenshotCommand_t>( RC_SCREENSHOT ); backEndData->readbackCommands.screenshot = r_delayedScreenshot;
if ( cmd ) { backEndData->readbackCommands.screenshot.requested = qtrue;
*cmd = r_delayedScreenshot; r_delayedScreenshotPending = qfalse;
r_delayedScreenshotPending = qfalse; r_delayedScreenshotFrame = 0;
r_delayedScreenshotFrame = 0;
}
} }
} }
@ -330,26 +307,16 @@ void RE_BeginFrame( stereoFrame_t stereoFrame )
void RE_EndFrame( qbool render ) void RE_EndFrame( qbool render )
{ {
if (!tr.registered) if ( !tr.registered )
return; return;
qbool delayScreenshot = qfalse;
if ( !render && r_delayedScreenshotPending ) if ( !render && r_delayedScreenshotPending )
render = qtrue; render = qtrue;
if ( !render ) { if ( !render ) {
screenshotCommand_t* ssCmd = (screenshotCommand_t*)R_FindRenderCommand( RC_SCREENSHOT ); readbackCommands_t* const readback = &backEndData->readbackCommands;
if ( R_IsReadbackRequested( readback ) )
if ( ssCmd )
render = qtrue; render = qtrue;
if ( ssCmd && !ssCmd->delayed ) {
// save and remove the command so we can push it back after the frame's done
r_delayedScreenshot = *ssCmd;
r_delayedScreenshot.delayed = qtrue;
RemoveRenderCommand( (byte*)ssCmd, sizeof(screenshotCommand_t) );
delayScreenshot = qtrue;
}
} }
backEnd.renderFrame = render; backEnd.renderFrame = render;
@ -359,10 +326,6 @@ void RE_EndFrame( qbool render )
if ( render ) { if ( render ) {
AllocateRenderCommand<swapBuffersCommand_t>( RC_SWAP_BUFFERS, qtrue ); AllocateRenderCommand<swapBuffersCommand_t>( RC_SWAP_BUFFERS, qtrue );
if ( delayScreenshot ) {
screenshotCommand_t* const cmd = AllocateRenderCommand<screenshotCommand_t>( RC_SCREENSHOT, qtrue );
*cmd = r_delayedScreenshot;
}
} else { } else {
R_ClearFrame(); R_ClearFrame();
} }
@ -385,9 +348,8 @@ void RE_TakeVideoFrame( int width, int height, byte *captureBuffer, byte *encode
End2D(); End2D();
End3D(); End3D();
videoFrameCommand_t* const cmd = AllocateRenderCommand<videoFrameCommand_t>( RC_VIDEOFRAME ); videoFrameCommand_t* const cmd = &backEndData->readbackCommands.videoFrame;
Q_assert( cmd ); cmd->requested = qtrue;
cmd->width = width; cmd->width = width;
cmd->height = height; cmd->height = height;
cmd->captureBuffer = captureBuffer; cmd->captureBuffer = captureBuffer;

View file

@ -184,7 +184,7 @@ static void RB_TakeScreenshotJPG( int width, int height, const char* fileName )
} }
const byte* RB_TakeScreenshotCmd( const screenshotCommand_t* cmd ) void RB_TakeScreenshotCmd( const screenshotCommand_t* cmd )
{ {
switch (cmd->type) { switch (cmd->type) {
case screenshotCommand_t::SS_JPG: case screenshotCommand_t::SS_JPG:
@ -202,8 +202,6 @@ const byte* RB_TakeScreenshotCmd( const screenshotCommand_t* cmd )
r_delayedScreenshotPending = qfalse; r_delayedScreenshotPending = qfalse;
r_delayedScreenshotFrame = 0; r_delayedScreenshotFrame = 0;
} }
return (const byte*)(cmd + 1);
} }
@ -220,14 +218,10 @@ static void R_TakeScreenshot( const char* ext, screenshotCommand_t::ss_type type
cmd = &r_delayedScreenshot; cmd = &r_delayedScreenshot;
r_delayedScreenshotPending = qtrue; r_delayedScreenshotPending = qtrue;
r_delayedScreenshotFrame = 0; r_delayedScreenshotFrame = 0;
cmd->delayed = qtrue;
} else { } else {
if ( R_FindRenderCommand( RC_SCREENSHOT ) ) cmd = &backEndData->readbackCommands.screenshot;
if ( cmd->requested )
return; return;
cmd = (screenshotCommand_t*)R_AllocateRenderCommand( sizeof(screenshotCommand_t), RC_SCREENSHOT, qfalse );
if ( !cmd )
return;
cmd->delayed = qfalse;
} }
if (ri.Cmd_Argc() == 2) { if (ri.Cmd_Argc() == 2) {
@ -240,7 +234,7 @@ static void R_TakeScreenshot( const char* ext, screenshotCommand_t::ss_type type
1900+t.tm_year, 1+t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, ms, ext ); 1900+t.tm_year, 1+t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, ms, ext );
} }
cmd->commandId = RC_SCREENSHOT; cmd->requested = qtrue;
cmd->width = glConfig.vidWidth; cmd->width = glConfig.vidWidth;
cmd->height = glConfig.vidHeight; cmd->height = glConfig.vidHeight;
cmd->fileName = s; cmd->fileName = s;
@ -276,7 +270,7 @@ static void R_ScreenShotNoConJPG_f()
//============================================================================ //============================================================================
const byte *RB_TakeVideoFrameCmd( const videoFrameCommand_t *cmd ) void RB_TakeVideoFrameCmd( const videoFrameCommand_t *cmd )
{ {
if( cmd->motionJpeg ) if( cmd->motionJpeg )
{ {
@ -290,8 +284,6 @@ const byte *RB_TakeVideoFrameCmd( const videoFrameCommand_t *cmd )
const int frameSize = PAD( cmd->width, 4 ) * cmd->height * 3; const int frameSize = PAD( cmd->width, 4 ) * cmd->height * 3;
ri.CL_WriteAVIVideoFrame( cmd->captureBuffer, frameSize ); ri.CL_WriteAVIVideoFrame( cmd->captureBuffer, frameSize );
} }
return (const byte *)(cmd + 1);
} }

View file

@ -1490,18 +1490,20 @@ struct endSceneCommand_t : renderCommandBase_t {
uint32_t padding2; uint32_t padding2;
}; };
struct screenshotCommand_t : renderCommandBase_t { struct readbackCommandBase_t {
qbool requested;
};
struct screenshotCommand_t : readbackCommandBase_t {
int width; int width;
int height; int height;
const char* fileName; const char* fileName;
enum ss_type { SS_TGA, SS_JPG } type; enum ss_type { SS_TGA, SS_JPG } type;
float conVis; // if > 0, this is a delayed screenshot and we need to float conVis; // if > 0, this is a delayed screenshot and we need to
// restore the console visibility to that value // restore the console visibility to that value
qbool delayed;
}; };
struct videoFrameCommand_t : renderCommandBase_t { struct videoFrameCommand_t : readbackCommandBase_t {
int commandId;
int width; int width;
int height; int height;
byte *captureBuffer; byte *captureBuffer;
@ -1509,6 +1511,11 @@ struct videoFrameCommand_t : renderCommandBase_t {
qbool motionJpeg; qbool motionJpeg;
}; };
struct readbackCommands_t {
screenshotCommand_t screenshot;
videoFrameCommand_t videoFrame;
};
#pragma pack(pop) #pragma pack(pop)
#define RENDER_COMMAND_LIST(Cmd) \ #define RENDER_COMMAND_LIST(Cmd) \
@ -1523,9 +1530,7 @@ struct videoFrameCommand_t : renderCommandBase_t {
Cmd(RC_DRAW_SCENE_VIEW, drawSceneViewCommand_t) \ Cmd(RC_DRAW_SCENE_VIEW, drawSceneViewCommand_t) \
Cmd(RC_END_SCENE, endSceneCommand_t) \ Cmd(RC_END_SCENE, endSceneCommand_t) \
Cmd(RC_BEGIN_FRAME, beginFrameCommand_t) \ Cmd(RC_BEGIN_FRAME, beginFrameCommand_t) \
Cmd(RC_SWAP_BUFFERS, swapBuffersCommand_t) \ Cmd(RC_SWAP_BUFFERS, swapBuffersCommand_t)
Cmd(RC_SCREENSHOT, screenshotCommand_t) \
Cmd(RC_VIDEOFRAME, videoFrameCommand_t)
#define RC(Enum, Type) Enum, #define RC(Enum, Type) Enum,
enum renderCommand_t { enum renderCommand_t {
@ -1550,6 +1555,7 @@ typedef struct {
srfPoly_t *polys; srfPoly_t *polys;
polyVert_t *polyVerts; polyVert_t *polyVerts;
renderCommandList_t commands; renderCommandList_t commands;
readbackCommands_t readbackCommands;
} backEndData_t; } backEndData_t;
#define SKY_SUBDIVISIONS 8 #define SKY_SUBDIVISIONS 8
@ -1566,8 +1572,8 @@ extern int max_polyverts;
extern backEndData_t* backEndData; extern backEndData_t* backEndData;
const byte* RB_TakeScreenshotCmd( const screenshotCommand_t* cmd ); void RB_TakeScreenshotCmd( const screenshotCommand_t* cmd );
const byte* RB_TakeVideoFrameCmd( const videoFrameCommand_t* cmd ); void RB_TakeVideoFrameCmd( const videoFrameCommand_t* cmd );
void RB_PushSingleStageShader( int stateBits, cullType_t cullType ); void RB_PushSingleStageShader( int stateBits, cullType_t cullType );
void RB_PopShader(); void RB_PopShader();
@ -1578,7 +1584,6 @@ void RB_DrawSky();
void R_BuildCloudData(); void R_BuildCloudData();
void R_IssueRenderCommands(); void R_IssueRenderCommands();
byte* R_FindRenderCommand( renderCommand_t type );
byte* R_AllocateRenderCommand( int bytes, int commandId, qbool endFrame ); byte* R_AllocateRenderCommand( int bytes, int commandId, qbool endFrame );
void R_AddDrawSurfCmd( drawSurf_t* drawSurfs, int numDrawSurfs, int numTranspSurfs ); void R_AddDrawSurfCmd( drawSurf_t* drawSurfs, int numDrawSurfs, int numTranspSurfs );
@ -1666,7 +1671,7 @@ struct IRenderPipeline
virtual void BeginTextureUpload(RHI::MappedTexture& mappedTexture, image_t* image) = 0; virtual void BeginTextureUpload(RHI::MappedTexture& mappedTexture, image_t* image) = 0;
virtual void EndTextureUpload() = 0; virtual void EndTextureUpload() = 0;
virtual void ExecuteRenderCommands(const byte* data) = 0; virtual void ExecuteRenderCommands(const byte* data, bool readbackRequested) = 0;
virtual void UISetColor(const uiSetColorCommand_t& cmd) = 0; virtual void UISetColor(const uiSetColorCommand_t& cmd) = 0;
virtual void UIDrawQuad(const uiDrawQuadCommand_t& cmd) = 0; virtual void UIDrawQuad(const uiDrawQuadCommand_t& cmd) = 0;