diff --git a/renderdoc/api/replay/d3d12_pipestate.h b/renderdoc/api/replay/d3d12_pipestate.h index d1e999700..f333cdb18 100644 --- a/renderdoc/api/replay/d3d12_pipestate.h +++ b/renderdoc/api/replay/d3d12_pipestate.h @@ -75,8 +75,8 @@ struct D3D12PipelineState struct ShaderStage { - ShaderStage() : Present(false), ShaderDetails(NULL), stage(eShaderStage_Vertex) {} - bool32 Present; + ShaderStage() : ShaderDetails(NULL), stage(eShaderStage_Vertex) {} + ResourceId Shader; ShaderReflection *ShaderDetails; ShaderBindpointMapping BindpointMapping; diff --git a/renderdoc/driver/d3d12/d3d12_common.cpp b/renderdoc/driver/d3d12/d3d12_common.cpp index c2fcc26b2..70c6a4bf4 100644 --- a/renderdoc/driver/d3d12/d3d12_common.cpp +++ b/renderdoc/driver/d3d12/d3d12_common.cpp @@ -28,6 +28,10 @@ #include "d3d12_manager.h" #include "d3d12_resources.h" +void MakeShaderReflection(DXBC::DXBCFile *dxbc, ShaderReflection *refl, + ShaderBindpointMapping *mapping) +{ +} enum D3D12ResourceBarrierSubresource { D3D12AllSubresources = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES diff --git a/renderdoc/driver/d3d12/d3d12_common.h b/renderdoc/driver/d3d12/d3d12_common.h index 5ad4d39d9..c34b3e59d 100644 --- a/renderdoc/driver/d3d12/d3d12_common.h +++ b/renderdoc/driver/d3d12/d3d12_common.h @@ -33,7 +33,8 @@ #include "driver/shaders/dxbc/dxbc_compile.h" #include "serialise/serialiser.h" -ShaderReflection *MakeShaderReflection(DXBC::DXBCFile *dxbc); +void MakeShaderReflection(DXBC::DXBCFile *dxbc, ShaderReflection *refl, + ShaderBindpointMapping *mapping); // similar to RDCUNIMPLEMENTED but for things that are hit often so we don't want to fire the // debugbreak. diff --git a/renderdoc/driver/d3d12/d3d12_device_wrap.cpp b/renderdoc/driver/d3d12/d3d12_device_wrap.cpp index 3829e9284..4e02b8c24 100644 --- a/renderdoc/driver/d3d12/d3d12_device_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_device_wrap.cpp @@ -290,22 +290,9 @@ bool WrappedID3D12Device::Serialise_CreateGraphicsPipelineState( for(size_t i = 0; i < ARRAY_COUNT(shaders); i++) { if(shaders[i]->BytecodeLength == 0) - { shaders[i]->pShaderBytecode = NULL; - } else - { - WrappedID3D12PipelineState::DXBCKey *key = - new WrappedID3D12PipelineState::DXBCKey(*shaders[i]); - - if(WrappedID3D12PipelineState::m_Shaders[*key] == NULL) - WrappedID3D12PipelineState::m_Shaders[*key] = - new WrappedID3D12PipelineState::ShaderEntry(*shaders[i]); - else - WrappedID3D12PipelineState::m_Shaders[*key]->AddRef(); - - shaders[i]->pShaderBytecode = key; - } + shaders[i]->pShaderBytecode = WrappedID3D12PipelineState::AddShader(*shaders[i], this); } GetResourceManager()->AddLiveResource(Pipe, ret); @@ -380,22 +367,11 @@ bool WrappedID3D12Device::Serialise_CreateComputePipelineState( } else { - ret = new WrappedID3D12PipelineState(ret, this); + WrappedID3D12PipelineState *wrapped = new WrappedID3D12PipelineState(ret, this); + ret = wrapped; - WrappedID3D12PipelineState *wrapped = (WrappedID3D12PipelineState *)ret; - - wrapped->compute = new D3D12_COMPUTE_PIPELINE_STATE_DESC(Descriptor); - - WrappedID3D12PipelineState::DXBCKey *key = - new WrappedID3D12PipelineState::DXBCKey(wrapped->compute->CS); - - if(WrappedID3D12PipelineState::m_Shaders[*key] == NULL) - WrappedID3D12PipelineState::m_Shaders[*key] = - new WrappedID3D12PipelineState::ShaderEntry(wrapped->compute->CS); - else - WrappedID3D12PipelineState::m_Shaders[*key]->AddRef(); - - wrapped->compute->CS.pShaderBytecode = key; + wrapped->compute->CS.pShaderBytecode = + WrappedID3D12PipelineState::AddShader(wrapped->compute->CS, this); GetResourceManager()->AddLiveResource(Pipe, ret); } diff --git a/renderdoc/driver/d3d12/d3d12_replay.cpp b/renderdoc/driver/d3d12/d3d12_replay.cpp index 80b1dfc6c..e3ed008f5 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.cpp +++ b/renderdoc/driver/d3d12/d3d12_replay.cpp @@ -198,6 +198,17 @@ FetchTexture D3D12Replay::GetTexture(ResourceId id) return ret; } +ShaderReflection *D3D12Replay::GetShader(ResourceId shader, string entryPoint) +{ + WrappedID3D12PipelineState::ShaderEntry *sh = + m_pDevice->GetResourceManager()->GetCurrentAs(shader); + + if(sh) + return &sh->GetDetails(); + + return NULL; +} + void D3D12Replay::FreeTargetResource(ResourceId id) { if(m_pDevice->GetResourceManager()->HasLiveResource(id)) @@ -233,6 +244,834 @@ vector D3D12Replay::GetUsage(ResourceId id) return m_pDevice->GetQueue()->GetUsage(id); } +void D3D12Replay::FillResourceView(D3D12PipelineState::ResourceView &view, + const PortableHandle &resHandle) +{ + 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"); + return; + } + + view.Resource = rm->GetOriginalID(GetResID(desc->nonsamp.resource)); + + if(view.Resource == ResourceId()) + return; + + D3D12_RESOURCE_DESC res = desc->nonsamp.resource->GetDesc(); + + { + DXGI_FORMAT fmt = DXGI_FORMAT_UNKNOWN; + + if(desc->GetType() == D3D12Descriptor::TypeRTV) + fmt = desc->nonsamp.rtv.Format; + else if(desc->GetType() == D3D12Descriptor::TypeSRV) + fmt = desc->nonsamp.srv.Format; + else if(desc->GetType() == D3D12Descriptor::TypeUAV) + fmt = (DXGI_FORMAT)desc->nonsamp.uav.desc.Format; + + if(fmt == DXGI_FORMAT_UNKNOWN) + fmt = res.Format; + + view.ElementSize = fmt == DXGI_FORMAT_UNKNOWN ? 1 : GetByteSize(1, 1, 1, fmt, 0); + + view.Format = MakeResourceFormat(fmt); + + if(desc->GetType() == D3D12Descriptor::TypeRTV) + { + view.Type = ToStr::Get(desc->nonsamp.rtv.ViewDimension); + + if(desc->nonsamp.rtv.ViewDimension == D3D12_RTV_DIMENSION_BUFFER) + { + view.FirstElement = desc->nonsamp.rtv.Buffer.FirstElement; + view.NumElements = desc->nonsamp.rtv.Buffer.NumElements; + } + else if(desc->nonsamp.rtv.ViewDimension == D3D12_RTV_DIMENSION_TEXTURE1D) + { + view.HighestMip = desc->nonsamp.rtv.Texture1D.MipSlice; + } + else if(desc->nonsamp.rtv.ViewDimension == D3D12_RTV_DIMENSION_TEXTURE1DARRAY) + { + view.ArraySize = desc->nonsamp.rtv.Texture1DArray.ArraySize; + view.FirstArraySlice = desc->nonsamp.rtv.Texture1DArray.FirstArraySlice; + view.HighestMip = desc->nonsamp.rtv.Texture1DArray.MipSlice; + } + else if(desc->nonsamp.rtv.ViewDimension == D3D12_RTV_DIMENSION_TEXTURE2D) + { + view.HighestMip = desc->nonsamp.rtv.Texture2D.MipSlice; + } + else if(desc->nonsamp.rtv.ViewDimension == D3D12_RTV_DIMENSION_TEXTURE2DARRAY) + { + view.ArraySize = desc->nonsamp.rtv.Texture2DArray.ArraySize; + view.FirstArraySlice = desc->nonsamp.rtv.Texture2DArray.FirstArraySlice; + view.HighestMip = desc->nonsamp.rtv.Texture2DArray.MipSlice; + } + else if(desc->nonsamp.rtv.ViewDimension == D3D12_RTV_DIMENSION_TEXTURE2DMS) + { + } + else if(desc->nonsamp.rtv.ViewDimension == D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY) + { + view.ArraySize = desc->nonsamp.rtv.Texture2DMSArray.ArraySize; + view.FirstArraySlice = desc->nonsamp.rtv.Texture2DArray.FirstArraySlice; + } + else if(desc->nonsamp.rtv.ViewDimension == D3D12_RTV_DIMENSION_TEXTURE3D) + { + view.ArraySize = desc->nonsamp.rtv.Texture3D.WSize; + view.FirstArraySlice = desc->nonsamp.rtv.Texture3D.FirstWSlice; + view.HighestMip = desc->nonsamp.rtv.Texture3D.MipSlice; + } + } + else if(desc->GetType() == D3D12Descriptor::TypeDSV) + { + view.Type = ToStr::Get(desc->nonsamp.dsv.ViewDimension); + + if(desc->nonsamp.dsv.ViewDimension == D3D12_DSV_DIMENSION_TEXTURE1D) + { + view.HighestMip = desc->nonsamp.dsv.Texture1D.MipSlice; + } + else if(desc->nonsamp.dsv.ViewDimension == D3D12_DSV_DIMENSION_TEXTURE1DARRAY) + { + view.ArraySize = desc->nonsamp.dsv.Texture1DArray.ArraySize; + view.FirstArraySlice = desc->nonsamp.dsv.Texture1DArray.FirstArraySlice; + view.HighestMip = desc->nonsamp.dsv.Texture1DArray.MipSlice; + } + else if(desc->nonsamp.dsv.ViewDimension == D3D12_DSV_DIMENSION_TEXTURE2D) + { + view.HighestMip = desc->nonsamp.dsv.Texture2D.MipSlice; + } + else if(desc->nonsamp.dsv.ViewDimension == D3D12_DSV_DIMENSION_TEXTURE2DARRAY) + { + view.ArraySize = desc->nonsamp.dsv.Texture2DArray.ArraySize; + view.FirstArraySlice = desc->nonsamp.dsv.Texture2DArray.FirstArraySlice; + view.HighestMip = desc->nonsamp.dsv.Texture2DArray.MipSlice; + } + else if(desc->nonsamp.dsv.ViewDimension == D3D12_DSV_DIMENSION_TEXTURE2DMS) + { + } + else if(desc->nonsamp.dsv.ViewDimension == D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY) + { + view.ArraySize = desc->nonsamp.dsv.Texture2DMSArray.ArraySize; + view.FirstArraySlice = desc->nonsamp.dsv.Texture2DArray.FirstArraySlice; + } + } + else if(desc->GetType() == D3D12Descriptor::TypeSRV) + { + view.Type = ToStr::Get(desc->nonsamp.srv.ViewDimension); + + view.swizzle[0] = (TextureSwizzle)D3D12_DECODE_SHADER_4_COMPONENT_MAPPING( + 0, desc->nonsamp.srv.Shader4ComponentMapping); + view.swizzle[1] = (TextureSwizzle)D3D12_DECODE_SHADER_4_COMPONENT_MAPPING( + 1, desc->nonsamp.srv.Shader4ComponentMapping); + view.swizzle[2] = (TextureSwizzle)D3D12_DECODE_SHADER_4_COMPONENT_MAPPING( + 2, desc->nonsamp.srv.Shader4ComponentMapping); + view.swizzle[3] = (TextureSwizzle)D3D12_DECODE_SHADER_4_COMPONENT_MAPPING( + 3, desc->nonsamp.srv.Shader4ComponentMapping); + + if(desc->nonsamp.srv.ViewDimension == D3D12_SRV_DIMENSION_BUFFER) + { + view.FirstElement = desc->nonsamp.srv.Buffer.FirstElement; + view.NumElements = desc->nonsamp.srv.Buffer.NumElements; + + view.BufferFlags = desc->nonsamp.srv.Buffer.Flags; + view.ElementSize = desc->nonsamp.srv.Buffer.StructureByteStride; + } + else if(desc->nonsamp.srv.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE1D) + { + view.HighestMip = desc->nonsamp.srv.Texture1D.MostDetailedMip; + view.NumMipLevels = desc->nonsamp.srv.Texture1D.MipLevels; + view.MinLODClamp = desc->nonsamp.srv.Texture1D.ResourceMinLODClamp; + } + else if(desc->nonsamp.srv.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE1DARRAY) + { + view.ArraySize = desc->nonsamp.srv.Texture1DArray.ArraySize; + view.FirstArraySlice = desc->nonsamp.srv.Texture1DArray.FirstArraySlice; + view.HighestMip = desc->nonsamp.srv.Texture1DArray.MostDetailedMip; + view.NumMipLevels = desc->nonsamp.srv.Texture1DArray.MipLevels; + view.MinLODClamp = desc->nonsamp.srv.Texture1DArray.ResourceMinLODClamp; + } + else if(desc->nonsamp.srv.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2D) + { + view.HighestMip = desc->nonsamp.srv.Texture2D.MostDetailedMip; + view.NumMipLevels = desc->nonsamp.srv.Texture2D.MipLevels; + view.MinLODClamp = desc->nonsamp.srv.Texture2D.ResourceMinLODClamp; + } + else if(desc->nonsamp.srv.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2DARRAY) + { + view.ArraySize = desc->nonsamp.srv.Texture2DArray.ArraySize; + view.FirstArraySlice = desc->nonsamp.srv.Texture2DArray.FirstArraySlice; + view.HighestMip = desc->nonsamp.srv.Texture2DArray.MostDetailedMip; + view.NumMipLevels = desc->nonsamp.srv.Texture2DArray.MipLevels; + view.MinLODClamp = desc->nonsamp.srv.Texture2DArray.ResourceMinLODClamp; + } + else if(desc->nonsamp.srv.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2DMS) + { + } + else if(desc->nonsamp.srv.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY) + { + view.ArraySize = desc->nonsamp.srv.Texture2DMSArray.ArraySize; + view.FirstArraySlice = desc->nonsamp.srv.Texture2DMSArray.FirstArraySlice; + } + else if(desc->nonsamp.srv.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE3D) + { + view.HighestMip = desc->nonsamp.srv.Texture3D.MostDetailedMip; + view.NumMipLevels = desc->nonsamp.srv.Texture3D.MipLevels; + view.MinLODClamp = desc->nonsamp.srv.Texture3D.ResourceMinLODClamp; + } + } + else if(desc->GetType() == D3D12Descriptor::TypeUAV) + { + D3D12_UNORDERED_ACCESS_VIEW_DESC uav = desc->nonsamp.uav.desc.AsDesc(); + + view.CounterResource = rm->GetOriginalID(GetResID(desc->nonsamp.uav.counterResource)); + + view.Type = ToStr::Get(uav.ViewDimension); + + if(uav.ViewDimension == D3D12_UAV_DIMENSION_BUFFER) + { + view.FirstElement = uav.Buffer.FirstElement; + view.NumElements = uav.Buffer.NumElements; + + view.BufferFlags = uav.Buffer.Flags; + view.ElementSize = uav.Buffer.StructureByteStride; + + view.CounterByteOffset = uav.Buffer.CounterOffsetInBytes; + } + else if(uav.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE1D) + { + view.HighestMip = uav.Texture1D.MipSlice; + } + else if(uav.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE1DARRAY) + { + view.ArraySize = uav.Texture1DArray.ArraySize; + view.FirstArraySlice = uav.Texture1DArray.FirstArraySlice; + view.HighestMip = uav.Texture1DArray.MipSlice; + } + else if(uav.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE2D) + { + view.HighestMip = uav.Texture2D.MipSlice; + } + else if(uav.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE2DARRAY) + { + view.ArraySize = uav.Texture2DArray.ArraySize; + view.FirstArraySlice = uav.Texture2DArray.FirstArraySlice; + view.HighestMip = uav.Texture2DArray.MipSlice; + } + else if(uav.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE3D) + { + view.ArraySize = uav.Texture3D.WSize; + view.FirstArraySlice = uav.Texture3D.FirstWSlice; + view.HighestMip = uav.Texture3D.MipSlice; + } + } + } +} + +void D3D12Replay::MakePipelineState() +{ + const D3D12RenderState &rs = m_pDevice->GetQueue()->GetCommandData()->m_RenderState; + + D3D12PipelineState &state = m_PipelineState; + + ///////////////////////////////////////////////// + // Input Assembler + ///////////////////////////////////////////////// + + D3D12ResourceManager *rm = m_pDevice->GetResourceManager(); + + state.pipeline = rm->GetOriginalID(rs.pipe); + + state.customName = true; + string str = m_pDevice->GetResourceName(rs.pipe); + + WrappedID3D12PipelineState *pipe = NULL; + + if(rs.pipe != ResourceId()) + pipe = rm->GetCurrentAs(rs.pipe); + + if(str == "") + { + state.customName = false; + + if(pipe) + str = StringFormat::Fmt(pipe->IsGraphics() ? "Graphics Pipe %llu" : "Compute Pipe %llu", + state.pipeline); + else + str = "Unbound"; + } + + state.PipelineName = str; + + if(pipe && pipe->IsGraphics()) + { + const D3D12_INPUT_ELEMENT_DESC *inputEl = pipe->graphics->InputLayout.pInputElementDescs; + UINT numInput = pipe->graphics->InputLayout.NumElements; + + create_array_uninit(state.m_IA.layouts, numInput); + for(UINT i = 0; i < numInput; i++) + { + D3D12PipelineState::InputAssembler::LayoutInput &l = state.m_IA.layouts[i]; + + l.ByteOffset = inputEl[i].AlignedByteOffset; + l.Format = MakeResourceFormat(inputEl[i].Format); + l.InputSlot = inputEl[i].InputSlot; + l.PerInstance = inputEl[i].InputSlotClass == D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA; + l.InstanceDataStepRate = inputEl[i].InstanceDataStepRate; + l.SemanticIndex = inputEl[i].SemanticIndex; + l.SemanticName = inputEl[i].SemanticName; + } + + state.m_IA.indexStripCutValue = 0; + switch(pipe->graphics->IBStripCutValue) + { + case D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF: state.m_IA.indexStripCutValue = 0xFFFF; break; + case D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF: + state.m_IA.indexStripCutValue = 0xFFFFFFFF; + break; + default: break; + } + + create_array_uninit(state.m_IA.vbuffers, rs.vbuffers.size()); + for(size_t i = 0; i < rs.vbuffers.size(); i++) + { + D3D12PipelineState::InputAssembler::VertexBuffer &vb = state.m_IA.vbuffers[i]; + + vb.Buffer = rm->GetOriginalID(rs.vbuffers[i].buf); + vb.Offset = rs.vbuffers[i].offs; + vb.Size = rs.vbuffers[i].size; + vb.Stride = rs.vbuffers[i].stride; + } + + state.m_IA.ibuffer.Buffer = rm->GetOriginalID(rs.ibuffer.buf); + state.m_IA.ibuffer.Offset = rs.ibuffer.offs; + state.m_IA.ibuffer.Size = rs.ibuffer.size; + } + + ///////////////////////////////////////////////// + // Shaders + ///////////////////////////////////////////////// + + ResourceId rootSig; + + if(pipe && pipe->IsCompute()) + { + WrappedID3D12PipelineState::ShaderEntry *sh = + (WrappedID3D12PipelineState::ShaderEntry *)pipe->compute->CS.pShaderBytecode; + + state.m_CS.Shader = sh->GetResourceID(); + state.m_CS.stage = eShaderStage_Compute; + + rootSig = rs.compute.rootsig; + } + else if(pipe) + { + D3D12PipelineState::ShaderStage *dstArr[] = {&state.m_VS, &state.m_HS, &state.m_DS, &state.m_GS, + &state.m_PS}; + + D3D12_SHADER_BYTECODE *srcArr[] = {&pipe->graphics->VS, &pipe->graphics->HS, &pipe->graphics->DS, + &pipe->graphics->GS, &pipe->graphics->PS}; + + for(size_t stage = 0; stage < 5; stage++) + { + D3D12PipelineState::ShaderStage &dst = *dstArr[stage]; + D3D12_SHADER_BYTECODE &src = *srcArr[stage]; + + dst.stage = (ShaderStageType)stage; + + WrappedID3D12PipelineState::ShaderEntry *sh = + (WrappedID3D12PipelineState::ShaderEntry *)src.pShaderBytecode; + + if(sh) + { + dst.Shader = sh->GetResourceID(); + dst.BindpointMapping = sh->GetMapping(); + } + } + + rootSig = rs.graphics.rootsig; + } + +#if 0 + { + D3D11PipelineState::ShaderStage &dst = *dstArr[stage]; + const D3D11RenderState::shader &src = *srcArr[stage]; + + dst.stage = (ShaderStageType)stage; + + 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()) + { + dst.customName = false; + str = StringFormat::Fmt("%s Shader %llu", stageNames[stage], dst.Shader); + } + + dst.ShaderName = str; + + // 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++) + { + // 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; + } + + 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()) + { + samp.SamplerName = GetDebugName(src.Samplers[s]); + samp.customSamplerName = true; + + if(samp.SamplerName.count == 0) + { + samp.customSamplerName = false; + samp.SamplerName = StringFormat::Fmt("Sampler %llu", samp.Samp); + } + + 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++) + { + D3D11PipelineState::ShaderStage::ResourceView &view = dst.SRVs[s]; + + view.View = rm->GetOriginalID(GetIDForResource(src.SRVs[s])); + + if(view.View != ResourceId()) + { + 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); + } + } + + 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++) + { + 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); + } + } + } +#endif + + if(pipe && pipe->IsGraphics()) + { + ///////////////////////////////////////////////// + // Stream Out + ///////////////////////////////////////////////// + + create_array_uninit(state.m_SO.Outputs, rs.streamouts.size()); + for(size_t s = 0; s < rs.streamouts.size(); s++) + { + state.m_SO.Outputs[s].Buffer = rm->GetOriginalID(rs.streamouts[s].buf); + state.m_SO.Outputs[s].Offset = rs.streamouts[s].offs; + state.m_SO.Outputs[s].Size = rs.streamouts[s].size; + + state.m_SO.Outputs[s].WrittenCountBuffer = rm->GetOriginalID(rs.streamouts[s].countbuf); + state.m_SO.Outputs[s].WrittenCountOffset = rs.streamouts[s].countoffs; + } + + ///////////////////////////////////////////////// + // Rasterizer + ///////////////////////////////////////////////// + + state.m_RS.SampleMask = pipe->graphics->SampleMask; + + { + D3D12PipelineState::Rasterizer::RasterizerState &dst = state.m_RS.m_State; + D3D12_RASTERIZER_DESC &src = pipe->graphics->RasterizerState; + + dst.AntialiasedLineEnable = src.AntialiasedLineEnable == TRUE; + + dst.CullMode = eCull_None; + if(src.CullMode == D3D12_CULL_MODE_FRONT) + dst.CullMode = eCull_Front; + if(src.CullMode == D3D12_CULL_MODE_BACK) + dst.CullMode = eCull_Back; + + dst.FillMode = eFill_Solid; + if(src.FillMode == D3D12_FILL_MODE_WIREFRAME) + dst.FillMode = eFill_Wireframe; + + dst.DepthBias = src.DepthBias; + dst.DepthBiasClamp = src.DepthBiasClamp; + dst.DepthClip = src.DepthClipEnable == TRUE; + dst.FrontCCW = src.FrontCounterClockwise == TRUE; + dst.MultisampleEnable = src.MultisampleEnable == TRUE; + dst.SlopeScaledDepthBias = src.SlopeScaledDepthBias; + dst.ForcedSampleCount = src.ForcedSampleCount; + dst.ConservativeRasterization = + src.ConservativeRaster == D3D12_CONSERVATIVE_RASTERIZATION_MODE_ON; + } + + size_t i = 0; + create_array_uninit(state.m_RS.Scissors, + D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE); + for(i = 0; i < rs.scissors.size(); i++) + state.m_RS.Scissors[i] = D3D12PipelineState::Rasterizer::Scissor( + rs.scissors[i].left, rs.scissors[i].top, rs.scissors[i].right, rs.scissors[i].bottom); + + for(; i < D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; i++) + state.m_RS.Scissors[i] = D3D12PipelineState::Rasterizer::Scissor(0, 0, 0, 0); + + create_array_uninit(state.m_RS.Viewports, + D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE); + for(i = 0; i < rs.views.size(); i++) + state.m_RS.Viewports[i] = D3D12PipelineState::Rasterizer::Viewport( + rs.views[i].TopLeftX, rs.views[i].TopLeftY, rs.views[i].Width, rs.views[i].Height, + rs.views[i].MinDepth, rs.views[i].MaxDepth); + + for(; i < D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; i++) + state.m_RS.Viewports[i] = D3D12PipelineState::Rasterizer::Viewport(0, 0, 0, 0, 0, 0); + + ///////////////////////////////////////////////// + // Output Merger + ///////////////////////////////////////////////// + + create_array(state.m_OM.RenderTargets, rs.rts.size()); + for(size_t i = 0; i < rs.rts.size(); i++) + { + D3D12PipelineState::ResourceView &view = state.m_OM.RenderTargets[i]; + + PortableHandle h = rs.rtSingle ? rs.rts[i] : rs.rts[i]; + + if(rs.rtSingle) + h.index += (uint32_t)i; + + FillResourceView(view, h); + } + + { + D3D12PipelineState::ResourceView &view = state.m_OM.DepthTarget; + + FillResourceView(view, rs.dsv); + } + + memcpy(state.m_OM.m_BlendState.BlendFactor, rs.blendFactor, sizeof(FLOAT) * 4); + + { + D3D12_BLEND_DESC &src = pipe->graphics->BlendState; + + state.m_OM.m_BlendState.AlphaToCoverage = src.AlphaToCoverageEnable == TRUE; + state.m_OM.m_BlendState.IndependentBlend = src.IndependentBlendEnable == TRUE; + + create_array_uninit(state.m_OM.m_BlendState.Blends, 8); + for(size_t i = 0; i < 8; i++) + { + D3D12PipelineState::OutputMerger::BlendState::RTBlend &blend = + state.m_OM.m_BlendState.Blends[i]; + + blend.Enabled = src.RenderTarget[i].BlendEnable == TRUE; + + blend.LogicEnabled = src.RenderTarget[i].LogicOpEnable == TRUE; + blend.LogicOp = ToStr::Get(src.RenderTarget[i].LogicOp); + + blend.m_AlphaBlend.Source = ToStr::Get(src.RenderTarget[i].SrcBlendAlpha); + blend.m_AlphaBlend.Destination = ToStr::Get(src.RenderTarget[i].DestBlendAlpha); + blend.m_AlphaBlend.Operation = ToStr::Get(src.RenderTarget[i].BlendOpAlpha); + + blend.m_Blend.Source = ToStr::Get(src.RenderTarget[i].SrcBlend); + blend.m_Blend.Destination = ToStr::Get(src.RenderTarget[i].DestBlend); + blend.m_Blend.Operation = ToStr::Get(src.RenderTarget[i].BlendOp); + + blend.WriteMask = src.RenderTarget[i].RenderTargetWriteMask; + } + } + + { + D3D12_DEPTH_STENCIL_DESC &src = pipe->graphics->DepthStencilState; + + state.m_OM.m_State.DepthEnable = src.DepthEnable == TRUE; + state.m_OM.m_State.DepthFunc = ToStr::Get(src.DepthFunc); + state.m_OM.m_State.DepthWrites = src.DepthWriteMask == D3D12_DEPTH_WRITE_MASK_ALL; + state.m_OM.m_State.StencilEnable = src.StencilEnable == TRUE; + state.m_OM.m_State.StencilRef = rs.stencilRef; + state.m_OM.m_State.StencilReadMask = src.StencilReadMask; + state.m_OM.m_State.StencilWriteMask = src.StencilWriteMask; + + state.m_OM.m_State.m_FrontFace.Func = ToStr::Get(src.FrontFace.StencilFunc); + state.m_OM.m_State.m_FrontFace.DepthFailOp = ToStr::Get(src.FrontFace.StencilDepthFailOp); + state.m_OM.m_State.m_FrontFace.PassOp = ToStr::Get(src.FrontFace.StencilPassOp); + state.m_OM.m_State.m_FrontFace.FailOp = ToStr::Get(src.FrontFace.StencilFailOp); + + state.m_OM.m_State.m_BackFace.Func = ToStr::Get(src.BackFace.StencilFunc); + state.m_OM.m_State.m_BackFace.DepthFailOp = ToStr::Get(src.BackFace.StencilDepthFailOp); + state.m_OM.m_State.m_BackFace.PassOp = ToStr::Get(src.BackFace.StencilPassOp); + state.m_OM.m_State.m_BackFace.FailOp = ToStr::Get(src.BackFace.StencilFailOp); + } + } +} + void D3D12Replay::RenderCheckerboard(Vec3f light, Vec3f dark) { m_pDevice->GetDebugManager()->RenderCheckerboard(light, dark); @@ -333,11 +1172,6 @@ APIProperties D3D12Replay::GetAPIProperties() return ret; } -ShaderReflection *D3D12Replay::GetShader(ResourceId shader, string entryPoint) -{ - return NULL; -} - vector D3D12Replay::GetDebugMessages() { return vector(); @@ -350,10 +1184,6 @@ vector D3D12Replay::GetPassEvents(uint32_t eventID) return passEvents; } -void D3D12Replay::MakePipelineState() -{ -} - void D3D12Replay::InitPostVSBuffers(uint32_t eventID) { } diff --git a/renderdoc/driver/d3d12/d3d12_replay.h b/renderdoc/driver/d3d12/d3d12_replay.h index f0c28ba2a..bfc059aec 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.h +++ b/renderdoc/driver/d3d12/d3d12_replay.h @@ -31,6 +31,8 @@ class WrappedID3D12Device; +struct PortableHandle; + class D3D12Replay : public IReplayDriver { public: @@ -163,6 +165,8 @@ public: private: void MakePipelineState(); + void FillResourceView(D3D12PipelineState::ResourceView &view, const PortableHandle &resHandle); + bool m_Proxy; vector m_ProxyResources; diff --git a/renderdoc/driver/d3d12/d3d12_resources.cpp b/renderdoc/driver/d3d12/d3d12_resources.cpp index d5e5113a3..3f2348d6a 100644 --- a/renderdoc/driver/d3d12/d3d12_resources.cpp +++ b/renderdoc/driver/d3d12/d3d12_resources.cpp @@ -23,6 +23,7 @@ ******************************************************************************/ #include "d3d12_resources.h" +#include "3rdparty/lz4/lz4.h" #include "d3d12_command_list.h" #include "d3d12_command_queue.h" @@ -31,11 +32,121 @@ std::map WrappedID3D12Resource::m_List; std::map WrappedID3D12PipelineState::m_Shaders; +const GUID RENDERDOC_ID3D12ShaderGUID_ShaderDebugMagicValue = RENDERDOC_ShaderDebugMagicValue_struct; + +void WrappedID3D12PipelineState::ShaderEntry::TryReplaceOriginalByteCode() +{ + if(!DXBC::DXBCFile::CheckForDebugInfo((const void *)&m_Bytecode[0], m_Bytecode.size())) + { + string originalPath = m_DebugInfoPath; + + if(originalPath.empty()) + originalPath = + DXBC::DXBCFile::GetDebugBinaryPath((const void *)&m_Bytecode[0], m_Bytecode.size()); + + if(!originalPath.empty()) + { + bool lz4 = false; + + if(!strncmp(originalPath.c_str(), "lz4#", 4)) + { + originalPath = originalPath.substr(4); + lz4 = true; + } + // could support more if we're willing to compile in the decompressor + + FILE *originalShaderFile = NULL; + + size_t numSearchPaths = m_DebugInfoSearchPaths ? m_DebugInfoSearchPaths->size() : 0; + + string foundPath; + + // while we haven't found a file, keep trying through the search paths. For i==0 + // check the path on its own, in case it's an absolute path. + for(size_t i = 0; originalShaderFile == NULL && i <= numSearchPaths; i++) + { + if(i == 0) + { + originalShaderFile = FileIO::fopen(originalPath.c_str(), "rb"); + foundPath = originalPath; + continue; + } + else + { + const std::string &searchPath = (*m_DebugInfoSearchPaths)[i - 1]; + foundPath = searchPath + "/" + originalPath; + originalShaderFile = FileIO::fopen(foundPath.c_str(), "rb"); + } + } + + if(originalShaderFile == NULL) + return; + + FileIO::fseek64(originalShaderFile, 0L, SEEK_END); + uint64_t originalShaderSize = FileIO::ftell64(originalShaderFile); + FileIO::fseek64(originalShaderFile, 0, SEEK_SET); + + if(lz4 || originalShaderSize >= m_Bytecode.size()) + { + vector originalBytecode; + + originalBytecode.resize((size_t)originalShaderSize); + FileIO::fread(&originalBytecode[0], sizeof(byte), (size_t)originalShaderSize, + originalShaderFile); + + if(lz4) + { + vector decompressed; + + // first try decompressing to 1MB flat + decompressed.resize(100 * 1024); + + int ret = LZ4_decompress_safe((const char *)&originalBytecode[0], (char *)&decompressed[0], + (int)originalBytecode.size(), (int)decompressed.size()); + + if(ret < 0) + { + // if it failed, either source is corrupt or we didn't allocate enough space. + // Just allocate 255x compressed size since it can't need any more than that. + decompressed.resize(255 * originalBytecode.size()); + + ret = LZ4_decompress_safe((const char *)&originalBytecode[0], (char *)&decompressed[0], + (int)originalBytecode.size(), (int)decompressed.size()); + + if(ret < 0) + { + RDCERR("Failed to decompress LZ4 data from %s", foundPath.c_str()); + return; + } + } + + RDCASSERT(ret > 0, ret); + + // we resize and memcpy instead of just doing .swap() because that would + // transfer over the over-large pessimistic capacity needed for decompression + originalBytecode.resize(ret); + memcpy(&originalBytecode[0], &decompressed[0], originalBytecode.size()); + } + + if(DXBC::DXBCFile::CheckForDebugInfo((const void *)&originalBytecode[0], + originalBytecode.size())) + { + m_Bytecode.swap(originalBytecode); + } + } + + FileIO::fclose(originalShaderFile); + } + } +} + #undef D3D12_TYPE_MACRO #define D3D12_TYPE_MACRO(iface) WRAPPED_POOL_INST(CONCAT(Wrapped, iface)); ALL_D3D12_TYPES; +WRAPPED_POOL_INST(WrappedID3D12PipelineState::ShaderEntry); + D3D12ResourceType IdentifyTypeByPtr(ID3D12DeviceChild *ptr) { if(ptr == NULL) @@ -70,6 +181,9 @@ TrackedResource *GetTracked(ID3D12DeviceChild *ptr) ALL_D3D12_TYPES; + if(WrappedID3D12PipelineState::ShaderEntry::IsAlloc(ptr)) + return (TrackedResource *)(WrappedID3D12PipelineState::ShaderEntry *)ptr; + return NULL; } diff --git a/renderdoc/driver/d3d12/d3d12_resources.h b/renderdoc/driver/d3d12/d3d12_resources.h index cf388da22..2e60fe15c 100644 --- a/renderdoc/driver/d3d12/d3d12_resources.h +++ b/renderdoc/driver/d3d12/d3d12_resources.h @@ -48,7 +48,7 @@ private: D3D12ResourceRecord *m_pRecord; }; -extern const GUID RENDERDOC_ID3D11ShaderGUID_ShaderDebugMagicValue; +extern const GUID RENDERDOC_ID3D12ShaderGUID_ShaderDebugMagicValue; template class WrappedDeviceChild12 : public RefCounter12, public NestedType2, public TrackedResource @@ -61,16 +61,21 @@ protected: { m_pDevice->SoftRef(); - bool ret = m_pDevice->GetResourceManager()->AddWrapper(this, real); - if(!ret) - RDCERR("Error adding wrapper for type %s", ToStr::Get(__uuidof(NestedType)).c_str()); + if(real) + { + bool ret = m_pDevice->GetResourceManager()->AddWrapper(this, real); + if(!ret) + RDCERR("Error adding wrapper for type %s", ToStr::Get(__uuidof(NestedType)).c_str()); + } m_pDevice->GetResourceManager()->AddCurrentResource(GetResourceID(), this); } virtual void Shutdown() { - m_pDevice->GetResourceManager()->RemoveWrapper(m_pReal); + if(m_pReal) + m_pDevice->GetResourceManager()->RemoveWrapper(m_pReal); + m_pDevice->GetResourceManager()->ReleaseCurrentResource(GetResourceID()); m_pDevice->ReleaseResource((NestedType *)this); SAFE_RELEASE(m_pReal); @@ -225,7 +230,7 @@ public: HRESULT STDMETHODCALLTYPE SetPrivateData(REFGUID guid, UINT DataSize, const void *pData) { - if(guid == RENDERDOC_ID3D11ShaderGUID_ShaderDebugMagicValue) + if(guid == RENDERDOC_ID3D12ShaderGUID_ShaderDebugMagicValue) return m_pDevice->SetShaderDebugPath(this, (const char *)pData); if(guid == WKPDID_D3DDebugObjectName) @@ -419,6 +424,8 @@ public: D3D12_GRAPHICS_PIPELINE_STATE_DESC *graphics; D3D12_COMPUTE_PIPELINE_STATE_DESC *compute; + bool IsGraphics() { return graphics != NULL; } + bool IsCompute() { return compute != NULL; } struct DXBCKey { DXBCKey(const D3D12_SHADER_BYTECODE &byteCode) @@ -450,40 +457,34 @@ public: } }; - class ShaderEntry + class ShaderEntry : public WrappedDeviceChild12 { public: - ShaderEntry() : m_DebugInfoSearchPaths(NULL), m_DXBCFile(NULL), m_Details(NULL) {} - ShaderEntry(const D3D12_SHADER_BYTECODE &byteCode) + static const int AllocPoolCount = 16384; + static const int AllocMaxByteSize = 8 * 1024 * 1024; + ALLOCATE_WITH_WRAPPED_POOL(ShaderEntry, AllocPoolCount, AllocMaxByteSize); + + ShaderEntry(const D3D12_SHADER_BYTECODE &byteCode, WrappedID3D12Device *device) + : WrappedDeviceChild12(NULL, device), m_Key(byteCode) { const byte *code = (const byte *)byteCode.pShaderBytecode; m_Bytecode.assign(code, code + byteCode.BytecodeLength); m_DebugInfoSearchPaths = NULL; m_DXBCFile = NULL; - m_Details = NULL; - m_RefCount = 1; + device->GetResourceManager()->AddLiveResource(GetResourceID(), this); + + m_Built = false; } - ~ShaderEntry() + + virtual ~ShaderEntry() { m_Bytecode.clear(); SAFE_DELETE(m_DXBCFile); - SAFE_DELETE(m_Details); - } - - void AddRef() { m_RefCount++; } - bool Release() - { - m_RefCount--; - if(m_RefCount <= 0) - { - delete this; - return true; - } - - return false; + Shutdown(); } + DXBCKey GetKey() { return m_Key; } void SetDebugInfoPath(vector *searchPaths, const std::string &path) { m_DebugInfoSearchPaths = searchPaths; @@ -499,40 +500,73 @@ public: } return m_DXBCFile; } - ShaderReflection *GetDetails() + ShaderReflection &GetDetails() { - if(m_Details == NULL && GetDXBC() != NULL) - m_Details = MakeShaderReflection(m_DXBCFile); + if(!m_Built && GetDXBC() != NULL) + MakeShaderReflection(m_DXBCFile, &m_Details, &m_Mapping); + m_Built = true; return m_Details; } + const ShaderBindpointMapping &GetMapping() + { + if(!m_Built && GetDXBC() != NULL) + MakeShaderReflection(m_DXBCFile, &m_Details, &m_Mapping); + m_Built = true; + return m_Mapping; + } private: ShaderEntry(const ShaderEntry &e); void TryReplaceOriginalByteCode(); ShaderEntry &operator=(const ShaderEntry &e); - int m_RefCount; + DXBCKey m_Key; std::string m_DebugInfoPath; vector *m_DebugInfoSearchPaths; vector m_Bytecode; + bool m_Built; DXBC::DXBCFile *m_DXBCFile; - ShaderReflection *m_Details; + ShaderReflection m_Details; + ShaderBindpointMapping m_Mapping; }; - static map m_Shaders; - enum { TypeEnum = Resource_PipelineState, }; + static ShaderEntry *AddShader(const D3D12_SHADER_BYTECODE &byteCode, WrappedID3D12Device *device) + { + DXBCKey key(byteCode); + ShaderEntry *shader = m_Shaders[key]; + + if(shader == NULL) + shader = m_Shaders[key] = new ShaderEntry(byteCode, device); + else + shader->AddRef(); + + return shader; + } + + static void ReleaseShader(ShaderEntry *shader) + { + if(shader == NULL) + return; + + DXBCKey key = shader->GetKey(); + + if(shader->Release() == 0) + m_Shaders.erase(key); + } + WrappedID3D12PipelineState(ID3D12PipelineState *real, WrappedID3D12Device *device) : WrappedDeviceChild12(real, device) { graphics = NULL; + compute = NULL; } virtual ~WrappedID3D12PipelineState() { @@ -540,44 +574,26 @@ public: if(graphics) { - DXBCKey *vs = (DXBCKey *)graphics->VS.pShaderBytecode; - DXBCKey *hs = (DXBCKey *)graphics->HS.pShaderBytecode; - DXBCKey *ds = (DXBCKey *)graphics->DS.pShaderBytecode; - DXBCKey *gs = (DXBCKey *)graphics->GS.pShaderBytecode; - DXBCKey *ps = (DXBCKey *)graphics->PS.pShaderBytecode; + ShaderEntry *vs = (ShaderEntry *)graphics->VS.pShaderBytecode; + ShaderEntry *hs = (ShaderEntry *)graphics->HS.pShaderBytecode; + ShaderEntry *ds = (ShaderEntry *)graphics->DS.pShaderBytecode; + ShaderEntry *gs = (ShaderEntry *)graphics->GS.pShaderBytecode; + ShaderEntry *ps = (ShaderEntry *)graphics->PS.pShaderBytecode; - if(m_Shaders[*vs]->Release()) - m_Shaders.erase(*vs); - - if(m_Shaders[*hs]->Release()) - m_Shaders.erase(*hs); - - if(m_Shaders[*ds]->Release()) - m_Shaders.erase(*ds); - - if(m_Shaders[*gs]->Release()) - m_Shaders.erase(*gs); - - if(m_Shaders[*ps]->Release()) - m_Shaders.erase(*ps); - - SAFE_DELETE(vs); - SAFE_DELETE(hs); - SAFE_DELETE(ds); - SAFE_DELETE(gs); - SAFE_DELETE(ps); + ReleaseShader(vs); + ReleaseShader(hs); + ReleaseShader(ds); + ReleaseShader(gs); + ReleaseShader(ps); SAFE_DELETE(graphics); } if(compute) { - DXBCKey *cs = (DXBCKey *)compute->CS.pShaderBytecode; + ShaderEntry *cs = (ShaderEntry *)compute->CS.pShaderBytecode; - if(m_Shaders[*cs]->Release()) - m_Shaders.erase(*cs); - - SAFE_DELETE(cs); + ReleaseShader(cs); SAFE_DELETE(compute); } @@ -590,6 +606,9 @@ public: { return m_pReal->GetCachedBlob(ppBlob); } + +private: + static map m_Shaders; }; class WrappedID3D12QueryHeap : public WrappedDeviceChild12 diff --git a/renderdoc/driver/d3d12/d3d12_state.h b/renderdoc/driver/d3d12/d3d12_state.h index c3049811d..40dd5aec5 100644 --- a/renderdoc/driver/d3d12/d3d12_state.h +++ b/renderdoc/driver/d3d12/d3d12_state.h @@ -157,6 +157,17 @@ struct D3D12RenderState vector heaps; + struct StreamOut + { + ResourceId buf; + UINT64 offs; + UINT64 size; + + ResourceId countbuf; + UINT64 countoffs; + }; + vector streamouts; + struct Pipeline { ResourceId rootsig; diff --git a/renderdoc/replay/replay_renderer.cpp b/renderdoc/replay/replay_renderer.cpp index 06c0f20cc..f5ae9cb4c 100644 --- a/renderdoc/replay/replay_renderer.cpp +++ b/renderdoc/replay/replay_renderer.cpp @@ -1643,12 +1643,9 @@ void ReplayRenderer::FetchPipelineState() &m_D3D12PipelineState.m_GS, &m_D3D12PipelineState.m_PS, &m_D3D12PipelineState.m_CS, }; - const char *stageNames[] = {"VS", "HS", "DS", "GS", "PS", "CS"}; - for(int i = 0; i < 6; i++) - if(stages[i]->Present) - stages[i]->ShaderDetails = - m_pDevice->GetShader(m_pDevice->GetLiveID(m_D3D12PipelineState.pipeline), stageNames[i]); + if(stages[i]->Shader != ResourceId()) + stages[i]->ShaderDetails = m_pDevice->GetShader(m_pDevice->GetLiveID(stages[i]->Shader), ""); } { diff --git a/renderdocui/Interop/D3D12PipelineState.cs b/renderdocui/Interop/D3D12PipelineState.cs index e86a760c5..6550b38bc 100644 --- a/renderdocui/Interop/D3D12PipelineState.cs +++ b/renderdocui/Interop/D3D12PipelineState.cs @@ -95,7 +95,6 @@ namespace renderdoc } public ResourceId Shader; - public bool Present; private IntPtr _ptr_ShaderDetails; [CustomMarshalAs(CustomUnmanagedType.Skip)] public ShaderReflection ShaderDetails; @@ -122,7 +121,7 @@ namespace renderdoc public D3DBufferViewFlags BufferFlags; public UInt32 BufferStructCount; public UInt32 ElementSize; - public UInt32 FirstElement; + public UInt64 FirstElement; public UInt32 NumElements; public ResourceId CounterResource; diff --git a/renderdocui/Windows/PipelineState/D3D12PipelineStateViewer.cs b/renderdocui/Windows/PipelineState/D3D12PipelineStateViewer.cs index db6408b8f..608986d56 100644 --- a/renderdocui/Windows/PipelineState/D3D12PipelineStateViewer.cs +++ b/renderdocui/Windows/PipelineState/D3D12PipelineStateViewer.cs @@ -300,12 +300,12 @@ namespace renderdocui.Windows.PipelineState D3D12PipelineState state = m_Core.CurD3D12PipelineState; ShaderReflection shaderDetails = stage.ShaderDetails; - if (!stage.Present) + if (stage.Shader == ResourceId.Null) shader.Text = "Unbound"; else if (state.customName) shader.Text = state.PipelineName + " - " + m_Core.CurPipelineState.Abbrev(stage.stage); else - shader.Text = stage.stage.Str(GraphicsAPI.D3D12); + shader.Text = state.PipelineName + " - " + stage.stage.Str(GraphicsAPI.D3D12) + " Shader"; if (shaderDetails != null && shaderDetails.DebugInfo.entryFunc.Length > 0 && shaderDetails.DebugInfo.files.Length > 0) { @@ -439,7 +439,7 @@ namespace renderdocui.Windows.PipelineState bool iaUsed = false; - if (state.m_VS.Present) + if (state.m_VS.Shader != ResourceId.Null) { for (int ia = 0; ia < state.m_VS.ShaderDetails.InputSig.Length; ia++) { @@ -2469,7 +2469,7 @@ namespace renderdocui.Windows.PipelineState string shadername = "Unknown"; - if (!sh.Present) + if (sh.Shader == ResourceId.Null) shadername = "Unbound"; else if (state.customName) shadername = state.PipelineName + " - " + m_Core.CurPipelineState.Abbrev(sh.stage); diff --git a/renderdocui/Windows/TextureViewer.cs b/renderdocui/Windows/TextureViewer.cs index 523bb0dcb..24b1858c3 100644 --- a/renderdocui/Windows/TextureViewer.cs +++ b/renderdocui/Windows/TextureViewer.cs @@ -1476,6 +1476,9 @@ namespace renderdocui.Windows ShaderReflection details = Following.GetReflection(m_Core, stage); ShaderBindpointMapping mapping = Following.GetMapping(m_Core, stage); + if (mapping == null) + continue; + InitStageResourcePreviews(stage, details != null ? details.ReadWriteResources : new ShaderResource[0], mapping.ReadWriteResources,