diff --git a/util/test/demos/d3d11/d3d11_overlay_test.cpp b/util/test/demos/d3d11/d3d11_overlay_test.cpp index f35643962..792744a6d 100644 --- a/util/test/demos/d3d11/d3d11_overlay_test.cpp +++ b/util/test/demos/d3d11/d3d11_overlay_test.cpp @@ -124,6 +124,23 @@ float4 main() : SV_Target0 MakeTexture(DXGI_FORMAT_D32_FLOAT_S8X24_UINT, screenWidth, screenHeight).DSV(); ID3D11DepthStencilViewPtr dsv = MakeDSV(depthtex); + UINT numQuals = 0; + dev->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 4, &numQuals); + + // when there's more than one quality, use a non-zero just to be awkward. + ID3D11Texture2DPtr msaatex = + MakeTexture(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, screenWidth, screenHeight) + .RTV() + .Multisampled(4, numQuals > 1 ? 1 : 0); + ID3D11RenderTargetViewPtr msaartv = MakeRTV(msaatex); + + dev->CheckMultisampleQualityLevels(DXGI_FORMAT_D32_FLOAT_S8X24_UINT, 4, &numQuals); + ID3D11Texture2DPtr msaadepthtex = + MakeTexture(DXGI_FORMAT_D32_FLOAT_S8X24_UINT, screenWidth, screenHeight) + .DSV() + .Multisampled(4, numQuals > 1 ? 1 : 0); + ID3D11DepthStencilViewPtr msaadsv = MakeDSV(msaadepthtex); + ID3D11Texture2DPtr subtex = MakeTexture(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, screenWidth, screenHeight).RTV().Array(5).Mips(4); ID3D11RenderTargetViewPtr subrtv = @@ -140,64 +157,72 @@ float4 main() : SV_Target0 ctx->VSSetShader(vs, NULL, 0); ctx->PSSetShader(ps, NULL, 0); - D3D11_DEPTH_STENCIL_DESC depth = GetDepthState(); + for(ID3D11RenderTargetViewPtr rtv : {bbRTV, msaartv}) + { + D3D11_DEPTH_STENCIL_DESC depth = GetDepthState(); - depth.StencilEnable = FALSE; - depth.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; - depth.FrontFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE; + depth.StencilEnable = FALSE; + depth.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + depth.FrontFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE; - SetDepthState(depth); - SetStencilRef(0x55); + SetDepthState(depth); + SetStencilRef(0x55); - D3D11_RASTERIZER_DESC raster = GetRasterState(); + D3D11_RASTERIZER_DESC raster = GetRasterState(); - raster.ScissorEnable = TRUE; + raster.ScissorEnable = TRUE; - SetRasterState(raster); + SetRasterState(raster); - RSSetViewport( - {10.0f, 10.0f, (float)screenWidth - 20.0f, (float)screenHeight - 20.0f, 0.0f, 1.0f}); - RSSetScissor({0, 0, screenWidth, screenHeight}); + RSSetViewport( + {10.0f, 10.0f, (float)screenWidth - 20.0f, (float)screenHeight - 20.0f, 0.0f, 1.0f}); + RSSetScissor({0, 0, screenWidth, screenHeight}); - ctx->OMSetRenderTargets(1, &bbRTV.GetInterfacePtr(), dsv); + ID3D11DepthStencilViewPtr curDSV = rtv == msaartv ? msaadsv : dsv; - ClearRenderTargetView(bbRTV, {0.2f, 0.2f, 0.2f, 1.0f}); - ctx->ClearDepthStencilView(dsv, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + ctx->OMSetRenderTargets(1, &rtv.GetInterfacePtr(), curDSV); - // draw the setup triangles + ClearRenderTargetView(rtv, {0.2f, 0.2f, 0.2f, 1.0f}); + ctx->ClearDepthStencilView(curDSV, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); - // 1: write depth - depth.DepthFunc = D3D11_COMPARISON_ALWAYS; - SetDepthState(depth); - ctx->Draw(3, 0); + // draw the setup triangles - // 2: write stencil - depth.DepthFunc = D3D11_COMPARISON_LESS_EQUAL; - depth.StencilEnable = TRUE; - SetDepthState(depth); - ctx->Draw(3, 3); + // 1: write depth + depth.DepthFunc = D3D11_COMPARISON_ALWAYS; + SetDepthState(depth); + ctx->Draw(3, 0); - // 3: write background - depth.StencilEnable = FALSE; - SetDepthState(depth); - ctx->Draw(3, 6); + // 2: write stencil + depth.DepthFunc = D3D11_COMPARISON_LESS_EQUAL; + depth.StencilEnable = TRUE; + SetDepthState(depth); + ctx->Draw(3, 3); - // add a marker so we can easily locate this draw - setMarker("Test Begin"); + // 3: write background + depth.StencilEnable = FALSE; + SetDepthState(depth); + ctx->Draw(3, 6); - depth.StencilEnable = TRUE; - depth.FrontFace.StencilFunc = D3D11_COMPARISON_GREATER; - SetDepthState(depth); - ctx->Draw(24, 9); + // add a marker so we can easily locate this draw + setMarker(rtv == msaartv ? "MSAA Test" : "Normal Test"); - depth.StencilEnable = FALSE; - depth.DepthFunc = D3D11_COMPARISON_ALWAYS; - SetDepthState(depth); + depth.StencilEnable = TRUE; + depth.FrontFace.StencilFunc = D3D11_COMPARISON_GREATER; + SetDepthState(depth); + ctx->Draw(24, 9); - 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); + depth.StencilEnable = FALSE; + depth.DepthFunc = D3D11_COMPARISON_ALWAYS; + SetDepthState(depth); + + if(rtv == bbRTV) + { + 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); diff --git a/util/test/demos/d3d12/d3d12_overlay_test.cpp b/util/test/demos/d3d12/d3d12_overlay_test.cpp index 469ba40b8..653904e96 100644 --- a/util/test/demos/d3d12/d3d12_overlay_test.cpp +++ b/util/test/demos/d3d12/d3d12_overlay_test.cpp @@ -117,6 +117,21 @@ float4 main() : SV_Target0 ID3D12RootSignaturePtr sig = MakeSig({}); + D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS qualData = {}; + qualData.Format = DXGI_FORMAT_D32_FLOAT_S8X24_UINT; + qualData.SampleCount = 4; + dev->CheckFeatureSupport(D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS, &qualData, sizeof(qualData)); + + D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS qualData2 = {}; + qualData2.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + qualData2.SampleCount = 4; + dev->CheckFeatureSupport(D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS, &qualData2, sizeof(qualData2)); + + UINT qual = std::min(qualData.NumQualityLevels, qualData2.NumQualityLevels) > 1 ? 1 : 0; + + DXGI_SAMPLE_DESC noMSAA = {1, 0}; + DXGI_SAMPLE_DESC yesMSAA = {4, qual}; + D3D12PSOCreator creator = MakePSO().RootSig(sig).InputLayout().VS(vsblob).PS(psblob).DSV( DXGI_FORMAT_D32_FLOAT_S8X24_UINT); @@ -136,23 +151,41 @@ float4 main() : SV_Target0 creator.GraphicsDesc.DepthStencilState.StencilWriteMask = 0xff; creator.GraphicsDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS; - ID3D12PipelineStatePtr depthWritePipe = creator; + ID3D12PipelineStatePtr depthWritePipe[2]; + creator.GraphicsDesc.SampleDesc = noMSAA; + depthWritePipe[0] = creator; + creator.GraphicsDesc.SampleDesc = yesMSAA; + depthWritePipe[1] = creator; creator.GraphicsDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL; creator.GraphicsDesc.DepthStencilState.StencilEnable = TRUE; - ID3D12PipelineStatePtr stencilWritePipe = creator; + + ID3D12PipelineStatePtr stencilWritePipe[2]; + creator.GraphicsDesc.SampleDesc = noMSAA; + stencilWritePipe[0] = creator; + creator.GraphicsDesc.SampleDesc = yesMSAA; + stencilWritePipe[1] = creator; creator.GraphicsDesc.DepthStencilState.StencilEnable = FALSE; - ID3D12PipelineStatePtr backgroundPipe = creator; + ID3D12PipelineStatePtr backgroundPipe[2]; + creator.GraphicsDesc.SampleDesc = noMSAA; + backgroundPipe[0] = creator; + creator.GraphicsDesc.SampleDesc = yesMSAA; + backgroundPipe[1] = creator; creator.GraphicsDesc.DepthStencilState.StencilEnable = TRUE; creator.GraphicsDesc.DepthStencilState.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_GREATER; - ID3D12PipelineStatePtr pipe = creator; + ID3D12PipelineStatePtr pipe[2]; + creator.GraphicsDesc.SampleDesc = noMSAA; + pipe[0] = creator; + creator.GraphicsDesc.SampleDesc = yesMSAA; + pipe[1] = creator; creator.GraphicsDesc.DepthStencilState.StencilEnable = FALSE; creator.GraphicsDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS; creator.PS(whitepsblob); creator.DSV(DXGI_FORMAT_UNKNOWN); + creator.GraphicsDesc.SampleDesc = noMSAA; ID3D12PipelineStatePtr whitepipe = creator; ResourceBarrier(vb, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER); @@ -167,6 +200,18 @@ float4 main() : SV_Target0 .Mips(4) .InitialState(D3D12_RESOURCE_STATE_RENDER_TARGET); + ID3D12ResourcePtr msaadsv = + MakeTexture(DXGI_FORMAT_D32_FLOAT_S8X24_UINT, screenWidth, screenHeight) + .DSV() + .Multisampled(4, qual) + .InitialState(D3D12_RESOURCE_STATE_DEPTH_WRITE); + + ID3D12ResourcePtr msaatex = + MakeTexture(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, screenWidth, screenHeight) + .RTV() + .Multisampled(4, qual) + .InitialState(D3D12_RESOURCE_STATE_RENDER_TARGET); + while(Running()) { ID3D12GraphicsCommandListPtr cmd = GetCommandBuffer(); @@ -175,47 +220,54 @@ float4 main() : SV_Target0 ID3D12ResourcePtr bb = StartUsingBackbuffer(cmd, D3D12_RESOURCE_STATE_RENDER_TARGET); - D3D12_CPU_DESCRIPTOR_HANDLE rtv = - MakeRTV(bb).Format(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB).CreateCPU(0); + for(bool is_msaa : {false, true}) + { + D3D12_CPU_DESCRIPTOR_HANDLE rtv = + MakeRTV(is_msaa ? msaatex : bb).Format(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB).CreateCPU(0); - cmd->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + cmd->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - IASetVertexBuffer(cmd, vb, sizeof(DefaultA2V), 0); - cmd->SetGraphicsRootSignature(sig); + IASetVertexBuffer(cmd, vb, sizeof(DefaultA2V), 0); + cmd->SetGraphicsRootSignature(sig); - RSSetViewport( - cmd, {10.0f, 10.0f, (float)screenWidth - 20.0f, (float)screenHeight - 20.0f, 0.0f, 1.0f}); - RSSetScissorRect(cmd, {0, 0, screenWidth, screenHeight}); + RSSetViewport(cmd, {10.0f, 10.0f, (float)screenWidth - 20.0f, (float)screenHeight - 20.0f, + 0.0f, 1.0f}); + RSSetScissorRect(cmd, {0, 0, screenWidth, screenHeight}); - OMSetRenderTargets(cmd, {rtv}, MakeDSV(dsv).CreateCPU(0)); + OMSetRenderTargets(cmd, {rtv}, MakeDSV(is_msaa ? msaadsv : dsv).CreateCPU(0)); - ClearRenderTargetView(cmd, rtv, {0.2f, 0.2f, 0.2f, 1.0f}); - ClearDepthStencilView(cmd, dsv, D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0); + ClearRenderTargetView(cmd, rtv, {0.2f, 0.2f, 0.2f, 1.0f}); + ClearDepthStencilView(cmd, is_msaa ? msaadsv : dsv, + D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0); - cmd->OMSetStencilRef(0x55); + cmd->OMSetStencilRef(0x55); - // draw the setup triangles - cmd->SetPipelineState(depthWritePipe); - cmd->DrawInstanced(3, 1, 0, 0); + // draw the setup triangles + cmd->SetPipelineState(depthWritePipe[is_msaa ? 1 : 0]); + cmd->DrawInstanced(3, 1, 0, 0); - cmd->SetPipelineState(stencilWritePipe); - cmd->DrawInstanced(3, 1, 3, 0); + cmd->SetPipelineState(stencilWritePipe[is_msaa ? 1 : 0]); + cmd->DrawInstanced(3, 1, 3, 0); - cmd->SetPipelineState(backgroundPipe); - cmd->DrawInstanced(3, 1, 6, 0); + cmd->SetPipelineState(backgroundPipe[is_msaa ? 1 : 0]); + cmd->DrawInstanced(3, 1, 6, 0); - // add a marker so we can easily locate this draw - setMarker(cmd, "Test Begin"); + // add a marker so we can easily locate this draw + setMarker(cmd, is_msaa ? "MSAA Test" : "Normal Test"); - cmd->SetPipelineState(pipe); - cmd->DrawInstanced(24, 1, 9, 0); + cmd->SetPipelineState(pipe[is_msaa ? 1 : 0]); + cmd->DrawInstanced(24, 1, 9, 0); - setMarker(cmd, "Viewport Test"); + if(!is_msaa) + { + 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); + RSSetViewport(cmd, {10.0f, 10.0f, 80.0f, 80.0f, 0.0f, 1.0f}); + RSSetScissorRect(cmd, {24, 24, 76, 76}); + cmd->SetPipelineState(backgroundPipe[0]); + cmd->DrawInstanced(3, 1, 33, 0); + } + } D3D12_CPU_DESCRIPTOR_HANDLE subrtv = MakeRTV(subtex) .Format(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB) diff --git a/util/test/demos/gl/gl_overlay_test.cpp b/util/test/demos/gl/gl_overlay_test.cpp index 33df6213c..4676071b2 100644 --- a/util/test/demos/gl/gl_overlay_test.cpp +++ b/util/test/demos/gl/gl_overlay_test.cpp @@ -181,7 +181,7 @@ void main() glBindFramebuffer(GL_FRAMEBUFFER, fbo); // Color render texture - GLuint attachments[] = {MakeTexture(), MakeTexture(), MakeTexture()}; + GLuint attachments[] = {MakeTexture(), MakeTexture(), MakeTexture(), MakeTexture()}; glBindTexture(GL_TEXTURE_2D, attachments[0]); glTexStorage2D(GL_TEXTURE_2D, 1, GL_SRGB8_ALPHA8, screenWidth, screenHeight); @@ -192,6 +192,21 @@ void main() glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, attachments[1], 0); + GLuint msaafbo = MakeFBO(); + glBindFramebuffer(GL_FRAMEBUFFER, msaafbo); + + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, attachments[2]); + glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_SRGB8_ALPHA8, screenWidth, + screenHeight, GL_TRUE); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, + attachments[2], 0); + + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, attachments[3]); + glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_DEPTH24_STENCIL8, screenWidth, + screenHeight, GL_TRUE); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, + attachments[3], 0); + GLuint subtex = MakeTexture(); glBindTexture(GL_TEXTURE_2D_ARRAY, subtex); glTexStorage3D(GL_TEXTURE_2D_ARRAY, 4, GL_SRGB8_ALPHA8, screenWidth, screenHeight, 5); @@ -223,52 +238,58 @@ void main() glUseProgram(program); - glEnable(GL_CULL_FACE); - glFrontFace(GL_CW); + for(GLuint fb : {fbo, msaafbo}) + { + glEnable(GL_CULL_FACE); + glFrontFace(GL_CW); - glDepthMask(GL_TRUE); - glEnable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glDisable(GL_DEPTH_CLAMP); - glDisable(GL_STENCIL_TEST); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - glStencilFunc(GL_ALWAYS, 0x55, 0xff); + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glDisable(GL_DEPTH_CLAMP); + glDisable(GL_STENCIL_TEST); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + glStencilFunc(GL_ALWAYS, 0x55, 0xff); - glViewport(10, 10, GLsizei(screenWidth) - 20, GLsizei(screenHeight) - 20); - glScissor(0, 0, screenWidth, screenHeight); + glViewport(10, 10, GLsizei(screenWidth) - 20, GLsizei(screenHeight) - 20); + glScissor(0, 0, screenWidth, screenHeight); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - float col[] = {0.2f, 0.2f, 0.2f, 1.0f}; - glClearBufferfv(GL_COLOR, 0, col); - glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0f, 0); + glBindFramebuffer(GL_FRAMEBUFFER, fb); + float col[] = {0.2f, 0.2f, 0.2f, 1.0f}; + glClearBufferfv(GL_COLOR, 0, col); + glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0f, 0); - // 1: write depth - glDepthFunc(GL_ALWAYS); - glDrawArrays(GL_TRIANGLES, 0, 3); + // 1: write depth + glDepthFunc(GL_ALWAYS); + glDrawArrays(GL_TRIANGLES, 0, 3); - // 2: write stencil - glDepthFunc(GL_LEQUAL); - glEnable(GL_STENCIL_TEST); - glDrawArrays(GL_TRIANGLES, 3, 3); + // 2: write stencil + glDepthFunc(GL_LEQUAL); + glEnable(GL_STENCIL_TEST); + glDrawArrays(GL_TRIANGLES, 3, 3); - // 3: write background - glDisable(GL_STENCIL_TEST); - glDrawArrays(GL_TRIANGLES, 6, 3); + // 3: write background + glDisable(GL_STENCIL_TEST); + glDrawArrays(GL_TRIANGLES, 6, 3); - // add a marker so we can easily locate this draw - setMarker("Test Begin"); + // add a marker so we can easily locate this draw + setMarker(fb == msaafbo ? "MSAA Test" : "Normal Test"); - glEnable(GL_STENCIL_TEST); - glStencilFunc(GL_GREATER, 0x55, 0xff); - glDrawArrays(GL_TRIANGLES, 9, 24); + glEnable(GL_STENCIL_TEST); + 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); + if(fb != msaafbo) + { + 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); + glScissor(0, 0, screenWidth, screenHeight); + } glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); diff --git a/util/test/demos/vk/vk_overlay_test.cpp b/util/test/demos/vk/vk_overlay_test.cpp index 4f1812400..6f46447c0 100644 --- a/util/test/demos/vk/vk_overlay_test.cpp +++ b/util/test/demos/vk/vk_overlay_test.cpp @@ -206,6 +206,17 @@ void main() VkRenderPass renderPass = createRenderPass(renderPassCreateInfo); + renderPassCreateInfo.attachments[0].samples = VK_SAMPLE_COUNT_4_BIT; + renderPassCreateInfo.attachments[1].samples = VK_SAMPLE_COUNT_4_BIT; + + VkRenderPass msaaRP = createRenderPass(renderPassCreateInfo); + + renderPassCreateInfo.attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; + renderPassCreateInfo.attachments.pop_back(); + renderPassCreateInfo.subpasses[0].pDepthStencilAttachment = NULL; + + VkRenderPass subrp = createRenderPass(renderPassCreateInfo); + // create framebuffers using swapchain images and DS image std::vector fbs; fbs.resize(mainWindow->GetCount()); @@ -218,7 +229,6 @@ void main() vkh::GraphicsPipelineCreateInfo pipeCreateInfo; pipeCreateInfo.layout = layout; - pipeCreateInfo.renderPass = renderPass; pipeCreateInfo.vertexInputState.vertexBindingDescriptions = {vkh::vertexBind(0, DefaultA2V)}; pipeCreateInfo.vertexInputState.vertexAttributeDescriptions = { @@ -245,26 +255,46 @@ void main() pipeCreateInfo.depthStencilState.back = pipeCreateInfo.depthStencilState.front; pipeCreateInfo.depthStencilState.depthCompareOp = VK_COMPARE_OP_ALWAYS; - VkPipeline depthWritePipe = createGraphicsPipeline(pipeCreateInfo); + VkPipeline depthWritePipe[2]; + pipeCreateInfo.multisampleState.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + pipeCreateInfo.renderPass = renderPass; + depthWritePipe[0] = createGraphicsPipeline(pipeCreateInfo); + pipeCreateInfo.multisampleState.rasterizationSamples = VK_SAMPLE_COUNT_4_BIT; + pipeCreateInfo.renderPass = msaaRP; + depthWritePipe[1] = createGraphicsPipeline(pipeCreateInfo); pipeCreateInfo.depthStencilState.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; pipeCreateInfo.depthStencilState.stencilTestEnable = VK_TRUE; - VkPipeline stencilWritePipe = createGraphicsPipeline(pipeCreateInfo); + VkPipeline stencilWritePipe[2]; + pipeCreateInfo.multisampleState.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + pipeCreateInfo.renderPass = renderPass; + stencilWritePipe[0] = createGraphicsPipeline(pipeCreateInfo); + pipeCreateInfo.multisampleState.rasterizationSamples = VK_SAMPLE_COUNT_4_BIT; + pipeCreateInfo.renderPass = msaaRP; + stencilWritePipe[1] = createGraphicsPipeline(pipeCreateInfo); pipeCreateInfo.depthStencilState.stencilTestEnable = VK_FALSE; - VkPipeline backgroundPipe = createGraphicsPipeline(pipeCreateInfo); + VkPipeline backgroundPipe[2]; + pipeCreateInfo.multisampleState.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + pipeCreateInfo.renderPass = renderPass; + backgroundPipe[0] = createGraphicsPipeline(pipeCreateInfo); + pipeCreateInfo.multisampleState.rasterizationSamples = VK_SAMPLE_COUNT_4_BIT; + pipeCreateInfo.renderPass = msaaRP; + backgroundPipe[1] = createGraphicsPipeline(pipeCreateInfo); pipeCreateInfo.depthStencilState.stencilTestEnable = VK_TRUE; pipeCreateInfo.depthStencilState.front.compareOp = VK_COMPARE_OP_GREATER; - VkPipeline pipe = createGraphicsPipeline(pipeCreateInfo); - - renderPassCreateInfo.attachments.pop_back(); - renderPassCreateInfo.subpasses[0].pDepthStencilAttachment = NULL; - - VkRenderPass subrp = createRenderPass(renderPassCreateInfo); + VkPipeline pipe[2]; + pipeCreateInfo.multisampleState.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + pipeCreateInfo.renderPass = renderPass; + pipe[0] = createGraphicsPipeline(pipeCreateInfo); + pipeCreateInfo.multisampleState.rasterizationSamples = VK_SAMPLE_COUNT_4_BIT; + pipeCreateInfo.renderPass = msaaRP; + pipe[1] = createGraphicsPipeline(pipeCreateInfo); pipeCreateInfo.stages[1] = CompileShaderModule(whitepixel, ShaderLang::glsl, ShaderStage::frag, "main"); + pipeCreateInfo.multisampleState.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; pipeCreateInfo.renderPass = subrp; pipeCreateInfo.depthStencilState.stencilTestEnable = VK_FALSE; pipeCreateInfo.depthStencilState.depthCompareOp = VK_COMPARE_OP_ALWAYS; @@ -294,6 +324,31 @@ void main() {mainWindow->scissor.extent.width / 8, mainWindow->scissor.extent.height / 8})), }; + AllocatedImage msaaimg( + this, vkh::ImageCreateInfo(mainWindow->scissor.extent.width, + mainWindow->scissor.extent.height, 0, mainWindow->format, + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 1, 1, VK_SAMPLE_COUNT_4_BIT), + VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_GPU_ONLY})); + + AllocatedImage msaadepthimg( + this, vkh::ImageCreateInfo( + mainWindow->scissor.extent.width, mainWindow->scissor.extent.height, 0, + VK_FORMAT_D32_SFLOAT_S8_UINT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 1, 1, + VK_SAMPLE_COUNT_4_BIT), + VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_GPU_ONLY})); + + VkImageView msaaRTV = createImageView( + vkh::ImageViewCreateInfo(msaaimg.image, VK_IMAGE_VIEW_TYPE_2D, mainWindow->format)); + VkImageView msaaDSV = createImageView(vkh::ImageViewCreateInfo( + msaadepthimg.image, VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_D32_SFLOAT_S8_UINT, {}, + vkh::ImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))); + + VkFramebuffer msaaFB = createFramebuffer(vkh::FramebufferCreateInfo( + msaaRP, {msaaRTV, msaaDSV}, + {mainWindow->scissor.extent.width, mainWindow->scissor.extent.height})); + + (void)msaaFB; + while(Running()) { VkCommandBuffer cmd = GetCommandBuffer(); @@ -302,61 +357,71 @@ void main() StartUsingBackbuffer(cmd, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL); - VkViewport v = mainWindow->viewport; - v.x += 10.0f; - v.y += 10.0f; - v.width -= 20.0f; - v.height -= 20.0f; + VkViewport v; + VkRect2D s; - // if we're using KHR_maintenance1, check that negative viewport height is handled - if(KHR_maintenance1) + for(bool is_msaa : {false, true}) { - v.y += v.height; - v.height = -v.height; + v = mainWindow->viewport; + v.x += 10.0f; + v.y += 10.0f; + v.width -= 20.0f; + v.height -= 20.0f; + + // if we're using KHR_maintenance1, check that negative viewport height is handled + if(KHR_maintenance1) + { + v.y += v.height; + v.height = -v.height; + } + + vkCmdSetViewport(cmd, 0, 1, &v); + vkCmdSetScissor(cmd, 0, 1, &mainWindow->scissor); + vkh::cmdBindVertexBuffers(cmd, 0, {vb.buffer}, {0}); + + vkCmdBeginRenderPass( + cmd, vkh::RenderPassBeginInfo( + is_msaa ? msaaRP : renderPass, is_msaa ? msaaFB : fbs[mainWindow->imgIndex], + mainWindow->scissor, + {vkh::ClearValue(0.2f, 0.2f, 0.2f, 1.0f), vkh::ClearValue(1.0f, 0)}), + VK_SUBPASS_CONTENTS_INLINE); + + // draw the setup triangles + + vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, depthWritePipe[is_msaa ? 1 : 0]); + vkCmdDraw(cmd, 3, 1, 0, 0); + + vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, stencilWritePipe[is_msaa ? 1 : 0]); + vkCmdDraw(cmd, 3, 1, 3, 0); + + vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, backgroundPipe[is_msaa ? 1 : 0]); + vkCmdDraw(cmd, 3, 1, 6, 0); + + // add a marker so we can easily locate this draw + setMarker(cmd, is_msaa ? "MSAA Test" : "Normal Test"); + + vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe[is_msaa ? 1 : 0]); + vkCmdDraw(cmd, 24, 1, 9, 0); + + if(!is_msaa) + { + 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; + } + s = {{24, 24}, {52, 52}}; + vkCmdSetViewport(cmd, 0, 1, &v); + vkCmdSetScissor(cmd, 0, 1, &s); + vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, backgroundPipe[0]); + vkCmdDraw(cmd, 3, 1, 33, 0); + } + + vkCmdEndRenderPass(cmd); } - vkCmdSetViewport(cmd, 0, 1, &v); - vkCmdSetScissor(cmd, 0, 1, &mainWindow->scissor); - vkh::cmdBindVertexBuffers(cmd, 0, {vb.buffer}, {0}); - - vkCmdBeginRenderPass(cmd, - vkh::RenderPassBeginInfo( - renderPass, fbs[mainWindow->imgIndex], mainWindow->scissor, - {vkh::ClearValue(0.2f, 0.2f, 0.2f, 1.0f), vkh::ClearValue(1.0f, 0)}), - VK_SUBPASS_CONTENTS_INLINE); - - // draw the setup triangles - - vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, depthWritePipe); - vkCmdDraw(cmd, 3, 1, 0, 0); - - vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, stencilWritePipe); - vkCmdDraw(cmd, 3, 1, 3, 0); - - vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, backgroundPipe); - vkCmdDraw(cmd, 3, 1, 6, 0); - - // add a marker so we can easily locate this draw - setMarker(cmd, "Test Begin"); - - 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; v.width /= 4.0f; v.height /= 4.0f; diff --git a/util/test/rdtest/shared/Overlay_Test.py b/util/test/rdtest/shared/Overlay_Test.py index 68c01e85f..e314581b8 100644 --- a/util/test/rdtest/shared/Overlay_Test.py +++ b/util/test/rdtest/shared/Overlay_Test.py @@ -14,365 +14,391 @@ class Overlay_Test(rdtest.TestCase): self.check(out is not None) - test_marker: rd.DrawcallDescription = self.find_draw("Test") - - self.controller.SetFrameEvent(test_marker.next.eventId, True) - - pipe: rd.PipeState = self.controller.GetPipelineState() - - col_tex: rd.ResourceId = pipe.GetOutputTargets()[0].resourceId - - tex = rd.TextureDisplay() - tex.resourceId = col_tex + api: rd.GraphicsAPI = self.controller.GetAPIProperties().pipelineType # Check the actual output is as expected first. - # Background around the outside - self.check_pixel_value(col_tex, 0.1, 0.1, [0.2, 0.2, 0.2, 1.0]) - self.check_pixel_value(col_tex, 0.8, 0.1, [0.2, 0.2, 0.2, 1.0]) - self.check_pixel_value(col_tex, 0.5, 0.95, [0.2, 0.2, 0.2, 1.0]) - - # Large dark grey triangle - self.check_pixel_value(col_tex, 0.5, 0.1, [0.1, 0.1, 0.1, 1.0]) - self.check_pixel_value(col_tex, 0.5, 0.9, [0.1, 0.1, 0.1, 1.0]) - self.check_pixel_value(col_tex, 0.2, 0.9, [0.1, 0.1, 0.1, 1.0]) - self.check_pixel_value(col_tex, 0.8, 0.9, [0.1, 0.1, 0.1, 1.0]) - - # Red upper half triangle - self.check_pixel_value(col_tex, 0.3, 0.4, [1.0, 0.0, 0.0, 1.0]) - # Blue lower half triangle - self.check_pixel_value(col_tex, 0.3, 0.6, [0.0, 0.0, 1.0, 1.0]) - - # Floating clipped triangle - self.check_pixel_value(col_tex, 335, 140, [0.0, 0.0, 0.0, 1.0]) - self.check_pixel_value(col_tex, 340, 140, [0.2, 0.2, 0.2, 1.0]) - - # Triangle size triangles - self.check_pixel_value(col_tex, 200, 51, [1.0, 0.5, 1.0, 1.0]) - self.check_pixel_value(col_tex, 200, 65, [1.0, 1.0, 0.0, 1.0]) - self.check_pixel_value(col_tex, 200, 79, [0.0, 1.0, 1.0, 1.0]) - self.check_pixel_value(col_tex, 200, 93, [0.0, 1.0, 0.0, 1.0]) - - 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 main draw".format(str(overlay))) - - tex.overlay = overlay - out.SetTextureDisplay(tex) - - out.Display() - - eps = 1.0 / 256.0 - - overlay_id: rd.ResourceId = out.GetDebugOverlayTexID() - - # We test a few key spots: - # 4 points along the left side of the big triangle, above/in/below its intersection with the tri behind - # 4 points outside all triangles - # The overlap between the big tri and the bottom tri, and between it and the right backface culled tri - # The bottom tri's part that sticks out - # The two parts of the backface culled tri that stick out - # The depth clipped tri, in and out of clipping - # The 4 triangle size test triangles - - if overlay == rd.DebugOverlay.Drawcall: - self.check_pixel_value(overlay_id, 150, 90, [0.8, 0.1, 0.8, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 150, 130, [0.8, 0.1, 0.8, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 150, 160, [0.8, 0.1, 0.8, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 150, 200, [0.8, 0.1, 0.8, 1.0], eps=eps) - - self.check_pixel_value(overlay_id, 125, 60, [0.0, 0.0, 0.0, 0.5], eps=eps) - self.check_pixel_value(overlay_id, 125, 250, [0.0, 0.0, 0.0, 0.5], eps=eps) - self.check_pixel_value(overlay_id, 250, 60, [0.0, 0.0, 0.0, 0.5], eps=eps) - self.check_pixel_value(overlay_id, 250, 250, [0.0, 0.0, 0.0, 0.5], eps=eps) - - self.check_pixel_value(overlay_id, 220, 175, [0.8, 0.1, 0.8, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 250, 150, [0.8, 0.1, 0.8, 1.0], eps=eps) - - self.check_pixel_value(overlay_id, 220, 190, [0.8, 0.1, 0.8, 1.0], eps=eps) - - self.check_pixel_value(overlay_id, 285, 135, [0.8, 0.1, 0.8, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 285, 165, [0.8, 0.1, 0.8, 1.0], eps=eps) - - self.check_pixel_value(overlay_id, 330, 145, [0.8, 0.1, 0.8, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 340, 145, [0.8, 0.1, 0.8, 1.0], eps=eps) - - self.check_pixel_value(overlay_id, 200, 51, [0.8, 0.1, 0.8, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 200, 65, [0.8, 0.1, 0.8, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 200, 79, [0.8, 0.1, 0.8, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 200, 93, [0.8, 0.1, 0.8, 1.0], 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 - - x = 142 - picked: rd.PixelValue = self.controller.PickPixel(overlay_id, x, 150, rd.Subresource(), rd.CompType.Typeless) - if picked.floatValue[3] == 0.0: - x = 141 - - self.check_pixel_value(overlay_id, x, 90, [200.0/255.0, 1.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, x, 130, [200.0/255.0, 1.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, x, 160, [200.0/255.0, 1.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, x, 200, [200.0/255.0, 1.0, 0.0, 1.0], eps=eps) - - self.check_pixel_value(overlay_id, 125, 60, [200.0/255.0, 1.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 125, 250, [200.0/255.0, 1.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 250, 60, [200.0/255.0, 1.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 250, 250, [200.0/255.0, 1.0, 0.0, 0.0], eps=eps) - - y = 149 - picked: rd.PixelValue = self.controller.PickPixel(overlay_id, 325, y, rd.Subresource(), rd.CompType.Typeless) - if picked.floatValue[3] == 0.0: - y = 150 - - self.check_pixel_value(overlay_id, 325, y, [200.0/255.0, 1.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 340, y, [200.0/255.0, 1.0, 0.0, 1.0], eps=eps) - elif overlay == rd.DebugOverlay.Depth: - self.check_pixel_value(overlay_id, 150, 90, [0.0, 1.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 150, 130, [0.0, 1.0, 0.0, 1.0], eps=eps) - # Intersection with lesser depth - depth fail - self.check_pixel_value(overlay_id, 150, 160, [1.0, 0.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 150, 200, [0.0, 1.0, 0.0, 1.0], eps=eps) - - self.check_pixel_value(overlay_id, 125, 60, [0.0, 1.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 125, 250, [0.0, 1.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 250, 60, [0.0, 1.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 250, 250, [0.0, 1.0, 0.0, 0.0], eps=eps) - - self.check_pixel_value(overlay_id, 220, 175, [0.0, 1.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 250, 150, [0.0, 1.0, 0.0, 1.0], eps=eps) - - self.check_pixel_value(overlay_id, 220, 190, [0.0, 1.0, 0.0, 1.0], eps=eps) - - # Backface culled triangle - self.check_pixel_value(overlay_id, 285, 135, [1.0, 0.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 285, 165, [1.0, 0.0, 0.0, 1.0], eps=eps) - - self.check_pixel_value(overlay_id, 330, 145, [0.0, 1.0, 0.0, 1.0], eps=eps) - # Depth clipped part of tri - self.check_pixel_value(overlay_id, 340, 145, [1.0, 0.0, 0.0, 1.0], eps=eps) - - self.check_pixel_value(overlay_id, 200, 51, [0.0, 1.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 200, 65, [0.0, 1.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 200, 79, [0.0, 1.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 200, 93, [0.0, 1.0, 0.0, 1.0], eps=eps) - elif overlay == rd.DebugOverlay.Stencil: - self.check_pixel_value(overlay_id, 150, 90, [0.0, 1.0, 0.0, 1.0], eps=eps) - # Intersection with different stencil - stencil fail - self.check_pixel_value(overlay_id, 150, 130, [1.0, 0.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 150, 160, [0.0, 1.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 150, 200, [0.0, 1.0, 0.0, 1.0], eps=eps) - - self.check_pixel_value(overlay_id, 125, 60, [0.0, 1.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 125, 250, [0.0, 1.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 250, 60, [0.0, 1.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 250, 250, [0.0, 1.0, 0.0, 0.0], eps=eps) - - self.check_pixel_value(overlay_id, 220, 175, [0.0, 1.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 250, 150, [0.0, 1.0, 0.0, 1.0], eps=eps) - - self.check_pixel_value(overlay_id, 220, 190, [0.0, 1.0, 0.0, 1.0], eps=eps) - - # Backface culled triangle - self.check_pixel_value(overlay_id, 285, 135, [1.0, 0.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 285, 165, [1.0, 0.0, 0.0, 1.0], eps=eps) - - self.check_pixel_value(overlay_id, 330, 145, [0.0, 1.0, 0.0, 1.0], eps=eps) - # Depth clipped part of tri - self.check_pixel_value(overlay_id, 340, 145, [1.0, 0.0, 0.0, 1.0], eps=eps) - - self.check_pixel_value(overlay_id, 200, 51, [0.0, 1.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 200, 65, [0.0, 1.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 200, 79, [0.0, 1.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 200, 93, [0.0, 1.0, 0.0, 1.0], eps=eps) - elif overlay == rd.DebugOverlay.BackfaceCull: - self.check_pixel_value(overlay_id, 150, 90, [0.0, 1.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 150, 130, [0.0, 1.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 150, 160, [0.0, 1.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 150, 200, [0.0, 1.0, 0.0, 1.0], eps=eps) - - self.check_pixel_value(overlay_id, 125, 60, [0.0, 1.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 125, 250, [0.0, 1.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 250, 60, [0.0, 1.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 250, 250, [0.0, 1.0, 0.0, 0.0], eps=eps) - - self.check_pixel_value(overlay_id, 220, 175, [0.0, 1.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 250, 150, [0.0, 1.0, 0.0, 1.0], eps=eps) - - self.check_pixel_value(overlay_id, 220, 190, [0.0, 1.0, 0.0, 1.0], eps=eps) - - # Backface culled triangle - self.check_pixel_value(overlay_id, 285, 135, [1.0, 0.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 285, 165, [1.0, 0.0, 0.0, 1.0], eps=eps) - - self.check_pixel_value(overlay_id, 330, 145, [0.0, 1.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 340, 145, [0.0, 1.0, 0.0, 1.0], eps=eps) - - self.check_pixel_value(overlay_id, 200, 51, [0.0, 1.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 200, 65, [0.0, 1.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 200, 79, [0.0, 1.0, 0.0, 1.0], eps=eps) - 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.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) - - # Outside viewport (not on scissor border) - self.check_pixel_value(overlay_id, 6, 6, [0.0, 0.0, 0.0, 0.0], eps=eps) - - # Scissor border - self.check_pixel_value(overlay_id, 0, 0, [1.0, 1.0, 1.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 20, 0, [0.0, 0.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 40, 0, [1.0, 1.0, 1.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 60, 0, [0.0, 0.0, 0.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 60, 0, [0.0, 0.0, 0.0, 1.0], eps=eps) - elif overlay == rd.DebugOverlay.QuadOverdrawDraw: - self.check_pixel_value(overlay_id, 150, 90, [1.0, 1.0, 1.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 150, 130, [0.0, 0.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 150, 160, [0.0, 0.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 150, 200, [1.0, 1.0, 1.0, 1.0], eps=eps) - - self.check_pixel_value(overlay_id, 125, 60, [0.0, 0.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 125, 250, [0.0, 0.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 250, 60, [0.0, 0.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 250, 250, [0.0, 0.0, 0.0, 0.0], eps=eps) - - self.check_pixel_value(overlay_id, 220, 175, [2.0, 2.0, 2.0, 2.0], eps=eps) - self.check_pixel_value(overlay_id, 250, 150, [1.0, 1.0, 1.0, 1.0], eps=eps) - - self.check_pixel_value(overlay_id, 220, 190, [1.0, 1.0, 1.0, 1.0], eps=eps) - - self.check_pixel_value(overlay_id, 285, 135, [0.0, 0.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 285, 165, [0.0, 0.0, 0.0, 0.0], eps=eps) - - self.check_pixel_value(overlay_id, 330, 145, [1.0, 1.0, 1.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 340, 145, [0.0, 0.0, 0.0, 0.0], eps=eps) - - self.check_pixel_value(overlay_id, 200, 51, [1.0, 1.0, 1.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 200, 65, [1.0, 1.0, 1.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 200, 79, [1.0, 1.0, 1.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 200, 93, [1.0, 1.0, 1.0, 1.0], eps=eps) - elif overlay == rd.DebugOverlay.QuadOverdrawPass: - self.check_pixel_value(overlay_id, 150, 90, [1.0, 1.0, 1.0, 1.0], eps=eps) - - # Do an extra tap here where we overlap with the extreme-background largest triangle, to show that - # overdraw - self.check_pixel_value(overlay_id, 150, 100, [2.0, 2.0, 2.0, 2.0], eps=eps) + for is_msaa in [False, True]: + if is_msaa: + test_marker: rd.DrawcallDescription = self.find_draw("MSAA Test") + else: + test_marker: rd.DrawcallDescription = self.find_draw("Normal Test") + + self.controller.SetFrameEvent(test_marker.next.eventId, True) + + pipe: rd.PipeState = self.controller.GetPipelineState() + + col_tex: rd.ResourceId = pipe.GetOutputTargets()[0].resourceId + + tex = rd.TextureDisplay() + tex.resourceId = col_tex + tex.subresource.sample = 0 + + # Background around the outside + self.check_pixel_value(col_tex, 0.1, 0.1, [0.2, 0.2, 0.2, 1.0]) + self.check_pixel_value(col_tex, 0.8, 0.1, [0.2, 0.2, 0.2, 1.0]) + self.check_pixel_value(col_tex, 0.5, 0.95, [0.2, 0.2, 0.2, 1.0]) + + # Large dark grey triangle + self.check_pixel_value(col_tex, 0.5, 0.1, [0.1, 0.1, 0.1, 1.0]) + self.check_pixel_value(col_tex, 0.5, 0.9, [0.1, 0.1, 0.1, 1.0]) + self.check_pixel_value(col_tex, 0.2, 0.9, [0.1, 0.1, 0.1, 1.0]) + self.check_pixel_value(col_tex, 0.8, 0.9, [0.1, 0.1, 0.1, 1.0]) + + # Red upper half triangle + self.check_pixel_value(col_tex, 0.3, 0.4, [1.0, 0.0, 0.0, 1.0]) + # Blue lower half triangle + self.check_pixel_value(col_tex, 0.3, 0.6, [0.0, 0.0, 1.0, 1.0]) + + # Floating clipped triangle + self.check_pixel_value(col_tex, 335, 140, [0.0, 0.0, 0.0, 1.0]) + self.check_pixel_value(col_tex, 340, 140, [0.2, 0.2, 0.2, 1.0]) + + # Triangle size triangles + self.check_pixel_value(col_tex, 200, 51, [1.0, 0.5, 1.0, 1.0]) + self.check_pixel_value(col_tex, 200, 65, [1.0, 1.0, 0.0, 1.0]) + self.check_pixel_value(col_tex, 200, 79, [0.0, 1.0, 1.0, 1.0]) + self.check_pixel_value(col_tex, 200, 93, [0.0, 1.0, 0.0, 1.0]) + + 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 {} main draw".format("MSAA" if is_msaa else "normal", str(overlay))) + + tex.overlay = overlay + out.SetTextureDisplay(tex) + + out.Display() + + eps = 1.0 / 256.0 + + overlay_id: rd.ResourceId = out.GetDebugOverlayTexID() + + # We test a few key spots: + # 4 points along the left side of the big triangle, above/in/below its intersection with the tri behind + # 4 points outside all triangles + # The overlap between the big tri and the bottom tri, and between it and the right backface culled tri + # The bottom tri's part that sticks out + # The two parts of the backface culled tri that stick out + # The depth clipped tri, in and out of clipping + # The 4 triangle size test triangles + + if overlay == rd.DebugOverlay.Drawcall: + self.check_pixel_value(overlay_id, 150, 90, [0.8, 0.1, 0.8, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 150, 130, [0.8, 0.1, 0.8, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 150, 160, [0.8, 0.1, 0.8, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 150, 200, [0.8, 0.1, 0.8, 1.0], eps=eps) + + self.check_pixel_value(overlay_id, 125, 60, [0.0, 0.0, 0.0, 0.5], eps=eps) + self.check_pixel_value(overlay_id, 125, 250, [0.0, 0.0, 0.0, 0.5], eps=eps) + self.check_pixel_value(overlay_id, 250, 60, [0.0, 0.0, 0.0, 0.5], eps=eps) + self.check_pixel_value(overlay_id, 250, 250, [0.0, 0.0, 0.0, 0.5], eps=eps) + + self.check_pixel_value(overlay_id, 220, 175, [0.8, 0.1, 0.8, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 250, 150, [0.8, 0.1, 0.8, 1.0], eps=eps) + + self.check_pixel_value(overlay_id, 220, 190, [0.8, 0.1, 0.8, 1.0], eps=eps) + + self.check_pixel_value(overlay_id, 285, 135, [0.8, 0.1, 0.8, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 285, 165, [0.8, 0.1, 0.8, 1.0], eps=eps) + + self.check_pixel_value(overlay_id, 330, 145, [0.8, 0.1, 0.8, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 340, 145, [0.8, 0.1, 0.8, 1.0], eps=eps) + + self.check_pixel_value(overlay_id, 200, 51, [0.8, 0.1, 0.8, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 200, 65, [0.8, 0.1, 0.8, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 200, 79, [0.8, 0.1, 0.8, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 200, 93, [0.8, 0.1, 0.8, 1.0], 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 + # Also to be safe we don't run this test on MSAA + if not is_msaa: + x = 142 + picked: rd.PixelValue = self.controller.PickPixel(overlay_id, x, 150, rd.Subresource(), rd.CompType.Typeless) + if picked.floatValue[3] == 0.0: + x = 141 + picked: rd.PixelValue = self.controller.PickPixel(overlay_id, x, 150, rd.Subresource(), rd.CompType.Typeless) + + self.check_pixel_value(overlay_id, x, 90, [200.0/255.0, 1.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, x, 130, [200.0/255.0, 1.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, x, 160, [200.0/255.0, 1.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, x, 200, [200.0/255.0, 1.0, 0.0, 1.0], eps=eps) + + self.check_pixel_value(overlay_id, 125, 60, [200.0/255.0, 1.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 125, 250, [200.0/255.0, 1.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 250, 60, [200.0/255.0, 1.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 250, 250, [200.0/255.0, 1.0, 0.0, 0.0], eps=eps) + + y = 149 + picked: rd.PixelValue = self.controller.PickPixel(overlay_id, 325, y, rd.Subresource(), rd.CompType.Typeless) + if picked.floatValue[3] == 0.0: + y = 150 + + self.check_pixel_value(overlay_id, 325, y, [200.0/255.0, 1.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 340, y, [200.0/255.0, 1.0, 0.0, 1.0], eps=eps) + elif overlay == rd.DebugOverlay.Depth: + self.check_pixel_value(overlay_id, 150, 90, [0.0, 1.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 150, 130, [0.0, 1.0, 0.0, 1.0], eps=eps) + # Intersection with lesser depth - depth fail + self.check_pixel_value(overlay_id, 150, 160, [1.0, 0.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 150, 200, [0.0, 1.0, 0.0, 1.0], eps=eps) + + self.check_pixel_value(overlay_id, 125, 60, [0.0, 1.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 125, 250, [0.0, 1.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 250, 60, [0.0, 1.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 250, 250, [0.0, 1.0, 0.0, 0.0], eps=eps) + + self.check_pixel_value(overlay_id, 220, 175, [0.0, 1.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 250, 150, [0.0, 1.0, 0.0, 1.0], eps=eps) + + self.check_pixel_value(overlay_id, 220, 190, [0.0, 1.0, 0.0, 1.0], eps=eps) + + # Backface culled triangle + self.check_pixel_value(overlay_id, 285, 135, [1.0, 0.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 285, 165, [1.0, 0.0, 0.0, 1.0], eps=eps) + + self.check_pixel_value(overlay_id, 330, 145, [0.0, 1.0, 0.0, 1.0], eps=eps) + # Depth clipped part of tri + self.check_pixel_value(overlay_id, 340, 145, [1.0, 0.0, 0.0, 1.0], eps=eps) + + self.check_pixel_value(overlay_id, 200, 51, [0.0, 1.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 200, 65, [0.0, 1.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 200, 79, [0.0, 1.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 200, 93, [0.0, 1.0, 0.0, 1.0], eps=eps) + elif overlay == rd.DebugOverlay.Stencil: + self.check_pixel_value(overlay_id, 150, 90, [0.0, 1.0, 0.0, 1.0], eps=eps) + # Intersection with different stencil - stencil fail + self.check_pixel_value(overlay_id, 150, 130, [1.0, 0.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 150, 160, [0.0, 1.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 150, 200, [0.0, 1.0, 0.0, 1.0], eps=eps) + + self.check_pixel_value(overlay_id, 125, 60, [0.0, 1.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 125, 250, [0.0, 1.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 250, 60, [0.0, 1.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 250, 250, [0.0, 1.0, 0.0, 0.0], eps=eps) + + self.check_pixel_value(overlay_id, 220, 175, [0.0, 1.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 250, 150, [0.0, 1.0, 0.0, 1.0], eps=eps) + + self.check_pixel_value(overlay_id, 220, 190, [0.0, 1.0, 0.0, 1.0], eps=eps) + + # Backface culled triangle + self.check_pixel_value(overlay_id, 285, 135, [1.0, 0.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 285, 165, [1.0, 0.0, 0.0, 1.0], eps=eps) + + self.check_pixel_value(overlay_id, 330, 145, [0.0, 1.0, 0.0, 1.0], eps=eps) + # Depth clipped part of tri + self.check_pixel_value(overlay_id, 340, 145, [1.0, 0.0, 0.0, 1.0], eps=eps) + + self.check_pixel_value(overlay_id, 200, 51, [0.0, 1.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 200, 65, [0.0, 1.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 200, 79, [0.0, 1.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 200, 93, [0.0, 1.0, 0.0, 1.0], eps=eps) + elif overlay == rd.DebugOverlay.BackfaceCull: + self.check_pixel_value(overlay_id, 150, 90, [0.0, 1.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 150, 130, [0.0, 1.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 150, 160, [0.0, 1.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 150, 200, [0.0, 1.0, 0.0, 1.0], eps=eps) + + self.check_pixel_value(overlay_id, 125, 60, [0.0, 1.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 125, 250, [0.0, 1.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 250, 60, [0.0, 1.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 250, 250, [0.0, 1.0, 0.0, 0.0], eps=eps) + + self.check_pixel_value(overlay_id, 220, 175, [0.0, 1.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 250, 150, [0.0, 1.0, 0.0, 1.0], eps=eps) + + self.check_pixel_value(overlay_id, 220, 190, [0.0, 1.0, 0.0, 1.0], eps=eps) + + # Backface culled triangle + self.check_pixel_value(overlay_id, 285, 135, [1.0, 0.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 285, 165, [1.0, 0.0, 0.0, 1.0], eps=eps) + + self.check_pixel_value(overlay_id, 330, 145, [0.0, 1.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 340, 145, [0.0, 1.0, 0.0, 1.0], eps=eps) + + self.check_pixel_value(overlay_id, 200, 51, [0.0, 1.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 200, 65, [0.0, 1.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 200, 79, [0.0, 1.0, 0.0, 1.0], eps=eps) + 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.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) + + # Outside viewport (not on scissor border) + self.check_pixel_value(overlay_id, 6, 6, [0.0, 0.0, 0.0, 0.0], eps=eps) + + # Scissor border + self.check_pixel_value(overlay_id, 0, 0, [1.0, 1.0, 1.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 20, 0, [0.0, 0.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 40, 0, [1.0, 1.0, 1.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 60, 0, [0.0, 0.0, 0.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 60, 0, [0.0, 0.0, 0.0, 1.0], eps=eps) + elif overlay == rd.DebugOverlay.QuadOverdrawDraw: + # This would require extreme command buffer patching to de-MSAA the framebuffer and renderpass + if api == rd.GraphicsAPI.Vulkan and is_msaa: + rdtest.log.print("Quad overdraw not currently supported on MSAA on Vulkan") + continue + + self.check_pixel_value(overlay_id, 150, 90, [1.0, 1.0, 1.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 150, 130, [0.0, 0.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 150, 160, [0.0, 0.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 150, 200, [1.0, 1.0, 1.0, 1.0], eps=eps) + + self.check_pixel_value(overlay_id, 125, 60, [0.0, 0.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 125, 250, [0.0, 0.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 250, 60, [0.0, 0.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 250, 250, [0.0, 0.0, 0.0, 0.0], eps=eps) + + self.check_pixel_value(overlay_id, 220, 175, [2.0, 2.0, 2.0, 2.0], eps=eps) + self.check_pixel_value(overlay_id, 250, 150, [1.0, 1.0, 1.0, 1.0], eps=eps) + + self.check_pixel_value(overlay_id, 220, 190, [1.0, 1.0, 1.0, 1.0], eps=eps) + + self.check_pixel_value(overlay_id, 285, 135, [0.0, 0.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 285, 165, [0.0, 0.0, 0.0, 0.0], eps=eps) + + self.check_pixel_value(overlay_id, 330, 145, [1.0, 1.0, 1.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 340, 145, [0.0, 0.0, 0.0, 0.0], eps=eps) + + self.check_pixel_value(overlay_id, 200, 51, [1.0, 1.0, 1.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 200, 65, [1.0, 1.0, 1.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 200, 79, [1.0, 1.0, 1.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 200, 93, [1.0, 1.0, 1.0, 1.0], eps=eps) + elif overlay == rd.DebugOverlay.QuadOverdrawPass: + # This would require extreme command buffer patching to de-MSAA the framebuffer and renderpass + if api == rd.GraphicsAPI.Vulkan and is_msaa: + rdtest.log.print("Quad overdraw not currently supported on MSAA on Vulkan") + continue + + self.check_pixel_value(overlay_id, 150, 90, [1.0, 1.0, 1.0, 1.0], eps=eps) + + # Do an extra tap here where we overlap with the extreme-background largest triangle, to show that + # overdraw + self.check_pixel_value(overlay_id, 150, 100, [2.0, 2.0, 2.0, 2.0], eps=eps) + + self.check_pixel_value(overlay_id, 150, 130, [1.0, 1.0, 1.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 150, 160, [1.0, 1.0, 1.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 150, 200, [2.0, 2.0, 2.0, 2.0], eps=eps) + + # Two of these have overdraw from the pass due to the large background triangle + self.check_pixel_value(overlay_id, 125, 60, [0.0, 0.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 125, 250, [1.0, 1.0, 1.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 250, 60, [0.0, 0.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 250, 250, [1.0, 1.0, 1.0, 1.0], eps=eps) + + self.check_pixel_value(overlay_id, 220, 175, [3.0, 3.0, 3.0, 3.0], eps=eps) + self.check_pixel_value(overlay_id, 250, 150, [2.0, 2.0, 2.0, 2.0], eps=eps) + + self.check_pixel_value(overlay_id, 220, 190, [2.0, 2.0, 2.0, 2.0], eps=eps) + + self.check_pixel_value(overlay_id, 285, 135, [0.0, 0.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 285, 165, [1.0, 1.0, 1.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 150, 130, [1.0, 1.0, 1.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 150, 160, [1.0, 1.0, 1.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 150, 200, [2.0, 2.0, 2.0, 2.0], eps=eps) - - # Two of these have overdraw from the pass due to the large background triangle - self.check_pixel_value(overlay_id, 125, 60, [0.0, 0.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 125, 250, [1.0, 1.0, 1.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 250, 60, [0.0, 0.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 250, 250, [1.0, 1.0, 1.0, 1.0], eps=eps) - - self.check_pixel_value(overlay_id, 220, 175, [3.0, 3.0, 3.0, 3.0], eps=eps) - self.check_pixel_value(overlay_id, 250, 150, [2.0, 2.0, 2.0, 2.0], eps=eps) - - self.check_pixel_value(overlay_id, 220, 190, [2.0, 2.0, 2.0, 2.0], eps=eps) - - self.check_pixel_value(overlay_id, 285, 135, [0.0, 0.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 285, 165, [1.0, 1.0, 1.0, 1.0], eps=eps) - - self.check_pixel_value(overlay_id, 330, 145, [1.0, 1.0, 1.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 340, 145, [0.0, 0.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 330, 145, [1.0, 1.0, 1.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 340, 145, [0.0, 0.0, 0.0, 0.0], eps=eps) + + self.check_pixel_value(overlay_id, 200, 51, [2.0, 2.0, 2.0, 2.0], eps=eps) + self.check_pixel_value(overlay_id, 200, 65, [2.0, 2.0, 2.0, 2.0], eps=eps) + self.check_pixel_value(overlay_id, 200, 79, [2.0, 2.0, 2.0, 2.0], eps=eps) + self.check_pixel_value(overlay_id, 200, 93, [2.0, 2.0, 2.0, 2.0], eps=eps) + elif overlay == rd.DebugOverlay.TriangleSizeDraw: + eps = 1.0 + + self.check_pixel_value(overlay_id, 150, 90, [10632.0, 10632.0, 10632.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 150, 130, [0.0, 0.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 150, 160, [0.0, 0.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 150, 200, [10632.0, 10632.0, 10632.0, 1.0], eps=eps) + + self.check_pixel_value(overlay_id, 125, 60, [0.0, 0.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 125, 250, [0.0, 0.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 250, 60, [0.0, 0.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 250, 250, [0.0, 0.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 200, 51, [2.0, 2.0, 2.0, 2.0], eps=eps) - self.check_pixel_value(overlay_id, 200, 65, [2.0, 2.0, 2.0, 2.0], eps=eps) - self.check_pixel_value(overlay_id, 200, 79, [2.0, 2.0, 2.0, 2.0], eps=eps) - self.check_pixel_value(overlay_id, 200, 93, [2.0, 2.0, 2.0, 2.0], eps=eps) - elif overlay == rd.DebugOverlay.TriangleSizeDraw: - eps = 1.0 + self.check_pixel_value(overlay_id, 220, 175, [2128.0, 2128.0, 2128.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 250, 150, [10632.0, 10632.0, 10632.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 150, 90, [10632.0, 10632.0, 10632.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 150, 130, [0.0, 0.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 150, 160, [0.0, 0.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 150, 200, [10632.0, 10632.0, 10632.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 220, 190, [2128.0, 2128.0, 2128.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 125, 60, [0.0, 0.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 125, 250, [0.0, 0.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 250, 60, [0.0, 0.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 250, 250, [0.0, 0.0, 0.0, 0.0], eps=eps) - - self.check_pixel_value(overlay_id, 220, 175, [2128.0, 2128.0, 2128.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 250, 150, [10632.0, 10632.0, 10632.0, 1.0], eps=eps) - - self.check_pixel_value(overlay_id, 220, 190, [2128.0, 2128.0, 2128.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 285, 135, [0.0, 0.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 285, 165, [0.0, 0.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 285, 135, [0.0, 0.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 285, 165, [0.0, 0.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 330, 145, [531.0, 531.0, 531.0, 531.0], eps=eps) + self.check_pixel_value(overlay_id, 340, 145, [0.0, 0.0, 0.0, 0.0], eps=eps) + + eps = 0.01 - self.check_pixel_value(overlay_id, 330, 145, [531.0, 531.0, 531.0, 531.0], eps=eps) - self.check_pixel_value(overlay_id, 340, 145, [0.0, 0.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 200, 51, [8.305, 8.305, 8.305, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 200, 65, [5.316, 5.316, 5.316, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 200, 79, [3.0, 3.0, 3.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 200, 93, [1.33, 1.33, 1.33, 1.0], eps=eps) + elif overlay == rd.DebugOverlay.TriangleSizePass: + eps = 1.0 - eps = 0.01 + self.check_pixel_value(overlay_id, 150, 90, [10632.0, 10632.0, 10632.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 150, 130, [3324.0, 3324.0, 3324.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 150, 160, [3324.0, 3324.0, 3324.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 150, 200, [10632.0, 10632.0, 10632.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 200, 51, [8.305, 8.305, 8.305, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 200, 65, [5.316, 5.316, 5.316, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 200, 79, [3.0, 3.0, 3.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 200, 93, [1.33, 1.33, 1.33, 1.0], eps=eps) - elif overlay == rd.DebugOverlay.TriangleSizePass: - eps = 1.0 + self.check_pixel_value(overlay_id, 125, 60, [0.0, 0.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 125, 250, [43072.0, 43072.0, 43072.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 250, 60, [0.0, 0.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 250, 250, [43072.0, 43072.0, 43072.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 150, 90, [10632.0, 10632.0, 10632.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 150, 130, [3324.0, 3324.0, 3324.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 150, 160, [3324.0, 3324.0, 3324.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 150, 200, [10632.0, 10632.0, 10632.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 220, 175, [2128.0, 2128.0, 2128.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 250, 150, [10632.0, 10632.0, 10632.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 125, 60, [0.0, 0.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 125, 250, [43072.0, 43072.0, 43072.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 250, 60, [0.0, 0.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 250, 250, [43072.0, 43072.0, 43072.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 220, 190, [2128.0, 2128.0, 2128.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 220, 175, [2128.0, 2128.0, 2128.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 250, 150, [10632.0, 10632.0, 10632.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 285, 135, [0.0, 0.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 285, 165, [43072.0, 43072.0, 43072.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 220, 190, [2128.0, 2128.0, 2128.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 330, 145, [531.0, 531.0, 531.0, 531.0], eps=eps) + self.check_pixel_value(overlay_id, 340, 145, [0.0, 0.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 285, 135, [0.0, 0.0, 0.0, 0.0], eps=eps) - self.check_pixel_value(overlay_id, 285, 165, [43072.0, 43072.0, 43072.0, 1.0], eps=eps) + eps = 0.01 - self.check_pixel_value(overlay_id, 330, 145, [531.0, 531.0, 531.0, 531.0], eps=eps) - self.check_pixel_value(overlay_id, 340, 145, [0.0, 0.0, 0.0, 0.0], eps=eps) + self.check_pixel_value(overlay_id, 200, 51, [8.305, 8.305, 8.305, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 200, 65, [5.316, 5.316, 5.316, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 200, 79, [3.0, 3.0, 3.0, 1.0], eps=eps) + self.check_pixel_value(overlay_id, 200, 93, [1.33, 1.33, 1.33, 1.0], eps=eps) - eps = 0.01 + rdtest.log.success("Picked pixels are as expected for {}".format(str(overlay))) - self.check_pixel_value(overlay_id, 200, 51, [8.305, 8.305, 8.305, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 200, 65, [5.316, 5.316, 5.316, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 200, 79, [3.0, 3.0, 3.0, 1.0], eps=eps) - self.check_pixel_value(overlay_id, 200, 93, [1.33, 1.33, 1.33, 1.0], eps=eps) - - rdtest.log.success("Picked pixels are as expected for {}".format(str(overlay))) - - rdtest.log.success("All normal overlays are as expected") + if is_msaa: + rdtest.log.success("All MSAA overlays are as expected") + else: + 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) + pipe: rd.PipeState = self.controller.GetPipelineState() + + col_tex: rd.ResourceId = pipe.GetOutputTargets()[0].resourceId + for overlay in rd.DebugOverlay: if overlay == rd.DebugOverlay.NoOverlay: continue @@ -387,6 +413,7 @@ class Overlay_Test(rdtest.TestCase): rdtest.log.print("Checking overlay {} in viewport draw".format(str(overlay))) + tex.resourceId = col_tex tex.overlay = overlay out.SetTextureDisplay(tex) @@ -396,6 +423,12 @@ class Overlay_Test(rdtest.TestCase): overlay_id: rd.ResourceId = out.GetDebugOverlayTexID() + save_data = rd.TextureSave() + save_data.resourceId = overlay_id + save_data.destType = rd.FileType.PNG + + self.controller.SaveTexture(save_data, rdtest.get_tmp_path('overlay.png')) + 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) @@ -476,6 +509,8 @@ class Overlay_Test(rdtest.TestCase): rdtest.log.success("Overlays are as expected around viewport/scissor behaviour") + test_marker: rd.DrawcallDescription = self.find_draw("Normal Test") + # Now check clear-before-X by hand, for colour and for depth self.controller.SetFrameEvent(test_marker.next.eventId, True)