mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-29 13:20:54 +00:00
Implement MSAA to Array colour copies. Closes #1023
This commit is contained in:
@@ -172,7 +172,7 @@ float RENDERDOC_DepthCopyMSToArray(float4 pos : SV_Position) : SV_Depth
|
||||
return 0;
|
||||
}
|
||||
|
||||
Texture2DArray<uint4> sourceArray : register(t0);
|
||||
Texture2DArray<uint4> sourceArray : register(t1);
|
||||
|
||||
uint4 RENDERDOC_CopyArrayToMS(float4 pos : SV_Position, uint curSample : SV_SampleIndex) : SV_Target0
|
||||
{
|
||||
@@ -181,7 +181,7 @@ uint4 RENDERDOC_CopyArrayToMS(float4 pos : SV_Position, uint curSample : SV_Samp
|
||||
return sourceArray.Load(srcCoord);
|
||||
}
|
||||
|
||||
Texture2DArray<float4> sourceFloatArray : register(t0);
|
||||
Texture2DArray<float4> sourceFloatArray : register(t1);
|
||||
|
||||
float4 RENDERDOC_FloatCopyArrayToMS(float4 pos : SV_Position, uint curSample : SV_SampleIndex) : SV_Target0
|
||||
{
|
||||
@@ -190,8 +190,8 @@ float4 RENDERDOC_FloatCopyArrayToMS(float4 pos : SV_Position, uint curSample : S
|
||||
return sourceFloatArray.Load(srcCoord);
|
||||
}
|
||||
|
||||
Texture2DArray<float2> sourceDepthArray : register(t0);
|
||||
Texture2DArray<uint2> sourceStencilArray : register(t1);
|
||||
Texture2DArray<float2> sourceDepthArray : register(t1);
|
||||
Texture2DArray<uint2> sourceStencilArray : register(t11);
|
||||
|
||||
float RENDERDOC_DepthCopyArrayToMS(float4 pos : SV_Position, uint curSample : SV_SampleIndex) : SV_Depth
|
||||
{
|
||||
|
||||
@@ -56,8 +56,8 @@ struct Tex2DMSToArrayStateTracker
|
||||
// only need to save/restore constant buffer 0
|
||||
PS.ConstantBuffers[0] = UNWRAP(WrappedID3D11Buffer, PS.ConstantBuffers[0]);
|
||||
|
||||
// same for the first 8 SRVs
|
||||
for(int i = 0; i < 8; i++)
|
||||
// same for the first 16 SRVs
|
||||
for(int i = 0; i < 16; i++)
|
||||
PS.SRVs[i] = UNWRAP(WrappedID3D11ShaderResourceView1, PS.SRVs[i]);
|
||||
|
||||
for(int i = 0; i < D3D11_SHADER_MAX_INTERFACES; i++)
|
||||
@@ -88,7 +88,7 @@ struct Tex2DMSToArrayStateTracker
|
||||
context->IASetInputLayout(Layout);
|
||||
context->VSSetShader((ID3D11VertexShader *)VS.Shader, VS.Instances, VS.NumInstances);
|
||||
|
||||
context->PSSetShaderResources(0, 8, PS.SRVs);
|
||||
context->PSSetShaderResources(0, 16, PS.SRVs);
|
||||
context->PSSetShader((ID3D11PixelShader *)PS.Shader, PS.Instances, PS.NumInstances);
|
||||
|
||||
if(m_WrappedContext->IsFL11_1())
|
||||
@@ -369,7 +369,7 @@ void D3D11DebugManager::CopyArrayToTex2DMS(ID3D11Texture2D *destMS, ID3D11Textur
|
||||
ID3D11ShaderResourceView *srvs[8] = {NULL};
|
||||
srvs[0] = srvArray;
|
||||
|
||||
m_pImmediateContext->PSSetShaderResources(0, 8, srvs);
|
||||
m_pImmediateContext->PSSetShaderResources(1, 8, srvs);
|
||||
|
||||
// loop over every array slice in MS texture
|
||||
for(UINT slice = 0; slice < descMS.ArraySize; slice++)
|
||||
@@ -428,7 +428,7 @@ void D3D11DebugManager::CopyArrayToTex2DMS(ID3D11Texture2D *destMS, ID3D11Textur
|
||||
return;
|
||||
}
|
||||
|
||||
m_pImmediateContext->PSSetShaderResources(1, 1, &srvArray);
|
||||
m_pImmediateContext->PSSetShaderResources(11, 1, &srvArray);
|
||||
|
||||
D3D11_DEPTH_STENCIL_DESC dsDesc;
|
||||
ID3D11DepthStencilState *dsState = NULL;
|
||||
|
||||
@@ -158,7 +158,13 @@ bool D3D12InitParams::IsSupportedVersion(uint64_t ver)
|
||||
if(ver == CurrentVersion)
|
||||
return true;
|
||||
|
||||
// see header for explanation of version changes
|
||||
// 0x5 -> 0x6 - Multiply by number of planes in format when serialising initial states -
|
||||
// i.e. stencil is saved with depth in initial states.
|
||||
if(ver == 0x4)
|
||||
return true;
|
||||
|
||||
// 0x4 -> 0x5 - CPU_DESCRIPTOR_HANDLE serialised inline as D3D12Descriptor in appropriate
|
||||
// list-recording functions
|
||||
if(ver == 0x4)
|
||||
return true;
|
||||
|
||||
|
||||
@@ -104,6 +104,8 @@ D3D12DebugManager::D3D12DebugManager(WrappedID3D12Device *wrapper)
|
||||
m_pDevice = wrapper;
|
||||
m_pDevice->InternalRef();
|
||||
|
||||
D3D12ResourceManager *rm = wrapper->GetResourceManager();
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC desc;
|
||||
@@ -112,6 +114,8 @@ D3D12DebugManager::D3D12DebugManager(WrappedID3D12Device *wrapper)
|
||||
desc.NumDescriptors = 1024;
|
||||
desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
||||
|
||||
RDCCOMPILE_ASSERT(FIRST_WIN_RTV + 256 < 1024, "Increase size of RTV heap");
|
||||
|
||||
hr = m_pDevice->CreateDescriptorHeap(&desc, __uuidof(ID3D12DescriptorHeap), (void **)&rtvHeap);
|
||||
|
||||
if(FAILED(hr))
|
||||
@@ -119,9 +123,13 @@ D3D12DebugManager::D3D12DebugManager(WrappedID3D12Device *wrapper)
|
||||
RDCERR("Couldn't create RTV descriptor heap! HRESULT: %s", ToStr(hr).c_str());
|
||||
}
|
||||
|
||||
desc.NumDescriptors = 16;
|
||||
rm->SetInternalResource(rtvHeap);
|
||||
|
||||
desc.NumDescriptors = 64;
|
||||
desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
|
||||
|
||||
RDCCOMPILE_ASSERT(FIRST_WIN_DSV + 32 < 64, "Increase size of DSV heap");
|
||||
|
||||
hr = m_pDevice->CreateDescriptorHeap(&desc, __uuidof(ID3D12DescriptorHeap), (void **)&dsvHeap);
|
||||
|
||||
if(FAILED(hr))
|
||||
@@ -129,9 +137,13 @@ D3D12DebugManager::D3D12DebugManager(WrappedID3D12Device *wrapper)
|
||||
RDCERR("Couldn't create DSV descriptor heap! HRESULT: %s", ToStr(hr).c_str());
|
||||
}
|
||||
|
||||
rm->SetInternalResource(dsvHeap);
|
||||
|
||||
desc.NumDescriptors = 4096;
|
||||
desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
|
||||
RDCCOMPILE_ASSERT(MAX_SRV_SLOT < 4096, "Increase size of CBV/SRV/UAV heap");
|
||||
|
||||
hr = m_pDevice->CreateDescriptorHeap(&desc, __uuidof(ID3D12DescriptorHeap), (void **)&uavClearHeap);
|
||||
|
||||
if(FAILED(hr))
|
||||
@@ -139,6 +151,8 @@ D3D12DebugManager::D3D12DebugManager(WrappedID3D12Device *wrapper)
|
||||
RDCERR("Couldn't create CBV/SRV descriptor heap! HRESULT: %s", ToStr(hr).c_str());
|
||||
}
|
||||
|
||||
rm->SetInternalResource(uavClearHeap);
|
||||
|
||||
desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
|
||||
hr = m_pDevice->CreateDescriptorHeap(&desc, __uuidof(ID3D12DescriptorHeap),
|
||||
@@ -149,6 +163,8 @@ D3D12DebugManager::D3D12DebugManager(WrappedID3D12Device *wrapper)
|
||||
RDCERR("Couldn't create CBV/SRV descriptor heap! HRESULT: %s", ToStr(hr).c_str());
|
||||
}
|
||||
|
||||
rm->SetInternalResource(cbvsrvuavHeap);
|
||||
|
||||
desc.NumDescriptors = 16;
|
||||
desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
|
||||
|
||||
@@ -159,6 +175,8 @@ D3D12DebugManager::D3D12DebugManager(WrappedID3D12Device *wrapper)
|
||||
RDCERR("Couldn't create sampler descriptor heap! HRESULT: %s", ToStr(hr).c_str());
|
||||
}
|
||||
|
||||
rm->SetInternalResource(samplerHeap);
|
||||
|
||||
// create fixed samplers, point and linear
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE samp;
|
||||
samp = samplerHeap->GetCPUDescriptorHandleForHeapStart();
|
||||
@@ -207,6 +225,28 @@ D3D12DebugManager::D3D12DebugManager(WrappedID3D12Device *wrapper)
|
||||
__uuidof(ID3D12RootSignature), (void **)&m_CBOnlyRootSig);
|
||||
|
||||
SAFE_RELEASE(root);
|
||||
|
||||
rm->SetInternalResource(m_CBOnlyRootSig);
|
||||
}
|
||||
|
||||
{
|
||||
ID3DBlob *root = shaderCache->MakeRootSig({
|
||||
// cbuffer
|
||||
cbvParam(D3D12_SHADER_VISIBILITY_PIXEL, 0, 0),
|
||||
// normal SRVs (2x, 4x, 8x, 16x, 32x)
|
||||
tableParam(D3D12_SHADER_VISIBILITY_PIXEL, D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 1, 5),
|
||||
// stencil SRVs (2x, 4x, 8x, 16x, 32x)
|
||||
tableParam(D3D12_SHADER_VISIBILITY_PIXEL, D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 11, 5),
|
||||
});
|
||||
|
||||
RDCASSERT(root);
|
||||
|
||||
hr = m_pDevice->CreateRootSignature(0, root->GetBufferPointer(), root->GetBufferSize(),
|
||||
__uuidof(ID3D12RootSignature), (void **)&m_ArrayMSAARootSig);
|
||||
|
||||
SAFE_RELEASE(root);
|
||||
|
||||
rm->SetInternalResource(m_ArrayMSAARootSig);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -220,6 +260,33 @@ D3D12DebugManager::D3D12DebugManager(WrappedID3D12Device *wrapper)
|
||||
"ps_5_0", &m_MeshPS);
|
||||
}
|
||||
|
||||
{
|
||||
std::string displayhlsl = GetEmbeddedResource(debugcbuffers_h);
|
||||
displayhlsl += GetEmbeddedResource(debugcommon_hlsl);
|
||||
displayhlsl += GetEmbeddedResource(debugdisplay_hlsl);
|
||||
|
||||
shaderCache->GetShaderBlob(displayhlsl.c_str(), "RENDERDOC_FullscreenVS",
|
||||
D3DCOMPILE_WARNINGS_ARE_ERRORS, "vs_5_0", &m_FullscreenVS);
|
||||
}
|
||||
|
||||
{
|
||||
std::string multisamplehlsl = GetEmbeddedResource(multisample_hlsl);
|
||||
|
||||
shaderCache->GetShaderBlob(multisamplehlsl.c_str(), "RENDERDOC_CopyMSToArray",
|
||||
D3DCOMPILE_WARNINGS_ARE_ERRORS, "ps_5_0", &m_IntMS2Array);
|
||||
shaderCache->GetShaderBlob(multisamplehlsl.c_str(), "RENDERDOC_FloatCopyMSToArray",
|
||||
D3DCOMPILE_WARNINGS_ARE_ERRORS, "ps_5_0", &m_FloatMS2Array);
|
||||
shaderCache->GetShaderBlob(multisamplehlsl.c_str(), "RENDERDOC_DepthCopyMSToArray",
|
||||
D3DCOMPILE_WARNINGS_ARE_ERRORS, "ps_5_0", &m_DepthMS2Array);
|
||||
|
||||
shaderCache->GetShaderBlob(multisamplehlsl.c_str(), "RENDERDOC_CopyArrayToMS",
|
||||
D3DCOMPILE_WARNINGS_ARE_ERRORS, "ps_5_0", &m_IntArray2MS);
|
||||
shaderCache->GetShaderBlob(multisamplehlsl.c_str(), "RENDERDOC_FloatCopyArrayToMS",
|
||||
D3DCOMPILE_WARNINGS_ARE_ERRORS, "ps_5_0", &m_FloatArray2MS);
|
||||
shaderCache->GetShaderBlob(multisamplehlsl.c_str(), "RENDERDOC_DepthCopyArrayToMS",
|
||||
D3DCOMPILE_WARNINGS_ARE_ERRORS, "ps_5_0", &m_DepthArray2MS);
|
||||
}
|
||||
|
||||
shaderCache->SetCaching(false);
|
||||
|
||||
D3D12_RESOURCE_DESC readbackDesc;
|
||||
@@ -248,6 +315,8 @@ D3D12DebugManager::D3D12DebugManager(WrappedID3D12Device *wrapper)
|
||||
|
||||
m_ReadbackBuffer->SetName(L"m_ReadbackBuffer");
|
||||
|
||||
rm->SetInternalResource(m_ReadbackBuffer);
|
||||
|
||||
hr = m_pDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT,
|
||||
__uuidof(ID3D12CommandAllocator), (void **)&m_DebugAlloc);
|
||||
|
||||
@@ -257,6 +326,8 @@ D3D12DebugManager::D3D12DebugManager(WrappedID3D12Device *wrapper)
|
||||
return;
|
||||
}
|
||||
|
||||
rm->SetInternalResource(m_DebugAlloc);
|
||||
|
||||
ID3D12GraphicsCommandList *list = NULL;
|
||||
|
||||
hr = m_pDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_DebugAlloc, NULL,
|
||||
@@ -271,6 +342,8 @@ D3D12DebugManager::D3D12DebugManager(WrappedID3D12Device *wrapper)
|
||||
return;
|
||||
}
|
||||
|
||||
rm->SetInternalResource(m_DebugList);
|
||||
|
||||
if(m_DebugList)
|
||||
m_DebugList->Close();
|
||||
}
|
||||
@@ -287,10 +360,16 @@ D3D12DebugManager::~D3D12DebugManager()
|
||||
SAFE_RELEASE(uavClearHeap);
|
||||
SAFE_RELEASE(samplerHeap);
|
||||
|
||||
SAFE_RELEASE(m_CBOnlyRootSig);
|
||||
SAFE_RELEASE(m_ArrayMSAARootSig);
|
||||
|
||||
SAFE_RELEASE(m_RingConstantBuffer);
|
||||
|
||||
SAFE_RELEASE(m_TexResource);
|
||||
|
||||
SAFE_RELEASE(m_DebugAlloc);
|
||||
SAFE_RELEASE(m_DebugList);
|
||||
|
||||
m_pDevice->InternalRelease();
|
||||
|
||||
if(RenderDoc::Inst().GetCrashHandler())
|
||||
@@ -361,7 +440,9 @@ D3D12_GPU_VIRTUAL_ADDRESS D3D12DebugManager::UploadConstants(const void *data, s
|
||||
|
||||
ret += m_RingConstantOffset;
|
||||
|
||||
FillBuffer(m_RingConstantBuffer, (size_t)m_RingConstantOffset, data, size);
|
||||
// passing the unwrapped object here is immaterial as all we do is Map/Unmap, but it means we can
|
||||
// call this function while capturing without worrying about serialising the map or deadlocking.
|
||||
FillBuffer(Unwrap(m_RingConstantBuffer), (size_t)m_RingConstantOffset, data, size);
|
||||
|
||||
m_RingConstantOffset += size;
|
||||
m_RingConstantOffset =
|
||||
@@ -1201,6 +1282,11 @@ void D3D12Replay::TextureRendering::Init(WrappedID3D12Device *device, D3D12Debug
|
||||
hr = device->CreateRootSignature(0, root->GetBufferPointer(), root->GetBufferSize(),
|
||||
__uuidof(ID3D12RootSignature), (void **)&RootSig);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
RDCERR("Couldn't create tex display RootSig! HRESULT: %s", ToStr(hr).c_str());
|
||||
}
|
||||
|
||||
SAFE_RELEASE(root);
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,19 @@ enum CBVUAVSRVSlot
|
||||
PICK_RESULT_CLEAR_UAV,
|
||||
|
||||
TMP_UAV,
|
||||
|
||||
MSAA_SRV2x,
|
||||
MSAA_SRV4x,
|
||||
MSAA_SRV8x,
|
||||
MSAA_SRV16x,
|
||||
MSAA_SRV32x,
|
||||
STENCIL_MSAA_SRV2x,
|
||||
STENCIL_MSAA_SRV4x,
|
||||
STENCIL_MSAA_SRV8x,
|
||||
STENCIL_MSAA_SRV16x,
|
||||
STENCIL_MSAA_SRV32x,
|
||||
|
||||
MAX_SRV_SLOT,
|
||||
};
|
||||
|
||||
enum RTVSlot
|
||||
@@ -64,6 +77,7 @@ enum RTVSlot
|
||||
CUSTOM_SHADER_RTV,
|
||||
OVERLAY_RTV,
|
||||
GET_TEX_RTV,
|
||||
MSAA_RTV,
|
||||
FIRST_TMP_RTV,
|
||||
LAST_TMP_RTV = FIRST_TMP_RTV + 16,
|
||||
FIRST_WIN_RTV,
|
||||
@@ -79,6 +93,7 @@ enum SamplerSlot
|
||||
enum DSVSlot
|
||||
{
|
||||
OVERLAY_DSV,
|
||||
MSAA_DSV,
|
||||
TMP_DSV,
|
||||
FIRST_WIN_DSV,
|
||||
};
|
||||
@@ -139,6 +154,9 @@ public:
|
||||
MeshDisplayPipelines CacheMeshDisplayPipelines(const MeshFormat &primary,
|
||||
const MeshFormat &secondary);
|
||||
|
||||
void CopyTex2DMSToArray(ID3D12Resource *destArray, ID3D12Resource *srcMS);
|
||||
void CopyArrayToTex2DMS(ID3D12Resource *destMS, ID3D12Resource *srcArray, UINT selectedSlice);
|
||||
|
||||
private:
|
||||
WrappedID3D12Device *m_pDevice = NULL;
|
||||
|
||||
@@ -168,6 +186,18 @@ private:
|
||||
|
||||
ID3D12Resource *m_ReadbackBuffer = NULL;
|
||||
|
||||
// Array <-> MSAA copying
|
||||
ID3D12RootSignature *m_ArrayMSAARootSig = NULL;
|
||||
ID3DBlob *m_FullscreenVS = NULL;
|
||||
|
||||
ID3DBlob *m_IntMS2Array = NULL;
|
||||
ID3DBlob *m_FloatMS2Array = NULL;
|
||||
ID3DBlob *m_DepthMS2Array = NULL;
|
||||
|
||||
ID3DBlob *m_IntArray2MS = NULL;
|
||||
ID3DBlob *m_FloatArray2MS = NULL;
|
||||
ID3DBlob *m_DepthArray2MS = NULL;
|
||||
|
||||
// Debug lists
|
||||
ID3D12GraphicsCommandList2 *m_DebugList = NULL;
|
||||
ID3D12CommandAllocator *m_DebugAlloc = NULL;
|
||||
|
||||
@@ -2295,8 +2295,7 @@ void WrappedID3D12Device::CreateInternalResources()
|
||||
if(m_TextRenderer == NULL)
|
||||
m_TextRenderer = new D3D12TextRenderer(this);
|
||||
|
||||
if(IsReplayMode(m_State))
|
||||
m_Replay.CreateResources();
|
||||
m_Replay.CreateResources();
|
||||
|
||||
WrappedID3D12Shader::InternalResources(false);
|
||||
}
|
||||
|
||||
@@ -46,10 +46,7 @@ struct D3D12InitParams
|
||||
D3D_FEATURE_LEVEL MinimumFeatureLevel;
|
||||
|
||||
// check if a frame capture section version is supported
|
||||
static const uint64_t CurrentVersion = 0x5;
|
||||
|
||||
// 0x4 -> 0x5 - CPU_DESCRIPTOR_HANDLE serialised inline as D3D12Descriptor in appropriate
|
||||
// list-recording functions
|
||||
static const uint64_t CurrentVersion = 0x6;
|
||||
|
||||
static bool IsSupportedVersion(uint64_t ver);
|
||||
};
|
||||
@@ -61,6 +58,7 @@ class WrappedID3D12Resource;
|
||||
|
||||
class D3D12TextRenderer;
|
||||
class D3D12ShaderCache;
|
||||
class D3D12DebugManager;
|
||||
|
||||
// give every impression of working but do nothing.
|
||||
// Just allow the user to call functions so that they don't
|
||||
@@ -405,6 +403,7 @@ public:
|
||||
static std::string GetChunkName(uint32_t idx);
|
||||
D3D12ResourceManager *GetResourceManager() { return m_ResourceManager; }
|
||||
D3D12ShaderCache *GetShaderCache() { return m_ShaderCache; }
|
||||
D3D12DebugManager *GetDebugManager() { return m_Replay.GetDebugManager(); }
|
||||
ResourceId GetResourceID() { return m_ResourceID; }
|
||||
Threading::RWLock &GetCapTransitionLock() { return m_CapTransitionLock; }
|
||||
void ReleaseSwapchainResources(IDXGISwapChain *swap, IUnknown **backbuffers, int numBackbuffers);
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "driver/dxgi/dxgi_common.h"
|
||||
#include "d3d12_command_list.h"
|
||||
#include "d3d12_command_queue.h"
|
||||
#include "d3d12_debug.h"
|
||||
#include "d3d12_device.h"
|
||||
#include "d3d12_manager.h"
|
||||
#include "d3d12_resources.h"
|
||||
@@ -67,14 +68,7 @@ bool D3D12ResourceManager::Prepare_InitialState(ID3D12DeviceChild *res)
|
||||
|
||||
D3D12_RESOURCE_DESC desc = r->GetDesc();
|
||||
|
||||
if(desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D && desc.SampleDesc.Count > 1)
|
||||
{
|
||||
D3D12NOTIMP("Multisampled initial contents");
|
||||
|
||||
SetInitialContents(GetResID(r), D3D12InitialContents(D3D12InitialContents::Multisampled));
|
||||
return true;
|
||||
}
|
||||
else if(desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
|
||||
if(desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
|
||||
{
|
||||
D3D12_HEAP_PROPERTIES heapProps;
|
||||
r->GetHeapProperties(&heapProps, NULL);
|
||||
@@ -128,6 +122,99 @@ bool D3D12ResourceManager::Prepare_InitialState(ID3D12DeviceChild *res)
|
||||
}
|
||||
else
|
||||
{
|
||||
if(nonresident)
|
||||
m_Device->MakeResident(1, &pageable);
|
||||
|
||||
ID3D12Resource *arrayTexture = NULL;
|
||||
D3D12_RESOURCE_STATES destState = D3D12_RESOURCE_STATE_COPY_SOURCE;
|
||||
ID3D12Resource *unwrappedCopySource = r->GetReal();
|
||||
|
||||
if(desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D && desc.SampleDesc.Count > 1)
|
||||
{
|
||||
bool isDepth = IsDepthFormat(desc.Format);
|
||||
|
||||
desc.Alignment = 0;
|
||||
desc.DepthOrArraySize *= (UINT16)desc.SampleDesc.Count;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
|
||||
if(isDepth)
|
||||
desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
|
||||
else
|
||||
desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
|
||||
|
||||
D3D12_HEAP_PROPERTIES defaultHeap;
|
||||
defaultHeap.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
defaultHeap.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
defaultHeap.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
defaultHeap.CreationNodeMask = 1;
|
||||
defaultHeap.VisibleNodeMask = 1;
|
||||
|
||||
// we don't want to serialise this resource's creation, so wrap it manually
|
||||
HRESULT hr = m_Device->GetReal()->CreateCommittedResource(
|
||||
&defaultHeap, D3D12_HEAP_FLAG_NONE, &desc,
|
||||
isDepth ? D3D12_RESOURCE_STATE_DEPTH_WRITE : D3D12_RESOURCE_STATE_RENDER_TARGET, NULL,
|
||||
__uuidof(ID3D12Resource), (void **)&arrayTexture);
|
||||
RDCASSERTEQUAL(hr, S_OK);
|
||||
|
||||
destState = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
||||
}
|
||||
|
||||
ID3D12GraphicsCommandList *list = Unwrap(m_Device->GetInitialStateList());
|
||||
|
||||
vector<D3D12_RESOURCE_BARRIER> barriers;
|
||||
|
||||
{
|
||||
const vector<D3D12_RESOURCE_STATES> &states = m_Device->GetSubresourceStates(GetResID(r));
|
||||
|
||||
barriers.reserve(states.size());
|
||||
|
||||
for(size_t i = 0; i < states.size(); i++)
|
||||
{
|
||||
if(states[i] & D3D12_RESOURCE_STATE_COPY_SOURCE)
|
||||
continue;
|
||||
|
||||
D3D12_RESOURCE_BARRIER barrier;
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
barrier.Transition.pResource = r->GetReal();
|
||||
barrier.Transition.Subresource = (UINT)i;
|
||||
barrier.Transition.StateBefore = states[i];
|
||||
barrier.Transition.StateAfter = destState;
|
||||
|
||||
barriers.push_back(barrier);
|
||||
}
|
||||
|
||||
// transition to copy dest
|
||||
if(!barriers.empty())
|
||||
list->ResourceBarrier((UINT)barriers.size(), &barriers[0]);
|
||||
}
|
||||
|
||||
if(arrayTexture)
|
||||
{
|
||||
// execute the above barriers
|
||||
m_Device->CloseInitialStateList();
|
||||
|
||||
m_Device->ExecuteLists(NULL, true);
|
||||
m_Device->FlushLists();
|
||||
|
||||
// expand multisamples out to array
|
||||
m_Device->GetDebugManager()->CopyTex2DMSToArray(arrayTexture, r->GetReal());
|
||||
|
||||
// open the initial state list again for the remainder of the work
|
||||
list = Unwrap(m_Device->GetInitialStateList());
|
||||
|
||||
D3D12_RESOURCE_BARRIER b = {};
|
||||
b.Transition.pResource = arrayTexture;
|
||||
b.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
b.Transition.StateBefore = IsDepthFormat(desc.Format) ? D3D12_RESOURCE_STATE_DEPTH_WRITE
|
||||
: D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
b.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE;
|
||||
list->ResourceBarrier(1, &b);
|
||||
|
||||
unwrappedCopySource = arrayTexture;
|
||||
}
|
||||
|
||||
D3D12_HEAP_PROPERTIES heapProps;
|
||||
heapProps.Type = D3D12_HEAP_TYPE_READBACK;
|
||||
heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
@@ -153,6 +240,17 @@ bool D3D12ResourceManager::Prepare_InitialState(ID3D12DeviceChild *res)
|
||||
if(desc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D)
|
||||
numSubresources *= desc.DepthOrArraySize;
|
||||
|
||||
// account for multiple planes (i.e. depth and stencil)
|
||||
{
|
||||
D3D12_FEATURE_DATA_FORMAT_INFO formatInfo = {};
|
||||
formatInfo.Format = desc.Format;
|
||||
m_Device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &formatInfo, sizeof(formatInfo));
|
||||
|
||||
UINT planes = RDCMAX((UINT8)1, formatInfo.PlaneCount);
|
||||
|
||||
numSubresources *= planes;
|
||||
}
|
||||
|
||||
D3D12_PLACED_SUBRESOURCE_FOOTPRINT *layouts =
|
||||
new D3D12_PLACED_SUBRESOURCE_FOOTPRINT[numSubresources];
|
||||
|
||||
@@ -164,45 +262,14 @@ bool D3D12ResourceManager::Prepare_InitialState(ID3D12DeviceChild *res)
|
||||
&heapProps, D3D12_HEAP_FLAG_NONE, &bufDesc, D3D12_RESOURCE_STATE_COPY_DEST, NULL,
|
||||
__uuidof(ID3D12Resource), (void **)©Dst);
|
||||
|
||||
if(nonresident)
|
||||
m_Device->MakeResident(1, &pageable);
|
||||
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
ID3D12GraphicsCommandList *list = Unwrap(m_Device->GetInitialStateList());
|
||||
|
||||
vector<D3D12_RESOURCE_BARRIER> barriers;
|
||||
|
||||
const vector<D3D12_RESOURCE_STATES> &states = m_Device->GetSubresourceStates(GetResID(r));
|
||||
|
||||
barriers.reserve(states.size());
|
||||
|
||||
for(size_t i = 0; i < states.size(); i++)
|
||||
{
|
||||
if(states[i] & D3D12_RESOURCE_STATE_COPY_SOURCE)
|
||||
continue;
|
||||
|
||||
D3D12_RESOURCE_BARRIER barrier;
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
barrier.Transition.pResource = r->GetReal();
|
||||
barrier.Transition.Subresource = (UINT)i;
|
||||
barrier.Transition.StateBefore = states[i];
|
||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE;
|
||||
|
||||
barriers.push_back(barrier);
|
||||
}
|
||||
|
||||
// transition to copy dest
|
||||
if(!barriers.empty())
|
||||
list->ResourceBarrier((UINT)barriers.size(), &barriers[0]);
|
||||
|
||||
for(UINT i = 0; i < numSubresources; i++)
|
||||
{
|
||||
D3D12_TEXTURE_COPY_LOCATION dst, src;
|
||||
|
||||
src.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||
src.pResource = r->GetReal();
|
||||
src.pResource = unwrappedCopySource;
|
||||
src.SubresourceIndex = i;
|
||||
|
||||
dst.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
||||
@@ -211,29 +278,31 @@ bool D3D12ResourceManager::Prepare_InitialState(ID3D12DeviceChild *res)
|
||||
|
||||
list->CopyTextureRegion(&dst, 0, 0, 0, &src, NULL);
|
||||
}
|
||||
|
||||
// transition back
|
||||
for(size_t i = 0; i < barriers.size(); i++)
|
||||
std::swap(barriers[i].Transition.StateBefore, barriers[i].Transition.StateAfter);
|
||||
|
||||
if(!barriers.empty())
|
||||
list->ResourceBarrier((UINT)barriers.size(), &barriers[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Couldn't create readback buffer: HRESULT: %s", ToStr(hr).c_str());
|
||||
}
|
||||
|
||||
if(nonresident)
|
||||
// transition back
|
||||
for(size_t i = 0; i < barriers.size(); i++)
|
||||
std::swap(barriers[i].Transition.StateBefore, barriers[i].Transition.StateAfter);
|
||||
|
||||
if(!barriers.empty())
|
||||
list->ResourceBarrier((UINT)barriers.size(), &barriers[0]);
|
||||
|
||||
if(nonresident || arrayTexture)
|
||||
{
|
||||
m_Device->CloseInitialStateList();
|
||||
|
||||
m_Device->ExecuteLists(NULL, true);
|
||||
m_Device->FlushLists();
|
||||
|
||||
m_Device->Evict(1, &pageable);
|
||||
if(nonresident)
|
||||
m_Device->Evict(1, &pageable);
|
||||
}
|
||||
|
||||
SAFE_RELEASE(arrayTexture);
|
||||
SAFE_DELETE_ARRAY(layouts);
|
||||
|
||||
SetInitialContents(GetResID(r), D3D12InitialContents(copyDst));
|
||||
@@ -269,11 +338,6 @@ uint32_t D3D12ResourceManager::GetSize_InitialState(ResourceId id, ID3D12DeviceC
|
||||
{
|
||||
buf = (ID3D12Resource *)res;
|
||||
}
|
||||
else if(initContents.tag == D3D12InitialContents::Multisampled)
|
||||
{
|
||||
D3D12NOTIMP("Multisampled initial contents");
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
return (uint32_t)WriteSerialiser::GetChunkAlignment() + 16 +
|
||||
uint32_t(buf ? buf->GetDesc().Width : 0);
|
||||
@@ -383,11 +447,6 @@ bool D3D12ResourceManager::Serialise_InitialState(SerialiserType &ser, ResourceI
|
||||
{
|
||||
mappedBuffer = (ID3D12Resource *)liveRes;
|
||||
}
|
||||
else if(initContents.tag == D3D12InitialContents::Multisampled)
|
||||
{
|
||||
D3D12NOTIMP("Multisampled initial contents");
|
||||
mappedBuffer = NULL;
|
||||
}
|
||||
|
||||
if(mappedBuffer)
|
||||
{
|
||||
@@ -417,12 +476,7 @@ bool D3D12ResourceManager::Serialise_InitialState(SerialiserType &ser, ResourceI
|
||||
D3D12_HEAP_PROPERTIES heapProps = {};
|
||||
((ID3D12Resource *)liveRes)->GetHeapProperties(&heapProps, NULL);
|
||||
|
||||
if(resDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D && resDesc.SampleDesc.Count > 1)
|
||||
{
|
||||
initContents.tag = D3D12InitialContents::Multisampled;
|
||||
D3D12NOTIMP("Multisampled initial contents");
|
||||
}
|
||||
else if(heapProps.Type == D3D12_HEAP_TYPE_UPLOAD)
|
||||
if(heapProps.Type == D3D12_HEAP_TYPE_UPLOAD)
|
||||
{
|
||||
// if destination is on the upload heap, it's impossible to copy via the device,
|
||||
// so we have to CPU copy. To save time and make a more optimal copy, we just keep the data
|
||||
@@ -457,9 +511,9 @@ bool D3D12ResourceManager::Serialise_InitialState(SerialiserType &ser, ResourceI
|
||||
desc.Width = RDCMAX(ContentsLength, 64ULL);
|
||||
|
||||
ID3D12Resource *copySrc = NULL;
|
||||
HRESULT hr = m_Device->GetReal()->CreateCommittedResource(
|
||||
&heapProps, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
|
||||
__uuidof(ID3D12Resource), (void **)©Src);
|
||||
HRESULT hr = m_Device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &desc,
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
|
||||
__uuidof(ID3D12Resource), (void **)©Src);
|
||||
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
@@ -506,10 +560,149 @@ bool D3D12ResourceManager::Serialise_InitialState(SerialiserType &ser, ResourceI
|
||||
{
|
||||
initContents.resourceType = Resource_Resource;
|
||||
initContents.resource = mappedBuffer;
|
||||
SetInitialContents(id, initContents);
|
||||
}
|
||||
|
||||
return true;
|
||||
D3D12_RESOURCE_DESC resDesc = ((ID3D12Resource *)liveRes)->GetDesc();
|
||||
|
||||
// for MSAA textures we upload to an MSAA texture here so we're ready to copy the image in
|
||||
// Apply_InitState
|
||||
if(resDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D && resDesc.SampleDesc.Count > 1)
|
||||
{
|
||||
if(ContentsLength == 0)
|
||||
{
|
||||
// backwards compatibility - older captures will have no data for MSAA textures.
|
||||
initContents.resource = NULL;
|
||||
SAFE_RELEASE(mappedBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D12_HEAP_PROPERTIES heapProps = {};
|
||||
((ID3D12Resource *)liveRes)->GetHeapProperties(&heapProps, NULL);
|
||||
|
||||
ID3D12GraphicsCommandList *list = Unwrap(m_Device->GetInitialStateList());
|
||||
|
||||
D3D12_RESOURCE_DESC arrayDesc = resDesc;
|
||||
arrayDesc.Alignment = 0;
|
||||
arrayDesc.DepthOrArraySize *= (UINT16)arrayDesc.SampleDesc.Count;
|
||||
arrayDesc.SampleDesc.Count = 1;
|
||||
arrayDesc.SampleDesc.Quality = 0;
|
||||
arrayDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
bool isDepth = IsDepthFormat(resDesc.Format);
|
||||
|
||||
D3D12_RESOURCE_DESC msaaDesc = resDesc;
|
||||
arrayDesc.Alignment = 0;
|
||||
arrayDesc.Flags = isDepth ? D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL
|
||||
: D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
|
||||
|
||||
ID3D12Resource *arrayTex = NULL;
|
||||
HRESULT hr = m_Device->CreateCommittedResource(
|
||||
&heapProps, D3D12_HEAP_FLAG_NONE, &arrayDesc, D3D12_RESOURCE_STATE_COPY_DEST, NULL,
|
||||
__uuidof(ID3D12Resource), (void **)&arrayTex);
|
||||
if(FAILED(hr))
|
||||
{
|
||||
RDCERR("Couldn't create temporary array texture: %s", ToStr(hr).c_str());
|
||||
ret = false;
|
||||
}
|
||||
|
||||
ID3D12Resource *msaaTex = NULL;
|
||||
hr = m_Device->CreateCommittedResource(
|
||||
&heapProps, D3D12_HEAP_FLAG_NONE, &msaaDesc,
|
||||
isDepth ? D3D12_RESOURCE_STATE_DEPTH_WRITE : D3D12_RESOURCE_STATE_RENDER_TARGET, NULL,
|
||||
__uuidof(ID3D12Resource), (void **)&msaaTex);
|
||||
RDCASSERTEQUAL(hr, S_OK);
|
||||
if(FAILED(hr))
|
||||
{
|
||||
RDCERR("Couldn't create init state MSAA texture: %s", ToStr(hr).c_str());
|
||||
ret = false;
|
||||
}
|
||||
|
||||
// copy buffer to array texture
|
||||
if(arrayTex)
|
||||
{
|
||||
uint32_t numSubresources = arrayDesc.DepthOrArraySize;
|
||||
|
||||
{
|
||||
D3D12_FEATURE_DATA_FORMAT_INFO formatInfo = {};
|
||||
formatInfo.Format = arrayDesc.Format;
|
||||
m_Device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &formatInfo,
|
||||
sizeof(formatInfo));
|
||||
|
||||
UINT planes = RDCMAX((UINT8)1, formatInfo.PlaneCount);
|
||||
|
||||
numSubresources *= planes;
|
||||
}
|
||||
|
||||
D3D12_PLACED_SUBRESOURCE_FOOTPRINT *layouts =
|
||||
new D3D12_PLACED_SUBRESOURCE_FOOTPRINT[numSubresources];
|
||||
|
||||
m_Device->GetCopyableFootprints(&arrayDesc, 0, numSubresources, 0, layouts, NULL, NULL,
|
||||
NULL);
|
||||
|
||||
for(UINT i = 0; i < numSubresources; i++)
|
||||
{
|
||||
D3D12_TEXTURE_COPY_LOCATION dst, src;
|
||||
|
||||
dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||
dst.pResource = Unwrap(arrayTex);
|
||||
dst.SubresourceIndex = i;
|
||||
|
||||
src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
||||
src.pResource = Unwrap(mappedBuffer);
|
||||
src.PlacedFootprint = layouts[i];
|
||||
|
||||
// copy buffer into this array slice
|
||||
list->CopyTextureRegion(&dst, 0, 0, 0, &src, NULL);
|
||||
|
||||
// this slice now needs to be in shader-read to copy to the MSAA texture
|
||||
D3D12_RESOURCE_BARRIER b = {};
|
||||
b.Transition.pResource = Unwrap(arrayTex);
|
||||
b.Transition.Subresource = i;
|
||||
b.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
b.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
||||
list->ResourceBarrier(1, &b);
|
||||
}
|
||||
|
||||
delete[] layouts;
|
||||
}
|
||||
|
||||
m_Device->CloseInitialStateList();
|
||||
m_Device->ExecuteLists(NULL, true);
|
||||
m_Device->FlushLists(true);
|
||||
|
||||
// compact array into MSAA texture
|
||||
if(msaaTex && arrayTex)
|
||||
m_Device->GetDebugManager()->CopyArrayToTex2DMS(msaaTex, arrayTex, ~0U);
|
||||
|
||||
// move MSAA texture permanently to copy source state
|
||||
if(msaaTex)
|
||||
{
|
||||
list = Unwrap(m_Device->GetInitialStateList());
|
||||
|
||||
D3D12_RESOURCE_BARRIER b = {};
|
||||
b.Transition.pResource = Unwrap(msaaTex);
|
||||
b.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
b.Transition.StateBefore =
|
||||
isDepth ? D3D12_RESOURCE_STATE_DEPTH_WRITE : D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
b.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE;
|
||||
list->ResourceBarrier(1, &b);
|
||||
|
||||
m_Device->CloseInitialStateList();
|
||||
m_Device->ExecuteLists(NULL, true);
|
||||
m_Device->FlushLists(true);
|
||||
}
|
||||
|
||||
// subsequent copy comes from msaa texture
|
||||
initContents.resource = msaaTex;
|
||||
|
||||
// we can release the buffer now, and the temporary array texture
|
||||
SAFE_RELEASE(mappedBuffer);
|
||||
SAFE_RELEASE(arrayTex);
|
||||
}
|
||||
}
|
||||
|
||||
if(initContents.resource)
|
||||
SetInitialContents(id, initContents);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -566,11 +759,7 @@ void D3D12ResourceManager::Apply_InitialState(ID3D12DeviceChild *live, D3D12Init
|
||||
}
|
||||
else if(type == Resource_Resource)
|
||||
{
|
||||
if(data.tag == D3D12InitialContents::Multisampled)
|
||||
{
|
||||
D3D12NOTIMP("Multisampled initial contents");
|
||||
}
|
||||
else if(data.tag == D3D12InitialContents::Copy)
|
||||
if(data.tag == D3D12InitialContents::Copy)
|
||||
{
|
||||
ID3D12Resource *copyDst = Unwrap((ID3D12Resource *)live);
|
||||
|
||||
@@ -709,7 +898,13 @@ void D3D12ResourceManager::Apply_InitialState(ID3D12DeviceChild *live, D3D12Init
|
||||
D3D12_RESOURCE_DESC srcDesc = copySrc->GetDesc();
|
||||
D3D12_RESOURCE_DESC dstDesc = copyDst->GetDesc();
|
||||
|
||||
list->CopyBufferRegion(copyDst, 0, copySrc, 0, RDCMIN(srcDesc.Width, dstDesc.Width));
|
||||
list->CopyBufferRegion(copyDst, 0, Unwrap(copySrc), 0,
|
||||
RDCMIN(srcDesc.Width, dstDesc.Width));
|
||||
}
|
||||
else if(copyDst->GetDesc().SampleDesc.Count > 1)
|
||||
{
|
||||
// MSAA texture was pre-uploaded and decoded, just copy the texture
|
||||
list->CopyResource(copyDst, Unwrap(copySrc));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -719,6 +914,19 @@ void D3D12ResourceManager::Apply_InitialState(ID3D12DeviceChild *live, D3D12Init
|
||||
if(desc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D)
|
||||
numSubresources *= desc.DepthOrArraySize;
|
||||
|
||||
// we only accounted for planes in version 0x6, before then we only copied the first plane
|
||||
// so the buffer won't have enough data
|
||||
if(m_Device->GetLogVersion() >= 0x6)
|
||||
{
|
||||
D3D12_FEATURE_DATA_FORMAT_INFO formatInfo = {};
|
||||
formatInfo.Format = desc.Format;
|
||||
m_Device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &formatInfo, sizeof(formatInfo));
|
||||
|
||||
UINT planes = RDCMAX((UINT8)1, formatInfo.PlaneCount);
|
||||
|
||||
numSubresources *= planes;
|
||||
}
|
||||
|
||||
D3D12_PLACED_SUBRESOURCE_FOOTPRINT *layouts =
|
||||
new D3D12_PLACED_SUBRESOURCE_FOOTPRINT[numSubresources];
|
||||
|
||||
@@ -733,7 +941,7 @@ void D3D12ResourceManager::Apply_InitialState(ID3D12DeviceChild *live, D3D12Init
|
||||
dst.SubresourceIndex = i;
|
||||
|
||||
src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
||||
src.pResource = copySrc;
|
||||
src.pResource = Unwrap(copySrc);
|
||||
src.PlacedFootprint = layouts[i];
|
||||
|
||||
list->CopyTextureRegion(&dst, 0, 0, 0, &src, NULL);
|
||||
|
||||
@@ -696,7 +696,7 @@ template void D3D12ResourceManager::SerialiseResourceStates(
|
||||
|
||||
void D3D12ResourceManager::SetInternalResource(ID3D12DeviceChild *res)
|
||||
{
|
||||
if(!RenderDoc::Inst().IsReplayApp())
|
||||
if(!RenderDoc::Inst().IsReplayApp() && res)
|
||||
{
|
||||
D3D12ResourceRecord *record = GetResourceRecord(GetResID(res));
|
||||
if(record)
|
||||
|
||||
@@ -593,7 +593,6 @@ struct D3D12InitialContents
|
||||
// this is only valid during capture - it indicates we didn't create a staging texture, we're
|
||||
// going to read directly from the resource (only valid for resources that are already READBACK)
|
||||
MapDirect,
|
||||
Multisampled,
|
||||
};
|
||||
D3D12InitialContents(D3D12Descriptor *d, uint32_t n)
|
||||
: tag(Copy),
|
||||
|
||||
@@ -0,0 +1,541 @@
|
||||
/******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 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/dx/official/d3dcompiler.h"
|
||||
#include "driver/dxgi/dxgi_common.h"
|
||||
#include "d3d12_command_list.h"
|
||||
#include "d3d12_command_queue.h"
|
||||
#include "d3d12_debug.h"
|
||||
#include "d3d12_device.h"
|
||||
|
||||
void D3D12DebugManager::CopyTex2DMSToArray(ID3D12Resource *destArray, ID3D12Resource *srcMS)
|
||||
{
|
||||
// this function operates during capture so we work on unwrapped objects
|
||||
|
||||
D3D12_RESOURCE_DESC descMS = srcMS->GetDesc();
|
||||
D3D12_RESOURCE_DESC descArr = destArray->GetDesc();
|
||||
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY;
|
||||
srvDesc.Texture2DMSArray.FirstArraySlice = 0;
|
||||
srvDesc.Texture2DMSArray.ArraySize = descMS.DepthOrArraySize;
|
||||
srvDesc.Format = GetTypedFormat(descMS.Format, CompType::UInt);
|
||||
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
|
||||
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc;
|
||||
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
|
||||
rtvDesc.Format = srvDesc.Format;
|
||||
rtvDesc.Texture2DArray.ArraySize = 1;
|
||||
rtvDesc.Texture2DArray.FirstArraySlice = 0;
|
||||
rtvDesc.Texture2DArray.MipSlice = 0;
|
||||
rtvDesc.Texture2DArray.PlaneSlice = 0;
|
||||
|
||||
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc;
|
||||
dsvDesc.Flags = D3D12_DSV_FLAG_NONE;
|
||||
dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DARRAY;
|
||||
dsvDesc.Format = srvDesc.Format;
|
||||
dsvDesc.Texture2DArray.ArraySize = 1;
|
||||
dsvDesc.Texture2DArray.FirstArraySlice = 0;
|
||||
dsvDesc.Texture2DArray.MipSlice = 0;
|
||||
|
||||
bool depthFormat = IsDepthFormat(rtvDesc.Format);
|
||||
bool intFormat = IsUIntFormat(rtvDesc.Format) || IsIntFormat(rtvDesc.Format);
|
||||
|
||||
bool stencil = false;
|
||||
DXGI_FORMAT stencilFormat = DXGI_FORMAT_UNKNOWN;
|
||||
|
||||
if(depthFormat)
|
||||
{
|
||||
switch(descMS.Format)
|
||||
{
|
||||
case DXGI_FORMAT_D32_FLOAT:
|
||||
case DXGI_FORMAT_R32_FLOAT:
|
||||
case DXGI_FORMAT_R32_TYPELESS: srvDesc.Format = DXGI_FORMAT_R32_FLOAT; break;
|
||||
|
||||
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
|
||||
case DXGI_FORMAT_R32G8X24_TYPELESS:
|
||||
case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
|
||||
case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
|
||||
srvDesc.Format = DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
|
||||
stencilFormat = DXGI_FORMAT_X32_TYPELESS_G8X24_UINT;
|
||||
stencil = true;
|
||||
break;
|
||||
|
||||
case DXGI_FORMAT_D24_UNORM_S8_UINT:
|
||||
case DXGI_FORMAT_R24G8_TYPELESS:
|
||||
case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
|
||||
case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
|
||||
srvDesc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
|
||||
stencilFormat = DXGI_FORMAT_X24_TYPELESS_G8_UINT;
|
||||
stencil = true;
|
||||
break;
|
||||
|
||||
case DXGI_FORMAT_D16_UNORM:
|
||||
case DXGI_FORMAT_R16_TYPELESS: srvDesc.Format = DXGI_FORMAT_R16_FLOAT; break;
|
||||
}
|
||||
}
|
||||
|
||||
for(CBVUAVSRVSlot slot : {MSAA_SRV2x, MSAA_SRV4x, MSAA_SRV8x, MSAA_SRV16x, MSAA_SRV32x})
|
||||
{
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE srv = Unwrap(GetCPUHandle(slot));
|
||||
m_pDevice->GetReal()->CreateShaderResourceView(srcMS, &srvDesc, srv);
|
||||
}
|
||||
|
||||
if(stencil)
|
||||
{
|
||||
srvDesc.Format = stencilFormat;
|
||||
|
||||
for(CBVUAVSRVSlot slot : {STENCIL_MSAA_SRV2x, STENCIL_MSAA_SRV4x, STENCIL_MSAA_SRV8x,
|
||||
STENCIL_MSAA_SRV16x, STENCIL_MSAA_SRV32x})
|
||||
{
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE srv = Unwrap(GetCPUHandle(slot));
|
||||
m_pDevice->GetReal()->CreateShaderResourceView(srcMS, &srvDesc, srv);
|
||||
}
|
||||
}
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE rtv = Unwrap(GetCPUHandle(MSAA_RTV));
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE dsv = Unwrap(GetCPUHandle(MSAA_DSV));
|
||||
|
||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC pipeDesc = {};
|
||||
|
||||
pipeDesc.pRootSignature = Unwrap(m_ArrayMSAARootSig);
|
||||
pipeDesc.VS.BytecodeLength = m_FullscreenVS->GetBufferSize();
|
||||
pipeDesc.VS.pShaderBytecode = m_FullscreenVS->GetBufferPointer();
|
||||
|
||||
pipeDesc.PS.BytecodeLength = m_FloatMS2Array->GetBufferSize();
|
||||
pipeDesc.PS.pShaderBytecode = m_FloatMS2Array->GetBufferPointer();
|
||||
pipeDesc.NumRenderTargets = 1;
|
||||
pipeDesc.RTVFormats[0] = rtvDesc.Format;
|
||||
pipeDesc.DSVFormat = DXGI_FORMAT_UNKNOWN;
|
||||
|
||||
if(depthFormat)
|
||||
{
|
||||
pipeDesc.PS.BytecodeLength = m_DepthMS2Array->GetBufferSize();
|
||||
pipeDesc.PS.pShaderBytecode = m_DepthMS2Array->GetBufferPointer();
|
||||
pipeDesc.NumRenderTargets = 0;
|
||||
pipeDesc.RTVFormats[0] = DXGI_FORMAT_UNKNOWN;
|
||||
pipeDesc.DSVFormat = rtvDesc.Format;
|
||||
pipeDesc.DepthStencilState.DepthEnable = TRUE;
|
||||
pipeDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
|
||||
pipeDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS;
|
||||
}
|
||||
else if(intFormat)
|
||||
{
|
||||
pipeDesc.PS.BytecodeLength = m_IntMS2Array->GetBufferSize();
|
||||
pipeDesc.PS.pShaderBytecode = m_IntMS2Array->GetBufferPointer();
|
||||
}
|
||||
|
||||
pipeDesc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
|
||||
pipeDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
|
||||
pipeDesc.SampleMask = 0xFFFFFFFF;
|
||||
pipeDesc.SampleDesc.Count = 1;
|
||||
pipeDesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;
|
||||
pipeDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
||||
pipeDesc.BlendState.RenderTarget[0].BlendEnable = FALSE;
|
||||
pipeDesc.BlendState.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA;
|
||||
pipeDesc.BlendState.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
|
||||
pipeDesc.BlendState.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD;
|
||||
pipeDesc.BlendState.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_SRC_ALPHA;
|
||||
pipeDesc.BlendState.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA;
|
||||
pipeDesc.BlendState.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD;
|
||||
pipeDesc.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
|
||||
|
||||
ID3D12PipelineState *pso = NULL, *psoStencil = NULL;
|
||||
HRESULT hr = m_pDevice->GetReal()->CreateGraphicsPipelineState(
|
||||
&pipeDesc, __uuidof(ID3D12PipelineState), (void **)&pso);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
RDCERR("Couldn't create MSAA conversion pipeline! HRESULT: %s", ToStr(hr).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
ID3D12GraphicsCommandList *list = Unwrap(m_DebugList);
|
||||
|
||||
list->Reset(Unwrap(m_DebugAlloc), NULL);
|
||||
|
||||
D3D12_VIEWPORT viewport = {0, 0, (float)descArr.Width, (float)descArr.Height, 0.0f, 1.0f};
|
||||
D3D12_RECT scissor = {0, 0, (LONG)descArr.Width, (LONG)descArr.Height};
|
||||
list->RSSetViewports(1, &viewport);
|
||||
list->RSSetScissorRects(1, &scissor);
|
||||
list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
ID3D12DescriptorHeap *heap = Unwrap(cbvsrvuavHeap);
|
||||
list->SetDescriptorHeaps(1, &heap);
|
||||
list->SetPipelineState(pso);
|
||||
list->SetGraphicsRootSignature(Unwrap(m_ArrayMSAARootSig));
|
||||
list->SetGraphicsRootDescriptorTable(1, Unwrap(GetGPUHandle(MSAA_SRV2x)));
|
||||
if(stencil)
|
||||
list->SetGraphicsRootDescriptorTable(2, Unwrap(GetGPUHandle(STENCIL_MSAA_SRV2x)));
|
||||
|
||||
// loop over every array slice in MS texture
|
||||
for(UINT slice = 0; slice < descMS.DepthOrArraySize; slice++)
|
||||
{
|
||||
// loop over every multi sample
|
||||
for(UINT sample = 0; sample < descMS.SampleDesc.Count; sample++)
|
||||
{
|
||||
uint32_t cdata[4] = {descMS.SampleDesc.Count, 1000, sample, slice};
|
||||
|
||||
list->SetGraphicsRootConstantBufferView(0, UploadConstants(cdata, sizeof(cdata)));
|
||||
|
||||
dsvDesc.Texture2DArray.FirstArraySlice = slice * descMS.SampleDesc.Count + sample;
|
||||
rtvDesc.Texture2DArray.FirstArraySlice = slice * descMS.SampleDesc.Count + sample;
|
||||
|
||||
if(depthFormat)
|
||||
{
|
||||
m_pDevice->GetReal()->CreateDepthStencilView(destArray, &dsvDesc, dsv);
|
||||
list->OMSetRenderTargets(0, NULL, FALSE, &dsv);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pDevice->GetReal()->CreateRenderTargetView(destArray, &rtvDesc, rtv);
|
||||
list->OMSetRenderTargets(1, &rtv, FALSE, NULL);
|
||||
}
|
||||
|
||||
list->DrawInstanced(3, 1, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if(stencil)
|
||||
{
|
||||
pipeDesc.DepthStencilState.DepthEnable = FALSE;
|
||||
pipeDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO;
|
||||
pipeDesc.DepthStencilState.StencilEnable = TRUE;
|
||||
pipeDesc.DepthStencilState.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS;
|
||||
pipeDesc.DepthStencilState.FrontFace.StencilPassOp = D3D12_STENCIL_OP_REPLACE;
|
||||
pipeDesc.DepthStencilState.FrontFace.StencilFailOp = D3D12_STENCIL_OP_REPLACE;
|
||||
pipeDesc.DepthStencilState.FrontFace.StencilDepthFailOp = D3D12_STENCIL_OP_REPLACE;
|
||||
pipeDesc.DepthStencilState.BackFace = pipeDesc.DepthStencilState.FrontFace;
|
||||
pipeDesc.DepthStencilState.StencilReadMask = 0xff;
|
||||
pipeDesc.DepthStencilState.StencilWriteMask = 0xff;
|
||||
|
||||
hr = m_pDevice->GetReal()->CreateGraphicsPipelineState(&pipeDesc, __uuidof(ID3D12PipelineState),
|
||||
(void **)&psoStencil);
|
||||
RDCASSERTEQUAL(hr, S_OK);
|
||||
|
||||
list->SetPipelineState(psoStencil);
|
||||
|
||||
dsvDesc.Flags = D3D12_DSV_FLAG_READ_ONLY_DEPTH;
|
||||
dsvDesc.Texture2DArray.ArraySize = 1;
|
||||
|
||||
// loop over every array slice in MS texture
|
||||
for(UINT slice = 0; slice < descMS.DepthOrArraySize; slice++)
|
||||
{
|
||||
// loop over every multi sample
|
||||
for(UINT sample = 0; sample < descMS.SampleDesc.Count; sample++)
|
||||
{
|
||||
dsvDesc.Texture2DArray.FirstArraySlice = slice * descMS.SampleDesc.Count + sample;
|
||||
m_pDevice->GetReal()->CreateDepthStencilView(destArray, &dsvDesc, dsv);
|
||||
list->OMSetRenderTargets(0, NULL, FALSE, &dsv);
|
||||
|
||||
// loop over every stencil value (in theory we could use SV_StencilRef, but it's optional
|
||||
// and would mean a different shader)
|
||||
for(UINT stencilval = 0; stencilval < 256; stencilval++)
|
||||
{
|
||||
uint32_t cdata[4] = {descMS.SampleDesc.Count, stencilval, sample, slice};
|
||||
|
||||
list->SetGraphicsRootConstantBufferView(0, UploadConstants(cdata, sizeof(cdata)));
|
||||
|
||||
list->OMSetStencilRef(stencilval);
|
||||
|
||||
list->DrawInstanced(3, 1, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list->Close();
|
||||
|
||||
ID3D12Fence *tmpFence = NULL;
|
||||
m_pDevice->GetReal()->CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(ID3D12Fence),
|
||||
(void **)&tmpFence);
|
||||
|
||||
ID3D12CommandList *l = list;
|
||||
m_pDevice->GetQueue()->GetReal()->ExecuteCommandLists(1, &l);
|
||||
m_pDevice->GPUSync(m_pDevice->GetQueue()->GetReal(), tmpFence);
|
||||
m_DebugAlloc->Reset();
|
||||
|
||||
SAFE_RELEASE(tmpFence);
|
||||
SAFE_RELEASE(pso);
|
||||
SAFE_RELEASE(psoStencil);
|
||||
}
|
||||
|
||||
void D3D12DebugManager::CopyArrayToTex2DMS(ID3D12Resource *destMS, ID3D12Resource *srcArray,
|
||||
UINT selectedSlice)
|
||||
{
|
||||
bool singleSliceMode = (selectedSlice != ~0U);
|
||||
|
||||
D3D12_RESOURCE_DESC descArr = srcArray->GetDesc();
|
||||
D3D12_RESOURCE_DESC descMS = destMS->GetDesc();
|
||||
|
||||
UINT sampleMask = ~0U;
|
||||
|
||||
if(singleSliceMode)
|
||||
{
|
||||
sampleMask = 1U << (selectedSlice % descMS.SampleDesc.Count);
|
||||
selectedSlice /= descMS.SampleDesc.Count;
|
||||
}
|
||||
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
|
||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
|
||||
srvDesc.Texture2DArray.MipLevels = 1;
|
||||
srvDesc.Texture2DArray.ArraySize = descArr.DepthOrArraySize;
|
||||
srvDesc.Format = GetTypedFormat(descMS.Format, CompType::UInt);
|
||||
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
|
||||
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc;
|
||||
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY;
|
||||
rtvDesc.Format = srvDesc.Format;
|
||||
rtvDesc.Texture2DMSArray.ArraySize = 1;
|
||||
|
||||
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc;
|
||||
dsvDesc.Flags = D3D12_DSV_FLAG_NONE;
|
||||
dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY;
|
||||
dsvDesc.Format = srvDesc.Format;
|
||||
dsvDesc.Texture2DMSArray.ArraySize = 1;
|
||||
|
||||
bool depthFormat = IsDepthFormat(rtvDesc.Format);
|
||||
bool intFormat = IsUIntFormat(rtvDesc.Format) || IsIntFormat(rtvDesc.Format);
|
||||
|
||||
bool stencil = false;
|
||||
DXGI_FORMAT stencilFormat = DXGI_FORMAT_UNKNOWN;
|
||||
|
||||
if(depthFormat)
|
||||
{
|
||||
switch(descMS.Format)
|
||||
{
|
||||
case DXGI_FORMAT_D32_FLOAT:
|
||||
case DXGI_FORMAT_R32_FLOAT:
|
||||
case DXGI_FORMAT_R32_TYPELESS: srvDesc.Format = DXGI_FORMAT_R32_FLOAT; break;
|
||||
|
||||
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
|
||||
case DXGI_FORMAT_R32G8X24_TYPELESS:
|
||||
case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
|
||||
case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
|
||||
srvDesc.Format = DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
|
||||
stencilFormat = DXGI_FORMAT_X32_TYPELESS_G8X24_UINT;
|
||||
stencil = true;
|
||||
break;
|
||||
|
||||
case DXGI_FORMAT_D24_UNORM_S8_UINT:
|
||||
case DXGI_FORMAT_R24G8_TYPELESS:
|
||||
case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
|
||||
case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
|
||||
srvDesc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
|
||||
stencilFormat = DXGI_FORMAT_X24_TYPELESS_G8_UINT;
|
||||
stencil = true;
|
||||
break;
|
||||
|
||||
case DXGI_FORMAT_D16_UNORM:
|
||||
case DXGI_FORMAT_R16_TYPELESS: srvDesc.Format = DXGI_FORMAT_R16_FLOAT; break;
|
||||
}
|
||||
}
|
||||
|
||||
for(CBVUAVSRVSlot slot : {MSAA_SRV2x, MSAA_SRV4x, MSAA_SRV8x, MSAA_SRV16x, MSAA_SRV32x})
|
||||
{
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE srv = GetCPUHandle(slot);
|
||||
m_pDevice->CreateShaderResourceView(srcArray, &srvDesc, srv);
|
||||
}
|
||||
|
||||
if(stencil)
|
||||
{
|
||||
srvDesc.Format = stencilFormat;
|
||||
|
||||
{
|
||||
D3D12_FEATURE_DATA_FORMAT_INFO formatInfo = {};
|
||||
formatInfo.Format = srvDesc.Format;
|
||||
m_pDevice->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &formatInfo, sizeof(formatInfo));
|
||||
|
||||
UINT planes = RDCMAX((UINT8)1, formatInfo.PlaneCount);
|
||||
|
||||
if(planes > 1)
|
||||
srvDesc.Texture2DArray.PlaneSlice = 1;
|
||||
}
|
||||
|
||||
for(CBVUAVSRVSlot slot : {STENCIL_MSAA_SRV2x, STENCIL_MSAA_SRV4x, STENCIL_MSAA_SRV8x,
|
||||
STENCIL_MSAA_SRV16x, STENCIL_MSAA_SRV32x})
|
||||
{
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE srv = GetCPUHandle(slot);
|
||||
m_pDevice->CreateShaderResourceView(srcArray, &srvDesc, srv);
|
||||
}
|
||||
}
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE rtv = GetCPUHandle(MSAA_RTV);
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE dsv = GetCPUHandle(MSAA_DSV);
|
||||
|
||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC pipeDesc = {};
|
||||
|
||||
pipeDesc.pRootSignature = m_ArrayMSAARootSig;
|
||||
pipeDesc.VS.BytecodeLength = m_FullscreenVS->GetBufferSize();
|
||||
pipeDesc.VS.pShaderBytecode = m_FullscreenVS->GetBufferPointer();
|
||||
|
||||
pipeDesc.PS.BytecodeLength = m_FloatArray2MS->GetBufferSize();
|
||||
pipeDesc.PS.pShaderBytecode = m_FloatArray2MS->GetBufferPointer();
|
||||
pipeDesc.NumRenderTargets = 1;
|
||||
pipeDesc.RTVFormats[0] = rtvDesc.Format;
|
||||
pipeDesc.DSVFormat = DXGI_FORMAT_UNKNOWN;
|
||||
|
||||
if(depthFormat)
|
||||
{
|
||||
pipeDesc.PS.BytecodeLength = m_DepthArray2MS->GetBufferSize();
|
||||
pipeDesc.PS.pShaderBytecode = m_DepthArray2MS->GetBufferPointer();
|
||||
pipeDesc.NumRenderTargets = 0;
|
||||
pipeDesc.RTVFormats[0] = DXGI_FORMAT_UNKNOWN;
|
||||
pipeDesc.DSVFormat = rtvDesc.Format;
|
||||
pipeDesc.DepthStencilState.DepthEnable = TRUE;
|
||||
pipeDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
|
||||
pipeDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS;
|
||||
}
|
||||
else if(intFormat)
|
||||
{
|
||||
pipeDesc.PS.BytecodeLength = m_IntArray2MS->GetBufferSize();
|
||||
pipeDesc.PS.pShaderBytecode = m_IntArray2MS->GetBufferPointer();
|
||||
}
|
||||
|
||||
pipeDesc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
|
||||
pipeDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
|
||||
pipeDesc.SampleMask = sampleMask;
|
||||
pipeDesc.SampleDesc = descMS.SampleDesc;
|
||||
pipeDesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;
|
||||
pipeDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
||||
pipeDesc.BlendState.RenderTarget[0].BlendEnable = FALSE;
|
||||
pipeDesc.BlendState.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA;
|
||||
pipeDesc.BlendState.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
|
||||
pipeDesc.BlendState.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD;
|
||||
pipeDesc.BlendState.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_SRC_ALPHA;
|
||||
pipeDesc.BlendState.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA;
|
||||
pipeDesc.BlendState.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD;
|
||||
pipeDesc.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
|
||||
|
||||
ID3D12PipelineState *pso = NULL, *psoStencil = NULL;
|
||||
HRESULT hr = m_pDevice->CreateGraphicsPipelineState(&pipeDesc, __uuidof(ID3D12PipelineState),
|
||||
(void **)&pso);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
RDCERR("Couldn't create MSAA conversion pipeline! HRESULT: %s", ToStr(hr).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
ID3D12GraphicsCommandList *list = m_DebugList;
|
||||
|
||||
list->Reset(m_DebugAlloc, NULL);
|
||||
|
||||
D3D12_VIEWPORT viewport = {0, 0, (float)descArr.Width, (float)descArr.Height, 0.0f, 1.0f};
|
||||
D3D12_RECT scissor = {0, 0, (LONG)descArr.Width, (LONG)descArr.Height};
|
||||
list->RSSetViewports(1, &viewport);
|
||||
list->RSSetScissorRects(1, &scissor);
|
||||
list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
list->SetDescriptorHeaps(1, &cbvsrvuavHeap);
|
||||
list->SetPipelineState(pso);
|
||||
list->SetGraphicsRootSignature(m_ArrayMSAARootSig);
|
||||
list->SetGraphicsRootDescriptorTable(1, GetGPUHandle(MSAA_SRV2x));
|
||||
if(stencil)
|
||||
list->SetGraphicsRootDescriptorTable(2, GetGPUHandle(STENCIL_MSAA_SRV2x));
|
||||
|
||||
// loop over every array slice in MS texture
|
||||
for(UINT slice = 0; slice < descMS.DepthOrArraySize; slice++)
|
||||
{
|
||||
if(singleSliceMode)
|
||||
slice = selectedSlice;
|
||||
|
||||
uint32_t cdata[4] = {descMS.SampleDesc.Count, 1000, 0, slice};
|
||||
|
||||
list->SetGraphicsRootConstantBufferView(0, UploadConstants(cdata, sizeof(cdata)));
|
||||
|
||||
rtvDesc.Texture2DMSArray.FirstArraySlice = slice;
|
||||
dsvDesc.Texture2DMSArray.FirstArraySlice = slice;
|
||||
|
||||
if(depthFormat)
|
||||
{
|
||||
m_pDevice->CreateDepthStencilView(destMS, &dsvDesc, dsv);
|
||||
list->OMSetRenderTargets(0, NULL, FALSE, &dsv);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pDevice->CreateRenderTargetView(destMS, &rtvDesc, rtv);
|
||||
list->OMSetRenderTargets(1, &rtv, FALSE, NULL);
|
||||
}
|
||||
|
||||
list->DrawInstanced(3, 1, 0, 0);
|
||||
|
||||
if(singleSliceMode)
|
||||
break;
|
||||
}
|
||||
|
||||
if(stencil)
|
||||
{
|
||||
pipeDesc.DepthStencilState.DepthEnable = FALSE;
|
||||
pipeDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO;
|
||||
pipeDesc.DepthStencilState.StencilEnable = TRUE;
|
||||
pipeDesc.DepthStencilState.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS;
|
||||
pipeDesc.DepthStencilState.FrontFace.StencilPassOp = D3D12_STENCIL_OP_REPLACE;
|
||||
pipeDesc.DepthStencilState.FrontFace.StencilFailOp = D3D12_STENCIL_OP_REPLACE;
|
||||
pipeDesc.DepthStencilState.FrontFace.StencilDepthFailOp = D3D12_STENCIL_OP_REPLACE;
|
||||
pipeDesc.DepthStencilState.BackFace = pipeDesc.DepthStencilState.FrontFace;
|
||||
pipeDesc.DepthStencilState.StencilReadMask = 0xff;
|
||||
pipeDesc.DepthStencilState.StencilWriteMask = 0xff;
|
||||
|
||||
hr = m_pDevice->CreateGraphicsPipelineState(&pipeDesc, __uuidof(ID3D12PipelineState),
|
||||
(void **)&psoStencil);
|
||||
RDCASSERTEQUAL(hr, S_OK);
|
||||
|
||||
dsvDesc.Flags = D3D12_DSV_FLAG_READ_ONLY_DEPTH;
|
||||
dsvDesc.Texture2DMSArray.ArraySize = 1;
|
||||
m_pDevice->CreateDepthStencilView(destMS, &dsvDesc, dsv);
|
||||
list->OMSetRenderTargets(0, NULL, FALSE, &dsv);
|
||||
list->SetPipelineState(psoStencil);
|
||||
|
||||
// loop over every array slice in MS texture
|
||||
for(UINT slice = 0; slice < descMS.DepthOrArraySize; slice++)
|
||||
{
|
||||
if(singleSliceMode)
|
||||
slice = selectedSlice;
|
||||
|
||||
dsvDesc.Texture2DArray.FirstArraySlice = slice;
|
||||
|
||||
// loop over every stencil value (in theory we could use SV_StencilRef, but it's optional
|
||||
// and would mean a different shader)
|
||||
for(UINT stencilval = 0; stencilval < 256; stencilval++)
|
||||
{
|
||||
uint32_t cdata[4] = {descMS.SampleDesc.Count, stencilval, 0, slice};
|
||||
|
||||
list->SetGraphicsRootConstantBufferView(0, UploadConstants(cdata, sizeof(cdata)));
|
||||
|
||||
list->OMSetStencilRef(stencilval);
|
||||
|
||||
list->DrawInstanced(3, 1, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list->Close();
|
||||
|
||||
ID3D12CommandList *l = m_DebugList;
|
||||
m_pDevice->GetQueue()->ExecuteCommandLists(1, &l);
|
||||
m_pDevice->GPUSync();
|
||||
m_DebugAlloc->Reset();
|
||||
|
||||
SAFE_RELEASE(pso);
|
||||
SAFE_RELEASE(psoStencil);
|
||||
}
|
||||
@@ -100,6 +100,8 @@ void D3D12Replay::Shutdown()
|
||||
|
||||
void D3D12Replay::CreateResources()
|
||||
{
|
||||
m_DebugManager = new D3D12DebugManager(m_pDevice);
|
||||
|
||||
if(RenderDoc::Inst().IsReplayApp())
|
||||
{
|
||||
typedef HRESULT(WINAPI * PFN_CREATE_DXGI_FACTORY)(REFIID, void **);
|
||||
@@ -136,8 +138,6 @@ void D3D12Replay::CreateResources()
|
||||
}
|
||||
}
|
||||
|
||||
m_DebugManager = new D3D12DebugManager(m_pDevice);
|
||||
|
||||
CreateSOBuffers();
|
||||
|
||||
m_General.Init(m_pDevice, m_DebugManager);
|
||||
@@ -146,10 +146,7 @@ void D3D12Replay::CreateResources()
|
||||
m_VertexPick.Init(m_pDevice, m_DebugManager);
|
||||
m_PixelPick.Init(m_pDevice, m_DebugManager);
|
||||
m_Histogram.Init(m_pDevice, m_DebugManager);
|
||||
}
|
||||
|
||||
if(RenderDoc::Inst().IsReplayApp())
|
||||
{
|
||||
AMDCounters *counters = NULL;
|
||||
|
||||
if(m_Vendor == GPUVendor::AMD)
|
||||
@@ -2926,6 +2923,7 @@ void D3D12Replay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip
|
||||
copyDesc.DepthOrArraySize *= (UINT16)copyDesc.SampleDesc.Count;
|
||||
copyDesc.SampleDesc.Count = 1;
|
||||
copyDesc.SampleDesc.Quality = 0;
|
||||
copyDesc.MipLevels = 1;
|
||||
|
||||
wasms = true;
|
||||
}
|
||||
@@ -3082,7 +3080,74 @@ void D3D12Replay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip
|
||||
else if(wasms)
|
||||
{
|
||||
// copy/expand multisampled live texture to array readback texture
|
||||
RDCUNIMPLEMENTED("CopyTex2DMSToArray on D3D12");
|
||||
if(isDepth)
|
||||
copyDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
|
||||
else
|
||||
copyDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
|
||||
copyDesc.Format = GetTypelessFormat(copyDesc.Format);
|
||||
|
||||
ID3D12Resource *arrayTexture;
|
||||
hr = m_pDevice->CreateCommittedResource(
|
||||
&defaultHeap, D3D12_HEAP_FLAG_NONE, ©Desc,
|
||||
isDepth ? D3D12_RESOURCE_STATE_DEPTH_WRITE : D3D12_RESOURCE_STATE_RENDER_TARGET, NULL,
|
||||
__uuidof(ID3D12Resource), (void **)&arrayTexture);
|
||||
RDCASSERTEQUAL(hr, S_OK);
|
||||
|
||||
list = m_pDevice->GetNewList();
|
||||
|
||||
// put source texture into shader read state
|
||||
const vector<D3D12_RESOURCE_STATES> &states = m_pDevice->GetSubresourceStates(tex);
|
||||
|
||||
std::vector<D3D12_RESOURCE_BARRIER> barriers;
|
||||
barriers.reserve(states.size());
|
||||
for(size_t i = 0; i < states.size(); i++)
|
||||
{
|
||||
D3D12_RESOURCE_BARRIER b;
|
||||
|
||||
// skip unneeded barriers
|
||||
if(states[i] & D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)
|
||||
continue;
|
||||
|
||||
b.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
b.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
b.Transition.pResource = resource;
|
||||
b.Transition.Subresource = (UINT)i;
|
||||
b.Transition.StateBefore = states[i];
|
||||
b.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
||||
|
||||
barriers.push_back(b);
|
||||
}
|
||||
|
||||
if(!barriers.empty())
|
||||
list->ResourceBarrier((UINT)barriers.size(), &barriers[0]);
|
||||
|
||||
list->Close();
|
||||
list = NULL;
|
||||
|
||||
m_pDevice->ExecuteLists();
|
||||
m_pDevice->FlushLists();
|
||||
|
||||
// expand multisamples out to array
|
||||
GetDebugManager()->CopyTex2DMSToArray(arrayTexture, srcTexture);
|
||||
|
||||
tmpTexture = srcTexture = arrayTexture;
|
||||
|
||||
list = m_pDevice->GetNewList();
|
||||
|
||||
// real resource back to normal
|
||||
for(size_t i = 0; i < barriers.size(); i++)
|
||||
std::swap(barriers[i].Transition.StateBefore, barriers[i].Transition.StateAfter);
|
||||
|
||||
if(!barriers.empty())
|
||||
list->ResourceBarrier((UINT)barriers.size(), &barriers[0]);
|
||||
|
||||
D3D12_RESOURCE_BARRIER b = {};
|
||||
b.Transition.pResource = arrayTexture;
|
||||
b.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
b.Transition.StateBefore =
|
||||
isDepth ? D3D12_RESOURCE_STATE_DEPTH_WRITE : D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
b.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE;
|
||||
list->ResourceBarrier(1, &b);
|
||||
}
|
||||
|
||||
if(list == NULL)
|
||||
|
||||
@@ -110,6 +110,7 @@
|
||||
<ClCompile Include="d3d12_hooks.cpp" />
|
||||
<ClCompile Include="d3d12_initstate.cpp" />
|
||||
<ClCompile Include="d3d12_manager.cpp" />
|
||||
<ClCompile Include="d3d12_msaa_array_conv.cpp" />
|
||||
<ClCompile Include="d3d12_outputwindow.cpp" />
|
||||
<ClCompile Include="d3d12_overlay.cpp" />
|
||||
<ClCompile Include="d3d12_postvs.cpp" />
|
||||
|
||||
@@ -146,5 +146,8 @@
|
||||
<ClCompile Include="d3d12_command_list1_wrap.cpp">
|
||||
<Filter>Wrapped</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="d3d12_msaa_array_conv.cpp">
|
||||
<Filter>Replay</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user