From 834148f862d22b96bf7d1ae9e7fc7b11657dec2f Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 16 Nov 2016 15:52:56 +0100 Subject: [PATCH] Add texture min/max calculation for D3D12 --- renderdoc/driver/d3d12/d3d12_debug.cpp | 456 +++++++++++++++++++++++- renderdoc/driver/d3d12/d3d12_debug.h | 20 +- renderdoc/driver/d3d12/d3d12_replay.cpp | 15 +- 3 files changed, 464 insertions(+), 27 deletions(-) diff --git a/renderdoc/driver/d3d12/d3d12_debug.cpp b/renderdoc/driver/d3d12/d3d12_debug.cpp index 37e78f218..1247d3bda 100644 --- a/renderdoc/driver/d3d12/d3d12_debug.cpp +++ b/renderdoc/driver/d3d12/d3d12_debug.cpp @@ -142,7 +142,7 @@ D3D12DebugManager::D3D12DebugManager(WrappedID3D12Device *wrapper) desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; hr = m_WrappedDevice->CreateDescriptorHeap(&desc, __uuidof(ID3D12DescriptorHeap), - (void **)&cbvsrvHeap); + (void **)&cbvsrvuavHeap); if(FAILED(hr)) { @@ -277,9 +277,12 @@ D3D12DebugManager::D3D12DebugManager(WrappedID3D12Device *wrapper) samp.ptr += m_WrappedDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); m_WrappedDevice->CreateSampler(&sampDesc, samp); - m_GenericVSCbuffer = MakeCBuffer(sizeof(DebugVertexCBuffer)); + m_GenericVSCbuffer = MakeCBuffer(1024); m_GenericPSCbuffer = MakeCBuffer(sizeof(DebugPixelCBufferData)); + RDCCOMPILE_ASSERT(sizeof(DebugVertexCBuffer) < 1024, "CBuffer isn't large enough"); + RDCCOMPILE_ASSERT(sizeof(HistogramCBufferData) < 1024, "CBuffer isn't large enough"); + RenderDoc::Inst().SetProgress(DebugManagerInit, 0.4f); bool success = LoadShaderCache("d3d12shaders.cache", m_ShaderCacheMagic, m_ShaderCacheVersion, @@ -343,6 +346,52 @@ D3D12DebugManager::D3D12DebugManager(WrappedID3D12Device *wrapper) SAFE_RELEASE(root); + rootSig.clear(); + + // 0: CBV + param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; + param.Descriptor.ShaderRegister = 0; + + rootSig.push_back(param); + + // 1: Texture SRVs + param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + param.DescriptorTable.NumDescriptorRanges = 1; + param.DescriptorTable.pDescriptorRanges = &srvrange; + + rootSig.push_back(param); + + // 2: Samplers + param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + param.DescriptorTable.NumDescriptorRanges = 1; + param.DescriptorTable.pDescriptorRanges = &samplerrange; + + rootSig.push_back(param); + + // 3: UAVs + D3D12_DESCRIPTOR_RANGE uavrange = {}; + uavrange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; + uavrange.BaseShaderRegister = 0; + uavrange.NumDescriptors = 3; + uavrange.OffsetInDescriptorsFromTableStart = 0; + + param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + param.DescriptorTable.NumDescriptorRanges = 1; + param.DescriptorTable.pDescriptorRanges = &uavrange; + + rootSig.push_back(param); + + root = MakeRootSig(rootSig); + + RDCASSERT(root); + + hr = m_WrappedDevice->CreateRootSignature(0, root->GetBufferPointer(), root->GetBufferSize(), + __uuidof(ID3D12RootSignature), + (void **)&m_HistogramRootSig); + + SAFE_RELEASE(root); + RenderDoc::Inst().SetProgress(DebugManagerInit, 0.6f); D3D12_GRAPHICS_PIPELINE_STATE_DESC pipeDesc; @@ -431,10 +480,201 @@ D3D12DebugManager::D3D12DebugManager(WrappedID3D12Device *wrapper) RDCERR("Couldn't create m_CheckerboardPipe! 0x%08x", hr); } + string histogramhlsl = GetEmbeddedResource(debugcbuffers_h); + histogramhlsl += GetEmbeddedResource(debugcommon_hlsl); + histogramhlsl += GetEmbeddedResource(histogram_hlsl); + + RenderDoc::Inst().SetProgress(DebugManagerInit, 0.7f); + + D3D12_COMPUTE_PIPELINE_STATE_DESC compPipeDesc; + RDCEraseEl(compPipeDesc); + + compPipeDesc.pRootSignature = m_HistogramRootSig; + + RDCEraseEl(m_TileMinMaxPipe); + RDCEraseEl(m_HistogramPipe); + RDCEraseEl(m_ResultMinMaxPipe); + + for(int t = RESTYPE_TEX1D; t <= RESTYPE_TEX2D_MS; t++) + { + // skip unused cube slot + if(t == 8) + continue; + + // float, uint, sint + for(int i = 0; i < 3; i++) + { + ID3DBlob *tile = NULL; + ID3DBlob *result = NULL; + ID3DBlob *histogram = NULL; + + string hlsl = string("#define SHADER_RESTYPE ") + ToStr::Get(t) + "\n"; + hlsl += string("#define UINT_TEX ") + (i == 1 ? "1" : "0") + "\n"; + hlsl += string("#define SINT_TEX ") + (i == 2 ? "1" : "0") + "\n"; + hlsl += histogramhlsl; + + GetShaderBlob(hlsl.c_str(), "RENDERDOC_TileMinMaxCS", D3DCOMPILE_WARNINGS_ARE_ERRORS, + "cs_5_0", &tile); + + compPipeDesc.CS.BytecodeLength = tile->GetBufferSize(); + compPipeDesc.CS.pShaderBytecode = tile->GetBufferPointer(); + + hr = m_WrappedDevice->CreateComputePipelineState(&compPipeDesc, __uuidof(ID3D12PipelineState), + (void **)&m_TileMinMaxPipe[t][i]); + + if(FAILED(hr)) + { + RDCERR("Couldn't create m_TileMinMaxPipe! 0x%08x", hr); + } + + GetShaderBlob(hlsl.c_str(), "RENDERDOC_HistogramCS", D3DCOMPILE_WARNINGS_ARE_ERRORS, "cs_5_0", + &histogram); + + compPipeDesc.CS.BytecodeLength = histogram->GetBufferSize(); + compPipeDesc.CS.pShaderBytecode = histogram->GetBufferPointer(); + + hr = m_WrappedDevice->CreateComputePipelineState(&compPipeDesc, __uuidof(ID3D12PipelineState), + (void **)&m_HistogramPipe[t][i]); + + if(FAILED(hr)) + { + RDCERR("Couldn't create m_HistogramPipe! 0x%08x", hr); + } + + if(t == 1) + { + GetShaderBlob(hlsl.c_str(), "RENDERDOC_ResultMinMaxCS", D3DCOMPILE_WARNINGS_ARE_ERRORS, + "cs_5_0", &result); + + compPipeDesc.CS.BytecodeLength = result->GetBufferSize(); + compPipeDesc.CS.pShaderBytecode = result->GetBufferPointer(); + + hr = m_WrappedDevice->CreateComputePipelineState( + &compPipeDesc, __uuidof(ID3D12PipelineState), (void **)&m_ResultMinMaxPipe[i]); + + if(FAILED(hr)) + { + RDCERR("Couldn't create m_HistogramPipe! 0x%08x", hr); + } + } + + SAFE_RELEASE(tile); + SAFE_RELEASE(histogram); + SAFE_RELEASE(result); + } + } + SAFE_RELEASE(GenericVS); SAFE_RELEASE(TexDisplayPS); SAFE_RELEASE(CheckerboardPS); + { + const uint64_t maxTexDim = 16384; + const uint64_t blockPixSize = HGRAM_PIXELS_PER_TILE * HGRAM_TILES_PER_BLOCK; + const uint64_t maxBlocksNeeded = (maxTexDim * maxTexDim) / (blockPixSize * blockPixSize); + + D3D12_RESOURCE_DESC minmaxDesc = {}; + minmaxDesc.Alignment = 0; + minmaxDesc.DepthOrArraySize = 1; + minmaxDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + minmaxDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; + minmaxDesc.Format = DXGI_FORMAT_UNKNOWN; + minmaxDesc.Height = 1; + minmaxDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + minmaxDesc.MipLevels = 1; + minmaxDesc.SampleDesc.Count = 1; + minmaxDesc.SampleDesc.Quality = 0; + minmaxDesc.Width = + 2 * sizeof(Vec4f) * HGRAM_TILES_PER_BLOCK * HGRAM_TILES_PER_BLOCK * maxBlocksNeeded; + + D3D12_HEAP_PROPERTIES heapProps; + heapProps.Type = D3D12_HEAP_TYPE_DEFAULT; + heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + heapProps.CreationNodeMask = 1; + heapProps.VisibleNodeMask = 1; + + hr = m_WrappedDevice->CreateCommittedResource( + &heapProps, D3D12_HEAP_FLAG_NONE, &minmaxDesc, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, NULL, + __uuidof(ID3D12Resource), (void **)&m_MinMaxTileBuffer); + + if(FAILED(hr)) + { + RDCERR("Failed to create tile buffer for min/max, HRESULT: 0x%08x", hr); + return; + } + + D3D12_CPU_DESCRIPTOR_HANDLE uav = cbvsrvuavHeap->GetCPUDescriptorHandleForHeapStart(); + uav.ptr += MINMAX_TILE_UAVS * sizeof(D3D12Descriptor); + + D3D12_UNORDERED_ACCESS_VIEW_DESC tileDesc = {}; + tileDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; + tileDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; + tileDesc.Buffer.FirstElement = 0; + tileDesc.Buffer.NumElements = UINT(minmaxDesc.Width / sizeof(Vec4f)); + + m_WrappedDevice->CreateUnorderedAccessView(m_MinMaxTileBuffer, NULL, &tileDesc, uav); + + uav.ptr += sizeof(D3D12Descriptor); + tileDesc.Format = DXGI_FORMAT_R32G32B32A32_UINT; + m_WrappedDevice->CreateUnorderedAccessView(m_MinMaxTileBuffer, NULL, &tileDesc, uav); + + uav.ptr += sizeof(D3D12Descriptor); + tileDesc.Format = DXGI_FORMAT_R32G32B32A32_SINT; + m_WrappedDevice->CreateUnorderedAccessView(m_MinMaxTileBuffer, NULL, &tileDesc, uav); + + D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; + srvDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; + srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + srvDesc.Buffer.FirstElement = 0; + srvDesc.Buffer.NumElements = UINT(minmaxDesc.Width / sizeof(Vec4f)); + + D3D12_CPU_DESCRIPTOR_HANDLE srv = cbvsrvuavHeap->GetCPUDescriptorHandleForHeapStart(); + srv.ptr += MINMAX_TILE_SRVS * sizeof(D3D12Descriptor); + + m_WrappedDevice->CreateShaderResourceView(m_MinMaxTileBuffer, &srvDesc, srv); + + srv.ptr += sizeof(D3D12Descriptor); + srvDesc.Format = DXGI_FORMAT_R32G32B32A32_UINT; + + m_WrappedDevice->CreateShaderResourceView(m_MinMaxTileBuffer, &srvDesc, srv); + + srv.ptr += sizeof(D3D12Descriptor); + srvDesc.Format = DXGI_FORMAT_R32G32B32A32_SINT; + + m_WrappedDevice->CreateShaderResourceView(m_MinMaxTileBuffer, &srvDesc, srv); + + minmaxDesc.Width = 2 * sizeof(Vec4f); + + hr = m_WrappedDevice->CreateCommittedResource( + &heapProps, D3D12_HEAP_FLAG_NONE, &minmaxDesc, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, NULL, + __uuidof(ID3D12Resource), (void **)&m_MinMaxResultBuffer); + + if(FAILED(hr)) + { + RDCERR("Failed to create result buffer for min/max, HRESULT: 0x%08x", hr); + return; + } + + uav = cbvsrvuavHeap->GetCPUDescriptorHandleForHeapStart(); + uav.ptr += MINMAX_RESULT_UAVS * sizeof(D3D12Descriptor); + + tileDesc.Buffer.NumElements = 2; + + tileDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; + + m_WrappedDevice->CreateUnorderedAccessView(m_MinMaxResultBuffer, NULL, &tileDesc, uav); + + uav.ptr += sizeof(D3D12Descriptor); + tileDesc.Format = DXGI_FORMAT_R32G32B32A32_UINT; + m_WrappedDevice->CreateUnorderedAccessView(m_MinMaxResultBuffer, NULL, &tileDesc, uav); + + uav.ptr += sizeof(D3D12Descriptor); + tileDesc.Format = DXGI_FORMAT_R32G32B32A32_SINT; + m_WrappedDevice->CreateUnorderedAccessView(m_MinMaxResultBuffer, NULL, &tileDesc, uav); + } + RenderDoc::Inst().SetProgress(DebugManagerInit, 0.8f); // font rendering @@ -559,13 +799,8 @@ D3D12DebugManager::D3D12DebugManager(WrappedID3D12Device *wrapper) SAFE_RELEASE(uploadBuf); - D3D12_CPU_DESCRIPTOR_HANDLE srv; - srv = cbvsrvHeap->GetCPUDescriptorHandleForHeapStart(); - - // texture display uses the first few, move to font texture slow - srv.ptr += - FONT_SRV * - m_WrappedDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + D3D12_CPU_DESCRIPTOR_HANDLE srv = cbvsrvuavHeap->GetCPUDescriptorHandleForHeapStart(); + srv.ptr += FONT_SRV * sizeof(D3D12Descriptor); m_WrappedDevice->CreateShaderResourceView(m_Font.Tex, NULL, srv); @@ -728,7 +963,7 @@ D3D12DebugManager::~D3D12DebugManager() SAFE_RELEASE(dsvHeap); SAFE_RELEASE(rtvHeap); - SAFE_RELEASE(cbvsrvHeap); + SAFE_RELEASE(cbvsrvuavHeap); SAFE_RELEASE(samplerHeap); SAFE_RELEASE(m_GenericVSCbuffer); @@ -743,6 +978,20 @@ D3D12DebugManager::~D3D12DebugManager() SAFE_RELEASE(m_PickPixelTex); + SAFE_RELEASE(m_HistogramRootSig); + for(int t = RESTYPE_TEX1D; t <= RESTYPE_TEX2D_MS; t++) + { + for(int i = 0; i < 3; i++) + { + SAFE_RELEASE(m_TileMinMaxPipe[t][i]); + SAFE_RELEASE(m_HistogramPipe[t][i]); + if(t == RESTYPE_TEX1D) + SAFE_RELEASE(m_ResultMinMaxPipe[i]); + } + } + SAFE_RELEASE(m_MinMaxResultBuffer); + SAFE_RELEASE(m_MinMaxTileBuffer); + SAFE_RELEASE(m_TexResource); SAFE_RELEASE(m_ReadbackBuffer); @@ -2064,12 +2313,12 @@ void D3D12DebugManager::RenderCheckerboard(Vec3f light, Vec3f dark) list->SetGraphicsRootSignature(m_TexDisplayRootSig); // Set the descriptor heap containing the texture srv - ID3D12DescriptorHeap *heaps[] = {cbvsrvHeap, samplerHeap}; + ID3D12DescriptorHeap *heaps[] = {cbvsrvuavHeap, samplerHeap}; list->SetDescriptorHeaps(2, heaps); list->SetGraphicsRootConstantBufferView(0, m_GenericVSCbuffer->GetGPUVirtualAddress()); list->SetGraphicsRootConstantBufferView(1, m_GenericPSCbuffer->GetGPUVirtualAddress()); - list->SetGraphicsRootDescriptorTable(2, cbvsrvHeap->GetGPUDescriptorHandleForHeapStart()); + list->SetGraphicsRootDescriptorTable(2, cbvsrvuavHeap->GetGPUDescriptorHandleForHeapStart()); list->SetGraphicsRootDescriptorTable(3, samplerHeap->GetGPUDescriptorHandleForHeapStart()); float factor[4] = {1.0f, 1.0f, 1.0f, 1.0f}; @@ -2178,7 +2427,7 @@ void D3D12DebugManager::RenderTextInternal(ID3D12GraphicsCommandList *list, floa list->SetGraphicsRootSignature(m_Font.RootSig); // Set the descriptor heap containing the texture srv - ID3D12DescriptorHeap *heaps[] = {cbvsrvHeap, samplerHeap}; + ID3D12DescriptorHeap *heaps[] = {cbvsrvuavHeap, samplerHeap}; list->SetDescriptorHeaps(2, heaps); list->SetGraphicsRootConstantBufferView( @@ -2186,7 +2435,7 @@ void D3D12DebugManager::RenderTextInternal(ID3D12GraphicsCommandList *list, floa list->SetGraphicsRootConstantBufferView(1, m_Font.GlyphData->GetGPUVirtualAddress()); list->SetGraphicsRootConstantBufferView( 2, m_Font.CharBuffer->GetGPUVirtualAddress() + charOffset * sizeof(Vec4f)); - list->SetGraphicsRootDescriptorTable(3, cbvsrvHeap->GetGPUDescriptorHandleForHeapStart()); + list->SetGraphicsRootDescriptorTable(3, cbvsrvuavHeap->GetGPUDescriptorHandleForHeapStart()); list->SetGraphicsRootDescriptorTable(4, samplerHeap->GetGPUDescriptorHandleForHeapStart()); list->DrawInstanced(4, (uint32_t)strlen(text), 0, 0); @@ -2261,7 +2510,7 @@ void D3D12DebugManager::PrepareTextureSampling(ID3D12Resource *resource, if(IsIntFormat(resourceDesc.Format)) srvOffset += 20; - D3D12_CPU_DESCRIPTOR_HANDLE srv = cbvsrvHeap->GetCPUDescriptorHandleForHeapStart(); + D3D12_CPU_DESCRIPTOR_HANDLE srv = cbvsrvuavHeap->GetCPUDescriptorHandleForHeapStart(); srv.ptr += srvOffset * sizeof(D3D12Descriptor); D3D12_RESOURCE_STATES realResourceState = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; @@ -2447,6 +2696,179 @@ void D3D12DebugManager::PrepareTextureSampling(ID3D12Resource *resource, } } +bool D3D12DebugManager::GetMinMax(ResourceId texid, uint32_t sliceFace, uint32_t mip, uint32_t sample, + FormatComponentType typeHint, float *minval, float *maxval) +{ + ID3D12Resource *resource = WrappedID3D12Resource::GetList()[texid]; + + if(resource == NULL) + return false; + + D3D12_RESOURCE_DESC resourceDesc = resource->GetDesc(); + + HistogramCBufferData cdata; + cdata.HistogramTextureResolution.x = float(RDCMAX(1U, uint32_t(resourceDesc.Width >> mip))); + cdata.HistogramTextureResolution.y = float(RDCMAX(1U, uint32_t(resourceDesc.Height >> mip))); + cdata.HistogramTextureResolution.z = + float(RDCMAX(1U, uint32_t(resourceDesc.DepthOrArraySize >> mip))); + + if(resourceDesc.DepthOrArraySize > 1 && resourceDesc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D) + cdata.HistogramTextureResolution.z = float(resourceDesc.DepthOrArraySize); + + cdata.HistogramSlice = float(RDCCLAMP(sliceFace, 0U, uint32_t(resourceDesc.DepthOrArraySize - 1))); + + if(resourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D) + cdata.HistogramSlice = float(sliceFace) / float(resourceDesc.DepthOrArraySize); + + cdata.HistogramMip = mip; + cdata.HistogramSample = (int)RDCCLAMP(sample, 0U, resourceDesc.SampleDesc.Count - 1); + if(sample == ~0U) + cdata.HistogramSample = -int(resourceDesc.SampleDesc.Count); + cdata.HistogramMin = 0.0f; + cdata.HistogramMax = 1.0f; + cdata.HistogramChannels = 0xf; + cdata.HistogramFlags = 0; + + int intIdx = 0; + + DXGI_FORMAT fmt = GetTypedFormat(resourceDesc.Format, typeHint); + + if(IsUIntFormat(fmt)) + intIdx = 1; + else if(IsIntFormat(fmt)) + intIdx = 2; + + FillBuffer(m_GenericVSCbuffer, &cdata, sizeof(cdata)); + + int blocksX = (int)ceil(cdata.HistogramTextureResolution.x / + float(HGRAM_PIXELS_PER_TILE * HGRAM_TILES_PER_BLOCK)); + int blocksY = (int)ceil(cdata.HistogramTextureResolution.y / + float(HGRAM_PIXELS_PER_TILE * HGRAM_TILES_PER_BLOCK)); + + vector barriers; + int resType = 0; + PrepareTextureSampling(resource, typeHint, resType, barriers); + + { + ID3D12GraphicsCommandList *list = m_WrappedDevice->GetNewList(); + + if(!barriers.empty()) + list->ResourceBarrier((UINT)barriers.size(), &barriers[0]); + + list->SetPipelineState(m_TileMinMaxPipe[resType][intIdx]); + + list->SetComputeRootSignature(m_HistogramRootSig); + + // Set the descriptor heap containing the texture srv + ID3D12DescriptorHeap *heaps[] = {cbvsrvuavHeap, samplerHeap}; + list->SetDescriptorHeaps(2, heaps); + + D3D12_GPU_DESCRIPTOR_HANDLE uav = cbvsrvuavHeap->GetGPUDescriptorHandleForHeapStart(); + D3D12_GPU_DESCRIPTOR_HANDLE srv = cbvsrvuavHeap->GetGPUDescriptorHandleForHeapStart(); + + uav.ptr += MINMAX_TILE_UAVS * sizeof(D3D12Descriptor); + + list->SetComputeRootConstantBufferView(0, m_GenericVSCbuffer->GetGPUVirtualAddress()); + list->SetComputeRootDescriptorTable(1, srv); + list->SetComputeRootDescriptorTable(2, samplerHeap->GetGPUDescriptorHandleForHeapStart()); + list->SetComputeRootDescriptorTable(3, uav); + + // discard the whole resource as we will overwrite it + D3D12_DISCARD_REGION region = {}; + region.NumSubresources = 1; + list->DiscardResource(m_MinMaxTileBuffer, ®ion); + + list->Dispatch(blocksX, blocksY, 1); + + D3D12_RESOURCE_BARRIER tileBarriers[2] = {}; + + // ensure UAV work is done. Transition to SRV + tileBarriers[0].Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; + tileBarriers[0].UAV.pResource = m_MinMaxTileBuffer; + tileBarriers[1].Transition.pResource = m_MinMaxTileBuffer; + tileBarriers[1].Transition.StateBefore = D3D12_RESOURCE_STATE_UNORDERED_ACCESS; + tileBarriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; + + list->ResourceBarrier(2, tileBarriers); + + // set up second dispatch + srv.ptr += MINMAX_TILE_SRVS * sizeof(D3D12Descriptor); + uav = cbvsrvuavHeap->GetGPUDescriptorHandleForHeapStart(); + uav.ptr += MINMAX_RESULT_UAVS * sizeof(D3D12Descriptor); + + list->SetComputeRootDescriptorTable(1, srv); + list->SetComputeRootDescriptorTable(3, uav); + + list->SetPipelineState(m_ResultMinMaxPipe[intIdx]); + + list->Dispatch(1, 1, 1); + + // transition back to UAV for next time + std::swap(tileBarriers[1].Transition.StateBefore, tileBarriers[1].Transition.StateAfter); + + list->ResourceBarrier(1, &tileBarriers[1]); + + // finish the UAV work, and transition to copy. + tileBarriers[0].UAV.pResource = m_MinMaxResultBuffer; + tileBarriers[1].Transition.pResource = m_MinMaxResultBuffer; + tileBarriers[1].Transition.StateBefore = D3D12_RESOURCE_STATE_UNORDERED_ACCESS; + tileBarriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE; + + list->ResourceBarrier(2, tileBarriers); + + // copy to readback + list->CopyBufferRegion(m_ReadbackBuffer, 0, m_MinMaxResultBuffer, 0, sizeof(Vec4f) * 2); + + // transition back to UAV for next time + std::swap(tileBarriers[1].Transition.StateBefore, tileBarriers[1].Transition.StateAfter); + + list->ResourceBarrier(1, &tileBarriers[1]); + + // transition image back to where it was + for(size_t i = 0; i < barriers.size(); i++) + std::swap(barriers[i].Transition.StateBefore, barriers[i].Transition.StateAfter); + + if(!barriers.empty()) + list->ResourceBarrier((UINT)barriers.size(), &barriers[0]); + + list->Close(); + + m_WrappedDevice->ExecuteLists(); + m_WrappedDevice->FlushLists(); + } + + D3D12_RANGE range = {0, sizeof(Vec4f) * 2}; + + void *data = NULL; + HRESULT hr = m_ReadbackBuffer->Map(0, &range, &data); + + if(FAILED(hr)) + { + RDCERR("Failed to map bufferdata buffer %08x", hr); + return false; + } + else + { + Vec4f *minmax = (Vec4f *)data; + + minval[0] = minmax[0].x; + minval[1] = minmax[0].y; + minval[2] = minmax[0].z; + minval[3] = minmax[0].w; + + maxval[0] = minmax[1].x; + maxval[1] = minmax[1].y; + maxval[2] = minmax[1].z; + maxval[3] = minmax[1].w; + + range.End = 0; + + m_ReadbackBuffer->Unmap(0, &range); + } + + return true; +} + bool D3D12DebugManager::RenderTextureInternal(D3D12_CPU_DESCRIPTOR_HANDLE rtv, TextureDisplay cfg, bool blendAlpha) { @@ -2609,12 +3031,12 @@ bool D3D12DebugManager::RenderTextureInternal(D3D12_CPU_DESCRIPTOR_HANDLE rtv, T list->SetGraphicsRootSignature(m_TexDisplayRootSig); // Set the descriptor heap containing the texture srv - ID3D12DescriptorHeap *heaps[] = {cbvsrvHeap, samplerHeap}; + ID3D12DescriptorHeap *heaps[] = {cbvsrvuavHeap, samplerHeap}; list->SetDescriptorHeaps(2, heaps); list->SetGraphicsRootConstantBufferView(0, m_GenericVSCbuffer->GetGPUVirtualAddress()); list->SetGraphicsRootConstantBufferView(1, m_GenericPSCbuffer->GetGPUVirtualAddress()); - list->SetGraphicsRootDescriptorTable(2, cbvsrvHeap->GetGPUDescriptorHandleForHeapStart()); + list->SetGraphicsRootDescriptorTable(2, cbvsrvuavHeap->GetGPUDescriptorHandleForHeapStart()); list->SetGraphicsRootDescriptorTable(3, samplerHeap->GetGPUDescriptorHandleForHeapStart()); float factor[4] = {1.0f, 1.0f, 1.0f, 1.0f}; diff --git a/renderdoc/driver/d3d12/d3d12_debug.h b/renderdoc/driver/d3d12/d3d12_debug.h index 70b8580a7..61d3cd4a2 100644 --- a/renderdoc/driver/d3d12/d3d12_debug.h +++ b/renderdoc/driver/d3d12/d3d12_debug.h @@ -73,6 +73,9 @@ public: void RenderCheckerboard(Vec3f light, Vec3f dark); bool RenderTexture(TextureDisplay cfg, bool blendAlpha); + bool GetMinMax(ResourceId texid, uint32_t sliceFace, uint32_t mip, uint32_t sample, + FormatComponentType typeHint, float *minval, float *maxval); + void PickPixel(ResourceId texture, uint32_t x, uint32_t y, uint32_t sliceFace, uint32_t mip, uint32_t sample, FormatComponentType typeHint, float pixel[4]); @@ -121,8 +124,12 @@ private: // how much character space is in the ring buffer static const int FONT_BUFFER_CHARS = 8192; - // index in SRV heap + // baked indices in heaps static const int FONT_SRV = 128; + static const int MINMAX_TILE_SRVS = FONT_SRV + 1; + + static const int MINMAX_TILE_UAVS = MINMAX_TILE_SRVS + 3; + static const int MINMAX_RESULT_UAVS = MINMAX_TILE_UAVS + 3; enum { @@ -171,7 +178,7 @@ private: float CharSize; } m_Font; - ID3D12DescriptorHeap *cbvsrvHeap; + ID3D12DescriptorHeap *cbvsrvuavHeap; ID3D12DescriptorHeap *samplerHeap; ID3D12DescriptorHeap *rtvHeap; ID3D12DescriptorHeap *dsvHeap; @@ -190,6 +197,15 @@ private: ID3D12Resource *m_PickPixelTex; D3D12_CPU_DESCRIPTOR_HANDLE m_PickPixelRTV; + ID3D12RootSignature *m_HistogramRootSig; + // one per texture type, one per int/uint/float + ID3D12PipelineState *m_TileMinMaxPipe[10][3]; + ID3D12PipelineState *m_HistogramPipe[10][3]; + // one per int/uint/float + ID3D12PipelineState *m_ResultMinMaxPipe[3]; + ID3D12Resource *m_MinMaxResultBuffer; + ID3D12Resource *m_MinMaxTileBuffer; + ID3D12GraphicsCommandList *m_ReadbackList; ID3D12CommandAllocator *m_ReadbackAlloc; ID3D12Resource *m_ReadbackBuffer; diff --git a/renderdoc/driver/d3d12/d3d12_replay.cpp b/renderdoc/driver/d3d12/d3d12_replay.cpp index 944c1762a..8f60580f6 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.cpp +++ b/renderdoc/driver/d3d12/d3d12_replay.cpp @@ -1178,6 +1178,13 @@ bool D3D12Replay::RenderTexture(TextureDisplay cfg) return m_pDevice->GetDebugManager()->RenderTexture(cfg, true); } +bool D3D12Replay::GetMinMax(ResourceId texid, uint32_t sliceFace, uint32_t mip, uint32_t sample, + FormatComponentType typeHint, float *minval, float *maxval) +{ + return m_pDevice->GetDebugManager()->GetMinMax(texid, sliceFace, mip, sample, typeHint, minval, + maxval); +} + bool D3D12Replay::IsTextureSupported(const ResourceFormat &format) { return MakeDXGIFormat(format) != DXGI_FORMAT_UNKNOWN; @@ -1474,14 +1481,6 @@ void D3D12Replay::InitPostVSBuffers(const vector &passEvents) { } -bool D3D12Replay::GetMinMax(ResourceId texid, uint32_t sliceFace, uint32_t mip, uint32_t sample, - FormatComponentType typeHint, float *minval, float *maxval) -{ - *minval = 0.0f; - *maxval = 1.0f; - return false; -} - bool D3D12Replay::GetHistogram(ResourceId texid, uint32_t sliceFace, uint32_t mip, uint32_t sample, FormatComponentType typeHint, float minval, float maxval, bool channels[4], vector &histogram)