From 7d50aad4d77876f5b20bb53bf3421cc2732868d9 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 8 Jul 2016 20:42:06 +0300 Subject: [PATCH] Implement RenderTexture() (in a hacky way) --- renderdoc/driver/d3d12/d3d12_debug.cpp | 654 +++++++++++++++++++++++- renderdoc/driver/d3d12/d3d12_debug.h | 25 + renderdoc/driver/d3d12/d3d12_replay.cpp | 2 +- 3 files changed, 677 insertions(+), 4 deletions(-) diff --git a/renderdoc/driver/d3d12/d3d12_debug.cpp b/renderdoc/driver/d3d12/d3d12_debug.cpp index 114e841ef..e58f408c7 100644 --- a/renderdoc/driver/d3d12/d3d12_debug.cpp +++ b/renderdoc/driver/d3d12/d3d12_debug.cpp @@ -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 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 &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; +} diff --git a/renderdoc/driver/d3d12/d3d12_debug.h b/renderdoc/driver/d3d12/d3d12_debug.h index 39242dbf5..835ebdb6b 100644 --- a/renderdoc/driver/d3d12/d3d12_debug.h +++ b/renderdoc/driver/d3d12/d3d12_debug.h @@ -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 m_ShaderCache; + + string GetShaderBlob(const char *source, const char *entry, const uint32_t compileFlags, + const char *profile, ID3DBlob **srcblob); + ID3DBlob *MakeRootSig(const vector &rootSig); + int m_width, m_height; uint64_t m_OutputWindowID; + uint64_t m_CurrentOutputWindow; map m_OutputWindows; WrappedID3D12Device *m_WrappedDevice; diff --git a/renderdoc/driver/d3d12/d3d12_replay.cpp b/renderdoc/driver/d3d12/d3d12_replay.cpp index 4305d3c6b..ee52a4840 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.cpp +++ b/renderdoc/driver/d3d12/d3d12_replay.cpp @@ -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)