added r_shadingRate

This commit is contained in:
myT 2023-08-03 02:38:29 +02:00
parent d841f13fb0
commit fd035c0f70
7 changed files with 155 additions and 4 deletions

View File

@ -360,6 +360,8 @@ struct World
int psoChangeCount; int psoChangeCount;
bool batchDepthHack; bool batchDepthHack;
bool batchOldDepthHack; bool batchOldDepthHack;
ShadingRate::Id batchShadingRate;
ShadingRate::Id batchOldShadingRate;
// dynamic // dynamic
GeometryBuffers dynBuffers[FrameCount]; GeometryBuffers dynBuffers[FrameCount];

View File

@ -399,6 +399,8 @@ void World::Begin()
CmdSetViewportAndScissor(backEnd.viewParms); CmdSetViewportAndScissor(backEnd.viewParms);
batchOldDepthHack = false; batchOldDepthHack = false;
batchDepthHack = false; batchDepthHack = false;
batchOldShadingRate = ShadingRate::SR_1x1;
batchShadingRate = ShadingRate::SR_1x1;
TextureBarrier tb(depthTexture, ResourceStates::DepthWriteBit); TextureBarrier tb(depthTexture, ResourceStates::DepthWriteBit);
CmdBarrier(1, &tb); CmdBarrier(1, &tb);
@ -562,6 +564,12 @@ void World::EndBatch()
batchOldDepthHack = batchDepthHack; batchOldDepthHack = batchDepthHack;
} }
if(batchShadingRate != batchOldShadingRate)
{
CmdSetShadingRate(batchShadingRate);
batchOldShadingRate = batchShadingRate;
}
for(int p = 0; p < shader->numPipelines; ++p) for(int p = 0; p < shader->numPipelines; ++p)
{ {
const pipeline_t& pipeline = shader->pipelines[p]; const pipeline_t& pipeline = shader->pipelines[p];
@ -631,6 +639,8 @@ void World::EndSkyBatch()
SCOPED_RENDER_PASS("Sky", 0.0, 0.5f, 1.0f); SCOPED_RENDER_PASS("Sky", 0.0, 0.5f, 1.0f);
CmdSetShadingRate(ShadingRate::SR_1x1);
const viewParms_t& vp = backEnd.viewParms; const viewParms_t& vp = backEnd.viewParms;
CmdSetViewport(vp.viewportX, vp.viewportY, vp.viewportWidth, vp.viewportHeight, 0.0f, 0.0f); CmdSetViewport(vp.viewportX, vp.viewportY, vp.viewportWidth, vp.viewportHeight, 0.0f, 0.0f);
RB_DrawSky(); RB_DrawSky();
@ -640,6 +650,8 @@ void World::EndSkyBatch()
batchOldDepthHack = false; batchOldDepthHack = false;
batchDepthHack = false; batchDepthHack = false;
batchOldShadingRate = ShadingRate::SR_1x1;
batchShadingRate = ShadingRate::SR_1x1;
} }
void World::RestartBatch() void World::RestartBatch()
@ -920,6 +932,10 @@ void World::DrawSceneView(const drawSceneViewCommand_t& cmd)
bool oldHasStaticGeo = false; bool oldHasStaticGeo = false;
backEnd.currentEntity = &tr.worldEntity; backEnd.currentEntity = &tr.worldEntity;
ShadingRate::Id lowShadingRate = (ShadingRate::Id)r_shadingRate->integer;
batchShadingRate = ShadingRate::SR_1x1;
batchOldShadingRate = ShadingRate::SR_1x1;
int ds; int ds;
const drawSurf_t* drawSurf; const drawSurf_t* drawSurf;
for(ds = 0, drawSurf = drawSurfs; ds < surfCount; ++ds, ++drawSurf) for(ds = 0, drawSurf = drawSurfs; ds < surfCount; ++ds, ++drawSurf)
@ -929,6 +945,8 @@ void World::DrawSceneView(const drawSceneViewCommand_t& cmd)
EndSkyBatch(); EndSkyBatch();
EndBatch(); EndBatch();
CmdSetShadingRate(lowShadingRate);
batchOldShadingRate = lowShadingRate;
DrawFog(); DrawFog();
if(transpCount > 0) if(transpCount > 0)
@ -982,6 +1000,7 @@ void World::DrawSceneView(const drawSceneViewCommand_t& cmd)
EndBatch(); EndBatch();
BeginBatch(shader, hasStaticGeo); BeginBatch(shader, hasStaticGeo);
tess.greyscale = drawSurf->greyscale; tess.greyscale = drawSurf->greyscale;
batchShadingRate = lowShadingRate;
} }
if(entityChanged) if(entityChanged)
@ -996,6 +1015,7 @@ void World::DrawSceneView(const drawSceneViewCommand_t& cmd)
{ {
EndBatch(); EndBatch();
BeginBatch(tess.shader, batchHasStaticGeo); BeginBatch(tess.shader, batchHasStaticGeo);
batchShadingRate = lowShadingRate;
} }
memcpy(tess.indexes + tess.numIndexes, statIndices + chunk.firstCPUIndex, chunk.indexCount * sizeof(uint32_t)); memcpy(tess.indexes + tess.numIndexes, statIndices + chunk.firstCPUIndex, chunk.indexCount * sizeof(uint32_t));
@ -1005,6 +1025,19 @@ void World::DrawSceneView(const drawSceneViewCommand_t& cmd)
{ {
R_TessellateSurface(drawSurf->surface); R_TessellateSurface(drawSurf->surface);
} }
// we want full rate for nopicmipped sprites and nopicmipped alpha tests
if((shader->imgflags & IMG_NOPICMIP) != 0)
{
if(entityNum != ENTITYNUM_WORLD && tr.refdef.entities[entityNum].e.reType == RT_SPRITE)
{
batchShadingRate = ShadingRate::SR_1x1;
}
else if(shader->isAlphaTestedOpaque)
{
batchShadingRate = ShadingRate::SR_1x1;
}
}
} }
backEnd.refdef.floatTime = originalTime; backEnd.refdef.floatTime = originalTime;
@ -1012,6 +1045,8 @@ void World::DrawSceneView(const drawSceneViewCommand_t& cmd)
EndSkyBatch(); EndSkyBatch();
EndBatch(); EndBatch();
CmdSetShadingRate(ShadingRate::SR_1x1);
if(transpCount <= 0) if(transpCount <= 0)
{ {
DrawFog(); DrawFog();
@ -1024,6 +1059,10 @@ void World::DrawSceneView(const drawSceneViewCommand_t& cmd)
CmdSetViewportAndScissor(backEnd.viewParms); CmdSetViewportAndScissor(backEnd.viewParms);
batchOldDepthHack = false; batchOldDepthHack = false;
batchDepthHack = false; batchDepthHack = false;
CmdSetShadingRate(ShadingRate::SR_1x1);
batchOldShadingRate = ShadingRate::SR_1x1;
batchShadingRate = ShadingRate::SR_1x1;
} }
void World::BindVertexBuffers(bool staticGeo, uint32_t firstStage, uint32_t stageCount) void World::BindVertexBuffers(bool staticGeo, uint32_t firstStage, uint32_t stageCount)

