From b9b419c86ae330f2d2df18440e69447342c4c471 Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 21 Sep 2016 18:52:12 +0200 Subject: [PATCH] Process root signature elements into pipeline state --- renderdoc/api/replay/d3d12_pipestate.h | 74 +-- renderdoc/api/replay/replay_enums.h | 4 + renderdoc/driver/d3d11/d3d11_replay.cpp | 7 +- renderdoc/driver/d3d12/d3d12_common.cpp | 314 ++++++++++++ renderdoc/driver/d3d12/d3d12_common.h | 17 +- renderdoc/driver/d3d12/d3d12_debug.cpp | 7 +- renderdoc/driver/d3d12/d3d12_replay.cpp | 596 ++++++++++------------ renderdoc/driver/d3d12/d3d12_replay.h | 2 +- renderdoc/driver/d3d12/d3d12_state.h | 2 +- renderdocui/Interop/D3D12PipelineState.cs | 60 +-- 10 files changed, 688 insertions(+), 395 deletions(-) diff --git a/renderdoc/api/replay/d3d12_pipestate.h b/renderdoc/api/replay/d3d12_pipestate.h index f333cdb18..dc6733ae5 100644 --- a/renderdoc/api/replay/d3d12_pipestate.h +++ b/renderdoc/api/replay/d3d12_pipestate.h @@ -83,10 +83,16 @@ struct D3D12PipelineState ShaderStageType stage; } m_VS, m_HS, m_DS, m_GS, m_PS, m_CS; + // Immediate indicates either a root parameter (not in a table), or static samplers + // RootElement is the index in the original root signature that this descriptor came from. + struct ResourceView { ResourceView() - : Resource(), + : VisibilityMask(), + Immediate(0), + RootElement(0), + Resource(), Format(), BufferFlags(0), BufferStructCount(0), @@ -106,6 +112,12 @@ struct D3D12PipelineState swizzle[3] = eSwizzle_Alpha; } + // parameters from descriptor + ShaderStageBits VisibilityMask; + bool32 Immediate; + uint32_t RootElement; + + // parameters from resource/view ResourceId Resource; rdctype::str Type; ResourceFormat Format; @@ -134,7 +146,10 @@ struct D3D12PipelineState struct Sampler { Sampler() - : UseBorder(false), + : VisibilityMask(), + Immediate(0), + RootElement(0), + UseBorder(false), UseComparison(false), MaxAniso(0), MaxLOD(0.0f), @@ -143,6 +158,13 @@ struct D3D12PipelineState { BorderColor[0] = BorderColor[1] = BorderColor[2] = BorderColor[3] = 0.0f; } + + // parameters from descriptor + ShaderStageBits VisibilityMask; + bool32 Immediate; + uint32_t RootElement; + + // parameters from resource/view rdctype::str AddressU, AddressV, AddressW; float BorderColor[4]; rdctype::str Comparison; @@ -157,52 +179,32 @@ struct D3D12PipelineState struct CBuffer { - CBuffer() : Buffer(), Offset(0), ByteSize(0) {} + CBuffer() : VisibilityMask(), Immediate(0), RootElement(0), Buffer(), Offset(0), ByteSize(0) {} + // parameters from descriptor + ShaderStageBits VisibilityMask; + bool32 Immediate; + uint32_t RootElement; + + // parameters from resource/view ResourceId Buffer; uint64_t Offset; uint32_t ByteSize; - rdctype::array Immediate; + rdctype::array RootValues; }; struct RootSignature { ResourceId obj; - // Immediate indicates either a root parameter (not in a table), or static samplers - // RootElement is the index in the original root signature that this descriptor came from. - - struct CBufferDescriptor + struct RegisterSpace { - ShaderStageBits VisibilityMask; - bool32 Immediate; - uint32_t RootElement; - - CBuffer obj; + rdctype::array ConstantBuffers; + rdctype::array Samplers; + rdctype::array SRVs; + rdctype::array UAVs; }; - - struct ViewDescriptor - { - ShaderStageBits VisibilityMask; - bool32 Immediate; - uint32_t RootElement; - - ResourceView obj; - }; - - struct SamplerDescriptor - { - ShaderStageBits VisibilityMask; - bool32 Immediate; - uint32_t RootElement; - - Sampler obj; - }; - - rdctype::array ConstantBuffers; - rdctype::array Samplers; - rdctype::array SRVs; - rdctype::array UAVs; + rdctype::array Spaces; } m_RootSig; struct Streamout diff --git a/renderdoc/api/replay/replay_enums.h b/renderdoc/api/replay/replay_enums.h index e16b44553..765790990 100644 --- a/renderdoc/api/replay/replay_enums.h +++ b/renderdoc/api/replay/replay_enums.h @@ -320,6 +320,7 @@ enum ShaderStageType enum ShaderStageBits { + eStageBits_None = 0, eStageBits_Vertex = 1 << eShaderStage_Vertex, eStageBits_Hull = 1 << eShaderStage_Hull, eStageBits_Tess_Control = 1 << eShaderStage_Tess_Control, @@ -329,6 +330,9 @@ enum ShaderStageBits eStageBits_Pixel = 1 << eShaderStage_Pixel, eStageBits_Fragment = 1 << eShaderStage_Fragment, eStageBits_Compute = 1 << eShaderStage_Compute, + eStageBits_All = eStageBits_Vertex | eStageBits_Hull | eStageBits_Domain | eStageBits_Geometry | + eStageBits_Pixel | + eStageBits_Compute, }; enum DebugMessageCategory diff --git a/renderdoc/driver/d3d11/d3d11_replay.cpp b/renderdoc/driver/d3d11/d3d11_replay.cpp index eb0b0c00e..f0f74b979 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.cpp +++ b/renderdoc/driver/d3d11/d3d11_replay.cpp @@ -647,12 +647,15 @@ D3D11PipelineState D3D11Replay::MakePipelineState() samp.Filter = ToStr::Get(desc.Filter); samp.MaxAniso = 0; if(desc.Filter == D3D11_FILTER_ANISOTROPIC || - desc.Filter == D3D11_FILTER_COMPARISON_ANISOTROPIC) + desc.Filter == D3D11_FILTER_COMPARISON_ANISOTROPIC || + desc.Filter == D3D11_FILTER_MINIMUM_ANISOTROPIC || + desc.Filter == D3D11_FILTER_MAXIMUM_ANISOTROPIC) samp.MaxAniso = desc.MaxAnisotropy; samp.MaxLOD = desc.MaxLOD; samp.MinLOD = desc.MinLOD; samp.MipLODBias = desc.MipLODBias; - samp.UseComparison = (desc.Filter >= D3D11_FILTER_COMPARISON_MIN_MAG_MIP_POINT); + samp.UseComparison = (desc.Filter >= D3D11_FILTER_COMPARISON_MIN_MAG_MIP_POINT && + desc.Filter <= D3D11_FILTER_COMPARISON_ANISOTROPIC); samp.UseBorder = (desc.AddressU == D3D11_TEXTURE_ADDRESS_BORDER || desc.AddressV == D3D11_TEXTURE_ADDRESS_BORDER || desc.AddressW == D3D11_TEXTURE_ADDRESS_BORDER); diff --git a/renderdoc/driver/d3d12/d3d12_common.cpp b/renderdoc/driver/d3d12/d3d12_common.cpp index ffbb2bdf4..f670f5abc 100644 --- a/renderdoc/driver/d3d12/d3d12_common.cpp +++ b/renderdoc/driver/d3d12/d3d12_common.cpp @@ -28,9 +28,308 @@ #include "d3d12_manager.h" #include "d3d12_resources.h" +static ShaderConstant MakeConstantBufferVariable(const DXBC::CBufferVariable &var, uint32_t &offset); + +static ShaderVariableType MakeShaderVariableType(DXBC::CBufferVariableType type, uint32_t &offset) +{ + ShaderVariableType ret; + + switch(type.descriptor.type) + { + case DXBC::VARTYPE_INT: ret.descriptor.type = eVar_Int; break; + case DXBC::VARTYPE_BOOL: + case DXBC::VARTYPE_UINT: ret.descriptor.type = eVar_UInt; break; + case DXBC::VARTYPE_DOUBLE: ret.descriptor.type = eVar_Double; break; + case DXBC::VARTYPE_FLOAT: + default: ret.descriptor.type = eVar_Float; break; + } + ret.descriptor.rows = type.descriptor.rows; + ret.descriptor.cols = type.descriptor.cols; + ret.descriptor.elements = type.descriptor.elements; + ret.descriptor.name = type.descriptor.name; + ret.descriptor.rowMajorStorage = (type.descriptor.varClass == DXBC::CLASS_MATRIX_ROWS); + + uint32_t baseElemSize = (ret.descriptor.type == eVar_Double) ? 8 : 4; + if(ret.descriptor.rowMajorStorage) + { + uint32_t primary = ret.descriptor.rows; + if(primary == 3) + primary = 4; + ret.descriptor.arrayStride = baseElemSize * primary * ret.descriptor.cols; + } + else + { + uint32_t primary = ret.descriptor.cols; + if(primary == 3) + primary = 4; + ret.descriptor.arrayStride = baseElemSize * primary * ret.descriptor.rows; + } + + uint32_t o = offset; + + create_array_uninit(ret.members, type.members.size()); + for(size_t i = 0; i < type.members.size(); i++) + { + offset = o; + ret.members[i] = MakeConstantBufferVariable(type.members[i], offset); + } + + if(ret.members.count > 0) + { + ret.descriptor.rows = 0; + ret.descriptor.cols = 0; + ret.descriptor.elements = 0; + } + + return ret; +} + +static ShaderConstant MakeConstantBufferVariable(const DXBC::CBufferVariable &var, uint32_t &offset) +{ + ShaderConstant ret; + + ret.name = var.name; + ret.reg.vec = offset + var.descriptor.offset / 16; + ret.reg.comp = (var.descriptor.offset - (var.descriptor.offset & ~0xf)) / 4; + ret.defaultValue = 0; + + offset = ret.reg.vec; + + ret.type = MakeShaderVariableType(var.type, offset); + + offset = ret.reg.vec + RDCMAX(1U, var.type.descriptor.bytesize / 16); + + return ret; +} + void MakeShaderReflection(DXBC::DXBCFile *dxbc, ShaderReflection *refl, ShaderBindpointMapping *mapping) { + if(dxbc == NULL || !RenderDoc::Inst().IsReplayApp()) + return; + + if(dxbc->m_DebugInfo) + { + refl->DebugInfo.entryFunc = dxbc->m_DebugInfo->GetEntryFunction(); + refl->DebugInfo.compileFlags = dxbc->m_DebugInfo->GetShaderCompileFlags(); + + refl->DebugInfo.entryFile = -1; + + create_array_uninit(refl->DebugInfo.files, dxbc->m_DebugInfo->Files.size()); + for(size_t i = 0; i < dxbc->m_DebugInfo->Files.size(); i++) + { + refl->DebugInfo.files[i].first = dxbc->m_DebugInfo->Files[i].first; + refl->DebugInfo.files[i].second = dxbc->m_DebugInfo->Files[i].second; + + if(refl->DebugInfo.entryFile == -1 && + strstr(refl->DebugInfo.files[i].second.elems, refl->DebugInfo.entryFunc.elems)) + { + refl->DebugInfo.entryFile = (int32_t)i; + } + } + } + + refl->Disassembly = dxbc->GetDisassembly(); + + if(dxbc->m_ShaderBlob.empty()) + create_array_uninit(refl->RawBytes, 0); + else + create_array_init(refl->RawBytes, dxbc->m_ShaderBlob.size(), &dxbc->m_ShaderBlob[0]); + + refl->DispatchThreadsDimension[0] = dxbc->DispatchThreadsDimension[0]; + refl->DispatchThreadsDimension[1] = dxbc->DispatchThreadsDimension[1]; + refl->DispatchThreadsDimension[2] = dxbc->DispatchThreadsDimension[2]; + + refl->InputSig = dxbc->m_InputSig; + refl->OutputSig = dxbc->m_OutputSig; + + create_array_uninit(mapping->InputAttributes, D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT); + for(int s = 0; s < D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; s++) + mapping->InputAttributes[s] = s; + + int numCbuffers = 0; + + // skip 'empty' cbuffers added for the benefit of D3D11 + for(size_t i = 0; i < dxbc->m_CBuffers.size(); i++) + { + if(dxbc->m_CBuffers[i].descriptor.type == DXBC::CBuffer::Descriptor::TYPE_CBUFFER) + numCbuffers++; + } + + create_array_uninit(mapping->ConstantBlocks, numCbuffers); + create_array_uninit(refl->ConstantBlocks, numCbuffers); + for(size_t i = 0, c = 0; i < dxbc->m_CBuffers.size(); i++) + { + ConstantBlock &cb = refl->ConstantBlocks[c]; + + if(dxbc->m_CBuffers[i].descriptor.type != DXBC::CBuffer::Descriptor::TYPE_CBUFFER) + continue; + + cb.name = dxbc->m_CBuffers[i].name; + cb.bufferBacked = true; + cb.byteSize = dxbc->m_CBuffers[i].descriptor.byteSize; + cb.bindPoint = (uint32_t)c; + + BindpointMap map = {}; + map.arraySize = 1; + map.bind = (int32_t)i; + map.used = true; + + mapping->ConstantBlocks[c] = map; + + create_array_uninit(cb.variables, dxbc->m_CBuffers[i].variables.size()); + for(size_t v = 0; v < dxbc->m_CBuffers[i].variables.size(); v++) + { + uint32_t vecOffset = 0; + cb.variables[v] = MakeConstantBufferVariable(dxbc->m_CBuffers[i].variables[v], vecOffset); + } + } + + int numRWResources = 0; + int numROResources = 0; + + for(size_t i = 0; i < dxbc->m_Resources.size(); i++) + { + const auto &r = dxbc->m_Resources[i]; + + if(r.type != DXBC::ShaderInputBind::TYPE_CBUFFER) + { + bool IsReadWrite = (r.type == DXBC::ShaderInputBind::TYPE_UAV_RWTYPED || + r.type == DXBC::ShaderInputBind::TYPE_UAV_RWSTRUCTURED || + r.type == DXBC::ShaderInputBind::TYPE_UAV_RWBYTEADDRESS || + r.type == DXBC::ShaderInputBind::TYPE_UAV_APPEND_STRUCTURED || + r.type == DXBC::ShaderInputBind::TYPE_UAV_CONSUME_STRUCTURED || + r.type == DXBC::ShaderInputBind::TYPE_UAV_RWSTRUCTURED_WITH_COUNTER); + + if(IsReadWrite) + numRWResources++; + else + numROResources++; + } + } + + create_array_uninit(mapping->ReadWriteResources, numRWResources); + create_array_uninit(refl->ReadWriteResources, numRWResources); + + create_array_uninit(mapping->ReadOnlyResources, numROResources); + create_array_uninit(refl->ReadOnlyResources, numROResources); + + int32_t rwidx = 0, roidx = 0; + for(size_t i = 0; i < dxbc->m_Resources.size(); i++) + { + const auto &r = dxbc->m_Resources[i]; + + if(r.type == DXBC::ShaderInputBind::TYPE_CBUFFER) + continue; + + ShaderResource res; + res.name = r.name; + + res.IsSampler = (r.type == DXBC::ShaderInputBind::TYPE_SAMPLER); + res.IsTexture = (r.type == DXBC::ShaderInputBind::TYPE_TEXTURE && + r.dimension != DXBC::ShaderInputBind::DIM_UNKNOWN && + r.dimension != DXBC::ShaderInputBind::DIM_BUFFER && + r.dimension != DXBC::ShaderInputBind::DIM_BUFFEREX); + res.IsSRV = (r.type == DXBC::ShaderInputBind::TYPE_TBUFFER || + r.type == DXBC::ShaderInputBind::TYPE_TEXTURE || + r.type == DXBC::ShaderInputBind::TYPE_STRUCTURED || + r.type == DXBC::ShaderInputBind::TYPE_BYTEADDRESS); + bool IsReadWrite = (r.type == DXBC::ShaderInputBind::TYPE_UAV_RWTYPED || + r.type == DXBC::ShaderInputBind::TYPE_UAV_RWSTRUCTURED || + r.type == DXBC::ShaderInputBind::TYPE_UAV_RWBYTEADDRESS || + r.type == DXBC::ShaderInputBind::TYPE_UAV_APPEND_STRUCTURED || + r.type == DXBC::ShaderInputBind::TYPE_UAV_CONSUME_STRUCTURED || + r.type == DXBC::ShaderInputBind::TYPE_UAV_RWSTRUCTURED_WITH_COUNTER); + + switch(r.dimension) + { + default: + case DXBC::ShaderInputBind::DIM_UNKNOWN: res.resType = eResType_None; break; + case DXBC::ShaderInputBind::DIM_BUFFER: + case DXBC::ShaderInputBind::DIM_BUFFEREX: res.resType = eResType_Buffer; break; + case DXBC::ShaderInputBind::DIM_TEXTURE1D: res.resType = eResType_Texture1D; break; + case DXBC::ShaderInputBind::DIM_TEXTURE1DARRAY: res.resType = eResType_Texture1DArray; break; + case DXBC::ShaderInputBind::DIM_TEXTURE2D: res.resType = eResType_Texture2D; break; + case DXBC::ShaderInputBind::DIM_TEXTURE2DARRAY: res.resType = eResType_Texture2DArray; break; + case DXBC::ShaderInputBind::DIM_TEXTURE2DMS: res.resType = eResType_Texture2DMS; break; + case DXBC::ShaderInputBind::DIM_TEXTURE2DMSARRAY: + res.resType = eResType_Texture2DMSArray; + break; + case DXBC::ShaderInputBind::DIM_TEXTURE3D: res.resType = eResType_Texture3D; break; + case DXBC::ShaderInputBind::DIM_TEXTURECUBE: res.resType = eResType_TextureCube; break; + case DXBC::ShaderInputBind::DIM_TEXTURECUBEARRAY: + res.resType = eResType_TextureCubeArray; + break; + } + + if(r.retType != DXBC::ShaderInputBind::RETTYPE_UNKNOWN && + r.retType != DXBC::ShaderInputBind::RETTYPE_MIXED && + r.retType != DXBC::ShaderInputBind::RETTYPE_CONTINUED) + { + res.variableType.descriptor.rows = 1; + res.variableType.descriptor.cols = r.numSamples; + res.variableType.descriptor.elements = 1; + + string name; + + switch(r.retType) + { + case DXBC::ShaderInputBind::RETTYPE_UNORM: name = "unorm float"; break; + case DXBC::ShaderInputBind::RETTYPE_SNORM: name = "snorm float"; break; + case DXBC::ShaderInputBind::RETTYPE_SINT: name = "int"; break; + case DXBC::ShaderInputBind::RETTYPE_UINT: name = "uint"; break; + case DXBC::ShaderInputBind::RETTYPE_FLOAT: name = "float"; break; + case DXBC::ShaderInputBind::RETTYPE_DOUBLE: name = "double"; break; + default: name = "unknown"; break; + } + + name += ToStr::Get(r.numSamples); + + res.variableType.descriptor.name = name; + } + else + { + if(dxbc->m_ResourceBinds.find(r.name) != dxbc->m_ResourceBinds.end()) + { + uint32_t vecOffset = 0; + res.variableType = MakeShaderVariableType(dxbc->m_ResourceBinds[r.name], vecOffset); + } + else + { + res.variableType.descriptor.rows = 0; + res.variableType.descriptor.cols = 0; + res.variableType.descriptor.elements = 0; + res.variableType.descriptor.name = ""; + } + } + + res.bindPoint = IsReadWrite ? rwidx : roidx; + + BindpointMap map = {}; + map.arraySize = 1; + map.bind = r.bindPoint; + map.used = true; + + if(IsReadWrite) + { + refl->ReadWriteResources[rwidx++] = res; + mapping->ReadWriteResources[i] = map; + } + else + { + refl->ReadOnlyResources[roidx++] = res; + mapping->ReadOnlyResources[i] = map; + } + } + + uint32_t numInterfaces = 0; + for(size_t i = 0; i < dxbc->m_Interfaces.variables.size(); i++) + numInterfaces = RDCMAX(dxbc->m_Interfaces.variables[i].descriptor.offset + 1, numInterfaces); + + create_array(refl->Interfaces, numInterfaces); + for(size_t i = 0; i < dxbc->m_Interfaces.variables.size(); i++) + refl->Interfaces[dxbc->m_Interfaces.variables[i].descriptor.offset] = + dxbc->m_Interfaces.variables[i].name; } enum D3D12ResourceBarrierSubresource @@ -127,6 +426,21 @@ UINT GetNumSubresources(const D3D12_RESOURCE_DESC *desc) return 1; } +ShaderStageBits ConvertVisibility(D3D12_SHADER_VISIBILITY ShaderVisibility) +{ + switch(ShaderVisibility) + { + case D3D12_SHADER_VISIBILITY_ALL: return eStageBits_All; + case D3D12_SHADER_VISIBILITY_VERTEX: return eStageBits_Vertex; + case D3D12_SHADER_VISIBILITY_HULL: return eStageBits_Hull; + case D3D12_SHADER_VISIBILITY_DOMAIN: return eStageBits_Domain; + case D3D12_SHADER_VISIBILITY_GEOMETRY: return eStageBits_Geometry; + case D3D12_SHADER_VISIBILITY_PIXEL: return eStageBits_Pixel; + } + + return eStageBits_Vertex; +} + string ToStrHelper::Get(const D3D12ComponentMapping &el) { string ret; diff --git a/renderdoc/driver/d3d12/d3d12_common.h b/renderdoc/driver/d3d12/d3d12_common.h index c34b3e59d..1bb200d8d 100644 --- a/renderdoc/driver/d3d12/d3d12_common.h +++ b/renderdoc/driver/d3d12/d3d12_common.h @@ -57,6 +57,7 @@ void MakeShaderReflection(DXBC::DXBCFile *dxbc, ShaderReflection *refl, // buffer replay is happening #define VERBOSE_PARTIAL_REPLAY +ShaderStageBits ConvertVisibility(D3D12_SHADER_VISIBILITY ShaderVisibility); UINT GetNumSubresources(const D3D12_RESOURCE_DESC *desc); class WrappedID3D12Device; @@ -125,7 +126,7 @@ public: struct D3D12RootSignatureParameter : D3D12_ROOT_PARAMETER { - void MakeFrom(const D3D12_ROOT_PARAMETER ¶m) + void MakeFrom(const D3D12_ROOT_PARAMETER ¶m, UINT &numSpaces) { ParameterType = param.ParameterType; ShaderVisibility = param.ShaderVisibility; @@ -138,11 +139,23 @@ struct D3D12RootSignatureParameter : D3D12_ROOT_PARAMETER { ranges.resize(param.DescriptorTable.NumDescriptorRanges); for(size_t i = 0; i < ranges.size(); i++) + { ranges[i] = param.DescriptorTable.pDescriptorRanges[i]; + numSpaces = RDCMAX(numSpaces, ranges[i].RegisterSpace + 1); + } + DescriptorTable.NumDescriptorRanges = (UINT)ranges.size(); DescriptorTable.pDescriptorRanges = &ranges[0]; } + else if(ParameterType == D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS) + { + numSpaces = RDCMAX(numSpaces, Constants.RegisterSpace + 1); + } + else + { + numSpaces = RDCMAX(numSpaces, Descriptor.RegisterSpace + 1); + } } vector ranges; @@ -150,6 +163,8 @@ struct D3D12RootSignatureParameter : D3D12_ROOT_PARAMETER struct D3D12RootSignature { + D3D12RootSignature() : numSpaces(0) {} + uint32_t numSpaces; vector params; vector samplers; }; diff --git a/renderdoc/driver/d3d12/d3d12_debug.cpp b/renderdoc/driver/d3d12/d3d12_debug.cpp index 1a70b799a..420ccee81 100644 --- a/renderdoc/driver/d3d12/d3d12_debug.cpp +++ b/renderdoc/driver/d3d12/d3d12_debug.cpp @@ -830,11 +830,16 @@ D3D12RootSignature D3D12DebugManager::GetRootSig(const void *data, size_t dataSi ret.params.resize(desc->NumParameters); for(size_t i = 0; i < ret.params.size(); i++) - ret.params[i].MakeFrom(desc->pParameters[i]); + ret.params[i].MakeFrom(desc->pParameters[i], ret.numSpaces); if(desc->NumStaticSamplers > 0) + { ret.samplers.assign(desc->pStaticSamplers, desc->pStaticSamplers + desc->NumStaticSamplers); + for(size_t i = 0; i < ret.samplers.size(); i++) + ret.numSpaces = RDCMAX(ret.numSpaces, ret.samplers[i].RegisterSpace + 1); + } + SAFE_RELEASE(deser); return ret; diff --git a/renderdoc/driver/d3d12/d3d12_replay.cpp b/renderdoc/driver/d3d12/d3d12_replay.cpp index 712327710..b0209650c 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.cpp +++ b/renderdoc/driver/d3d12/d3d12_replay.cpp @@ -28,6 +28,15 @@ #include "d3d12_device.h" #include "d3d12_resources.h" +template +T &resize_and_add(std::vector &vec, size_t idx) +{ + if(idx >= vec.size()) + vec.resize(idx + 1); + + return vec[idx]; +} + D3D12Replay::D3D12Replay() { m_pDevice = NULL; @@ -244,20 +253,10 @@ vector D3D12Replay::GetUsage(ResourceId id) return m_pDevice->GetQueue()->GetUsage(id); } -void D3D12Replay::FillResourceView(D3D12PipelineState::ResourceView &view, - const PortableHandle &resHandle) +void D3D12Replay::FillResourceView(D3D12PipelineState::ResourceView &view, D3D12Descriptor *desc) { D3D12ResourceManager *rm = m_pDevice->GetResourceManager(); - if(resHandle.heap == ResourceId()) - return; - - WrappedID3D12DescriptorHeap *heap = rm->GetLiveAs(resHandle.heap); - D3D12_CPU_DESCRIPTOR_HANDLE handle = heap->GetCPUDescriptorHandleForHeapStart(); - - D3D12Descriptor *desc = (D3D12Descriptor *)handle.ptr; - desc += resHandle.index; - if(desc->GetType() == D3D12Descriptor::TypeSampler || desc->GetType() == D3D12Descriptor::TypeCBV) { RDCERR("Invalid descriptors - expected a resource view"); @@ -561,7 +560,7 @@ void D3D12Replay::MakePipelineState() // Shaders ///////////////////////////////////////////////// - ResourceId rootSig; + const D3D12RenderState::RootSignature *rootSig = NULL; if(pipe && pipe->IsCompute()) { @@ -570,8 +569,9 @@ void D3D12Replay::MakePipelineState() state.m_CS.Shader = sh->GetResourceID(); state.m_CS.stage = eShaderStage_Compute; + state.m_CS.BindpointMapping = sh->GetMapping(); - rootSig = rs.compute.rootsig; + rootSig = &rs.compute; } else if(pipe) { @@ -598,331 +598,281 @@ void D3D12Replay::MakePipelineState() } } - rootSig = rs.graphics.rootsig; + rootSig = &rs.graphics; } -#if 0 + if(rootSig) { - D3D11PipelineState::ShaderStage &dst = *dstArr[stage]; - const D3D11RenderState::shader &src = *srcArr[stage]; + state.m_RootSig.obj = rm->GetOriginalID(rootSig->rootsig); - dst.stage = (ShaderStageType)stage; + WrappedID3D12RootSignature *sig = + m_pDevice->GetResourceManager()->GetCurrentAs(rootSig->rootsig); - ResourceId id = GetIDForResource(src.Shader); - - WrappedShader *shad = (WrappedShader *)(WrappedID3D11Shader *)src.Shader; - - ShaderReflection *refl = NULL; - - if(shad != NULL) - refl = shad->GetDetails(); - - dst.Shader = rm->GetOriginalID(id); - dst.ShaderDetails = NULL; - - string str = GetDebugName(src.Shader); - dst.customName = true; - - if(str == "" && dst.Shader != ResourceId()) + struct Space { - dst.customName = false; - str = StringFormat::Fmt("%s Shader %llu", stageNames[stage], dst.Shader); - } + vector cbuffers; + vector samplers; + vector srvs; + vector uavs; + }; - dst.ShaderName = str; + Space *spaces = new Space[sig->sig.numSpaces]; + create_array_uninit(state.m_RootSig.Spaces, sig->sig.numSpaces); - // create identity bindpoint mapping - create_array_uninit(dst.BindpointMapping.InputAttributes, - D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT); - for(int s = 0; s < D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; s++) + for(size_t rootEl = 0; rootEl < RDCMIN(sig->sig.params.size(), rootSig->sigelems.size()); rootEl++) { - // TODO: this should do any semantic rematching as defined by the bytecode - // the input layout was built with (not necessarily the vertex shader's bytecode - - // in the case of a mismatch). It's commonly, but not always the identity mapping - dst.BindpointMapping.InputAttributes[s] = s; - } + const D3D12RenderState::SignatureElement &e = rootSig->sigelems[rootEl]; + const D3D12RootSignatureParameter &p = sig->sig.params[rootEl]; - create_array_uninit(dst.BindpointMapping.ConstantBlocks, - D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT); - for(int s = 0; s < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; s++) - { - dst.BindpointMapping.ConstantBlocks[s].bindset = 0; - dst.BindpointMapping.ConstantBlocks[s].bind = s; - dst.BindpointMapping.ConstantBlocks[s].used = false; - dst.BindpointMapping.ConstantBlocks[s].arraySize = 1; - } - - create_array_uninit(dst.BindpointMapping.ReadOnlyResources, - D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT); - for(int32_t s = 0; s < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; s++) - { - dst.BindpointMapping.ReadOnlyResources[s].bindset = 0; - dst.BindpointMapping.ReadOnlyResources[s].bind = s; - dst.BindpointMapping.ReadOnlyResources[s].used = false; - dst.BindpointMapping.ReadOnlyResources[s].arraySize = 1; - } - - create_array_uninit(dst.BindpointMapping.ReadWriteResources, D3D11_1_UAV_SLOT_COUNT); - for(int32_t s = 0; s < D3D11_1_UAV_SLOT_COUNT; s++) - { - dst.BindpointMapping.ReadWriteResources[s].bindset = 0; - dst.BindpointMapping.ReadWriteResources[s].bind = s; - dst.BindpointMapping.ReadWriteResources[s].used = false; - dst.BindpointMapping.ReadWriteResources[s].arraySize = 1; - } - - // mark resources as used if they are referenced by the shader - if(refl) - { - for(int32_t i = 0; i < refl->ConstantBlocks.count; i++) - if(refl->ConstantBlocks[i].bufferBacked) - dst.BindpointMapping.ConstantBlocks[refl->ConstantBlocks[i].bindPoint].used = true; - - for(int32_t i = 0; i < refl->ReadOnlyResources.count; i++) - if(!refl->ReadOnlyResources[i].IsSampler) - dst.BindpointMapping.ReadOnlyResources[refl->ReadOnlyResources[i].bindPoint].used = true; - - for(int32_t i = 0; i < refl->ReadWriteResources.count; i++) - dst.BindpointMapping.ReadWriteResources[refl->ReadWriteResources[i].bindPoint].used = true; - } - - create_array_uninit(dst.ConstantBuffers, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT); - for(size_t s = 0; s < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; s++) - { - dst.ConstantBuffers[s].Buffer = rm->GetOriginalID(GetIDForResource(src.ConstantBuffers[s])); - dst.ConstantBuffers[s].VecOffset = src.CBOffsets[s]; - dst.ConstantBuffers[s].VecCount = src.CBCounts[s]; - } - - create_array_uninit(dst.Samplers, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT); - for(size_t s = 0; s < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; s++) - { - D3D11PipelineState::ShaderStage::Sampler &samp = dst.Samplers[s]; - - samp.Samp = rm->GetOriginalID(GetIDForResource(src.Samplers[s])); - - if(samp.Samp != ResourceId()) + if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS && e.type == eRootConst) { - samp.SamplerName = GetDebugName(src.Samplers[s]); - samp.customSamplerName = true; + D3D12PipelineState::CBuffer &cb = + resize_and_add(spaces[p.Constants.RegisterSpace].cbuffers, p.Constants.ShaderRegister); + cb.VisibilityMask = ConvertVisibility(p.ShaderVisibility); + cb.Immediate = true; + cb.RootElement = (uint32_t)rootEl; + cb.ByteSize = uint32_t(sizeof(uint32_t) * p.Constants.Num32BitValues); - if(samp.SamplerName.count == 0) + create_array_init(cb.RootValues, e.constants.size(), &e.constants[0]); + } + else if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV && e.type == eRootCBV) + { + D3D12PipelineState::CBuffer &cb = + resize_and_add(spaces[p.Constants.RegisterSpace].cbuffers, p.Constants.ShaderRegister); + cb.VisibilityMask = ConvertVisibility(p.ShaderVisibility); + cb.Immediate = true; + cb.RootElement = (uint32_t)rootEl; + + ID3D12Resource *res = rm->GetCurrentAs(e.id); + + cb.Buffer = rm->GetOriginalID(e.id); + cb.Offset = e.offset; + cb.ByteSize = uint32_t(res->GetDesc().Width - cb.Offset); + } + else if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV && e.type == eRootSRV) + { + D3D12PipelineState::ResourceView &view = + resize_and_add(spaces[p.Constants.RegisterSpace].srvs, p.Constants.ShaderRegister); + view.VisibilityMask = ConvertVisibility(p.ShaderVisibility); + view.Immediate = true; + view.RootElement = (uint32_t)rootEl; + + ID3D12Resource *res = rm->GetCurrentAs(e.id); + + // parameters from resource/view + view.Resource = rm->GetOriginalID(e.id); + view.Type = ToStr::Get(D3D12_SRV_DIMENSION_BUFFER); + view.Format = MakeResourceFormat(DXGI_FORMAT_R32_UINT); + + view.ElementSize = sizeof(uint32_t); + view.FirstElement = e.offset / sizeof(uint32_t); + view.NumElements = uint32_t((res->GetDesc().Width - e.offset) / sizeof(uint32_t)); + } + else if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV && e.type == eRootUAV) + { + D3D12PipelineState::ResourceView &view = + resize_and_add(spaces[p.Constants.RegisterSpace].uavs, p.Constants.ShaderRegister); + view.VisibilityMask = ConvertVisibility(p.ShaderVisibility); + view.Immediate = true; + view.RootElement = (uint32_t)rootEl; + + ID3D12Resource *res = rm->GetCurrentAs(e.id); + + // parameters from resource/view + view.Resource = rm->GetOriginalID(e.id); + view.Type = ToStr::Get(D3D12_UAV_DIMENSION_BUFFER); + view.Format = MakeResourceFormat(DXGI_FORMAT_R32_UINT); + + view.ElementSize = sizeof(uint32_t); + view.FirstElement = e.offset / sizeof(uint32_t); + view.NumElements = uint32_t((res->GetDesc().Width - e.offset) / sizeof(uint32_t)); + } + else if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE && e.type == eRootTable) + { + WrappedID3D12DescriptorHeap *heap = rm->GetCurrentAs(e.id); + + UINT prevTableOffset = 0; + + for(size_t r = 0; r < p.ranges.size(); r++) { - samp.customSamplerName = false; - samp.SamplerName = StringFormat::Fmt("Sampler %llu", samp.Samp); + const D3D12_DESCRIPTOR_RANGE &range = p.ranges[r]; + + UINT shaderReg = range.BaseShaderRegister; + UINT regSpace = range.RegisterSpace; + + D3D12Descriptor *desc = (D3D12Descriptor *)heap->GetCPUDescriptorHandleForHeapStart().ptr; + + UINT offset = range.OffsetInDescriptorsFromTableStart; + + if(range.OffsetInDescriptorsFromTableStart == D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) + offset = prevTableOffset; + + desc += offset; + + prevTableOffset = offset + range.NumDescriptors; + + if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER) + { + UINT maxReg = shaderReg + range.NumDescriptors - 1; + if(maxReg >= spaces[regSpace].samplers.size()) + spaces[regSpace].samplers.resize(maxReg + 1); + + for(UINT i = 0; i < range.NumDescriptors; i++, desc++, shaderReg++) + { + D3D12PipelineState::Sampler &samp = spaces[regSpace].samplers[shaderReg]; + samp.VisibilityMask = ConvertVisibility(p.ShaderVisibility); + samp.Immediate = false; + samp.RootElement = (uint32_t)rootEl; + + D3D12_SAMPLER_DESC &sampDesc = desc->samp.desc; + + samp.AddressU = ToStr::Get(sampDesc.AddressU); + samp.AddressV = ToStr::Get(sampDesc.AddressV); + samp.AddressW = ToStr::Get(sampDesc.AddressW); + + memcpy(samp.BorderColor, sampDesc.BorderColor, sizeof(FLOAT) * 4); + + samp.Comparison = ToStr::Get(sampDesc.ComparisonFunc); + samp.Filter = ToStr::Get(sampDesc.Filter); + samp.MaxAniso = 0; + if(sampDesc.Filter == D3D12_FILTER_ANISOTROPIC || + sampDesc.Filter == D3D12_FILTER_COMPARISON_ANISOTROPIC || + sampDesc.Filter == D3D12_FILTER_MINIMUM_ANISOTROPIC || + sampDesc.Filter == D3D12_FILTER_MAXIMUM_ANISOTROPIC) + samp.MaxAniso = sampDesc.MaxAnisotropy; + samp.MaxLOD = sampDesc.MaxLOD; + samp.MinLOD = sampDesc.MinLOD; + samp.MipLODBias = sampDesc.MipLODBias; + samp.UseComparison = (sampDesc.Filter >= D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT && + sampDesc.Filter <= D3D12_FILTER_COMPARISON_ANISOTROPIC); + samp.UseBorder = (sampDesc.AddressU == D3D12_TEXTURE_ADDRESS_MODE_BORDER || + sampDesc.AddressV == D3D12_TEXTURE_ADDRESS_MODE_BORDER || + sampDesc.AddressW == D3D12_TEXTURE_ADDRESS_MODE_BORDER); + } + } + else if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_CBV) + { + UINT maxReg = shaderReg + range.NumDescriptors - 1; + if(maxReg >= spaces[regSpace].cbuffers.size()) + spaces[regSpace].cbuffers.resize(maxReg + 1); + + for(UINT i = 0; i < range.NumDescriptors; i++, desc++, shaderReg++) + { + D3D12PipelineState::CBuffer &cb = spaces[regSpace].cbuffers[shaderReg]; + cb.VisibilityMask = ConvertVisibility(p.ShaderVisibility); + cb.Immediate = false; + cb.RootElement = (uint32_t)rootEl; + + WrappedID3D12Resource::GetResIDFromAddr(desc->nonsamp.cbv.BufferLocation, cb.Buffer, + cb.Offset); + cb.Buffer = rm->GetOriginalID(cb.Buffer); + cb.ByteSize = desc->nonsamp.cbv.SizeInBytes; + } + } + else if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV) + { + UINT maxReg = shaderReg + range.NumDescriptors - 1; + if(maxReg >= spaces[regSpace].srvs.size()) + spaces[regSpace].srvs.resize(maxReg + 1); + + for(UINT i = 0; i < range.NumDescriptors; i++, desc++, shaderReg++) + { + D3D12PipelineState::ResourceView &view = spaces[regSpace].srvs[shaderReg]; + view.VisibilityMask = ConvertVisibility(p.ShaderVisibility); + view.Immediate = false; + view.RootElement = (uint32_t)rootEl; + + FillResourceView(view, desc); + } + } + else if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV) + { + UINT maxReg = shaderReg + range.NumDescriptors - 1; + if(maxReg >= spaces[regSpace].uavs.size()) + spaces[regSpace].uavs.resize(maxReg + 1); + + for(UINT i = 0; i < range.NumDescriptors; i++, desc++, shaderReg++) + { + D3D12PipelineState::ResourceView &view = spaces[regSpace].uavs[shaderReg]; + view.VisibilityMask = ConvertVisibility(p.ShaderVisibility); + view.Immediate = false; + view.RootElement = (uint32_t)rootEl; + + FillResourceView(view, desc); + } + } } - - D3D11_SAMPLER_DESC desc; - src.Samplers[s]->GetDesc(&desc); - - samp.AddressU = ToStr::Get(desc.AddressU); - samp.AddressV = ToStr::Get(desc.AddressV); - samp.AddressW = ToStr::Get(desc.AddressW); - - memcpy(samp.BorderColor, desc.BorderColor, sizeof(FLOAT) * 4); - - samp.Comparison = ToStr::Get(desc.ComparisonFunc); - samp.Filter = ToStr::Get(desc.Filter); - samp.MaxAniso = 0; - if(desc.Filter == D3D11_FILTER_ANISOTROPIC || - desc.Filter == D3D11_FILTER_COMPARISON_ANISOTROPIC) - samp.MaxAniso = desc.MaxAnisotropy; - samp.MaxLOD = desc.MaxLOD; - samp.MinLOD = desc.MinLOD; - samp.MipLODBias = desc.MipLODBias; - samp.UseComparison = (desc.Filter >= D3D11_FILTER_COMPARISON_MIN_MAG_MIP_POINT); - samp.UseBorder = (desc.AddressU == D3D11_TEXTURE_ADDRESS_BORDER || - desc.AddressV == D3D11_TEXTURE_ADDRESS_BORDER || - desc.AddressW == D3D11_TEXTURE_ADDRESS_BORDER); } } - create_array_uninit(dst.SRVs, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT); - for(size_t s = 0; s < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; s++) + for(size_t i = 0; i < sig->sig.samplers.size(); i++) { - D3D11PipelineState::ShaderStage::ResourceView &view = dst.SRVs[s]; + D3D12_STATIC_SAMPLER_DESC &sampDesc = sig->sig.samplers[i]; - view.View = rm->GetOriginalID(GetIDForResource(src.SRVs[s])); + D3D12PipelineState::Sampler &samp = + resize_and_add(spaces[sampDesc.RegisterSpace].samplers, sampDesc.ShaderRegister); + samp.VisibilityMask = ConvertVisibility(sampDesc.ShaderVisibility); + samp.Immediate = true; + samp.RootElement = (uint32_t)i; - if(view.View != ResourceId()) + samp.AddressU = ToStr::Get(sampDesc.AddressU); + samp.AddressV = ToStr::Get(sampDesc.AddressV); + samp.AddressW = ToStr::Get(sampDesc.AddressW); + + if(sampDesc.BorderColor == D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK) { - D3D11_SHADER_RESOURCE_VIEW_DESC desc; - src.SRVs[s]->GetDesc(&desc); - - view.Format = MakeResourceFormat(desc.Format); - - ID3D11Resource *res = NULL; - src.SRVs[s]->GetResource(&res); - - view.Structured = false; - view.BufferStructCount = 0; - - view.ElementSize = - desc.Format == DXGI_FORMAT_UNKNOWN ? 1 : GetByteSize(1, 1, 1, desc.Format, 0); - - view.Resource = rm->GetOriginalID(GetIDForResource(res)); - - view.Type = ToStr::Get(desc.ViewDimension); - - if(desc.ViewDimension == D3D11_SRV_DIMENSION_BUFFER) - { - view.FirstElement = desc.Buffer.FirstElement; - view.NumElements = desc.Buffer.NumElements; - view.ElementOffset = desc.Buffer.ElementOffset; - view.ElementWidth = desc.Buffer.ElementWidth; - - D3D11_BUFFER_DESC bufdesc; - ((ID3D11Buffer *)res)->GetDesc(&bufdesc); - - view.Structured = bufdesc.StructureByteStride > 0 && desc.Format == DXGI_FORMAT_UNKNOWN; - - if(view.Structured) - view.ElementSize = bufdesc.StructureByteStride; - } - else if(desc.ViewDimension == D3D11_SRV_DIMENSION_BUFFEREX) - { - view.FirstElement = desc.BufferEx.FirstElement; - view.NumElements = desc.BufferEx.NumElements; - view.Flags = desc.BufferEx.Flags; - } - else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE1D) - { - view.HighestMip = desc.Texture1D.MostDetailedMip; - view.NumMipLevels = desc.Texture1D.MipLevels; - } - else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE1DARRAY) - { - view.ArraySize = desc.Texture1DArray.ArraySize; - view.FirstArraySlice = desc.Texture1DArray.FirstArraySlice; - view.HighestMip = desc.Texture1DArray.MostDetailedMip; - view.NumMipLevels = desc.Texture1DArray.MipLevels; - } - else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2D) - { - view.HighestMip = desc.Texture2D.MostDetailedMip; - view.NumMipLevels = desc.Texture2D.MipLevels; - } - else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2DARRAY) - { - view.ArraySize = desc.Texture2DArray.ArraySize; - view.FirstArraySlice = desc.Texture2DArray.FirstArraySlice; - view.HighestMip = desc.Texture2DArray.MostDetailedMip; - view.NumMipLevels = desc.Texture2DArray.MipLevels; - } - else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2DMS) - { - } - else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY) - { - view.ArraySize = desc.Texture2DArray.ArraySize; - view.FirstArraySlice = desc.Texture2DArray.FirstArraySlice; - } - else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE3D) - { - view.HighestMip = desc.Texture3D.MostDetailedMip; - view.NumMipLevels = desc.Texture3D.MipLevels; - } - else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURECUBE) - { - view.ArraySize = 6; - view.HighestMip = desc.TextureCube.MostDetailedMip; - view.NumMipLevels = desc.TextureCube.MipLevels; - } - else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURECUBEARRAY) - { - view.ArraySize = desc.TextureCubeArray.NumCubes * 6; - view.FirstArraySlice = desc.TextureCubeArray.First2DArrayFace; - view.HighestMip = desc.TextureCubeArray.MostDetailedMip; - view.NumMipLevels = desc.TextureCubeArray.MipLevels; - } - - SAFE_RELEASE(res); + samp.BorderColor[0] = 0.0f; + samp.BorderColor[1] = 0.0f; + samp.BorderColor[2] = 0.0f; + samp.BorderColor[3] = 0.0f; } + else if(sampDesc.BorderColor == D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK) + { + samp.BorderColor[0] = 0.0f; + samp.BorderColor[1] = 0.0f; + samp.BorderColor[2] = 0.0f; + samp.BorderColor[3] = 1.0f; + } + else if(sampDesc.BorderColor == D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE) + { + samp.BorderColor[0] = 1.0f; + samp.BorderColor[1] = 1.0f; + samp.BorderColor[2] = 1.0f; + samp.BorderColor[3] = 1.0f; + } + else + { + RDCERR("Unexpected static border colour: %u", sampDesc.BorderColor); + } + + samp.Comparison = ToStr::Get(sampDesc.ComparisonFunc); + samp.Filter = ToStr::Get(sampDesc.Filter); + samp.MaxAniso = 0; + if(sampDesc.Filter == D3D12_FILTER_ANISOTROPIC || + sampDesc.Filter == D3D12_FILTER_COMPARISON_ANISOTROPIC || + sampDesc.Filter == D3D12_FILTER_MINIMUM_ANISOTROPIC || + sampDesc.Filter == D3D12_FILTER_MAXIMUM_ANISOTROPIC) + samp.MaxAniso = sampDesc.MaxAnisotropy; + samp.MaxLOD = sampDesc.MaxLOD; + samp.MinLOD = sampDesc.MinLOD; + samp.MipLODBias = sampDesc.MipLODBias; + samp.UseComparison = (sampDesc.Filter >= D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT && + sampDesc.Filter <= D3D12_FILTER_COMPARISON_ANISOTROPIC); + samp.UseBorder = (sampDesc.AddressU == D3D12_TEXTURE_ADDRESS_MODE_BORDER || + sampDesc.AddressV == D3D12_TEXTURE_ADDRESS_MODE_BORDER || + sampDesc.AddressW == D3D12_TEXTURE_ADDRESS_MODE_BORDER); } - create_array(dst.UAVs, D3D11_1_UAV_SLOT_COUNT); - for(size_t s = 0; dst.stage == eShaderStage_Compute && s < D3D11_1_UAV_SLOT_COUNT; s++) + for(uint32_t i = 0; i < sig->sig.numSpaces; i++) { - D3D11PipelineState::ShaderStage::ResourceView &view = dst.UAVs[s]; - - view.View = rm->GetOriginalID(GetIDForResource(rs.CSUAVs[s])); - - if(view.View != ResourceId()) - { - D3D11_UNORDERED_ACCESS_VIEW_DESC desc; - rs.CSUAVs[s]->GetDesc(&desc); - - ID3D11Resource *res = NULL; - rs.CSUAVs[s]->GetResource(&res); - - view.Structured = false; - view.BufferStructCount = 0; - - view.ElementSize = - desc.Format == DXGI_FORMAT_UNKNOWN ? 1 : GetByteSize(1, 1, 1, desc.Format, 0); - - if(desc.ViewDimension == D3D11_UAV_DIMENSION_BUFFER && - (desc.Buffer.Flags & (D3D11_BUFFER_UAV_FLAG_APPEND | D3D11_BUFFER_UAV_FLAG_COUNTER))) - { - view.BufferStructCount = m_pDevice->GetDebugManager()->GetStructCount(rs.CSUAVs[s]); - } - - view.Resource = rm->GetOriginalID(GetIDForResource(res)); - - view.Format = MakeResourceFormat(desc.Format); - view.Type = ToStr::Get(desc.ViewDimension); - - if(desc.ViewDimension == D3D11_UAV_DIMENSION_BUFFER) - { - view.FirstElement = desc.Buffer.FirstElement; - view.NumElements = desc.Buffer.NumElements; - view.Flags = desc.Buffer.Flags; - - D3D11_BUFFER_DESC bufdesc; - ((ID3D11Buffer *)res)->GetDesc(&bufdesc); - - view.Structured = bufdesc.StructureByteStride > 0 && desc.Format == DXGI_FORMAT_UNKNOWN; - - if(view.Structured) - view.ElementSize = bufdesc.StructureByteStride; - } - else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE1D) - { - view.HighestMip = desc.Texture1D.MipSlice; - view.NumMipLevels = 1; - } - else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE1DARRAY) - { - view.ArraySize = desc.Texture1DArray.ArraySize; - view.FirstArraySlice = desc.Texture1DArray.FirstArraySlice; - view.HighestMip = desc.Texture1DArray.MipSlice; - view.NumMipLevels = 1; - } - else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE2D) - { - view.HighestMip = desc.Texture2D.MipSlice; - view.NumMipLevels = 1; - } - else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE2DARRAY) - { - view.ArraySize = desc.Texture2DArray.ArraySize; - view.FirstArraySlice = desc.Texture2DArray.FirstArraySlice; - view.HighestMip = desc.Texture2DArray.MipSlice; - view.NumMipLevels = 1; - } - else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE3D) - { - view.ArraySize = desc.Texture3D.WSize; - view.FirstArraySlice = desc.Texture3D.FirstWSlice; - view.HighestMip = desc.Texture3D.MipSlice; - view.NumMipLevels = 1; - } - - SAFE_RELEASE(res); - } + state.m_RootSig.Spaces[i].ConstantBuffers = spaces[i].cbuffers; + state.m_RootSig.Spaces[i].Samplers = spaces[i].samplers; + state.m_RootSig.Spaces[i].SRVs = spaces[i].srvs; + state.m_RootSig.Spaces[i].UAVs = spaces[i].uavs; } + + SAFE_DELETE_ARRAY(spaces); } -#endif if(pipe && pipe->IsGraphics()) { @@ -994,18 +944,32 @@ void D3D12Replay::MakePipelineState() { D3D12PipelineState::ResourceView &view = state.m_OM.RenderTargets[i]; - PortableHandle h = rs.rtSingle ? rs.rts[i] : rs.rts[i]; + PortableHandle h = rs.rtSingle ? rs.rts[0] : rs.rts[i]; - if(rs.rtSingle) - h.index += (uint32_t)i; + if(h.heap != ResourceId()) + { + WrappedID3D12DescriptorHeap *heap = rm->GetLiveAs(h.heap); + D3D12Descriptor *desc = + (D3D12Descriptor *)heap->GetCPUDescriptorHandleForHeapStart().ptr + h.index; - FillResourceView(view, h); + if(rs.rtSingle) + desc += i; + + FillResourceView(view, desc); + } } { D3D12PipelineState::ResourceView &view = state.m_OM.DepthTarget; - FillResourceView(view, rs.dsv); + if(rs.dsv.heap != ResourceId()) + { + WrappedID3D12DescriptorHeap *heap = rm->GetLiveAs(rs.dsv.heap); + D3D12Descriptor *desc = + (D3D12Descriptor *)heap->GetCPUDescriptorHandleForHeapStart().ptr + rs.dsv.index; + + FillResourceView(view, desc); + } } memcpy(state.m_OM.m_BlendState.BlendFactor, rs.blendFactor, sizeof(FLOAT) * 4); diff --git a/renderdoc/driver/d3d12/d3d12_replay.h b/renderdoc/driver/d3d12/d3d12_replay.h index bfc059aec..398e21677 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.h +++ b/renderdoc/driver/d3d12/d3d12_replay.h @@ -165,7 +165,7 @@ public: private: void MakePipelineState(); - void FillResourceView(D3D12PipelineState::ResourceView &view, const PortableHandle &resHandle); + void FillResourceView(D3D12PipelineState::ResourceView &view, D3D12Descriptor *desc); bool m_Proxy; diff --git a/renderdoc/driver/d3d12/d3d12_state.h b/renderdoc/driver/d3d12/d3d12_state.h index 40dd5aec5..6cbf588f0 100644 --- a/renderdoc/driver/d3d12/d3d12_state.h +++ b/renderdoc/driver/d3d12/d3d12_state.h @@ -168,7 +168,7 @@ struct D3D12RenderState }; vector streamouts; - struct Pipeline + struct RootSignature { ResourceId rootsig; diff --git a/renderdocui/Interop/D3D12PipelineState.cs b/renderdocui/Interop/D3D12PipelineState.cs index 6550b38bc..f052c4782 100644 --- a/renderdocui/Interop/D3D12PipelineState.cs +++ b/renderdocui/Interop/D3D12PipelineState.cs @@ -109,6 +109,10 @@ namespace renderdoc [StructLayout(LayoutKind.Sequential)] public class ResourceView { + public ShaderStageBits VisibilityMask; + public bool Immediate; + public UInt32 RootElement; + public ResourceId Resource; [CustomMarshalAs(CustomUnmanagedType.UTF8TemplatedString)] public string Type; @@ -141,6 +145,10 @@ namespace renderdoc [StructLayout(LayoutKind.Sequential)] public class Sampler { + public ShaderStageBits VisibilityMask; + public bool Immediate; + public UInt32 RootElement; + [CustomMarshalAs(CustomUnmanagedType.UTF8TemplatedString)] public string AddressU, AddressV, AddressW; [CustomMarshalAs(CustomUnmanagedType.FixedArray, FixedLength = 4)] @@ -160,12 +168,16 @@ namespace renderdoc [StructLayout(LayoutKind.Sequential)] public class CBuffer { + public ShaderStageBits VisibilityMask; + public bool Immediate; + public UInt32 RootElement; + public ResourceId Buffer; public UInt64 Offset; public UInt32 ByteSize; [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] - public UInt32[] Immediate; + public UInt32[] RootValues; }; [StructLayout(LayoutKind.Sequential)] @@ -174,46 +186,20 @@ namespace renderdoc public ResourceId Obj; [StructLayout(LayoutKind.Sequential)] - public class CBufferDescriptor + public class RegisterSpace { - public ShaderStageBits VisibilityMask; - public bool Immediate; - public UInt32 RootElement; - - [CustomMarshalAs(CustomUnmanagedType.CustomClass)] - CBuffer obj; - }; - - [StructLayout(LayoutKind.Sequential)] - public class ViewDescriptor - { - public ShaderStageBits VisibilityMask; - public bool Immediate; - public UInt32 RootElement; - - [CustomMarshalAs(CustomUnmanagedType.CustomClass)] - ResourceView obj; - }; - - [StructLayout(LayoutKind.Sequential)] - public class SamplerDescriptor - { - public ShaderStageBits VisibilityMask; - public bool Immediate; - public UInt32 RootElement; - - [CustomMarshalAs(CustomUnmanagedType.CustomClass)] - Sampler obj; + [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] + public CBuffer[] ConstantBuffers; + [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] + public Sampler[] Samplers; + [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] + public ResourceView[] SRVs; + [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] + public ResourceView[] UAVs; }; [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] - public CBufferDescriptor[] ConstantBuffers; - [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] - public SamplerDescriptor[] Samplers; - [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] - public ViewDescriptor[] SRVs; - [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] - public ViewDescriptor[] UAVs; + public RegisterSpace[] Spaces; }; [CustomMarshalAs(CustomUnmanagedType.CustomClass)] public RootSignature m_RootSig;