mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-13 21:40:41 +00:00
Implement histogram for D3D12
This commit is contained in:
@@ -623,6 +623,14 @@ D3D12DebugManager::D3D12DebugManager(WrappedID3D12Device *wrapper)
|
||||
tileDesc.Format = DXGI_FORMAT_R32G32B32A32_SINT;
|
||||
m_WrappedDevice->CreateUnorderedAccessView(m_MinMaxTileBuffer, NULL, &tileDesc, uav);
|
||||
|
||||
uav = cbvsrvuavHeap->GetCPUDescriptorHandleForHeapStart();
|
||||
uav.ptr += HISTOGRAM_UAV * sizeof(D3D12Descriptor);
|
||||
|
||||
// re-use the tile buffer for histogram
|
||||
tileDesc.Format = DXGI_FORMAT_R32_UINT;
|
||||
tileDesc.Buffer.NumElements = HGRAM_NUM_BUCKETS;
|
||||
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;
|
||||
@@ -2869,6 +2877,168 @@ bool D3D12DebugManager::GetMinMax(ResourceId texid, uint32_t sliceFace, uint32_t
|
||||
return true;
|
||||
}
|
||||
|
||||
bool D3D12DebugManager::GetHistogram(ResourceId texid, uint32_t sliceFace, uint32_t mip,
|
||||
uint32_t sample, FormatComponentType typeHint, float minval,
|
||||
float maxval, bool channels[4], vector<uint32_t> &histogram)
|
||||
{
|
||||
if(minval >= maxval)
|
||||
return false;
|
||||
|
||||
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 = minval;
|
||||
cdata.HistogramFlags = 0;
|
||||
|
||||
// The calculation in the shader normalises each value between min and max, then multiplies by the
|
||||
// number of buckets.
|
||||
// But any value equal to HistogramMax must go into NUM_BUCKETS-1, so add a small delta.
|
||||
cdata.HistogramMax = maxval + maxval * 1e-6f;
|
||||
|
||||
cdata.HistogramChannels = 0;
|
||||
if(channels[0])
|
||||
cdata.HistogramChannels |= 0x1;
|
||||
if(channels[1])
|
||||
cdata.HistogramChannels |= 0x2;
|
||||
if(channels[2])
|
||||
cdata.HistogramChannels |= 0x4;
|
||||
if(channels[3])
|
||||
cdata.HistogramChannels |= 0x8;
|
||||
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 tilesX = (int)ceil(cdata.HistogramTextureResolution.x /
|
||||
float(HGRAM_PIXELS_PER_TILE * HGRAM_TILES_PER_BLOCK));
|
||||
int tilesY = (int)ceil(cdata.HistogramTextureResolution.y /
|
||||
float(HGRAM_PIXELS_PER_TILE * HGRAM_TILES_PER_BLOCK));
|
||||
|
||||
vector<D3D12_RESOURCE_BARRIER> 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_HistogramPipe[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 += HISTOGRAM_UAV * sizeof(D3D12Descriptor);
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE uavcpu = cbvsrvuavHeap->GetCPUDescriptorHandleForHeapStart();
|
||||
|
||||
uavcpu.ptr += HISTOGRAM_UAV * sizeof(D3D12Descriptor);
|
||||
|
||||
UINT zeroes[] = {0, 0, 0, 0};
|
||||
list->ClearUnorderedAccessViewUint(uav, uavcpu, m_MinMaxTileBuffer, zeroes, 0, NULL);
|
||||
|
||||
list->SetComputeRootConstantBufferView(0, m_GenericVSCbuffer->GetGPUVirtualAddress());
|
||||
list->SetComputeRootDescriptorTable(1, srv);
|
||||
list->SetComputeRootDescriptorTable(2, samplerHeap->GetGPUDescriptorHandleForHeapStart());
|
||||
list->SetComputeRootDescriptorTable(3, uav);
|
||||
|
||||
list->Dispatch(tilesX, tilesY, 1);
|
||||
|
||||
D3D12_RESOURCE_BARRIER tileBarriers[2] = {};
|
||||
|
||||
// finish the UAV work, and transition to copy.
|
||||
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_COPY_SOURCE;
|
||||
|
||||
list->ResourceBarrier(2, tileBarriers);
|
||||
|
||||
// copy to readback
|
||||
list->CopyBufferRegion(m_ReadbackBuffer, 0, m_MinMaxTileBuffer, 0,
|
||||
sizeof(uint32_t) * HGRAM_NUM_BUCKETS);
|
||||
|
||||
// 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(uint32_t) * HGRAM_NUM_BUCKETS};
|
||||
|
||||
void *data = NULL;
|
||||
HRESULT hr = m_ReadbackBuffer->Map(0, &range, &data);
|
||||
|
||||
histogram.clear();
|
||||
histogram.resize(HGRAM_NUM_BUCKETS);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
RDCERR("Failed to map bufferdata buffer %08x", hr);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&histogram[0], data, sizeof(uint32_t) * HGRAM_NUM_BUCKETS);
|
||||
|
||||
range.End = 0;
|
||||
|
||||
m_ReadbackBuffer->Unmap(0, &range);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool D3D12DebugManager::RenderTextureInternal(D3D12_CPU_DESCRIPTOR_HANDLE rtv, TextureDisplay cfg,
|
||||
bool blendAlpha)
|
||||
{
|
||||
|
||||
@@ -76,6 +76,10 @@ public:
|
||||
bool GetMinMax(ResourceId texid, uint32_t sliceFace, uint32_t mip, uint32_t sample,
|
||||
FormatComponentType typeHint, float *minval, float *maxval);
|
||||
|
||||
bool GetHistogram(ResourceId texid, uint32_t sliceFace, uint32_t mip, uint32_t sample,
|
||||
FormatComponentType typeHint, float minval, float maxval, bool channels[4],
|
||||
vector<uint32_t> &histogram);
|
||||
|
||||
void PickPixel(ResourceId texture, uint32_t x, uint32_t y, uint32_t sliceFace, uint32_t mip,
|
||||
uint32_t sample, FormatComponentType typeHint, float pixel[4]);
|
||||
|
||||
@@ -130,6 +134,7 @@ private:
|
||||
|
||||
static const int MINMAX_TILE_UAVS = MINMAX_TILE_SRVS + 3;
|
||||
static const int MINMAX_RESULT_UAVS = MINMAX_TILE_UAVS + 3;
|
||||
static const int HISTOGRAM_UAV = MINMAX_RESULT_UAVS + 3;
|
||||
|
||||
enum
|
||||
{
|
||||
|
||||
@@ -1185,6 +1185,14 @@ bool D3D12Replay::GetMinMax(ResourceId texid, uint32_t sliceFace, uint32_t mip,
|
||||
maxval);
|
||||
}
|
||||
|
||||
bool D3D12Replay::GetHistogram(ResourceId texid, uint32_t sliceFace, uint32_t mip, uint32_t sample,
|
||||
FormatComponentType typeHint, float minval, float maxval,
|
||||
bool channels[4], vector<uint32_t> &histogram)
|
||||
{
|
||||
return m_pDevice->GetDebugManager()->GetHistogram(texid, sliceFace, mip, sample, typeHint, minval,
|
||||
maxval, channels, histogram);
|
||||
}
|
||||
|
||||
bool D3D12Replay::IsTextureSupported(const ResourceFormat &format)
|
||||
{
|
||||
return MakeDXGIFormat(format) != DXGI_FORMAT_UNKNOWN;
|
||||
@@ -1481,14 +1489,6 @@ void D3D12Replay::InitPostVSBuffers(const vector<uint32_t> &passEvents)
|
||||
{
|
||||
}
|
||||
|
||||
bool D3D12Replay::GetHistogram(ResourceId texid, uint32_t sliceFace, uint32_t mip, uint32_t sample,
|
||||
FormatComponentType typeHint, float minval, float maxval,
|
||||
bool channels[4], vector<uint32_t> &histogram)
|
||||
{
|
||||
histogram.resize(256, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
MeshFormat D3D12Replay::GetPostVSBuffers(uint32_t eventID, uint32_t instID, MeshDataStage stage)
|
||||
{
|
||||
return MeshFormat();
|
||||
|
||||
Reference in New Issue
Block a user