D3D12 pixel history copy pixel and resource creation

This adds some of the D3D12 pixel history framework, with creation
of resources that will be needed during pixel history, and a helper
function and shader to copy pixels from MSAA resources.
This commit is contained in:
Steve Karolewics
2023-10-07 12:41:28 -07:00
committed by Baldur Karlsson
parent 15ba420905
commit b3bc0e98bc
10 changed files with 618 additions and 0 deletions
+171
View File
@@ -0,0 +1,171 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2019-2023 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.
******************************************************************************/
cbuffer CopyPixelShaderInput : register(b0)
{
uint4 src_coord; // x, y, mip/sample, slice
uint dst_slot;
bool copy_depth;
bool copy_stencil;
bool multisampled;
bool is_float;
bool is_uint;
bool is_int;
};
Texture2DArray<float> copyin_depth : register(t0);
Texture2DArray<uint> copyin_stencil : register(t1);
Texture2DMSArray<float> copyin_depth_ms : register(t2);
Texture2DMSArray<uint> copyin_stencil_ms : register(t3);
Texture2DArray<float4> copyin_float : register(t4);
Texture2DMSArray<float4> copyin_float_ms : register(t5);
Texture2DArray<uint4> copyin_uint : register(t6);
Texture2DMSArray<uint4> copyin_uint_ms : register(t7);
Texture2DArray<int4> copyin_int : register(t8);
Texture2DMSArray<int4> copyin_int_ms : register(t9);
RWBuffer<float> copyout_depth : register(u0);
RWBuffer<uint> copyout_stencil : register(u1);
RWBuffer<float> copyout_float : register(u2);
RWBuffer<uint> copyout_uint : register(u3);
RWBuffer<int> copyout_int : register(u4);
[numthreads(1, 1, 1)] void RENDERDOC_PixelHistoryUnused() { copyout_depth[dst_slot] = -1.0f; }
[numthreads(1, 1, 1)] void RENDERDOC_PixelHistoryCopyPixel()
{
if(multisampled)
{
if(copy_depth)
{
float val = copyin_depth_ms.sample[src_coord.z][uint3(src_coord.xy, src_coord.w)];
copyout_depth[dst_slot] = val;
}
else if(copy_stencil)
{
uint val = copyin_stencil_ms.sample[src_coord.z][uint3(src_coord.xy, src_coord.w)];
copyout_stencil[dst_slot] = val;
}
else
{
if(is_float)
{
float4 val = copyin_float_ms.sample[src_coord.z][uint3(src_coord.xy, src_coord.w)];
copyout_float[dst_slot] = val.x;
copyout_float[dst_slot + 1] = val.y;
copyout_float[dst_slot + 2] = val.z;
copyout_float[dst_slot + 3] = val.w;
}
else if(is_uint)
{
uint4 val = copyin_uint_ms.sample[src_coord.z][uint3(src_coord.xy, src_coord.w)];
copyout_uint[dst_slot] = val.x;
copyout_uint[dst_slot + 1] = val.y;
copyout_uint[dst_slot + 2] = val.z;
copyout_uint[dst_slot + 3] = val.w;
}
else if(is_int)
{
int4 val = copyin_int_ms.sample[src_coord.z][uint3(src_coord.xy, src_coord.w)];
copyout_int[dst_slot] = val.x;
copyout_int[dst_slot + 1] = val.y;
copyout_int[dst_slot + 2] = val.z;
copyout_int[dst_slot + 3] = val.w;
}
}
}
else
{
if(copy_depth)
{
float val = copyin_depth.mips[src_coord.z][uint3(src_coord.xy, src_coord.w)];
copyout_depth[dst_slot] = val;
}
else if(copy_stencil)
{
uint val = copyin_stencil.mips[src_coord.z][uint3(src_coord.xy, src_coord.w)];
copyout_stencil[dst_slot] = val;
}
else
{
if(is_float)
{
float4 val = copyin_float.mips[src_coord.z][uint3(src_coord.xy, src_coord.w)];
copyout_float[dst_slot] = val.x;
copyout_float[dst_slot + 1] = val.y;
copyout_float[dst_slot + 2] = val.z;
copyout_float[dst_slot + 3] = val.w;
}
else if(is_uint)
{
uint4 val = copyin_uint.mips[src_coord.z][uint3(src_coord.xy, src_coord.w)];
copyout_uint[dst_slot] = val.x;
copyout_uint[dst_slot + 1] = val.y;
copyout_uint[dst_slot + 2] = val.z;
copyout_uint[dst_slot + 3] = val.w;
}
else if(is_int)
{
int4 val = copyin_int.mips[src_coord.z][uint3(src_coord.xy, src_coord.w)];
copyout_int[dst_slot] = val.x;
copyout_int[dst_slot + 1] = val.y;
copyout_int[dst_slot + 2] = val.z;
copyout_int[dst_slot + 3] = val.w;
}
}
}
}
float4 RENDERDOC_PrimitiveIDPS(uint prim : SV_PrimitiveID) : SV_Target0
{
return asfloat(prim).xxxx;
}
struct MultipleOutput
{
float4 col0 : SV_Target0;
float4 col1 : SV_Target1;
float4 col2 : SV_Target2;
float4 col3 : SV_Target3;
float4 col4 : SV_Target4;
float4 col5 : SV_Target5;
float4 col6 : SV_Target6;
float4 col7 : SV_Target7;
};
MultipleOutput RENDERDOC_PixelHistoryFixedColPS()
{
MultipleOutput OUT = (MultipleOutput)0;
float4 color = float4(0.1f, 0.2f, 0.3f, 0.4f);
OUT.col0 = OUT.col1 = OUT.col2 = OUT.col3 = OUT.col4 = OUT.col5 = OUT.col6 = OUT.col7 = color;
return OUT;
}
+1
View File
@@ -115,6 +115,7 @@ RESOURCE_quadoverdraw_hlsl TYPE_EMBED "hlsl/quadoverdraw.hlsl"
RESOURCE_texremap_hlsl TYPE_EMBED "hlsl/texremap.hlsl"
RESOURCE_fixedcol_hlsl TYPE_EMBED "hlsl/fixedcol.hlsl"
RESOURCE_shaderdebug_hlsl TYPE_EMBED "hlsl/shaderdebug.hlsl"
RESOURCE_d3d12_pixelhistory_hlsl TYPE_EMBED "hlsl/d3d12_pixelhistory.hlsl"
#ifdef RENDERDOC_BAKED_DXC_SHADERS
+1
View File
@@ -18,6 +18,7 @@
#define RESOURCE_texremap_hlsl 111
#define RESOURCE_fixedcol_hlsl 112
#define RESOURCE_shaderdebug_hlsl 118
#define RESOURCE_d3d12_pixelhistory_hlsl 119
#define RESOURCE_fixedcol_0_dxbc 113
#define RESOURCE_fixedcol_1_dxbc 114
+41
View File
@@ -337,6 +337,43 @@ D3D12DebugManager::D3D12DebugManager(WrappedID3D12Device *wrapper)
D3DCOMPILE_WARNINGS_ARE_ERRORS, {}, "ps_5_0", &m_DepthArray2MS);
}
{
ID3DBlob *root = shaderCache->MakeRootSig({
cbvParam(D3D12_SHADER_VISIBILITY_ALL, 0, 0),
tableParam(D3D12_SHADER_VISIBILITY_ALL, D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0, 0, 5),
tableParam(D3D12_SHADER_VISIBILITY_ALL, D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 0, 10),
});
RDCASSERT(root);
hr = m_pDevice->CreateRootSignature(0, root->GetBufferPointer(), root->GetBufferSize(),
__uuidof(ID3D12RootSignature),
(void **)&m_PixelHistoryCopySig);
m_pDevice->InternalRef();
SAFE_RELEASE(root);
rm->SetInternalResource(m_PixelHistoryCopySig);
rdcstr hlsl = GetEmbeddedResource(d3d12_pixelhistory_hlsl);
shaderCache->GetShaderBlob(hlsl.c_str(), "RENDERDOC_PixelHistoryCopyPixel",
D3DCOMPILE_WARNINGS_ARE_ERRORS, {}, "cs_5_0", &m_PixelHistoryCopyCS);
D3D12_COMPUTE_PIPELINE_STATE_DESC pipeDesc = {};
pipeDesc.CS.pShaderBytecode = m_PixelHistoryCopyCS->GetBufferPointer();
pipeDesc.CS.BytecodeLength = m_PixelHistoryCopyCS->GetBufferSize();
pipeDesc.pRootSignature = m_PixelHistoryCopySig;
hr = m_pDevice->CreateComputePipelineState(&pipeDesc, __uuidof(ID3D12PipelineState),
(void **)&m_PixelHistoryCopyPso);
if(FAILED(hr))
{
RDCERR("Failed to create PSO for pixel history HRESULT: %s", ToStr(hr).c_str());
return;
}
m_pDevice->GetResourceManager()->SetInternalResource(m_PixelHistoryCopyPso);
}
shaderCache->SetCaching(false);
D3D12_RESOURCE_DESC readbackDesc;
@@ -490,6 +527,10 @@ D3D12DebugManager::~D3D12DebugManager()
SAFE_RELEASE(m_FloatArray2MS);
SAFE_RELEASE(m_DepthArray2MS);
SAFE_RELEASE(m_PixelHistoryCopyCS);
SAFE_RELEASE(m_PixelHistoryCopySig);
SAFE_RELEASE(m_PixelHistoryCopyPso);
SAFE_RELEASE(m_ReadbackBuffer);
SAFE_RELEASE(m_RingConstantBuffer);
+25
View File
@@ -31,7 +31,9 @@
class WrappedID3D12Device;
class D3D12ResourceManager;
struct D3D12CopyPixelParams;
struct D3D12Descriptor;
struct D3D12PixelHistoryResources;
namespace DXBC
{
@@ -80,6 +82,14 @@ enum CBVUAVSRVSlot
FIRST_SHADDEBUG_SRV,
LAST_SHADDEBUG_SRV = FIRST_SHADDEBUG_SRV + 25,
FIRST_PIXELHISTORY_SRV,
LAST_PIXELHISTORY_SRV = FIRST_PIXELHISTORY_SRV + 10,
FIRST_PIXELHISTORY_SCRATCH_SRV,
LAST_PIXELHISTORY_SCRATCH_SRV = LAST_PIXELHISTORY_SRV + 10,
FIRST_PIXELHISTORY_UAV,
LAST_PIXELHISTORY_UAV = FIRST_PIXELHISTORY_UAV + 5,
MAX_SRV_SLOT,
};
@@ -91,6 +101,7 @@ enum RTVSlot
GET_TEX_RTV,
MSAA_RTV,
SHADER_DEBUG_RTV,
PIXEL_HISTORY_RTV,
FIRST_TMP_RTV,
LAST_TMP_RTV = FIRST_TMP_RTV + 16,
FIRST_WIN_RTV,
@@ -110,6 +121,7 @@ enum DSVSlot
{
OVERLAY_DSV,
MSAA_DSV,
PIXEL_HISTORY_DSV,
TMP_DSV,
FIRST_WIN_DSV,
LAST_WIN_DSV = FIRST_WIN_DSV + 64,
@@ -192,6 +204,14 @@ public:
ID3D12Resource *srcMS);
void CopyArrayToTex2DMS(ID3D12Resource *destMS, ID3D12Resource *srcArray, UINT selectedSlice);
void PixelHistoryCopyPixel(ID3D12GraphicsCommandListX *cmd, ID3D12Resource *dstBuffer,
D3D12CopyPixelParams &params, size_t offset);
bool PixelHistorySetupResources(D3D12PixelHistoryResources &resources,
WrappedID3D12Resource *targetImage,
const D3D12_RESOURCE_DESC &desc, uint32_t numEvents);
bool PixelHistoryDestroyResources(D3D12PixelHistoryResources &resources);
private:
bool CreateShaderDebugResources();
@@ -230,6 +250,11 @@ private:
ID3D12PipelineState *m_TexSamplePso = NULL;
std::map<uint32_t, ID3D12PipelineState *> m_OffsetTexSamplePso;
// PixelHistoryCopyPixel
ID3D12RootSignature *m_PixelHistoryCopySig = NULL;
ID3DBlob *m_PixelHistoryCopyCS = NULL;
ID3D12PipelineState *m_PixelHistoryCopyPso = NULL;
// GetBufferData
static const uint64_t m_ReadbackSize = 16 * 1024 * 1024;
@@ -0,0 +1,371 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2023 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 "driver/dxgi/dxgi_common.h"
#include "d3d12_command_queue.h"
#include "d3d12_debug.h"
struct D3D12CopyPixelParams
{
// The image being copied from
ID3D12Resource *srcImage;
// The source image format and format to use when copying. In most cases these are
// the same, but for some planar formats, the copy format will correspond to a single
// plane's typeless format, not the multi-plane format.
DXGI_FORMAT srcImageFormat;
DXGI_FORMAT copyFormat;
D3D12_RESOURCE_STATES srcImageState;
// Data about the pixel we want to copy
uint32_t x;
uint32_t y;
uint32_t mip;
uint32_t sample;
uint32_t planeSlice;
uint32_t arraySlice;
// Additional info to inform how to copy
bool depthcopy;
bool multisampled;
bool scratchBuffer;
};
struct D3D12PixelHistoryResources
{
ID3D12Resource *dstBuffer;
// Used for offscreen color/depth/stencil rendering for draw call events.
ID3D12Resource *colorImage;
D3D12Descriptor *colorDescriptor;
ID3D12Resource *dsImage;
D3D12Descriptor *dsDescriptor;
};
struct D3D12PixelHistoryValue
{
// Max size is 4 component with 8 byte component width
uint8_t color[32];
union
{
uint32_t udepth;
float fdepth;
} depth;
int8_t stencil;
uint8_t padding[3 + 8];
};
struct D3D12EventInfo
{
D3D12PixelHistoryValue premod;
D3D12PixelHistoryValue postmod;
uint8_t dsWithoutShaderDiscard[8];
uint8_t padding[8];
uint8_t dsWithShaderDiscard[8];
uint8_t padding1[8];
};
// Helper function to copy a single pixel out of a source texture, which will handle any texture
// type and binding type, doing any copying as needed. Writes the result to a given buffer UAV.
void D3D12DebugManager::PixelHistoryCopyPixel(ID3D12GraphicsCommandListX *cmd,
ID3D12Resource *dstBuffer, D3D12CopyPixelParams &p,
size_t offset)
{
D3D12RenderState &state = m_pDevice->GetQueue()->GetCommandData()->GetCurRenderState();
D3D12RenderState prevState = state;
state.pipe = GetResID(m_PixelHistoryCopyPso);
state.compute.rootsig = GetResID(m_PixelHistoryCopySig);
bool floatTex = false, uintTex = false, intTex = false;
DXGI_FORMAT srvFormat = p.srcImageFormat;
bool uintStencil = p.depthcopy && p.planeSlice == 1 &&
(p.srcImageFormat == DXGI_FORMAT_X24_TYPELESS_G8_UINT ||
p.srcImageFormat == DXGI_FORMAT_X32_TYPELESS_G8X24_UINT);
if(IsUIntFormat(p.srcImageFormat) || uintStencil)
{
uintTex = true;
srvFormat = GetUIntTypedFormat(srvFormat);
}
else if(IsIntFormat(p.srcImageFormat))
{
intTex = true;
srvFormat = GetSIntTypedFormat(srvFormat);
}
else
{
floatTex = true;
srvFormat = GetFloatTypedFormat(srvFormat);
}
UINT srvIndex = 0;
UINT uavIndex = 0;
// SRV indices by type:
// 0 - depth
// 1 - stencil
// 2 - depth MSAA
// 3 - stencil MSAA
// 4 - float
// 5 - float MSAA
// 6 - uint
// 7 - uint MSAA
// 8 - int
// 9 - int MSAA
// UAV indices by type:
// 0 - depth
// 1 - stencil
// 2 - float
// 3 - uint
// 4 - int
// Determine which SRV we will read from in the shader
if(p.depthcopy)
{
srvIndex = p.planeSlice;
if(p.multisampled)
srvIndex += 2;
// This should already be the SRV format for depth/stencil copies
srvFormat = p.srcImageFormat;
}
else
{
if(floatTex)
srvIndex = 4;
else if(uintTex)
srvIndex = 6;
else if(intTex)
srvIndex = 8;
if(p.multisampled)
srvIndex++;
}
// Determine which UAV we will write to in the shader
if(p.depthcopy && p.planeSlice == 0)
uavIndex = 0;
else if(p.depthcopy && p.planeSlice == 1)
uavIndex = 1;
else if(floatTex)
uavIndex = 2;
else if(uintTex)
uavIndex = 3;
else
uavIndex = 4;
struct CopyPixelShaderInput
{
Vec4u src_coord; // x, y, mip/sample, slice
uint32_t dst_slot;
uint32_t copy_depth;
uint32_t copy_stencil;
uint32_t multisampled;
uint32_t is_float;
uint32_t is_uint;
uint32_t is_int;
} inputData;
inputData.src_coord = {p.x, p.y, p.multisampled ? p.sample : p.mip, p.arraySlice};
inputData.multisampled = p.multisampled;
inputData.is_float = floatTex;
inputData.is_uint = uintTex;
inputData.is_int = intTex;
inputData.dst_slot = (uint32_t)(offset / sizeof(float));
inputData.copy_depth = p.depthcopy && p.planeSlice == 0;
inputData.copy_stencil = p.depthcopy && p.planeSlice == 1;
// When copying a scratch buffer, we need to use a different SRV range from the heap
CBVUAVSRVSlot srvStartSlot =
p.scratchBuffer ? FIRST_PIXELHISTORY_SCRATCH_SRV : FIRST_PIXELHISTORY_SRV;
D3D12_CPU_DESCRIPTOR_HANDLE srv = m_pDevice->GetDebugManager()->GetCPUHandle(srvStartSlot);
D3D12_CPU_DESCRIPTOR_HANDLE uav =
m_pDevice->GetDebugManager()->GetCPUHandle(FIRST_PIXELHISTORY_UAV);
m_pDevice->GetDebugManager()->SetDescriptorHeaps(state.heaps, true, false);
state.compute.sigelems = {
D3D12RenderState::SignatureElement(
eRootCBV, m_pDevice->GetDebugManager()->UploadConstants(&inputData, sizeof(inputData))),
D3D12RenderState::SignatureElement(eRootTable, uav),
D3D12RenderState::SignatureElement(eRootTable, srv),
};
srv.ptr += srvIndex * sizeof(D3D12Descriptor);
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.ViewDimension =
p.multisampled ? D3D12_SRV_DIMENSION_TEXTURE2DMS : D3D12_SRV_DIMENSION_TEXTURE2D;
srvDesc.Format = p.srcImageFormat;
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
if(!p.multisampled)
{
srvDesc.Texture2D.MipLevels = 1;
srvDesc.Texture2D.PlaneSlice = p.planeSlice;
}
m_pDevice->CreateShaderResourceView(p.srcImage, &srvDesc, srv);
uav.ptr += uavIndex * sizeof(D3D12Descriptor);
D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
uavDesc.Format = DXGI_FORMAT_UNKNOWN;
uavDesc.Buffer.NumElements = (UINT)(dstBuffer->GetDesc().Width / sizeof(float));
uavDesc.Buffer.FirstElement = 0;
uavDesc.Buffer.StructureByteStride = sizeof(float);
m_pDevice->CreateUnorderedAccessView(dstBuffer, NULL, &uavDesc, uav);
state.ApplyState(m_pDevice, cmd);
cmd->Dispatch(1, 1, 1);
state = prevState;
state.ApplyState(m_pDevice, cmd);
}
bool D3D12DebugManager::PixelHistorySetupResources(D3D12PixelHistoryResources &resources,
WrappedID3D12Resource *targetImage,
const D3D12_RESOURCE_DESC &desc,
uint32_t numEvents)
{
D3D12MarkerRegion region(
m_pDevice->GetQueue()->GetReal(),
StringFormat::Fmt("PixelHistorySetupResources %ux%ux%u %s %ux MSAA", desc.Width, desc.Height,
desc.DepthOrArraySize, ToStr(desc.Format).c_str(), desc.SampleDesc.Count));
ResourceFormat targetFmt = MakeResourceFormat(desc.Format);
ID3D12Resource *colorImage;
ID3D12Resource *dsImage;
ID3D12Resource *dstBuffer;
HRESULT hr = S_OK;
D3D12_HEAP_PROPERTIES heapProps;
heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
heapProps.CreationNodeMask = 1;
heapProps.VisibleNodeMask = 1;
D3D12_RESOURCE_DESC imageDesc = desc;
imageDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
imageDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
imageDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
hr = m_pDevice->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &imageDesc,
D3D12_RESOURCE_STATE_RENDER_TARGET, NULL,
__uuidof(ID3D12Resource), (void **)&colorImage);
m_pDevice->CheckHRESULT(hr);
if(FAILED(hr))
{
RDCERR("Failed to create scratch render target for pixel history: %s", ToStr(hr).c_str());
return false;
}
colorImage->SetName(L"Pixel History Color Image");
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {};
rtvDesc.Format = imageDesc.Format;
rtvDesc.ViewDimension = imageDesc.SampleDesc.Count > 1 ? D3D12_RTV_DIMENSION_TEXTURE2DMS
: D3D12_RTV_DIMENSION_TEXTURE2D;
D3D12_CPU_DESCRIPTOR_HANDLE rtv = m_pDevice->GetDebugManager()->GetCPUHandle(PIXEL_HISTORY_RTV);
m_pDevice->CreateRenderTargetView(colorImage, &rtvDesc, rtv);
imageDesc.Format = DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
imageDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
hr = m_pDevice->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &imageDesc,
D3D12_RESOURCE_STATE_DEPTH_WRITE, NULL,
__uuidof(ID3D12Resource), (void **)&dsImage);
m_pDevice->CheckHRESULT(hr);
if(FAILED(hr))
{
RDCERR("Failed to create scratch depth stencil for pixel history: %s", ToStr(hr).c_str());
SAFE_RELEASE(colorImage);
return false;
}
dsImage->SetName(L"Pixel History Depth Stencil");
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
dsvDesc.Format = imageDesc.Format;
dsvDesc.ViewDimension = imageDesc.SampleDesc.Count > 1 ? D3D12_DSV_DIMENSION_TEXTURE2DMS
: D3D12_DSV_DIMENSION_TEXTURE2D;
D3D12_CPU_DESCRIPTOR_HANDLE dsv = m_pDevice->GetDebugManager()->GetCPUHandle(PIXEL_HISTORY_DSV);
m_pDevice->CreateDepthStencilView(dsImage, &dsvDesc, dsv);
// With a readback heap, buffers cannot be created with the UAV flag. As a workaround, a custom heap
// can be created with the same properties as a readback heap, and then the UAV flag is permitted.
D3D12_HEAP_PROPERTIES readbackHeapProps =
m_pDevice->GetCustomHeapProperties(0, D3D12_HEAP_TYPE_READBACK);
D3D12_RESOURCE_DESC bufDesc;
bufDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
bufDesc.Alignment = 0;
bufDesc.Height = 1;
bufDesc.DepthOrArraySize = 1;
bufDesc.MipLevels = 1;
bufDesc.Format = DXGI_FORMAT_UNKNOWN;
bufDesc.SampleDesc.Count = 1;
bufDesc.SampleDesc.Quality = 0;
bufDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
bufDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
bufDesc.Width = AlignUp((uint32_t)(numEvents * sizeof(D3D12EventInfo)), 4096U);
hr = m_pDevice->CreateCommittedResource(&readbackHeapProps, D3D12_HEAP_FLAG_NONE, &bufDesc,
D3D12_RESOURCE_STATE_COPY_DEST, NULL,
__uuidof(ID3D12Resource), (void **)&dstBuffer);
m_pDevice->CheckHRESULT(hr);
if(FAILED(hr))
{
RDCERR("Failed to create readback buffer for pixel history: %s", ToStr(hr).c_str());
SAFE_RELEASE(colorImage);
SAFE_RELEASE(dsImage);
return false;
}
dstBuffer->SetName(L"Pixel History DstBuffer");
resources.colorImage = colorImage;
resources.colorDescriptor = GetWrapped(rtv);
resources.dsImage = dsImage;
resources.dsDescriptor = GetWrapped(dsv);
resources.dstBuffer = dstBuffer;
return true;
}
bool D3D12DebugManager::PixelHistoryDestroyResources(D3D12PixelHistoryResources &r)
{
SAFE_RELEASE(r.colorImage);
r.colorDescriptor = NULL;
SAFE_RELEASE(r.dsImage);
r.dsDescriptor = NULL;
SAFE_RELEASE(r.dstBuffer);
return true;
}
@@ -136,6 +136,7 @@
<ClCompile Include="d3d12_msaa_array_conv.cpp" />
<ClCompile Include="d3d12_outputwindow.cpp" />
<ClCompile Include="d3d12_overlay.cpp" />
<ClCompile Include="d3d12_pixelhistory.cpp" />
<ClCompile Include="d3d12_postvs.cpp" />
<ClCompile Include="d3d12_rendermesh.cpp" />
<ClCompile Include="d3d12_rendertext.cpp" />
@@ -227,5 +227,8 @@
<ClCompile Include="d3d12_device_rescreate_wrap.cpp">
<Filter>Wrapped</Filter>
</ClCompile>
<ClCompile Include="d3d12_pixelhistory.cpp">
<Filter>Replay</Filter>
</ClCompile>
</ItemGroup>
</Project>
+1
View File
@@ -720,6 +720,7 @@
<None Include="data\hlsl\mesh.hlsl" />
<None Include="data\hlsl\multisample.hlsl" />
<None Include="data\hlsl\pixelhistory.hlsl" />
<None Include="data\hlsl\d3d12_pixelhistory.hlsl" />
<None Include="data\hlsl\quadoverdraw.hlsl" />
<None Include="data\hlsl\texdisplay.hlsl" />
<None Include="os\win32\comexport.def" />
+3
View File
@@ -1084,6 +1084,9 @@
<None Include="data\hlsl\pixelhistory.hlsl">
<Filter>Resources\hlsl</Filter>
</None>
<None Include="data\hlsl\d3d12_pixelhistory.hlsl">
<Filter>Resources\hlsl</Filter>
</None>
<None Include="data\hlsl\quadoverdraw.hlsl">
<Filter>Resources\hlsl</Filter>
</None>