View File

@ -533,11 +533,11 @@ namespace RHI
IDXGISwapChain3* swapChain; IDXGISwapChain3* swapChain;
HTexture renderTargets[FrameCount]; HTexture renderTargets[FrameCount];
ID3D12CommandAllocator* mainCommandAllocators[FrameCount]; ID3D12CommandAllocator* mainCommandAllocators[FrameCount];
ID3D12GraphicsCommandList* mainCommandList; ID3D12GraphicsCommandList6* mainCommandList;
ID3D12CommandAllocator* tempCommandAllocator; ID3D12CommandAllocator* tempCommandAllocator;
ID3D12GraphicsCommandList* tempCommandList; ID3D12GraphicsCommandList6* tempCommandList;
bool tempCommandListOpen; bool tempCommandListOpen;
ID3D12GraphicsCommandList* commandList; // not owned, don't release it! ID3D12GraphicsCommandList6* commandList; // not owned, don't release it!
uint32_t swapChainBufferCount; uint32_t swapChainBufferCount;
uint32_t renderFrameCount; uint32_t renderFrameCount;
HANDLE frameLatencyWaitableObject; HANDLE frameLatencyWaitableObject;
@ -555,6 +555,8 @@ namespace RHI
bool isTearingSupported; bool isTearingSupported;
bool vsync; bool vsync;
bool frameBegun; bool frameBegun;
bool baseVRSSupport;
bool extendedVRSSupport;
HMODULE dxcModule; HMODULE dxcModule;
HMODULE dxilModule; HMODULE dxilModule;
@ -1646,6 +1648,21 @@ namespace RHI
} }
} }
D3D12_SHADING_RATE GetD3DShadingRate(ShadingRate::Id shadingRate)
{
switch(shadingRate)
{
case ShadingRate::SR_1x1: return D3D12_SHADING_RATE_1X1;
case ShadingRate::SR_1x2: return D3D12_SHADING_RATE_1X2;
case ShadingRate::SR_2x1: return D3D12_SHADING_RATE_2X1;
case ShadingRate::SR_2x2: return D3D12_SHADING_RATE_2X2;
case ShadingRate::SR_2x4: return D3D12_SHADING_RATE_2X4;
case ShadingRate::SR_4x2: return D3D12_SHADING_RATE_4X2;
case ShadingRate::SR_4x4: return D3D12_SHADING_RATE_4X4;
default: Q_assert(!"Unsupported shading rate"); return D3D12_SHADING_RATE_1X1;
}
}
static D3D12_BLEND GetAlphaBlendFromColorBlend(D3D12_BLEND colorBlend) static D3D12_BLEND GetAlphaBlendFromColorBlend(D3D12_BLEND colorBlend)
{ {
switch(colorBlend) switch(colorBlend)
@ -2178,7 +2195,23 @@ namespace RHI
case D3D12_RAYTRACING_TIER_1_1: tier = "1.1"; case D3D12_RAYTRACING_TIER_1_1: tier = "1.1";
default: break; default: break;
} }
TableRow(2, "Raytracing tier (DXR)", tier); TableRow(2, "Raytracing (DXR) tier", tier);
}
D3D12_FEATURE_DATA_D3D12_OPTIONS6 options6 = { 0 };
if(SUCCEEDED(rhi.device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS6, &options6, sizeof(options6))))
{
const char* tier = "Unknown";
switch(options6.VariableShadingRateTier)
{
case D3D12_VARIABLE_SHADING_RATE_TIER_NOT_SUPPORTED: tier = "N/A";
case D3D12_VARIABLE_SHADING_RATE_TIER_1: tier = "1";
case D3D12_VARIABLE_SHADING_RATE_TIER_2: tier = "2";
default: break;
}
TableRow(2, "Variable shading rate (VRS) tier", tier);
TableRow(2, "VRS: 2x4, 4x2, 4x4 support", options6.AdditionalShadingRatesSupported ? "YES" : "NO");
} }
NvU64 cvvTotal, cvvFree; NvU64 cvvTotal, cvvFree;
@ -2710,6 +2743,19 @@ namespace RHI
D3D(dxcCreateInstance(CLSID_DxcUtils, IID_PPV_ARGS(&rhi.dxcUtils))); D3D(dxcCreateInstance(CLSID_DxcUtils, IID_PPV_ARGS(&rhi.dxcUtils)));
D3D(dxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&rhi.dxcCompiler))); D3D(dxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&rhi.dxcCompiler)));
{
D3D12_FEATURE_DATA_D3D12_OPTIONS6 options6 = {};
if(SUCCEEDED(rhi.device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS6, &options6, sizeof(options6))))
{
rhi.baseVRSSupport = options6.VariableShadingRateTier != D3D12_VARIABLE_SHADING_RATE_TIER_NOT_SUPPORTED;
rhi.extendedVRSSupport = rhi.baseVRSSupport && options6.AdditionalShadingRatesSupported;
}
const char* modeLists[] = { "1x1", "1x1 2x1 1x2 2x2", "1x1 2x1 1x2 2x2 4x2 2x4 4x4" };
const int listIndex = rhi.extendedVRSSupport ? 2 : (rhi.baseVRSSupport ? 1 : 0);
ri.Printf(PRINT_ALL, "Supported VRS modes: %s\n", modeLists[listIndex]);
}
glInfo.maxTextureSize = MAX_TEXTURE_SIZE; glInfo.maxTextureSize = MAX_TEXTURE_SIZE;
glInfo.maxAnisotropy = 16; glInfo.maxAnisotropy = 16;
glInfo.depthFadeSupport = qfalse; glInfo.depthFadeSupport = qfalse;
@ -4273,6 +4319,32 @@ namespace RHI
rhi.commandList->CopyBufferRegion(dst.buffer, 0, src.buffer, 0, byteCount); rhi.commandList->CopyBufferRegion(dst.buffer, 0, src.buffer, 0, byteCount);
} }
void CmdSetShadingRate(ShadingRate::Id shadingRate)
{
Q_assert(CanWriteCommands());
if(!rhi.baseVRSSupport)
{
return;
}
if(!rhi.extendedVRSSupport)
{
switch(shadingRate)
{
case ShadingRate::SR_2x4:
case ShadingRate::SR_4x2:
case ShadingRate::SR_4x4:
shadingRate = ShadingRate::SR_2x2;
break;
default:
break;
}
}
rhi.commandList->RSSetShadingRate(GetD3DShadingRate(shadingRate), NULL);
}
uint32_t GetDurationCount() uint32_t GetDurationCount()
{ {
return rhi.resolvedQueries.durationQueryCount; return rhi.resolvedQueries.durationQueryCount;

View File

@ -234,6 +234,23 @@ namespace RHI
}; };
}; };
struct ShadingRate
{
enum Id
{
// Guaranteed modes:
SR_1x1,
SR_2x1,
SR_1x2,
SR_2x2,
// Additional modes:
SR_4x2,
SR_2x4,
SR_4x4,
Count
};
};
struct RootSignatureDesc struct RootSignatureDesc
{ {
RootSignatureDesc() = default; RootSignatureDesc() = default;
@ -716,6 +733,7 @@ namespace RHI
void CmdEndDebugLabel(); void CmdEndDebugLabel();
void CmdSetStencilReference(uint8_t stencilRef); void CmdSetStencilReference(uint8_t stencilRef);
void CmdCopyBuffer(HBuffer dest, HBuffer source); void CmdCopyBuffer(HBuffer dest, HBuffer source);
void CmdSetShadingRate(ShadingRate::Id shadingRate);
#if 0 #if 0
void CmdClearUAV(HTexture htexture, uint32_t mip); void CmdClearUAV(HTexture htexture, uint32_t mip);

View File

@ -142,6 +142,23 @@ S_COLOR_VAL " 2 " S_COLOR_HELP "= None"
S_COLOR_VAL "2500 " S_COLOR_HELP "should be enough to deal with delayed thread wake-ups.\n" \ S_COLOR_VAL "2500 " S_COLOR_HELP "should be enough to deal with delayed thread wake-ups.\n" \
"Use the frame graph to confirm that higher values help on your system." "Use the frame graph to confirm that higher values help on your system."
#define help_r_shadingRate \
"variable-rate shading (VRS) mode\n" \
S_COLOR_VAL " 0 " S_COLOR_HELP "= 1x1 (VRS off)\n" \
S_COLOR_VAL " 1 " S_COLOR_HELP "= 2x1 (base mode)\n" \
S_COLOR_VAL " 2 " S_COLOR_HELP "= 1x2 (base mode)\n" \
S_COLOR_VAL " 3 " S_COLOR_HELP "= 2x2 (base mode)\n" \
S_COLOR_VAL " 4 " S_COLOR_HELP "= 4x2 (extended mode)\n" \
S_COLOR_VAL " 5 " S_COLOR_HELP "= 2x4 (extended mode)\n" \
S_COLOR_VAL " 6 " S_COLOR_HELP "= 4x4 (extended mode)\n" \
"The numbers are the horizontal and vertical subsampling factors.\n" \
"1x1 is forced for the sky, nopicmipped sprites (e.g. simple items)\n" \
"and nopicmipped alpha tested surfaces (e.g. grates).\n" \
"If extended modes are not supported, 2x2 is used instead.\n" \
"Prefer horizontal subsampling as many maps have textures\n" \
"with thin horizontal lines, which become an aliased mess when\n" \
"vertically subsampled."
#define help_r_ignoreShaderSortKey \ #define help_r_ignoreShaderSortKey \
"ignores the shader sort key of transparent surfaces\n" \ "ignores the shader sort key of transparent surfaces\n" \
"Instead, it sorts by depth and original registration order only.\n" \ "Instead, it sorts by depth and original registration order only.\n" \

View File

@ -60,6 +60,7 @@ cvar_t *r_mapGreyscale;
cvar_t *r_mapGreyscaleCTF; cvar_t *r_mapGreyscaleCTF;
cvar_t *r_teleporterFlash; cvar_t *r_teleporterFlash;
cvar_t *r_sleepThreshold; cvar_t *r_sleepThreshold;
cvar_t *r_shadingRate;
cvar_t *r_novis; cvar_t *r_novis;
cvar_t *r_nocull; cvar_t *r_nocull;
cvar_t *r_nocurves; cvar_t *r_nocurves;
@ -392,6 +393,7 @@ static const cvarTableItem_t r_cvars[] =
{ &r_mapGreyscaleCTF, "r_mapGreyscaleCTF", "0", CVAR_ARCHIVE, CVART_FLOAT, "0", "1", help_r_mapGreyscaleCTF }, { &r_mapGreyscaleCTF, "r_mapGreyscaleCTF", "0", CVAR_ARCHIVE, CVART_FLOAT, "0", "1", help_r_mapGreyscaleCTF },
{ &r_teleporterFlash, "r_teleporterFlash", "1", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "draws bright colors when being teleported" }, { &r_teleporterFlash, "r_teleporterFlash", "1", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "draws bright colors when being teleported" },
{ &r_sleepThreshold, "r_sleepThreshold", "2500", CVAR_ARCHIVE, CVART_INTEGER, "2000", "4000", help_r_sleepThreshold }, { &r_sleepThreshold, "r_sleepThreshold", "2500", CVAR_ARCHIVE, CVART_INTEGER, "2000", "4000", help_r_sleepThreshold },
{ &r_shadingRate, "r_shadingRate", "0", CVAR_ARCHIVE, CVART_INTEGER, "0", "6", help_r_shadingRate },
// //
// temporary variables that can change at any time // temporary variables that can change at any time

View File

@ -1061,6 +1061,7 @@ extern cvar_t *r_mapGreyscale; // how monochrome the map looks
extern cvar_t *r_mapGreyscaleCTF; // how monochrome CTF map surfaces look extern cvar_t *r_mapGreyscaleCTF; // how monochrome CTF map surfaces look
extern cvar_t *r_teleporterFlash; // 1 is default Q3 behavior, 0 is pure black extern cvar_t *r_teleporterFlash; // 1 is default Q3 behavior, 0 is pure black
extern cvar_t *r_sleepThreshold; // time cushion in us for a call to Sleep(1+) extern cvar_t *r_sleepThreshold; // time cushion in us for a call to Sleep(1+)
extern cvar_t *r_shadingRate; // variable-rate shading (VRS) mode
extern cvar_t *r_fullbright; // avoid lightmap pass extern cvar_t *r_fullbright; // avoid lightmap pass
extern cvar_t *r_depthFade; // fades marked shaders based on depth extern cvar_t *r_depthFade; // fades marked shaders based on depth
extern cvar_t *r_dither; // enables dithering extern cvar_t *r_dither; // enables dithering