mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-09-14 17:55:50 +00:00
Implement RenderTexture() (in a hacky way)
This commit is contained in:
@@ -23,9 +23,59 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "d3d12_debug.h"
|
||||
#include "common/shader_cache.h"
|
||||
#include "data/resource.h"
|
||||
#include "driver/dx/official/d3dcompiler.h"
|
||||
#include "driver/dxgi/dxgi_common.h"
|
||||
#include "maths/matrix.h"
|
||||
#include "maths/vec.h"
|
||||
#include "serialise/string_utils.h"
|
||||
#include "d3d12_command_queue.h"
|
||||
#include "d3d12_device.h"
|
||||
|
||||
#include "data/hlsl/debugcbuffers.h"
|
||||
|
||||
typedef HRESULT(WINAPI *pD3DCreateBlob)(SIZE_T Size, ID3DBlob **ppBlob);
|
||||
|
||||
struct D3D12BlobShaderCallbacks
|
||||
{
|
||||
D3D12BlobShaderCallbacks()
|
||||
{
|
||||
HMODULE d3dcompiler = GetD3DCompiler();
|
||||
|
||||
if(d3dcompiler == NULL)
|
||||
RDCFATAL("Can't get handle to d3dcompiler_??.dll");
|
||||
|
||||
m_BlobCreate = (pD3DCreateBlob)GetProcAddress(d3dcompiler, "D3DCreateBlob");
|
||||
|
||||
if(m_BlobCreate == NULL)
|
||||
RDCFATAL("d3dcompiler.dll doesn't contain D3DCreateBlob");
|
||||
}
|
||||
|
||||
bool Create(uint32_t size, byte *data, ID3DBlob **ret) const
|
||||
{
|
||||
RDCASSERT(ret);
|
||||
|
||||
*ret = NULL;
|
||||
HRESULT hr = m_BlobCreate((SIZE_T)size, ret);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
RDCERR("Couldn't create blob of size %u from shadercache: %08x", size, hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy((*ret)->GetBufferPointer(), data, size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Destroy(ID3DBlob *blob) const { blob->Release(); }
|
||||
uint32_t GetSize(ID3DBlob *blob) const { return (uint32_t)blob->GetBufferSize(); }
|
||||
byte *GetData(ID3DBlob *blob) const { return (byte *)blob->GetBufferPointer(); }
|
||||
pD3DCreateBlob m_BlobCreate;
|
||||
} ShaderCache12Callbacks;
|
||||
|
||||
extern "C" __declspec(dllexport) HRESULT
|
||||
__cdecl RENDERDOC_CreateWrappedDXGIFactory1(REFIID riid, void **ppFactory);
|
||||
|
||||
@@ -52,7 +102,7 @@ D3D12DebugManager::D3D12DebugManager(WrappedID3D12Device *wrapper)
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
RDCERR("Couldn't create DXGI factory!");
|
||||
RDCERR("Couldn't create DXGI factory! 0x%08x", hr);
|
||||
}
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC desc;
|
||||
@@ -66,7 +116,7 @@ D3D12DebugManager::D3D12DebugManager(WrappedID3D12Device *wrapper)
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
RDCERR("Couldn't create RTV descriptor heap!");
|
||||
RDCERR("Couldn't create RTV descriptor heap! 0x%08x", hr);
|
||||
}
|
||||
|
||||
desc.NumDescriptors = 16;
|
||||
@@ -77,28 +127,385 @@ D3D12DebugManager::D3D12DebugManager(WrappedID3D12Device *wrapper)
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
RDCERR("Couldn't create DSV descriptor heap!");
|
||||
RDCERR("Couldn't create DSV descriptor heap! 0x%08x", hr);
|
||||
}
|
||||
|
||||
desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
desc.NumDescriptors = 4096;
|
||||
desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
|
||||
hr = m_WrappedDevice->CreateDescriptorHeap(&desc, __uuidof(ID3D12DescriptorHeap),
|
||||
(void **)&cbvsrvHeap);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
RDCERR("Couldn't create CBV/SRV descriptor heap! 0x%08x", hr);
|
||||
}
|
||||
|
||||
desc.NumDescriptors = 16;
|
||||
desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
|
||||
|
||||
hr = m_WrappedDevice->CreateDescriptorHeap(&desc, __uuidof(ID3D12DescriptorHeap),
|
||||
(void **)&samplerHeap);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
RDCERR("Couldn't create sampler descriptor heap! 0x%08x", hr);
|
||||
}
|
||||
|
||||
RenderDoc::Inst().SetProgress(DebugManagerInit, 0.2f);
|
||||
|
||||
// create fixed samplers, point and linear
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE samp;
|
||||
samp = samplerHeap->GetCPUDescriptorHandleForHeapStart();
|
||||
|
||||
D3D12_SAMPLER_DESC sampDesc;
|
||||
RDCEraseEl(sampDesc);
|
||||
|
||||
sampDesc.AddressU = sampDesc.AddressV = sampDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
sampDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
|
||||
sampDesc.MaxAnisotropy = 1;
|
||||
sampDesc.MinLOD = 0;
|
||||
sampDesc.MaxLOD = FLT_MAX;
|
||||
sampDesc.MipLODBias = 0.0f;
|
||||
sampDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
|
||||
|
||||
m_WrappedDevice->CreateSampler(&sampDesc, samp);
|
||||
|
||||
sampDesc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT;
|
||||
|
||||
samp.ptr += m_WrappedDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
|
||||
m_WrappedDevice->CreateSampler(&sampDesc, samp);
|
||||
|
||||
D3D12_HEAP_PROPERTIES heapProps;
|
||||
heapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
heapProps.CreationNodeMask = 1;
|
||||
heapProps.VisibleNodeMask = 1;
|
||||
|
||||
D3D12_RESOURCE_DESC cbDesc;
|
||||
cbDesc.Alignment = 0;
|
||||
cbDesc.DepthOrArraySize = 1;
|
||||
cbDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
cbDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
cbDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
cbDesc.Height = 1;
|
||||
cbDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
cbDesc.MipLevels = 1;
|
||||
cbDesc.SampleDesc.Count = 1;
|
||||
cbDesc.SampleDesc.Quality = 0;
|
||||
cbDesc.Width = sizeof(DebugVertexCBuffer);
|
||||
|
||||
hr = m_WrappedDevice->CreateCommittedResource(
|
||||
&heapProps, D3D12_HEAP_FLAG_NONE, &cbDesc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
|
||||
__uuidof(ID3D12Resource), (void **)&m_GenericVSCbuffer);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
RDCERR("Couldn't create m_GenericVSCbuffer! 0x%08x", hr);
|
||||
}
|
||||
|
||||
cbDesc.Width = sizeof(DebugPixelCBufferData);
|
||||
|
||||
hr = m_WrappedDevice->CreateCommittedResource(
|
||||
&heapProps, D3D12_HEAP_FLAG_NONE, &cbDesc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
|
||||
__uuidof(ID3D12Resource), (void **)&m_GenericPSCbuffer);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
RDCERR("Couldn't create m_GenericPSCbuffer! 0x%08x", hr);
|
||||
}
|
||||
|
||||
RenderDoc::Inst().SetProgress(DebugManagerInit, 0.4f);
|
||||
|
||||
bool success = LoadShaderCache("d3d12shaders.cache", m_ShaderCacheMagic, m_ShaderCacheVersion,
|
||||
m_ShaderCache, ShaderCache12Callbacks);
|
||||
|
||||
// if we failed to load from the cache
|
||||
m_ShaderCacheDirty = !success;
|
||||
|
||||
m_CacheShaders = true;
|
||||
|
||||
vector<D3D12_ROOT_PARAMETER> rootSig;
|
||||
|
||||
D3D12_ROOT_PARAMETER param = {};
|
||||
|
||||
// m_GenericVSCbuffer
|
||||
param.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
|
||||
param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
|
||||
param.Descriptor.ShaderRegister = 0;
|
||||
|
||||
rootSig.push_back(param);
|
||||
|
||||
// m_GenericPSCbuffer
|
||||
param.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
|
||||
param.Descriptor.ShaderRegister = 1;
|
||||
|
||||
rootSig.push_back(param);
|
||||
|
||||
D3D12_DESCRIPTOR_RANGE srvrange = {};
|
||||
srvrange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
|
||||
srvrange.BaseShaderRegister = 0;
|
||||
srvrange.NumDescriptors = 32;
|
||||
srvrange.OffsetInDescriptorsFromTableStart = 0;
|
||||
|
||||
param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
param.DescriptorTable.NumDescriptorRanges = 1;
|
||||
param.DescriptorTable.pDescriptorRanges = &srvrange;
|
||||
|
||||
// SRV
|
||||
rootSig.push_back(param);
|
||||
|
||||
D3D12_DESCRIPTOR_RANGE samplerrange = {};
|
||||
samplerrange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
|
||||
samplerrange.BaseShaderRegister = 0;
|
||||
samplerrange.NumDescriptors = 2;
|
||||
samplerrange.OffsetInDescriptorsFromTableStart = 0;
|
||||
|
||||
param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
param.DescriptorTable.NumDescriptorRanges = 1;
|
||||
param.DescriptorTable.pDescriptorRanges = &samplerrange;
|
||||
|
||||
// samplers
|
||||
rootSig.push_back(param);
|
||||
|
||||
ID3DBlob *root = MakeRootSig(rootSig);
|
||||
|
||||
RDCASSERT(root);
|
||||
|
||||
hr = m_WrappedDevice->CreateRootSignature(0, root->GetBufferPointer(), root->GetBufferSize(),
|
||||
__uuidof(ID3D12RootSignature),
|
||||
(void **)&m_TexDisplayRootSig);
|
||||
|
||||
RenderDoc::Inst().SetProgress(DebugManagerInit, 0.6f);
|
||||
|
||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC pipeDesc;
|
||||
RDCEraseEl(pipeDesc);
|
||||
|
||||
string displayhlsl = GetEmbeddedResource(debugcbuffers_h);
|
||||
displayhlsl += GetEmbeddedResource(debugcommon_hlsl);
|
||||
displayhlsl += GetEmbeddedResource(debugdisplay_hlsl);
|
||||
|
||||
ID3DBlob *GenericVS = NULL;
|
||||
ID3DBlob *TexDisplayPS = NULL;
|
||||
|
||||
GetShaderBlob(displayhlsl.c_str(), "RENDERDOC_DebugVS", D3DCOMPILE_WARNINGS_ARE_ERRORS, "vs_5_0",
|
||||
&GenericVS);
|
||||
GetShaderBlob(displayhlsl.c_str(), "RENDERDOC_TexDisplayPS", D3DCOMPILE_WARNINGS_ARE_ERRORS,
|
||||
"ps_5_0", &TexDisplayPS);
|
||||
|
||||
RDCASSERT(GenericVS);
|
||||
RDCASSERT(TexDisplayPS);
|
||||
|
||||
pipeDesc.pRootSignature = m_TexDisplayRootSig;
|
||||
pipeDesc.VS.BytecodeLength = GenericVS->GetBufferSize();
|
||||
pipeDesc.VS.pShaderBytecode = GenericVS->GetBufferPointer();
|
||||
pipeDesc.PS.BytecodeLength = TexDisplayPS->GetBufferSize();
|
||||
pipeDesc.PS.pShaderBytecode = TexDisplayPS->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.NumRenderTargets = 1;
|
||||
pipeDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
pipeDesc.DSVFormat = DXGI_FORMAT_UNKNOWN;
|
||||
pipeDesc.BlendState.RenderTarget[0].BlendEnable = TRUE;
|
||||
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_ONE;
|
||||
pipeDesc.BlendState.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO;
|
||||
pipeDesc.BlendState.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD;
|
||||
pipeDesc.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
|
||||
|
||||
hr = m_WrappedDevice->CreateGraphicsPipelineState(&pipeDesc, __uuidof(ID3D12PipelineState),
|
||||
(void **)&m_TexDisplayBlendPipe);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
RDCERR("Couldn't create m_TexDisplayBlendPipe! 0x%08x", hr);
|
||||
}
|
||||
|
||||
pipeDesc.BlendState.RenderTarget[0].BlendEnable = FALSE;
|
||||
|
||||
hr = m_WrappedDevice->CreateGraphicsPipelineState(&pipeDesc, __uuidof(ID3D12PipelineState),
|
||||
(void **)&m_TexDisplayPipe);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
RDCERR("Couldn't create m_TexDisplayPipe! 0x%08x", hr);
|
||||
}
|
||||
|
||||
SAFE_RELEASE(GenericVS);
|
||||
SAFE_RELEASE(TexDisplayPS);
|
||||
|
||||
RenderDoc::Inst().SetProgress(DebugManagerInit, 0.8f);
|
||||
|
||||
RenderDoc::Inst().SetProgress(DebugManagerInit, 1.0f);
|
||||
|
||||
m_CacheShaders = false;
|
||||
}
|
||||
|
||||
D3D12DebugManager::~D3D12DebugManager()
|
||||
{
|
||||
if(m_ShaderCacheDirty)
|
||||
{
|
||||
SaveShaderCache("d3d12shaders.cache", m_ShaderCacheMagic, m_ShaderCacheVersion, m_ShaderCache,
|
||||
ShaderCache12Callbacks);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(auto it = m_ShaderCache.begin(); it != m_ShaderCache.end(); ++it)
|
||||
ShaderCache12Callbacks.Destroy(it->second);
|
||||
}
|
||||
|
||||
SAFE_RELEASE(m_pFactory);
|
||||
|
||||
SAFE_RELEASE(dsvHeap);
|
||||
SAFE_RELEASE(rtvHeap);
|
||||
SAFE_RELEASE(cbvsrvHeap);
|
||||
SAFE_RELEASE(samplerHeap);
|
||||
|
||||
SAFE_RELEASE(m_GenericVSCbuffer);
|
||||
SAFE_RELEASE(m_GenericPSCbuffer);
|
||||
|
||||
m_WrappedDevice->InternalRelease();
|
||||
|
||||
if(RenderDoc::Inst().GetCrashHandler())
|
||||
RenderDoc::Inst().GetCrashHandler()->UnregisterMemoryRegion(this);
|
||||
}
|
||||
|
||||
string D3D12DebugManager::GetShaderBlob(const char *source, const char *entry,
|
||||
const uint32_t compileFlags, const char *profile,
|
||||
ID3DBlob **srcblob)
|
||||
{
|
||||
uint32_t hash = strhash(source);
|
||||
hash = strhash(entry, hash);
|
||||
hash = strhash(profile, hash);
|
||||
hash ^= compileFlags;
|
||||
|
||||
if(m_ShaderCache.find(hash) != m_ShaderCache.end())
|
||||
{
|
||||
*srcblob = m_ShaderCache[hash];
|
||||
(*srcblob)->AddRef();
|
||||
return "";
|
||||
}
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
ID3DBlob *byteBlob = NULL;
|
||||
ID3DBlob *errBlob = NULL;
|
||||
|
||||
HMODULE d3dcompiler = GetD3DCompiler();
|
||||
|
||||
if(d3dcompiler == NULL)
|
||||
{
|
||||
RDCFATAL("Can't get handle to d3dcompiler_??.dll");
|
||||
}
|
||||
|
||||
pD3DCompile compileFunc = (pD3DCompile)GetProcAddress(d3dcompiler, "D3DCompile");
|
||||
|
||||
if(compileFunc == NULL)
|
||||
{
|
||||
RDCFATAL("Can't get D3DCompile from d3dcompiler_??.dll");
|
||||
}
|
||||
|
||||
uint32_t flags = compileFlags & ~D3DCOMPILE_NO_PRESHADER;
|
||||
|
||||
hr = compileFunc(source, strlen(source), entry, NULL, NULL, entry, profile, flags, 0, &byteBlob,
|
||||
&errBlob);
|
||||
|
||||
string errors = "";
|
||||
|
||||
if(errBlob)
|
||||
{
|
||||
errors = (char *)errBlob->GetBufferPointer();
|
||||
|
||||
string logerror = errors;
|
||||
if(logerror.length() > 1024)
|
||||
logerror = logerror.substr(0, 1024) + "...";
|
||||
|
||||
RDCWARN("Shader compile error in '%s':\n%s", entry, logerror.c_str());
|
||||
|
||||
SAFE_RELEASE(errBlob);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
SAFE_RELEASE(byteBlob);
|
||||
return errors;
|
||||
}
|
||||
}
|
||||
|
||||
if(m_CacheShaders)
|
||||
{
|
||||
m_ShaderCache[hash] = byteBlob;
|
||||
byteBlob->AddRef();
|
||||
m_ShaderCacheDirty = true;
|
||||
}
|
||||
|
||||
SAFE_RELEASE(errBlob);
|
||||
|
||||
*srcblob = byteBlob;
|
||||
return errors;
|
||||
}
|
||||
|
||||
ID3DBlob *D3D12DebugManager::MakeRootSig(const vector<D3D12_ROOT_PARAMETER> &rootSig)
|
||||
{
|
||||
PFN_D3D12_SERIALIZE_ROOT_SIGNATURE serializeRootSig =
|
||||
(PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)GetProcAddress(GetModuleHandleA("d3d12.dll"),
|
||||
"D3D12SerializeRootSignature");
|
||||
|
||||
if(serializeRootSig == NULL)
|
||||
{
|
||||
RDCERR("Can't get D3D12SerializeRootSignature");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
D3D12_ROOT_SIGNATURE_DESC desc;
|
||||
desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE;
|
||||
desc.NumStaticSamplers = 0;
|
||||
desc.pStaticSamplers = NULL;
|
||||
desc.NumParameters = (UINT)rootSig.size();
|
||||
desc.pParameters = &rootSig[0];
|
||||
|
||||
ID3DBlob *ret = NULL;
|
||||
ID3DBlob *errBlob = NULL;
|
||||
HRESULT hr = serializeRootSig(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &ret, &errBlob);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
string errors = (char *)errBlob->GetBufferPointer();
|
||||
|
||||
string logerror = errors;
|
||||
if(logerror.length() > 1024)
|
||||
logerror = logerror.substr(0, 1024) + "...";
|
||||
|
||||
RDCERR("Root signature serialize error:\n%s", logerror.c_str());
|
||||
|
||||
SAFE_RELEASE(errBlob);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
SAFE_RELEASE(ret);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SAFE_RELEASE(errBlob);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void D3D12DebugManager::OutputWindow::MakeRTV(bool multisampled)
|
||||
{
|
||||
SAFE_RELEASE(col);
|
||||
|
||||
D3D12_RESOURCE_DESC texDesc = bb[0]->GetDesc();
|
||||
|
||||
texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
texDesc.SampleDesc.Count = multisampled ? 4 : 1;
|
||||
texDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
|
||||
|
||||
@@ -421,3 +828,244 @@ void D3D12DebugManager::FlipOutputWindow(uint64_t id)
|
||||
outw.bbIdx++;
|
||||
outw.bbIdx %= 2;
|
||||
}
|
||||
|
||||
void D3D12DebugManager::FillCBuffer(ID3D12Resource *buf, void *data, size_t size)
|
||||
{
|
||||
void *ptr = NULL;
|
||||
HRESULT hr = buf->Map(0, NULL, &ptr);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
RDCERR("Can't fill cbuffer %08x", hr);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(ptr, data, size);
|
||||
buf->Unmap(0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
bool D3D12DebugManager::RenderTexture(TextureDisplay cfg, bool blendAlpha)
|
||||
{
|
||||
DebugVertexCBuffer vertexData;
|
||||
DebugPixelCBufferData pixelData;
|
||||
|
||||
pixelData.AlwaysZero = 0.0f;
|
||||
|
||||
float x = cfg.offx;
|
||||
float y = cfg.offy;
|
||||
|
||||
vertexData.Position.x = x * (2.0f / float(GetWidth()));
|
||||
vertexData.Position.y = -y * (2.0f / float(GetHeight()));
|
||||
|
||||
vertexData.ScreenAspect.x =
|
||||
(float(GetHeight()) / float(GetWidth())); // 0.5 = character width / character height
|
||||
vertexData.ScreenAspect.y = 1.0f;
|
||||
|
||||
vertexData.TextureResolution.x = 1.0f / vertexData.ScreenAspect.x;
|
||||
vertexData.TextureResolution.y = 1.0f;
|
||||
|
||||
vertexData.LineStrip = 0;
|
||||
|
||||
if(cfg.rangemax <= cfg.rangemin)
|
||||
cfg.rangemax += 0.00001f;
|
||||
|
||||
pixelData.Channels.x = cfg.Red ? 1.0f : 0.0f;
|
||||
pixelData.Channels.y = cfg.Green ? 1.0f : 0.0f;
|
||||
pixelData.Channels.z = cfg.Blue ? 1.0f : 0.0f;
|
||||
pixelData.Channels.w = cfg.Alpha ? 1.0f : 0.0f;
|
||||
|
||||
pixelData.RangeMinimum = cfg.rangemin;
|
||||
pixelData.InverseRangeSize = 1.0f / (cfg.rangemax - cfg.rangemin);
|
||||
|
||||
if(_isnan(pixelData.InverseRangeSize) || !_finite(pixelData.InverseRangeSize))
|
||||
{
|
||||
pixelData.InverseRangeSize = FLT_MAX;
|
||||
}
|
||||
|
||||
pixelData.WireframeColour.x = cfg.HDRMul;
|
||||
|
||||
pixelData.RawOutput = cfg.rawoutput ? 1 : 0;
|
||||
|
||||
pixelData.FlipY = cfg.FlipY ? 1 : 0;
|
||||
|
||||
// TODO GetShaderDetails(cfg.texid, cfg.typeHint, cfg.rawoutput ? true : false);
|
||||
WrappedID3D12Resource *resource = WrappedID3D12Resource::m_List[cfg.texid];
|
||||
D3D12_RESOURCE_DESC resourceDesc = resource->GetDesc();
|
||||
|
||||
pixelData.SampleIdx = (int)RDCCLAMP(cfg.sampleIdx, 0U, resourceDesc.SampleDesc.Count - 1);
|
||||
|
||||
// hacky resolve
|
||||
if(cfg.sampleIdx == ~0U)
|
||||
pixelData.SampleIdx = -int(resourceDesc.SampleDesc.Count);
|
||||
|
||||
if(resourceDesc.Format == DXGI_FORMAT_UNKNOWN)
|
||||
return false;
|
||||
|
||||
if(resourceDesc.Format == DXGI_FORMAT_A8_UNORM && cfg.scale <= 0.0f)
|
||||
{
|
||||
pixelData.Channels.x = pixelData.Channels.y = pixelData.Channels.z = 0.0f;
|
||||
pixelData.Channels.w = 1.0f;
|
||||
}
|
||||
|
||||
float tex_x = float(resourceDesc.Width);
|
||||
float tex_y =
|
||||
float(resourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE1D ? 100 : resourceDesc.Height);
|
||||
|
||||
vertexData.TextureResolution.x *= tex_x / float(GetWidth());
|
||||
vertexData.TextureResolution.y *= tex_y / float(GetHeight());
|
||||
|
||||
pixelData.TextureResolutionPS.x = float(RDCMAX(1U, uint32_t(resourceDesc.Width >> cfg.mip)));
|
||||
pixelData.TextureResolutionPS.y = float(RDCMAX(1U, uint32_t(resourceDesc.Height >> cfg.mip)));
|
||||
pixelData.TextureResolutionPS.z =
|
||||
float(RDCMAX(1U, uint32_t(resourceDesc.DepthOrArraySize >> cfg.mip)));
|
||||
|
||||
if(resourceDesc.DepthOrArraySize > 1 && resourceDesc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D)
|
||||
pixelData.TextureResolutionPS.z = float(resourceDesc.DepthOrArraySize);
|
||||
|
||||
vertexData.Scale = cfg.scale;
|
||||
pixelData.ScalePS = cfg.scale;
|
||||
|
||||
if(cfg.scale <= 0.0f)
|
||||
{
|
||||
float xscale = float(GetWidth()) / tex_x;
|
||||
float yscale = float(GetHeight()) / tex_y;
|
||||
|
||||
vertexData.Scale = RDCMIN(xscale, yscale);
|
||||
|
||||
if(yscale > xscale)
|
||||
{
|
||||
vertexData.Position.x = 0;
|
||||
vertexData.Position.y = tex_y * vertexData.Scale / float(GetHeight()) - 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
vertexData.Position.y = 0;
|
||||
vertexData.Position.x = 1.0f - tex_x * vertexData.Scale / float(GetWidth());
|
||||
}
|
||||
}
|
||||
|
||||
vertexData.Scale *= 2.0f; // viewport is -1 -> 1
|
||||
|
||||
pixelData.MipLevel = (float)cfg.mip;
|
||||
pixelData.OutputDisplayFormat = RESTYPE_TEX2D;
|
||||
pixelData.Slice = float(RDCCLAMP(cfg.sliceFace, 0U, uint32_t(resourceDesc.DepthOrArraySize - 1)));
|
||||
|
||||
if(resourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D)
|
||||
{
|
||||
pixelData.OutputDisplayFormat = RESTYPE_TEX3D;
|
||||
pixelData.Slice = float(cfg.sliceFace) / float(resourceDesc.DepthOrArraySize);
|
||||
}
|
||||
else if(resourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE1D)
|
||||
{
|
||||
pixelData.OutputDisplayFormat = RESTYPE_TEX1D;
|
||||
}
|
||||
/*
|
||||
else if(details.texType == eTexType_Depth)
|
||||
{
|
||||
pixelData.OutputDisplayFormat = RESTYPE_DEPTH;
|
||||
}
|
||||
else if(details.texType == eTexType_Stencil)
|
||||
{
|
||||
pixelData.OutputDisplayFormat = RESTYPE_DEPTH_STENCIL;
|
||||
}
|
||||
else if(details.texType == eTexType_DepthMS)
|
||||
{
|
||||
pixelData.OutputDisplayFormat = RESTYPE_DEPTH_MS;
|
||||
}
|
||||
else if(details.texType == eTexType_StencilMS)
|
||||
{
|
||||
pixelData.OutputDisplayFormat = RESTYPE_DEPTH_STENCIL_MS;
|
||||
}*/
|
||||
else if(resourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D &&
|
||||
resourceDesc.SampleDesc.Count > 1)
|
||||
{
|
||||
pixelData.OutputDisplayFormat = RESTYPE_TEX2D_MS;
|
||||
}
|
||||
|
||||
if(cfg.overlay == eTexOverlay_NaN)
|
||||
{
|
||||
pixelData.OutputDisplayFormat |= TEXDISPLAY_NANS;
|
||||
}
|
||||
|
||||
if(cfg.overlay == eTexOverlay_Clipping)
|
||||
{
|
||||
pixelData.OutputDisplayFormat |= TEXDISPLAY_CLIPPING;
|
||||
}
|
||||
|
||||
int srvOffset = 0;
|
||||
|
||||
if(IsUIntFormat(resourceDesc.Format))
|
||||
{
|
||||
pixelData.OutputDisplayFormat |= TEXDISPLAY_UINT_TEX;
|
||||
srvOffset = 10;
|
||||
}
|
||||
if(IsIntFormat(resourceDesc.Format))
|
||||
{
|
||||
pixelData.OutputDisplayFormat |= TEXDISPLAY_SINT_TEX;
|
||||
srvOffset = 20;
|
||||
}
|
||||
if(!IsSRGBFormat(resourceDesc.Format) && cfg.linearDisplayAsGamma)
|
||||
{
|
||||
pixelData.OutputDisplayFormat |= TEXDISPLAY_GAMMA_CURVE;
|
||||
}
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE srv = cbvsrvHeap->GetCPUDescriptorHandleForHeapStart();
|
||||
|
||||
// hack, tex2d float is slot 2
|
||||
srv.ptr +=
|
||||
2 * m_WrappedDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
srvDesc.Texture2D.MipLevels = 1;
|
||||
srvDesc.Texture2D.MostDetailedMip = 0;
|
||||
srvDesc.Texture2D.PlaneSlice = 0;
|
||||
srvDesc.Texture2D.ResourceMinLODClamp = 0.0f;
|
||||
|
||||
m_WrappedDevice->CreateShaderResourceView(resource, &srvDesc, srv);
|
||||
|
||||
FillCBuffer(m_GenericVSCbuffer, &vertexData, sizeof(DebugVertexCBuffer));
|
||||
FillCBuffer(m_GenericPSCbuffer, &pixelData, sizeof(DebugPixelCBufferData));
|
||||
|
||||
OutputWindow &outw = m_OutputWindows[m_CurrentOutputWindow];
|
||||
|
||||
// can't just clear state because we need to keep things like render targets.
|
||||
{
|
||||
ID3D12GraphicsCommandList *list = m_WrappedDevice->GetNewList();
|
||||
|
||||
list->OMSetRenderTargets(1, &outw.rtv, TRUE, NULL);
|
||||
|
||||
list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
|
||||
if(cfg.rawoutput || !blendAlpha || cfg.CustomShader != ResourceId())
|
||||
list->SetPipelineState(m_TexDisplayPipe);
|
||||
else
|
||||
list->SetPipelineState(m_TexDisplayBlendPipe);
|
||||
|
||||
list->SetGraphicsRootSignature(m_TexDisplayRootSig);
|
||||
|
||||
// Set the descriptor heap containing the texture srv
|
||||
ID3D12DescriptorHeap *heaps[] = {cbvsrvHeap, samplerHeap};
|
||||
list->SetDescriptorHeaps(2, heaps);
|
||||
|
||||
list->SetGraphicsRootConstantBufferView(0, m_GenericVSCbuffer->GetGPUVirtualAddress());
|
||||
list->SetGraphicsRootConstantBufferView(1, m_GenericPSCbuffer->GetGPUVirtualAddress());
|
||||
list->SetGraphicsRootDescriptorTable(2, cbvsrvHeap->GetGPUDescriptorHandleForHeapStart());
|
||||
list->SetGraphicsRootDescriptorTable(3, samplerHeap->GetGPUDescriptorHandleForHeapStart());
|
||||
|
||||
float factor[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
list->OMSetBlendFactor(factor);
|
||||
|
||||
list->DrawInstanced(4, 1, 0, 0);
|
||||
|
||||
list->Close();
|
||||
|
||||
m_WrappedDevice->ExecuteLists();
|
||||
m_WrappedDevice->FlushLists();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -55,6 +55,8 @@ public:
|
||||
}
|
||||
int GetWidth() { return m_width; }
|
||||
int GetHeight() { return m_height; }
|
||||
bool RenderTexture(TextureDisplay cfg, bool blendAlpha);
|
||||
|
||||
private:
|
||||
struct OutputWindow
|
||||
{
|
||||
@@ -75,12 +77,35 @@ private:
|
||||
int width, height;
|
||||
};
|
||||
|
||||
void FillCBuffer(ID3D12Resource *buf, void *data, size_t size);
|
||||
|
||||
ID3D12DescriptorHeap *cbvsrvHeap;
|
||||
ID3D12DescriptorHeap *samplerHeap;
|
||||
ID3D12DescriptorHeap *rtvHeap;
|
||||
ID3D12DescriptorHeap *dsvHeap;
|
||||
|
||||
ID3D12Resource *m_GenericVSCbuffer;
|
||||
ID3D12Resource *m_GenericPSCbuffer;
|
||||
|
||||
ID3D12PipelineState *m_TexDisplayPipe;
|
||||
ID3D12PipelineState *m_TexDisplayBlendPipe;
|
||||
|
||||
ID3D12RootSignature *m_TexDisplayRootSig;
|
||||
|
||||
static const uint32_t m_ShaderCacheMagic = 0xbaafd1d1;
|
||||
static const uint32_t m_ShaderCacheVersion = 1;
|
||||
|
||||
bool m_ShaderCacheDirty, m_CacheShaders;
|
||||
map<uint32_t, ID3DBlob *> m_ShaderCache;
|
||||
|
||||
string GetShaderBlob(const char *source, const char *entry, const uint32_t compileFlags,
|
||||
const char *profile, ID3DBlob **srcblob);
|
||||
ID3DBlob *MakeRootSig(const vector<D3D12_ROOT_PARAMETER> &rootSig);
|
||||
|
||||
int m_width, m_height;
|
||||
|
||||
uint64_t m_OutputWindowID;
|
||||
uint64_t m_CurrentOutputWindow;
|
||||
map<uint64_t, OutputWindow> m_OutputWindows;
|
||||
|
||||
WrappedID3D12Device *m_WrappedDevice;
|
||||
|
||||
@@ -282,7 +282,7 @@ void D3D12Replay::BuildCustomShader(string source, string entry, const uint32_t
|
||||
|
||||
bool D3D12Replay::RenderTexture(TextureDisplay cfg)
|
||||
{
|
||||
return false;
|
||||
return m_pDevice->GetDebugManager()->RenderTexture(cfg, true);
|
||||
}
|
||||
|
||||
void D3D12Replay::RenderCheckerboard(Vec3f light, Vec3f dark)
|
||||
|
||||
Reference in New Issue
Block a user