Add test of D3D11 pixel history

* This doesn't test every edge case, but it is a simple smoke test that ensures
  any format can at least get consistent accurate results out.
* Further work is needed to test the different failures, overdraws, primitive
  IDs, and all the other specific checks in the history.
This commit is contained in:
baldurk
2020-03-05 19:35:45 +00:00
parent 98af55d513
commit 2250e44ae6
9 changed files with 851 additions and 48 deletions
+2 -2
View File
@@ -738,7 +738,7 @@ D3D11ViewCreator::operator ID3D11ShaderResourceViewPtr()
if(desc.srv.ViewDimension == D3D11_SRV_DIMENSION_BUFFER)
{
D3D11_BUFFER_DESC bufdesc;
((ID3D11Buffer *)m_Res)->GetDesc(&bufdesc);
((ID3D11BufferPtr)m_Res)->GetDesc(&bufdesc);
if(bufdesc.MiscFlags & D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS)
{
@@ -772,7 +772,7 @@ D3D11ViewCreator::operator ID3D11UnorderedAccessViewPtr()
if(desc.uav.ViewDimension == D3D11_UAV_DIMENSION_BUFFER)
{
D3D11_BUFFER_DESC bufdesc;
((ID3D11Buffer *)m_Res)->GetDesc(&bufdesc);
((ID3D11BufferPtr)m_Res)->GetDesc(&bufdesc);
if(bufdesc.MiscFlags & D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS)
desc.uav.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
+4 -1
View File
@@ -161,6 +161,9 @@ public:
operator ID3D11Texture2DPtr() const;
operator ID3D11Texture3DPtr() const;
ID3D11Texture1DPtr Tex1D() const { return (ID3D11Texture1DPtr) * this; };
ID3D11Texture2DPtr Tex2D() const { return (ID3D11Texture2DPtr) * this; };
ID3D11Texture3DPtr Tex3D() const { return (ID3D11Texture3DPtr) * this; };
protected:
D3D11GraphicsTest *m_Test;
@@ -271,7 +274,7 @@ private:
void SetupDescriptors();
D3D11GraphicsTest *m_Test;
ID3D11Resource *m_Res;
ID3D11ResourcePtr m_Res;
ViewType m_ViewType;
ResourceType m_ResType;
@@ -0,0 +1,736 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2019-2020 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#include "d3d11_test.h"
const std::string dxgiFormatName[] = {
"DXGI_FORMAT_UNKNOWN",
"DXGI_FORMAT_R32G32B32A32_TYPELESS",
"DXGI_FORMAT_R32G32B32A32_FLOAT",
"DXGI_FORMAT_R32G32B32A32_UINT",
"DXGI_FORMAT_R32G32B32A32_SINT",
"DXGI_FORMAT_R32G32B32_TYPELESS",
"DXGI_FORMAT_R32G32B32_FLOAT",
"DXGI_FORMAT_R32G32B32_UINT",
"DXGI_FORMAT_R32G32B32_SINT",
"DXGI_FORMAT_R16G16B16A16_TYPELESS",
"DXGI_FORMAT_R16G16B16A16_FLOAT",
"DXGI_FORMAT_R16G16B16A16_UNORM",
"DXGI_FORMAT_R16G16B16A16_UINT",
"DXGI_FORMAT_R16G16B16A16_SNORM",
"DXGI_FORMAT_R16G16B16A16_SINT",
"DXGI_FORMAT_R32G32_TYPELESS",
"DXGI_FORMAT_R32G32_FLOAT",
"DXGI_FORMAT_R32G32_UINT",
"DXGI_FORMAT_R32G32_SINT",
"DXGI_FORMAT_R32G8X24_TYPELESS",
"DXGI_FORMAT_D32_FLOAT_S8X24_UINT",
"DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS",
"DXGI_FORMAT_X32_TYPELESS_G8X24_UINT",
"DXGI_FORMAT_R10G10B10A2_TYPELESS",
"DXGI_FORMAT_R10G10B10A2_UNORM",
"DXGI_FORMAT_R10G10B10A2_UINT",
"DXGI_FORMAT_R11G11B10_FLOAT",
"DXGI_FORMAT_R8G8B8A8_TYPELESS",
"DXGI_FORMAT_R8G8B8A8_UNORM",
"DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
"DXGI_FORMAT_R8G8B8A8_UINT",
"DXGI_FORMAT_R8G8B8A8_SNORM",
"DXGI_FORMAT_R8G8B8A8_SINT",
"DXGI_FORMAT_R16G16_TYPELESS",
"DXGI_FORMAT_R16G16_FLOAT",
"DXGI_FORMAT_R16G16_UNORM",
"DXGI_FORMAT_R16G16_UINT",
"DXGI_FORMAT_R16G16_SNORM",
"DXGI_FORMAT_R16G16_SINT",
"DXGI_FORMAT_R32_TYPELESS",
"DXGI_FORMAT_D32_FLOAT",
"DXGI_FORMAT_R32_FLOAT",
"DXGI_FORMAT_R32_UINT",
"DXGI_FORMAT_R32_SINT",
"DXGI_FORMAT_R24G8_TYPELESS",
"DXGI_FORMAT_D24_UNORM_S8_UINT",
"DXGI_FORMAT_R24_UNORM_X8_TYPELESS",
"DXGI_FORMAT_X24_TYPELESS_G8_UINT",
"DXGI_FORMAT_R8G8_TYPELESS",
"DXGI_FORMAT_R8G8_UNORM",
"DXGI_FORMAT_R8G8_UINT",
"DXGI_FORMAT_R8G8_SNORM",
"DXGI_FORMAT_R8G8_SINT",
"DXGI_FORMAT_R16_TYPELESS",
"DXGI_FORMAT_R16_FLOAT",
"DXGI_FORMAT_D16_UNORM",
"DXGI_FORMAT_R16_UNORM",
"DXGI_FORMAT_R16_UINT",
"DXGI_FORMAT_R16_SNORM",
"DXGI_FORMAT_R16_SINT",
"DXGI_FORMAT_R8_TYPELESS",
"DXGI_FORMAT_R8_UNORM",
"DXGI_FORMAT_R8_UINT",
"DXGI_FORMAT_R8_SNORM",
"DXGI_FORMAT_R8_SINT",
"DXGI_FORMAT_A8_UNORM",
"DXGI_FORMAT_R1_UNORM",
"DXGI_FORMAT_R9G9B9E5_SHAREDEXP",
"DXGI_FORMAT_R8G8_B8G8_UNORM",
"DXGI_FORMAT_G8R8_G8B8_UNORM",
"DXGI_FORMAT_BC1_TYPELESS",
"DXGI_FORMAT_BC1_UNORM",
"DXGI_FORMAT_BC1_UNORM_SRGB",
"DXGI_FORMAT_BC2_TYPELESS",
"DXGI_FORMAT_BC2_UNORM",
"DXGI_FORMAT_BC2_UNORM_SRGB",
"DXGI_FORMAT_BC3_TYPELESS",
"DXGI_FORMAT_BC3_UNORM",
"DXGI_FORMAT_BC3_UNORM_SRGB",
"DXGI_FORMAT_BC4_TYPELESS",
"DXGI_FORMAT_BC4_UNORM",
"DXGI_FORMAT_BC4_SNORM",
"DXGI_FORMAT_BC5_TYPELESS",
"DXGI_FORMAT_BC5_UNORM",
"DXGI_FORMAT_BC5_SNORM",
"DXGI_FORMAT_B5G6R5_UNORM",
"DXGI_FORMAT_B5G5R5A1_UNORM",
"DXGI_FORMAT_B8G8R8A8_UNORM",
"DXGI_FORMAT_B8G8R8X8_UNORM",
"DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM",
"DXGI_FORMAT_B8G8R8A8_TYPELESS",
"DXGI_FORMAT_B8G8R8A8_UNORM_SRGB",
"DXGI_FORMAT_B8G8R8X8_TYPELESS",
"DXGI_FORMAT_B8G8R8X8_UNORM_SRGB",
"DXGI_FORMAT_BC6H_TYPELESS",
"DXGI_FORMAT_BC6H_UF16",
"DXGI_FORMAT_BC6H_SF16",
"DXGI_FORMAT_BC7_TYPELESS",
"DXGI_FORMAT_BC7_UNORM",
"DXGI_FORMAT_BC7_UNORM_SRGB",
"DXGI_FORMAT_AYUV",
"DXGI_FORMAT_Y410",
"DXGI_FORMAT_Y416",
"DXGI_FORMAT_NV12",
"DXGI_FORMAT_P010",
"DXGI_FORMAT_P016",
"DXGI_FORMAT_420_OPAQUE",
"DXGI_FORMAT_YUY2",
"DXGI_FORMAT_Y210",
"DXGI_FORMAT_Y216",
"DXGI_FORMAT_NV11",
"DXGI_FORMAT_AI44",
"DXGI_FORMAT_IA44",
"DXGI_FORMAT_P8",
"DXGI_FORMAT_A8P8",
"DXGI_FORMAT_B4G4R4A4_UNORM",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"DXGI_FORMAT_P208",
"DXGI_FORMAT_V208",
"DXGI_FORMAT_V408",
};
RD_TEST(D3D11_Pixel_History_Zoo, D3D11GraphicsTest)
{
static constexpr const char *Description =
"Checks pixel history on different formats, scenarios, overdraw, etc.";
bool IsUIntFormat(DXGI_FORMAT f)
{
switch(f)
{
case DXGI_FORMAT_R32G32B32A32_UINT:
case DXGI_FORMAT_R32G32B32_UINT:
case DXGI_FORMAT_R16G16B16A16_UINT:
case DXGI_FORMAT_R32G32_UINT:
case DXGI_FORMAT_R10G10B10A2_UINT:
case DXGI_FORMAT_R8G8B8A8_UINT:
case DXGI_FORMAT_R16G16_UINT:
case DXGI_FORMAT_R32_UINT:
case DXGI_FORMAT_R8G8_UINT:
case DXGI_FORMAT_R16_UINT:
case DXGI_FORMAT_R8_UINT: return true;
default: break;
}
return false;
}
bool IsSIntFormat(DXGI_FORMAT f)
{
switch(f)
{
case DXGI_FORMAT_R32G32B32A32_SINT:
case DXGI_FORMAT_R32G32B32_SINT:
case DXGI_FORMAT_R16G16B16A16_SINT:
case DXGI_FORMAT_R32G32_SINT:
case DXGI_FORMAT_R8G8B8A8_SINT:
case DXGI_FORMAT_R16G16_SINT:
case DXGI_FORMAT_R32_SINT:
case DXGI_FORMAT_R8G8_SINT:
case DXGI_FORMAT_R16_SINT:
case DXGI_FORMAT_R8_SINT: return true;
default: break;
}
return false;
}
DXGI_FORMAT GetTypelessFormat(DXGI_FORMAT f)
{
switch(f)
{
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
case DXGI_FORMAT_R32G32B32A32_FLOAT:
case DXGI_FORMAT_R32G32B32A32_UINT:
case DXGI_FORMAT_R32G32B32A32_SINT: return DXGI_FORMAT_R32G32B32A32_TYPELESS;
case DXGI_FORMAT_R32G32B32_TYPELESS:
case DXGI_FORMAT_R32G32B32_FLOAT:
case DXGI_FORMAT_R32G32B32_UINT:
case DXGI_FORMAT_R32G32B32_SINT: return DXGI_FORMAT_R32G32B32_TYPELESS;
case DXGI_FORMAT_R16G16B16A16_TYPELESS:
case DXGI_FORMAT_R16G16B16A16_FLOAT:
case DXGI_FORMAT_R16G16B16A16_UNORM:
case DXGI_FORMAT_R16G16B16A16_UINT:
case DXGI_FORMAT_R16G16B16A16_SNORM:
case DXGI_FORMAT_R16G16B16A16_SINT: return DXGI_FORMAT_R16G16B16A16_TYPELESS;
case DXGI_FORMAT_R32G32_TYPELESS:
case DXGI_FORMAT_R32G32_FLOAT:
case DXGI_FORMAT_R32G32_UINT:
case DXGI_FORMAT_R32G32_SINT: return DXGI_FORMAT_R32G32_TYPELESS;
case DXGI_FORMAT_R32G8X24_TYPELESS:
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: return DXGI_FORMAT_R32G8X24_TYPELESS;
case DXGI_FORMAT_R10G10B10A2_TYPELESS:
case DXGI_FORMAT_R10G10B10A2_UNORM:
case DXGI_FORMAT_R10G10B10A2_UINT:
case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: // maybe not valid cast?
return DXGI_FORMAT_R10G10B10A2_TYPELESS;
case DXGI_FORMAT_R8G8B8A8_TYPELESS:
case DXGI_FORMAT_R8G8B8A8_UNORM:
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
case DXGI_FORMAT_R8G8B8A8_UINT:
case DXGI_FORMAT_R8G8B8A8_SNORM:
case DXGI_FORMAT_R8G8B8A8_SINT: return DXGI_FORMAT_R8G8B8A8_TYPELESS;
case DXGI_FORMAT_R16G16_TYPELESS:
case DXGI_FORMAT_R16G16_FLOAT:
case DXGI_FORMAT_R16G16_UNORM:
case DXGI_FORMAT_R16G16_UINT:
case DXGI_FORMAT_R16G16_SNORM:
case DXGI_FORMAT_R16G16_SINT: return DXGI_FORMAT_R16G16_TYPELESS;
case DXGI_FORMAT_R32_TYPELESS:
case DXGI_FORMAT_D32_FLOAT: // maybe not valid cast?
case DXGI_FORMAT_R32_FLOAT:
case DXGI_FORMAT_R32_UINT:
case DXGI_FORMAT_R32_SINT:
return DXGI_FORMAT_R32_TYPELESS;
// maybe not valid casts?
case DXGI_FORMAT_R24G8_TYPELESS:
case DXGI_FORMAT_D24_UNORM_S8_UINT:
case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
case DXGI_FORMAT_X24_TYPELESS_G8_UINT: return DXGI_FORMAT_R24G8_TYPELESS;
case DXGI_FORMAT_B8G8R8A8_TYPELESS:
case DXGI_FORMAT_B8G8R8A8_UNORM:
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
case DXGI_FORMAT_R8G8_B8G8_UNORM: // maybe not valid cast?
case DXGI_FORMAT_G8R8_G8B8_UNORM: // maybe not valid cast?
return DXGI_FORMAT_B8G8R8A8_TYPELESS;
case DXGI_FORMAT_B8G8R8X8_UNORM:
case DXGI_FORMAT_B8G8R8X8_TYPELESS:
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: return DXGI_FORMAT_B8G8R8X8_TYPELESS;
case DXGI_FORMAT_R8G8_TYPELESS:
case DXGI_FORMAT_R8G8_UNORM:
case DXGI_FORMAT_R8G8_UINT:
case DXGI_FORMAT_R8G8_SNORM:
case DXGI_FORMAT_R8G8_SINT: return DXGI_FORMAT_R8G8_TYPELESS;
case DXGI_FORMAT_R16_TYPELESS:
case DXGI_FORMAT_R16_FLOAT:
case DXGI_FORMAT_D16_UNORM:
case DXGI_FORMAT_R16_UNORM:
case DXGI_FORMAT_R16_UINT:
case DXGI_FORMAT_R16_SNORM:
case DXGI_FORMAT_R16_SINT: return DXGI_FORMAT_R16_TYPELESS;
case DXGI_FORMAT_R8_TYPELESS:
case DXGI_FORMAT_R8_UNORM:
case DXGI_FORMAT_R8_UINT:
case DXGI_FORMAT_R8_SNORM:
case DXGI_FORMAT_R8_SINT: return DXGI_FORMAT_R8_TYPELESS;
case DXGI_FORMAT_BC1_TYPELESS:
case DXGI_FORMAT_BC1_UNORM:
case DXGI_FORMAT_BC1_UNORM_SRGB: return DXGI_FORMAT_BC1_TYPELESS;
case DXGI_FORMAT_BC4_TYPELESS:
case DXGI_FORMAT_BC4_UNORM:
case DXGI_FORMAT_BC4_SNORM: return DXGI_FORMAT_BC4_TYPELESS;
case DXGI_FORMAT_BC2_TYPELESS:
case DXGI_FORMAT_BC2_UNORM:
case DXGI_FORMAT_BC2_UNORM_SRGB: return DXGI_FORMAT_BC2_TYPELESS;
case DXGI_FORMAT_BC3_TYPELESS:
case DXGI_FORMAT_BC3_UNORM:
case DXGI_FORMAT_BC3_UNORM_SRGB: return DXGI_FORMAT_BC3_TYPELESS;
case DXGI_FORMAT_BC5_TYPELESS:
case DXGI_FORMAT_BC5_UNORM:
case DXGI_FORMAT_BC5_SNORM: return DXGI_FORMAT_BC5_TYPELESS;
case DXGI_FORMAT_BC6H_TYPELESS:
case DXGI_FORMAT_BC6H_UF16:
case DXGI_FORMAT_BC6H_SF16: return DXGI_FORMAT_BC6H_TYPELESS;
case DXGI_FORMAT_BC7_TYPELESS:
case DXGI_FORMAT_BC7_UNORM:
case DXGI_FORMAT_BC7_UNORM_SRGB: return DXGI_FORMAT_BC7_TYPELESS;
case DXGI_FORMAT_R1_UNORM:
case DXGI_FORMAT_A8_UNORM:
case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
case DXGI_FORMAT_B5G6R5_UNORM:
case DXGI_FORMAT_B5G5R5A1_UNORM:
case DXGI_FORMAT_R11G11B10_FLOAT:
case DXGI_FORMAT_AYUV:
case DXGI_FORMAT_Y410:
case DXGI_FORMAT_YUY2:
case DXGI_FORMAT_Y416:
case DXGI_FORMAT_NV12:
case DXGI_FORMAT_P010:
case DXGI_FORMAT_P016:
case DXGI_FORMAT_420_OPAQUE:
case DXGI_FORMAT_Y210:
case DXGI_FORMAT_Y216:
case DXGI_FORMAT_NV11:
case DXGI_FORMAT_AI44:
case DXGI_FORMAT_IA44:
case DXGI_FORMAT_P8:
case DXGI_FORMAT_A8P8:
case DXGI_FORMAT_P208:
case DXGI_FORMAT_V208:
case DXGI_FORMAT_V408:
case DXGI_FORMAT_B4G4R4A4_UNORM: return f;
case DXGI_FORMAT_UNKNOWN: return DXGI_FORMAT_UNKNOWN;
default: return DXGI_FORMAT_UNKNOWN;
}
}
std::string vertex = R"EOSHADER(
struct vertin
{
float3 pos : POSITION;
float4 col : COLOR0;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 pos : SV_POSITION;
float4 col : COLOR0;
float2 uv : TEXCOORD0;
};
v2f main(vertin IN, uint vid : SV_VertexID)
{
v2f OUT = (v2f)0;
OUT.pos = float4(IN.pos.xy, 0.5f, 1.0f);
OUT.col = IN.col;
OUT.uv = IN.uv;
return OUT;
}
)EOSHADER";
std::string pixel = R"EOSHADER(
cbuffer refcounter : register(b0)
{
uint expected;
};
cbuffer uavcounter : register(b1)
{
uint actual;
};
float4 main() : SV_Target0
{
if(expected != actual)
return float4(1.0f, 0.0f, 0.0f, 1.0f);
return float4(0.0f, 1.0f, 0.1234f, 0.5f);
}
)EOSHADER";
std::string pixelUInt = R"EOSHADER(
cbuffer refcounter : register(b0)
{
uint expected;
};
cbuffer uavcounter : register(b1)
{
uint actual;
};
uint4 main() : SV_Target0
{
if(expected != actual)
return uint4(1, 0, 0, 1);
return uint4(0, 1, 1234, 5);
}
)EOSHADER";
std::string pixelSInt = R"EOSHADER(
cbuffer refcounter : register(b0)
{
uint expected;
};
cbuffer uavcounter : register(b1)
{
uint actual;
};
int4 main() : SV_Target0
{
if(expected != actual)
return int4(1, 0, 0, 1);
return int4(0, 1, -1234, 5);
}
)EOSHADER";
std::string compute = R"EOSHADER(
RWBuffer<uint> buf : register(u0);
[numthreads(1,1,1)]
void main()
{
InterlockedAdd(buf[0], 1);
}
)EOSHADER";
int main()
{
// initialise, create window, create device, etc
if(!Init())
return 3;
ID3DBlobPtr vsblob = Compile(vertex, "main", "vs_4_0");
CreateDefaultInputLayout(vsblob);
ID3D11VertexShaderPtr vs = CreateVS(vsblob);
ID3D11PixelShaderPtr ps = CreatePS(Compile(pixel, "main", "ps_4_0"));
ID3D11PixelShaderPtr psUInt = CreatePS(Compile(pixelUInt, "main", "ps_4_0"));
ID3D11PixelShaderPtr psSInt = CreatePS(Compile(pixelSInt, "main", "ps_4_0"));
ID3D11ComputeShaderPtr cs = CreateCS(Compile(compute, "main", "cs_5_0"));
ID3D11BufferPtr vb = MakeBuffer().Vertex().Data(DefaultTri);
const DXGI_FORMAT depthFormats[] = {
DXGI_FORMAT_D32_FLOAT,
DXGI_FORMAT_D16_UNORM,
DXGI_FORMAT_D24_UNORM_S8_UINT,
DXGI_FORMAT_R32G8X24_TYPELESS,
DXGI_FORMAT_D32_FLOAT_S8X24_UINT,
};
const DXGI_FORMAT dsvFormats[] = {
DXGI_FORMAT_D32_FLOAT,
DXGI_FORMAT_D16_UNORM,
DXGI_FORMAT_D24_UNORM_S8_UINT,
DXGI_FORMAT_D32_FLOAT_S8X24_UINT,
DXGI_FORMAT_D32_FLOAT_S8X24_UINT,
};
static_assert(sizeof(depthFormats) == sizeof(dsvFormats),
"depth arrays should be identical sizes.");
ID3D11BufferPtr bufRef = MakeBuffer().Size(256).Constant();
ID3D11BufferPtr bufCounter = MakeBuffer().Size(256).UAV();
ID3D11BufferPtr bufCounterCB = MakeBuffer().Size(256).Constant();
ID3D11UnorderedAccessViewPtr bufCounterUAV = MakeUAV(bufCounter).Format(DXGI_FORMAT_R32_UINT);
ctx->CSSetUnorderedAccessViews(0, 1, &bufCounterUAV.GetInterfacePtr(), NULL);
ctx->CSSetShader(cs, NULL, 0);
std::vector<ID3D11DepthStencilViewPtr> dsvs;
std::vector<ID3D11RenderTargetViewPtr> rts;
for(size_t i = 0; i < ARRAY_COUNT(dsvFormats); i++)
{
// normal
dsvs.push_back(
MakeDSV(MakeTexture(depthFormats[i], 16, 16).DSV().Tex2D()).Format(dsvFormats[i]));
// submip and subslice selected
dsvs.push_back(MakeDSV(MakeTexture(depthFormats[i], 32, 32).Array(32).DSV().Mips(2).Tex2D())
.Format(dsvFormats[i])
.FirstMip(1)
.NumMips(1)
.FirstSlice(4)
.NumSlices(1));
}
const DXGI_FORMAT colorFormats[] = {
DXGI_FORMAT_R32G32B32A32_FLOAT,
DXGI_FORMAT_R32G32B32A32_UINT,
DXGI_FORMAT_R32G32B32A32_SINT,
DXGI_FORMAT_R32G32B32_FLOAT,
DXGI_FORMAT_R32G32B32_UINT,
DXGI_FORMAT_R32G32B32_SINT,
DXGI_FORMAT_R16G16B16A16_FLOAT,
DXGI_FORMAT_R16G16B16A16_UNORM,
DXGI_FORMAT_R16G16B16A16_UINT,
DXGI_FORMAT_R16G16B16A16_SNORM,
DXGI_FORMAT_R16G16B16A16_SINT,
DXGI_FORMAT_R32G32_FLOAT,
DXGI_FORMAT_R32G32_UINT,
DXGI_FORMAT_R32G32_SINT,
DXGI_FORMAT_R10G10B10A2_UNORM,
DXGI_FORMAT_R10G10B10A2_UINT,
DXGI_FORMAT_R11G11B10_FLOAT,
DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
DXGI_FORMAT_R8G8B8A8_UINT,
DXGI_FORMAT_R8G8B8A8_SNORM,
DXGI_FORMAT_R8G8B8A8_SINT,
DXGI_FORMAT_R16G16_FLOAT,
DXGI_FORMAT_R16G16_UNORM,
DXGI_FORMAT_R16G16_UINT,
DXGI_FORMAT_R16G16_SNORM,
DXGI_FORMAT_R16G16_SINT,
DXGI_FORMAT_R32_FLOAT,
DXGI_FORMAT_R32_UINT,
DXGI_FORMAT_R32_SINT,
DXGI_FORMAT_R8G8_UNORM,
DXGI_FORMAT_R8G8_UINT,
DXGI_FORMAT_R8G8_SNORM,
DXGI_FORMAT_R8G8_SINT,
DXGI_FORMAT_R16_FLOAT,
DXGI_FORMAT_R16_UNORM,
DXGI_FORMAT_R16_UINT,
DXGI_FORMAT_R16_SNORM,
DXGI_FORMAT_R16_SINT,
DXGI_FORMAT_R8_UNORM,
DXGI_FORMAT_R8_UINT,
DXGI_FORMAT_R8_SNORM,
DXGI_FORMAT_R8_SINT,
DXGI_FORMAT_A8_UNORM,
DXGI_FORMAT_R1_UNORM,
DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
DXGI_FORMAT_B5G6R5_UNORM,
DXGI_FORMAT_B5G5R5A1_UNORM,
DXGI_FORMAT_B8G8R8A8_UNORM,
DXGI_FORMAT_B8G8R8X8_UNORM,
DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM,
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
DXGI_FORMAT_B8G8R8X8_UNORM_SRGB,
DXGI_FORMAT_B4G4R4A4_UNORM,
};
for(size_t i = 0; i < ARRAY_COUNT(colorFormats); i++)
{
DXGI_FORMAT f = colorFormats[i];
UINT supp = 0;
dev->CheckFormatSupport(f, &supp);
if((supp & D3D11_FORMAT_SUPPORT_RENDER_TARGET) == 0)
continue;
std::vector<DXGI_FORMAT> fmts = {f};
// test typeless->casted for the first three (RGBA32)
if(i < 3)
fmts.push_back(GetTypelessFormat(f));
for(DXGI_FORMAT tex_fmt : fmts)
{
// make a normal one
rts.push_back(MakeRTV(MakeTexture(tex_fmt, 16, 16).RTV().Tex2D()).Format(f));
// make a subslice and submip one
rts.push_back(MakeRTV(MakeTexture(tex_fmt, 32, 32).Array(32).Mips(2).RTV().Tex2D())
.Format(f)
.FirstMip(1)
.NumMips(1)
.FirstSlice(4)
.NumSlices(1));
}
}
// make a simple dummy texture for MRT testing
ID3D11RenderTargetViewPtr mrt =
MakeRTV(MakeTexture(DXGI_FORMAT_R8G8B8A8_UNORM, 16, 16).RTV().Tex2D());
while(Running())
{
ClearRenderTargetView(bbRTV, {0.2f, 0.2f, 0.2f, 1.0f});
IASetVertexBuffer(vb, sizeof(DefaultA2V), 0);
ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ctx->IASetInputLayout(defaultLayout);
ctx->VSSetShader(vs, NULL, 0);
ctx->PSSetShader(ps, NULL, 0);
RSSetViewport({0.0f, 0.0f, 16.0f, 16.0f, 0.0f, 1.0f});
UINT zero[4] = {};
ctx->ClearUnorderedAccessViewUint(bufCounterUAV, zero);
uint32_t testCounter = 0;
// for each DSV and for none
for(size_t dsvIdx = 0; dsvIdx <= dsvs.size(); dsvIdx++)
{
ID3D11DepthStencilViewPtr dsv = dsvIdx < dsvs.size() ? dsvs[dsvIdx] : NULL;
DXGI_FORMAT df = DXGI_FORMAT_UNKNOWN;
if(dsv)
{
D3D11_DEPTH_STENCIL_VIEW_DESC desc;
dsv->GetDesc(&desc);
df = desc.Format;
}
// for each RT
for(size_t rtIdx = 0; rtIdx < rts.size(); rtIdx++)
{
ID3D11RenderTargetViewPtr rt = rts[rtIdx];
ID3D11RenderTargetViewPtr dummy = mrt;
DXGI_FORMAT f = DXGI_FORMAT_UNKNOWN;
{
D3D11_RENDER_TARGET_VIEW_DESC desc;
rt->GetDesc(&desc);
f = desc.Format;
}
// for all but the first DSV and the last (none) DSV, skip the bulk of the colour tests to
// reduce the test matrix.
if(dsvIdx > 0 && dsvIdx < dsvs.size())
{
if(rtIdx > 10)
break;
}
pushMarker("Test RTV: " + dxgiFormatName[f] + " & depth: " +
(df == DXGI_FORMAT_UNKNOWN ? "None" : dxgiFormatName[df]));
ctx->OMSetRenderTargets(1, &rt.GetInterfacePtr(), dsv);
// dispatch the CS to increment the buffer counter on the GPU
ctx->Dispatch(1, 1, 1);
// increment the CPU counter
testCounter++;
// update CBs so we can check for validity
uint32_t data[256 / 4];
data[0] = testCounter;
ctx->UpdateSubresource(bufRef, 0, NULL, data, 256, 256);
ctx->CopyResource(bufCounterCB, bufCounter);
ctx->PSSetConstantBuffers(0, 1, &bufRef.GetInterfacePtr());
ctx->PSSetConstantBuffers(1, 1, &bufCounterCB.GetInterfacePtr());
setMarker("Test " + std::to_string(testCounter));
if(IsUIntFormat(f))
{
setMarker("UInt tex");
ctx->PSSetShader(psUInt, NULL, 0);
}
else if(IsSIntFormat(f))
{
setMarker("SInt tex");
ctx->PSSetShader(psSInt, NULL, 0);
}
else
{
setMarker("Float tex");
ctx->PSSetShader(ps, NULL, 0);
}
if(dsv)
{
setMarker("DSVClear");
ctx->ClearDepthStencilView(dsv, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
}
setMarker("RTVClear");
ClearRenderTargetView(rt, Vec4f(1.0f, 0.0f, 1.0f, 1.0f));
setMarker("BasicDraw");
ctx->Draw(3, 0);
popMarker();
}
}
Present();
}
return 0;
}
};
REGISTER_TEST();
+1
View File
@@ -140,6 +140,7 @@
<ClCompile Include="d3d11\d3d11_mip_gen_rt.cpp" />
<ClCompile Include="d3d11\d3d11_mip_rtv.cpp" />
<ClCompile Include="d3d11\d3d11_overdraw_stress.cpp" />
<ClCompile Include="d3d11\d3d11_pixel_history_zoo.cpp" />
<ClCompile Include="d3d11\d3d11_primitiveid.cpp" />
<ClCompile Include="d3d11\d3d11_shader_debug_zoo.cpp" />
<ClCompile Include="d3d11\d3d11_overlay_test.cpp" />
+3
View File
@@ -454,6 +454,9 @@
<ClCompile Include="d3d12\d3d12_rendertarget_binds.cpp">
<Filter>D3D12\demos</Filter>
</ClCompile>
<ClCompile Include="d3d11\d3d11_pixel_history_zoo.cpp">
<Filter>D3D11\demos</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="D3D11">
+27 -41
View File
@@ -214,7 +214,7 @@ class TestCase:
draw: rd.DrawcallDescription
for draw in draw_list:
# If this draw matches, return it
if draw.eventId >= start_event and name in draw.name:
if draw.eventId >= start_event and (name == '' or name in draw.name):
return draw
# Recurse to children - depth-first search
@@ -240,6 +240,16 @@ class TestCase:
return self._find_draw(name, start_event, self.controller.GetDrawcalls())
def get_draw(self, event: int = 0):
"""
Finds the drawcall for the given event
:param event: The eventId to search for.
:return:
"""
return self._find_draw('', event, self.controller.GetDrawcalls())
def get_vsin(self, draw: rd.DrawcallDescription, first_index: int=0, num_indices: int=0, instance: int=0, view: int=0):
ib: rd.BoundVBuffer = self.controller.GetPipelineState().GetIBuffer()
@@ -299,26 +309,36 @@ class TestCase:
log.success("Mesh data is identical to reference")
def check_pixel_value(self, tex: rd.ResourceId, x, y, value, eps=util.FLT_EPSILON):
def check_pixel_value(self, tex: rd.ResourceId, x, y, value, sub=None, cast=None, eps=util.FLT_EPSILON):
tex_details = self.get_texture(tex)
res_details = self.get_resource(tex)
if sub is None:
sub = rd.Subresource(0,0,0)
if cast is None:
cast = rd.CompType.Typeless
if type(x) is float:
x = int((tex_details.width-1) * x)
if type(y) is float:
y = int((tex_details.height-1) * y)
cast = rd.CompType.Typeless
if tex_details.creationFlags & rd.TextureCategory.SwapBuffer:
if cast == rd.CompType.Typeless and tex_details.creationFlags & rd.TextureCategory.SwapBuffer:
cast = rd.CompType.UNormSRGB
# Reduce epsilon for RGBA8 textures if it's not already reduced
if tex_details.format.compByteWidth == 1 and eps == util.FLT_EPSILON:
eps = (1.0 / 255.0)
picked: rd.PixelValue = self.controller.PickPixel(tex, x, y, rd.Subresource(0, 0, 0), cast)
picked: rd.PixelValue = self.controller.PickPixel(tex, x, y, sub, cast)
if not util.value_compare(picked.floatValue, value, eps):
picked_value = picked.floatValue
if cast == rd.CompType.UInt:
picked_value = picked.uintValue
elif cast == rd.CompType.SInt:
picked_value = picked.intValue
if not util.value_compare(picked_value, value, eps):
save_data = rd.TextureSave()
save_data.resourceId = tex
save_data.destType = rd.FileType.PNG
@@ -328,45 +348,11 @@ class TestCase:
self.controller.SaveTexture(save_data, img_path)
raise TestFailureException(
"Picked value {} at {},{} doesn't match expectation of {}".format(picked.floatValue, x, y, value),
"Picked value {} at {},{} doesn't match expectation of {}".format(picked_value, x, y, value),
img_path)
log.success("Picked value at {},{} in {} is as expected".format(x, y, res_details.name))
def check_pixel_sample_value(self, tex: rd.ResourceId, x, y, sample, value, eps=util.FLT_EPSILON):
tex_details = self.get_texture(tex)
res_details = self.get_resource(tex)
if type(x) is float:
x = int((tex_details.width-1) * x)
if type(y) is float:
y = int((tex_details.height-1) * y)
cast = rd.CompType.Typeless
if tex_details.creationFlags & rd.TextureCategory.SwapBuffer:
cast = rd.CompType.UNormSRGB
# Reduce epsilon for RGBA8 textures if it's not already reduced
if tex_details.format.compByteWidth == 1 and eps == util.FLT_EPSILON:
eps = (1.0 / 255.0)
picked: rd.PixelValue = self.controller.PickPixel(tex, x, y, rd.Subresource(0, 0, sample), cast)
if not util.value_compare(picked.floatValue, value, eps):
save_data = rd.TextureSave()
save_data.resourceId = tex
save_data.destType = rd.FileType.PNG
img_path = util.get_tmp_path('output.png')
self.controller.SaveTexture(save_data, img_path)
raise TestFailureException(
"Picked value {} at {},{} sample {} doesn't match expectation of {}".
format(picked.floatValue, x, y, sample, value), img_path)
log.success("Picked value at {},{} sample {} in {} is as expected".format(x, y, sample, res_details.name))
def check_triangle(self, out = None, back = None, fore = None, vp = None):
pipe: rd.PipeState = self.controller.GetPipelineState()
@@ -0,0 +1,74 @@
import renderdoc as rd
import rdtest
from typing import List
class D3D11_Pixel_History_Zoo(rdtest.TestCase):
slow_test = True
demos_test_name = 'D3D11_Pixel_History_Zoo'
def check_capture(self):
draws = self.controller.GetDrawcalls()
for d in self.controller.GetDrawcalls():
# Only process test draws
if not d.name.startswith('Test'):
continue
# Go to the last child draw
self.controller.SetFrameEvent(d.children[-1].eventId, True)
if any(['UInt tex' in d.name for d in d.children]):
value_selector = lambda x: x.uintValue
shader_out = (0, 1, 1234, 5)
elif any(['SInt tex' in d.name for d in d.children]):
value_selector = lambda x: x.intValue
shader_out = (0, 1, -1234, 5)
else:
value_selector = lambda x: x.floatValue
shader_out = (0.0, 1.0, 0.1234, 0.5)
pipe: rd.PipeState = self.controller.GetPipelineState()
rt: rd.BoundResource = pipe.GetOutputTargets()[0]
vp: rd.Viewport = pipe.GetViewport(0)
tex = rt.resourceId
x, y = (int(vp.width / 2), int(vp.height / 2))
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
modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.typeCast)
# Should be at least two modifications in every test - clear and draw
self.check(len(modifs) >= 2)
# Check that the modifications are self consistent - postmod of each should match premod of the next
for i in range(len(modifs) - 1):
if value_selector(modifs[i].postMod.col) != value_selector(modifs[i + 1].preMod.col):
raise rdtest.TestFailureException(
"postmod at {}: {} doesn't match premod at {}: {}".format(modifs[i].eventId,
value_selector(modifs[i].postMod.col),
modifs[i + 1].eventId,
value_selector(modifs[i].preMod.col)))
if self.get_draw(modifs[i].eventId).flags & rd.DrawFlags.Drawcall:
if not rdtest.value_compare(value_selector(modifs[i].shaderOut.col), shader_out):
raise rdtest.TestFailureException(
"Shader output {} isn't as expected {}".format(value_selector(modifs[i].shaderOut.col),
shader_out))
rdtest.log.success("shader output and premod/postmod is consistent")
# The current pixel value should match the last postMod
self.check_pixel_value(tex, x, y, value_selector(modifs[-1].postMod.col), sub=sub, cast=rt.typeCast)
# Also the red channel should be zero, as it indicates errors
self.check(float(value_selector(modifs[-1].postMod.col)[0]) == 0.0)
@@ -63,11 +63,11 @@ class D3D11_Shader_Debug_Zoo(rdtest.TestCase):
output = self.find_output_source_var(trace, rd.ShaderBuiltin.ColorOutput, 0)
debugged = self.evalute_source_var(output, variables)
debugged = self.evaluate_source_var(output, variables)
# Validate the debug output result
try:
self.check_pixel_sample_value(pipe.GetOutputTargets()[0].resourceId, 4, 4, test, debugged.value.fv[0:4], 0.0)
self.check_pixel_value(pipe.GetOutputTargets()[0].resourceId, 4, 4, debugged.value.fv[0:4], 0.0, sub=rd.Subresource(0, 0, test))
except rdtest.TestFailureException as ex:
failed = True
rdtest.log.error("Test {} did not match. {}".format(test, str(ex)))
@@ -72,11 +72,11 @@ class D3D12_Shader_Debug_Zoo(rdtest.TestCase):
output = self.find_output_source_var(trace, rd.ShaderBuiltin.ColorOutput, 0)
debugged = self.evalute_source_var(output, variables)
debugged = self.evaluate_source_var(output, variables)
# Validate the debug output result
try:
self.check_pixel_sample_value(pipe.GetOutputTargets()[0].resourceId, 4, 4, test, debugged.value.fv[0:4], 0.0)
self.check_pixel_value(pipe.GetOutputTargets()[0].resourceId, 4, 4, debugged.value.fv[0:4], 0.0, sub=rd.Subresource(0, 0, test))
except rdtest.TestFailureException as ex:
failed = True
rdtest.log.error("Test {} did not match. {}".format(test, str(ex)))