/****************************************************************************** * The MIT License (MIT) * * Copyright (c) 2016 Baldur Karlsson * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. ******************************************************************************/ #include "d3d12_common.h" #include "driver/dxgi/dxgi_common.h" #include "driver/dxgi/dxgi_wrapped.h" #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; i < dxbc->m_CBuffers.size(); i++) { ConstantBlock &cb = refl->ConstantBlocks[i]; 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)i; BindpointMap map; map.arraySize = 1; map.bindset = dxbc->m_CBuffers[i].space; map.bind = dxbc->m_CBuffers[i].reg; map.used = true; mapping->ConstantBlocks[i] = 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 = r.bindCount == 0 ? ~0U : r.bindCount; map.bindset = r.space; map.bind = r.reg; map.used = true; if(IsReadWrite) { mapping->ReadWriteResources[rwidx] = map; refl->ReadWriteResources[rwidx++] = res; } else { mapping->ReadOnlyResources[roidx] = map; refl->ReadOnlyResources[roidx++] = res; } } 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 { D3D12AllSubresources = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES }; string ToStrHelper::Get(const D3D12ResourceBarrierSubresource &el) { if(el == D3D12AllSubresources) return "All Subresources"; return ToStr::Get(uint32_t(el)); } enum D3D12ComponentMapping { }; UINT GetResourceNumMipLevels(const D3D12_RESOURCE_DESC *desc) { switch(desc->Dimension) { default: case D3D12_RESOURCE_DIMENSION_UNKNOWN: RDCERR("Unexpected resource dimension! %d", desc->Dimension); break; case D3D12_RESOURCE_DIMENSION_BUFFER: return 1; case D3D12_RESOURCE_DIMENSION_TEXTURE1D: { if(desc->MipLevels) return desc->MipLevels; UINT w = RDCMAX(1U, UINT(desc->Width)); UINT count = 1; while(w > 1) { ++count; w = RDCMAX(1U, w >> 1U); } return count; } case D3D12_RESOURCE_DIMENSION_TEXTURE2D: { if(desc->MipLevels) return desc->MipLevels; UINT w = RDCMAX(1U, UINT(desc->Width)); UINT h = RDCMAX(1U, desc->Height); UINT count = 1; while(w > 1 || h > 1) { ++count; w = RDCMAX(1U, w >> 1U); h = RDCMAX(1U, h >> 1U); } return count; } case D3D12_RESOURCE_DIMENSION_TEXTURE3D: { if(desc->MipLevels) return desc->MipLevels; UINT w = RDCMAX(1U, UINT(desc->Width)); UINT h = RDCMAX(1U, desc->Height); UINT d = RDCMAX(1U, UINT(desc->DepthOrArraySize)); UINT count = 1; while(w > 1 || h > 1 || d > 1) { ++count; w = RDCMAX(1U, w >> 1U); h = RDCMAX(1U, h >> 1U); d = RDCMAX(1U, d >> 1U); } return count; } } return 1; } UINT GetNumSubresources(ID3D12Device *dev, const D3D12_RESOURCE_DESC *desc) { D3D12_FEATURE_DATA_FORMAT_INFO formatInfo = {}; formatInfo.Format = desc->Format; dev->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &formatInfo, sizeof(formatInfo)); UINT planes = RDCMAX((UINT8)1, formatInfo.PlaneCount); switch(desc->Dimension) { default: case D3D12_RESOURCE_DIMENSION_UNKNOWN: RDCERR("Unexpected resource dimension! %d", desc->Dimension); break; case D3D12_RESOURCE_DIMENSION_BUFFER: return planes; case D3D12_RESOURCE_DIMENSION_TEXTURE1D: case D3D12_RESOURCE_DIMENSION_TEXTURE2D: return RDCMAX((UINT16)1, desc->DepthOrArraySize) * GetResourceNumMipLevels(desc) * planes; case D3D12_RESOURCE_DIMENSION_TEXTURE3D: return GetResourceNumMipLevels(desc) * planes; } 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; // value should always be <= 5, see D3D12_SHADER_COMPONENT_MAPPING const char mapping[] = {'R', 'G', 'B', 'A', '0', '1', '?', '?'}; uint32_t swizzle = (uint32_t)el; for(int i = 0; i < 4; i++) ret += mapping[D3D12_DECODE_SHADER_4_COMPONENT_MAPPING(i, swizzle)]; return ret; } #define SerialiseObject(type, name, obj) \ { \ D3D12ResourceManager *rm = (D3D12ResourceManager *)GetUserData(); \ ResourceId id; \ if(m_Mode >= WRITING) \ id = GetResID(obj); \ Serialise(name, id); \ if(m_Mode < WRITING) \ obj = (id == ResourceId() || !rm->HasLiveResource(id)) ? NULL \ : Unwrap(rm->GetLiveAs(id)); \ } #define SerialiseWrappedObject(type, name, obj) \ { \ D3D12ResourceManager *rm = (D3D12ResourceManager *)GetUserData(); \ ResourceId id; \ if(m_Mode >= WRITING) \ id = GetResID(obj); \ Serialise(name, id); \ if(m_Mode < WRITING) \ obj = (id == ResourceId() || !rm->HasLiveResource(id)) ? NULL : rm->GetLiveAs(id); \ } template <> void Serialiser::Serialise(const char *name, D3D12Descriptor &el) { ScopedContext scope(this, name, "D3D12Descriptor", 0, true); D3D12Descriptor::DescriptorType type = el.GetType(); Serialise("type", type); // we serialise the heap by hand because we want to keep it wrapped { D3D12ResourceManager *rm = (D3D12ResourceManager *)GetUserData(); PortableHandle handle; if(m_Mode >= WRITING) handle = PortableHandle(el.samp.heap ? el.samp.heap->GetResourceID() : ResourceId(), el.samp.idx); Serialise("handle", handle); if(m_Mode < WRITING) { el.samp.heap = (handle.heap == ResourceId() || !rm->HasLiveResource(handle.heap)) ? NULL : rm->GetLiveAs(handle.heap); el.samp.idx = handle.index; } } // for sampler types, this will be overwritten when serialising the sampler descriptor el.nonsamp.type = type; switch(type) { case D3D12Descriptor::TypeSampler: { Serialise("Descriptor", el.samp.desc); RDCASSERTEQUAL(el.GetType(), D3D12Descriptor::TypeSampler); break; } case D3D12Descriptor::TypeCBV: { Serialise("Descriptor", el.nonsamp.cbv); break; } case D3D12Descriptor::TypeSRV: { SerialiseWrappedObject(ID3D12Resource, "Resource", el.nonsamp.resource); Serialise("Descriptor", el.nonsamp.srv); break; } case D3D12Descriptor::TypeRTV: { SerialiseWrappedObject(ID3D12Resource, "Resource", el.nonsamp.resource); Serialise("Descriptor", el.nonsamp.rtv); break; } case D3D12Descriptor::TypeDSV: { SerialiseWrappedObject(ID3D12Resource, "Resource", el.nonsamp.resource); Serialise("Descriptor", el.nonsamp.dsv); break; } case D3D12Descriptor::TypeUAV: { SerialiseWrappedObject(ID3D12Resource, "Resource", el.nonsamp.resource); SerialiseWrappedObject(ID3D12Resource, "CounterResource", el.nonsamp.uav.counterResource); // special case because of extra resource and squeezed descriptor D3D12_UNORDERED_ACCESS_VIEW_DESC desc = el.nonsamp.uav.desc.AsDesc(); Serialise("Descriptor", desc); el.nonsamp.uav.desc.Init(desc); break; } case D3D12Descriptor::TypeUndefined: { el.nonsamp.type = type; break; } } } template <> void Serialiser::Serialise(const char *name, D3D12_RESOURCE_DESC &el) { ScopedContext scope(this, name, "D3D12_RESOURCE_DESC", 0, true); Serialise("Dimension", el.Dimension); Serialise("Alignment", el.Alignment); Serialise("Width", el.Width); Serialise("Height", el.Height); Serialise("DepthOrArraySize", el.DepthOrArraySize); Serialise("MipLevels", el.MipLevels); Serialise("Format", el.Format); Serialise("SampleDesc", el.SampleDesc); Serialise("Layout", el.Layout); Serialise("Flags", el.Flags); } template <> void Serialiser::Serialise(const char *name, D3D12_COMMAND_QUEUE_DESC &el) { ScopedContext scope(this, name, "D3D12_COMMAND_QUEUE_DESC", 0, true); Serialise("Type", el.Type); Serialise("Priority", el.Priority); Serialise("Flags", el.Flags); Serialise("NodeMask", el.NodeMask); } template <> void Serialiser::Serialise(const char *name, D3D12_SHADER_BYTECODE &el) { ScopedContext scope(this, name, "D3D12_SHADER_BYTECODE", 0, true); uint64_t dataSize = el.BytecodeLength; Serialise("BytecodeLength", dataSize); size_t sz = (size_t)dataSize; if(m_Mode == READING) { el.pShaderBytecode = NULL; el.BytecodeLength = sz; } if(dataSize > 0) SerialiseBuffer("pShaderBytecode", (byte *&)el.pShaderBytecode, sz); } template <> void Serialiser::Serialise(const char *name, D3D12_SO_DECLARATION_ENTRY &el) { ScopedContext scope(this, name, "D3D12_SO_DECLARATION_ENTRY", 0, true); Serialise("Stream", el.Stream); { string s = ""; if(m_Mode == WRITING && el.SemanticName) s = el.SemanticName; Serialise("SemanticName", s); if(m_Mode == READING) { m_StringDB.insert(s); el.SemanticName = m_StringDB.find(s)->c_str(); } } Serialise("SemanticIndex", el.SemanticIndex); Serialise("StartComponent", el.StartComponent); Serialise("ComponentCount", el.ComponentCount); Serialise("OutputSlot", el.OutputSlot); } template <> void Serialiser::Serialise(const char *name, D3D12_STREAM_OUTPUT_DESC &el) { ScopedContext scope(this, name, "D3D12_STREAM_OUTPUT_DESC", 0, true); if(m_Mode == READING) { el.pSODeclaration = NULL; el.pBufferStrides = NULL; } SerialiseComplexArray("pSODeclaration", (D3D12_SO_DECLARATION_ENTRY *&)el.pSODeclaration, el.NumEntries); SerialisePODArray("pBufferStrides", (UINT *&)el.pBufferStrides, el.NumStrides); Serialise("RasterizedStream", el.RasterizedStream); } template <> void Serialiser::Deserialise(const D3D12_STREAM_OUTPUT_DESC *const el) const { if(m_Mode == READING) { delete[] el->pSODeclaration; delete[] el->pBufferStrides; } } template <> void Serialiser::Serialise(const char *name, D3D12_RENDER_TARGET_BLEND_DESC &el) { ScopedContext scope(this, name, "D3D12_RENDER_TARGET_BLEND_DESC", 0, true); Serialise("BlendEnable", el.BlendEnable); Serialise("LogicOpEnable", el.LogicOpEnable); Serialise("SrcBlend", el.SrcBlend); Serialise("DestBlend", el.DestBlend); Serialise("BlendOp", el.BlendOp); Serialise("SrcBlendAlpha", el.SrcBlendAlpha); Serialise("DestBlendAlpha", el.DestBlendAlpha); Serialise("BlendOpAlpha", el.BlendOpAlpha); Serialise("LogicOp", el.LogicOp); Serialise("RenderTargetWriteMask", el.RenderTargetWriteMask); } template <> void Serialiser::Serialise(const char *name, D3D12_BLEND_DESC &el) { ScopedContext scope(this, name, "D3D12_BLEND_DESC", 0, true); Serialise("AlphaToCoverageEnable", el.AlphaToCoverageEnable); Serialise("IndependentBlendEnable", el.IndependentBlendEnable); for(int i = 0; i < 8; i++) { ScopedContext targetscope(this, name, "D3D12_RENDER_TARGET_BLEND_DESC", 0, true); bool enable = el.RenderTarget[i].BlendEnable == TRUE; Serialise("BlendEnable", enable); el.RenderTarget[i].BlendEnable = enable; enable = el.RenderTarget[i].LogicOpEnable == TRUE; Serialise("LogicOpEnable", enable); el.RenderTarget[i].LogicOpEnable = enable; Serialise("SrcBlend", el.RenderTarget[i].SrcBlend); Serialise("DestBlend", el.RenderTarget[i].DestBlend); Serialise("BlendOp", el.RenderTarget[i].BlendOp); Serialise("SrcBlendAlpha", el.RenderTarget[i].SrcBlendAlpha); Serialise("DestBlendAlpha", el.RenderTarget[i].DestBlendAlpha); Serialise("BlendOpAlpha", el.RenderTarget[i].BlendOpAlpha); Serialise("LogicOp", el.RenderTarget[i].LogicOp); Serialise("RenderTargetWriteMask", el.RenderTarget[i].RenderTargetWriteMask); } } template <> void Serialiser::Serialise(const char *name, D3D12_RASTERIZER_DESC &el) { ScopedContext scope(this, name, "D3D12_RASTERIZER_DESC", 0, true); Serialise("FillMode", el.FillMode); Serialise("CullMode", el.CullMode); Serialise("FrontCounterClockwise", el.FrontCounterClockwise); Serialise("DepthBias", el.DepthBias); Serialise("DepthBiasClamp", el.DepthBiasClamp); Serialise("SlopeScaledDepthBias", el.SlopeScaledDepthBias); Serialise("DepthClipEnable", el.DepthClipEnable); Serialise("MultisampleEnable", el.MultisampleEnable); Serialise("AntialiasedLineEnable", el.AntialiasedLineEnable); Serialise("ForcedSampleCount", el.ForcedSampleCount); Serialise("ConservativeRaster", el.ConservativeRaster); } template <> void Serialiser::Serialise(const char *name, D3D12_DEPTH_STENCILOP_DESC &el) { ScopedContext scope(this, name, "D3D12_DEPTH_STENCILOP_DESC", 0, true); Serialise("StencilFailOp", el.StencilFailOp); Serialise("StencilDepthFailOp", el.StencilDepthFailOp); Serialise("StencilPassOp", el.StencilPassOp); Serialise("StencilFunc", el.StencilFunc); } template <> void Serialiser::Serialise(const char *name, D3D12_DEPTH_STENCIL_DESC &el) { ScopedContext scope(this, name, "D3D12_DEPTH_STENCIL_DESC", 0, true); Serialise("DepthEnable", el.DepthEnable); Serialise("DepthWriteMask", el.DepthWriteMask); Serialise("DepthFunc", el.DepthFunc); Serialise("StencilEnable", el.StencilEnable); Serialise("StencilReadMask", el.StencilReadMask); Serialise("StencilWriteMask", el.StencilWriteMask); Serialise("FrontFace", el.FrontFace); Serialise("BackFace", el.BackFace); } template <> void Serialiser::Serialise(const char *name, D3D12_INPUT_ELEMENT_DESC &el) { ScopedContext scope(this, name, "D3D12_INPUT_ELEMENT_DESC", 0, true); { string s = ""; if(m_Mode == WRITING && el.SemanticName) s = el.SemanticName; Serialise("SemanticName", s); if(m_Mode == READING) { m_StringDB.insert(s); el.SemanticName = m_StringDB.find(s)->c_str(); } } Serialise("SemanticIndex", el.SemanticIndex); Serialise("Format", el.Format); Serialise("InputSlot", el.InputSlot); Serialise("AlignedByteOffset", el.AlignedByteOffset); Serialise("InputSlotClass", el.InputSlotClass); Serialise("InstanceDataStepRate", el.InstanceDataStepRate); } template <> void Serialiser::Serialise(const char *name, D3D12_INPUT_LAYOUT_DESC &el) { ScopedContext scope(this, name, "D3D12_INPUT_LAYOUT_DESC", 0, true); SerialiseComplexArray("pInputElementDescs", (D3D12_INPUT_ELEMENT_DESC *&)el.pInputElementDescs, el.NumElements); } template <> void Serialiser::Deserialise(const D3D12_INPUT_LAYOUT_DESC *const el) const { if(m_Mode == READING) delete[] el->pInputElementDescs; } template <> void Serialiser::Serialise(const char *name, D3D12_INDIRECT_ARGUMENT_DESC &el) { ScopedContext scope(this, name, "D3D12_INDIRECT_ARGUMENT_DESC", 0, true); Serialise("Type", el.Type); switch(el.Type) { case D3D12_INDIRECT_ARGUMENT_TYPE_DRAW: case D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED: case D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH: case D3D12_INDIRECT_ARGUMENT_TYPE_INDEX_BUFFER_VIEW: // nothing to serialise break; case D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW: Serialise("VertexBuffer.Slot", el.VertexBuffer.Slot); break; case D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT: Serialise("Constant.RootParameterIndex", el.Constant.RootParameterIndex); Serialise("Constant.DestOffsetIn32BitValues", el.Constant.DestOffsetIn32BitValues); Serialise("Constant.Num32BitValuesToSet", el.Constant.Num32BitValuesToSet); break; case D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT_BUFFER_VIEW: Serialise("ConstantBufferView.RootParameterIndex", el.ConstantBufferView.RootParameterIndex); break; case D3D12_INDIRECT_ARGUMENT_TYPE_SHADER_RESOURCE_VIEW: Serialise("ShaderResourceView.RootParameterIndex", el.ShaderResourceView.RootParameterIndex); break; case D3D12_INDIRECT_ARGUMENT_TYPE_UNORDERED_ACCESS_VIEW: Serialise("UnorderedAccessView.RootParameterIndex", el.UnorderedAccessView.RootParameterIndex); break; default: RDCERR("Unexpected indirect argument type: %u", el.Type); break; } } template <> void Serialiser::Serialise(const char *name, D3D12_COMMAND_SIGNATURE_DESC &el) { ScopedContext scope(this, name, "D3D12_COMMAND_SIGNATURE_DESC", 0, true); Serialise("ByteStride", el.ByteStride); Serialise("NodeMask", el.NodeMask); SerialiseComplexArray("pArgumentDescs", (D3D12_INDIRECT_ARGUMENT_DESC *&)el.pArgumentDescs, el.NumArgumentDescs); } template <> void Serialiser::Deserialise(const D3D12_COMMAND_SIGNATURE_DESC *const el) const { if(m_Mode == READING) delete[] el->pArgumentDescs; } template <> void Serialiser::Serialise(const char *name, D3D12_GRAPHICS_PIPELINE_STATE_DESC &el) { ScopedContext scope(this, name, "D3D12_GRAPHICS_PIPELINE_STATE_DESC", 0, true); SerialiseObject(ID3D12RootSignature, "pRootSignature", el.pRootSignature); Serialise("VS", el.VS); Serialise("PS", el.PS); Serialise("DS", el.DS); Serialise("HS", el.HS); Serialise("GS", el.GS); Serialise("StreamOutput", el.StreamOutput); Serialise("BlendState", el.BlendState); Serialise("SampleMask", el.SampleMask); Serialise("RasterizerState", el.RasterizerState); Serialise("DepthStencilState", el.DepthStencilState); Serialise("InputLayout", el.InputLayout); Serialise("IBStripCutValue", el.IBStripCutValue); Serialise("PrimitiveTopologyType", el.PrimitiveTopologyType); Serialise("NumRenderTargets", el.NumRenderTargets); SerialisePODArray<8>("RTVFormats", el.RTVFormats); Serialise("DSVFormat", el.DSVFormat); Serialise("SampleDesc", el.SampleDesc); Serialise("NodeMask", el.NodeMask); Serialise("Flags", el.Flags); if(m_Mode == READING) { el.CachedPSO.CachedBlobSizeInBytes = 0; el.CachedPSO.pCachedBlob = NULL; } } template <> void Serialiser::Deserialise(const D3D12_GRAPHICS_PIPELINE_STATE_DESC *const el) const { if(m_Mode == READING) { delete[](byte *)(el->VS.pShaderBytecode); delete[](byte *)(el->PS.pShaderBytecode); delete[](byte *)(el->DS.pShaderBytecode); delete[](byte *)(el->HS.pShaderBytecode); delete[](byte *)(el->GS.pShaderBytecode); } } template <> void Serialiser::Serialise(const char *name, D3D12_COMPUTE_PIPELINE_STATE_DESC &el) { ScopedContext scope(this, name, "D3D12_COMPUTE_PIPELINE_STATE_DESC", 0, true); SerialiseObject(ID3D12RootSignature, "pRootSignature", el.pRootSignature); Serialise("CS", el.CS); Serialise("NodeMask", el.NodeMask); Serialise("Flags", el.Flags); if(m_Mode == READING) { el.CachedPSO.CachedBlobSizeInBytes = 0; el.CachedPSO.pCachedBlob = NULL; } } template <> void Serialiser::Deserialise(const D3D12_COMPUTE_PIPELINE_STATE_DESC *const el) const { if(m_Mode == READING) delete[](byte *)(el->CS.pShaderBytecode); } template <> void Serialiser::Serialise(const char *name, D3D12_VERTEX_BUFFER_VIEW &el) { ScopedContext scope(this, name, "D3D12_VERTEX_BUFFER_VIEW", 0, true); D3D12ResourceManager *rm = (D3D12ResourceManager *)GetUserData(); ResourceId buffer; UINT64 offs = 0; if(m_Mode == WRITING) WrappedID3D12Resource::GetResIDFromAddr(el.BufferLocation, buffer, offs); Serialise("BufferLocation", buffer); Serialise("BufferLocation_Offset", offs); if(m_Mode == READING) { ID3D12Resource *res = rm->GetLiveAs(buffer); if(res) el.BufferLocation = res->GetGPUVirtualAddress() + offs; else el.BufferLocation = 0; } Serialise("SizeInBytes", el.SizeInBytes); Serialise("StrideInBytes", el.StrideInBytes); } template <> void Serialiser::Serialise(const char *name, D3D12_INDEX_BUFFER_VIEW &el) { ScopedContext scope(this, name, "D3D12_INDEX_BUFFER_VIEW", 0, true); D3D12ResourceManager *rm = (D3D12ResourceManager *)GetUserData(); ResourceId buffer; UINT64 offs = 0; if(m_Mode == WRITING) WrappedID3D12Resource::GetResIDFromAddr(el.BufferLocation, buffer, offs); Serialise("BufferLocation", buffer); Serialise("BufferLocation_Offset", offs); if(m_Mode == READING) { ID3D12Resource *res = rm->GetLiveAs(buffer); if(res) el.BufferLocation = res->GetGPUVirtualAddress() + offs; else el.BufferLocation = 0; } Serialise("SizeInBytes", el.SizeInBytes); Serialise("Format", el.Format); } template <> void Serialiser::Serialise(const char *name, D3D12_STREAM_OUTPUT_BUFFER_VIEW &el) { ScopedContext scope(this, name, "D3D12_STREAM_OUTPUT_BUFFER_VIEW", 0, true); D3D12ResourceManager *rm = (D3D12ResourceManager *)GetUserData(); ResourceId buffer; UINT64 offs = 0; if(m_Mode == WRITING) WrappedID3D12Resource::GetResIDFromAddr(el.BufferLocation, buffer, offs); Serialise("BufferLocation", buffer); Serialise("BufferLocation_Offset", offs); if(m_Mode == READING) { ID3D12Resource *res = rm->GetLiveAs(buffer); if(res) el.BufferLocation = res->GetGPUVirtualAddress() + offs; else el.BufferLocation = 0; } if(m_Mode == WRITING) WrappedID3D12Resource::GetResIDFromAddr(el.BufferFilledSizeLocation, buffer, offs); Serialise("BufferFilledSizeLocation", buffer); Serialise("BufferFilledSizeLocation_Offset", offs); if(m_Mode == READING) { ID3D12Resource *res = rm->GetLiveAs(buffer); if(res) el.BufferFilledSizeLocation = res->GetGPUVirtualAddress() + offs; else el.BufferFilledSizeLocation = 0; } Serialise("SizeInBytes", el.SizeInBytes); } template <> void Serialiser::Serialise(const char *name, D3D12_CONSTANT_BUFFER_VIEW_DESC &el) { ScopedContext scope(this, name, "D3D12_CONSTANT_BUFFER_VIEW_DESC", 0, true); D3D12ResourceManager *rm = (D3D12ResourceManager *)GetUserData(); ResourceId buffer; UINT64 offs = 0; if(m_Mode == WRITING) WrappedID3D12Resource::GetResIDFromAddr(el.BufferLocation, buffer, offs); Serialise("BufferLocation", buffer); Serialise("BufferLocation_Offset", offs); if(m_Mode == READING) { ID3D12Resource *res = NULL; if(buffer != ResourceId() && rm->HasLiveResource(buffer)) res = rm->GetLiveAs(buffer); if(res) el.BufferLocation = res->GetGPUVirtualAddress() + offs; else el.BufferLocation = 0; } Serialise("SizeInBytes", el.SizeInBytes); } template <> void Serialiser::Serialise(const char *name, D3D12_SHADER_RESOURCE_VIEW_DESC &el) { ScopedContext scope(this, name, "D3D12_SHADER_RESOURCE_VIEW_DESC", 0, true); Serialise("Format", el.Format); Serialise("ViewDimension", el.ViewDimension); // cast to a special enum so we print nicely Serialise("Shader4ComponentMapping", (D3D12ComponentMapping &)el.Shader4ComponentMapping); switch(el.ViewDimension) { case D3D12_SRV_DIMENSION_UNKNOWN: // indicates an empty descriptor, which comes from a NULL parameter to Create. break; case D3D12_SRV_DIMENSION_BUFFER: Serialise("Buffer.FirstElement", el.Buffer.FirstElement); Serialise("Buffer.NumElements", el.Buffer.NumElements); Serialise("Buffer.StructureByteStride", el.Buffer.StructureByteStride); Serialise("Buffer.Flags", el.Buffer.Flags); break; case D3D12_SRV_DIMENSION_TEXTURE1D: Serialise("Texture1D.MostDetailedMip", el.Texture1D.MostDetailedMip); Serialise("Texture1D.MipLevels", el.Texture1D.MipLevels); Serialise("Texture1D.ResourceMinLODClamp", el.Texture1D.ResourceMinLODClamp); break; case D3D12_SRV_DIMENSION_TEXTURE1DARRAY: Serialise("Texture1DArray.MostDetailedMip", el.Texture1DArray.MostDetailedMip); Serialise("Texture1DArray.MipLevels", el.Texture1DArray.MipLevels); Serialise("Texture1DArray.FirstArraySlice", el.Texture1DArray.FirstArraySlice); Serialise("Texture1DArray.ArraySize", el.Texture1DArray.ArraySize); Serialise("Texture1DArray.ResourceMinLODClamp", el.Texture1DArray.ResourceMinLODClamp); break; case D3D12_SRV_DIMENSION_TEXTURE2D: Serialise("Texture2D.MostDetailedMip", el.Texture2D.MostDetailedMip); Serialise("Texture2D.MipLevels", el.Texture2D.MipLevels); Serialise("Texture2D.PlaneSlice", el.Texture2D.PlaneSlice); Serialise("Texture2D.ResourceMinLODClamp", el.Texture2D.ResourceMinLODClamp); break; case D3D12_SRV_DIMENSION_TEXTURE2DARRAY: Serialise("Texture2DArray.MostDetailedMip", el.Texture2DArray.MostDetailedMip); Serialise("Texture2DArray.MipLevels", el.Texture2DArray.MipLevels); Serialise("Texture2DArray.FirstArraySlice", el.Texture2DArray.FirstArraySlice); Serialise("Texture2DArray.ArraySize", el.Texture2DArray.ArraySize); Serialise("Texture2DArray.PlaneSlice", el.Texture2DArray.PlaneSlice); Serialise("Texture2DArray.ResourceMinLODClamp", el.Texture2DArray.ResourceMinLODClamp); break; case D3D12_SRV_DIMENSION_TEXTURE2DMS: // el.Texture2DMS.UnusedField_NothingToDefine break; case D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY: Serialise("Texture2DMSArray.FirstArraySlice", el.Texture2DMSArray.FirstArraySlice); Serialise("Texture2DMSArray.ArraySize", el.Texture2DMSArray.ArraySize); break; case D3D12_SRV_DIMENSION_TEXTURE3D: Serialise("Texture3D.MipLevels", el.Texture3D.MipLevels); Serialise("Texture3D.MostDetailedMip", el.Texture3D.MostDetailedMip); Serialise("Texture3D.ResourceMinLODClamp", el.Texture3D.ResourceMinLODClamp); break; case D3D12_SRV_DIMENSION_TEXTURECUBE: Serialise("TextureCube.MostDetailedMip", el.TextureCube.MostDetailedMip); Serialise("TextureCube.MipLevels", el.TextureCube.MipLevels); Serialise("TextureCube.ResourceMinLODClamp", el.TextureCube.ResourceMinLODClamp); break; case D3D12_SRV_DIMENSION_TEXTURECUBEARRAY: Serialise("TextureCubeArray.MostDetailedMip", el.TextureCubeArray.MostDetailedMip); Serialise("TextureCubeArray.MipLevels", el.TextureCubeArray.MipLevels); Serialise("TextureCubeArray.First2DArrayFace", el.TextureCubeArray.First2DArrayFace); Serialise("TextureCubeArray.NumCubes", el.TextureCubeArray.NumCubes); Serialise("TextureCubeArray.ResourceMinLODClamp", el.TextureCubeArray.ResourceMinLODClamp); break; default: RDCERR("Unrecognised SRV Dimension %d", el.ViewDimension); break; } } template <> void Serialiser::Serialise(const char *name, D3D12_RENDER_TARGET_VIEW_DESC &el) { ScopedContext scope(this, name, "D3D12_RENDER_TARGET_VIEW_DESC", 0, true); Serialise("Format", el.Format); Serialise("ViewDimension", el.ViewDimension); switch(el.ViewDimension) { case D3D12_RTV_DIMENSION_UNKNOWN: // indicates an empty descriptor, which comes from a NULL parameter to Create. break; case D3D12_RTV_DIMENSION_BUFFER: Serialise("Buffer.FirstElement", el.Buffer.FirstElement); Serialise("Buffer.NumElements", el.Buffer.NumElements); break; case D3D12_RTV_DIMENSION_TEXTURE1D: Serialise("Texture1D.MipSlice", el.Texture1D.MipSlice); break; case D3D12_RTV_DIMENSION_TEXTURE1DARRAY: Serialise("Texture1DArray.MipSlice", el.Texture1DArray.MipSlice); Serialise("Texture1DArray.FirstArraySlice", el.Texture1DArray.FirstArraySlice); Serialise("Texture1DArray.ArraySize", el.Texture1DArray.ArraySize); break; case D3D12_RTV_DIMENSION_TEXTURE2D: Serialise("Texture2D.MipSlice", el.Texture2D.MipSlice); Serialise("Texture2D.PlaneSlice", el.Texture2D.PlaneSlice); break; case D3D12_RTV_DIMENSION_TEXTURE2DARRAY: Serialise("Texture2DArray.MipSlice", el.Texture2DArray.MipSlice); Serialise("Texture2DArray.FirstArraySlice", el.Texture2DArray.FirstArraySlice); Serialise("Texture2DArray.ArraySize", el.Texture2DArray.ArraySize); Serialise("Texture2DArray.PlaneSlice", el.Texture2DArray.PlaneSlice); break; case D3D12_RTV_DIMENSION_TEXTURE2DMS: // el.Texture2DMS.UnusedField_NothingToDefine break; case D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY: Serialise("Texture2DMSArray.FirstArraySlice", el.Texture2DMSArray.FirstArraySlice); Serialise("Texture2DMSArray.ArraySize", el.Texture2DMSArray.ArraySize); break; case D3D12_RTV_DIMENSION_TEXTURE3D: Serialise("Texture3D.MipSlice", el.Texture3D.MipSlice); Serialise("Texture3D.FirstWSlice", el.Texture3D.FirstWSlice); Serialise("Texture3D.WSize", el.Texture3D.WSize); break; default: RDCERR("Unrecognised RTV Dimension %d", el.ViewDimension); break; } } template <> void Serialiser::Serialise(const char *name, D3D12_DEPTH_STENCIL_VIEW_DESC &el) { ScopedContext scope(this, name, "D3D12_DEPTH_STENCIL_VIEW_DESC", 0, true); Serialise("Format", el.Format); Serialise("Flags", el.Flags); Serialise("ViewDimension", el.ViewDimension); switch(el.ViewDimension) { case D3D12_DSV_DIMENSION_UNKNOWN: // indicates an empty descriptor, which comes from a NULL parameter to Create. break; case D3D12_DSV_DIMENSION_TEXTURE1D: Serialise("Texture1D.MipSlice", el.Texture1D.MipSlice); break; case D3D12_DSV_DIMENSION_TEXTURE1DARRAY: Serialise("Texture1DArray.MipSlice", el.Texture1DArray.MipSlice); Serialise("Texture1DArray.FirstArraySlice", el.Texture1DArray.FirstArraySlice); Serialise("Texture1DArray.ArraySize", el.Texture1DArray.ArraySize); break; case D3D12_DSV_DIMENSION_TEXTURE2D: Serialise("Texture2D.MipSlice", el.Texture2D.MipSlice); break; case D3D12_DSV_DIMENSION_TEXTURE2DARRAY: Serialise("Texture2DArray.MipSlice", el.Texture2DArray.MipSlice); Serialise("Texture2DArray.FirstArraySlice", el.Texture2DArray.FirstArraySlice); Serialise("Texture2DArray.ArraySize", el.Texture2DArray.ArraySize); break; case D3D12_DSV_DIMENSION_TEXTURE2DMS: // el.Texture2DMS.UnusedField_NothingToDefine break; case D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY: Serialise("Texture2DMSArray.FirstArraySlice", el.Texture2DMSArray.FirstArraySlice); Serialise("Texture2DMSArray.ArraySize", el.Texture2DMSArray.ArraySize); break; default: RDCERR("Unrecognised DSV Dimension %d", el.ViewDimension); break; } } template <> void Serialiser::Serialise(const char *name, D3D12_UNORDERED_ACCESS_VIEW_DESC &el) { ScopedContext scope(this, name, "D3D12_UNORDERED_ACCESS_VIEW_DESC", 0, true); Serialise("Format", el.Format); Serialise("ViewDimension", el.ViewDimension); switch(el.ViewDimension) { case D3D12_UAV_DIMENSION_UNKNOWN: // indicates an empty descriptor, which comes from a NULL parameter to Create. break; case D3D12_UAV_DIMENSION_BUFFER: Serialise("Buffer.FirstElement", el.Buffer.FirstElement); Serialise("Buffer.NumElements", el.Buffer.NumElements); Serialise("Buffer.StructureByteStride", el.Buffer.StructureByteStride); Serialise("Buffer.CounterOffsetInBytes", el.Buffer.CounterOffsetInBytes); Serialise("Buffer.Flags", el.Buffer.Flags); break; case D3D12_UAV_DIMENSION_TEXTURE1D: Serialise("Texture1D.MipSlice", el.Texture1D.MipSlice); break; case D3D12_UAV_DIMENSION_TEXTURE1DARRAY: Serialise("Texture1DArray.MipSlice", el.Texture1DArray.MipSlice); Serialise("Texture1DArray.FirstArraySlice", el.Texture1DArray.FirstArraySlice); Serialise("Texture1DArray.ArraySize", el.Texture1DArray.ArraySize); break; case D3D12_UAV_DIMENSION_TEXTURE2D: Serialise("Texture2D.MipSlice", el.Texture2D.MipSlice); Serialise("Texture2D.PlaneSlice", el.Texture2D.PlaneSlice); break; case D3D12_UAV_DIMENSION_TEXTURE2DARRAY: Serialise("Texture2DArray.MipSlice", el.Texture2DArray.MipSlice); Serialise("Texture2DArray.FirstArraySlice", el.Texture2DArray.FirstArraySlice); Serialise("Texture2DArray.ArraySize", el.Texture2DArray.ArraySize); Serialise("Texture2DArray.PlaneSlice", el.Texture2DArray.PlaneSlice); break; case D3D12_UAV_DIMENSION_TEXTURE3D: Serialise("Texture3D.MipSlice", el.Texture3D.MipSlice); Serialise("Texture3D.FirstWSlice", el.Texture3D.FirstWSlice); Serialise("Texture3D.WSize", el.Texture3D.WSize); break; default: RDCERR("Unrecognised RTV Dimension %d", el.ViewDimension); break; } } template <> void Serialiser::Serialise(const char *name, D3D12_RESOURCE_BARRIER &el) { ScopedContext scope(this, name, "D3D12_RESOURCE_BARRIER", 0, true); Serialise("Type", el.Type); Serialise("Flags", el.Flags); switch(el.Type) { case D3D12_RESOURCE_BARRIER_TYPE_TRANSITION: { SerialiseObject(ID3D12Resource, "Transition.pResource", el.Transition.pResource); // cast to a special enum so we print 'all subresources' nicely RDCCOMPILE_ASSERT(sizeof(D3D12ResourceBarrierSubresource) == sizeof(UINT), "Enum isn't uint sized"); Serialise("Transition.Subresource", (D3D12ResourceBarrierSubresource &)el.Transition.Subresource); Serialise("Transition.StateBefore", el.Transition.StateBefore); Serialise("Transition.StateAfter", el.Transition.StateAfter); break; } case D3D12_RESOURCE_BARRIER_TYPE_ALIASING: { SerialiseObject(ID3D12Resource, "Aliasing.pResourceBefore", el.Aliasing.pResourceBefore); SerialiseObject(ID3D12Resource, "Aliasing.pResourceAfter", el.Aliasing.pResourceAfter); break; } case D3D12_RESOURCE_BARRIER_TYPE_UAV: { SerialiseObject(ID3D12Resource, "UAV.pResource", el.UAV.pResource); break; } } } template <> void Serialiser::Serialise(const char *name, D3D12_HEAP_PROPERTIES &el) { ScopedContext scope(this, name, "D3D12_HEAP_PROPERTIES", 0, true); Serialise("Type", el.Type); Serialise("CPUPageProperty", el.CPUPageProperty); Serialise("MemoryPoolPreference", el.MemoryPoolPreference); Serialise("CreationNodeMask", el.CreationNodeMask); Serialise("VisibleNodeMask", el.VisibleNodeMask); } template <> void Serialiser::Serialise(const char *name, D3D12_HEAP_DESC &el) { ScopedContext scope(this, name, "D3D12_HEAP_DESC", 0, true); Serialise("SizeInBytes", el.SizeInBytes); Serialise("Properties", el.Properties); Serialise("Alignment", el.Alignment); Serialise("Flags", el.Flags); } template <> void Serialiser::Serialise(const char *name, D3D12_DESCRIPTOR_HEAP_DESC &el) { ScopedContext scope(this, name, "D3D12_DESCRIPTOR_HEAP_DESC", 0, true); Serialise("Type", el.Type); Serialise("NumDescriptors", el.NumDescriptors); Serialise("Flags", el.Flags); Serialise("NodeMask", el.NodeMask); } template <> void Serialiser::Serialise(const char *name, D3D12_QUERY_HEAP_DESC &el) { ScopedContext scope(this, name, "D3D12_QUERY_HEAP_DESC", 0, true); Serialise("Type", el.Type); Serialise("Count", el.Count); Serialise("NodeMask", el.NodeMask); } template <> void Serialiser::Serialise(const char *name, D3D12_CLEAR_VALUE &el) { ScopedContext scope(this, name, "D3D12_CLEAR_VALUE", 0, true); Serialise("Format", el.Format); if(!IsDepthFormat(el.Format)) { SerialisePODArray<4>("Color", el.Color); } else { Serialise("Depth", el.DepthStencil.Depth); Serialise("Stencil", el.DepthStencil.Stencil); } } template <> void Serialiser::Serialise(const char *name, D3D12_SUBRESOURCE_FOOTPRINT &el) { ScopedContext scope(this, name, "D3D12_SUBRESOURCE_FOOTPRINT", 0, true); Serialise("Format", el.Format); Serialise("Width", el.Width); Serialise("Height", el.Height); Serialise("Depth", el.Depth); Serialise("RowPitch", el.RowPitch); } template <> void Serialiser::Serialise(const char *name, D3D12_TEXTURE_COPY_LOCATION &el) { ScopedContext scope(this, name, "D3D12_TEXTURE_COPY_LOCATION", 0, true); SerialiseObject(ID3D12Resource, "pResource", el.pResource); Serialise("Type", el.Type); switch(el.Type) { case D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT: Serialise("PlacedFootprint.Footprint", el.PlacedFootprint.Footprint); Serialise("PlacedFootprint.Offset", el.PlacedFootprint.Offset); break; case D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX: Serialise("SubresourceIndex", el.SubresourceIndex); break; default: RDCERR("Unexpected texture copy type %d", el.Type); break; } } template <> void Serialiser::Serialise(const char *name, D3D12_DISCARD_REGION &el) { ScopedContext scope(this, name, "D3D12_DISCARD_REGION", 0, true); Serialise("FirstSubresource", el.FirstSubresource); Serialise("NumSubresources", el.NumSubresources); SerialiseComplexArray("pRects", (D3D12_RECT *&)el.pRects, el.NumRects); } template <> void Serialiser::Deserialise(const D3D12_DISCARD_REGION *const el) const { if(m_Mode == READING) delete[] el->pRects; } template <> void Serialiser::Serialise(const char *name, D3D12_SAMPLER_DESC &el) { ScopedContext scope(this, name, "D3D12_SAMPLER_DESC", 0, true); Serialise("Filter", el.Filter); Serialise("AddressU", el.AddressU); Serialise("AddressV", el.AddressV); Serialise("AddressW", el.AddressW); Serialise("MipLODBias", el.MipLODBias); Serialise("MaxAnisotropy", el.MaxAnisotropy); Serialise("ComparisonFunc", el.ComparisonFunc); SerialisePODArray<4>("BorderColor", el.BorderColor); Serialise("MinLOD", el.MinLOD); Serialise("MaxLOD", el.MaxLOD); } string ToStrHelper::Get(const D3D12_VIEWPORT &el) { return StringFormat::Fmt("Viewport<%.0fx%.0f+%.0f+%.0f z=%f->%f>", el.Width, el.Height, el.TopLeftX, el.TopLeftY, el.MinDepth, el.MaxDepth); } string ToStrHelper::Get(const D3D12_BOX &el) { return StringFormat::Fmt("Box<%u,%u,%u -> %u,%u,%u>", el.left, el.top, el.front, el.right, el.bottom, el.back); } string ToStrHelper::Get(const PortableHandle &el) { if(el.heap == ResourceId()) return "NULL"; return StringFormat::Fmt("D3D12_CPU_DESCRIPTOR_HANDLE(%s, %u)", ToStr::Get(el.heap).c_str(), el.index); } string ToStrHelper::Get(const D3D12Descriptor::DescriptorType &el) { switch(el) { case D3D12Descriptor::TypeCBV: return "CBV"; case D3D12Descriptor::TypeSRV: return "SRV"; case D3D12Descriptor::TypeUAV: return "UAV"; case D3D12Descriptor::TypeRTV: return "RTV"; case D3D12Descriptor::TypeDSV: return "DSV"; case D3D12Descriptor::TypeUndefined: return "Undefined"; default: break; } if((uint32_t)el < D3D12Descriptor::TypeCBV) return "Sampler"; return StringFormat::Fmt("DescriptorType<%d>", el); } string ToStrHelper::Get(const D3D12ResourceType &el) { switch(el) { case Resource_Device: return "Device"; case Resource_Unknown: return "Unknown"; case Resource_CommandAllocator: return "Command Allocator"; case Resource_CommandQueue: return "Command Queue"; case Resource_CommandSignature: return "Command Signature"; case Resource_DescriptorHeap: return "Descriptor Heap"; case Resource_Fence: return "Fence"; case Resource_Heap: return "Heap"; case Resource_PipelineState: return "Pipeline State"; case Resource_QueryHeap: return "Query Heap"; case Resource_Resource: return "Resource"; case Resource_GraphicsCommandList: return "Graphics CommandList"; case Resource_RootSignature: return "Root Signature"; default: break; } return StringFormat::Fmt("D3D12ResourceType<%d>", el); } string ToStrHelper::Get(const D3D12_HEAP_TYPE &el) { switch(el) { TOSTR_CASE_STRINGIZE(D3D12_HEAP_TYPE_DEFAULT) TOSTR_CASE_STRINGIZE(D3D12_HEAP_TYPE_UPLOAD) TOSTR_CASE_STRINGIZE(D3D12_HEAP_TYPE_READBACK) TOSTR_CASE_STRINGIZE(D3D12_HEAP_TYPE_CUSTOM) default: break; } return StringFormat::Fmt("D3D12_HEAP_TYPE<%d>", el); } string ToStrHelper::Get(const D3D12_CPU_PAGE_PROPERTY &el) { switch(el) { TOSTR_CASE_STRINGIZE(D3D12_CPU_PAGE_PROPERTY_UNKNOWN) TOSTR_CASE_STRINGIZE(D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE) TOSTR_CASE_STRINGIZE(D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE) TOSTR_CASE_STRINGIZE(D3D12_CPU_PAGE_PROPERTY_WRITE_BACK) default: break; } return StringFormat::Fmt("D3D12_CPU_PAGE_PROPERTY<%d>", el); } string ToStrHelper::Get(const D3D12_MEMORY_POOL &el) { switch(el) { TOSTR_CASE_STRINGIZE(D3D12_MEMORY_POOL_UNKNOWN) TOSTR_CASE_STRINGIZE(D3D12_MEMORY_POOL_L0) TOSTR_CASE_STRINGIZE(D3D12_MEMORY_POOL_L1) default: break; } return StringFormat::Fmt("D3D12_MEMORY_POOL<%d>", el); } string ToStrHelper::Get(const D3D12_QUERY_HEAP_TYPE &el) { switch(el) { TOSTR_CASE_STRINGIZE(D3D12_QUERY_HEAP_TYPE_OCCLUSION) TOSTR_CASE_STRINGIZE(D3D12_QUERY_HEAP_TYPE_TIMESTAMP) TOSTR_CASE_STRINGIZE(D3D12_QUERY_HEAP_TYPE_PIPELINE_STATISTICS) TOSTR_CASE_STRINGIZE(D3D12_QUERY_HEAP_TYPE_SO_STATISTICS) default: break; } return StringFormat::Fmt("D3D12_QUERY_HEAP_TYPE<%d>", el); } string ToStrHelper::Get(const D3D12_QUERY_TYPE &el) { switch(el) { TOSTR_CASE_STRINGIZE(D3D12_QUERY_TYPE_OCCLUSION) TOSTR_CASE_STRINGIZE(D3D12_QUERY_TYPE_BINARY_OCCLUSION) TOSTR_CASE_STRINGIZE(D3D12_QUERY_TYPE_TIMESTAMP) TOSTR_CASE_STRINGIZE(D3D12_QUERY_TYPE_PIPELINE_STATISTICS) TOSTR_CASE_STRINGIZE(D3D12_QUERY_TYPE_SO_STATISTICS_STREAM0) TOSTR_CASE_STRINGIZE(D3D12_QUERY_TYPE_SO_STATISTICS_STREAM1) TOSTR_CASE_STRINGIZE(D3D12_QUERY_TYPE_SO_STATISTICS_STREAM2) TOSTR_CASE_STRINGIZE(D3D12_QUERY_TYPE_SO_STATISTICS_STREAM3) default: break; } return StringFormat::Fmt("D3D12_QUERY_TYPE<%d>", el); } string ToStrHelper::Get(const D3D12_PREDICATION_OP &el) { switch(el) { TOSTR_CASE_STRINGIZE(D3D12_PREDICATION_OP_EQUAL_ZERO) TOSTR_CASE_STRINGIZE(D3D12_PREDICATION_OP_NOT_EQUAL_ZERO) default: break; } return StringFormat::Fmt("D3D12_PREDICATION_OP<%d>", el); } string ToStrHelper::Get(const D3D12_DESCRIPTOR_HEAP_TYPE &el) { switch(el) { TOSTR_CASE_STRINGIZE(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) TOSTR_CASE_STRINGIZE(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) TOSTR_CASE_STRINGIZE(D3D12_DESCRIPTOR_HEAP_TYPE_RTV) TOSTR_CASE_STRINGIZE(D3D12_DESCRIPTOR_HEAP_TYPE_DSV) default: break; } return StringFormat::Fmt("D3D12_DESCRIPTOR_HEAP_TYPE<%d>", el); } string ToStrHelper::Get(const D3D12_RESOURCE_BARRIER_TYPE &el) { switch(el) { TOSTR_CASE_STRINGIZE(D3D12_RESOURCE_BARRIER_TYPE_TRANSITION) TOSTR_CASE_STRINGIZE(D3D12_RESOURCE_BARRIER_TYPE_ALIASING) TOSTR_CASE_STRINGIZE(D3D12_RESOURCE_BARRIER_TYPE_UAV) default: break; } return StringFormat::Fmt("D3D12_RESOURCE_BARRIER_TYPE<%d>", el); } string ToStrHelper::Get(const D3D12_SRV_DIMENSION &el) { switch(el) { TOSTR_CASE_STRINGIZE(D3D12_SRV_DIMENSION_UNKNOWN) TOSTR_CASE_STRINGIZE(D3D12_SRV_DIMENSION_BUFFER) TOSTR_CASE_STRINGIZE(D3D12_SRV_DIMENSION_TEXTURE1D) TOSTR_CASE_STRINGIZE(D3D12_SRV_DIMENSION_TEXTURE1DARRAY) TOSTR_CASE_STRINGIZE(D3D12_SRV_DIMENSION_TEXTURE2D) TOSTR_CASE_STRINGIZE(D3D12_SRV_DIMENSION_TEXTURE2DARRAY) TOSTR_CASE_STRINGIZE(D3D12_SRV_DIMENSION_TEXTURE2DMS) TOSTR_CASE_STRINGIZE(D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY) TOSTR_CASE_STRINGIZE(D3D12_SRV_DIMENSION_TEXTURE3D) TOSTR_CASE_STRINGIZE(D3D12_SRV_DIMENSION_TEXTURECUBE) TOSTR_CASE_STRINGIZE(D3D12_SRV_DIMENSION_TEXTURECUBEARRAY) default: break; } return StringFormat::Fmt("D3D12_SRV_DIMENSION<%d>", el); } string ToStrHelper::Get(const D3D12_RTV_DIMENSION &el) { switch(el) { TOSTR_CASE_STRINGIZE(D3D12_RTV_DIMENSION_UNKNOWN) TOSTR_CASE_STRINGIZE(D3D12_RTV_DIMENSION_BUFFER) TOSTR_CASE_STRINGIZE(D3D12_RTV_DIMENSION_TEXTURE1D) TOSTR_CASE_STRINGIZE(D3D12_RTV_DIMENSION_TEXTURE1DARRAY) TOSTR_CASE_STRINGIZE(D3D12_RTV_DIMENSION_TEXTURE2D) TOSTR_CASE_STRINGIZE(D3D12_RTV_DIMENSION_TEXTURE2DARRAY) TOSTR_CASE_STRINGIZE(D3D12_RTV_DIMENSION_TEXTURE2DMS) TOSTR_CASE_STRINGIZE(D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY) TOSTR_CASE_STRINGIZE(D3D12_RTV_DIMENSION_TEXTURE3D) default: break; } return StringFormat::Fmt("D3D12_RTV_DIMENSION<%d>", el); } string ToStrHelper::Get(const D3D12_UAV_DIMENSION &el) { switch(el) { TOSTR_CASE_STRINGIZE(D3D12_UAV_DIMENSION_BUFFER) TOSTR_CASE_STRINGIZE(D3D12_UAV_DIMENSION_TEXTURE1D) TOSTR_CASE_STRINGIZE(D3D12_UAV_DIMENSION_TEXTURE1DARRAY) TOSTR_CASE_STRINGIZE(D3D12_UAV_DIMENSION_TEXTURE2D) TOSTR_CASE_STRINGIZE(D3D12_UAV_DIMENSION_TEXTURE2DARRAY) TOSTR_CASE_STRINGIZE(D3D12_UAV_DIMENSION_TEXTURE3D) default: break; } return StringFormat::Fmt("D3D12_UAV_DIMENSION<%d>", el); } string ToStrHelper::Get(const D3D12_DSV_DIMENSION &el) { switch(el) { TOSTR_CASE_STRINGIZE(D3D12_DSV_DIMENSION_UNKNOWN) TOSTR_CASE_STRINGIZE(D3D12_DSV_DIMENSION_TEXTURE1D) TOSTR_CASE_STRINGIZE(D3D12_DSV_DIMENSION_TEXTURE1DARRAY) TOSTR_CASE_STRINGIZE(D3D12_DSV_DIMENSION_TEXTURE2D) TOSTR_CASE_STRINGIZE(D3D12_DSV_DIMENSION_TEXTURE2DARRAY) TOSTR_CASE_STRINGIZE(D3D12_DSV_DIMENSION_TEXTURE2DMS) TOSTR_CASE_STRINGIZE(D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY) default: break; } return StringFormat::Fmt("D3D12_DSV_DIMENSION<%d>", el); } string ToStrHelper::Get(const D3D12_FILTER &el) { switch(el) { case D3D12_FILTER_MIN_MAG_MIP_POINT: return "MIN_MAG_MIP_POINT"; case D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR: return "MIN_MAG_POINT_MIP_LINEAR"; case D3D12_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT: return "MIN_POINT_MAG_LINEAR_MIP_POINT"; case D3D12_FILTER_MIN_POINT_MAG_MIP_LINEAR: return "MIN_POINT_MAG_MIP_LINEAR"; case D3D12_FILTER_MIN_LINEAR_MAG_MIP_POINT: return "MIN_LINEAR_MAG_MIP_POINT"; case D3D12_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR: return "MIN_LINEAR_MAG_POINT_MIP_LINEAR"; case D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT: return "MIN_MAG_LINEAR_MIP_POINT"; case D3D12_FILTER_MIN_MAG_MIP_LINEAR: return "MIN_MAG_MIP_LINEAR"; case D3D12_FILTER_ANISOTROPIC: return "ANISOTROPIC"; case D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT: return "CMP:MIN_MAG_MIP_POINT"; case D3D12_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR: return "CMP:MIN_MAG_POINT_MIP_LINEAR"; case D3D12_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT: return "CMP:MIN_POINT_MAG_LINEAR_MIP_POINT"; case D3D12_FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR: return "CMP:MIN_POINT_MAG_MIP_LINEAR"; case D3D12_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT: return "CMP:MIN_LINEAR_MAG_MIP_POINT"; case D3D12_FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR: return "CMP:MIN_LINEAR_MAG_POINT_MIP_LINEAR"; case D3D12_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT: return "CMP:MIN_MAG_LINEAR_MIP_POINT"; case D3D12_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR: return "CMP:MIN_MAG_MIP_LINEAR"; case D3D12_FILTER_COMPARISON_ANISOTROPIC: return "CMP:ANISOTROPIC"; case D3D12_FILTER_MINIMUM_MIN_MAG_MIP_POINT: return "MIN:MIN_MAG_MIP_POINT"; case D3D12_FILTER_MINIMUM_MIN_MAG_POINT_MIP_LINEAR: return "MIN:MIN_MAG_POINT_MIP_LINEAR"; case D3D12_FILTER_MINIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT: return "MIN:MIN_POINT_MAG_LINEAR_MIP_POINT"; case D3D12_FILTER_MINIMUM_MIN_POINT_MAG_MIP_LINEAR: return "MIN:MIN_POINT_MAG_MIP_LINEAR"; case D3D12_FILTER_MINIMUM_MIN_LINEAR_MAG_MIP_POINT: return "MIN:MIN_LINEAR_MAG_MIP_POINT"; case D3D12_FILTER_MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR: return "MIN:MIN_LINEAR_MAG_POINT_MIP_LINEAR"; case D3D12_FILTER_MINIMUM_MIN_MAG_LINEAR_MIP_POINT: return "MIN:MIN_MAG_LINEAR_MIP_POINT"; case D3D12_FILTER_MINIMUM_MIN_MAG_MIP_LINEAR: return "MIN:MIN_MAG_MIP_LINEAR"; case D3D12_FILTER_MINIMUM_ANISOTROPIC: return "MIN:ANISOTROPIC"; case D3D12_FILTER_MAXIMUM_MIN_MAG_MIP_POINT: return "MAX:MIN_MAG_MIP_POINT"; case D3D12_FILTER_MAXIMUM_MIN_MAG_POINT_MIP_LINEAR: return "MAX:MIN_MAG_POINT_MIP_LINEAR"; case D3D12_FILTER_MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT: return "MAX:MIN_POINT_MAG_LINEAR_MIP_POINT"; case D3D12_FILTER_MAXIMUM_MIN_POINT_MAG_MIP_LINEAR: return "MAX:MIN_POINT_MAG_MIP_LINEAR"; case D3D12_FILTER_MAXIMUM_MIN_LINEAR_MAG_MIP_POINT: return "MAX:MIN_LINEAR_MAG_MIP_POINT"; case D3D12_FILTER_MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR: return "MAX:MIN_LINEAR_MAG_POINT_MIP_LINEAR"; case D3D12_FILTER_MAXIMUM_MIN_MAG_LINEAR_MIP_POINT: return "MAX:MIN_MAG_LINEAR_MIP_POINT"; case D3D12_FILTER_MAXIMUM_MIN_MAG_MIP_LINEAR: return "MAX:MIN_MAG_MIP_LINEAR"; case D3D12_FILTER_MAXIMUM_ANISOTROPIC: return "MAX:ANISOTROPIC"; default: break; } return StringFormat::Fmt("D3D12_FILTER<%d>", el); } string ToStrHelper::Get(const D3D12_TEXTURE_ADDRESS_MODE &el) { switch(el) { case D3D12_TEXTURE_ADDRESS_MODE_WRAP: return "WRAP"; case D3D12_TEXTURE_ADDRESS_MODE_MIRROR: return "MIRROR"; case D3D12_TEXTURE_ADDRESS_MODE_CLAMP: return "CLAMP"; case D3D12_TEXTURE_ADDRESS_MODE_BORDER: return "BORDER"; case D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE: return "MIRROR_ONCE"; default: break; } // possible for unused fields via 0-initialisation if((int)el == 0) return "--"; return StringFormat::Fmt("D3D12_TEXTURE_ADDRESS_MODE<%d>", el); } string ToStrHelper::Get(const D3D12_BLEND &el) { switch(el) { case D3D12_BLEND_ZERO: return "ZERO"; case D3D12_BLEND_ONE: return "ONE"; case D3D12_BLEND_SRC_COLOR: return "SRC_COLOR"; case D3D12_BLEND_INV_SRC_COLOR: return "INV_SRC_COLOR"; case D3D12_BLEND_SRC_ALPHA: return "SRC_ALPHA"; case D3D12_BLEND_INV_SRC_ALPHA: return "INV_SRC_ALPHA"; case D3D12_BLEND_DEST_ALPHA: return "DEST_ALPHA"; case D3D12_BLEND_INV_DEST_ALPHA: return "INV_DEST_ALPHA"; case D3D12_BLEND_DEST_COLOR: return "DEST_COLOR"; case D3D12_BLEND_INV_DEST_COLOR: return "INV_DEST_COLOR"; case D3D12_BLEND_SRC_ALPHA_SAT: return "SRC_ALPHA_SAT"; case D3D12_BLEND_BLEND_FACTOR: return "BLEND_FACTOR"; case D3D12_BLEND_INV_BLEND_FACTOR: return "INV_BLEND_FACTOR"; case D3D12_BLEND_SRC1_COLOR: return "SRC1_COLOR"; case D3D12_BLEND_INV_SRC1_COLOR: return "INV_SRC1_COLOR"; case D3D12_BLEND_SRC1_ALPHA: return "SRC1_ALPHA"; case D3D12_BLEND_INV_SRC1_ALPHA: return "INV_SRC1_ALPHA"; default: break; } // possible for unused fields via 0-initialisation if((int)el == 0) return "--"; return StringFormat::Fmt("D3D12_BLEND<%d>", el); } string ToStrHelper::Get(const D3D12_BLEND_OP &el) { switch(el) { case D3D12_BLEND_OP_ADD: return "ADD"; case D3D12_BLEND_OP_SUBTRACT: return "SUBTRACT"; case D3D12_BLEND_OP_REV_SUBTRACT: return "REV_SUBTRACT"; case D3D12_BLEND_OP_MIN: return "MIN"; case D3D12_BLEND_OP_MAX: return "MAX"; default: break; } // possible for unused fields via 0-initialisation if((int)el == 0) return "--"; return StringFormat::Fmt("D3D12_BLEND_OP<%d>", el); } string ToStrHelper::Get(const D3D12_LOGIC_OP &el) { switch(el) { case D3D12_LOGIC_OP_CLEAR: return "CLEAR"; case D3D12_LOGIC_OP_SET: return "SET"; case D3D12_LOGIC_OP_COPY: return "COPY"; case D3D12_LOGIC_OP_COPY_INVERTED: return "COPY_INVERTED"; case D3D12_LOGIC_OP_NOOP: return "NOOP"; case D3D12_LOGIC_OP_INVERT: return "INVERT"; case D3D12_LOGIC_OP_AND: return "AND"; case D3D12_LOGIC_OP_NAND: return "NAND"; case D3D12_LOGIC_OP_OR: return "OR"; case D3D12_LOGIC_OP_NOR: return "NOR"; case D3D12_LOGIC_OP_XOR: return "XOR"; case D3D12_LOGIC_OP_EQUIV: return "EQUIV"; case D3D12_LOGIC_OP_AND_REVERSE: return "AND_REVERSE"; case D3D12_LOGIC_OP_AND_INVERTED: return "AND_INVERTED"; case D3D12_LOGIC_OP_OR_REVERSE: return "OR_REVERSE"; case D3D12_LOGIC_OP_OR_INVERTED: return "OR_INVERTED"; default: break; } return StringFormat::Fmt("D3D12_LOGIC_OP<%d>", el); } string ToStrHelper::Get(const D3D12_FILL_MODE &el) { switch(el) { case D3D12_FILL_MODE_WIREFRAME: return "WIREFRAME"; case D3D12_FILL_MODE_SOLID: return "SOLID"; default: break; } // possible for unused fields via 0-initialisation if((int)el == 0) return "--"; return StringFormat::Fmt("D3D12_FILL_MODE<%d>", el); } string ToStrHelper::Get(const D3D12_CULL_MODE &el) { switch(el) { case D3D12_CULL_MODE_NONE: return "NONE"; case D3D12_CULL_MODE_FRONT: return "FRONT"; case D3D12_CULL_MODE_BACK: return "BACK"; default: break; } // possible for unused fields via 0-initialisation if((int)el == 0) return "--"; return StringFormat::Fmt("D3D12_CULL_MODE<%d>", el); } string ToStrHelper::Get( const D3D12_CONSERVATIVE_RASTERIZATION_MODE &el) { switch(el) { TOSTR_CASE_STRINGIZE(D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF) TOSTR_CASE_STRINGIZE(D3D12_CONSERVATIVE_RASTERIZATION_MODE_ON) default: break; } return StringFormat::Fmt("D3D12_CONSERVATIVE_RASTERIZATION_MODE<%d>", el); } string ToStrHelper::Get(const D3D12_COMPARISON_FUNC &el) { switch(el) { case D3D12_COMPARISON_FUNC_NEVER: return "NEVER"; case D3D12_COMPARISON_FUNC_LESS: return "LESS"; case D3D12_COMPARISON_FUNC_EQUAL: return "EQUAL"; case D3D12_COMPARISON_FUNC_LESS_EQUAL: return "LESS_EQUAL"; case D3D12_COMPARISON_FUNC_GREATER: return "GREATER"; case D3D12_COMPARISON_FUNC_NOT_EQUAL: return "NOT_EQUAL"; case D3D12_COMPARISON_FUNC_GREATER_EQUAL: return "GREATER_EQUAL"; case D3D12_COMPARISON_FUNC_ALWAYS: return "ALWAYS"; default: break; } // possible for unused fields via 0-initialisation if((int)el == 0) return "--"; return StringFormat::Fmt("D3D12_COMPARISON_FUNC<%d>", el); } string ToStrHelper::Get(const D3D12_DEPTH_WRITE_MASK &el) { switch(el) { TOSTR_CASE_STRINGIZE(D3D12_DEPTH_WRITE_MASK_ZERO) TOSTR_CASE_STRINGIZE(D3D12_DEPTH_WRITE_MASK_ALL) default: break; } return StringFormat::Fmt("D3D12_DEPTH_WRITE_MASK<%d>", el); } string ToStrHelper::Get(const D3D12_STENCIL_OP &el) { switch(el) { case D3D12_STENCIL_OP_KEEP: return "KEEP"; case D3D12_STENCIL_OP_ZERO: return "ZERO"; case D3D12_STENCIL_OP_REPLACE: return "REPLACE"; case D3D12_STENCIL_OP_INCR_SAT: return "INCR_SAT"; case D3D12_STENCIL_OP_DECR_SAT: return "DECR_SAT"; case D3D12_STENCIL_OP_INVERT: return "INVERT"; case D3D12_STENCIL_OP_INCR: return "INCR"; case D3D12_STENCIL_OP_DECR: return "DECR"; default: break; } // possible for unused fields via 0-initialisation if((int)el == 0) return "--"; return StringFormat::Fmt("D3D12_STENCIL_OP<%d>", el); } string ToStrHelper::Get(const D3D12_INPUT_CLASSIFICATION &el) { switch(el) { TOSTR_CASE_STRINGIZE(D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA) TOSTR_CASE_STRINGIZE(D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA) default: break; } return StringFormat::Fmt("D3D12_INPUT_CLASSIFICATION<%d>", el); } string ToStrHelper::Get( const D3D12_INDEX_BUFFER_STRIP_CUT_VALUE &el) { switch(el) { TOSTR_CASE_STRINGIZE(D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED) TOSTR_CASE_STRINGIZE(D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF) TOSTR_CASE_STRINGIZE(D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF) default: break; } return StringFormat::Fmt("D3D12_INDEX_BUFFER_STRIP_CUT_VALUE<%d>", el); } string ToStrHelper::Get(const D3D12_PRIMITIVE_TOPOLOGY_TYPE &el) { switch(el) { TOSTR_CASE_STRINGIZE(D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED) TOSTR_CASE_STRINGIZE(D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT) TOSTR_CASE_STRINGIZE(D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE) TOSTR_CASE_STRINGIZE(D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE) TOSTR_CASE_STRINGIZE(D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH) default: break; } return StringFormat::Fmt("D3D12_PRIMITIVE_TOPOLOGY_TYPE<%d>", el); } string ToStrHelper::Get(const D3D12_INDIRECT_ARGUMENT_TYPE &el) { switch(el) { TOSTR_CASE_STRINGIZE(D3D12_INDIRECT_ARGUMENT_TYPE_DRAW) TOSTR_CASE_STRINGIZE(D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED) TOSTR_CASE_STRINGIZE(D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH) TOSTR_CASE_STRINGIZE(D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW) TOSTR_CASE_STRINGIZE(D3D12_INDIRECT_ARGUMENT_TYPE_INDEX_BUFFER_VIEW) TOSTR_CASE_STRINGIZE(D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT) TOSTR_CASE_STRINGIZE(D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT_BUFFER_VIEW) TOSTR_CASE_STRINGIZE(D3D12_INDIRECT_ARGUMENT_TYPE_SHADER_RESOURCE_VIEW) TOSTR_CASE_STRINGIZE(D3D12_INDIRECT_ARGUMENT_TYPE_UNORDERED_ACCESS_VIEW) default: break; } return StringFormat::Fmt("D3D12_INDIRECT_ARGUMENT_TYPE<%d>", el); } string ToStrHelper::Get(const D3D12_COMMAND_LIST_TYPE &el) { switch(el) { TOSTR_CASE_STRINGIZE(D3D12_COMMAND_LIST_TYPE_DIRECT) TOSTR_CASE_STRINGIZE(D3D12_COMMAND_LIST_TYPE_BUNDLE) TOSTR_CASE_STRINGIZE(D3D12_COMMAND_LIST_TYPE_COMPUTE) TOSTR_CASE_STRINGIZE(D3D12_COMMAND_LIST_TYPE_COPY) default: break; } return StringFormat::Fmt("D3D12_COMMAND_LIST_TYPE<%d>", el); } string ToStrHelper::Get(const D3D12_TEXTURE_COPY_TYPE &el) { switch(el) { TOSTR_CASE_STRINGIZE(D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX) TOSTR_CASE_STRINGIZE(D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT) default: break; } return StringFormat::Fmt("D3D12_TEXTURE_COPY_TYPE<%d>", el); } string ToStrHelper::Get(const D3D12_RESOURCE_DIMENSION &el) { switch(el) { TOSTR_CASE_STRINGIZE(D3D12_RESOURCE_DIMENSION_UNKNOWN) TOSTR_CASE_STRINGIZE(D3D12_RESOURCE_DIMENSION_BUFFER) TOSTR_CASE_STRINGIZE(D3D12_RESOURCE_DIMENSION_TEXTURE1D) TOSTR_CASE_STRINGIZE(D3D12_RESOURCE_DIMENSION_TEXTURE2D) TOSTR_CASE_STRINGIZE(D3D12_RESOURCE_DIMENSION_TEXTURE3D) default: break; } return StringFormat::Fmt("D3D12_RESOURCE_DIMENSION<%d>", el); } string ToStrHelper::Get(const D3D12_TEXTURE_LAYOUT &el) { switch(el) { TOSTR_CASE_STRINGIZE(D3D12_TEXTURE_LAYOUT_UNKNOWN) TOSTR_CASE_STRINGIZE(D3D12_TEXTURE_LAYOUT_ROW_MAJOR) TOSTR_CASE_STRINGIZE(D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE) TOSTR_CASE_STRINGIZE(D3D12_TEXTURE_LAYOUT_64KB_STANDARD_SWIZZLE) default: break; } return StringFormat::Fmt("D3D12_TEXTURE_LAYOUT<%d>", el); } string ToStrHelper::Get(const D3D12_CLEAR_FLAGS &el) { string ret; if(el & D3D12_CLEAR_FLAG_DEPTH) ret += " | D3D12_CLEAR_FLAG_DEPTH"; if(el & D3D12_CLEAR_FLAG_STENCIL) ret += " | D3D12_CLEAR_FLAG_STENCIL"; if(!ret.empty()) ret = ret.substr(3); return ret; } string ToStrHelper::Get(const D3D12_BUFFER_SRV_FLAGS &el) { string ret; if(el == D3D12_BUFFER_SRV_FLAG_NONE) return "D3D12_BUFFER_SRV_FLAG_NONE"; if(el & D3D12_BUFFER_SRV_FLAG_RAW) ret += " | D3D12_BUFFER_SRV_FLAG_RAW"; if(!ret.empty()) ret = ret.substr(3); return ret; } string ToStrHelper::Get(const D3D12_DSV_FLAGS &el) { string ret; if(el == D3D12_DSV_FLAG_NONE) return "D3D12_DSV_FLAG_NONE"; if(el & D3D12_DSV_FLAG_READ_ONLY_DEPTH) ret += " | D3D12_DSV_FLAG_READ_ONLY_DEPTH"; if(el & D3D12_DSV_FLAG_READ_ONLY_STENCIL) ret += " | D3D12_DSV_FLAG_READ_ONLY_STENCIL"; if(!ret.empty()) ret = ret.substr(3); return ret; } string ToStrHelper::Get(const D3D12_BUFFER_UAV_FLAGS &el) { string ret; if(el == D3D12_BUFFER_UAV_FLAG_NONE) return "D3D12_BUFFER_UAV_FLAG_NONE"; if(el & D3D12_BUFFER_UAV_FLAG_RAW) ret += " | D3D12_BUFFER_UAV_FLAG_RAW"; if(!ret.empty()) ret = ret.substr(3); return ret; } string ToStrHelper::Get(const D3D12_HEAP_FLAGS &el) { string ret; if(el == D3D12_HEAP_FLAG_NONE) return "D3D12_HEAP_FLAG_NONE"; if(el & D3D12_HEAP_FLAG_SHARED) ret += " | D3D12_HEAP_FLAG_SHARED"; if(el & D3D12_HEAP_FLAG_DENY_BUFFERS) ret += " | D3D12_HEAP_FLAG_DENY_BUFFERS"; if(el & D3D12_HEAP_FLAG_ALLOW_DISPLAY) ret += " | D3D12_HEAP_FLAG_ALLOW_DISPLAY"; if(el & D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER) ret += " | D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER"; if(el & D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES) ret += " | D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES"; if(el & D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES) ret += " | D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES"; if(el & D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES) ret += " | D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES"; if(el & D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS) ret += " | D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS"; if(el & D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES) ret += " | D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES"; if(el & D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES) ret += " | D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES"; if(!ret.empty()) ret = ret.substr(3); return ret; } string ToStrHelper::Get(const D3D12_FENCE_FLAGS &el) { string ret; if(el == D3D12_FENCE_FLAG_NONE) return "D3D12_FENCE_FLAG_NONE"; if(el & D3D12_FENCE_FLAG_SHARED) ret += " | D3D12_FENCE_FLAG_SHARED"; if(el & D3D12_FENCE_FLAG_SHARED_CROSS_ADAPTER) ret += " | D3D12_FENCE_FLAG_SHARED_CROSS_ADAPTER"; if(!ret.empty()) ret = ret.substr(3); return ret; } string ToStrHelper::Get(const D3D12_DESCRIPTOR_HEAP_FLAGS &el) { string ret; if(el == D3D12_DESCRIPTOR_HEAP_FLAG_NONE) return "D3D12_DESCRIPTOR_HEAP_FLAG_NONE"; if(el & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE) ret += " | D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE"; if(!ret.empty()) ret = ret.substr(3); return ret; } string ToStrHelper::Get(const D3D12_RESOURCE_BARRIER_FLAGS &el) { string ret; if(el == D3D12_RESOURCE_BARRIER_FLAG_NONE) return "D3D12_RESOURCE_BARRIER_FLAG_NONE"; if(el & D3D12_RESOURCE_BARRIER_FLAG_BEGIN_ONLY) ret += " | D3D12_RESOURCE_BARRIER_FLAG_BEGIN_ONLY"; if(el & D3D12_RESOURCE_BARRIER_FLAG_END_ONLY) ret += " | D3D12_RESOURCE_BARRIER_FLAG_END_ONLY"; if(!ret.empty()) ret = ret.substr(3); return ret; } string ToStrHelper::Get(const D3D12_RESOURCE_STATES &el) { string ret; if(el == D3D12_RESOURCE_STATE_COMMON) return "COMMON/PRESENT"; if(el == D3D12_RESOURCE_STATE_GENERIC_READ) return "GENERIC_READ"; if(el & D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER) ret += " | VB & CB"; if(el & D3D12_RESOURCE_STATE_INDEX_BUFFER) ret += " | IB"; if(el & D3D12_RESOURCE_STATE_RENDER_TARGET) ret += " | RTV"; if(el & D3D12_RESOURCE_STATE_UNORDERED_ACCESS) ret += " | UAV"; if(el & D3D12_RESOURCE_STATE_DEPTH_WRITE) ret += " | DSV Write"; if(el & D3D12_RESOURCE_STATE_DEPTH_READ) ret += " | DSV Read"; if(el & D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE) ret += " | SRV (Non-Pixel)"; if(el & D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE) ret += " | SRV (Pixel)"; if(el & D3D12_RESOURCE_STATE_STREAM_OUT) ret += " | Stream Out"; if(el & D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT) ret += " | Indirect"; if(el & D3D12_RESOURCE_STATE_COPY_DEST) ret += " | Copy (Dst)"; if(el & D3D12_RESOURCE_STATE_COPY_SOURCE) ret += " | Copy (Src)"; if(el & D3D12_RESOURCE_STATE_RESOLVE_DEST) ret += " | Resolve (Dst)"; if(el & D3D12_RESOURCE_STATE_RESOLVE_SOURCE) ret += " | Resolve (Src)"; if(el & D3D12_RESOURCE_STATE_PREDICATION) ret += " | Predication"; if(!ret.empty()) ret = ret.substr(3); return ret; } string ToStrHelper::Get(const D3D12_PIPELINE_STATE_FLAGS &el) { string ret; if(el == D3D12_PIPELINE_STATE_FLAG_NONE) return "D3D12_PIPELINE_STATE_FLAG_NONE"; if(el & D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG) ret += " | D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG"; if(!ret.empty()) ret = ret.substr(3); return ret; } string ToStrHelper::Get(const D3D12_RESOURCE_FLAGS &el) { string ret; if(el == D3D12_RESOURCE_FLAG_NONE) return "D3D12_RESOURCE_FLAG_NONE"; if(el & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET) ret += " | D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET"; if(el & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL) ret += " | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL"; if(el & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS) ret += " | D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS"; if(el & D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE) ret += " | D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE"; if(el & D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER) ret += " | D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER"; if(el & D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS) ret += " | D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS"; if(!ret.empty()) ret = ret.substr(3); return ret; } string ToStrHelper::Get(const D3D12_COMMAND_QUEUE_FLAGS &el) { string ret; if(el == D3D12_COMMAND_QUEUE_FLAG_NONE) return "D3D12_COMMAND_QUEUE_FLAG_NONE"; if(el & D3D12_COMMAND_QUEUE_FLAG_DISABLE_GPU_TIMEOUT) ret += " | D3D12_COMMAND_QUEUE_FLAG_DISABLE_GPU_TIMEOUT"; if(!ret.empty()) ret = ret.substr(3); return ret; }