diff --git a/renderdoc/data/hlsl/empty.dxbc b/renderdoc/data/hlsl/empty.dxbc new file mode 100644 index 000000000..e69de29bb diff --git a/renderdoc/data/renderdoc.rc b/renderdoc/data/renderdoc.rc index 26ffde5da..c640ccc5e 100644 --- a/renderdoc/data/renderdoc.rc +++ b/renderdoc/data/renderdoc.rc @@ -115,6 +115,29 @@ RESOURCE_quadoverdraw_hlsl TYPE_EMBED "hlsl/quadoverdraw.hlsl" RESOURCE_texremap_hlsl TYPE_EMBED "hlsl/texremap.hlsl" RESOURCE_fixedcol_hlsl TYPE_EMBED "hlsl/fixedcol.hlsl" +#ifdef RENDERDOC_BAKED_DXC_SHADERS + +#if !defined(CONCAT) +#define CONCAT2(a, b) a##b +#define CONCAT(a, b) CONCAT2(a, b) +#endif + +RESOURCE_fixedcol_0_dxbc TYPE_EMBED CONCAT(RENDERDOC_BAKED_PATH, fixedcol_0.dxbc) +RESOURCE_fixedcol_1_dxbc TYPE_EMBED CONCAT(RENDERDOC_BAKED_PATH, fixedcol_1.dxbc) +RESOURCE_fixedcol_2_dxbc TYPE_EMBED CONCAT(RENDERDOC_BAKED_PATH, fixedcol_2.dxbc) +RESOURCE_fixedcol_3_dxbc TYPE_EMBED CONCAT(RENDERDOC_BAKED_PATH, fixedcol_3.dxbc) +RESOURCE_quadwrite_dxbc TYPE_EMBED CONCAT(RENDERDOC_BAKED_PATH, quadwrite.dxbc) + +#else + +RESOURCE_fixedcol_0_dxbc TYPE_EMBED "hlsl/empty.dxbc" +RESOURCE_fixedcol_1_dxbc TYPE_EMBED "hlsl/empty.dxbc" +RESOURCE_fixedcol_2_dxbc TYPE_EMBED "hlsl/empty.dxbc" +RESOURCE_fixedcol_3_dxbc TYPE_EMBED "hlsl/empty.dxbc" +RESOURCE_quadwrite_dxbc TYPE_EMBED "hlsl/empty.dxbc" + +#endif + RESOURCE_sourcecodepro_ttf TYPE_EMBED "sourcecodepro.ttf" RESOURCE_glsl_blit_vert TYPE_EMBED "glsl/blit.vert" diff --git a/renderdoc/data/resource.h b/renderdoc/data/resource.h index 803943fd4..0e9dc2079 100644 --- a/renderdoc/data/resource.h +++ b/renderdoc/data/resource.h @@ -18,6 +18,12 @@ #define RESOURCE_texremap_hlsl 111 #define RESOURCE_fixedcol_hlsl 112 +#define RESOURCE_fixedcol_0_dxbc 113 +#define RESOURCE_fixedcol_1_dxbc 114 +#define RESOURCE_fixedcol_2_dxbc 115 +#define RESOURCE_fixedcol_3_dxbc 116 +#define RESOURCE_quadwrite_dxbc 117 + #define RESOURCE_sourcecodepro_ttf 301 #define RESOURCE_glsl_blit_vert 401 diff --git a/renderdoc/driver/d3d12/d3d12_debug.cpp b/renderdoc/driver/d3d12/d3d12_debug.cpp index ee01df0ee..e172b2ee2 100644 --- a/renderdoc/driver/d3d12/d3d12_debug.cpp +++ b/renderdoc/driver/d3d12/d3d12_debug.cpp @@ -1296,6 +1296,21 @@ void D3D12Replay::OverlayRendering::Init(WrappedID3D12Device *device, D3D12Debug shaderCache->GetShaderBlob(hlsl.c_str(), "RENDERDOC_QuadOverdrawPS", D3DCOMPILE_WARNINGS_ARE_ERRORS, "ps_5_0", &QuadOverdrawWritePS); + + shaderCache->GetShaderBlob(hlsl.c_str(), "RENDERDOC_QuadOverdrawPS", + D3DCOMPILE_WARNINGS_ARE_ERRORS, "ps_6_0", &QuadOverdrawWriteDXILPS); + + if(QuadOverdrawWriteDXILPS == NULL) + { + RDCWARN("Couldn't compile DXIL overlay shader at runtime, falling back to baked DXIL shader"); + + QuadOverdrawWriteDXILPS = shaderCache->GetQuadShaderDXILBlob(); + + if(!QuadOverdrawWriteDXILPS) + { + RDCWARN("No fallback DXIL shader available!"); + } + } } { @@ -1372,6 +1387,7 @@ void D3D12Replay::OverlayRendering::Release() SAFE_RELEASE(TriangleSizeGS); SAFE_RELEASE(TriangleSizePS); SAFE_RELEASE(QuadOverdrawWritePS); + SAFE_RELEASE(QuadOverdrawWriteDXILPS); SAFE_RELEASE(QuadResolveRootSig); SAFE_RELEASE(QuadResolvePipe); diff --git a/renderdoc/driver/d3d12/d3d12_overlay.cpp b/renderdoc/driver/d3d12/d3d12_overlay.cpp index 130b3f5e1..ad2139f96 100644 --- a/renderdoc/driver/d3d12/d3d12_overlay.cpp +++ b/renderdoc/driver/d3d12/d3d12_overlay.cpp @@ -43,8 +43,13 @@ struct D3D12QuadOverdrawCallback : public D3D12DrawcallCallback { D3D12QuadOverdrawCallback(WrappedID3D12Device *dev, D3D12_SHADER_BYTECODE quadWrite, - const rdcarray &events, PortableHandle uav) - : m_pDevice(dev), m_QuadWritePS(quadWrite), m_Events(events), m_UAV(uav) + D3D12_SHADER_BYTECODE quadWriteDXIL, const rdcarray &events, + PortableHandle uav) + : m_pDevice(dev), + m_QuadWritePS(quadWrite), + m_QuadWriteDXILPS(quadWriteDXIL), + m_Events(events), + m_UAV(uav) { m_pDevice->GetQueue()->GetCommandData()->m_DrawcallCallback = this; } @@ -131,7 +136,23 @@ struct D3D12QuadOverdrawCallback : public D3D12DrawcallCallback pipeDesc.DepthStencilState.BackFace.StencilDepthFailOp = D3D12_STENCIL_OP_KEEP; pipeDesc.DepthStencilState.StencilWriteMask = 0; - pipeDesc.PS = m_QuadWritePS; + bool dxil = + DXBC::DXBCContainer::CheckForDXIL(pipeDesc.VS.pShaderBytecode, pipeDesc.VS.BytecodeLength); + + if(dxil) + { + pipeDesc.PS = m_QuadWriteDXILPS; + if(pipeDesc.PS.BytecodeLength == 0) + { + m_pDevice->AddDebugMessage(MessageCategory::Shaders, MessageSeverity::High, + MessageSource::UnsupportedConfiguration, + "No DXIL shader available for overlay"); + } + } + else + { + pipeDesc.PS = m_QuadWritePS; + } pipeDesc.pRootSignature = cache.sig; @@ -185,6 +206,7 @@ struct D3D12QuadOverdrawCallback : public D3D12DrawcallCallback WrappedID3D12Device *m_pDevice; D3D12_SHADER_BYTECODE m_QuadWritePS; + D3D12_SHADER_BYTECODE m_QuadWriteDXILPS; const rdcarray &m_Events; PortableHandle m_UAV; @@ -475,11 +497,11 @@ ResourceId D3D12Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC psoDesc; pipe->Fill(psoDesc); - float overlayConsts[4] = {0.8f, 0.1f, 0.8f, 1.0f}; - ID3DBlob *ps = m_pDevice->GetShaderCache()->MakeFixedColShader(overlayConsts); + bool dxil = + DXBC::DXBCContainer::CheckForDXIL(psoDesc.VS.pShaderBytecode, psoDesc.VS.BytecodeLength); - psoDesc.PS.pShaderBytecode = ps->GetBufferPointer(); - psoDesc.PS.BytecodeLength = ps->GetBufferSize(); + ID3DBlob *ps = + m_pDevice->GetShaderCache()->MakeFixedColShader(D3D12ShaderCache::HIGHLIGHT, dxil); psoDesc.DepthStencilState.DepthEnable = FALSE; psoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO; @@ -514,6 +536,17 @@ ResourceId D3D12Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De list->Close(); list = NULL; + if(!ps) + { + m_pDevice->AddDebugMessage(MessageCategory::Shaders, MessageSeverity::High, + MessageSource::UnsupportedConfiguration, + "No DXIL shader available for overlay"); + return m_Overlay.resourceId; + } + + psoDesc.PS.pShaderBytecode = ps->GetBufferPointer(); + psoDesc.PS.BytecodeLength = ps->GetBufferSize(); + ID3D12PipelineState *pso = NULL; HRESULT hr = m_pDevice->CreatePipeState(psoDesc, &pso); if(FAILED(hr)) @@ -551,11 +584,12 @@ ResourceId D3D12Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De D3D12_CULL_MODE origCull = psoDesc.RasterizerState.CullMode; BOOL origFrontCCW = psoDesc.RasterizerState.FrontCounterClockwise; - float redCol[4] = {1.0f, 0.0f, 0.0f, 1.0f}; - ID3DBlob *red = m_pDevice->GetShaderCache()->MakeFixedColShader(redCol); + bool dxil = + DXBC::DXBCContainer::CheckForDXIL(psoDesc.VS.pShaderBytecode, psoDesc.VS.BytecodeLength); - float greenCol[4] = {0.0f, 1.0f, 0.0f, 1.0f}; - ID3DBlob *green = m_pDevice->GetShaderCache()->MakeFixedColShader(greenCol); + ID3DBlob *red = m_pDevice->GetShaderCache()->MakeFixedColShader(D3D12ShaderCache::RED, dxil); + ID3DBlob *green = + m_pDevice->GetShaderCache()->MakeFixedColShader(D3D12ShaderCache::GREEN, dxil); psoDesc.DepthStencilState.DepthEnable = FALSE; psoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO; @@ -583,15 +617,25 @@ ResourceId D3D12Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De psoDesc.RasterizerState.MultisampleEnable = FALSE; psoDesc.RasterizerState.AntialiasedLineEnable = FALSE; - psoDesc.PS.pShaderBytecode = red->GetBufferPointer(); - psoDesc.PS.BytecodeLength = red->GetBufferSize(); - float clearColour[] = {0.0f, 1.0f, 0.0f, 0.0f}; list->ClearRenderTargetView(rtv, clearColour, 0, NULL); list->Close(); list = NULL; + if(!red || !green) + { + SAFE_RELEASE(red); + SAFE_RELEASE(green); + m_pDevice->AddDebugMessage(MessageCategory::Shaders, MessageSeverity::High, + MessageSource::UnsupportedConfiguration, + "No DXIL shader available for overlay"); + return m_Overlay.resourceId; + } + + psoDesc.PS.pShaderBytecode = red->GetBufferPointer(); + psoDesc.PS.BytecodeLength = red->GetBufferSize(); + ID3D12PipelineState *redPSO = NULL; HRESULT hr = m_pDevice->CreatePipeState(psoDesc, &redPSO); if(FAILED(hr)) @@ -649,11 +693,11 @@ ResourceId D3D12Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC psoDesc; pipe->Fill(psoDesc); - float overlayConsts[] = {200.0f / 255.0f, 255.0f / 255.0f, 0.0f / 255.0f, 1.0f}; - ID3DBlob *ps = m_pDevice->GetShaderCache()->MakeFixedColShader(overlayConsts); + bool dxil = + DXBC::DXBCContainer::CheckForDXIL(psoDesc.VS.pShaderBytecode, psoDesc.VS.BytecodeLength); - psoDesc.PS.pShaderBytecode = ps->GetBufferPointer(); - psoDesc.PS.BytecodeLength = ps->GetBufferSize(); + ID3DBlob *ps = + m_pDevice->GetShaderCache()->MakeFixedColShader(D3D12ShaderCache::WIREFRAME, dxil); psoDesc.DepthStencilState.DepthEnable = FALSE; psoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO; @@ -681,12 +725,23 @@ ResourceId D3D12Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De psoDesc.RasterizerState.MultisampleEnable = FALSE; psoDesc.RasterizerState.AntialiasedLineEnable = FALSE; - overlayConsts[3] = 0.0f; - list->ClearRenderTargetView(rtv, overlayConsts, 0, NULL); + float wireClearCol[4] = {200.0f / 255.0f, 255.0f / 255.0f, 0.0f / 255.0f, 0.0f}; + list->ClearRenderTargetView(rtv, wireClearCol, 0, NULL); list->Close(); list = NULL; + if(!ps) + { + m_pDevice->AddDebugMessage(MessageCategory::Shaders, MessageSeverity::High, + MessageSource::UnsupportedConfiguration, + "No DXIL shader available for overlay"); + return m_Overlay.resourceId; + } + + psoDesc.PS.pShaderBytecode = ps->GetBufferPointer(); + psoDesc.PS.BytecodeLength = ps->GetBufferSize(); + ID3D12PipelineState *pso = NULL; HRESULT hr = m_pDevice->CreatePipeState(psoDesc, &pso); if(FAILED(hr)) @@ -1133,8 +1188,15 @@ ResourceId D3D12Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De quadWrite.BytecodeLength = m_Overlay.QuadOverdrawWritePS->GetBufferSize(); quadWrite.pShaderBytecode = m_Overlay.QuadOverdrawWritePS->GetBufferPointer(); + D3D12_SHADER_BYTECODE quadWriteDXIL = {}; + if(m_Overlay.QuadOverdrawWriteDXILPS) + { + quadWriteDXIL.BytecodeLength = m_Overlay.QuadOverdrawWriteDXILPS->GetBufferSize(); + quadWriteDXIL.pShaderBytecode = m_Overlay.QuadOverdrawWriteDXILPS->GetBufferPointer(); + } + // declare callback struct here - D3D12QuadOverdrawCallback cb(m_pDevice, quadWrite, events, + D3D12QuadOverdrawCallback cb(m_pDevice, quadWrite, quadWriteDXIL, events, ToPortableHandle(GetDebugManager()->GetCPUHandle(OVERDRAW_UAV))); m_pDevice->ReplayLog(events.front(), events.back(), eReplay_Full); @@ -1202,11 +1264,12 @@ ResourceId D3D12Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC psoDesc; pipe->Fill(psoDesc); - float redCol[4] = {1.0f, 0.0f, 0.0f, 1.0f}; - ID3DBlob *red = m_pDevice->GetShaderCache()->MakeFixedColShader(redCol); + bool dxil = + DXBC::DXBCContainer::CheckForDXIL(psoDesc.VS.pShaderBytecode, psoDesc.VS.BytecodeLength); - float greenCol[4] = {0.0f, 1.0f, 0.0f, 1.0f}; - ID3DBlob *green = m_pDevice->GetShaderCache()->MakeFixedColShader(greenCol); + ID3DBlob *red = m_pDevice->GetShaderCache()->MakeFixedColShader(D3D12ShaderCache::RED, dxil); + ID3DBlob *green = + m_pDevice->GetShaderCache()->MakeFixedColShader(D3D12ShaderCache::GREEN, dxil); // make sure that if a test is disabled, it shows all // pixels passing @@ -1250,15 +1313,25 @@ ResourceId D3D12Replay::RenderOverlay(ResourceId texid, FloatVector clearCol, De psoDesc.RasterizerState.MultisampleEnable = FALSE; psoDesc.RasterizerState.AntialiasedLineEnable = FALSE; - psoDesc.PS.pShaderBytecode = green->GetBufferPointer(); - psoDesc.PS.BytecodeLength = green->GetBufferSize(); - float clearColour[] = {0.0f, 1.0f, 0.0f, 0.0f}; list->ClearRenderTargetView(rtv, clearColour, 0, NULL); list->Close(); list = NULL; + if(!red || !green) + { + SAFE_RELEASE(red); + SAFE_RELEASE(green); + m_pDevice->AddDebugMessage(MessageCategory::Shaders, MessageSeverity::High, + MessageSource::UnsupportedConfiguration, + "No DXIL shader available for overlay"); + return m_Overlay.resourceId; + } + + psoDesc.PS.pShaderBytecode = green->GetBufferPointer(); + psoDesc.PS.BytecodeLength = green->GetBufferSize(); + ID3D12PipelineState *greenPSO = NULL; HRESULT hr = m_pDevice->CreatePipeState(psoDesc, &greenPSO); if(FAILED(hr)) diff --git a/renderdoc/driver/d3d12/d3d12_replay.h b/renderdoc/driver/d3d12/d3d12_replay.h index 55e285266..685355e72 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.h +++ b/renderdoc/driver/d3d12/d3d12_replay.h @@ -366,6 +366,7 @@ private: ID3DBlob *TriangleSizeGS = NULL; ID3DBlob *TriangleSizePS = NULL; ID3DBlob *QuadOverdrawWritePS = NULL; + ID3DBlob *QuadOverdrawWriteDXILPS = NULL; ID3D12RootSignature *QuadResolveRootSig = NULL; ID3D12PipelineState *QuadResolvePipe = NULL; diff --git a/renderdoc/driver/d3d12/d3d12_shader_cache.cpp b/renderdoc/driver/d3d12/d3d12_shader_cache.cpp index c4dda4ec9..7b6c0d723 100644 --- a/renderdoc/driver/d3d12/d3d12_shader_cache.cpp +++ b/renderdoc/driver/d3d12/d3d12_shader_cache.cpp @@ -799,14 +799,37 @@ ID3DBlob *D3D12ShaderCache::MakeRootSig(const D3D12RootSignature &rootsig) rootsig.StaticSamplers.empty() ? NULL : &rootsig.StaticSamplers[0]); } -ID3DBlob *D3D12ShaderCache::MakeFixedColShader(FixedColVariant variant) +ID3DBlob *D3D12ShaderCache::MakeFixedColShader(FixedColVariant variant, bool dxil) { ID3DBlob *ret = NULL; rdcstr hlsl = StringFormat::Fmt("#define VARIANT %u\n\n", variant) + GetEmbeddedResource(fixedcol_hlsl); bool wasCaching = m_CacheShaders; m_CacheShaders = true; - GetShaderBlob(hlsl.c_str(), "main", ShaderCompileFlags(), "ps_5_0", &ret); + GetShaderBlob(hlsl.c_str(), "main", ShaderCompileFlags(), dxil ? "ps_6_0" : "ps_5_0", &ret); m_CacheShaders = wasCaching; + + if(!ret) + { + const rdcstr embedded[] = { + GetEmbeddedResource(fixedcol_0_dxbc), GetEmbeddedResource(fixedcol_1_dxbc), + GetEmbeddedResource(fixedcol_2_dxbc), GetEmbeddedResource(fixedcol_3_dxbc), + }; + + D3D12ShaderCacheCallbacks.Create((uint32_t)embedded[variant].size(), embedded[variant].data(), + &ret); + } + + return ret; +} + +ID3DBlob *D3D12ShaderCache::GetQuadShaderDXILBlob() +{ + rdcstr embedded = GetEmbeddedResource(quadwrite_dxbc); + if(embedded.empty() || !embedded.beginsWith("DXBC")) + return NULL; + + ID3DBlob *ret = NULL; + D3D12ShaderCacheCallbacks.Create((uint32_t)embedded.size(), embedded.data(), &ret); return ret; } diff --git a/renderdoc/driver/d3d12/d3d12_shader_cache.h b/renderdoc/driver/d3d12/d3d12_shader_cache.h index 06c5f4bda..d7a941cb6 100644 --- a/renderdoc/driver/d3d12/d3d12_shader_cache.h +++ b/renderdoc/driver/d3d12/d3d12_shader_cache.h @@ -58,7 +58,8 @@ public: HIGHLIGHT = 2, WIREFRAME = 3, }; - ID3DBlob *MakeFixedColShader(FixedColVariant variant); + ID3DBlob *MakeFixedColShader(FixedColVariant variant, bool dxil = false); + ID3DBlob *GetQuadShaderDXILBlob(); void SetCaching(bool enabled) { m_CacheShaders = enabled; } private: diff --git a/renderdoc/renderdoc.vcxproj b/renderdoc/renderdoc.vcxproj index 3b5dae41c..c241baac3 100644 --- a/renderdoc/renderdoc.vcxproj +++ b/renderdoc/renderdoc.vcxproj @@ -627,6 +627,93 @@ + + + + + + + + + +using System; +using System.Diagnostics; +using System.Linq; +using System.Runtime.CompilerServices; + +namespace DXCEnumerateAndCheck { + public class GetDXCExecutable : Microsoft.Build.Utilities.Task { + public override bool Execute() { + string[] dirs = System.IO.Directory.GetDirectories(SDKPath, "10.*"); + // sort and reverse so we try from latest to oldest + System.Array.Sort(dirs); + System.Array.Reverse(dirs); + + // look for the latest dxc.exe available that works + foreach(string path in dirs) + { + string dxcCheck = System.IO.Path.Combine(path, "x64", "dxc.exe"); + if(System.IO.File.Exists(dxcCheck)) + { + // check that dxc.exe is runnable, some dxc.exe are broken + try + { + ProcessStartInfo psi = new ProcessStartInfo(); + psi.UseShellExecute = false; + psi.FileName = dxcCheck; + psi.CreateNoWindow = true; + Process.Start(psi); + DXC = dxcCheck; + return true; + } + catch(Exception ex) + { + // keep going, maybe we'll find one that works + } + } + } + // always succeed even if we don't find dxc + return true; + } + + [Microsoft.Build.Framework.Required] public string SDKPath { get; set; } + [Microsoft.Build.Framework.Output] public string DXC { get; set; } + } +} + + + + + + + + + + + + + $(IntDir) + $(DXILBakedDir.Replace('\', '/')) + + + + + RENDERDOC_BAKED_DXC_SHADERS=1;RENDERDOC_BAKED_PATH="$(DXILBakedDirParam)";%(PreprocessorDefinitions) + + + + + + + + + + + + + + +