mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-09-24 14:45:53 +00:00
Bring across FillCBufferVariables from D3D11
* These implementations are identical and really only depend on DXBC - they should be shared.
This commit is contained in:
@@ -1391,6 +1391,362 @@ void D3D12DebugManager::PickPixel(ResourceId texture, uint32_t x, uint32_t y, ui
|
||||
m_ReadbackBuffer->Unmap(0, &range);
|
||||
}
|
||||
|
||||
void D3D12DebugManager::FillCBufferVariables(const string &prefix, size_t &offset, bool flatten,
|
||||
const vector<DXBC::CBufferVariable> &invars,
|
||||
vector<ShaderVariable> &outvars,
|
||||
const vector<byte> &data)
|
||||
{
|
||||
using namespace DXBC;
|
||||
using namespace ShaderDebug;
|
||||
|
||||
size_t o = offset;
|
||||
|
||||
for(size_t v = 0; v < invars.size(); v++)
|
||||
{
|
||||
size_t vec = o + invars[v].descriptor.offset / 16;
|
||||
size_t comp = (invars[v].descriptor.offset - (invars[v].descriptor.offset & ~0xf)) / 4;
|
||||
size_t sz = RDCMAX(1U, invars[v].type.descriptor.bytesize / 16);
|
||||
|
||||
offset = vec + sz;
|
||||
|
||||
string basename = prefix + invars[v].name;
|
||||
|
||||
uint32_t rows = invars[v].type.descriptor.rows;
|
||||
uint32_t cols = invars[v].type.descriptor.cols;
|
||||
uint32_t elems = RDCMAX(1U, invars[v].type.descriptor.elements);
|
||||
|
||||
if(!invars[v].type.members.empty())
|
||||
{
|
||||
char buf[64] = {0};
|
||||
StringFormat::snprintf(buf, 63, "[%d]", elems);
|
||||
|
||||
ShaderVariable var;
|
||||
var.name = basename;
|
||||
var.rows = var.columns = 0;
|
||||
var.type = eVar_Float;
|
||||
|
||||
std::vector<ShaderVariable> varmembers;
|
||||
|
||||
if(elems > 1)
|
||||
{
|
||||
for(uint32_t i = 0; i < elems; i++)
|
||||
{
|
||||
StringFormat::snprintf(buf, 63, "[%d]", i);
|
||||
|
||||
if(flatten)
|
||||
{
|
||||
FillCBufferVariables(basename + buf + ".", vec, flatten, invars[v].type.members,
|
||||
outvars, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
ShaderVariable vr;
|
||||
vr.name = basename + buf;
|
||||
vr.rows = vr.columns = 0;
|
||||
vr.type = eVar_Float;
|
||||
|
||||
std::vector<ShaderVariable> mems;
|
||||
|
||||
FillCBufferVariables("", vec, flatten, invars[v].type.members, mems, data);
|
||||
|
||||
vr.isStruct = true;
|
||||
|
||||
vr.members = mems;
|
||||
|
||||
varmembers.push_back(vr);
|
||||
}
|
||||
}
|
||||
|
||||
var.isStruct = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
var.isStruct = true;
|
||||
|
||||
if(flatten)
|
||||
FillCBufferVariables(basename + ".", vec, flatten, invars[v].type.members, outvars, data);
|
||||
else
|
||||
FillCBufferVariables("", vec, flatten, invars[v].type.members, varmembers, data);
|
||||
}
|
||||
|
||||
if(!flatten)
|
||||
{
|
||||
var.members = varmembers;
|
||||
outvars.push_back(var);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if(invars[v].type.descriptor.varClass == CLASS_OBJECT ||
|
||||
invars[v].type.descriptor.varClass == CLASS_STRUCT ||
|
||||
invars[v].type.descriptor.varClass == CLASS_INTERFACE_CLASS ||
|
||||
invars[v].type.descriptor.varClass == CLASS_INTERFACE_POINTER)
|
||||
{
|
||||
RDCWARN("Unexpected variable '%s' of class '%u' in cbuffer, skipping.",
|
||||
invars[v].name.c_str(), invars[v].type.descriptor.type);
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t elemByteSize = 4;
|
||||
VarType type = eVar_Float;
|
||||
switch(invars[v].type.descriptor.type)
|
||||
{
|
||||
case VARTYPE_INT: type = eVar_Int; break;
|
||||
case VARTYPE_FLOAT: type = eVar_Float; break;
|
||||
case VARTYPE_BOOL:
|
||||
case VARTYPE_UINT:
|
||||
case VARTYPE_UINT8: type = eVar_UInt; break;
|
||||
case VARTYPE_DOUBLE:
|
||||
elemByteSize = 8;
|
||||
type = eVar_Double;
|
||||
break;
|
||||
default:
|
||||
RDCERR("Unexpected type %d for variable '%s' in cbuffer", invars[v].type.descriptor.type,
|
||||
invars[v].name.c_str());
|
||||
}
|
||||
|
||||
bool columnMajor = invars[v].type.descriptor.varClass == CLASS_MATRIX_COLUMNS;
|
||||
|
||||
size_t outIdx = vec;
|
||||
if(!flatten)
|
||||
{
|
||||
outIdx = outvars.size();
|
||||
outvars.resize(RDCMAX(outIdx + 1, outvars.size()));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(columnMajor)
|
||||
outvars.resize(RDCMAX(outIdx + cols * elems, outvars.size()));
|
||||
else
|
||||
outvars.resize(RDCMAX(outIdx + rows * elems, outvars.size()));
|
||||
}
|
||||
|
||||
size_t dataOffset = vec * sizeof(Vec4f) + comp * sizeof(float);
|
||||
|
||||
if(outvars[outIdx].name.count > 0)
|
||||
{
|
||||
RDCASSERT(flatten);
|
||||
|
||||
RDCASSERT(outvars[vec].rows == 1);
|
||||
RDCASSERT(outvars[vec].columns == comp);
|
||||
RDCASSERT(rows == 1);
|
||||
|
||||
string combinedName = outvars[outIdx].name.elems;
|
||||
combinedName += ", " + basename;
|
||||
outvars[outIdx].name = combinedName;
|
||||
outvars[outIdx].rows = 1;
|
||||
outvars[outIdx].isStruct = false;
|
||||
outvars[outIdx].columns += cols;
|
||||
|
||||
if(dataOffset < data.size())
|
||||
{
|
||||
const byte *d = &data[dataOffset];
|
||||
|
||||
memcpy(&outvars[outIdx].value.uv[comp], d,
|
||||
RDCMIN(data.size() - dataOffset, elemByteSize * cols));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
outvars[outIdx].name = basename;
|
||||
outvars[outIdx].rows = 1;
|
||||
outvars[outIdx].type = type;
|
||||
outvars[outIdx].isStruct = false;
|
||||
outvars[outIdx].columns = cols;
|
||||
|
||||
ShaderVariable &var = outvars[outIdx];
|
||||
|
||||
bool isArray = invars[v].type.descriptor.elements > 1;
|
||||
|
||||
if(rows * elems == 1)
|
||||
{
|
||||
if(dataOffset < data.size())
|
||||
{
|
||||
const byte *d = &data[dataOffset];
|
||||
|
||||
memcpy(&outvars[outIdx].value.uv[flatten ? comp : 0], d,
|
||||
RDCMIN(data.size() - dataOffset, elemByteSize * cols));
|
||||
}
|
||||
}
|
||||
else if(!isArray && !flatten)
|
||||
{
|
||||
outvars[outIdx].rows = rows;
|
||||
|
||||
if(dataOffset < data.size())
|
||||
{
|
||||
const byte *d = &data[dataOffset];
|
||||
|
||||
RDCASSERT(rows <= 4 && rows * cols <= 16);
|
||||
|
||||
if(columnMajor)
|
||||
{
|
||||
uint32_t tmp[16] = {0};
|
||||
|
||||
// matrices always have 4 columns, for padding reasons (the same reason arrays
|
||||
// put every element on a new vec4)
|
||||
for(uint32_t c = 0; c < cols; c++)
|
||||
{
|
||||
size_t srcoffs = 4 * elemByteSize * c;
|
||||
size_t dstoffs = rows * elemByteSize * c;
|
||||
memcpy((byte *)(tmp) + dstoffs, d + srcoffs,
|
||||
RDCMIN(data.size() - dataOffset + srcoffs, elemByteSize * rows));
|
||||
}
|
||||
|
||||
// transpose
|
||||
for(size_t r = 0; r < rows; r++)
|
||||
for(size_t c = 0; c < cols; c++)
|
||||
outvars[outIdx].value.uv[r * cols + c] = tmp[c * rows + r];
|
||||
}
|
||||
else // CLASS_MATRIX_ROWS or other data not to transpose.
|
||||
{
|
||||
// matrices always have 4 columns, for padding reasons (the same reason arrays
|
||||
// put every element on a new vec4)
|
||||
for(uint32_t r = 0; r < rows; r++)
|
||||
{
|
||||
size_t srcoffs = 4 * elemByteSize * r;
|
||||
size_t dstoffs = cols * elemByteSize * r;
|
||||
memcpy((byte *)(&outvars[outIdx].value.uv[0]) + dstoffs, d + srcoffs,
|
||||
RDCMIN(data.size() - dataOffset + srcoffs, elemByteSize * cols));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(rows * elems > 1)
|
||||
{
|
||||
char buf[64] = {0};
|
||||
|
||||
var.name = outvars[outIdx].name;
|
||||
|
||||
vector<ShaderVariable> varmembers;
|
||||
vector<ShaderVariable> *out = &outvars;
|
||||
size_t rowCopy = 1;
|
||||
|
||||
uint32_t registers = rows;
|
||||
uint32_t regLen = cols;
|
||||
const char *regName = "row";
|
||||
|
||||
string base = outvars[outIdx].name.elems;
|
||||
|
||||
if(!flatten)
|
||||
{
|
||||
var.rows = 0;
|
||||
var.columns = 0;
|
||||
outIdx = 0;
|
||||
out = &varmembers;
|
||||
varmembers.resize(elems);
|
||||
rowCopy = rows;
|
||||
rows = 1;
|
||||
registers = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(columnMajor)
|
||||
{
|
||||
registers = cols;
|
||||
regLen = rows;
|
||||
regName = "col";
|
||||
}
|
||||
}
|
||||
|
||||
size_t rowDataOffset = vec * sizeof(Vec4f);
|
||||
|
||||
for(size_t r = 0; r < registers * elems; r++)
|
||||
{
|
||||
if(isArray && registers > 1)
|
||||
StringFormat::snprintf(buf, 63, "[%d].%s%d", r / registers, regName, r % registers);
|
||||
else if(registers > 1)
|
||||
StringFormat::snprintf(buf, 63, ".%s%d", regName, r);
|
||||
else
|
||||
StringFormat::snprintf(buf, 63, "[%d]", r);
|
||||
|
||||
(*out)[outIdx + r].name = base + buf;
|
||||
(*out)[outIdx + r].rows = (uint32_t)rowCopy;
|
||||
(*out)[outIdx + r].type = type;
|
||||
(*out)[outIdx + r].isStruct = false;
|
||||
(*out)[outIdx + r].columns = regLen;
|
||||
|
||||
size_t totalSize = 0;
|
||||
|
||||
if(flatten)
|
||||
{
|
||||
totalSize = elemByteSize * regLen;
|
||||
}
|
||||
else
|
||||
{
|
||||
// in a matrix, each major element before the last takes up a full
|
||||
// vec4 at least
|
||||
size_t vecSize = elemByteSize * 4;
|
||||
|
||||
if(columnMajor)
|
||||
totalSize = vecSize * (cols - 1) + elemByteSize * rowCopy;
|
||||
else
|
||||
totalSize = vecSize * (rowCopy - 1) + elemByteSize * cols;
|
||||
}
|
||||
|
||||
if((rowDataOffset % sizeof(Vec4f) != 0) &&
|
||||
(rowDataOffset / sizeof(Vec4f) != (rowDataOffset + totalSize) / sizeof(Vec4f)))
|
||||
{
|
||||
rowDataOffset = AlignUp(rowDataOffset, sizeof(Vec4f));
|
||||
}
|
||||
|
||||
if(rowDataOffset < data.size())
|
||||
{
|
||||
const byte *d = &data[rowDataOffset];
|
||||
|
||||
memcpy(&((*out)[outIdx + r].value.uv[0]), d,
|
||||
RDCMIN(data.size() - rowDataOffset, totalSize));
|
||||
|
||||
if(!flatten && columnMajor)
|
||||
{
|
||||
ShaderVariable tmp = (*out)[outIdx + r];
|
||||
|
||||
size_t transposeRows = rowCopy > 1 ? 4 : 1;
|
||||
|
||||
// transpose
|
||||
for(size_t ri = 0; ri < transposeRows; ri++)
|
||||
for(size_t ci = 0; ci < cols; ci++)
|
||||
(*out)[outIdx + r].value.uv[ri * cols + ci] = tmp.value.uv[ci * transposeRows + ri];
|
||||
}
|
||||
}
|
||||
|
||||
if(flatten)
|
||||
{
|
||||
rowDataOffset += sizeof(Vec4f);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(columnMajor)
|
||||
rowDataOffset += sizeof(Vec4f) * (cols - 1) + sizeof(float) * rowCopy;
|
||||
else
|
||||
rowDataOffset += sizeof(Vec4f) * (rowCopy - 1) + sizeof(float) * cols;
|
||||
}
|
||||
}
|
||||
|
||||
if(!flatten)
|
||||
{
|
||||
var.isStruct = false;
|
||||
var.members = varmembers;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void D3D12DebugManager::FillCBufferVariables(const vector<DXBC::CBufferVariable> &invars,
|
||||
vector<ShaderVariable> &outvars, bool flattenVec4s,
|
||||
const vector<byte> &data)
|
||||
{
|
||||
size_t zero = 0;
|
||||
|
||||
vector<ShaderVariable> v;
|
||||
FillCBufferVariables("", zero, flattenVec4s, invars, v, data);
|
||||
|
||||
outvars.reserve(v.size());
|
||||
for(size_t i = 0; i < v.size(); i++)
|
||||
outvars.push_back(v[i]);
|
||||
}
|
||||
|
||||
void D3D12DebugManager::GetBufferData(ResourceId buff, uint64_t offset, uint64_t length,
|
||||
vector<byte> &retData)
|
||||
{
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include "api/replay/renderdoc_replay.h"
|
||||
#include "core/core.h"
|
||||
#include "driver/shaders/dxbc/dxbc_debug.h"
|
||||
#include "replay/replay_driver.h"
|
||||
#include "d3d12_common.h"
|
||||
|
||||
@@ -73,6 +74,10 @@ public:
|
||||
void PickPixel(ResourceId texture, uint32_t x, uint32_t y, uint32_t sliceFace, uint32_t mip,
|
||||
uint32_t sample, FormatComponentType typeHint, float pixel[4]);
|
||||
|
||||
void FillCBufferVariables(const vector<DXBC::CBufferVariable> &invars,
|
||||
vector<ShaderVariable> &outvars, bool flattenVec4s,
|
||||
const vector<byte> &data);
|
||||
|
||||
void GetBufferData(ResourceId buff, uint64_t offset, uint64_t length, vector<byte> &retData);
|
||||
void GetBufferData(ID3D12Resource *buff, uint64_t offset, uint64_t length, vector<byte> &retData);
|
||||
|
||||
@@ -190,6 +195,10 @@ private:
|
||||
bool m_ShaderCacheDirty, m_CacheShaders;
|
||||
map<uint32_t, ID3DBlob *> m_ShaderCache;
|
||||
|
||||
void FillCBufferVariables(const string &prefix, size_t &offset, bool flatten,
|
||||
const vector<DXBC::CBufferVariable> &invars,
|
||||
vector<ShaderVariable> &outvars, const vector<byte> &data);
|
||||
|
||||
void RenderTextInternal(ID3D12GraphicsCommandList *list, float x, float y, const char *text);
|
||||
bool RenderTextureInternal(D3D12_CPU_DESCRIPTOR_HANDLE rtv, TextureDisplay cfg, bool blendAlpha);
|
||||
|
||||
|
||||
@@ -1316,7 +1316,84 @@ void D3D12Replay::RenderHighlightBox(float w, float h, float scale)
|
||||
void D3D12Replay::FillCBufferVariables(ResourceId shader, string entryPoint, uint32_t cbufSlot,
|
||||
vector<ShaderVariable> &outvars, const vector<byte> &data)
|
||||
{
|
||||
return;
|
||||
if(shader == ResourceId())
|
||||
return;
|
||||
|
||||
ID3D12DeviceChild *res = m_pDevice->GetResourceManager()->GetCurrentResource(shader);
|
||||
|
||||
if(!WrappedID3D12PipelineState::ShaderEntry::IsAlloc(res))
|
||||
{
|
||||
RDCERR("Shader ID %llu does not correspond to a known fake shader", shader);
|
||||
return;
|
||||
}
|
||||
|
||||
WrappedID3D12PipelineState::ShaderEntry *sh = (WrappedID3D12PipelineState::ShaderEntry *)res;
|
||||
|
||||
DXBC::DXBCFile *dxbc = sh->GetDXBC();
|
||||
const ShaderBindpointMapping &bindMap = sh->GetMapping();
|
||||
|
||||
RDCASSERT(dxbc);
|
||||
|
||||
DXBC::CBuffer *cb = NULL;
|
||||
|
||||
uint32_t idx = 0;
|
||||
for(size_t i = 0; i < dxbc->m_CBuffers.size(); i++)
|
||||
{
|
||||
if(dxbc->m_CBuffers[i].descriptor.type != DXBC::CBuffer::Descriptor::TYPE_CBUFFER)
|
||||
continue;
|
||||
|
||||
if(idx == cbufSlot)
|
||||
cb = &dxbc->m_CBuffers[i];
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
if(cb && cbufSlot < (uint32_t)bindMap.ConstantBlocks.count)
|
||||
{
|
||||
// check if the data actually comes from root constants
|
||||
|
||||
const D3D12RenderState &rs = m_pDevice->GetQueue()->GetCommandData()->m_RenderState;
|
||||
BindpointMap bind = bindMap.ConstantBlocks[cbufSlot];
|
||||
|
||||
WrappedID3D12RootSignature *sig = NULL;
|
||||
const vector<D3D12RenderState::SignatureElement> *sigElems = NULL;
|
||||
|
||||
if(dxbc->m_Type == D3D11_ShaderType_Compute && rs.compute.rootsig != ResourceId())
|
||||
{
|
||||
sig = m_pDevice->GetResourceManager()->GetCurrentAs<WrappedID3D12RootSignature>(
|
||||
rs.compute.rootsig);
|
||||
sigElems = &rs.compute.sigelems;
|
||||
}
|
||||
else if(dxbc->m_Type != D3D11_ShaderType_Compute && rs.graphics.rootsig != ResourceId())
|
||||
{
|
||||
sig = m_pDevice->GetResourceManager()->GetCurrentAs<WrappedID3D12RootSignature>(
|
||||
rs.graphics.rootsig);
|
||||
sigElems = &rs.graphics.sigelems;
|
||||
}
|
||||
|
||||
vector<byte> rootData;
|
||||
|
||||
for(size_t i = 0; sig && i < sig->sig.params.size(); i++)
|
||||
{
|
||||
const D3D12RootSignatureParameter &p = sig->sig.params[i];
|
||||
|
||||
if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS &&
|
||||
p.Constants.RegisterSpace == (UINT)bind.bindset &&
|
||||
p.Constants.ShaderRegister == (UINT)bind.bind)
|
||||
{
|
||||
rootData.resize(sig->sig.params[i].Constants.Num32BitValues);
|
||||
|
||||
if(i < sigElems->size() && (*sigElems)[i].type == eRootConst)
|
||||
{
|
||||
memcpy(&rootData[0], &(*sigElems)[i].constants[0],
|
||||
RDCMIN((*sigElems)[i].constants.size() * sizeof(uint32_t), rootData.size()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_pDevice->GetDebugManager()->FillCBufferVariables(cb->variables, outvars, false,
|
||||
rootData.empty() ? data : rootData);
|
||||
}
|
||||
}
|
||||
|
||||
vector<PixelModification> D3D12Replay::PixelHistory(vector<EventUsage> events, ResourceId target,
|
||||
|
||||
Reference in New Issue
Block a user