From a6ad1313fdc82adaa7ee2df879cc291d14f8efc6 Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 16 Oct 2025 02:04:26 +0100 Subject: [PATCH] Move D3D12 test to use common pixel history test framework --- util/test/demos/d3d12/d3d12_pixel_history.cpp | 1239 +++++++++-------- util/test/demos/d3d12/d3d12_test.cpp | 5 +- util/test/demos/d3d12/d3d12_test.h | 1 + util/test/tests/D3D12/D3D12_Pixel_History.py | 581 +------- 4 files changed, 632 insertions(+), 1194 deletions(-) diff --git a/util/test/demos/d3d12/d3d12_pixel_history.cpp b/util/test/demos/d3d12/d3d12_pixel_history.cpp index b0893cf9b..7f2ff079d 100644 --- a/util/test/demos/d3d12/d3d12_pixel_history.cpp +++ b/util/test/demos/d3d12/d3d12_pixel_history.cpp @@ -28,256 +28,154 @@ RD_TEST(D3D12_Pixel_History, D3D12GraphicsTest) { static constexpr const char *Description = "Tests pixel history"; - std::string common = R"EOSHADER( -struct v2f -{ - float4 pos : SV_POSITION; - float4 col : COLOR0; - float2 uv : TEXCOORD0; -}; - -)EOSHADER"; - const std::string vertex = R"EOSHADER( -struct vertin +void main(float3 pos : POSITION, float4 col : COLOR0, + out float4 outPos : SV_POSITION, out COL_TYPE outCol : COLOR0) { - float3 pos : POSITION; - float4 col : COLOR0; - float2 uv : TEXCOORD0; -}; - -v2f main(vertin IN, uint vid : SV_VertexID) -{ - v2f OUT = (v2f)0; - - OUT.pos = float4(IN.pos, 1.0f); - OUT.col = IN.col; - OUT.uv = IN.uv; - - return OUT; + outPos = float4(pos, 1.0f); + outCol = ProcessColor(col); } )EOSHADER"; const std::string pixel = R"EOSHADER( -float4 main(v2f vertIn) : SV_Target0 +void main(float4 pos : SV_POSITION, COL_TYPE col : COLOR0 +#if COLOR == 1 + , out COL_TYPE outCol : SV_Target0 +#endif + ) { - if (vertIn.pos.x < 151 && vertIn.pos.x > 150) + if (pos.x < DISCARD_X+1 && pos.x > DISCARD_X) discard; - return vertIn.col + float4(0, 0, 0, 1.75); + if (col.x > 10000 && col.y > 10000 && col.z > 10000) + discard; +#if COLOR == 1 + outCol = col + COL_TYPE(0, 0, 0, ProcessColor((ALPHA_ADD).xxxx).x); +#endif } )EOSHADER"; std::string mspixel = R"EOSHADER( -float4 main(v2f vertIn, uint primId : SV_PrimitiveID, uint sampleId : SV_SampleIndex) : SV_Target0 +void main(float4 pos : SV_POSITION, uint sampleId : SV_SampleIndex +#if COLOR == 1 + , out COL_TYPE outCol : SV_Target0 +#endif + ) { - float4 color = (float4)0; - if(primId == 0) - { - color = float4(1, 0, 1, 2.75); - } - else - { - if (sampleId == 0) - color = float4(1, 0, 0, 2.75); - else if (sampleId == 1) - color = float4(0, 0, 1, 2.75); - else if (sampleId == 2) - color = float4(0, 1, 1, 2.75); - else if (sampleId == 3) - color = float4(1, 1, 1, 2.75); - } - - return color; +#if COLOR == 1 + float4 col = 0.0f.xxxx; + if (sampleId == 0) + col = float4(1, 0, 0, 1+ALPHA_ADD); + else if (sampleId == 1) + col = float4(0, 0, 1, 1+ALPHA_ADD); + else if (sampleId == 2) + col = float4(0, 1, 1, 1+ALPHA_ADD); + else if (sampleId == 3) + col = float4(1, 1, 1, 1+ALPHA_ADD); + outCol = ProcessColor(col); +#endif } )EOSHADER"; - int main() + std::string comp = R"EOSHADER( + +IMAGE_TYPE Output : register(u0); + +[numthreads(1, 1, 1)] +void main() +{ + float4 data = float4(3, 3, 3, 9); + + for(int x=0; x < 10; x++) + for(int y=0; y < 10; y++) + Output[uint3(STORE_X+x, STORE_Y+y, STORE_Z)] = ProcessColor(data); +} + +)EOSHADER"; + + void Prepare(int argc, char **argv) { - // initialise, create window, create context, etc - if(!Init()) - return 3; + D3D12GraphicsTest::Prepare(argc, argv); - DefaultA2V VBData[] = { - // this triangle occludes in depth - {Vec3f(-0.5f, -0.5f, 0.0f), Vec4f(0.0f, 0.0f, 1.0f, 1.0f), Vec2f(0.0f, 0.0f)}, - {Vec3f(-0.5f, 0.0f, 0.0f), Vec4f(0.0f, 0.0f, 1.0f, 1.0f), Vec2f(0.0f, 1.0f)}, - {Vec3f(0.0f, 0.0f, 0.0f), Vec4f(0.0f, 0.0f, 1.0f, 1.0f), Vec2f(1.0f, 0.0f)}, + if(!Avail.empty()) + return; - // this triangle occludes in stencil - {Vec3f(-0.5f, 0.0f, 0.9f), Vec4f(1.0f, 0.0f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)}, - {Vec3f(-0.5f, 0.5f, 0.9f), Vec4f(1.0f, 0.0f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)}, - {Vec3f(0.0f, 0.0f, 0.9f), Vec4f(1.0f, 0.0f, 0.0f, 1.0f), Vec2f(1.0f, 0.0f)}, + if(!opts2.DepthBoundsTestSupported) + Avail = "Depth Bounds is not supported"; + } - // this triangle is just in the background to contribute to overdraw - {Vec3f(-0.9f, -0.9f, 0.95f), Vec4f(1.0f, 0.0f, 1.0f, 1.0f), Vec2f(0.0f, 0.0f)}, - {Vec3f(0.0f, 0.9f, 0.95f), Vec4f(1.0f, 0.0f, 1.0f, 1.0f), Vec2f(0.0f, 1.0f)}, - {Vec3f(0.9f, -0.9f, 0.95f), Vec4f(1.0f, 0.0f, 1.0f, 1.0f), Vec2f(1.0f, 0.0f)}, + struct D3D12TestBatch + { + std::string name; - // the draw has a few triangles, main one that is occluded for depth, another that is - // adding to overdraw complexity, one that is backface culled, then a few more of various - // sizes for triangle size overlay - {Vec3f(-0.3f, -0.5f, 0.5f), Vec4f(0.0f, 0.0f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)}, - {Vec3f(-0.3f, 0.5f, 0.5f), Vec4f(0.0f, 0.0f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)}, - {Vec3f(0.5f, 0.0f, 0.5f), Vec4f(1.0f, 1.0f, 1.0f, 1.0f), Vec2f(1.0f, 0.0f)}, + bool uint = false; - {Vec3f(-0.2f, -0.2f, 0.6f), Vec4f(0.0f, 0.0f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)}, - {Vec3f(0.2f, 0.0f, 0.6f), Vec4f(0.0f, 0.0f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)}, - {Vec3f(0.2f, -0.4f, 0.6f), Vec4f(0.0f, 0.0f, 0.0f, 1.0f), Vec2f(1.0f, 0.0f)}, + uint32_t mip = 0; - // backface culled - {Vec3f(0.1f, 0.0f, 0.5f), Vec4f(0.0f, 0.0f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)}, - {Vec3f(0.5f, -0.2f, 0.5f), Vec4f(0.0f, 0.0f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)}, - {Vec3f(0.5f, 0.2f, 0.5f), Vec4f(0.0f, 0.0f, 0.0f, 1.0f), Vec2f(1.0f, 0.0f)}, + ID3D12ResourcePtr colImg; + ID3D12ResourcePtr depthImg; - // depth clipped (i.e. not clamped) - {Vec3f(0.6f, 0.0f, 0.5f), Vec4f(0.0f, 0.0f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)}, - {Vec3f(0.7f, 0.2f, 0.5f), Vec4f(0.0f, 0.0f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)}, - {Vec3f(0.8f, 0.0f, 1.5f), Vec4f(0.0f, 0.0f, 0.0f, 1.0f), Vec2f(1.0f, 0.0f)}, + ID3D12RootSignaturePtr rootSig; - // small triangles - // size=0.005 - {Vec3f(0.0f, 0.4f, 0.5f), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)}, - {Vec3f(0.0f, 0.41f, 0.5f), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)}, - {Vec3f(0.01f, 0.4f, 0.5f), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(1.0f, 0.0f)}, + D3D12_CPU_DESCRIPTOR_HANDLE RTV = {}, DSV = {}; - // size=0.015 - {Vec3f(0.0f, 0.5f, 0.5f), Vec4f(0.0f, 1.0f, 1.0f, 1.0f), Vec2f(0.0f, 0.0f)}, - {Vec3f(0.0f, 0.515f, 0.5f), Vec4f(0.0f, 1.0f, 1.0f, 1.0f), Vec2f(0.0f, 1.0f)}, - {Vec3f(0.015f, 0.5f, 0.5f), Vec4f(0.0f, 1.0f, 1.0f, 1.0f), Vec2f(1.0f, 0.0f)}, + DXGI_FORMAT depthFormat; - // size=0.02 - {Vec3f(0.0f, 0.6f, 0.5f), Vec4f(1.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)}, - {Vec3f(0.0f, 0.62f, 0.5f), Vec4f(1.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)}, - {Vec3f(0.02f, 0.6f, 0.5f), Vec4f(1.0f, 1.0f, 0.0f, 1.0f), Vec2f(1.0f, 0.0f)}, + ID3D12RootSignaturePtr compRootSig; + D3D12_GPU_DESCRIPTOR_HANDLE compUAV; + ID3D12PipelineStatePtr comppipe; - // size=0.025 - {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)}, + uint32_t width, height; - // dynamic triangles - {Vec3f(-0.6f, -0.75f, 0.5f), Vec4f(1.0f, 0.0f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)}, - {Vec3f(-0.5f, -0.65f, 0.5f), Vec4f(1.0f, 0.0f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)}, - {Vec3f(-0.4f, -0.75f, 0.5f), Vec4f(1.0f, 0.0f, 0.0f, 1.0f), Vec2f(1.0f, 0.0f)}, + ID3D12PipelineStatePtr depthWritePipe; + ID3D12PipelineStatePtr scissorPipe; + ID3D12PipelineStatePtr stencilRefPipe; + ID3D12PipelineStatePtr stencilMaskPipe; + ID3D12PipelineStatePtr depthEqualPipe; + ID3D12PipelineStatePtr depthPipe; + ID3D12PipelineStatePtr stencilWritePipe; + ID3D12PipelineStatePtr backgroundPipe; + ID3D12PipelineStatePtr noPsPipe; + ID3D12PipelineStatePtr basicPipe; + ID3D12PipelineStatePtr colorMaskPipe; + ID3D12PipelineStatePtr cullFrontPipe; + ID3D12PipelineStatePtr depthBoundsPipe; + ID3D12PipelineStatePtr sampleColourPipe; + }; - {Vec3f(-0.6f, -0.75f, 0.5f), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)}, - {Vec3f(-0.5f, -0.65f, 0.5f), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)}, - {Vec3f(-0.4f, -0.75f, 0.5f), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(1.0f, 0.0f)}, + std::vector batches; - {Vec3f(-0.6f, -0.75f, 0.5f), Vec4f(0.0f, 0.0f, 1.0f, 1.0f), Vec2f(0.0f, 0.0f)}, - {Vec3f(-0.5f, -0.65f, 0.5f), Vec4f(0.0f, 0.0f, 1.0f, 1.0f), Vec2f(0.0f, 1.0f)}, - {Vec3f(-0.4f, -0.75f, 0.5f), Vec4f(0.0f, 0.0f, 1.0f, 1.0f), Vec2f(1.0f, 0.0f)}, + void BuildTestBatch(const std::string &name, const std::string &sm_suffix, uint32_t sampleCount, + DXGI_FORMAT colourFormat, DXGI_FORMAT depthStencilFormat, int targetMip = -1, + int targetSlice = -1, int targetDepthSlice = -1) + { + batches.push_back({}); - {Vec3f(-0.6f, -0.75f, 0.5f), Vec4f(0.0f, 1.0f, 1.0f, 1.0f), Vec2f(0.0f, 0.0f)}, - {Vec3f(-0.5f, -0.65f, 0.5f), Vec4f(0.0f, 1.0f, 1.0f, 1.0f), Vec2f(0.0f, 1.0f)}, - {Vec3f(-0.4f, -0.75f, 0.5f), Vec4f(0.0f, 1.0f, 1.0f, 1.0f), Vec2f(1.0f, 0.0f)}, + D3D12TestBatch &batch = batches.back(); + batch.name = name + "(" + sm_suffix + ")"; - // Different depth triangles - {Vec3f(0.0f, -0.8f, 0.97f), Vec4f(1.0f, 1.0f, 1.0f, 1.0f), Vec2f(0.0f, 0.0f)}, - {Vec3f(0.4f, -0.2f, 0.97f), Vec4f(1.0f, 1.0f, 1.0f, 1.0f), Vec2f(0.0f, 1.0f)}, - {Vec3f(0.8f, -0.8f, 0.97f), Vec4f(1.0f, 1.0f, 1.0f, 1.0f), Vec2f(1.0f, 0.0f)}, + batch.width = screenWidth; + batch.height = screenHeight; - {Vec3f(0.2f, -0.8f, 0.20f), Vec4f(1.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)}, - {Vec3f(0.4f, -0.4f, 0.20f), Vec4f(1.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)}, - {Vec3f(0.6f, -0.8f, 0.20f), Vec4f(1.0f, 1.0f, 0.0f, 1.0f), Vec2f(1.0f, 0.0f)}, + uint32_t arraySize = targetSlice >= 0 ? 5 : 1; + uint32_t mips = targetMip >= 0 ? 4 : 1; + uint32_t depth = targetDepthSlice >= 0 ? 14 : 1; - {Vec3f(0.2f, -0.8f, 0.30f), Vec4f(1.0f, 0.0f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)}, - {Vec3f(0.4f, -0.6f, 0.30f), Vec4f(1.0f, 0.0f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)}, - {Vec3f(0.6f, -0.8f, 0.30f), Vec4f(1.0f, 0.0f, 0.0f, 1.0f), Vec2f(1.0f, 0.0f)}, + uint32_t mip = (uint32_t)std::max(0, targetMip); + uint32_t slice = (uint32_t)std::max(0, targetSlice); + if(depth > 1) + slice = (uint32_t)targetDepthSlice; - {Vec3f(0.2f, -0.8f, 0.10f), Vec4f(0.0f, 0.0f, 1.0f, 1.0f), Vec2f(0.0f, 0.0f)}, - {Vec3f(0.4f, -0.7f, 0.10f), Vec4f(0.0f, 0.0f, 1.0f, 1.0f), Vec2f(0.0f, 1.0f)}, - {Vec3f(0.6f, -0.8f, 0.10f), Vec4f(0.0f, 0.0f, 1.0f, 1.0f), Vec2f(1.0f, 0.0f)}, + batch.mip = mip; - // Fails depth bounds test. - {Vec3f(0.2f, -0.8f, 0.05f), Vec4f(1.0f, 1.0f, 1.0f, 1.0f), Vec2f(0.0f, 0.0f)}, - {Vec3f(0.4f, -0.7f, 0.05f), Vec4f(1.0f, 1.0f, 1.0f, 1.0f), Vec2f(0.0f, 1.0f)}, - {Vec3f(0.6f, -0.8f, 0.05f), Vec4f(1.0f, 1.0f, 1.0f, 1.0f), Vec2f(1.0f, 0.0f)}, - - // Should be back face culled. - {Vec3f(0.6f, -0.8f, 0.25f), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(1.0f, 0.0f)}, - {Vec3f(0.4f, -0.7f, 0.25f), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)}, - {Vec3f(0.2f, -0.8f, 0.25f), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)}, - - // depth bounds prep - {Vec3f(0.6f, 0.3f, 0.3f), Vec4f(1.0f, 0.0f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)}, - {Vec3f(0.7f, 0.5f, 0.5f), Vec4f(1.0f, 0.0f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)}, - {Vec3f(0.8f, 0.3f, 0.7f), Vec4f(1.0f, 0.0f, 0.0f, 1.0f), Vec2f(1.0f, 0.0f)}, - // depth bounds clip - {Vec3f(0.6f, 0.3f, 0.3f), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)}, - {Vec3f(0.7f, 0.5f, 0.5f), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)}, - {Vec3f(0.8f, 0.3f, 0.7f), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(1.0f, 0.0f)}, - // D16 triangle - {Vec3f(-0.7f, 0.5f, 0.33f), Vec4f(1.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)}, - {Vec3f(-0.6f, 0.3f, 0.33f), Vec4f(1.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)}, - {Vec3f(-0.8f, 0.3f, 0.33f), Vec4f(1.0f, 1.0f, 0.0f, 1.0f), Vec2f(1.0f, 0.0f)}, - // 1000 draws of 1 triangle - {Vec3f(-0.7f, 0.0f, 0.33f), Vec4f(0.5f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)}, - {Vec3f(-0.8f, 0.2f, 0.33f), Vec4f(0.5f, 1.0f, 0.0f, 1.0f), Vec2f(1.0f, 0.0f)}, - {Vec3f(-0.6f, 0.2f, 0.33f), Vec4f(0.5f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)}, - // 1000 instances of 1 triangle - {Vec3f(-0.7f, 0.6f, 0.33f), Vec4f(1.0f, 0.5f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)}, - {Vec3f(-0.8f, 0.8f, 0.33f), Vec4f(1.0f, 0.5f, 0.0f, 1.0f), Vec2f(1.0f, 0.0f)}, - {Vec3f(-0.6f, 0.8f, 0.33f), Vec4f(1.0f, 0.5f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)}, - }; - - ID3D12ResourcePtr vb = MakeBuffer().Data(VBData); - - uint32_t rtvIndex = 1; // Start at 1, backbuffer takes id 0 - uint32_t dsvIndex = 0; - - const DXGI_FORMAT renderSurfaceFormat = DXGI_FORMAT_R8G8B8A8_TYPELESS; - const DXGI_FORMAT renderViewFormat = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; - const DXGI_FORMAT depthFormat = DXGI_FORMAT_D24_UNORM_S8_UINT; - const DXGI_FORMAT depth16Format = DXGI_FORMAT_D16_UNORM; - - struct PassResources - { - std::string markerName; - D3D_SHADER_MODEL shaderModel; - - ID3D12ResourcePtr mainRT; - D3D12_CPU_DESCRIPTOR_HANDLE mainRTV; - ID3D12ResourcePtr mainDS; - D3D12_CPU_DESCRIPTOR_HANDLE mainDSV; - ID3D12ResourcePtr main16DS; - D3D12_CPU_DESCRIPTOR_HANDLE main16DSV; - - ID3D12ResourcePtr mipArrayRT; - D3D12_CPU_DESCRIPTOR_HANDLE mipArraySubRTV; - ID3D12ResourcePtr mipArrayDS; - D3D12_CPU_DESCRIPTOR_HANDLE mipArraySubDSV; - - ID3D12ResourcePtr msaaRT; - D3D12_CPU_DESCRIPTOR_HANDLE msaaRTV; - ID3D12ResourcePtr msaaDS; - D3D12_CPU_DESCRIPTOR_HANDLE msaaDSV; - - ID3D12ResourcePtr msaaMipArrayRT; - D3D12_CPU_DESCRIPTOR_HANDLE msaaMipArraySubRTV; - ID3D12ResourcePtr msaaMipArrayDS; - D3D12_CPU_DESCRIPTOR_HANDLE msaaMipArraySubDSV; - - ID3D12RootSignaturePtr rootSig; - ID3D12PipelineStatePtr depthWritePipe; - ID3D12PipelineStatePtr dynamicScissorPipe; - ID3D12PipelineStatePtr depthPipe; - ID3D12PipelineStatePtr stencilWritePipe; - ID3D12PipelineStatePtr backgroundPipe; - ID3D12PipelineStatePtr noPsPipe; - ID3D12PipelineStatePtr mainTestPipe; - ID3D12PipelineStatePtr cullFrontPipe; - ID3D12PipelineStatePtr depthBoundsPipe; - ID3D12PipelineStatePtr whitePipe; - ID3D12PipelineStatePtr msaaPipe; - ID3D12PipelineStatePtr depth16Pipe; - }; + static uint32_t rtvIndex = 1; // Start at 1, backbuffer takes id 0 + static uint32_t dsvIndex = 0; + static uint32_t uavIndex = 1; struct DepthBoundsTestStream { @@ -310,138 +208,167 @@ float4 main(v2f vertIn, uint primId : SV_PrimitiveID, uint sampleId : SV_SampleI D3D12_PIPELINE_STATE_SUBOBJECT_TYPE Type7 = D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PS; UINT Padding7; D3D12_SHADER_BYTECODE PS; + + D3D12_PIPELINE_STATE_SUBOBJECT_TYPE Type8 = D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_DESC; + DXGI_SAMPLE_DESC SampleDesc; } depthBoundsTestStream; - D3D12_STATIC_SAMPLER_DESC staticSamp = {}; - staticSamp.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; - staticSamp.AddressU = staticSamp.AddressV = staticSamp.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; - staticSamp.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; + std::string defines; + defines += + "#define COLOR " + std::string(colourFormat == DXGI_FORMAT_UNKNOWN ? "0" : "1") + "\n"; - PassResources passes[3]; - passes[0].shaderModel = D3D_SHADER_MODEL_5_1; // DXBC with optional bindless - passes[1].shaderModel = D3D_SHADER_MODEL_6_0; // DXIL with optional bindless - passes[2].shaderModel = D3D_SHADER_MODEL_6_6; // DXIL with direct heap access bindless - passes[0].markerName = "Begin SM5.1"; - passes[1].markerName = "Begin SM6.0"; - passes[2].markerName = "Begin SM6.6"; - - const std::string profileSuffix[3] = {"_5_1", "_6_0", "_6_6"}; - const std::wstring nameSuffix[3] = {L"_SM51", L"_SM60", L"_SM66"}; - - bool supportSM66 = m_HighestShaderModel >= D3D_SHADER_MODEL_6_6; - int numPasses = (supportSM66 && m_DXILSupport) ? 3 : (m_DXILSupport ? 2 : 1); - for(int i = 0; i < numPasses; ++i) + if(colourFormat == DXGI_FORMAT_R8G8B8A8_UINT || colourFormat == DXGI_FORMAT_R16G16B16A16_UINT || + colourFormat == DXGI_FORMAT_R32G32B32A32_UINT) { - PassResources &pass = passes[i]; - pass.mainRT = MakeTexture(renderSurfaceFormat, screenWidth, screenHeight).RTV(); - pass.mainRT->SetName((L"mainRT" + nameSuffix[i]).c_str()); - pass.mainRTV = MakeRTV(pass.mainRT).Format(renderViewFormat).CreateCPU(rtvIndex++); + batch.uint = true; + defines += R"( - pass.mainDS = MakeTexture(depthFormat, screenWidth, screenHeight).DSV(); - pass.mainDS->SetName((L"mainDS" + nameSuffix[i]).c_str()); - pass.mainDSV = MakeDSV(pass.mainDS).Format(depthFormat).CreateCPU(dsvIndex++); +#define COL_TYPE uint4 +#define ALPHA_ADD 3 - pass.main16DS = MakeTexture(depth16Format, screenWidth, screenHeight).DSV(); - pass.main16DS->SetName((L"main16DS" + nameSuffix[i]).c_str()); - pass.main16DSV = MakeDSV(pass.main16DS).Format(depth16Format).CreateCPU(dsvIndex++); +uint4 ProcessColor(float4 col) +{ + uint4 ret = uint4(16*col); - pass.mipArrayRT = - MakeTexture(renderSurfaceFormat, screenWidth, screenHeight).RTV().Mips(4).Array(5); - pass.mipArrayRT->SetName((L"mipArrayRT" + nameSuffix[i]).c_str()); + if(col.x < 0.0f) ret.x = 0xfffffff0; + if(col.y < 0.0f) ret.y = 0xfffffff0; + if(col.z < 0.0f) ret.z = 0xfffffff0; - pass.mipArraySubRTV = MakeRTV(pass.mipArrayRT) - .Format(renderViewFormat) - .FirstMip(2) - .NumMips(1) - .FirstSlice(2) - .NumSlices(1) - .CreateCPU(rtvIndex++); - pass.mipArrayDS = MakeTexture(depthFormat, screenWidth, screenHeight).DSV().Mips(4).Array(5); - pass.mipArrayDS->SetName((L"mipArrayDS" + nameSuffix[i]).c_str()); + return ret; +} - pass.mipArraySubDSV = MakeDSV(pass.mipArrayDS) - .Format(depthFormat) - .FirstMip(2) - .NumMips(1) - .FirstSlice(2) - .NumSlices(1) - .CreateCPU(dsvIndex++); +)"; + } + else + { + defines += R"( - pass.msaaRT = MakeTexture(renderSurfaceFormat, screenWidth, screenHeight).RTV().Multisampled(4); - pass.msaaRT->SetName((L"msaaRT" + nameSuffix[i]).c_str()); - pass.msaaRTV = MakeRTV(pass.msaaRT).Format(renderViewFormat).CreateCPU(rtvIndex++); +#define COL_TYPE float4 +#define ALPHA_ADD 1.75 - pass.msaaDS = MakeTexture(depthFormat, screenWidth, screenHeight).DSV().Multisampled(4); - pass.msaaDS->SetName((L"msaaDS" + nameSuffix[i]).c_str()); - pass.msaaDSV = MakeDSV(pass.msaaDS).Format(depthFormat).CreateCPU(dsvIndex++); +float4 ProcessColor(float4 col) +{ + float4 ret = col; - pass.msaaMipArrayRT = MakeTexture(renderSurfaceFormat, screenWidth, screenHeight) - .RTV() - .Mips(1) - .Array(4) - .Multisampled(4); - pass.msaaMipArrayRT->SetName((L"msaaMipArrayRT" + nameSuffix[i]).c_str()); - pass.msaaMipArraySubRTV = MakeRTV(pass.msaaMipArrayRT) - .Format(renderViewFormat) - .FirstMip(0) - .NumMips(1) - .FirstSlice(2) - .NumSlices(1) - .CreateCPU(rtvIndex++); + // this obviously won't overflow F32 but it will overflow anything 16-bit and under + if(col.x < 0.0f) ret.x = 100000.0f; + if(col.y < 0.0f) ret.y = 100000.0f; + if(col.z < 0.0f) ret.z = 100000.0f; - pass.msaaMipArrayDS = - MakeTexture(depthFormat, screenWidth, screenHeight).DSV().Mips(1).Array(4).Multisampled(4); - pass.msaaMipArrayDS->SetName((L"msaaMipArrayDS" + nameSuffix[i]).c_str()); - pass.msaaMipArraySubDSV = MakeDSV(pass.msaaMipArrayDS) - .Format(depthFormat) - .FirstMip(0) - .NumMips(1) - .FirstSlice(2) - .NumSlices(1) - .CreateCPU(dsvIndex++); + return ret; +} - ID3DBlobPtr vsBlob = Compile(common + vertex, "main", ("vs" + profileSuffix[i]).c_str()); - ID3DBlobPtr psBlob = Compile(common + pixel, "main", ("ps" + profileSuffix[i]).c_str()); - ID3DBlobPtr psMsaaBlob = Compile(common + mspixel, "main", ("ps" + profileSuffix[i]).c_str()); +)"; + } - pass.rootSig = - MakeSig({}, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT, 1, &staticSamp); - // TODO: Different root sig setup for SM6.6 + defines += "#define DISCARD_X " + std::to_string(150 >> mip) + "\n"; + defines += + "#define IMAGE_TYPE " + std::string(depth > 1 ? "RWTexture3D" : "RWTexture2DArray") + "\n"; + defines += "#define STORE_X " + std::to_string(220 >> mip) + "\n"; + defines += "#define STORE_Y " + std::to_string(80 >> mip) + "\n"; + defines += "#define STORE_Z " + std::to_string(slice) + "\n"; + defines += "\n\n"; - D3D12PSOCreator baselinePSO = MakePSO() - .RootSig(pass.rootSig) - .InputLayout() - .RTVs({DXGI_FORMAT_R8G8B8A8_UNORM_SRGB}) - .DSV(depthFormat) - .VS(vsBlob) - .PS(psBlob); + ID3DBlobPtr vsBlob = Compile(defines + vertex, "main", ("vs_" + sm_suffix).c_str()); + ID3DBlobPtr psBlob = Compile(defines + pixel, "main", ("ps_" + sm_suffix).c_str()); + ID3DBlobPtr psMsaaBlob = Compile(defines + mspixel, "main", ("ps_" + sm_suffix).c_str()); - baselinePSO.GraphicsDesc.RasterizerState.DepthClipEnable = TRUE; - baselinePSO.GraphicsDesc.RasterizerState.CullMode = D3D12_CULL_MODE_BACK; - D3D12_DEPTH_STENCIL_DESC &depthState = baselinePSO.GraphicsDesc.DepthStencilState; - depthState.DepthEnable = TRUE; - depthState.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS; - depthState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; - depthState.StencilEnable = FALSE; - depthState.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS; - depthState.FrontFace.StencilPassOp = D3D12_STENCIL_OP_REPLACE; - depthState.StencilReadMask = 0xff; - depthState.StencilWriteMask = 0xff; - depthState.BackFace = depthState.FrontFace; + if(colourFormat != DXGI_FORMAT_UNKNOWN) + { + D3D12TextureCreator colCreator = + MakeTexture(colourFormat, batch.width, batch.height, depth) + .Mips(mips) + // this is DepthOrArraySize so need to set it correctly from either + .Array(std::max(depth, arraySize)) + .Multisampled(sampleCount) + .InitialState(D3D12_RESOURCE_STATE_COMMON) + .RTV(); - depthState.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS; - pass.depthWritePipe = baselinePSO; + if(sampleCount == 1) + colCreator.UAV(); - depthState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO; - depthState.DepthEnable = FALSE; - pass.dynamicScissorPipe = baselinePSO; + batch.colImg = colCreator; + setName(batch.colImg, batch.name + " colImg"); - depthState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL; - depthState.DepthEnable = TRUE; - depthState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; + batch.RTV = + MakeRTV(batch.colImg).FirstMip(mip).NumMips(1).FirstSlice(slice).NumSlices(1).CreateCPU(rtvIndex++); - depthBoundsTestStream.RootSignature = baselinePSO.GraphicsDesc.pRootSignature; + if(sampleCount == 1) + { + ID3DBlobPtr compBlob = Compile(defines + comp, "main", ("cs_" + sm_suffix).c_str()); + batch.compRootSig = MakeSig({ + tableParam(D3D12_SHADER_VISIBILITY_ALL, D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0, 0, 1, 0), + }); + batch.comppipe = MakePSO().RootSig(batch.compRootSig).CS(compBlob); + + batch.compUAV = MakeUAV(batch.colImg).FirstMip(mip).NumMips(1).CreateGPU(uavIndex++); + } + } + + batch.depthFormat = depthStencilFormat; + + if(depthStencilFormat != DXGI_FORMAT_UNKNOWN) + { + // can't create 2D views of 3D with depth images, so we just use a normal 2D array image + if(depth > 1) + { + arraySize = depth; + depth = 1; + } + + batch.depthImg = MakeTexture(depthStencilFormat, batch.width, batch.height, depth) + .Mips(mips) + // this is DepthOrArraySize so need to set it correctly from either + .Array(std::max(depth, arraySize)) + .Multisampled(sampleCount) + .InitialState(D3D12_RESOURCE_STATE_COMMON) + .DSV(); + setName(batch.depthImg, batch.name + " depthImg"); + + batch.DSV = MakeDSV(batch.depthImg) + .FirstMip(mip) + .NumMips(1) + .FirstSlice(slice) + .NumSlices(1) + .CreateCPU(dsvIndex++); + } + + batch.width >>= mip; + batch.height >>= mip; + + batch.rootSig = MakeSig({}); + + D3D12PSOCreator pipeInfo = MakePSO() + .RootSig(batch.rootSig) + .InputLayout() + .DSV(depthStencilFormat) + .SampleCount(sampleCount) + .VS(vsBlob) + .PS(psBlob); + + if(colourFormat == DXGI_FORMAT_UNKNOWN) + pipeInfo.RTVs({}); + else + pipeInfo.RTVs({colourFormat}); + + pipeInfo.GraphicsDesc.RasterizerState.DepthClipEnable = TRUE; + pipeInfo.GraphicsDesc.RasterizerState.CullMode = D3D12_CULL_MODE_BACK; + + pipeInfo.GraphicsDesc.DepthStencilState.DepthEnable = TRUE; + pipeInfo.GraphicsDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS; + pipeInfo.GraphicsDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; + pipeInfo.GraphicsDesc.DepthStencilState.StencilEnable = FALSE; + pipeInfo.GraphicsDesc.DepthStencilState.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS; + pipeInfo.GraphicsDesc.DepthStencilState.FrontFace.StencilPassOp = D3D12_STENCIL_OP_REPLACE; + pipeInfo.GraphicsDesc.DepthStencilState.StencilReadMask = 0xff; + pipeInfo.GraphicsDesc.DepthStencilState.StencilWriteMask = 0xff; + pipeInfo.GraphicsDesc.DepthStencilState.BackFace = + pipeInfo.GraphicsDesc.DepthStencilState.FrontFace; + + { + const D3D12_DEPTH_STENCIL_DESC &depthState = pipeInfo.GraphicsDesc.DepthStencilState; + depthBoundsTestStream.RootSignature = pipeInfo.GraphicsDesc.pRootSignature; depthBoundsTestStream.DepthStencil.DepthEnable = depthState.DepthEnable; depthBoundsTestStream.DepthStencil.DepthWriteMask = depthState.DepthWriteMask; depthBoundsTestStream.DepthStencil.DepthFunc = depthState.DepthFunc; @@ -452,343 +379,427 @@ float4 main(v2f vertIn, uint primId : SV_PrimitiveID, uint sampleId : SV_SampleI depthBoundsTestStream.DepthStencil.BackFace = depthState.BackFace; depthBoundsTestStream.DepthStencil.DepthBoundsTestEnable = TRUE; - depthBoundsTestStream.Rasterizer = baselinePSO.GraphicsDesc.RasterizerState; - depthBoundsTestStream.InputLayout = baselinePSO.GraphicsDesc.InputLayout; - depthBoundsTestStream.RTVFormats.NumRenderTargets = baselinePSO.GraphicsDesc.NumRenderTargets; + depthBoundsTestStream.SampleDesc = pipeInfo.GraphicsDesc.SampleDesc; + + depthBoundsTestStream.Rasterizer = pipeInfo.GraphicsDesc.RasterizerState; + depthBoundsTestStream.InputLayout = pipeInfo.GraphicsDesc.InputLayout; + depthBoundsTestStream.RTVFormats.NumRenderTargets = pipeInfo.GraphicsDesc.NumRenderTargets; for(int j = 0; j < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++j) - depthBoundsTestStream.RTVFormats.RTFormats[j] = baselinePSO.GraphicsDesc.RTVFormats[j]; - depthBoundsTestStream.DSVFormat = baselinePSO.GraphicsDesc.DSVFormat; + depthBoundsTestStream.RTVFormats.RTFormats[j] = pipeInfo.GraphicsDesc.RTVFormats[j]; + depthBoundsTestStream.DSVFormat = pipeInfo.GraphicsDesc.DSVFormat; - depthBoundsTestStream.VS.BytecodeLength = vsBlob->GetBufferSize(); - depthBoundsTestStream.VS.pShaderBytecode = vsBlob->GetBufferPointer(); - depthBoundsTestStream.PS.BytecodeLength = psBlob->GetBufferSize(); - depthBoundsTestStream.PS.pShaderBytecode = psBlob->GetBufferPointer(); + depthBoundsTestStream.VS = pipeInfo.GraphicsDesc.VS; + depthBoundsTestStream.PS = pipeInfo.GraphicsDesc.PS; + } + D3D12_PIPELINE_STATE_STREAM_DESC depthBoundsTestStreamDesc = {}; + depthBoundsTestStreamDesc.SizeInBytes = sizeof(depthBoundsTestStream); + depthBoundsTestStreamDesc.pPipelineStateSubobjectStream = &depthBoundsTestStream; - D3D12_PIPELINE_STATE_STREAM_DESC depthBoundsTestStreamDesc = {}; - depthBoundsTestStreamDesc.SizeInBytes = sizeof(depthBoundsTestStream); - depthBoundsTestStreamDesc.pPipelineStateSubobjectStream = &depthBoundsTestStream; - HRESULT hr = dev2->CreatePipelineState( - &depthBoundsTestStreamDesc, __uuidof(ID3D12PipelineState), (void **)&pass.depthPipe); - TEST_ASSERT(hr == S_OK, "Pipe created"); + pipeInfo.GraphicsDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS; + batch.depthWritePipe = pipeInfo; + setName(batch.depthWritePipe, batch.name + " depthWritePipe"); - depthState.StencilEnable = TRUE; - pass.stencilWritePipe = baselinePSO; + { + D3D12PSOCreator depthEqualPipeInfo = pipeInfo; + depthEqualPipeInfo.GraphicsDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO; + depthEqualPipeInfo.GraphicsDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_EQUAL; - depthState.StencilEnable = FALSE; - pass.backgroundPipe = baselinePSO; - - depthState.StencilEnable = FALSE; - pass.depth16Pipe = baselinePSO.DSV(DXGI_FORMAT_D16_UNORM); - baselinePSO.DSV(depthFormat); - - depthState.StencilEnable = TRUE; - pass.noPsPipe = baselinePSO.PS(NULL); - - depthState.StencilEnable = TRUE; - depthState.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_GREATER; - pass.mainTestPipe = baselinePSO.PS(psBlob); - - depthState.StencilEnable = FALSE; - - baselinePSO.GraphicsDesc.RasterizerState.CullMode = D3D12_CULL_MODE_FRONT; - pass.cullFrontPipe = baselinePSO; - - baselinePSO.GraphicsDesc.RasterizerState.CullMode = D3D12_CULL_MODE_BACK; - - depthBoundsTestStream.RootSignature = baselinePSO.GraphicsDesc.pRootSignature; - depthBoundsTestStream.DepthStencil.DepthEnable = TRUE; - depthBoundsTestStream.DepthStencil.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; - depthBoundsTestStream.DepthStencil.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL; - depthBoundsTestStream.DepthStencil.StencilEnable = depthState.StencilEnable; - depthBoundsTestStream.DepthStencil.StencilReadMask = depthState.StencilReadMask; - depthBoundsTestStream.DepthStencil.StencilWriteMask = depthState.StencilWriteMask; - depthBoundsTestStream.DepthStencil.FrontFace = depthState.FrontFace; - depthBoundsTestStream.DepthStencil.BackFace = depthState.BackFace; - depthBoundsTestStream.DepthStencil.DepthBoundsTestEnable = TRUE; - depthBoundsTestStream.Rasterizer = baselinePSO.GraphicsDesc.RasterizerState; - depthBoundsTestStream.InputLayout = baselinePSO.GraphicsDesc.InputLayout; - depthBoundsTestStream.RTVFormats.NumRenderTargets = baselinePSO.GraphicsDesc.NumRenderTargets; - for(int j = 0; j < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++j) - depthBoundsTestStream.RTVFormats.RTFormats[j] = baselinePSO.GraphicsDesc.RTVFormats[j]; - depthBoundsTestStream.DSVFormat = baselinePSO.GraphicsDesc.DSVFormat; - - // Depth bounds values are set on the command list before draw - depthBoundsTestStream.VS.BytecodeLength = vsBlob->GetBufferSize(); - depthBoundsTestStream.VS.pShaderBytecode = vsBlob->GetBufferPointer(); - depthBoundsTestStream.PS.BytecodeLength = psBlob->GetBufferSize(); - depthBoundsTestStream.PS.pShaderBytecode = psBlob->GetBufferPointer(); - hr = dev2->CreatePipelineState(&depthBoundsTestStreamDesc, __uuidof(ID3D12PipelineState), - (void **)&pass.depthBoundsPipe); - TEST_ASSERT(hr == S_OK, "Pipe created"); - - depthState.StencilEnable = FALSE; - depthState.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS; - pass.whitePipe = baselinePSO.DSV(DXGI_FORMAT_UNKNOWN); - - depthState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; - pass.msaaPipe = baselinePSO.PS(psMsaaBlob).DSV(depthFormat).SampleCount(4); + batch.depthEqualPipe = depthEqualPipeInfo; + setName(batch.depthEqualPipe, batch.name + " depthEqualPipe"); } - // TODO: Additional testing: - // CS UAV usage that doesn't write, does direct write, does atomic write - // Bindless access of target resource as UAV - // SM6.6 bindless access of target resource as UAV - // Pixel history of RT with depth/stencil changing formats throughout history - // Pixel history of DSV with render target changing formats throughout history - // Several RTs bound, tracking history for pixel in various RT slots - // RTs swapping position in RT array, tracking history of a color pixel - // RT/DSV with mips/slices, getting history of pixel in non-0 mip/slice + { + D3D12PSOCreator scissorStencilPipes = pipeInfo; + scissorStencilPipes.GraphicsDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO; + scissorStencilPipes.GraphicsDesc.DepthStencilState.DepthEnable = FALSE; + + batch.scissorPipe = scissorStencilPipes; + setName(batch.scissorPipe, batch.name + " scissorPipe"); + + batch.stencilRefPipe = scissorStencilPipes; + setName(batch.stencilRefPipe, batch.name + " stencilRefPipe"); + + scissorStencilPipes.GraphicsDesc.DepthStencilState.StencilReadMask = 0; + scissorStencilPipes.GraphicsDesc.DepthStencilState.StencilWriteMask = 0; + + batch.stencilMaskPipe = scissorStencilPipes; + setName(batch.stencilMaskPipe, batch.name + " dynamicStencilMaskPipe"); + } + + pipeInfo.GraphicsDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL; + depthBoundsTestStream.DepthStencil.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL; + + CHECK_HR(dev2->CreatePipelineState(&depthBoundsTestStreamDesc, __uuidof(ID3D12PipelineState), + (void **)&batch.depthPipe)); + setName(batch.depthPipe, batch.name + " depthPipe"); + + pipeInfo.GraphicsDesc.DepthStencilState.StencilEnable = TRUE; + batch.stencilWritePipe = pipeInfo; + setName(batch.stencilWritePipe, batch.name + " stencilWritePipe"); + + pipeInfo.GraphicsDesc.DepthStencilState.StencilEnable = FALSE; + batch.backgroundPipe = pipeInfo; + setName(batch.backgroundPipe, batch.name + " backgroundPipe"); + + { + D3D12_SHADER_BYTECODE PS = pipeInfo.GraphicsDesc.PS; + pipeInfo.GraphicsDesc.PS = {}; + pipeInfo.GraphicsDesc.DepthStencilState.StencilEnable = TRUE; + batch.noPsPipe = pipeInfo; + setName(batch.noPsPipe, batch.name + " noPsPipe"); + pipeInfo.GraphicsDesc.PS = PS; + } + + pipeInfo.GraphicsDesc.DepthStencilState.StencilEnable = TRUE; + pipeInfo.GraphicsDesc.DepthStencilState.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_GREATER; + batch.basicPipe = pipeInfo; + setName(batch.basicPipe, batch.name + " basicPipe"); + pipeInfo.GraphicsDesc.DepthStencilState.StencilEnable = FALSE; + + { + D3D12PSOCreator maskPipeInfo = pipeInfo; + maskPipeInfo.GraphicsDesc.BlendState.RenderTarget[0].RenderTargetWriteMask = 0x3; + batch.colorMaskPipe = maskPipeInfo; + setName(batch.colorMaskPipe, batch.name + " colorMaskPipe"); + } + + pipeInfo.GraphicsDesc.RasterizerState.CullMode = D3D12_CULL_MODE_FRONT; + batch.cullFrontPipe = pipeInfo; + setName(batch.cullFrontPipe, batch.name + " cullFrontPipe"); + pipeInfo.GraphicsDesc.RasterizerState.CullMode = D3D12_CULL_MODE_BACK; + + depthBoundsTestStream.DepthStencil.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL; + + CHECK_HR(dev2->CreatePipelineState(&depthBoundsTestStreamDesc, __uuidof(ID3D12PipelineState), + (void **)&batch.depthBoundsPipe)); + setName(batch.depthBoundsPipe, batch.name + " depthBoundsPipe"); + + pipeInfo.PS(psMsaaBlob); + + pipeInfo.GraphicsDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; + if(sampleCount == 4) + pipeInfo.GraphicsDesc.SampleMask = 0x7; + batch.sampleColourPipe = pipeInfo; + setName(batch.sampleColourPipe, batch.name + " sampleColourPipe"); + } + + void RunDraw(ID3D12GraphicsCommandList1Ptr cmd, const PixelHistory::draw &draw, + uint32_t numInstances = 1) + { + cmd->DrawInstanced(draw.count, numInstances, draw.first, 0); + } + + void RunBatch(const D3D12TestBatch &b, ID3D12GraphicsCommandList1Ptr cmd) + { + float factor = float(b.width) / float(screenWidth); + + D3D12_VIEWPORT v = {}; + v.Width = (float)b.width - (20.0f * factor); + v.Height = (float)b.height - (20.0f * factor); + v.TopLeftX = floorf(10.0f * factor); + v.TopLeftY = floorf(10.0f * factor); + v.MaxDepth = 1.0f; + + D3D12_RECT scissor = {0, 0, (LONG)b.width, (LONG)b.height}; + D3D12_RECT scissorPass = {95 >> b.mip, 245 >> b.mip, 115U >> b.mip, 253U >> b.mip}; + D3D12_RECT scissorFail = {95 >> b.mip, 245 >> b.mip, 103U >> b.mip, 253U >> b.mip}; + + cmd->RSSetViewports(1, &v); + cmd->RSSetScissorRects(1, &scissor); + + cmd->OMSetStencilRef(0x55); + cmd->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + cmd->SetGraphicsRootSignature(b.rootSig); + + // draw the setup triangles + + pushMarker(cmd, "Setup"); + { + setMarker(cmd, "Depth Write"); + cmd->SetPipelineState(b.depthWritePipe); + RunDraw(cmd, PixelHistory::DepthWrite); + + setMarker(cmd, "Depth Equal Setup"); + RunDraw(cmd, PixelHistory::DepthEqualSetup); + + cmd->OMSetStencilRef(0x33); + + setMarker(cmd, "Unbound Fragment Shader"); + cmd->SetPipelineState(b.noPsPipe); + RunDraw(cmd, PixelHistory::UnboundPS); + + cmd->OMSetStencilRef(0x55); + + setMarker(cmd, "Stencil Write"); + cmd->SetPipelineState(b.stencilWritePipe); + RunDraw(cmd, PixelHistory::StencilWrite); + + setMarker(cmd, "Background"); + cmd->SetPipelineState(b.backgroundPipe); + RunDraw(cmd, PixelHistory::Background); + + setMarker(cmd, "Cull Front"); + cmd->SetPipelineState(b.cullFrontPipe); + RunDraw(cmd, PixelHistory::CullFront); + + setMarker(cmd, "Depth Bounds Prep"); + cmd->SetPipelineState(b.depthBoundsPipe); + cmd->OMSetDepthBounds(0.0f, 1.0f); + RunDraw(cmd, PixelHistory::DepthBoundsPrep); + setMarker(cmd, "Depth Bounds Clip"); + cmd->OMSetDepthBounds(0.4f, 0.6f); + RunDraw(cmd, PixelHistory::DepthBoundsClip); + } + popMarker(cmd); + + pushMarker(cmd, "Stress Test"); + { + pushMarker(cmd, "Lots of Drawcalls"); + { + setMarker(cmd, "300 Draws"); + cmd->SetPipelineState(b.depthWritePipe); + for(int d = 0; d < 300; ++d) + RunDraw(cmd, PixelHistory::Draws300); + } + popMarker(cmd); + + setMarker(cmd, "300 Instances"); + RunDraw(cmd, PixelHistory::Instances300, 300); + } + popMarker(cmd); + + setMarker(cmd, "Simple Test"); + cmd->SetPipelineState(b.basicPipe); + RunDraw(cmd, PixelHistory::MainTest); + + cmd->SetPipelineState(b.scissorPipe); + + setMarker(cmd, "Scissor Fail"); + cmd->RSSetScissorRects(1, &scissorFail); + RunDraw(cmd, PixelHistory::ScissorFail); + + setMarker(cmd, "Scissor Pass"); + cmd->RSSetScissorRects(1, &scissorPass); + RunDraw(cmd, PixelHistory::ScissorPass); + + cmd->RSSetScissorRects(1, &scissor); + + setMarker(cmd, "Stencil Ref"); + cmd->SetPipelineState(b.stencilRefPipe); + cmd->OMSetStencilRef(0x67); + RunDraw(cmd, PixelHistory::StencilRef); + + cmd->OMSetStencilRef(0x55); + + setMarker(cmd, "Stencil Mask"); + cmd->SetPipelineState(b.stencilMaskPipe); + RunDraw(cmd, PixelHistory::StencilMask); + + setMarker(cmd, "Depth Test"); + cmd->SetPipelineState(b.depthPipe); + cmd->OMSetDepthBounds(0.15f, 1.0f); + RunDraw(cmd, PixelHistory::DepthTest); + + setMarker(cmd, "Sample Colouring"); + cmd->SetPipelineState(b.sampleColourPipe); + RunDraw(cmd, PixelHistory::SampleColour); + + setMarker(cmd, "Depth Equal Fail"); + cmd->SetPipelineState(b.depthEqualPipe); + RunDraw(cmd, PixelHistory::DepthEqualFail); + + setMarker(cmd, "Depth Equal Pass"); + cmd->SetPipelineState(b.depthEqualPipe); + if(b.depthFormat == DXGI_FORMAT_D24_UNORM_S8_UINT) + RunDraw(cmd, PixelHistory::DepthEqualPass24); + else if(b.depthFormat == DXGI_FORMAT_D16_UNORM) + RunDraw(cmd, PixelHistory::DepthEqualPass16); + else + RunDraw(cmd, PixelHistory::DepthEqualPass32); + + setMarker(cmd, "Colour Masked"); + cmd->SetPipelineState(b.colorMaskPipe); + RunDraw(cmd, PixelHistory::ColourMask); + + setMarker(cmd, "Overflowing"); + cmd->SetPipelineState(b.backgroundPipe); + RunDraw(cmd, PixelHistory::OverflowingDraw); + + setMarker(cmd, "Per-Fragment discarding"); + cmd->SetPipelineState(b.backgroundPipe); + RunDraw(cmd, PixelHistory::PerFragDiscard); + } + + int main() + { + // initialise, create window, create context, etc + if(!Init()) + return 3; + + PixelHistory::init(); + + ID3D12ResourcePtr vb = MakeBuffer() + .Size(UINT(sizeof(DefaultA2V) * PixelHistory::vb.size())) + .Data(PixelHistory::vb.data()); + + ID3D12ResourcePtr bbBlitSource; + + BuildTestBatch("Basic", "5_0", 1, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_D32_FLOAT_S8X24_UINT); + bbBlitSource = batches.back().colImg; + + if(m_DXILSupport) + { + BuildTestBatch("Basic", "6_0", 1, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_D32_FLOAT_S8X24_UINT); + + if(m_HighestShaderModel >= D3D_SHADER_MODEL_6_6) + BuildTestBatch("Basic", "6_6", 1, DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_D32_FLOAT_S8X24_UINT); + } + + BuildTestBatch("MSAA", "5_0", 4, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_D32_FLOAT_S8X24_UINT); + BuildTestBatch("Colour Only", "5_0", 1, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + BuildTestBatch("Depth Only", "5_0", 1, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D32_FLOAT_S8X24_UINT); + BuildTestBatch("Mip & Slice", "5_0", 1, DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_D32_FLOAT_S8X24_UINT, 2, 3); + BuildTestBatch("Slice MSAA", "5_0", 4, DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_D32_FLOAT_S8X24_UINT, -1, 3); + + // with new features we can have depth in this test, via a 2D array textures. Otherwise we need + // to test without depth + if(opts19.MismatchingOutputDimensionsSupported) + BuildTestBatch("3D texture", "5_0", 1, DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_D32_FLOAT_S8X24_UINT, -1, -1, 8); + else + BuildTestBatch("3D texture", "5_0", 1, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, -1, + -1, 8); + + BuildTestBatch("D24S8", "5_0", 1, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_D24_UNORM_S8_UINT); + + BuildTestBatch("D16", "5_0", 1, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_D16_UNORM); + BuildTestBatch("D32", "5_0", 1, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_D32_FLOAT); + + BuildTestBatch("F16 UNORM", "5_0", 1, DXGI_FORMAT_R16G16B16A16_UNORM, + DXGI_FORMAT_D32_FLOAT_S8X24_UINT); + BuildTestBatch("F16 FLOAT", "5_0", 1, DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_D32_FLOAT_S8X24_UINT); + BuildTestBatch("F32 FLOAT", "5_0", 1, DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_D32_FLOAT_S8X24_UINT); + + BuildTestBatch("8-bit uint", "5_0", 1, DXGI_FORMAT_R8G8B8A8_UINT, + DXGI_FORMAT_D32_FLOAT_S8X24_UINT); + BuildTestBatch("16-bit uint", "5_0", 1, DXGI_FORMAT_R16G16B16A16_UINT, + DXGI_FORMAT_D32_FLOAT_S8X24_UINT); + BuildTestBatch("32-bit uint", "5_0", 1, DXGI_FORMAT_R32G32B32A32_UINT, + DXGI_FORMAT_D32_FLOAT_S8X24_UINT); while(Running()) { - for(int i = 0; i < numPasses; ++i) - { - PassResources &pass = passes[i]; + std::vector cmds; + for(const D3D12TestBatch &b : batches) + { ID3D12GraphicsCommandList1Ptr cmd = GetCommandBuffer(); Reset(cmd); - pushMarker(cmd, pass.markerName); - - cmd->OMSetStencilRef(0x55); - - D3D12_VIEWPORT v; - v.TopLeftX = 10; - v.TopLeftY = 10; - v.MinDepth = 0; - v.MaxDepth = 1; - v.Width = screenWidth - 20.0f; - v.Height = screenHeight - 20.0f; - RSSetViewport(cmd, v); - - D3D12_RECT scissor; - scissor.left = scissor.top = 0; - scissor.right = screenWidth; - scissor.bottom = screenHeight; - RSSetScissorRect(cmd, scissor); IASetVertexBuffer(cmd, vb, sizeof(DefaultA2V), 0); - cmd->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - float clearColor[4] = {0.2f, 0.2f, 0.2f, 1.0f}; - cmd->OMSetRenderTargets(1, &pass.mainRTV, FALSE, &pass.mainDSV); - cmd->ClearRenderTargetView(pass.mainRTV, clearColor, 0, NULL); - cmd->ClearDepthStencilView(pass.mainDSV, D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, - 1.0f, 0, 0, NULL); - - cmd->SetGraphicsRootSignature(pass.rootSig); - - // Draw the setup triangles - - setMarker(cmd, "Depth Write"); - cmd->SetPipelineState(pass.depthWritePipe); - cmd->DrawInstanced(3, 1, 0, 0); - - setMarker(cmd, "Unbound Fragment Shader"); - cmd->OMSetStencilRef(0x33); - cmd->SetPipelineState(pass.noPsPipe); - cmd->DrawInstanced(3, 1, 3, 0); - cmd->OMSetStencilRef(0x55); - - setMarker(cmd, "Stencil Write"); - cmd->SetPipelineState(pass.stencilWritePipe); - cmd->DrawInstanced(3, 1, 3, 0); - - setMarker(cmd, "Background"); - cmd->SetPipelineState(pass.backgroundPipe); - cmd->DrawInstanced(3, 1, 6, 0); - - setMarker(cmd, "Cull Front"); - cmd->SetPipelineState(pass.cullFrontPipe); - cmd->DrawInstanced(3, 1, 0, 0); - - setMarker(cmd, "Depth Bounds Prep"); - cmd->SetPipelineState(pass.depthBoundsPipe); - cmd->OMSetDepthBounds(0.0f, 1.0f); - cmd->DrawInstanced(3, 1, 63, 0); - setMarker(cmd, "Depth Bounds Clip"); - cmd->OMSetDepthBounds(0.4f, 0.6f); - cmd->DrawInstanced(3, 1, 66, 0); - - pushMarker(cmd, "Stress Test"); - pushMarker(cmd, "Lots of Drawcalls"); - setMarker(cmd, "1000 Draws"); - cmd->SetPipelineState(pass.depthWritePipe); - for(int d = 0; d < 1000; ++d) - cmd->DrawInstanced(3, 1, 72, 0); - popMarker(cmd); - setMarker(cmd, "1000 Instances"); - cmd->DrawInstanced(3, 1000, 75, 0); - popMarker(cmd); - - // Add a marker so we can easily locate this draw - setMarker(cmd, "Test Begin"); - - cmd->SetPipelineState(pass.mainTestPipe); - cmd->DrawInstanced(24, 1, 9, 0); - - setMarker(cmd, "Fixed Scissor Fail"); - cmd->SetPipelineState(pass.dynamicScissorPipe); - D3D12_RECT testScissor; - testScissor.left = 95; - testScissor.top = 245; - testScissor.right = 99; - testScissor.bottom = 249; - RSSetScissorRect(cmd, testScissor); - cmd->DrawInstanced(3, 1, 33, 0); - - setMarker(cmd, "Fixed Scissor Pass"); - cmd->SetPipelineState(pass.dynamicScissorPipe); - testScissor.left = 95; - testScissor.top = 245; - testScissor.right = 105; - testScissor.bottom = 255; - RSSetScissorRect(cmd, testScissor); - cmd->DrawInstanced(3, 1, 36, 0); - - setMarker(cmd, "Dynamic Stencil Ref"); - cmd->SetPipelineState(pass.dynamicScissorPipe); - RSSetScissorRect(cmd, scissor); - cmd->OMSetStencilRef(0x67); - cmd->DrawInstanced(3, 1, 39, 0); - - setMarker(cmd, "Dynamic Stencil Mask"); - cmd->SetPipelineState(pass.dynamicScissorPipe); - cmd->DrawInstanced(3, 1, 42, 0); - - // Six triangles, five fragments reported. - // 0: Fails depth test - // 1: Passes - // 2: Fails depth test compared to 1st fragment - // 3: Passes - // 4: Fails depth bounds test - // 5: Fails backface culling, not reported. - setMarker(cmd, "Depth Test"); - cmd->SetPipelineState(pass.depthPipe); - cmd->OMSetDepthBounds(0.15f, 1.0f); - cmd->DrawInstanced(6 * 3, 1, 45, 0); - - cmd->OMSetRenderTargets(1, &pass.mainRTV, FALSE, &pass.main16DSV); - setMarker(cmd, "Clear Depth 16-bit"); - cmd->ClearDepthStencilView(pass.main16DSV, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, NULL); - setMarker(cmd, "Depth 16-bit Test"); - cmd->SetPipelineState(pass.depth16Pipe); - cmd->DrawInstanced(3, 1, 69, 0); - - ResourceBarrier(cmd, pass.main16DS, D3D12_RESOURCE_STATE_DEPTH_WRITE, - D3D12_RESOURCE_STATE_COMMON); { - pushMarker(cmd, "Begin MSAA"); + pushMarker(cmd, "Batch: " + b.name); + { + setMarker(cmd, "Begin RenderPass"); - ResourceBarrier(cmd, pass.msaaDS, D3D12_RESOURCE_STATE_COMMON, - D3D12_RESOURCE_STATE_DEPTH_WRITE); - ResourceBarrier(cmd, pass.msaaRT, D3D12_RESOURCE_STATE_COMMON, - D3D12_RESOURCE_STATE_RENDER_TARGET); + float clearColor[4] = {0.2f, 0.2f, 0.2f, 1.0f}; + if(b.uint) + { + clearColor[0] = 80.0f; + clearColor[1] = 80.0f; + clearColor[2] = 80.0f; + clearColor[3] = 16.0f; + } - cmd->OMSetRenderTargets(1, &pass.msaaRTV, FALSE, &pass.msaaDSV); - float clearColorMsaa[4] = {0.0f, 1.0f, 0.0f, 1.0f}; - cmd->ClearRenderTargetView(pass.msaaRTV, clearColorMsaa, 0, NULL); - cmd->ClearDepthStencilView( - pass.msaaDSV, D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 0.0f, 0, 0, NULL); + if(b.RTV.ptr) + cmd->ClearRenderTargetView(b.RTV, clearColor, 0, NULL); + if(b.DSV.ptr) + cmd->ClearDepthStencilView(b.DSV, D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, + 1.0f, 0, 0, NULL); - cmd->SetPipelineState(pass.msaaPipe); + cmd->OMSetRenderTargets(b.RTV.ptr ? 1 : 0, &b.RTV, FALSE, b.DSV.ptr ? &b.DSV : NULL); - setMarker(cmd, "Multisampled: test"); - cmd->DrawInstanced(6, 1, 3, 0); + RunBatch(b, cmd); - ResourceBarrier(cmd, pass.msaaDS, D3D12_RESOURCE_STATE_DEPTH_WRITE, - D3D12_RESOURCE_STATE_COMMON); - ResourceBarrier(cmd, pass.msaaRT, D3D12_RESOURCE_STATE_RENDER_TARGET, - D3D12_RESOURCE_STATE_COMMON); + if(b.depthImg) + ResourceBarrier(cmd, b.depthImg, D3D12_RESOURCE_STATE_DEPTH_WRITE, + D3D12_RESOURCE_STATE_COMMON); + if(b.comppipe) + { + setMarker(cmd, "Compute write"); + if(b.colImg) + ResourceBarrier(cmd, b.colImg, D3D12_RESOURCE_STATE_RENDER_TARGET, + D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + + cmd->SetDescriptorHeaps(1, &m_CBVUAVSRV.GetInterfacePtr()); + cmd->SetComputeRootSignature(b.compRootSig); + cmd->SetPipelineState(b.comppipe); + cmd->SetComputeRootDescriptorTable(0, b.compUAV); + cmd->Dispatch(1, 1, 1); + + if(b.colImg) + ResourceBarrier(cmd, b.colImg, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, + D3D12_RESOURCE_STATE_COMMON); + } + else + { + if(b.colImg) + ResourceBarrier(cmd, b.colImg, D3D12_RESOURCE_STATE_RENDER_TARGET, + D3D12_RESOURCE_STATE_COMMON); + } + } popMarker(cmd); } - v.Width = screenWidth / 4.0f - 10; - v.Height = screenHeight / 4.0f - 10; - v.TopLeftX = 5.0f; - v.TopLeftY = 5.0f; - - scissor.right = (scissor.right - scissor.left) / 4 + scissor.left; - scissor.bottom = (scissor.bottom - scissor.top) / 4 + scissor.top; - - // Render to a secondary surface - { - pushMarker(cmd, "Begin RenderPass Secondary"); - - ResourceBarrier(cmd, pass.mipArrayDS, D3D12_RESOURCE_STATE_COMMON, - D3D12_RESOURCE_STATE_DEPTH_WRITE); - ResourceBarrier(cmd, pass.mipArrayRT, D3D12_RESOURCE_STATE_COMMON, - D3D12_RESOURCE_STATE_RENDER_TARGET); - cmd->OMSetRenderTargets(1, &pass.mipArraySubRTV, FALSE, NULL); - float clearColorSecondary[4] = {0.0f, 1.0f, 0.0f, 1.0f}; - cmd->ClearRenderTargetView(pass.mipArraySubRTV, clearColorSecondary, 0, NULL); - cmd->OMSetStencilRef(0x55); - - IASetVertexBuffer(cmd, vb, sizeof(DefaultA2V), 0); - cmd->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - cmd->SetPipelineState(pass.whitePipe); - - RSSetViewport(cmd, v); - RSSetScissorRect(cmd, scissor); - - setMarker(cmd, "Secondary: background"); - cmd->DrawInstanced(6, 1, 3, 0); - setMarker(cmd, "Secondary: culled"); - cmd->DrawInstanced(6, 1, 12, 0); - setMarker(cmd, "Secondary: pink"); - cmd->DrawInstanced(9, 1, 24, 0); - setMarker(cmd, "Secondary: red and blue"); - cmd->DrawInstanced(6, 1, 0, 0); - - ResourceBarrier(cmd, pass.mipArrayDS, D3D12_RESOURCE_STATE_DEPTH_WRITE, - D3D12_RESOURCE_STATE_COMMON); - ResourceBarrier(cmd, pass.mipArrayRT, D3D12_RESOURCE_STATE_RENDER_TARGET, - D3D12_RESOURCE_STATE_COMMON); - popMarker(cmd); - } - - ResourceBarrier(cmd, pass.mainDS, D3D12_RESOURCE_STATE_DEPTH_WRITE, - D3D12_RESOURCE_STATE_COMMON); - ResourceBarrier(cmd, pass.mainRT, D3D12_RESOURCE_STATE_RENDER_TARGET, - D3D12_RESOURCE_STATE_COMMON); - - popMarker(cmd); cmd->Close(); { ID3D12GraphicsCommandList1Ptr barrierCmd = GetCommandBuffer(); Reset(barrierCmd); - ResourceBarrier(barrierCmd, pass.main16DS, D3D12_RESOURCE_STATE_COMMON, - D3D12_RESOURCE_STATE_DEPTH_WRITE); - ResourceBarrier(barrierCmd, pass.mainDS, D3D12_RESOURCE_STATE_COMMON, - D3D12_RESOURCE_STATE_DEPTH_WRITE); - ResourceBarrier(barrierCmd, pass.mainRT, D3D12_RESOURCE_STATE_COMMON, - D3D12_RESOURCE_STATE_RENDER_TARGET); + if(b.depthImg) + ResourceBarrier(barrierCmd, b.depthImg, D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_DEPTH_WRITE); + if(b.colImg) + ResourceBarrier(barrierCmd, b.colImg, D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_RENDER_TARGET); barrierCmd->Close(); - Submit({barrierCmd}); + cmds.push_back(barrierCmd); } - Submit({cmd}); + cmds.push_back(cmd); } - ID3D12GraphicsCommandList1Ptr cmd = GetCommandBuffer(); - Reset(cmd); - // Now blit the main render targets to the back buffer - ID3D12ResourcePtr bb = StartUsingBackbuffer(cmd, D3D12_RESOURCE_STATE_RENDER_TARGET); - for(int i = 0; i < numPasses; ++i) { - ResourceBarrier(cmd, passes[i].mainRT, D3D12_RESOURCE_STATE_COMMON, - D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + ID3D12GraphicsCommandList1Ptr cmd = GetCommandBuffer(); + Reset(cmd); - blitToSwap(cmd, passes[i].mainRT, bb, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB); + ID3D12ResourcePtr bb = StartUsingBackbuffer(cmd, D3D12_RESOURCE_STATE_RENDER_TARGET); - ResourceBarrier(cmd, passes[i].mainRT, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, - D3D12_RESOURCE_STATE_COMMON); + if(bbBlitSource != NULL) + { + ResourceBarrier(cmd, bbBlitSource, D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + + blitToSwap(cmd, bbBlitSource, bb, DXGI_FORMAT_R8G8B8A8_UNORM); + + ResourceBarrier(cmd, bbBlitSource, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, + D3D12_RESOURCE_STATE_COMMON); + } + + FinishUsingBackbuffer(cmd, D3D12_RESOURCE_STATE_RENDER_TARGET); + + cmd->Close(); + cmds.push_back(cmd); } - FinishUsingBackbuffer(cmd, D3D12_RESOURCE_STATE_RENDER_TARGET); - cmd->Close(); - - Submit({cmd}); + Submit(cmds); Present(); } diff --git a/util/test/demos/d3d12/d3d12_test.cpp b/util/test/demos/d3d12/d3d12_test.cpp index 797281ed0..e35b4bcd5 100644 --- a/util/test/demos/d3d12/d3d12_test.cpp +++ b/util/test/demos/d3d12/d3d12_test.cpp @@ -81,6 +81,7 @@ struct Capabilities D3D12_FEATURE_DATA_D3D12_OPTIONS5 opts5 = {}; D3D12_FEATURE_DATA_D3D12_OPTIONS6 opts6 = {}; D3D12_FEATURE_DATA_D3D12_OPTIONS7 opts7 = {}; + D3D12_FEATURE_DATA_D3D12_OPTIONS19 opts19 = {}; D3D_SHADER_MODEL sm = D3D_SHADER_MODEL_5_1; } caps; @@ -386,6 +387,7 @@ void D3D12GraphicsTest::Prepare(int argc, char **argv) tmpdev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS5, &caps.opts5, sizeof(caps.opts5)); tmpdev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS6, &caps.opts6, sizeof(caps.opts6)); tmpdev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS7, &caps.opts7, sizeof(caps.opts7)); + tmpdev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS19, &caps.opts19, sizeof(caps.opts19)); D3D12_FEATURE_DATA_SHADER_MODEL oShaderModel = {}; oShaderModel.HighestShaderModel = D3D_SHADER_MODEL_6_7; while(oShaderModel.HighestShaderModel >= D3D_SHADER_MODEL_6_0) @@ -430,6 +432,7 @@ void D3D12GraphicsTest::Prepare(int argc, char **argv) opts5 = caps.opts5; opts6 = caps.opts6; opts7 = caps.opts7; + opts19 = caps.opts19; for(int i = 0; i < argc; i++) { @@ -594,7 +597,7 @@ void D3D12GraphicsTest::PostDeviceCreate() m_RTV->SetName(L"RTV heap"); - desc.NumDescriptors = 16; + desc.NumDescriptors = 128; desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; CHECK_HR(dev->CreateDescriptorHeap(&desc, __uuidof(ID3D12DescriptorHeap), (void **)&m_DSV)); diff --git a/util/test/demos/d3d12/d3d12_test.h b/util/test/demos/d3d12/d3d12_test.h index 1283351e1..f2a90e52d 100644 --- a/util/test/demos/d3d12/d3d12_test.h +++ b/util/test/demos/d3d12/d3d12_test.h @@ -268,6 +268,7 @@ struct D3D12GraphicsTest : public GraphicsTest D3D12_FEATURE_DATA_D3D12_OPTIONS5 opts5 = {}; D3D12_FEATURE_DATA_D3D12_OPTIONS6 opts6 = {}; D3D12_FEATURE_DATA_D3D12_OPTIONS7 opts7 = {}; + D3D12_FEATURE_DATA_D3D12_OPTIONS19 opts19 = {}; D3D_SHADER_MODEL m_HighestShaderModel = D3D_SHADER_MODEL_5_1; ID3D12FencePtr m_GPUSyncFence; diff --git a/util/test/tests/D3D12/D3D12_Pixel_History.py b/util/test/tests/D3D12/D3D12_Pixel_History.py index 55b54684d..6938b6f11 100644 --- a/util/test/tests/D3D12/D3D12_Pixel_History.py +++ b/util/test/tests/D3D12/D3D12_Pixel_History.py @@ -1,582 +1,5 @@ -import renderdoc as rd import rdtest -from typing import List - -def value_selector(x): return x.floatValue -def passed(x): return x.Passed() -def event_id(x): return x.eventId -def culled(x): return x.backfaceCulled -def depth_test_failed(x): return x.depthTestFailed -def depth_clipped(x): return x.depthClipped -def depth_bounds_failed(x): return x.depthBoundsFailed -def scissor_clipped(x): return x.scissorClipped -def stencil_test_failed(x): return x.stencilTestFailed -def shader_discarded(x): return x.shaderDiscarded - -def get_shader_out_color(x): return value_selector(x.shaderOut.col) -def get_shader_out_depth(x): return x.shaderOut.depth - -def get_pre_mod_color(x): return value_selector(x.preMod.col) -def get_pre_mod_depth(x): return x.preMod.depth - -def get_post_mod_color(x): return value_selector(x.postMod.col) -def get_post_mod_depth(x): return x.postMod.depth -def get_post_mod_stencil(x): return x.postMod.stencil -def unknown_post_mod_stencil(x): return x.postMod.stencil == -1 or x.postMod.stencil == -2 - -def unknown_stencil(x): return x == -1 or x == -2 -def primitive_id(x): return x.primitiveID -def unboundPS(x): return x.unboundPS - -class D3D12_Pixel_History(rdtest.TestCase): +class D3D12_Pixel_History(rdtest.Pixel_History): demos_test_name = 'D3D12_Pixel_History' - demos_frame_cap = 5 - - def check_capture(self): - apiprops: rd.APIProperties = self.controller.GetAPIProperties() - - if not apiprops.pixelHistory: - rdtest.log.print("D3D12 pixel history not tested") - return - - # Disabling SM6.6 test as the test setup is not doing anything special for it yet - tests = ["SM5.1", "SM6.0"] #, "SM6.6"] - for t in tests: - rdtest.log.print("Testing " + t) - - self.is_depth = False - rdtest.log.print("Testing primary") - self.primary_test("Begin " + t) - rdtest.log.print("Testing secondary") - self.secondary_cmd_test("Begin " + t) - - self.is_depth = True - rdtest.log.print("Testing depth") - self.depth_target_test("Begin " + t) - - self.is_depth = False - rdtest.log.print("Testing MSAA") - self.multisampled_image_test("Begin " + t) - - def primary_test(self, begin_name: str): - begin_renderpass_action = self.find_action(begin_name) - if begin_renderpass_action is None: - rdtest.log.print("Test not found") - return - - begin_renderpass_eid = begin_renderpass_action.next.eventId - test_marker: rd.ActionDescription = self.find_action("Test Begin", begin_renderpass_eid) - self.controller.SetFrameEvent(test_marker.next.eventId, True) - - pipe: rd.PipeState = self.controller.GetPipelineState() - - rt = pipe.GetOutputTargets()[0] - - tex = rt.resource - tex_details = self.get_texture(tex) - - sub = rd.Subresource() - if tex_details.arraysize > 1: - sub.slice = rt.firstSlice - if tex_details.mips > 1: - sub.mip = rt.firstMip - - depth_write_eid = self.find_action("Depth Write", begin_renderpass_eid).next.eventId - stencil_write_eid = self.find_action("Stencil Write", begin_renderpass_eid).next.eventId - unbound_fs_eid = self.find_action("Unbound Fragment Shader", begin_renderpass_eid).next.eventId - background_eid = self.find_action("Background", begin_renderpass_eid).next.eventId - cull_eid = self.find_action("Cull Front", begin_renderpass_eid).next.eventId - test_eid = self.find_action("Test Begin", begin_renderpass_eid).next.eventId - fixed_scissor_fail_eid = self.find_action("Fixed Scissor Fail", begin_renderpass_eid).next.eventId - fixed_scissor_pass_eid = self.find_action("Fixed Scissor Pass", begin_renderpass_eid).next.eventId - dynamic_stencil_ref_eid = self.find_action("Dynamic Stencil Ref", begin_renderpass_eid).next.eventId - dynamic_stencil_mask_eid = self.find_action("Dynamic Stencil Mask", begin_renderpass_eid).next.eventId - depth_test_eid = self.find_action("Depth Test", begin_renderpass_eid).next.eventId - depth_16bit_test_eid = self.find_action("Depth 16-bit Test", begin_renderpass_eid).next.eventId - depth_bounds_prep_eid = self.find_action("Depth Bounds Prep", begin_renderpass_eid).next.eventId - depth_bounds_clip_eid = self.find_action("Depth Bounds Clip", begin_renderpass_eid).next.eventId - one_thousand_instances_action = self.find_action("1000 Instances", begin_renderpass_eid) - - # For pixel 110, 100, inside the red triangle with stencil value 0x55 - x, y = 110, 100 - rdtest.log.print("Testing pixel {}, {}".format(x, y)) - modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.format.compType) - events = [ - [[event_id, begin_renderpass_eid], [passed, True]], - [[event_id, unbound_fs_eid], [passed, True], [unboundPS, True], [primitive_id, 0], [get_post_mod_stencil, 0x33]], - [[event_id, stencil_write_eid], [passed, True], [primitive_id, 0], [get_post_mod_stencil, 0x55]], - ] - self.check_events(events, modifs, False) - self.check_pixel_value(tex, x, y, value_selector(modifs[-1].postMod.col), sub=sub, cast=rt.format.compType) - - # For pixel 190, 149 inside the red triangle - x, y = 190, 149 - rdtest.log.print("Testing pixel {}, {}".format(x, y)) - modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.format.compType) - events = [ - [[event_id, begin_renderpass_eid], [passed, True]], - [[event_id, unbound_fs_eid], [passed, True], [unboundPS, True], [primitive_id, 0]], - [[event_id, stencil_write_eid], [passed, True]], - [[event_id, background_eid], [depth_test_failed, True], [get_post_mod_color, (1.0, 0.0, 0.0, 1.0)]], - [[event_id, test_eid], [stencil_test_failed, True]], - ] - - self.check_events(events, modifs, False) - self.check_pixel_value(tex, x, y, get_post_mod_color(modifs[-1]), sub=sub, cast=rt.format.compType) - - x, y = 190, 150 - rdtest.log.print("Testing pixel {}, {}".format(x, y)) - modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.format.compType) - events = [ - [[event_id, begin_renderpass_eid], [passed, True]], - [[event_id, depth_write_eid], [passed, True]], - [[event_id, background_eid], [depth_test_failed, True]], - [[event_id, cull_eid], [culled, True]], - [[event_id, test_eid], [depth_test_failed, True]], - ] - self.check_events(events, modifs, False) - self.check_pixel_value(tex, x, y, get_post_mod_color(modifs[-1]), sub=sub, cast=rt.format.compType) - - x, y = 200, 50 - rdtest.log.print("Testing pixel {}, {}".format(x, y)) - modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.format.compType) - events = [ - [[event_id, begin_renderpass_eid], [passed, True]], - [[event_id, background_eid], [passed, True]], - [[event_id, test_eid], [passed, True], [primitive_id, 7]], - ] - self.check_events(events, modifs, False) - self.check_pixel_value(tex, x, y, get_post_mod_color(modifs[-1]), sub=sub, cast=rt.format.compType) - - x, y = 150, 250 - rdtest.log.print("Testing pixel {}, {}".format(x, y)) - modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.format.compType) - events = [ - [[event_id, begin_renderpass_eid], [passed, True]], - [[event_id, background_eid], [shader_discarded, True]], - ] - self.check_events(events, modifs, False) - self.check_pixel_value(tex, x, y, get_post_mod_color(modifs[-1]), sub=sub, cast=rt.format.compType) - - x, y = 330, 145 - rdtest.log.print("Testing pixel {}, {}".format(x, y)) - modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.format.compType) - events = [ - [[event_id, begin_renderpass_eid], [passed, True]], - [[event_id, test_eid], [passed, True], [primitive_id, 3], [get_shader_out_color, (0.0, 0.0, 0.0, 2.75)]], - ] - self.check_events(events, modifs, False) - self.check_pixel_value(tex, x, y, get_post_mod_color(modifs[-1]), sub=sub, cast=rt.format.compType) - - x, y = 340, 145 - rdtest.log.print("Testing pixel {}, {}".format(x, y)) - modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.format.compType) - events = [ - [[event_id, begin_renderpass_eid], [passed, True]], - [[event_id, test_eid], [passed, False], [depth_clipped, True]], - ] - self.check_events(events, modifs, False) - self.check_pixel_value(tex, x, y, get_post_mod_color(modifs[-1]), sub=sub, cast=rt.format.compType) - - x, y = 330, 105 - rdtest.log.print("Testing pixel {}, {}".format(x, y)) - modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.format.compType) - events = [ - [[event_id, begin_renderpass_eid], [passed, True]], - [[event_id, depth_bounds_prep_eid], [passed, True], [primitive_id, 0], [get_shader_out_color, (1.0, 0.0, 0.0, 2.75)]], - [[event_id, depth_bounds_clip_eid], [passed, True], [primitive_id, 0], [get_shader_out_color, (0.0, 1.0, 0.0, 2.75)]], - ] - self.check_events(events, modifs, False) - self.check_pixel_value(tex, x, y, get_post_mod_color(modifs[-1]), sub=sub, cast=rt.format.compType) - - x, y = 320, 105 - rdtest.log.print("Testing pixel {}, {}".format(x, y)) - modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.format.compType) - events = [ - [[event_id, begin_renderpass_eid], [passed, True]], - [[event_id, depth_bounds_prep_eid], [passed, True], [primitive_id, 0], [get_shader_out_color, (1.0, 0.0, 0.0, 2.75)]], - [[event_id, depth_bounds_clip_eid], [passed, False], [depth_bounds_failed, True]], - ] - self.check_events(events, modifs, False) - self.check_pixel_value(tex, x, y, get_post_mod_color(modifs[-1]), sub=sub, cast=rt.format.compType) - - x, y = 345, 105 - rdtest.log.print("Testing pixel {}, {}".format(x, y)) - modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.format.compType) - events = [ - [[event_id, begin_renderpass_eid], [passed, True]], - [[event_id, depth_bounds_prep_eid], [passed, True], [primitive_id, 0], [get_shader_out_color, (1.0, 0.0, 0.0, 2.75)]], - [[event_id, depth_bounds_clip_eid], [passed, False], [depth_bounds_failed, True]], - ] - self.check_events(events, modifs, False) - self.check_pixel_value(tex, x, y, get_post_mod_color(modifs[-1]), sub=sub, cast=rt.format.compType) - - rdtest.log.print("Testing dynamic state pipelines") - self.controller.SetFrameEvent(dynamic_stencil_mask_eid, True) - - x, y = 100, 250 - rdtest.log.print("Testing pixel {}, {}".format(x, y)) - modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.format.compType) - events = [ - [[event_id, begin_renderpass_eid], [passed, True]], - [[event_id, background_eid], [passed, True]], - [[event_id, fixed_scissor_fail_eid], [scissor_clipped, True]], - [[event_id, fixed_scissor_pass_eid], [passed, True], [get_shader_out_color, (0.0, 1.0, 0.0, 2.75)], - [get_post_mod_color, (0.0, 1.0, 0.0, 1.0)]], - [[event_id, dynamic_stencil_ref_eid], [passed, True], [get_shader_out_color, (0.0, 0.0, 1.0, 2.75)], - [get_post_mod_color, (0.0, 0.0, 1.0, 1.0)]], - [[event_id, dynamic_stencil_mask_eid], [passed, True], [get_shader_out_color, (0.0, 1.0, 1.0, 2.75)], - [get_post_mod_color, (0.0, 1.0, 1.0, 1.0)]], - ] - self.check_events(events, modifs, False) - self.check_pixel_value(tex, x, y, get_post_mod_color(modifs[-1]), sub=sub, cast=rt.format.compType) - - rdtest.log.print("Testing depth test for per fragment reporting") - self.controller.SetFrameEvent(depth_test_eid, True) - - x, y = 275, 260 - rdtest.log.print("Testing pixel {}, {}".format(x, y)) - modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.format.compType) - events = [ - [[event_id, begin_renderpass_eid], [passed, True]], - [[event_id, background_eid], [passed, True]], - [[event_id, depth_test_eid], [primitive_id, 0], [depth_test_failed, True], - [get_shader_out_color, (1.0, 1.0, 1.0, 2.75)], [get_shader_out_depth, 0.97], [get_post_mod_color, (1.0, 0.0, 1.0, 1.0)], - [get_post_mod_depth, 0.95], [unknown_post_mod_stencil, True]], - [[event_id, depth_test_eid], [primitive_id, 1], [depth_test_failed, False], - [get_shader_out_color, (1.0, 1.0, 0.0, 2.75)], [get_shader_out_depth, 0.20], [get_post_mod_color, (1.0, 1.0, 0.0, 1.0)], - [get_post_mod_depth, 0.20]], - [[event_id, depth_test_eid], [primitive_id, 2], [depth_test_failed, True], - [get_shader_out_color, (1.0, 0.0, 0.0, 2.75)], [get_shader_out_depth, 0.30], [get_post_mod_color, (1.0, 1.0, 0.0, 1.0)], - [get_post_mod_depth, 0.20]], - [[event_id, depth_test_eid], [primitive_id, 3], [depth_test_failed, False], - [get_shader_out_color, (0.0, 0.0, 1.0, 2.75)], [get_shader_out_depth, 0.10], [get_post_mod_color, (0.0, 0.0, 1.0, 1.0)], - [get_post_mod_depth, 0.10]], - [[event_id, depth_test_eid], [primitive_id, 4], [depth_test_failed, False], [depth_bounds_failed, True], - [get_shader_out_color, (1.0, 1.0, 1.0, 2.75)], [get_shader_out_depth, 0.05], [get_post_mod_color, (0.0, 0.0, 1.0, 1.0)], - [get_post_mod_depth, 0.10]], - ] - self.check_events(events, modifs, False) - self.check_pixel_value(tex, x, y, get_post_mod_color(modifs[-1]), sub=sub, cast=rt.format.compType) - - # For pixel 70, 100 inside the yellow triangle rendered with 16-bit depth - rdtest.log.print("Testing 16-bit depth format") - self.controller.SetFrameEvent(depth_16bit_test_eid, True) - x, y = 70, 100 - rdtest.log.print("Testing pixel {}, {}".format(x, y)) - modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.format.compType) - events = [ - [[event_id, begin_renderpass_eid], [passed, True]], - [[event_id, depth_16bit_test_eid], [primitive_id, 0], [depth_test_failed, False], - [get_shader_out_color, (1.0, 1.0, 0.0, 2.75)], [get_shader_out_depth, 0.33], [get_post_mod_color, (1.0, 1.0, 0.0, 1.0)], - [get_post_mod_depth, 0.33]], - ] - self.check_events(events, modifs, False) - self.check_pixel_value(tex, x, y, get_post_mod_color(modifs[-1]), sub=sub, cast=rt.format.compType) - - # For pixel 60, 130 inside the light green triangle which is 1000 draws of 1 instance of 1 triangle - rdtest.log.print("Testing Lots of Drawcalls") - self.controller.SetFrameEvent(one_thousand_instances_action.eventId, True) - x, y = 60, 130 - rdtest.log.print("Testing pixel {}, {}".format(x, y)) - modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.format.compType) - self.check_pixel_value(tex, x, y, get_post_mod_color(modifs[-1]), sub=sub, cast=rt.format.compType) - countEvents = 1 + 1000 - self.check(len(modifs) == countEvents, "Expected {} events, got {}".format(countEvents, len(modifs))) - self.check_modifs_consistent(modifs) - - # For pixel 60, 50 inside the orange triangle which is 1 draws of 1000 instances of 1 triangle - rdtest.log.print("Testing Lots of Instances") - self.controller.SetFrameEvent(one_thousand_instances_action.next.eventId, True) - x, y = 60, 50 - rdtest.log.print("Testing pixel {}, {}".format(x, y)) - modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.format.compType) - self.check_pixel_value(tex, x, y, get_post_mod_color(modifs[-1]), sub=sub, cast=rt.format.compType) - countEvents = 1 + 255 - self.check(len(modifs) == countEvents, "Expected {} events, got {}".format(countEvents, len(modifs))) - self.check_modifs_consistent(modifs) - - def multisampled_image_test(self, pass_name: str): - begin_pass_action = self.find_action(pass_name) - if begin_pass_action is None: - rdtest.log.print("Test not found") - return - - pass_start_eid = begin_pass_action.next.eventId - - test_marker: rd.ActionDescription = self.find_action("Multisampled: test", pass_start_eid) - action_eid = test_marker.next.eventId - self.controller.SetFrameEvent(action_eid, True) - - pipe: rd.PipeState = self.controller.GetPipelineState() - rt = pipe.GetOutputTargets()[0] - - if self.is_depth: - rt = pipe.GetDepthTarget() - - sub = rd.Subresource() - tex = rt.resource - tex_details = self.get_texture(tex) - if tex_details.arraysize > 1: - sub.slice = rt.firstSlice - - beg_renderpass_eid = self.find_action("Begin MSAA", pass_start_eid).next.eventId - - x, y = 140, 130 - sub.sample = 1 - rdtest.log.print("Testing pixel {}, {} at sample {}".format(x, y, sub.sample)) - modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.format.compType) - - events = [ - [[event_id, beg_renderpass_eid], [passed, True]], - [[event_id, action_eid], [passed, True], [primitive_id, 0], [get_pre_mod_depth, 0.0], [get_shader_out_depth, 0.9], - [get_post_mod_depth, 0.9]], - [[event_id, action_eid], [passed, True], [primitive_id, 1], [get_shader_out_depth, 0.95], [get_post_mod_depth, 0.95]], - ] - - if not self.is_depth: - events[0] += [[get_post_mod_color, (0.0, 1.0, 0.0, 1.0)]] - events[1] += [[get_shader_out_color, (1.0, 0.0, 1.0, 2.75)], [get_post_mod_color, (1.0, 0.0, 1.0, 1.0)]] - events[2] += [[get_shader_out_color, (0.0, 0.0, 1.0, 2.75)], [get_post_mod_color, (0.0, 0.0, 1.0, 1.0)]] - - self.check_events(events, modifs, True) - - if self.is_depth: - self.check_pixel_value(tex, x, y, [modifs[-1].postMod.depth, float(modifs[-1].postMod.stencil)/255.0, 0.0, 1.0], sub=sub, cast=rt.format.compType) - else: - self.check_pixel_value(tex, x, y, get_post_mod_color(modifs[-1]), sub=sub, cast=rt.format.compType) - - sub.sample = 2 - rdtest.log.print("Testing pixel {}, {} at sample {}".format(x, y, sub.sample)) - modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.format.compType) - events = [ - [[event_id, beg_renderpass_eid], [passed, True]], - [[event_id, action_eid], [passed, True], [primitive_id, 0], [get_pre_mod_depth, 0.0], [get_shader_out_depth, 0.9], - [get_post_mod_depth, 0.9]], - [[event_id, action_eid], [passed, True], [primitive_id, 1], [get_shader_out_depth, 0.95], [get_post_mod_depth, 0.95]], - ] - - if not self.is_depth: - events[0] += [[get_post_mod_color, (0.0, 1.0, 0.0, 1.0)]] - events[1] += [[get_shader_out_color, (1.0, 0.0, 1.0, 2.75)], [get_post_mod_color, (1.0, 0.0, 1.0, 1.0)]] - events[2] += [[get_shader_out_color, (0.0, 1.0, 1.0, 2.75)], [get_post_mod_color, (0.0, 1.0, 1.0, 1.0)]] - - self.check_events(events, modifs, True) - - if self.is_depth: - self.check_pixel_value(tex, x, y, - [modifs[-1].postMod.depth, float(modifs[-1].postMod.stencil) / 255.0, 0.0, 1.0], - sub=sub, cast=rt.format.compType) - else: - self.check_pixel_value(tex, x, y, get_post_mod_color(modifs[-1]), sub=sub, cast=rt.format.compType) - - def secondary_cmd_test(self, pass_name: str): - begin_pass_action = self.find_action(pass_name) - if begin_pass_action is None: - rdtest.log.print("Test not found") - return - - pass_start_eid = begin_pass_action.next.eventId - - secondary_marker: rd.ActionDescription = self.find_action("Secondary: red and blue", pass_start_eid) - self.controller.SetFrameEvent(secondary_marker.next.eventId, True) - - pipe: rd.PipeState = self.controller.GetPipelineState() - rt = pipe.GetOutputTargets()[0] - sub = rd.Subresource() - tex = rt.resource - tex_details = self.get_texture(tex) - if tex_details.arraysize > 1: - sub.slice = rt.firstSlice - if tex_details.mips > 1: - sub.mip = rt.firstMip - - sec_beg_renderpass_eid = self.find_action("Begin RenderPass Secondary", pass_start_eid).next.eventId - background_eid = self.find_action("Secondary: background", pass_start_eid).next.eventId - culled_eid = self.find_action("Secondary: culled", pass_start_eid).next.eventId - sec_red_and_blue = self.find_action("Secondary: red and blue", pass_start_eid).next.eventId - - # Test culling - x, y = 70, 40 - rdtest.log.print("Testing pixel {}, {}".format(x, y)) - modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.format.compType) - events = [ - [[event_id, sec_beg_renderpass_eid], [passed, True], [get_post_mod_color, (0.0, 1.0, 0.0, 1.0)]], - [[event_id, background_eid], [passed, True], [get_pre_mod_color, (0.0, 1.0, 0.0, 1.0)]], - [[event_id, culled_eid], [passed, False], [culled, True]], - ] - self.check_events(events, modifs, True) - self.check_pixel_value(tex, x, y, get_post_mod_color(modifs[-1]), sub=sub, cast=rt.format.compType) - - # Blue triangle - x, y = 40, 40 - rdtest.log.print("Testing pixel {}, {}".format(x, y)) - modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.format.compType) - events = [ - [[event_id, sec_beg_renderpass_eid], [passed, True], [get_post_mod_color, (0.0, 1.0, 0.0, 1.0)]], - # This is the first event in the command buffer, should have pre-mod - [[event_id, background_eid], [passed, True], [get_pre_mod_color, (0.0, 1.0, 0.0, 1.0)]], - # This is the last event in the command buffer, should have post-mod - [[event_id, sec_red_and_blue], [passed, True], [get_post_mod_color, (0.0, 0.0, 1.0, 1.0)]], - ] - self.check_events(events, modifs, True) - self.check_pixel_value(tex, x, y, get_post_mod_color(modifs[-1]), sub=sub, cast=rt.format.compType) - - # Didn't get post mod for background_eid - self.controller.SetFrameEvent(background_eid, True) - modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.format.compType) - events = [ - [[event_id, sec_beg_renderpass_eid]], - # The only event, should have both pre and post mod. - [[event_id, background_eid], [passed, True], [get_pre_mod_color, (0.0, 1.0, 0.0, 1.0)], [get_post_mod_color, (1.0, 0.0, 1.0, 1.0)]], - ] - self.check_events(events, modifs, True) - self.check_pixel_value(tex, x, y, get_post_mod_color(modifs[-1]), sub=sub, cast=rt.format.compType) - - def depth_target_test(self, begin_name: str): - begin_pass_action = self.find_action(begin_name) - if begin_pass_action is None: - rdtest.log.print("Test not found") - return - - # Advance one more than the color test since DSV clear is a separate event than RT clear - begin_renderpass_eid = begin_pass_action.next.next.eventId - - test_marker: rd.ActionDescription = self.find_action("Test Begin", begin_renderpass_eid) - - self.controller.SetFrameEvent(test_marker.next.eventId, True) - - pipe: rd.PipeState = self.controller.GetPipelineState() - - rt = pipe.GetDepthTarget() - - tex = rt.resource - tex_details = self.get_texture(tex) - - sub = rd.Subresource() - if tex_details.arraysize > 1: - sub.slice = rt.firstSlice - if tex_details.mips > 1: - sub.mip = rt.firstMip - - stencil_write_eid = self.find_action("Stencil Write", begin_renderpass_eid).next.eventId - unbound_fs_eid = self.find_action("Unbound Fragment Shader", begin_renderpass_eid).next.eventId - background_eid = self.find_action("Background", begin_renderpass_eid).next.eventId - clear_depth_16bit_eid = self.find_action("Clear Depth 16-bit", begin_renderpass_eid).next.eventId - depth_16bit_test_eid = self.find_action("Depth 16-bit Test", begin_renderpass_eid).next.eventId - test_eid = self.find_action("Test Begin", begin_renderpass_eid).next.eventId - - x, y = 200, 190 - rdtest.log.print("Testing pixel {}, {}".format(x, y)) - modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.format.compType) - events = [ - [[event_id, begin_renderpass_eid], [passed, True], [get_post_mod_depth, -1.0]], - [[event_id, background_eid], [passed, True], [primitive_id, 0], [get_pre_mod_depth, 1.0], [get_post_mod_depth, 0.95]], - [[event_id, test_eid], [passed, True], [depth_test_failed, False], [primitive_id, 0], [get_shader_out_depth, 0.5], [get_post_mod_depth, 0.5]], - [[event_id, test_eid], [passed, False], [depth_test_failed, True], [primitive_id, 1], [get_shader_out_depth, 0.6], [get_post_mod_depth, 0.5]], - ] - self.check_events(events, modifs, False) - - # For pixel 110, 100, inside the red triangle with stencil value 0x55 - x, y = 110, 100 - rdtest.log.print("Testing pixel {}, {}".format(x, y)) - modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.format.compType) - events = [ - [[event_id, begin_renderpass_eid], [passed, True]], - [[event_id, unbound_fs_eid], [passed, True], [unboundPS, True], [primitive_id, 0], [get_post_mod_stencil, 0x33]], - [[event_id, stencil_write_eid], [passed, True], [primitive_id, 0], [get_post_mod_stencil, 0x55]], - ] - self.check_events(events, modifs, False) - - # For pixel 70, 100 inside the yellow triangle rendered with 16-bit depth - rdtest.log.print("Testing 16-bit depth format") - self.controller.SetFrameEvent(depth_16bit_test_eid, True) - pipe: rd.PipeState = self.controller.GetPipelineState() - - rt = pipe.GetDepthTarget() - - tex = rt.resource - tex_details = self.get_texture(tex) - - sub = rd.Subresource() - if tex_details.arraysize > 1: - sub.slice = rt.firstSlice - if tex_details.mips > 1: - sub.mip = rt.firstMip - - x, y = 70, 100 - rdtest.log.print("Testing pixel {}, {}".format(x, y)) - modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.format.compType) - events = [ - [[event_id, clear_depth_16bit_eid], [passed, True]], - [[event_id, depth_16bit_test_eid], [passed, True], [primitive_id, 0], [depth_test_failed, False], - [get_shader_out_depth, 0.33], [get_post_mod_depth, 0.33]], - ] - self.check_events(events, modifs, False) - - def check_events(self, events, modifs, hasSecondary): - self.check(len(modifs) == len(events), "Expected {} events, got {}".format(len(events), len(modifs))) - # Check for consistency first. For secondary command buffers, - # might not have all information, so don't check for consistency - if not hasSecondary: - self.check_modifs_consistent(modifs) - for i in range(len(modifs)): - for c in range(len(events[i])): - expected = events[i][c][1] - actual = events[i][c][0](modifs[i]) - if not rdtest.value_compare(actual, expected, eps=1.0/256.0): - raise rdtest.TestFailureException( - "eventId {}, primitiveID {}: testing {} expected {}, got {}".format(modifs[i].eventId, modifs[i].primitiveID, - events[i][c][0].__name__, - expected, - actual)) - - def check_modifs_consistent(self, modifs): - # postmod of each should match premod of the next - for i in range(len(modifs) - 1): - a = get_post_mod_color(modifs[i]) - b = get_pre_mod_color(modifs[i + 1]) - - # A fragment event : postMod.stencil should be unknown - if modifs[i].eventId == modifs[i+1].eventId: - if not unknown_stencil(modifs[i].postMod.stencil): - raise rdtest.TestFailureException( - "postmod stencil at {} primitive {}: {} is not unknown".format(modifs[i].eventId, - modifs[i].primitiveID, - modifs[i].postMod.stencil)) - - if self.is_depth: - a = (modifs[i].postMod.depth, modifs[i].postMod.stencil) - b = (modifs[i + 1].preMod.depth, modifs[i + 1].preMod.stencil) - # ignore if postmod depth data is unknwon - if a[0] == -1 and a[1] == -1: - continue - - if a != b: - raise rdtest.TestFailureException( - "postmod at {} primitive {}: {} doesn't match premod at {} primitive {}: {}".format(modifs[i].eventId, - modifs[i].primitiveID, - a, - modifs[i + 1].eventId, - modifs[i + 1].primitiveID, - b)) - - # Check that if the test failed, its postmod is the same as premod - for i in range(len(modifs)): - if not modifs[i].Passed(): - a = get_pre_mod_color(modifs[i]) - b = get_post_mod_color(modifs[i]) - - if self.is_depth: - a = (modifs[i].preMod.depth, modifs[i].preMod.stencil) - b = (modifs[i].postMod.depth, modifs[i].postMod.stencil) - - if a[1] == -2 or b[2] == -2: - a = (a[0], -2) - b = (b[0], -2) - - if not rdtest.value_compare(a, b): - raise rdtest.TestFailureException( - "postmod at {} primitive {}: {} doesn't match premod: {}".format(modifs[i].eventId, - modifs[i].primitiveID, b, a)) + internal = False