Make overlays interact consistently with viewport/scissor

* We also add a red/green display to the viewport and scissor overlay to show
  pixels that fail the scissor test.
This commit is contained in:
baldurk
2020-07-17 16:53:34 +01:00
parent e176fcb9d7
commit 485f7d21fc
10 changed files with 798 additions and 197 deletions
+80 -42
View File
@@ -357,6 +357,7 @@ ResourceId D3D11Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De
{
origdesc.CullMode = D3D11_CULL_BACK;
origdesc.FrontCounterClockwise = FALSE;
origdesc.ScissorEnable = FALSE;
}
SAFE_RELEASE(rs);
@@ -372,7 +373,7 @@ ResourceId D3D11Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De
rdesc.DepthBiasClamp = D3D11_DEFAULT_DEPTH_BIAS_CLAMP;
rdesc.SlopeScaledDepthBias = D3D11_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
rdesc.DepthClipEnable = FALSE;
rdesc.ScissorEnable = FALSE;
rdesc.ScissorEnable = origdesc.ScissorEnable;
rdesc.MultisampleEnable = FALSE;
rdesc.AntialiasedLineEnable = FALSE;
@@ -422,27 +423,22 @@ ResourceId D3D11Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De
}
else if(overlay == DebugOverlay::ViewportScissor)
{
m_pImmediateContext->VSSetShader(m_Overlay.FullscreenVS, NULL, 0);
m_pImmediateContext->HSSetShader(NULL, NULL, 0);
m_pImmediateContext->DSSetShader(NULL, NULL, 0);
m_pImmediateContext->GSSetShader(NULL, NULL, 0);
m_pImmediateContext->PSSetShader(m_General.CheckerboardPS, NULL, 0);
m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
m_pImmediateContext->IASetInputLayout(NULL);
m_pImmediateContext->OMSetBlendState(NULL, NULL, 0xffffffff);
m_pImmediateContext->PSSetShader(m_General.FixedColPS, NULL, 0);
D3D11_RASTERIZER_DESC origdesc;
D3D11_RASTERIZER_DESC origdesc = {};
{
ID3D11RasterizerState *rs = NULL;
ID3D11RasterizerState *origRS = NULL;
m_pImmediateContext->RSGetState(&rs);
m_pImmediateContext->RSGetState(&origRS);
if(rs)
rs->GetDesc(&origdesc);
if(origRS)
origRS->GetDesc(&origdesc);
else
origdesc.ScissorEnable = FALSE;
SAFE_RELEASE(rs);
SAFE_RELEASE(origRS);
}
dsDesc.DepthEnable = FALSE;
@@ -456,8 +452,71 @@ ResourceId D3D11Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De
return m_Overlay.resourceId;
}
ID3D11RasterizerState *rs = NULL;
ID3D11RasterizerState *rsScissorOn = NULL;
{
D3D11_RASTERIZER_DESC rdesc;
rdesc.FillMode = D3D11_FILL_SOLID;
rdesc.CullMode = D3D11_CULL_NONE;
rdesc.FrontCounterClockwise = FALSE;
rdesc.DepthBias = D3D11_DEFAULT_DEPTH_BIAS;
rdesc.DepthBiasClamp = D3D11_DEFAULT_DEPTH_BIAS_CLAMP;
rdesc.SlopeScaledDepthBias = D3D11_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
rdesc.DepthClipEnable = FALSE;
rdesc.ScissorEnable = FALSE;
rdesc.MultisampleEnable = FALSE;
rdesc.AntialiasedLineEnable = FALSE;
hr = m_pDevice->CreateRasterizerState(&rdesc, &rs);
if(FAILED(hr))
{
RDCERR("Failed to create drawcall rast state HRESULT: %s", ToStr(hr).c_str());
return m_Overlay.resourceId;
}
rdesc.ScissorEnable = TRUE;
hr = m_pDevice->CreateRasterizerState(&rdesc, &rsScissorOn);
if(FAILED(hr))
{
RDCERR("Failed to create drawcall rast state HRESULT: %s", ToStr(hr).c_str());
return m_Overlay.resourceId;
}
}
float clearColour[] = {0.0f, 0.0f, 0.0f, 0.0f};
m_pImmediateContext->ClearRenderTargetView(rtv, clearColour);
m_pImmediateContext->RSSetState(rs);
m_pImmediateContext->OMSetDepthStencilState(os, 0);
float overlayConsts[] = {1.0f, 0.0f, 0.0f, 1.0f};
ID3D11Buffer *buf = GetDebugManager()->MakeCBuffer(overlayConsts, sizeof(overlayConsts));
m_pImmediateContext->PSSetConstantBuffers(0, 1, &buf);
m_pDevice->ReplayLog(0, eventId, eReplay_OnlyDraw);
overlayConsts[0] = 0.0f;
overlayConsts[1] = 1.0f;
buf = GetDebugManager()->MakeCBuffer(overlayConsts, sizeof(overlayConsts));
m_pImmediateContext->PSSetConstantBuffers(0, 1, &buf);
m_pImmediateContext->RSSetState(rsScissorOn);
m_pDevice->ReplayLog(0, eventId, eReplay_OnlyDraw);
m_pImmediateContext->VSSetShader(m_Overlay.FullscreenVS, NULL, 0);
m_pImmediateContext->HSSetShader(NULL, NULL, 0);
m_pImmediateContext->DSSetShader(NULL, NULL, 0);
m_pImmediateContext->GSSetShader(NULL, NULL, 0);
m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
m_pImmediateContext->IASetInputLayout(NULL);
m_pImmediateContext->PSSetShader(m_General.CheckerboardPS, NULL, 0);
D3D11_BLEND_DESC blendDesc;
RDCEraseEl(blendDesc);
@@ -478,32 +537,6 @@ ResourceId D3D11Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De
float blendwhite[] = {1.0f, 1.0f, 1.0f, 1.0f};
m_pImmediateContext->OMSetBlendState(bs, blendwhite, 0xffffffff);
ID3D11RasterizerState *rs = NULL;
{
D3D11_RASTERIZER_DESC rdesc;
rdesc.FillMode = D3D11_FILL_SOLID;
rdesc.CullMode = D3D11_CULL_NONE;
rdesc.FrontCounterClockwise = FALSE;
rdesc.DepthBias = D3D11_DEFAULT_DEPTH_BIAS;
rdesc.DepthBiasClamp = D3D11_DEFAULT_DEPTH_BIAS_CLAMP;
rdesc.SlopeScaledDepthBias = D3D11_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
rdesc.DepthClipEnable = FALSE;
rdesc.ScissorEnable = FALSE;
rdesc.MultisampleEnable = FALSE;
rdesc.AntialiasedLineEnable = FALSE;
hr = m_pDevice->CreateRasterizerState(&rdesc, &rs);
if(FAILED(hr))
{
RDCERR("Failed to create drawcall rast state HRESULT: %s", ToStr(hr).c_str());
return m_Overlay.resourceId;
}
}
float clearColour[] = {0.0f, 0.0f, 0.0f, 0.0f};
m_pImmediateContext->ClearRenderTargetView(rtv, clearColour);
m_pImmediateContext->RSSetState(rs);
CheckerboardCBuffer pixelData = {0};
@@ -517,13 +550,13 @@ ResourceId D3D11Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De
// set primary/secondary to the same to 'disable' checkerboard
pixelData.PrimaryColor = pixelData.SecondaryColor = Vec4f(0.1f, 0.1f, 0.1f, 1.0f);
pixelData.InnerColor = Vec4f(0.2f, 0.2f, 0.9f, 0.7f);
pixelData.InnerColor = Vec4f(0.2f, 0.2f, 0.9f, 0.4f);
// set viewport rect
pixelData.RectPosition = Vec2f(views[0].TopLeftX, views[0].TopLeftY);
pixelData.RectSize = Vec2f(views[0].Width, views[0].Height);
ID3D11Buffer *buf = GetDebugManager()->MakeCBuffer(&pixelData, sizeof(pixelData));
buf = GetDebugManager()->MakeCBuffer(&pixelData, sizeof(pixelData));
m_pImmediateContext->PSSetConstantBuffers(0, 1, &buf);
@@ -565,6 +598,7 @@ ResourceId D3D11Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De
SAFE_RELEASE(os);
SAFE_RELEASE(rs);
SAFE_RELEASE(rsScissorOn);
SAFE_RELEASE(bs);
}
else if(overlay == DebugOverlay::Wireframe)
@@ -1116,6 +1150,10 @@ ResourceId D3D11Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De
m_pImmediateContext->OMSetBlendState(NULL, NULL, 0xffffffff);
m_pImmediateContext->RSSetState(m_General.RasterState);
D3D11_VIEWPORT view = {0.0f, 0.0f, (float)realTexDesc.Width, (float)realTexDesc.Height,
0.0f, 1.0f};
m_pImmediateContext->RSSetViewports(1, &view);
float clearColour[] = {0.0f, 0.0f, 0.0f, 0.0f};
m_pImmediateContext->ClearRenderTargetView(rtv, clearColour);
+154 -41
View File
@@ -442,7 +442,7 @@ ResourceId D3D12Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De
D3D12_RENDER_TARGET_VIEW_DESC rtDesc = {};
rtDesc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT;
ID3D12GraphicsCommandList *list = m_pDevice->GetNewList();
ID3D12GraphicsCommandListX *list = m_pDevice->GetNewList();
// clear all mips and all slices first
for(UINT mip = 0; mip < overlayTexDesc.MipLevels; mip++)
@@ -563,6 +563,9 @@ ResourceId D3D12Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De
rs.rts[0] = *GetWrapped(rtv);
RDCEraseEl(rs.dsv);
for(D3D12_RECT &r : rs.scissors)
r = {0, 0, 32768, 32768};
m_pDevice->ReplayLog(0, eventId, eReplay_OnlyDraw);
rs = prev;
@@ -844,12 +847,102 @@ ResourceId D3D12Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De
{
if(pipe && pipe->IsGraphics() && !rs.views.empty())
{
D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC psoDesc;
pipe->Fill(psoDesc);
bool dxil =
DXBC::DXBCContainer::CheckForDXIL(psoDesc.VS.pShaderBytecode, psoDesc.VS.BytecodeLength);
ID3DBlob *red = m_pDevice->GetShaderCache()->MakeFixedColShader(D3D12ShaderCache::RED, dxil);
ID3DBlob *green =
m_pDevice->GetShaderCache()->MakeFixedColShader(D3D12ShaderCache::GREEN, dxil);
psoDesc.DepthStencilState.DepthEnable = FALSE;
psoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO;
psoDesc.DepthStencilState.StencilEnable = FALSE;
psoDesc.BlendState.AlphaToCoverageEnable = FALSE;
psoDesc.BlendState.IndependentBlendEnable = FALSE;
psoDesc.BlendState.RenderTarget[0].BlendEnable = FALSE;
psoDesc.BlendState.RenderTarget[0].RenderTargetWriteMask = 0xf;
psoDesc.BlendState.RenderTarget[0].LogicOpEnable = FALSE;
RDCEraseEl(psoDesc.RTVFormats.RTFormats);
psoDesc.RTVFormats.RTFormats[0] = DXGI_FORMAT_R16G16B16A16_FLOAT;
psoDesc.RTVFormats.NumRenderTargets = 1;
psoDesc.SampleMask = ~0U;
psoDesc.SampleDesc.Count = RDCMAX(1U, psoDesc.SampleDesc.Count);
psoDesc.DSVFormat = DXGI_FORMAT_UNKNOWN;
psoDesc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
psoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
psoDesc.RasterizerState.FrontCounterClockwise = FALSE;
psoDesc.RasterizerState.DepthBias = D3D12_DEFAULT_DEPTH_BIAS;
psoDesc.RasterizerState.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;
psoDesc.RasterizerState.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
psoDesc.RasterizerState.DepthClipEnable = FALSE;
psoDesc.RasterizerState.MultisampleEnable = FALSE;
psoDesc.RasterizerState.AntialiasedLineEnable = FALSE;
psoDesc.PS.pShaderBytecode = red->GetBufferPointer();
psoDesc.PS.BytecodeLength = red->GetBufferSize();
ID3D12PipelineState *redPSO = NULL;
HRESULT hr = m_pDevice->CreatePipeState(psoDesc, &redPSO);
if(FAILED(hr))
{
RDCERR("Failed to create overlay pso HRESULT: %s", ToStr(hr).c_str());
SAFE_RELEASE(red);
SAFE_RELEASE(redPSO);
SAFE_RELEASE(green);
return m_Overlay.resourceId;
}
psoDesc.PS.pShaderBytecode = green->GetBufferPointer();
psoDesc.PS.BytecodeLength = green->GetBufferSize();
ID3D12PipelineState *greenPSO = NULL;
hr = m_pDevice->CreatePipeState(psoDesc, &greenPSO);
if(FAILED(hr))
{
RDCERR("Failed to create overlay pso HRESULT: %s", ToStr(hr).c_str());
SAFE_RELEASE(red);
SAFE_RELEASE(redPSO);
SAFE_RELEASE(green);
SAFE_RELEASE(greenPSO);
return m_Overlay.resourceId;
}
list->Close();
list = NULL;
D3D12_RECT scissor = {0, 0, 16384, 16384};
D3D12RenderState prev = rs;
rs.rts = {*GetWrapped(rtv)};
for(D3D12_RECT &s : rs.scissors)
s = scissor;
rs.pipe = GetResID(redPSO);
m_pDevice->ReplayLog(0, eventId, eReplay_OnlyDraw);
rs.scissors = prev.scissors;
rs.pipe = GetResID(greenPSO);
m_pDevice->ReplayLog(0, eventId, eReplay_OnlyDraw);
rs = prev;
list = m_pDevice->GetNewList();
rs.ApplyState(m_pDevice, list);
list->OMSetRenderTargets(1, &rtv, TRUE, NULL);
D3D12_VIEWPORT viewport = rs.views[0];
list->RSSetViewports(1, &viewport);
D3D12_RECT scissor = {0, 0, 16384, 16384};
list->RSSetScissorRects(1, &scissor);
list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
@@ -866,7 +959,7 @@ ResourceId D3D12Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De
// set primary/secondary to the same to 'disable' checkerboard
pixelData.PrimaryColor = pixelData.SecondaryColor = Vec4f(0.1f, 0.1f, 0.1f, 1.0f);
pixelData.InnerColor = Vec4f(0.2f, 0.2f, 0.9f, 0.7f);
pixelData.InnerColor = Vec4f(0.2f, 0.2f, 0.9f, 0.4f);
// set viewport rect
pixelData.RectPosition = Vec2f(viewport.TopLeftX, viewport.TopLeftY);
@@ -905,6 +998,17 @@ ResourceId D3D12Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De
list->SetGraphicsRootConstantBufferView(0, scissorCB);
list->DrawInstanced(3, 1, 0, 0);
list->Close();
list = NULL;
m_pDevice->ExecuteLists();
m_pDevice->FlushLists();
SAFE_RELEASE(red);
SAFE_RELEASE(redPSO);
SAFE_RELEASE(green);
SAFE_RELEASE(greenPSO);
}
}
else if(overlay == DebugOverlay::TriangleSizeDraw || overlay == DebugOverlay::TriangleSizePass)
@@ -937,8 +1041,6 @@ ResourceId D3D12Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De
list = NULL;
m_pDevice->ReplayLog(0, events[0], eReplay_WithoutDraw);
list = m_pDevice->GetNewList();
}
pipe = m_pDevice->GetResourceManager()->GetCurrentAs<WrappedID3D12PipelineState>(rs.pipe);
@@ -996,40 +1098,40 @@ ResourceId D3D12Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De
vertexData.ModelViewProj = Matrix4f::Identity();
vertexData.SpriteSize = Vec2f();
Vec4f viewport;
if(!rs.views.empty())
viewport = Vec4f(rs.views[0].Width, rs.views[0].Height);
if(rs.dsv.GetResResourceId() != ResourceId())
{
D3D12_CPU_DESCRIPTOR_HANDLE tmpdsv = GetDebugManager()->GetTempDescriptor(rs.dsv);
list->OMSetRenderTargets(1, &rtv, TRUE, &tmpdsv);
}
else
{
list->OMSetRenderTargets(1, &rtv, TRUE, NULL);
}
if(!rs.views.empty())
list->RSSetViewports(1, &rs.views[0]);
D3D12_RECT scissor = {0, 0, 16384, 16384};
list->RSSetScissorRects(1, &scissor);
list->OMSetStencilRef(rs.stencilRef);
list->OMSetBlendFactor(rs.blendFactor);
list->SetGraphicsRootSignature(GetDebugManager()->GetMeshRootSig());
list->SetGraphicsRootConstantBufferView(
0, GetDebugManager()->UploadConstants(&vertexData, sizeof(vertexData)));
list->SetGraphicsRootConstantBufferView(
1, GetDebugManager()->UploadConstants(&viewport, sizeof(viewport)));
list->SetGraphicsRoot32BitConstants(2, 4, &viewport.x, 0);
D3D12RenderState::SignatureElement vertexElem(eRootCBV, ResourceId(), 0);
WrappedID3D12Resource1::GetResIDFromAddr(
GetDebugManager()->UploadConstants(&vertexData, sizeof(vertexData)), vertexElem.id,
vertexElem.offset);
for(size_t i = 0; i < events.size(); i++)
{
D3D12RenderState prevState = rs;
Vec4f viewport;
if(!rs.views.empty())
viewport = Vec4f(rs.views[0].Width, rs.views[0].Height);
D3D12RenderState::SignatureElement viewportElem(eRootCBV, ResourceId(), 0);
WrappedID3D12Resource1::GetResIDFromAddr(
GetDebugManager()->UploadConstants(&viewport, sizeof(viewport)), viewportElem.id,
viewportElem.offset);
D3D12RenderState::SignatureElement viewportConstElem(eRootConst, ResourceId(), 0);
viewportConstElem.SetConstants(4, &viewport, 0);
rs.graphics.rootsig = GetResID(GetDebugManager()->GetMeshRootSig());
rs.graphics.sigelems = {
vertexElem, viewportElem, viewportConstElem,
};
rs.rts = {*(D3D12Descriptor *)rtv.ptr};
if(list == NULL)
list = m_pDevice->GetNewList();
rs.ApplyState(m_pDevice, list);
const DrawcallDescription *draw = m_pDevice->GetDrawcall(events[i]);
for(uint32_t inst = 0; draw && inst < RDCMAX(1U, draw->numInstances); inst++)
@@ -1097,10 +1199,20 @@ ResourceId D3D12Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De
}
}
}
}
list->Close();
list = NULL;
list->Close();
list = NULL;
rs = prevState;
if(overlay == DebugOverlay::TriangleSizePass)
{
m_pDevice->ReplayLog(events[i], events[i], eReplay_OnlyDraw);
if(i + 1 < events.size())
m_pDevice->ReplayLog(events[i], events[i + 1], eReplay_WithoutDraw);
}
}
m_pDevice->ExecuteLists();
m_pDevice->FlushLists();
@@ -1220,8 +1332,9 @@ ResourceId D3D12Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De
list->OMSetRenderTargets(1, &rtv, TRUE, NULL);
if(!rs.views.empty())
list->RSSetViewports(1, &rs.views[0]);
D3D12_VIEWPORT view = {0.0f, 0.0f, (float)resourceDesc.Width, (float)resourceDesc.Height,
0.0f, 1.0f};
list->RSSetViewports(1, &view);
D3D12_RECT scissor = {0, 0, 16384, 16384};
list->RSSetScissorRects(1, &scissor);
+175 -3
View File
@@ -548,7 +548,6 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, Debug
// clear all mips first
drv.glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
drv.glDisable(eGL_BLEND);
drv.glDisable(eGL_SCISSOR_TEST);
drv.glDepthMask(GL_FALSE);
drv.glDisable(eGL_CULL_FACE);
drv.glDisable(eGL_DEPTH_TEST);
@@ -563,6 +562,8 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, Debug
drv.glBindFramebuffer(eGL_FRAMEBUFFER, DebugData.overlayFBO);
drv.glDisable(eGL_SCISSOR_TEST);
// clear the overlay texture to black
{
GLfloat black[4] = {};
@@ -597,7 +598,6 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, Debug
// the program's state.
drv.glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
drv.glDisable(eGL_BLEND);
drv.glDisable(eGL_SCISSOR_TEST);
drv.glDepthMask(GL_FALSE);
drv.glDisable(eGL_CULL_FACE);
drv.glDisable(eGL_DEPTH_TEST);
@@ -609,6 +609,24 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, Debug
drv.glEnable(eGL_DEPTH_CLAMP);
}
if(HasExt[ARB_viewport_array])
{
for(size_t s = 0; s < ARRAY_COUNT(rs.Scissors); s++)
{
if(rs.Scissors[s].enabled)
drv.glEnablei(eGL_SCISSOR_TEST, (GLuint)s);
else
drv.glDisablei(eGL_SCISSOR_TEST, (GLuint)s);
}
}
else
{
if(rs.Scissors[0].enabled)
drv.glEnable(eGL_SCISSOR_TEST);
else
drv.glDisable(eGL_SCISSOR_TEST);
}
if(overlay == DebugOverlay::NaN || overlay == DebugOverlay::Clipping)
{
// just need the basic texture
@@ -617,6 +635,11 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, Debug
}
else if(overlay == DebugOverlay::Drawcall)
{
if(HasExt[ARB_viewport_array])
drv.glDisablei(eGL_SCISSOR_TEST, 0);
else
drv.glDisable(eGL_SCISSOR_TEST);
float black[] = {0.0f, 0.0f, 0.0f, 0.5f};
drv.glClearBufferfv(eGL_COLOR, 0, black);
@@ -727,6 +750,41 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, Debug
float col[] = {0.0f, 0.0f, 0.0f, 0.0f};
drv.glClearBufferfv(eGL_COLOR, 0, col);
if(HasExt[ARB_viewport_array])
drv.glDisablei(eGL_SCISSOR_TEST, 0);
else
drv.glDisable(eGL_SCISSOR_TEST);
col[0] = 1.0f;
col[1] = 0.0f;
col[3] = 1.0f;
drv.glProgramUniform4fv(DebugData.overlayProg, overlayFixedColLocation, 1, col);
ReplayLog(eventId, eReplay_OnlyDraw);
if(HasExt[ARB_viewport_array])
{
if(rs.Scissors[0].enabled)
drv.glEnablei(eGL_SCISSOR_TEST, 0);
else
drv.glDisablei(eGL_SCISSOR_TEST, 0);
}
else
{
if(rs.Scissors[0].enabled)
drv.glEnable(eGL_SCISSOR_TEST);
else
drv.glDisable(eGL_SCISSOR_TEST);
}
col[0] = 0.0f;
col[1] = 1.0f;
drv.glProgramUniform4fv(DebugData.overlayProg, overlayFixedColLocation, 1, col);
ReplayLog(eventId, eReplay_OnlyDraw);
// don't need to use the existing program at all!
drv.glUseProgram(DebugData.checkerProg);
drv.glBindProgramPipeline(0);
@@ -775,7 +833,7 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, Debug
// set primary/secondary to the same to 'disable' checkerboard
cdata->PrimaryColor = cdata->SecondaryColor = Vec4f(0.1f, 0.1f, 0.1f, 1.0f);
cdata->InnerColor = Vec4f(0.2f, 0.2f, 0.9f, 0.7f);
cdata->InnerColor = Vec4f(0.2f, 0.2f, 0.9f, 0.4f);
// set viewport rect
cdata->RectPosition = Vec2f(rs.Viewports[0].x, rs.Viewports[0].y);
@@ -820,9 +878,29 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, Debug
}
else if(overlay == DebugOverlay::Depth || overlay == DebugOverlay::Stencil)
{
if(HasExt[ARB_viewport_array])
drv.glDisablei(eGL_SCISSOR_TEST, 0);
else
drv.glDisable(eGL_SCISSOR_TEST);
float backCol[] = {0.0f, 1.0f, 0.0f, 0.0f};
drv.glClearBufferfv(eGL_COLOR, 0, backCol);
if(HasExt[ARB_viewport_array])
{
if(rs.Scissors[0].enabled)
drv.glEnablei(eGL_SCISSOR_TEST, 0);
else
drv.glDisablei(eGL_SCISSOR_TEST, 0);
}
else
{
if(rs.Scissors[0].enabled)
drv.glEnable(eGL_SCISSOR_TEST);
else
drv.glDisable(eGL_SCISSOR_TEST);
}
float red[] = {1.0f, 0.0f, 0.0f, 1.0f};
drv.glProgramUniform4fv(DebugData.overlayProg, overlayFixedColLocation, 1, red);
@@ -1091,9 +1169,29 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, Debug
}
else if(overlay == DebugOverlay::BackfaceCull)
{
if(HasExt[ARB_viewport_array])
drv.glDisablei(eGL_SCISSOR_TEST, 0);
else
drv.glDisable(eGL_SCISSOR_TEST);
float col[] = {0.0f, 1.0f, 0.0f, 0.0f};
drv.glClearBufferfv(eGL_COLOR, 0, col);
if(HasExt[ARB_viewport_array])
{
if(rs.Scissors[0].enabled)
drv.glEnablei(eGL_SCISSOR_TEST, 0);
else
drv.glDisablei(eGL_SCISSOR_TEST, 0);
}
else
{
if(rs.Scissors[0].enabled)
drv.glEnable(eGL_SCISSOR_TEST);
else
drv.glDisable(eGL_SCISSOR_TEST);
}
col[0] = 1.0f;
col[1] = 0.0f;
col[3] = 1.0f;
@@ -1116,9 +1214,32 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, Debug
}
else if(overlay == DebugOverlay::ClearBeforeDraw || overlay == DebugOverlay::ClearBeforePass)
{
if(HasExt[ARB_viewport_array])
drv.glDisablei(eGL_SCISSOR_TEST, 0);
else
drv.glDisable(eGL_SCISSOR_TEST);
float col[] = {0.0f, 0.0f, 0.0f, 0.0f};
drv.glClearBufferfv(eGL_COLOR, 0, col);
if(HasExt[ARB_viewport_array])
{
for(size_t s = 0; s < ARRAY_COUNT(rs.Scissors); s++)
{
if(rs.Scissors[s].enabled)
drv.glEnablei(eGL_SCISSOR_TEST, (GLuint)s);
else
drv.glDisablei(eGL_SCISSOR_TEST, (GLuint)s);
}
}
else
{
if(rs.Scissors[0].enabled)
drv.glEnable(eGL_SCISSOR_TEST);
else
drv.glDisable(eGL_SCISSOR_TEST);
}
rdcarray<uint32_t> events = passEvents;
if(overlay == DebugOverlay::ClearBeforeDraw)
@@ -1138,9 +1259,32 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, Debug
rs.ApplyState(&drv);
}
GLboolean scissor = HasExt[ARB_viewport_array] ? GL.glIsEnabledi(eGL_SCISSOR_TEST, 0)
: GL.glIsEnabled(eGL_SCISSOR_TEST);
if(HasExt[ARB_viewport_array])
drv.glDisablei(eGL_SCISSOR_TEST, 0);
else
drv.glDisable(eGL_SCISSOR_TEST);
for(int i = 0; i < 8; i++)
drv.glClearBufferfv(eGL_COLOR, i, &clearCol.x);
if(HasExt[ARB_viewport_array])
{
if(scissor == GL_TRUE)
drv.glEnablei(eGL_SCISSOR_TEST, 0);
else
drv.glDisablei(eGL_SCISSOR_TEST, 0);
}
else
{
if(scissor == GL_TRUE)
drv.glEnable(eGL_SCISSOR_TEST);
else
drv.glDisable(eGL_SCISSOR_TEST);
}
// Try to clear depth as well, to help debug shadow rendering
if(IsDepthStencilFormat(texDetails.internalFormat))
{
@@ -1172,9 +1316,32 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, Debug
{
SCOPED_TIMER("Triangle Size");
if(HasExt[ARB_viewport_array])
drv.glDisablei(eGL_SCISSOR_TEST, 0);
else
drv.glDisable(eGL_SCISSOR_TEST);
float black[] = {0.0f, 0.0f, 0.0f, 0.0f};
drv.glClearBufferfv(eGL_COLOR, 0, black);
if(HasExt[ARB_viewport_array])
{
for(size_t s = 0; s < ARRAY_COUNT(rs.Scissors); s++)
{
if(rs.Scissors[s].enabled)
drv.glEnablei(eGL_SCISSOR_TEST, (GLuint)s);
else
drv.glDisablei(eGL_SCISSOR_TEST, (GLuint)s);
}
}
else
{
if(rs.Scissors[0].enabled)
drv.glEnable(eGL_SCISSOR_TEST);
else
drv.glDisable(eGL_SCISSOR_TEST);
}
MeshUBOData uboParams = {};
uboParams.homogenousInput = 1;
uboParams.invProj = Matrix4f::Identity();
@@ -1568,6 +1735,11 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, Debug
{
SCOPED_TIMER("Quad Overdraw");
if(HasExt[ARB_viewport_array])
drv.glDisablei(eGL_SCISSOR_TEST, 0);
else
drv.glDisable(eGL_SCISSOR_TEST);
float black[] = {0.0f, 0.0f, 0.0f, 0.0f};
drv.glClearBufferfv(eGL_COLOR, 0, black);
+200 -99
View File
@@ -935,14 +935,17 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
att->colorWriteMask = 0xf;
}
// set scissors to max
for(size_t i = 0; i < pipeCreateInfo.pViewportState->scissorCount; i++)
// set scissors to max for drawcall
if(overlay == DebugOverlay::Drawcall)
{
VkRect2D &sc = (VkRect2D &)pipeCreateInfo.pViewportState->pScissors[i];
sc.offset.x = 0;
sc.offset.y = 0;
sc.extent.width = 16384;
sc.extent.height = 16384;
for(size_t i = 0; i < pipeCreateInfo.pViewportState->scissorCount; i++)
{
VkRect2D &sc = (VkRect2D &)pipeCreateInfo.pViewportState->pScissors[i];
sc.offset.x = 0;
sc.offset.y = 0;
sc.extent.width = 16384;
sc.extent.height = 16384;
}
}
// set our renderpass and shader
@@ -992,12 +995,15 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
m_pDriver->m_RenderState.graphics.pipeline = GetResID(pipe);
// set dynamic scissors in case pipeline was using them
for(size_t i = 0; i < m_pDriver->m_RenderState.scissors.size(); i++)
if(overlay == DebugOverlay::Drawcall)
{
m_pDriver->m_RenderState.scissors[i].offset.x = 0;
m_pDriver->m_RenderState.scissors[i].offset.x = 0;
m_pDriver->m_RenderState.scissors[i].extent.width = 16384;
m_pDriver->m_RenderState.scissors[i].extent.height = 16384;
for(size_t i = 0; i < m_pDriver->m_RenderState.scissors.size(); i++)
{
m_pDriver->m_RenderState.scissors[i].offset.x = 0;
m_pDriver->m_RenderState.scissors[i].offset.y = 0;
m_pDriver->m_RenderState.scissors[i].extent.width = 16384;
m_pDriver->m_RenderState.scissors[i].extent.height = 16384;
}
}
if(overlay == DebugOverlay::Wireframe)
@@ -1051,7 +1057,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
{
// clear the whole image to opaque black. We'll overwite the render area with transparent black
// before rendering the viewport/scissors
float black[] = {0.0f, 0.0f, 0.0f, 1.0f};
float black[] = {0.0f, 0.0f, 0.0f, 0.0f};
VkImageMemoryBarrier barrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
NULL,
@@ -1077,6 +1083,138 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
black[3] = 0.0f;
vkr = vt->EndCommandBuffer(Unwrap(cmd));
RDCASSERTEQUAL(vkr, VK_SUCCESS);
float highlightCol[] = {1.0f, 0.0f, 0.0f, 1.0f};
// backup state
VulkanRenderState prevstate = m_pDriver->m_RenderState;
// make patched shader
VkShaderModule mod[2] = {0};
VkPipeline pipe[2] = {0};
// first shader, no culling, writes red
GetDebugManager()->PatchFixedColShader(mod[0], highlightCol);
highlightCol[0] = 0.0f;
highlightCol[1] = 1.0f;
// second shader, normal culling, writes green
GetDebugManager()->PatchFixedColShader(mod[1], highlightCol);
// make patched pipeline
VkGraphicsPipelineCreateInfo pipeCreateInfo;
m_pDriver->GetShaderCache()->MakeGraphicsPipelineInfo(pipeCreateInfo,
prevstate.graphics.pipeline);
// disable all tests possible
VkPipelineDepthStencilStateCreateInfo *ds =
(VkPipelineDepthStencilStateCreateInfo *)pipeCreateInfo.pDepthStencilState;
ds->depthTestEnable = false;
ds->depthWriteEnable = false;
ds->stencilTestEnable = false;
ds->depthBoundsTestEnable = false;
VkPipelineRasterizationStateCreateInfo *rs =
(VkPipelineRasterizationStateCreateInfo *)pipeCreateInfo.pRasterizationState;
rs->cullMode = VK_CULL_MODE_NONE; // first render without any culling
rs->rasterizerDiscardEnable = false;
if(m_pDriver->GetDeviceEnabledFeatures().depthClamp)
rs->depthClampEnable = true;
VkPipelineColorBlendStateCreateInfo *cb =
(VkPipelineColorBlendStateCreateInfo *)pipeCreateInfo.pColorBlendState;
cb->logicOpEnable = false;
cb->attachmentCount = 1; // only one colour attachment
for(uint32_t i = 0; i < cb->attachmentCount; i++)
{
VkPipelineColorBlendAttachmentState *att =
(VkPipelineColorBlendAttachmentState *)&cb->pAttachments[i];
att->blendEnable = false;
att->colorWriteMask = 0xf;
}
// set our renderpass and shader
pipeCreateInfo.renderPass = m_Overlay.NoDepthRP;
pipeCreateInfo.subpass = 0;
VkPipelineShaderStageCreateInfo *fragShader = NULL;
for(uint32_t i = 0; i < pipeCreateInfo.stageCount; i++)
{
VkPipelineShaderStageCreateInfo &sh =
(VkPipelineShaderStageCreateInfo &)pipeCreateInfo.pStages[i];
if(sh.stage == VK_SHADER_STAGE_FRAGMENT_BIT)
{
sh.module = mod[0];
sh.pName = "main";
fragShader = &sh;
break;
}
}
if(fragShader == NULL)
{
// we know this is safe because it's pointing to a static array that's
// big enough for all shaders
VkPipelineShaderStageCreateInfo &sh =
(VkPipelineShaderStageCreateInfo &)pipeCreateInfo.pStages[pipeCreateInfo.stageCount++];
sh.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
sh.pNext = NULL;
sh.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
sh.module = mod[0];
sh.pName = "main";
sh.pSpecializationInfo = NULL;
fragShader = &sh;
}
vkr = m_pDriver->vkCreateGraphicsPipelines(m_Device, VK_NULL_HANDLE, 1, &pipeCreateInfo, NULL,
&pipe[0]);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
fragShader->module = mod[1];
vkr = m_pDriver->vkCreateGraphicsPipelines(m_Device, VK_NULL_HANDLE, 1, &pipeCreateInfo, NULL,
&pipe[1]);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
// modify state
m_pDriver->m_RenderState.renderPass = GetResID(m_Overlay.NoDepthRP);
m_pDriver->m_RenderState.subpass = 0;
m_pDriver->m_RenderState.SetFramebuffer(m_pDriver, GetResID(m_Overlay.NoDepthFB));
m_pDriver->m_RenderState.graphics.pipeline = GetResID(pipe[0]);
m_pDriver->m_RenderState.scissors = prevstate.scissors;
for(VkRect2D &sc : m_pDriver->m_RenderState.scissors)
{
sc.offset.x = 0;
sc.offset.y = 0;
sc.extent.width = 16384;
sc.extent.height = 16384;
}
m_pDriver->ReplayLog(0, eventId, eReplay_OnlyDraw);
m_pDriver->m_RenderState.graphics.pipeline = GetResID(pipe[1]);
m_pDriver->m_RenderState.scissors = prevstate.scissors;
m_pDriver->ReplayLog(0, eventId, eReplay_OnlyDraw);
// restore state
m_pDriver->m_RenderState = prevstate;
cmd = m_pDriver->GetNextCmd();
vkr = vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
{
VkClearValue clearval = {};
VkRenderPassBeginInfo rpbegin = {
@@ -1090,23 +1228,6 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
};
vt->CmdBeginRenderPass(Unwrap(cmd), &rpbegin, VK_SUBPASS_CONTENTS_INLINE);
VkClearRect rect = {
{
{
m_pDriver->m_RenderState.renderArea.offset.x,
m_pDriver->m_RenderState.renderArea.offset.y,
},
{
m_pDriver->m_RenderState.renderArea.extent.width,
m_pDriver->m_RenderState.renderArea.extent.height,
},
},
0,
1,
};
VkClearAttachment blackclear = {VK_IMAGE_ASPECT_COLOR_BIT, 0, {}};
vt->CmdClearAttachments(Unwrap(cmd), 1, &blackclear, 1, &rect);
VkViewport viewport = m_pDriver->m_RenderState.views[0];
vt->CmdSetViewport(Unwrap(cmd), 0, 1, &viewport);
@@ -1119,7 +1240,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
// set primary/secondary to the same to 'disable' checkerboard
ubo->PrimaryColor = ubo->SecondaryColor = Vec4f(0.1f, 0.1f, 0.1f, 1.0f);
ubo->InnerColor = Vec4f(0.2f, 0.2f, 0.9f, 0.7f);
ubo->InnerColor = Vec4f(0.2f, 0.2f, 0.9f, 0.4f);
// set viewport rect
ubo->RectPosition = Vec2f(viewport.x, viewport.y);
@@ -1185,6 +1306,24 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
vt->CmdEndRenderPass(Unwrap(cmd));
}
vkr = vt->EndCommandBuffer(Unwrap(cmd));
RDCASSERTEQUAL(vkr, VK_SUCCESS);
// submit & flush so that we don't have to keep pipeline around for a while
m_pDriver->SubmitCmds();
m_pDriver->FlushQ();
cmd = m_pDriver->GetNextCmd();
vkr = vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
for(int i = 0; i < 2; i++)
{
m_pDriver->vkDestroyPipeline(m_Device, pipe[i], NULL);
m_pDriver->vkDestroyShaderModule(m_Device, mod[i], NULL);
}
}
else if(overlay == DebugOverlay::BackfaceCull)
{
@@ -1267,16 +1406,6 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
att->colorWriteMask = 0xf;
}
// set scissors to max
for(size_t i = 0; i < pipeCreateInfo.pViewportState->scissorCount; i++)
{
VkRect2D &sc = (VkRect2D &)pipeCreateInfo.pViewportState->pScissors[i];
sc.offset.x = 0;
sc.offset.y = 0;
sc.extent.width = 16384;
sc.extent.height = 16384;
}
// set our renderpass and shader
pipeCreateInfo.renderPass = m_Overlay.NoDepthRP;
pipeCreateInfo.subpass = 0;
@@ -1334,15 +1463,6 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
m_pDriver->m_RenderState.graphics.pipeline = GetResID(pipe[0]);
// set dynamic scissors in case pipeline was using them
for(size_t i = 0; i < m_pDriver->m_RenderState.scissors.size(); i++)
{
m_pDriver->m_RenderState.scissors[i].offset.x = 0;
m_pDriver->m_RenderState.scissors[i].offset.x = 0;
m_pDriver->m_RenderState.scissors[i].extent.width = 16384;
m_pDriver->m_RenderState.scissors[i].extent.height = 16384;
}
m_pDriver->ReplayLog(0, eventId, eReplay_OnlyDraw);
m_pDriver->m_RenderState.graphics.pipeline = GetResID(pipe[1]);
@@ -1544,16 +1664,6 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
att->colorWriteMask = 0xf;
}
// set scissors to max
for(size_t i = 0; i < pipeCreateInfo.pViewportState->scissorCount; i++)
{
VkRect2D &sc = (VkRect2D &)pipeCreateInfo.pViewportState->pScissors[i];
sc.offset.x = 0;
sc.offset.y = 0;
sc.extent.width = 16384;
sc.extent.height = 16384;
}
// subpass 0 in either render pass
pipeCreateInfo.subpass = 0;
@@ -1631,15 +1741,6 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
m_pDriver->m_RenderState.graphics.pipeline = GetResID(failpipe);
// set dynamic scissors in case pipeline was using them
for(size_t i = 0; i < m_pDriver->m_RenderState.scissors.size(); i++)
{
m_pDriver->m_RenderState.scissors[i].offset.x = 0;
m_pDriver->m_RenderState.scissors[i].offset.x = 0;
m_pDriver->m_RenderState.scissors[i].extent.width = 16384;
m_pDriver->m_RenderState.scissors[i].extent.height = 16384;
}
vkr = vt->EndCommandBuffer(Unwrap(cmd));
RDCASSERTEQUAL(vkr, VK_SUCCESS);
@@ -2372,33 +2473,25 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
std::map<PipeKey, VkPipeline> pipes;
cmd = m_pDriver->GetNextCmd();
vkr = vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
VkClearValue clearval = {};
VkRenderPassBeginInfo rpbegin = {
VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
NULL,
Unwrap(RP),
Unwrap(FB),
{{0, 0}, m_Overlay.ImageDim},
1,
&clearval,
};
vt->CmdBeginRenderPass(Unwrap(cmd), &rpbegin, VK_SUBPASS_CONTENTS_INLINE);
VkViewport viewport = {0.0f,
0.0f,
(float)RDCMAX(1U, m_Overlay.ImageDim.width >> sub.mip),
(float)RDCMAX(1U, m_Overlay.ImageDim.height >> sub.mip),
0.0f,
1.0f};
vt->CmdSetViewport(Unwrap(cmd), 0, 1, &viewport);
for(size_t i = 0; i < events.size(); i++)
{
cmd = m_pDriver->GetNextCmd();
vkr = vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
VkClearValue clearval = {};
VkRenderPassBeginInfo rpbegin = {
VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
NULL,
Unwrap(RP),
Unwrap(FB),
{{0, 0}, m_Overlay.ImageDim},
1,
&clearval,
};
vt->CmdBeginRenderPass(Unwrap(cmd), &rpbegin, VK_SUBPASS_CONTENTS_INLINE);
const DrawcallDescription *draw = m_pDriver->GetDrawcall(events[i]);
for(uint32_t inst = 0; draw && inst < RDCMAX(1U, draw->numInstances); inst++)
@@ -2567,13 +2660,21 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
}
}
}
vt->CmdEndRenderPass(Unwrap(cmd));
vkr = vt->EndCommandBuffer(Unwrap(cmd));
RDCASSERTEQUAL(vkr, VK_SUCCESS);
if(overlay == DebugOverlay::TriangleSizePass)
{
m_pDriver->ReplayLog(events[i], events[i], eReplay_OnlyDraw);
if(i + 1 < events.size())
m_pDriver->ReplayLog(events[i], events[i + 1], eReplay_WithoutDraw);
}
}
vt->CmdEndRenderPass(Unwrap(cmd));
vkr = vt->EndCommandBuffer(Unwrap(cmd));
RDCASSERTEQUAL(vkr, VK_SUCCESS);
m_pDriver->SubmitCmds();
m_pDriver->FlushQ();
@@ -110,6 +110,12 @@ float4 main() : SV_Target0
{Vec3f(0.0f, 0.7f, 0.5f), Vec4f(1.0f, 0.5f, 1.0f, 1.0f), Vec2f(0.0f, 0.0f)},
{Vec3f(0.0f, 0.725f, 0.5f), Vec4f(1.0f, 0.5f, 1.0f, 1.0f), Vec2f(0.0f, 1.0f)},
{Vec3f(0.025f, 0.7f, 0.5f), Vec4f(1.0f, 0.5f, 1.0f, 1.0f), Vec2f(1.0f, 0.0f)},
// this triangle deliberately goes out of the viewport, it will test viewport & scissor
// clipping
{Vec3f(-1.3f, -1.3f, 0.95f), Vec4f(0.1f, 0.1f, 0.5f, 1.0f), Vec2f(0.0f, 0.0f)},
{Vec3f(0.0f, 1.3f, 0.95f), Vec4f(0.1f, 0.1f, 0.5f, 1.0f), Vec2f(0.0f, 1.0f)},
{Vec3f(1.3f, -1.3f, 0.95f), Vec4f(0.1f, 0.1f, 0.5f, 1.0f), Vec2f(1.0f, 0.0f)},
};
ID3D11BufferPtr vb = MakeBuffer().Vertex().Data(VBData);
@@ -188,6 +194,11 @@ float4 main() : SV_Target0
depth.DepthFunc = D3D11_COMPARISON_ALWAYS;
SetDepthState(depth);
setMarker("Viewport Test");
RSSetViewport({10.0f, 10.0f, 80.0f, 80.0f, 0.0f, 1.0f});
RSSetScissor({24, 24, 76, 76});
ctx->Draw(3, 33);
ctx->PSSetShader(whiteps, NULL, 0);
RSSetViewport({5.0f, 5.0f, float(screenWidth) / 4.0f - 10.0f,
@@ -105,6 +105,12 @@ float4 main() : SV_Target0
{Vec3f(0.0f, 0.7f, 0.5f), Vec4f(1.0f, 0.5f, 1.0f, 1.0f), Vec2f(0.0f, 0.0f)},
{Vec3f(0.0f, 0.725f, 0.5f), Vec4f(1.0f, 0.5f, 1.0f, 1.0f), Vec2f(0.0f, 1.0f)},
{Vec3f(0.025f, 0.7f, 0.5f), Vec4f(1.0f, 0.5f, 1.0f, 1.0f), Vec2f(1.0f, 0.0f)},
// this triangle deliberately goes out of the viewport, it will test viewport & scissor
// clipping
{Vec3f(-1.3f, -1.3f, 0.95f), Vec4f(0.1f, 0.1f, 0.5f, 1.0f), Vec2f(0.0f, 0.0f)},
{Vec3f(0.0f, 1.3f, 0.95f), Vec4f(0.1f, 0.1f, 0.5f, 1.0f), Vec2f(0.0f, 1.0f)},
{Vec3f(1.3f, -1.3f, 0.95f), Vec4f(0.1f, 0.1f, 0.5f, 1.0f), Vec2f(1.0f, 0.0f)},
};
ID3D12ResourcePtr vb = MakeBuffer().Data(VBData);
@@ -204,6 +210,13 @@ float4 main() : SV_Target0
cmd->SetPipelineState(pipe);
cmd->DrawInstanced(24, 1, 9, 0);
setMarker(cmd, "Viewport Test");
RSSetViewport(cmd, {10.0f, 10.0f, 80.0f, 80.0f, 0.0f, 1.0f});
RSSetScissorRect(cmd, {24, 24, 76, 76});
cmd->SetPipelineState(backgroundPipe);
cmd->DrawInstanced(3, 1, 33, 0);
D3D12_CPU_DESCRIPTOR_HANDLE subrtv = MakeRTV(subtex)
.Format(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB)
.FirstSlice(2)
+14
View File
@@ -153,6 +153,12 @@ void main()
{Vec3f(0.0f, 0.7f, 0.0f), Vec4f(1.0f, 0.5f, 1.0f, 1.0f), Vec2f(0.0f, 0.0f)},
{Vec3f(0.0f, 0.725f, 0.0f), Vec4f(1.0f, 0.5f, 1.0f, 1.0f), Vec2f(0.0f, 1.0f)},
{Vec3f(0.025f, 0.7f, 0.0f), Vec4f(1.0f, 0.5f, 1.0f, 1.0f), Vec2f(1.0f, 0.0f)},
// this triangle deliberately goes out of the viewport, it will test viewport & scissor
// clipping
{Vec3f(-1.3f, -1.3f, 0.95f), Vec4f(0.1f, 0.1f, 0.5f, 1.0f), Vec2f(0.0f, 0.0f)},
{Vec3f(0.0f, 1.3f, 0.95f), Vec4f(0.1f, 0.1f, 0.5f, 1.0f), Vec2f(0.0f, 1.0f)},
{Vec3f(1.3f, -1.3f, 0.95f), Vec4f(0.1f, 0.1f, 0.5f, 1.0f), Vec2f(1.0f, 0.0f)},
};
GLuint vb = MakeBuffer();
@@ -256,6 +262,14 @@ void main()
glStencilFunc(GL_GREATER, 0x55, 0xff);
glDrawArrays(GL_TRIANGLES, 9, 24);
setMarker("Viewport Test");
glDisable(GL_STENCIL_TEST);
glViewport(10, screenHeight - 90, 80, 80);
glScissor(24, screenHeight - 76, 52, 52);
glDrawArrays(GL_TRIANGLES, 33, 3);
glScissor(0, 0, screenWidth, screenHeight);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBlitFramebuffer(0, 0, screenWidth, screenHeight, 0, 0, screenWidth, screenHeight,
+20 -1
View File
@@ -157,6 +157,12 @@ void main()
{Vec3f(0.0f, -0.7f, 0.5f), Vec4f(1.0f, 0.5f, 1.0f, 1.0f), Vec2f(0.0f, 0.0f)},
{Vec3f(0.0f, -0.725f, 0.5f), Vec4f(1.0f, 0.5f, 1.0f, 1.0f), Vec2f(0.0f, 1.0f)},
{Vec3f(0.025f, -0.7f, 0.5f), Vec4f(1.0f, 0.5f, 1.0f, 1.0f), Vec2f(1.0f, 0.0f)},
// this triangle deliberately goes out of the viewport, it will test viewport & scissor
// clipping
{Vec3f(-1.3f, 1.3f, 0.95f), Vec4f(0.1f, 0.1f, 0.5f, 1.0f), Vec2f(0.0f, 0.0f)},
{Vec3f(0.0f, -1.3f, 0.95f), Vec4f(0.1f, 0.1f, 0.5f, 1.0f), Vec2f(0.0f, 1.0f)},
{Vec3f(1.3f, 1.3f, 0.95f), Vec4f(0.1f, 0.1f, 0.5f, 1.0f), Vec2f(1.0f, 0.0f)},
};
// negate y if we're using negative viewport height
@@ -336,6 +342,19 @@ void main()
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vkCmdDraw(cmd, 24, 1, 9, 0);
setMarker(cmd, "Viewport Test");
v = {10.0f, 10.0f, 80.0f, 80.0f, 0.0f, 1.0f};
if(KHR_maintenance1)
{
v.y += v.height;
v.height = -v.height;
}
VkRect2D s = {{24, 24}, {52, 52}};
vkCmdSetViewport(cmd, 0, 1, &v);
vkCmdSetScissor(cmd, 0, 1, &s);
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, backgroundPipe);
vkCmdDraw(cmd, 3, 1, 33, 0);
vkCmdEndRenderPass(cmd);
v = mainWindow->viewport;
@@ -352,7 +371,7 @@ void main()
v.height = -v.height;
}
VkRect2D s = mainWindow->scissor;
s = mainWindow->scissor;
s.extent.width /= 4;
s.extent.height /= 4;
+128 -11
View File
@@ -224,10 +224,14 @@ class Overlay_Test(rdtest.TestCase):
self.check_pixel_value(overlay_id, 200, 93, [0.0, 1.0, 0.0, 1.0], eps=eps)
elif overlay == rd.DebugOverlay.ViewportScissor:
# Inside viewport
self.check_pixel_value(overlay_id, 50, 50, [0.2*0.7, 0.2*0.7, 0.9*0.7, 0.7*0.7], eps=eps)
self.check_pixel_value(overlay_id, 350, 50, [0.2*0.7, 0.2*0.7, 0.9*0.7, 0.7*0.7], eps=eps)
self.check_pixel_value(overlay_id, 50, 250, [0.2*0.7, 0.2*0.7, 0.9*0.7, 0.7*0.7], eps=eps)
self.check_pixel_value(overlay_id, 350, 250, [0.2*0.7, 0.2*0.7, 0.9*0.7, 0.7*0.7], eps=eps)
self.check_pixel_value(overlay_id, 50, 50, [0.2 * 0.4, 0.2 * 0.4, 0.9 * 0.4, 0.4 * 0.4], eps=eps)
self.check_pixel_value(overlay_id, 350, 50, [0.2 * 0.4, 0.2 * 0.4, 0.9 * 0.4, 0.4 * 0.4], eps=eps)
self.check_pixel_value(overlay_id, 50, 250, [0.2 * 0.4, 0.2 * 0.4, 0.9 * 0.4, 0.4 * 0.4], eps=eps)
self.check_pixel_value(overlay_id, 350, 250, [0.2 * 0.4, 0.2 * 0.4, 0.9 * 0.4, 0.4 * 0.4], eps=eps)
# Passing triangle inside the viewport
self.check_pixel_value(overlay_id, 200, 150,
[0.2 * 0.4, 1.0 * 0.6 + 0.2 * 0.4, 0.9 * 0.4, 1.0 * 0.6 + 0.4 * 0.4], eps=eps)
# Viewport border
self.check_pixel_value(overlay_id, 12, 12, [0.1, 0.1, 0.1, 1.0], eps=eps)
@@ -364,7 +368,116 @@ class Overlay_Test(rdtest.TestCase):
rdtest.log.success("All normal overlays are as expected")
# Check the viewport overlay especially
view_marker: rd.DrawcallDescription = self.find_draw("Viewport Test")
self.controller.SetFrameEvent(view_marker.next.eventId, True)
for overlay in rd.DebugOverlay:
if overlay == rd.DebugOverlay.NoOverlay:
continue
# These overlays are just displaymodes really, not actually separate overlays
if overlay == rd.DebugOverlay.NaN or overlay == rd.DebugOverlay.Clipping:
continue
# We'll test the clear-before-X overlays seperately, for both colour and depth
if overlay == rd.DebugOverlay.ClearBeforeDraw or overlay == rd.DebugOverlay.ClearBeforePass:
continue
rdtest.log.print("Checking overlay {} in viewport draw".format(str(overlay)))
tex.overlay = overlay
out.SetTextureDisplay(tex)
out.Display()
eps = 1.0 / 256.0
overlay_id: rd.ResourceId = out.GetDebugOverlayTexID()
if overlay == rd.DebugOverlay.Drawcall:
# The drawcall overlay will show up outside the scissor region
self.check_pixel_value(overlay_id, 50, 85, [0.8, 0.1, 0.8, 1.0], eps=eps)
self.check_pixel_value(overlay_id, 50, 50, [0.8, 0.1, 0.8, 1.0], eps=eps)
self.check_pixel_value(overlay_id, 50, 10, [0.8, 0.1, 0.8, 1.0], eps=eps)
self.check_pixel_value(overlay_id, 85, 85, [0.8, 0.1, 0.8, 1.0], eps=eps)
self.check_pixel_value(overlay_id, 50, 5, [0.0, 0.0, 0.0, 0.5], eps=eps)
self.check_pixel_value(overlay_id, 95, 85, [0.0, 0.0, 0.0, 0.5], eps=eps)
self.check_pixel_value(overlay_id, 80, 30, [0.0, 0.0, 0.0, 0.5], eps=eps)
elif overlay == rd.DebugOverlay.Wireframe:
# Wireframe we only test a limited set to avoid hitting implementation variations of line raster
# We also have to fudge a little because the lines might land on adjacent pixels
found = False
for delta in range(0, 5):
try:
self.check_pixel_value(overlay_id, 30 + delta, 32, [200.0 / 255.0, 1.0, 0.0, 1.0], eps=eps)
found = True
break
except rdtest.TestFailureException:
pass
if not found:
raise rdtest.TestFailureException("Couldn't find wireframe within scissor")
found = False
for delta in range(0, 5):
try:
self.check_pixel_value(overlay_id, 34 + delta, 22, [200.0 / 255.0, 1.0, 0.0, 1.0], eps=eps)
found = True
break
except rdtest.TestFailureException:
pass
if found:
raise rdtest.TestFailureException("Found wireframe outside of scissor")
elif overlay == rd.DebugOverlay.Depth or overlay == rd.DebugOverlay.Stencil or overlay == rd.DebugOverlay.BackfaceCull:
self.check_pixel_value(overlay_id, 50, 25, [0.0, 1.0, 0.0, 1.0], eps=eps)
self.check_pixel_value(overlay_id, 50, 75, [0.0, 1.0, 0.0, 1.0], eps=eps)
self.check_pixel_value(overlay_id, 50, 20, [0.0, 1.0, 0.0, 0.0], eps=eps)
self.check_pixel_value(overlay_id, 50, 80, [0.0, 1.0, 0.0, 0.0], eps=eps)
elif overlay == rd.DebugOverlay.ViewportScissor:
# Inside viewport and scissor, passing triangle
self.check_pixel_value(overlay_id, 50, 50,
[0.2 * 0.4, 1.0 * 0.6 + 0.2 * 0.4, 0.9 * 0.4, 1.0 * 0.6 + 0.4 * 0.4], eps=eps)
# Inside viewport and outside scissor
self.check_pixel_value(overlay_id, 50, 80,
[1.0 * 0.6 + 0.2 * 0.4, 0.2 * 0.4, 0.9 * 0.4, 1.0 * 0.6 + 0.4 * 0.4], eps=eps)
elif overlay == rd.DebugOverlay.QuadOverdrawDraw:
self.check_pixel_value(overlay_id, 50, 50, [1.0, 1.0, 1.0, 1.0], eps=eps)
self.check_pixel_value(overlay_id, 50, 15, [0.0, 0.0, 0.0, 0.0], eps=eps)
elif overlay == rd.DebugOverlay.QuadOverdrawPass:
self.check_pixel_value(overlay_id, 50, 50, [1.0, 1.0, 1.0, 1.0], eps=eps)
self.check_pixel_value(overlay_id, 50, 15, [0.0, 0.0, 0.0, 0.0], eps=eps)
self.check_pixel_value(overlay_id, 200, 270, [1.0, 1.0, 1.0, 1.0], eps=eps)
self.check_pixel_value(overlay_id, 200, 280, [0.0, 0.0, 0.0, 0.0], eps=eps)
elif overlay == rd.DebugOverlay.TriangleSizeDraw:
eps = 1.0
self.check_pixel_value(overlay_id, 50, 50, [5408.0, 5408.0, 5408.0, 1.0], eps=eps)
self.check_pixel_value(overlay_id, 50, 15, [0.0, 0.0, 0.0, 0.0], eps=eps)
elif overlay == rd.DebugOverlay.TriangleSizePass:
eps = 1.0
self.check_pixel_value(overlay_id, 50, 50, [5408.0, 5408.0, 5408.0, 1.0], eps=eps)
self.check_pixel_value(overlay_id, 50, 15, [0.0, 0.0, 0.0, 0.0], eps=eps)
self.check_pixel_value(overlay_id, 200, 270, [43072.0, 43072.0, 43072.0, 1.0], eps=eps)
self.check_pixel_value(overlay_id, 200, 280, [0.0, 0.0, 0.0, 0.0], eps=eps)
rdtest.log.success("Picked pixels are as expected for {}".format(str(overlay)))
rdtest.log.success("Overlays are as expected around viewport/scissor behaviour")
# Now check clear-before-X by hand, for colour and for depth
self.controller.SetFrameEvent(test_marker.next.eventId, True)
depth_tex: rd.ResourceId = pipe.GetDepthTarget().resourceId
@@ -535,14 +648,18 @@ class Overlay_Test(rdtest.TestCase):
self.check_pixel_value(overlay_id, 70 >> shift, 34 >> shift, [1.0, 0.0, 0.0, 1.0], sub=sub)
self.check_pixel_value(overlay_id, 70 >> shift, 20 >> shift, [0.0, 1.0, 0.0, 0.0], sub=sub)
elif overlay == rd.DebugOverlay.ViewportScissor:
self.check_pixel_value(overlay_id, 20 >> shift, 15 >> shift,
[0.2 * 0.4, 0.2 * 0.4, 0.9 * 0.4, 0.4 * 0.4], sub=sub, eps=eps)
self.check_pixel_value(overlay_id, 80 >> shift, 15 >> shift,
[0.2 * 0.4, 0.2 * 0.4, 0.9 * 0.4, 0.4 * 0.4], sub=sub, eps=eps)
self.check_pixel_value(overlay_id, 20 >> shift, 60 >> shift,
[0.2 * 0.4, 0.2 * 0.4, 0.9 * 0.4, 0.4 * 0.4], sub=sub, eps=eps)
self.check_pixel_value(overlay_id, 80 >> shift, 60 >> shift,
[0.2 * 0.4, 0.2 * 0.4, 0.9 * 0.4, 0.4 * 0.4], sub=sub, eps=eps)
self.check_pixel_value(overlay_id, 50 >> shift, 36 >> shift,
[0.2 * 0.7, 0.2 * 0.7, 0.9 * 0.7, 0.7 * 0.7], sub=sub, eps=eps)
self.check_pixel_value(overlay_id, 30 >> shift, 36 >> shift,
[0.2 * 0.7, 0.2 * 0.7, 0.9 * 0.7, 0.7 * 0.7], sub=sub, eps=eps)
self.check_pixel_value(overlay_id, 70 >> shift, 34 >> shift,
[0.2 * 0.7, 0.2 * 0.7, 0.9 * 0.7, 0.7 * 0.7], sub=sub, eps=eps)
self.check_pixel_value(overlay_id, 70 >> shift, 20 >> shift,
[0.2 * 0.7, 0.2 * 0.7, 0.9 * 0.7, 0.7 * 0.7], sub=sub, eps=eps)
[0.2 * 0.4, 1.0 * 0.6 + 0.2 * 0.4, 0.9 * 0.4, 1.0 * 0.6 + 0.4 * 0.4],
sub=sub, eps=eps)
if mip == 2:
self.check_pixel_value(overlay_id, 6, 6, [0.1, 0.1, 0.1, 1.0], sub=sub, eps=eps)
+3
View File
@@ -382,6 +382,9 @@ class TestCase:
save_data = rd.TextureSave()
save_data.resourceId = tex
save_data.destType = rd.FileType.PNG
save_data.slice.sliceIndex = sub.slice
save_data.mip = sub.mip
save_data.sample.sampleIndex = sub.sample
img_path = util.get_tmp_path('output.png')