From 0faf0931c2278114c76d10e9f96ab231bf368711 Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 31 Aug 2017 12:17:43 +0100 Subject: [PATCH] Ditch D3D11's anomalous identity bindpoint mapping for proper handling --- .../Code/Interface/CommonPipelineState.cpp | 16 +- qrenderdoc/Windows/BufferViewer.cpp | 40 +- .../D3D11PipelineStateViewer.cpp | 113 ++++-- .../PipelineState/D3D11PipelineStateViewer.h | 2 +- renderdoc/driver/d3d11/d3d11_common.cpp | 313 --------------- renderdoc/driver/d3d11/d3d11_common.h | 2 - renderdoc/driver/d3d11/d3d11_replay.cpp | 65 +-- renderdoc/driver/d3d11/d3d11_resources.cpp | 14 + renderdoc/driver/d3d11/d3d11_resources.h | 40 +- renderdoc/driver/d3d12/d3d12_common.cpp | 353 ----------------- renderdoc/driver/d3d12/d3d12_common.h | 3 - renderdoc/driver/d3d12/d3d12_resources.cpp | 14 + renderdoc/driver/d3d12/d3d12_resources.h | 10 +- .../driver/shaders/dxbc/dxbc_reflect.cpp | 370 ++++++++++++++++++ renderdoc/driver/shaders/dxbc/dxbc_reflect.h | 38 ++ .../shaders/dxbc/renderdoc_dxbc.vcxproj | 4 +- .../dxbc/renderdoc_dxbc.vcxproj.filters | 2 + 17 files changed, 591 insertions(+), 808 deletions(-) create mode 100644 renderdoc/driver/shaders/dxbc/dxbc_reflect.cpp create mode 100644 renderdoc/driver/shaders/dxbc/dxbc_reflect.h diff --git a/qrenderdoc/Code/Interface/CommonPipelineState.cpp b/qrenderdoc/Code/Interface/CommonPipelineState.cpp index 8000a20be..c387c1053 100644 --- a/qrenderdoc/Code/Interface/CommonPipelineState.cpp +++ b/qrenderdoc/Code/Interface/CommonPipelineState.cpp @@ -890,11 +890,19 @@ BoundCBuffer CommonPipelineState::GetConstantBuffer(ShaderStage stage, uint32_t { const D3D11Pipe::Shader &s = GetD3D11Stage(stage); - if(BufIdx < (uint32_t)s.ConstantBuffers.count) + if(s.ShaderDetails != NULL && BufIdx < (uint32_t)s.ShaderDetails->ConstantBlocks.count) { - buf = s.ConstantBuffers[BufIdx].Buffer; - ByteOffset = s.ConstantBuffers[BufIdx].VecOffset * 4 * sizeof(float); - ByteSize = s.ConstantBuffers[BufIdx].VecCount * 4 * sizeof(float); + const BindpointMap &bind = + s.BindpointMapping.ConstantBlocks[s.ShaderDetails->ConstantBlocks[BufIdx].bindPoint]; + + if(bind.bind >= s.ConstantBuffers.count) + return BoundCBuffer(); + + const D3D11Pipe::CBuffer &descriptor = s.ConstantBuffers[bind.bind]; + + buf = descriptor.Buffer; + ByteOffset = descriptor.VecOffset * 4 * sizeof(float); + ByteSize = descriptor.VecCount * 4 * sizeof(float); } } else if(IsLogD3D12()) diff --git a/qrenderdoc/Windows/BufferViewer.cpp b/qrenderdoc/Windows/BufferViewer.cpp index 0adfe055e..4df27515a 100644 --- a/qrenderdoc/Windows/BufferViewer.cpp +++ b/qrenderdoc/Windows/BufferViewer.cpp @@ -1411,13 +1411,15 @@ void BufferViewer::OnEventChanged(uint32_t eventID) m_Ctx.Replay().AsyncInvoke([this, vsinHoriz, vsoutHoriz, gsoutHoriz](IReplayController *r) { + BufferData *buf = NULL; + if(m_MeshView) { RT_FetchMeshData(r); } else { - BufferData *buf = new BufferData; + buf = new BufferData; rdctype::array data; if(m_IsBuffer) { @@ -1435,25 +1437,31 @@ void BufferViewer::OnEventChanged(uint32_t eventID) buf->data = new byte[data.count]; memcpy(buf->data, data.elems, data.count); buf->end = buf->data + data.count; - - // calculate tight stride - buf->stride = 0; - for(const FormatElement &el : m_ModelVSIn->columns) - buf->stride += el.byteSize(); - - buf->stride = qMax((size_t)1, buf->stride); - - m_ModelVSIn->numRows = uint32_t((data.count + buf->stride - 1) / buf->stride); - - // ownership passes to model - m_ModelVSIn->buffers.push_back(buf); } - updatePreviewColumns(); + GUIInvoke::call([this, buf, vsinHoriz, vsoutHoriz, gsoutHoriz] { - RT_UpdateAndDisplay(r); + if(buf) + { + // calculate tight stride + buf->stride = 0; + for(const FormatElement &el : m_ModelVSIn->columns) + buf->stride += el.byteSize(); + + buf->stride = qMax((size_t)1, buf->stride); + + uint32_t bufCount = uint32_t(buf->end - buf->data); + + m_ModelVSIn->numRows = uint32_t((bufCount + buf->stride - 1) / buf->stride); + + // ownership passes to model + m_ModelVSIn->buffers.push_back(buf); + } + + updatePreviewColumns(); + + INVOKE_MEMFN(RT_UpdateAndDisplay); - GUIInvoke::call([this, vsinHoriz, vsoutHoriz, gsoutHoriz] { m_ModelVSIn->endReset(); m_ModelVSOut->endReset(); m_ModelGSOut->endReset(); diff --git a/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp index 1ef805c8c..f7de57754 100644 --- a/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp @@ -233,7 +233,7 @@ D3D11PipelineStateViewer::D3D11PipelineStateViewer(ICaptureContext &ctx, RDHeaderView *header = new RDHeaderView(Qt::Horizontal, this); cbuffer->setHeader(header); - cbuffer->setColumns({tr("Slot"), tr("Buffer"), tr("Byte Range"), tr("Size"), tr("Go")}); + cbuffer->setColumns({tr("Slot"), tr("Buffer"), tr("Vec4 Range"), tr("Size"), tr("Go")}); header->setColumnStretchHints({1, 2, 3, 3, -1}); cbuffer->setHoverIconColumn(4, action, action_hover); @@ -580,7 +580,7 @@ void D3D11PipelineStateViewer::setViewDetails(RDTreeWidgetItem *node, const D3D1 void D3D11PipelineStateViewer::addResourceRow(const D3D11ViewTag &view, const ShaderResource *shaderInput, - RDTreeWidget *resources) + const BindpointMap *map, RDTreeWidget *resources) { const D3D11Pipe::View &r = view.res; @@ -591,7 +591,7 @@ void D3D11PipelineStateViewer::addResourceRow(const D3D11ViewTag &view, m_Ctx.CurD3D11PipelineState().m_OM.StencilReadOnly; bool filledSlot = (r.Resource != ResourceId()); - bool usedSlot = (shaderInput); + bool usedSlot = (map && map->used); // if a target is set to RTVs or DSV, it is implicitly used if(filledSlot) @@ -845,6 +845,7 @@ void D3D11PipelineStateViewer::setShaderState(const D3D11Pipe::Shader &stage, QL RDTreeWidget *cbuffers, RDTreeWidget *classes) { ShaderReflection *shaderDetails = stage.ShaderDetails; + const ShaderBindpointMapping &mapping = stage.BindpointMapping; if(stage.Object == ResourceId()) shader->setText(tr("Unbound Shader")); @@ -866,20 +867,25 @@ void D3D11PipelineStateViewer::setShaderState(const D3D11Pipe::Shader &stage, QL for(int i = 0; i < stage.SRVs.count; i++) { const ShaderResource *shaderInput = NULL; + const BindpointMap *map = NULL; if(shaderDetails) { - for(const ShaderResource &bind : shaderDetails->ReadOnlyResources) + for(int b = 0; b < shaderDetails->ReadOnlyResources.count; b++) { - if(!bind.IsSampler && bind.IsReadOnly && bind.bindPoint == i) + const ShaderResource &res = shaderDetails->ReadOnlyResources[b]; + const BindpointMap &bind = mapping.ReadOnlyResources[b]; + + if(!res.IsSampler && res.IsReadOnly && bind.bind == i) { - shaderInput = &bind; + shaderInput = &res; + map = &bind; break; } } } - addResourceRow(D3D11ViewTag(D3D11ViewTag::SRV, i, stage.SRVs[i]), shaderInput, resources); + addResourceRow(D3D11ViewTag(D3D11ViewTag::SRV, i, stage.SRVs[i]), shaderInput, map, resources); } resources->clearSelection(); resources->endUpdate(); @@ -893,21 +899,26 @@ void D3D11PipelineStateViewer::setShaderState(const D3D11Pipe::Shader &stage, QL const D3D11Pipe::Sampler &s = stage.Samplers[i]; const ShaderResource *shaderInput = NULL; + const BindpointMap *map = NULL; if(shaderDetails) { - for(const ShaderResource &bind : shaderDetails->ReadOnlyResources) + for(int b = 0; b < shaderDetails->ReadOnlyResources.count; b++) { - if(bind.IsSampler && bind.bindPoint == i) + const ShaderResource &res = shaderDetails->ReadOnlyResources[b]; + const BindpointMap &bind = mapping.ReadOnlyResources[b]; + + if(res.IsSampler && bind.bind == i) { - shaderInput = &bind; + shaderInput = &res; + map = &bind; break; } } } bool filledSlot = s.Samp != ResourceId(); - bool usedSlot = (shaderInput); + bool usedSlot = (map && map->used); if(showNode(usedSlot, filledSlot)) { @@ -995,26 +1006,26 @@ void D3D11PipelineStateViewer::setShaderState(const D3D11Pipe::Shader &stage, QL const D3D11Pipe::CBuffer &b = stage.ConstantBuffers[i]; const ConstantBlock *shaderCBuf = NULL; - - int cbufIdx = -1; + const BindpointMap *map = NULL; if(shaderDetails) { for(int cb = 0; cb < shaderDetails->ConstantBlocks.count; cb++) { - const ConstantBlock &bind = shaderDetails->ConstantBlocks[cb]; + const ConstantBlock &cbuf = shaderDetails->ConstantBlocks[cb]; + const BindpointMap &bind = mapping.ConstantBlocks[cb]; - if(bind.bindPoint == i) + if(bind.bind == i) { - shaderCBuf = &bind; - cbufIdx = cb; + shaderCBuf = &cbuf; + map = &bind; break; } } } bool filledSlot = b.Buffer != ResourceId(); - bool usedSlot = shaderCBuf; + bool usedSlot = (map && map->used); if(showNode(usedSlot, filledSlot)) { @@ -1056,7 +1067,7 @@ void D3D11PipelineStateViewer::setShaderState(const D3D11Pipe::Shader &stage, QL RDTreeWidgetItem *node = new RDTreeWidgetItem({slotname, name, vecrange, sizestr, QString()}); - node->setTag(QVariant::fromValue(cbufIdx)); + node->setTag(QVariant::fromValue(i)); if(!filledSlot) setEmptyRow(node); @@ -1409,20 +1420,28 @@ void D3D11PipelineStateViewer::setState() for(int i = 0; i < state.m_CS.UAVs.count; i++) { const ShaderResource *shaderInput = NULL; + const BindpointMap *map = NULL; - if(state.m_CS.ShaderDetails) + const D3D11Pipe::Shader &cs = state.m_CS; + + if(cs.ShaderDetails) { - for(const ShaderResource &bind : state.m_CS.ShaderDetails->ReadWriteResources) + for(int b = 0; b < cs.ShaderDetails->ReadWriteResources.count; b++) { - if(bind.bindPoint == i) + const ShaderResource &res = cs.ShaderDetails->ReadWriteResources[b]; + const BindpointMap &bind = cs.BindpointMapping.ReadWriteResources[b]; + + if(bind.bind == i) { - shaderInput = &bind; + shaderInput = &res; + map = &bind; break; } } } - addResourceRow(D3D11ViewTag(D3D11ViewTag::UAV, i, state.m_CS.UAVs[i]), shaderInput, ui->csUAVs); + addResourceRow(D3D11ViewTag(D3D11ViewTag::UAV, i, state.m_CS.UAVs[i]), shaderInput, map, + ui->csUAVs); } ui->csUAVs->clearSelection(); ui->csUAVs->endUpdate(); @@ -1558,7 +1577,7 @@ void D3D11PipelineStateViewer::setState() for(int i = 0; i < state.m_OM.RenderTargets.count; i++) { addResourceRow(D3D11ViewTag(D3D11ViewTag::OMTarget, i, state.m_OM.RenderTargets[i]), NULL, - ui->targetOutputs); + NULL, ui->targetOutputs); if(state.m_OM.RenderTargets[i].Resource != ResourceId()) targets[i] = true; @@ -1567,6 +1586,7 @@ void D3D11PipelineStateViewer::setState() for(int i = 0; i < state.m_OM.UAVs.count; i++) { const ShaderResource *shaderInput = NULL; + const BindpointMap *map = NULL; // any non-CS shader can use these. When that's not supported (Before feature level 11.1) // this search will just boil down to only PS. @@ -1578,22 +1598,25 @@ void D3D11PipelineStateViewer::setState() { if(stage->ShaderDetails) { - for(const ShaderResource &bind : stage->ShaderDetails->ReadWriteResources) + for(int b = 0; b < stage->ShaderDetails->ReadOnlyResources.count; b++) { - if(bind.bindPoint == i + (int)state.m_OM.UAVStartSlot) + const ShaderResource &res = stage->ShaderDetails->ReadOnlyResources[b]; + const BindpointMap &bind = stage->BindpointMapping.ReadOnlyResources[b]; + + if(bind.bind == i + (int)state.m_OM.UAVStartSlot) { - shaderInput = &bind; + shaderInput = &res; + map = &bind; break; } } } } - - addResourceRow(D3D11ViewTag(D3D11ViewTag::UAV, i, state.m_OM.UAVs[i]), shaderInput, + addResourceRow(D3D11ViewTag(D3D11ViewTag::UAV, i, state.m_OM.UAVs[i]), shaderInput, map, ui->targetOutputs); } - addResourceRow(D3D11ViewTag(D3D11ViewTag::OMDepth, 0, state.m_OM.DepthTarget), NULL, + addResourceRow(D3D11ViewTag(D3D11ViewTag::OMDepth, 0, state.m_OM.DepthTarget), NULL, NULL, ui->targetOutputs); } ui->targetOutputs->clearSelection(); @@ -2031,7 +2054,33 @@ void D3D11PipelineStateViewer::cbuffer_itemActivated(RDTreeWidgetItem *item, int int cb = tag.value(); - IConstantBufferPreviewer *prev = m_Ctx.ViewConstantBuffer(stage->stage, cb, 0); + int cbufIdx = -1; + + for(int i = 0; i < stage->BindpointMapping.ConstantBlocks.count; i++) + { + if(stage->BindpointMapping.ConstantBlocks[i].bind == cb) + { + cbufIdx = i; + break; + } + } + + if(cbufIdx == -1) + { + // unused cbuffer, open regular buffer viewer + if(cb >= stage->ConstantBuffers.count) + return; + + const D3D11Pipe::CBuffer &bind = stage->ConstantBuffers[cb]; + + IBufferViewer *viewer = m_Ctx.ViewBuffer(bind.VecOffset * sizeof(float) * 4, + bind.VecCount * sizeof(float) * 4, bind.Buffer); + + m_Ctx.AddDockWindow(viewer->Widget(), DockReference::AddTo, this); + return; + } + + IConstantBufferPreviewer *prev = m_Ctx.ViewConstantBuffer(stage->stage, cbufIdx, 0); m_Ctx.AddDockWindow(prev->Widget(), DockReference::ConstantBufferArea, this, 0.3f); } diff --git a/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.h b/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.h index c3b9464f3..38c059699 100644 --- a/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.h +++ b/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.h @@ -86,7 +86,7 @@ private: RDTreeWidget *samp, RDTreeWidget *cbuffer, RDTreeWidget *classes); void addResourceRow(const D3D11ViewTag &view, const ShaderResource *shaderInput, - RDTreeWidget *resources); + const BindpointMap *map, RDTreeWidget *resources); void clearShaderState(QLabel *shader, RDTreeWidget *tex, RDTreeWidget *samp, RDTreeWidget *cbuffer, RDTreeWidget *classes); diff --git a/renderdoc/driver/d3d11/d3d11_common.cpp b/renderdoc/driver/d3d11/d3d11_common.cpp index b9d900d3c..be12e5871 100644 --- a/renderdoc/driver/d3d11/d3d11_common.cpp +++ b/renderdoc/driver/d3d11/d3d11_common.cpp @@ -719,319 +719,6 @@ StencilOp MakeStencilOp(D3D11_STENCIL_OP op) return StencilOp::Keep; } -static ShaderConstant MakeConstantBufferVariable(const DXBC::CBufferVariable &var, uint32_t &offset); - -static ShaderVariableType MakeShaderVariableType(DXBC::CBufferVariableType type, uint32_t &offset) -{ - ShaderVariableType ret; - - switch(type.descriptor.type) - { - case DXBC::VARTYPE_MIN12INT: - case DXBC::VARTYPE_MIN16INT: - case DXBC::VARTYPE_INT: ret.descriptor.type = VarType::Int; break; - case DXBC::VARTYPE_BOOL: - case DXBC::VARTYPE_MIN16UINT: - case DXBC::VARTYPE_UINT: ret.descriptor.type = VarType::UInt; break; - case DXBC::VARTYPE_DOUBLE: ret.descriptor.type = VarType::Double; break; - case DXBC::VARTYPE_FLOAT: - case DXBC::VARTYPE_MIN8FLOAT: - case DXBC::VARTYPE_MIN10FLOAT: - case DXBC::VARTYPE_MIN16FLOAT: - default: ret.descriptor.type = VarType::Float; break; - } - ret.descriptor.rows = (uint8_t)type.descriptor.rows; - ret.descriptor.cols = (uint8_t)type.descriptor.cols; - ret.descriptor.elements = type.descriptor.elements; - ret.descriptor.name = type.descriptor.name; - ret.descriptor.rowMajorStorage = (type.descriptor.varClass == DXBC::CLASS_MATRIX_ROWS); - - uint32_t baseElemSize = (ret.descriptor.type == VarType::Double) ? 8 : 4; - if(ret.descriptor.rowMajorStorage) - { - uint32_t primary = ret.descriptor.rows; - if(primary == 3) - primary = 4; - ret.descriptor.arrayStride = baseElemSize * primary * ret.descriptor.cols; - } - else - { - uint32_t primary = ret.descriptor.cols; - if(primary == 3) - primary = 4; - ret.descriptor.arrayStride = baseElemSize * primary * ret.descriptor.rows; - } - - uint32_t o = offset; - - create_array_uninit(ret.members, type.members.size()); - for(size_t i = 0; i < type.members.size(); i++) - { - offset = o; - ret.members[i] = MakeConstantBufferVariable(type.members[i], offset); - } - - if(ret.members.count > 0) - { - ret.descriptor.rows = 0; - ret.descriptor.cols = 0; - ret.descriptor.elements = 0; - } - - return ret; -} - -static ShaderConstant MakeConstantBufferVariable(const DXBC::CBufferVariable &var, uint32_t &offset) -{ - ShaderConstant ret; - - ret.name = var.name; - ret.reg.vec = offset + var.descriptor.offset / 16; - ret.reg.comp = (var.descriptor.offset - (var.descriptor.offset & ~0xf)) / 4; - ret.defaultValue = 0; - - offset = ret.reg.vec; - - ret.type = MakeShaderVariableType(var.type, offset); - - offset = ret.reg.vec + RDCMAX(1U, var.type.descriptor.bytesize / 16); - - return ret; -} - -ShaderReflection *MakeShaderReflection(DXBC::DXBCFile *dxbc) -{ - if(dxbc == NULL || !RenderDoc::Inst().IsReplayApp()) - return NULL; - - ShaderReflection *ret = new ShaderReflection(); - - if(dxbc->m_DebugInfo) - { - ret->DebugInfo.compileFlags = DXBC::EncodeFlags(dxbc->m_DebugInfo); - - create_array_uninit(ret->DebugInfo.files, dxbc->m_DebugInfo->Files.size()); - for(size_t i = 0; i < dxbc->m_DebugInfo->Files.size(); i++) - { - ret->DebugInfo.files[i].first = dxbc->m_DebugInfo->Files[i].first; - ret->DebugInfo.files[i].second = dxbc->m_DebugInfo->Files[i].second; - } - - string entry = dxbc->m_DebugInfo->GetEntryFunction(); - if(entry.empty()) - entry = "main"; - - // sort the file with the entry point to the start. We don't have to do anything if there's only - // one file. - // This isn't a perfect search - it will match entry_point() anywhere in the file, even if it's - // in a comment or disabled preprocessor definition. This is just best-effort - if(ret->DebugInfo.files.count > 1) - { - // search from 0 up. If we find a match, we swap it into [0]. If we don't find a match then - // we can't rearrange anything. This is a no-op for 0 since it's already in first place, but - // since our search isn't perfect we might have multiple matches with some being false - // positives, and so we want to bias towards leaving [0] in place. - for(int32_t i = 0; i < ret->DebugInfo.files.count; i++) - { - char *c = strstr(ret->DebugInfo.files[i].first.elems, entry.c_str()); - char *end = ret->DebugInfo.files[i].first.elems + ret->DebugInfo.files[i].first.count; - - // no substring match? continue - if(c == NULL) - continue; - - // if we did get a substring match, ensure there's whitespace preceeding it. - if(c == entry.c_str() || !isspace((int)*(c - 1))) - continue; - - // skip past the entry point. Then skip any whitespace - c += entry.size(); - - // check for EOF. - if(c >= end) - continue; - - while(c < end && isspace(*c)) - c++; - - if(c >= end) - continue; - - // if there's an open bracket next, we found a entry_point( which we count as the - // declaration. - if(*c == '(') - { - // only do anything if we're looking at a later file - if(i > 0) - std::swap(ret->DebugInfo.files[0], ret->DebugInfo.files[i]); - - break; - } - } - } - } - - if(dxbc->m_ShaderBlob.empty()) - create_array_uninit(ret->RawBytes, 0); - else - create_array_init(ret->RawBytes, dxbc->m_ShaderBlob.size(), &dxbc->m_ShaderBlob[0]); - - ret->DispatchThreadsDimension[0] = dxbc->DispatchThreadsDimension[0]; - ret->DispatchThreadsDimension[1] = dxbc->DispatchThreadsDimension[1]; - ret->DispatchThreadsDimension[2] = dxbc->DispatchThreadsDimension[2]; - - ret->InputSig = dxbc->m_InputSig; - ret->OutputSig = dxbc->m_OutputSig; - - create_array_uninit(ret->ConstantBlocks, dxbc->m_CBuffers.size()); - for(size_t i = 0; i < dxbc->m_CBuffers.size(); i++) - { - ConstantBlock &cb = ret->ConstantBlocks[i]; - cb.name = dxbc->m_CBuffers[i].name; - cb.bufferBacked = dxbc->m_CBuffers[i].descriptor.type == DXBC::CBuffer::Descriptor::TYPE_CBUFFER; - cb.byteSize = dxbc->m_CBuffers[i].descriptor.byteSize; - cb.bindPoint = dxbc->m_CBuffers[i].reg; - - create_array_uninit(cb.variables, dxbc->m_CBuffers[i].variables.size()); - for(size_t v = 0; v < dxbc->m_CBuffers[i].variables.size(); v++) - { - uint32_t vecOffset = 0; - cb.variables[v] = MakeConstantBufferVariable(dxbc->m_CBuffers[i].variables[v], vecOffset); - } - } - - int numRWResources = 0; - int numROResources = 0; - - for(size_t i = 0; i < dxbc->m_Resources.size(); i++) - { - const auto &r = dxbc->m_Resources[i]; - - if(r.type != DXBC::ShaderInputBind::TYPE_CBUFFER) - { - bool IsReadOnly = (r.type == DXBC::ShaderInputBind::TYPE_TBUFFER || - r.type == DXBC::ShaderInputBind::TYPE_TEXTURE || - r.type == DXBC::ShaderInputBind::TYPE_SAMPLER || - r.type == DXBC::ShaderInputBind::TYPE_STRUCTURED || - r.type == DXBC::ShaderInputBind::TYPE_BYTEADDRESS); - - if(IsReadOnly) - numROResources++; - else - numRWResources++; - } - } - - create_array_uninit(ret->ReadWriteResources, numRWResources); - create_array_uninit(ret->ReadOnlyResources, numROResources); - - int32_t rwidx = 0, roidx = 0; - for(size_t i = 0; i < dxbc->m_Resources.size(); i++) - { - const auto &r = dxbc->m_Resources[i]; - - if(r.type == DXBC::ShaderInputBind::TYPE_CBUFFER) - continue; - - ShaderResource res; - res.bindPoint = r.reg; - res.name = r.name; - - res.IsSampler = (r.type == DXBC::ShaderInputBind::TYPE_SAMPLER); - res.IsTexture = (r.type == DXBC::ShaderInputBind::TYPE_TEXTURE && - r.dimension != DXBC::ShaderInputBind::DIM_UNKNOWN && - r.dimension != DXBC::ShaderInputBind::DIM_BUFFER && - r.dimension != DXBC::ShaderInputBind::DIM_BUFFEREX); - res.IsReadOnly = (r.type == DXBC::ShaderInputBind::TYPE_TBUFFER || - r.type == DXBC::ShaderInputBind::TYPE_TEXTURE || - r.type == DXBC::ShaderInputBind::TYPE_SAMPLER || - r.type == DXBC::ShaderInputBind::TYPE_STRUCTURED || - r.type == DXBC::ShaderInputBind::TYPE_BYTEADDRESS); - - switch(r.dimension) - { - default: - case DXBC::ShaderInputBind::DIM_UNKNOWN: res.resType = TextureDim::Unknown; break; - case DXBC::ShaderInputBind::DIM_BUFFER: - case DXBC::ShaderInputBind::DIM_BUFFEREX: res.resType = TextureDim::Buffer; break; - case DXBC::ShaderInputBind::DIM_TEXTURE1D: res.resType = TextureDim::Texture1D; break; - case DXBC::ShaderInputBind::DIM_TEXTURE1DARRAY: - res.resType = TextureDim::Texture1DArray; - break; - case DXBC::ShaderInputBind::DIM_TEXTURE2D: res.resType = TextureDim::Texture2D; break; - case DXBC::ShaderInputBind::DIM_TEXTURE2DARRAY: - res.resType = TextureDim::Texture2DArray; - break; - case DXBC::ShaderInputBind::DIM_TEXTURE2DMS: res.resType = TextureDim::Texture2DMS; break; - case DXBC::ShaderInputBind::DIM_TEXTURE2DMSARRAY: - res.resType = TextureDim::Texture2DMSArray; - break; - case DXBC::ShaderInputBind::DIM_TEXTURE3D: res.resType = TextureDim::Texture3D; break; - case DXBC::ShaderInputBind::DIM_TEXTURECUBE: res.resType = TextureDim::TextureCube; break; - case DXBC::ShaderInputBind::DIM_TEXTURECUBEARRAY: - res.resType = TextureDim::TextureCubeArray; - break; - } - - if(r.retType != DXBC::ShaderInputBind::RETTYPE_UNKNOWN && - r.retType != DXBC::ShaderInputBind::RETTYPE_MIXED && - r.retType != DXBC::ShaderInputBind::RETTYPE_CONTINUED) - { - res.variableType.descriptor.rows = 1; - res.variableType.descriptor.cols = (uint8_t)r.numSamples; - res.variableType.descriptor.elements = 1; - - string name; - - switch(r.retType) - { - case DXBC::ShaderInputBind::RETTYPE_UNORM: name = "unorm float"; break; - case DXBC::ShaderInputBind::RETTYPE_SNORM: name = "snorm float"; break; - case DXBC::ShaderInputBind::RETTYPE_SINT: name = "int"; break; - case DXBC::ShaderInputBind::RETTYPE_UINT: name = "uint"; break; - case DXBC::ShaderInputBind::RETTYPE_FLOAT: name = "float"; break; - case DXBC::ShaderInputBind::RETTYPE_DOUBLE: name = "double"; break; - default: name = "unknown"; break; - } - - name += ToStr::Get(r.numSamples); - - res.variableType.descriptor.name = name; - } - else - { - if(dxbc->m_ResourceBinds.find(r.name) != dxbc->m_ResourceBinds.end()) - { - uint32_t vecOffset = 0; - res.variableType = MakeShaderVariableType(dxbc->m_ResourceBinds[r.name], vecOffset); - } - else - { - res.variableType.descriptor.rows = 0; - res.variableType.descriptor.cols = 0; - res.variableType.descriptor.elements = 0; - res.variableType.descriptor.name = ""; - } - } - - if(res.IsReadOnly) - ret->ReadOnlyResources[roidx++] = res; - else - ret->ReadWriteResources[rwidx++] = res; - } - - uint32_t numInterfaces = 0; - for(size_t i = 0; i < dxbc->m_Interfaces.variables.size(); i++) - numInterfaces = RDCMAX(dxbc->m_Interfaces.variables[i].descriptor.offset + 1, numInterfaces); - - create_array(ret->Interfaces, numInterfaces); - for(size_t i = 0; i < dxbc->m_Interfaces.variables.size(); i++) - ret->Interfaces[dxbc->m_Interfaces.variables[i].descriptor.offset] = - dxbc->m_Interfaces.variables[i].name; - - return ret; -} - ///////////////////////////////////////////////////////////// // Structures/descriptors. Serialise members separately // instead of ToStrInternal separately. Mostly for convenience of diff --git a/renderdoc/driver/d3d11/d3d11_common.h b/renderdoc/driver/d3d11/d3d11_common.h index 05d8d298b..49eb424bf 100644 --- a/renderdoc/driver/d3d11/d3d11_common.h +++ b/renderdoc/driver/d3d11/d3d11_common.h @@ -162,8 +162,6 @@ BlendMultiplier MakeBlendMultiplier(D3D11_BLEND blend, bool alpha); BlendOp MakeBlendOp(D3D11_BLEND_OP op); StencilOp MakeStencilOp(D3D11_STENCIL_OP op); -ShaderReflection *MakeShaderReflection(DXBC::DXBCFile *dxbc); - template inline void SetDebugName(T *pObj, const char *name) { diff --git a/renderdoc/driver/d3d11/d3d11_replay.cpp b/renderdoc/driver/d3d11/d3d11_replay.cpp index e1b3ea22d..733e4ec9c 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.cpp +++ b/renderdoc/driver/d3d11/d3d11_replay.cpp @@ -310,10 +310,9 @@ ShaderReflection *D3D11Replay::GetShader(ResourceId shader, string entryPoint) if(it == WrappedShader::m_ShaderList.end()) return NULL; - ShaderReflection *ret = it->second->GetDetails(); - RDCASSERT(ret); + ShaderReflection &ret = it->second->GetDetails(); - return ret; + return &ret; } vector D3D11Replay::GetDisassemblyTargets() @@ -581,7 +580,10 @@ void D3D11Replay::SavePipelineState() ShaderReflection *refl = NULL; if(shad != NULL) - refl = shad->GetDetails(); + { + refl = &shad->GetDetails(); + dst.BindpointMapping = shad->GetMapping(); + } dst.Object = rm->GetOriginalID(id); dst.ShaderDetails = refl; @@ -597,61 +599,6 @@ void D3D11Replay::SavePipelineState() dst.name = 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++) { diff --git a/renderdoc/driver/d3d11/d3d11_resources.cpp b/renderdoc/driver/d3d11/d3d11_resources.cpp index 8e588c971..2c3d0730e 100644 --- a/renderdoc/driver/d3d11/d3d11_resources.cpp +++ b/renderdoc/driver/d3d11/d3d11_resources.cpp @@ -29,6 +29,7 @@ #include "driver/d3d11/d3d11_context.h" #include "driver/d3d11/d3d11_renderstate.h" #include "driver/dxgi/dxgi_wrapped.h" +#include "driver/shaders/dxbc/dxbc_reflect.h" WRAPPED_POOL_INST(WrappedID3D11Buffer); WRAPPED_POOL_INST(WrappedID3D11Texture1D); @@ -176,6 +177,19 @@ void WrappedShader::ShaderEntry::TryReplaceOriginalByteCode() } } +void WrappedShader::ShaderEntry::BuildReflection() +{ + RDCCOMPILE_ASSERT( + D3Dx_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT == D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT, + "Mismatched vertex input count"); + + MakeShaderReflection(m_DXBCFile, &m_Details, &m_Mapping); + m_Details.ID = m_ID; + m_Details.EntryPoint = m_DXBCFile->m_DebugInfo ? m_DXBCFile->m_DebugInfo->GetEntryFunction() : ""; + if(m_Details.EntryPoint.empty()) + m_Details.EntryPoint = "main"; +} + UINT GetMipForSubresource(ID3D11Resource *res, int Subresource) { D3D11_RESOURCE_DIMENSION dim; diff --git a/renderdoc/driver/d3d11/d3d11_resources.h b/renderdoc/driver/d3d11/d3d11_resources.h index 108781dbf..705a96de1 100644 --- a/renderdoc/driver/d3d11/d3d11_resources.h +++ b/renderdoc/driver/d3d11/d3d11_resources.h @@ -903,20 +903,18 @@ public: class ShaderEntry { public: - ShaderEntry() : m_DebugInfoSearchPaths(NULL), m_DXBCFile(NULL), m_Details(NULL) {} + ShaderEntry() : m_DebugInfoSearchPaths(NULL), m_DXBCFile(NULL) {} ShaderEntry(WrappedID3D11Device *device, ResourceId id, const byte *code, size_t codeLen) { m_ID = id; m_Bytecode.assign(code, code + codeLen); m_DebugInfoSearchPaths = device->GetShaderDebugInfoSearchPaths(); m_DXBCFile = NULL; - m_Details = NULL; } ~ShaderEntry() { m_Bytecode.clear(); SAFE_DELETE(m_DXBCFile); - SAFE_DELETE(m_Details); } void SetDebugInfoPath(const std::string &path) { m_DebugInfoPath = path; } @@ -929,25 +927,30 @@ public: } return m_DXBCFile; } - ShaderReflection *GetDetails() + + ShaderReflection &GetDetails() { - if(m_Details == NULL && GetDXBC() != NULL) - { - m_Details = MakeShaderReflection(m_DXBCFile); - m_Details->ID = m_ID; - m_Details->EntryPoint = - m_DXBCFile->m_DebugInfo ? m_DXBCFile->m_DebugInfo->GetEntryFunction() : ""; - if(m_Details->EntryPoint.empty()) - m_Details->EntryPoint = "main"; - } + if(!m_Built && GetDXBC() != NULL) + BuildReflection(); + m_Built = true; return m_Details; } + const ShaderBindpointMapping &GetMapping() + { + if(!m_Built && GetDXBC() != NULL) + BuildReflection(); + m_Built = true; + return m_Mapping; + } + private: ShaderEntry(const ShaderEntry &e); void TryReplaceOriginalByteCode(); ShaderEntry &operator=(const ShaderEntry &e); + void BuildReflection(); + ResourceId m_ID; std::string m_DebugInfoPath; @@ -955,8 +958,10 @@ public: vector m_Bytecode; + bool m_Built = false; DXBC::DXBCFile *m_DXBCFile; - ShaderReflection *m_Details; + ShaderReflection m_Details; + ShaderBindpointMapping m_Mapping; }; static map m_ShaderList; @@ -989,11 +994,16 @@ public: SCOPED_LOCK(m_ShaderListLock); return m_ShaderList[m_ID]->GetDXBC(); } - ShaderReflection *GetDetails() + ShaderReflection &GetDetails() { SCOPED_LOCK(m_ShaderListLock); return m_ShaderList[m_ID]->GetDetails(); } + const ShaderBindpointMapping &GetMapping() + { + SCOPED_LOCK(m_ShaderListLock); + return m_ShaderList[m_ID]->GetMapping(); + } private: ResourceId m_ID; diff --git a/renderdoc/driver/d3d12/d3d12_common.cpp b/renderdoc/driver/d3d12/d3d12_common.cpp index e05bebfd0..bf651feb7 100644 --- a/renderdoc/driver/d3d12/d3d12_common.cpp +++ b/renderdoc/driver/d3d12/d3d12_common.cpp @@ -363,359 +363,6 @@ StencilOp MakeStencilOp(D3D12_STENCIL_OP op) return StencilOp::Keep; } -static ShaderConstant MakeConstantBufferVariable(const DXBC::CBufferVariable &var, uint32_t &offset); - -static ShaderVariableType MakeShaderVariableType(DXBC::CBufferVariableType type, uint32_t &offset) -{ - ShaderVariableType ret; - - switch(type.descriptor.type) - { - case DXBC::VARTYPE_MIN12INT: - case DXBC::VARTYPE_MIN16INT: - case DXBC::VARTYPE_INT: ret.descriptor.type = VarType::Int; break; - case DXBC::VARTYPE_BOOL: - case DXBC::VARTYPE_MIN16UINT: - case DXBC::VARTYPE_UINT: ret.descriptor.type = VarType::UInt; break; - case DXBC::VARTYPE_DOUBLE: ret.descriptor.type = VarType::Double; break; - case DXBC::VARTYPE_FLOAT: - case DXBC::VARTYPE_MIN8FLOAT: - case DXBC::VARTYPE_MIN10FLOAT: - case DXBC::VARTYPE_MIN16FLOAT: - default: ret.descriptor.type = VarType::Float; break; - } - ret.descriptor.rows = (uint8_t)type.descriptor.rows; - ret.descriptor.cols = (uint8_t)type.descriptor.cols; - ret.descriptor.elements = type.descriptor.elements; - ret.descriptor.name = type.descriptor.name; - ret.descriptor.rowMajorStorage = (type.descriptor.varClass == DXBC::CLASS_MATRIX_ROWS); - - uint32_t baseElemSize = (ret.descriptor.type == VarType::Double) ? 8 : 4; - if(ret.descriptor.rowMajorStorage) - { - uint32_t primary = ret.descriptor.rows; - if(primary == 3) - primary = 4; - ret.descriptor.arrayStride = baseElemSize * primary * ret.descriptor.cols; - } - else - { - uint32_t primary = ret.descriptor.cols; - if(primary == 3) - primary = 4; - ret.descriptor.arrayStride = baseElemSize * primary * ret.descriptor.rows; - } - - uint32_t o = offset; - - create_array_uninit(ret.members, type.members.size()); - for(size_t i = 0; i < type.members.size(); i++) - { - offset = o; - ret.members[i] = MakeConstantBufferVariable(type.members[i], offset); - } - - if(ret.members.count > 0) - { - ret.descriptor.rows = 0; - ret.descriptor.cols = 0; - ret.descriptor.elements = 0; - } - - return ret; -} - -static ShaderConstant MakeConstantBufferVariable(const DXBC::CBufferVariable &var, uint32_t &offset) -{ - ShaderConstant ret; - - ret.name = var.name; - ret.reg.vec = offset + var.descriptor.offset / 16; - ret.reg.comp = (var.descriptor.offset - (var.descriptor.offset & ~0xf)) / 4; - ret.defaultValue = 0; - - offset = ret.reg.vec; - - ret.type = MakeShaderVariableType(var.type, offset); - - offset = ret.reg.vec + RDCMAX(1U, var.type.descriptor.bytesize / 16); - - return ret; -} - -void MakeShaderReflection(DXBC::DXBCFile *dxbc, ShaderReflection *refl, - ShaderBindpointMapping *mapping) -{ - if(dxbc == NULL || !RenderDoc::Inst().IsReplayApp()) - return; - - if(dxbc->m_DebugInfo) - { - refl->DebugInfo.compileFlags = DXBC::EncodeFlags(dxbc->m_DebugInfo); - - create_array_uninit(refl->DebugInfo.files, dxbc->m_DebugInfo->Files.size()); - for(size_t i = 0; i < dxbc->m_DebugInfo->Files.size(); i++) - { - refl->DebugInfo.files[i].first = dxbc->m_DebugInfo->Files[i].first; - refl->DebugInfo.files[i].second = dxbc->m_DebugInfo->Files[i].second; - } - - string entry = dxbc->m_DebugInfo->GetEntryFunction(); - if(entry.empty()) - entry = "main"; - - // sort the file with the entry point to the start. We don't have to do anything if there's only - // one file. - // This isn't a perfect search - it will match entry_point() anywhere in the file, even if it's - // in a comment or disabled preprocessor definition. This is just best-effort - if(refl->DebugInfo.files.count > 1) - { - // search from 0 up. If we find a match, we swap it into [0]. If we don't find a match then - // we can't rearrange anything. This is a no-op for 0 since it's already in first place, but - // since our search isn't perfect we might have multiple matches with some being false - // positives, and so we want to bias towards leaving [0] in place. - for(int32_t i = 0; i < refl->DebugInfo.files.count; i++) - { - char *c = strstr(refl->DebugInfo.files[i].first.elems, entry.c_str()); - char *end = refl->DebugInfo.files[i].first.elems + refl->DebugInfo.files[i].first.count; - - // no substring match? continue - if(c == NULL) - continue; - - // if we did get a substring match, ensure there's whitespace preceeding it. - if(c == entry.c_str() || !isspace((int)*(c - 1))) - continue; - - // skip past the entry point. Then skip any whitespace - c += entry.size(); - - // check for EOF. - if(c >= end) - continue; - - while(c < end && isspace(*c)) - c++; - - if(c >= end) - continue; - - // if there's an open bracket next, we found a entry_point( which we count as the - // declaration. - if(*c == '(') - { - // only do anything if we're looking at a later file - if(i > 0) - std::swap(refl->DebugInfo.files[0], refl->DebugInfo.files[i]); - - break; - } - } - } - } - - if(dxbc->m_ShaderBlob.empty()) - create_array_uninit(refl->RawBytes, 0); - else - create_array_init(refl->RawBytes, dxbc->m_ShaderBlob.size(), &dxbc->m_ShaderBlob[0]); - - refl->DispatchThreadsDimension[0] = dxbc->DispatchThreadsDimension[0]; - refl->DispatchThreadsDimension[1] = dxbc->DispatchThreadsDimension[1]; - refl->DispatchThreadsDimension[2] = dxbc->DispatchThreadsDimension[2]; - - refl->InputSig = dxbc->m_InputSig; - refl->OutputSig = dxbc->m_OutputSig; - - create_array_uninit(mapping->InputAttributes, D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT); - for(int s = 0; s < D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; s++) - mapping->InputAttributes[s] = s; - - int numCbuffers = 0; - - // skip 'empty' cbuffers added for the benefit of D3D11 - for(size_t i = 0; i < dxbc->m_CBuffers.size(); i++) - { - if(dxbc->m_CBuffers[i].descriptor.type == DXBC::CBuffer::Descriptor::TYPE_CBUFFER) - numCbuffers++; - } - - create_array_uninit(mapping->ConstantBlocks, numCbuffers); - create_array_uninit(refl->ConstantBlocks, numCbuffers); - for(size_t i = 0; i < dxbc->m_CBuffers.size(); i++) - { - ConstantBlock &cb = refl->ConstantBlocks[i]; - - if(dxbc->m_CBuffers[i].descriptor.type != DXBC::CBuffer::Descriptor::TYPE_CBUFFER) - continue; - - cb.name = dxbc->m_CBuffers[i].name; - cb.bufferBacked = true; - cb.byteSize = dxbc->m_CBuffers[i].descriptor.byteSize; - cb.bindPoint = (uint32_t)i; - - BindpointMap map; - map.arraySize = 1; - map.bindset = dxbc->m_CBuffers[i].space; - map.bind = dxbc->m_CBuffers[i].reg; - map.used = true; - - mapping->ConstantBlocks[i] = map; - - create_array_uninit(cb.variables, dxbc->m_CBuffers[i].variables.size()); - for(size_t v = 0; v < dxbc->m_CBuffers[i].variables.size(); v++) - { - uint32_t vecOffset = 0; - cb.variables[v] = MakeConstantBufferVariable(dxbc->m_CBuffers[i].variables[v], vecOffset); - } - } - - int numRWResources = 0; - int numROResources = 0; - - for(size_t i = 0; i < dxbc->m_Resources.size(); i++) - { - const auto &r = dxbc->m_Resources[i]; - - if(r.type != DXBC::ShaderInputBind::TYPE_CBUFFER) - { - bool IsReadWrite = (r.type == DXBC::ShaderInputBind::TYPE_UAV_RWTYPED || - r.type == DXBC::ShaderInputBind::TYPE_UAV_RWSTRUCTURED || - r.type == DXBC::ShaderInputBind::TYPE_UAV_RWBYTEADDRESS || - r.type == DXBC::ShaderInputBind::TYPE_UAV_APPEND_STRUCTURED || - r.type == DXBC::ShaderInputBind::TYPE_UAV_CONSUME_STRUCTURED || - r.type == DXBC::ShaderInputBind::TYPE_UAV_RWSTRUCTURED_WITH_COUNTER); - - if(IsReadWrite) - numRWResources++; - else - numROResources++; - } - } - - create_array_uninit(mapping->ReadWriteResources, numRWResources); - create_array_uninit(refl->ReadWriteResources, numRWResources); - - create_array_uninit(mapping->ReadOnlyResources, numROResources); - create_array_uninit(refl->ReadOnlyResources, numROResources); - - int32_t rwidx = 0, roidx = 0; - for(size_t i = 0; i < dxbc->m_Resources.size(); i++) - { - const auto &r = dxbc->m_Resources[i]; - - if(r.type == DXBC::ShaderInputBind::TYPE_CBUFFER) - continue; - - ShaderResource res; - res.name = r.name; - - res.IsSampler = (r.type == DXBC::ShaderInputBind::TYPE_SAMPLER); - res.IsTexture = (r.type == DXBC::ShaderInputBind::TYPE_TEXTURE && - r.dimension != DXBC::ShaderInputBind::DIM_UNKNOWN && - r.dimension != DXBC::ShaderInputBind::DIM_BUFFER && - r.dimension != DXBC::ShaderInputBind::DIM_BUFFEREX); - res.IsReadOnly = (r.type == DXBC::ShaderInputBind::TYPE_TBUFFER || - r.type == DXBC::ShaderInputBind::TYPE_SAMPLER || - r.type == DXBC::ShaderInputBind::TYPE_TEXTURE || - r.type == DXBC::ShaderInputBind::TYPE_STRUCTURED || - r.type == DXBC::ShaderInputBind::TYPE_BYTEADDRESS); - - switch(r.dimension) - { - default: - case DXBC::ShaderInputBind::DIM_UNKNOWN: res.resType = TextureDim::Unknown; break; - case DXBC::ShaderInputBind::DIM_BUFFER: - case DXBC::ShaderInputBind::DIM_BUFFEREX: res.resType = TextureDim::Buffer; break; - case DXBC::ShaderInputBind::DIM_TEXTURE1D: res.resType = TextureDim::Texture1D; break; - case DXBC::ShaderInputBind::DIM_TEXTURE1DARRAY: - res.resType = TextureDim::Texture1DArray; - break; - case DXBC::ShaderInputBind::DIM_TEXTURE2D: res.resType = TextureDim::Texture2D; break; - case DXBC::ShaderInputBind::DIM_TEXTURE2DARRAY: - res.resType = TextureDim::Texture2DArray; - break; - case DXBC::ShaderInputBind::DIM_TEXTURE2DMS: res.resType = TextureDim::Texture2DMS; break; - case DXBC::ShaderInputBind::DIM_TEXTURE2DMSARRAY: - res.resType = TextureDim::Texture2DMSArray; - break; - case DXBC::ShaderInputBind::DIM_TEXTURE3D: res.resType = TextureDim::Texture3D; break; - case DXBC::ShaderInputBind::DIM_TEXTURECUBE: res.resType = TextureDim::TextureCube; break; - case DXBC::ShaderInputBind::DIM_TEXTURECUBEARRAY: - res.resType = TextureDim::TextureCubeArray; - break; - } - - if(r.retType != DXBC::ShaderInputBind::RETTYPE_UNKNOWN && - r.retType != DXBC::ShaderInputBind::RETTYPE_MIXED && - r.retType != DXBC::ShaderInputBind::RETTYPE_CONTINUED) - { - res.variableType.descriptor.rows = 1; - res.variableType.descriptor.cols = (uint8_t)r.numSamples; - res.variableType.descriptor.elements = 1; - - string name; - - switch(r.retType) - { - case DXBC::ShaderInputBind::RETTYPE_UNORM: name = "unorm float"; break; - case DXBC::ShaderInputBind::RETTYPE_SNORM: name = "snorm float"; break; - case DXBC::ShaderInputBind::RETTYPE_SINT: name = "int"; break; - case DXBC::ShaderInputBind::RETTYPE_UINT: name = "uint"; break; - case DXBC::ShaderInputBind::RETTYPE_FLOAT: name = "float"; break; - case DXBC::ShaderInputBind::RETTYPE_DOUBLE: name = "double"; break; - default: name = "unknown"; break; - } - - name += ToStr::Get(r.numSamples); - - res.variableType.descriptor.name = name; - } - else - { - if(dxbc->m_ResourceBinds.find(r.name) != dxbc->m_ResourceBinds.end()) - { - uint32_t vecOffset = 0; - res.variableType = MakeShaderVariableType(dxbc->m_ResourceBinds[r.name], vecOffset); - } - else - { - res.variableType.descriptor.rows = 0; - res.variableType.descriptor.cols = 0; - res.variableType.descriptor.elements = 0; - res.variableType.descriptor.name = ""; - } - } - - res.bindPoint = res.IsReadOnly ? roidx : rwidx; - - BindpointMap map; - map.arraySize = r.bindCount == 0 ? ~0U : r.bindCount; - map.bindset = r.space; - map.bind = r.reg; - map.used = true; - - if(res.IsReadOnly) - { - mapping->ReadOnlyResources[roidx] = map; - refl->ReadOnlyResources[roidx++] = res; - } - else - { - mapping->ReadWriteResources[rwidx] = map; - refl->ReadWriteResources[rwidx++] = res; - } - } - - uint32_t numInterfaces = 0; - for(size_t i = 0; i < dxbc->m_Interfaces.variables.size(); i++) - numInterfaces = RDCMAX(dxbc->m_Interfaces.variables[i].descriptor.offset + 1, numInterfaces); - - create_array(refl->Interfaces, numInterfaces); - for(size_t i = 0; i < dxbc->m_Interfaces.variables.size(); i++) - refl->Interfaces[dxbc->m_Interfaces.variables[i].descriptor.offset] = - dxbc->m_Interfaces.variables[i].name; -} - enum D3D12ResourceBarrierSubresource { D3D12AllSubresources = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES diff --git a/renderdoc/driver/d3d12/d3d12_common.h b/renderdoc/driver/d3d12/d3d12_common.h index ac3833bbe..79b535a41 100644 --- a/renderdoc/driver/d3d12/d3d12_common.h +++ b/renderdoc/driver/d3d12/d3d12_common.h @@ -69,9 +69,6 @@ BlendMultiplier MakeBlendMultiplier(D3D12_BLEND blend, bool alpha); BlendOp MakeBlendOp(D3D12_BLEND_OP op); StencilOp MakeStencilOp(D3D12_STENCIL_OP op); -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. #define D3D12NOTIMP(...) \ diff --git a/renderdoc/driver/d3d12/d3d12_resources.cpp b/renderdoc/driver/d3d12/d3d12_resources.cpp index 3c020c61d..627c2ce67 100644 --- a/renderdoc/driver/d3d12/d3d12_resources.cpp +++ b/renderdoc/driver/d3d12/d3d12_resources.cpp @@ -24,6 +24,7 @@ #include "d3d12_resources.h" #include "3rdparty/lz4/lz4.h" +#include "driver/shaders/dxbc/dxbc_reflect.h" #include "d3d12_command_list.h" #include "d3d12_command_queue.h" @@ -458,3 +459,16 @@ WrappedID3D12DescriptorHeap::~WrappedID3D12DescriptorHeap() Shutdown(); SAFE_DELETE_ARRAY(descriptors); } + +void WrappedID3D12PipelineState::ShaderEntry::BuildReflection() +{ + RDCCOMPILE_ASSERT( + D3Dx_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT == D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT, + "Mismatched vertex input count"); + + MakeShaderReflection(m_DXBCFile, &m_Details, &m_Mapping); + m_Details.ID = GetResourceID(); + m_Details.EntryPoint = m_DXBCFile->m_DebugInfo ? m_DXBCFile->m_DebugInfo->GetEntryFunction() : ""; + if(m_Details.EntryPoint.empty()) + m_Details.EntryPoint = "main"; +} diff --git a/renderdoc/driver/d3d12/d3d12_resources.h b/renderdoc/driver/d3d12/d3d12_resources.h index 436bc8a69..92b7751cc 100644 --- a/renderdoc/driver/d3d12/d3d12_resources.h +++ b/renderdoc/driver/d3d12/d3d12_resources.h @@ -610,15 +610,7 @@ public: void TryReplaceOriginalByteCode(); ShaderEntry &operator=(const ShaderEntry &e); - void BuildReflection() - { - MakeShaderReflection(m_DXBCFile, &m_Details, &m_Mapping); - m_Details.ID = GetResourceID(); - m_Details.EntryPoint = - m_DXBCFile->m_DebugInfo ? m_DXBCFile->m_DebugInfo->GetEntryFunction() : ""; - if(m_Details.EntryPoint.empty()) - m_Details.EntryPoint = "main"; - } + void BuildReflection(); DXBCKey m_Key; diff --git a/renderdoc/driver/shaders/dxbc/dxbc_reflect.cpp b/renderdoc/driver/shaders/dxbc/dxbc_reflect.cpp new file mode 100644 index 000000000..dd91373f3 --- /dev/null +++ b/renderdoc/driver/shaders/dxbc/dxbc_reflect.cpp @@ -0,0 +1,370 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2017 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#include "dxbc_reflect.h" +#include "api/replay/renderdoc_replay.h" +#include "core/core.h" +#include "replay/type_helpers.h" +#include "dxbc_inspect.h" + +static ShaderConstant MakeConstantBufferVariable(const DXBC::CBufferVariable &var, uint32_t &offset); + +static ShaderVariableType MakeShaderVariableType(DXBC::CBufferVariableType type, uint32_t &offset) +{ + ShaderVariableType ret; + + switch(type.descriptor.type) + { + case DXBC::VARTYPE_MIN12INT: + case DXBC::VARTYPE_MIN16INT: + case DXBC::VARTYPE_INT: ret.descriptor.type = VarType::Int; break; + case DXBC::VARTYPE_BOOL: + case DXBC::VARTYPE_MIN16UINT: + case DXBC::VARTYPE_UINT: ret.descriptor.type = VarType::UInt; break; + case DXBC::VARTYPE_DOUBLE: ret.descriptor.type = VarType::Double; break; + case DXBC::VARTYPE_FLOAT: + case DXBC::VARTYPE_MIN8FLOAT: + case DXBC::VARTYPE_MIN10FLOAT: + case DXBC::VARTYPE_MIN16FLOAT: + default: ret.descriptor.type = VarType::Float; break; + } + ret.descriptor.rows = (uint8_t)type.descriptor.rows; + ret.descriptor.cols = (uint8_t)type.descriptor.cols; + ret.descriptor.elements = type.descriptor.elements; + ret.descriptor.name = type.descriptor.name; + ret.descriptor.rowMajorStorage = (type.descriptor.varClass == DXBC::CLASS_MATRIX_ROWS); + + uint32_t baseElemSize = (ret.descriptor.type == VarType::Double) ? 8 : 4; + if(ret.descriptor.rowMajorStorage) + { + uint32_t primary = ret.descriptor.rows; + if(primary == 3) + primary = 4; + ret.descriptor.arrayStride = baseElemSize * primary * ret.descriptor.cols; + } + else + { + uint32_t primary = ret.descriptor.cols; + if(primary == 3) + primary = 4; + ret.descriptor.arrayStride = baseElemSize * primary * ret.descriptor.rows; + } + + uint32_t o = offset; + + create_array_uninit(ret.members, type.members.size()); + for(size_t i = 0; i < type.members.size(); i++) + { + offset = o; + ret.members[i] = MakeConstantBufferVariable(type.members[i], offset); + } + + if(ret.members.count > 0) + { + ret.descriptor.rows = 0; + ret.descriptor.cols = 0; + ret.descriptor.elements = 0; + } + + return ret; +} + +static ShaderConstant MakeConstantBufferVariable(const DXBC::CBufferVariable &var, uint32_t &offset) +{ + ShaderConstant ret; + + ret.name = var.name; + ret.reg.vec = offset + var.descriptor.offset / 16; + ret.reg.comp = (var.descriptor.offset - (var.descriptor.offset & ~0xf)) / 4; + ret.defaultValue = 0; + + offset = ret.reg.vec; + + ret.type = MakeShaderVariableType(var.type, offset); + + offset = ret.reg.vec + RDCMAX(1U, var.type.descriptor.bytesize / 16); + + return ret; +} + +void MakeShaderReflection(DXBC::DXBCFile *dxbc, ShaderReflection *refl, + ShaderBindpointMapping *mapping) +{ + if(dxbc == NULL || !RenderDoc::Inst().IsReplayApp()) + return; + + if(dxbc->m_DebugInfo) + { + refl->DebugInfo.compileFlags = DXBC::EncodeFlags(dxbc->m_DebugInfo); + + create_array_uninit(refl->DebugInfo.files, dxbc->m_DebugInfo->Files.size()); + for(size_t i = 0; i < dxbc->m_DebugInfo->Files.size(); i++) + { + refl->DebugInfo.files[i].first = dxbc->m_DebugInfo->Files[i].first; + refl->DebugInfo.files[i].second = dxbc->m_DebugInfo->Files[i].second; + } + + string entry = dxbc->m_DebugInfo->GetEntryFunction(); + if(entry.empty()) + entry = "main"; + + // sort the file with the entry point to the start. We don't have to do anything if there's only + // one file. + // This isn't a perfect search - it will match entry_point() anywhere in the file, even if it's + // in a comment or disabled preprocessor definition. This is just best-effort + if(refl->DebugInfo.files.count > 1) + { + // search from 0 up. If we find a match, we swap it into [0]. If we don't find a match then + // we can't rearrange anything. This is a no-op for 0 since it's already in first place, but + // since our search isn't perfect we might have multiple matches with some being false + // positives, and so we want to bias towards leaving [0] in place. + for(int32_t i = 0; i < refl->DebugInfo.files.count; i++) + { + char *c = strstr(refl->DebugInfo.files[i].first.elems, entry.c_str()); + char *end = refl->DebugInfo.files[i].first.elems + refl->DebugInfo.files[i].first.count; + + // no substring match? continue + if(c == NULL) + continue; + + // if we did get a substring match, ensure there's whitespace preceeding it. + if(c == entry.c_str() || !isspace((int)*(c - 1))) + continue; + + // skip past the entry point. Then skip any whitespace + c += entry.size(); + + // check for EOF. + if(c >= end) + continue; + + while(c < end && isspace(*c)) + c++; + + if(c >= end) + continue; + + // if there's an open bracket next, we found a entry_point( which we count as the + // declaration. + if(*c == '(') + { + // only do anything if we're looking at a later file + if(i > 0) + std::swap(refl->DebugInfo.files[0], refl->DebugInfo.files[i]); + + break; + } + } + } + } + + if(dxbc->m_ShaderBlob.empty()) + create_array_uninit(refl->RawBytes, 0); + else + create_array_init(refl->RawBytes, dxbc->m_ShaderBlob.size(), &dxbc->m_ShaderBlob[0]); + + refl->DispatchThreadsDimension[0] = dxbc->DispatchThreadsDimension[0]; + refl->DispatchThreadsDimension[1] = dxbc->DispatchThreadsDimension[1]; + refl->DispatchThreadsDimension[2] = dxbc->DispatchThreadsDimension[2]; + + refl->InputSig = dxbc->m_InputSig; + refl->OutputSig = dxbc->m_OutputSig; + + create_array_uninit(mapping->InputAttributes, D3Dx_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT); + for(int s = 0; s < D3Dx_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; s++) + mapping->InputAttributes[s] = s; + + create_array_uninit(mapping->ConstantBlocks, dxbc->m_CBuffers.size()); + create_array_uninit(refl->ConstantBlocks, dxbc->m_CBuffers.size()); + for(size_t i = 0; i < dxbc->m_CBuffers.size(); i++) + { + ConstantBlock &cb = refl->ConstantBlocks[i]; + + cb.name = dxbc->m_CBuffers[i].name; + cb.bufferBacked = true; + cb.byteSize = dxbc->m_CBuffers[i].descriptor.byteSize; + cb.bindPoint = (uint32_t)i; + + BindpointMap map; + map.arraySize = 1; + map.bindset = dxbc->m_CBuffers[i].space; + map.bind = dxbc->m_CBuffers[i].reg; + map.used = true; + + mapping->ConstantBlocks[i] = map; + + create_array_uninit(cb.variables, dxbc->m_CBuffers[i].variables.size()); + for(size_t v = 0; v < dxbc->m_CBuffers[i].variables.size(); v++) + { + uint32_t vecOffset = 0; + cb.variables[v] = MakeConstantBufferVariable(dxbc->m_CBuffers[i].variables[v], vecOffset); + } + } + + int numRWResources = 0; + int numROResources = 0; + + for(size_t i = 0; i < dxbc->m_Resources.size(); i++) + { + const auto &r = dxbc->m_Resources[i]; + + if(r.type != DXBC::ShaderInputBind::TYPE_CBUFFER) + { + bool IsReadWrite = (r.type == DXBC::ShaderInputBind::TYPE_UAV_RWTYPED || + r.type == DXBC::ShaderInputBind::TYPE_UAV_RWSTRUCTURED || + r.type == DXBC::ShaderInputBind::TYPE_UAV_RWBYTEADDRESS || + r.type == DXBC::ShaderInputBind::TYPE_UAV_APPEND_STRUCTURED || + r.type == DXBC::ShaderInputBind::TYPE_UAV_CONSUME_STRUCTURED || + r.type == DXBC::ShaderInputBind::TYPE_UAV_RWSTRUCTURED_WITH_COUNTER); + + if(IsReadWrite) + numRWResources++; + else + numROResources++; + } + } + + create_array_uninit(mapping->ReadWriteResources, numRWResources); + create_array_uninit(refl->ReadWriteResources, numRWResources); + + create_array_uninit(mapping->ReadOnlyResources, numROResources); + create_array_uninit(refl->ReadOnlyResources, numROResources); + + int32_t rwidx = 0, roidx = 0; + for(size_t i = 0; i < dxbc->m_Resources.size(); i++) + { + const auto &r = dxbc->m_Resources[i]; + + if(r.type == DXBC::ShaderInputBind::TYPE_CBUFFER) + continue; + + ShaderResource res; + res.name = r.name; + + res.IsSampler = (r.type == DXBC::ShaderInputBind::TYPE_SAMPLER); + res.IsTexture = (r.type == DXBC::ShaderInputBind::TYPE_TEXTURE && + r.dimension != DXBC::ShaderInputBind::DIM_UNKNOWN && + r.dimension != DXBC::ShaderInputBind::DIM_BUFFER && + r.dimension != DXBC::ShaderInputBind::DIM_BUFFEREX); + res.IsReadOnly = (r.type == DXBC::ShaderInputBind::TYPE_TBUFFER || + r.type == DXBC::ShaderInputBind::TYPE_SAMPLER || + r.type == DXBC::ShaderInputBind::TYPE_TEXTURE || + r.type == DXBC::ShaderInputBind::TYPE_STRUCTURED || + r.type == DXBC::ShaderInputBind::TYPE_BYTEADDRESS); + + switch(r.dimension) + { + default: + case DXBC::ShaderInputBind::DIM_UNKNOWN: res.resType = TextureDim::Unknown; break; + case DXBC::ShaderInputBind::DIM_BUFFER: + case DXBC::ShaderInputBind::DIM_BUFFEREX: res.resType = TextureDim::Buffer; break; + case DXBC::ShaderInputBind::DIM_TEXTURE1D: res.resType = TextureDim::Texture1D; break; + case DXBC::ShaderInputBind::DIM_TEXTURE1DARRAY: + res.resType = TextureDim::Texture1DArray; + break; + case DXBC::ShaderInputBind::DIM_TEXTURE2D: res.resType = TextureDim::Texture2D; break; + case DXBC::ShaderInputBind::DIM_TEXTURE2DARRAY: + res.resType = TextureDim::Texture2DArray; + break; + case DXBC::ShaderInputBind::DIM_TEXTURE2DMS: res.resType = TextureDim::Texture2DMS; break; + case DXBC::ShaderInputBind::DIM_TEXTURE2DMSARRAY: + res.resType = TextureDim::Texture2DMSArray; + break; + case DXBC::ShaderInputBind::DIM_TEXTURE3D: res.resType = TextureDim::Texture3D; break; + case DXBC::ShaderInputBind::DIM_TEXTURECUBE: res.resType = TextureDim::TextureCube; break; + case DXBC::ShaderInputBind::DIM_TEXTURECUBEARRAY: + res.resType = TextureDim::TextureCubeArray; + break; + } + + if(r.retType != DXBC::ShaderInputBind::RETTYPE_UNKNOWN && + r.retType != DXBC::ShaderInputBind::RETTYPE_MIXED && + r.retType != DXBC::ShaderInputBind::RETTYPE_CONTINUED) + { + res.variableType.descriptor.rows = 1; + res.variableType.descriptor.cols = (uint8_t)r.numSamples; + res.variableType.descriptor.elements = 1; + + string name; + + switch(r.retType) + { + case DXBC::ShaderInputBind::RETTYPE_UNORM: name = "unorm float"; break; + case DXBC::ShaderInputBind::RETTYPE_SNORM: name = "snorm float"; break; + case DXBC::ShaderInputBind::RETTYPE_SINT: name = "int"; break; + case DXBC::ShaderInputBind::RETTYPE_UINT: name = "uint"; break; + case DXBC::ShaderInputBind::RETTYPE_FLOAT: name = "float"; break; + case DXBC::ShaderInputBind::RETTYPE_DOUBLE: name = "double"; break; + default: name = "unknown"; break; + } + + name += StringFormat::Fmt("%u", r.numSamples); + + res.variableType.descriptor.name = name; + } + else + { + if(dxbc->m_ResourceBinds.find(r.name) != dxbc->m_ResourceBinds.end()) + { + uint32_t vecOffset = 0; + res.variableType = MakeShaderVariableType(dxbc->m_ResourceBinds[r.name], vecOffset); + } + else + { + res.variableType.descriptor.rows = 0; + res.variableType.descriptor.cols = 0; + res.variableType.descriptor.elements = 0; + res.variableType.descriptor.name = ""; + } + } + + res.bindPoint = res.IsReadOnly ? roidx : rwidx; + + BindpointMap map; + map.arraySize = r.bindCount == 0 ? ~0U : r.bindCount; + map.bindset = r.space; + map.bind = r.reg; + map.used = true; + + if(res.IsReadOnly) + { + mapping->ReadOnlyResources[roidx] = map; + refl->ReadOnlyResources[roidx++] = res; + } + else + { + mapping->ReadWriteResources[rwidx] = map; + refl->ReadWriteResources[rwidx++] = res; + } + } + + uint32_t numInterfaces = 0; + for(size_t i = 0; i < dxbc->m_Interfaces.variables.size(); i++) + numInterfaces = RDCMAX(dxbc->m_Interfaces.variables[i].descriptor.offset + 1, numInterfaces); + + create_array(refl->Interfaces, numInterfaces); + for(size_t i = 0; i < dxbc->m_Interfaces.variables.size(); i++) + refl->Interfaces[dxbc->m_Interfaces.variables[i].descriptor.offset] = + dxbc->m_Interfaces.variables[i].name; +} diff --git a/renderdoc/driver/shaders/dxbc/dxbc_reflect.h b/renderdoc/driver/shaders/dxbc/dxbc_reflect.h new file mode 100644 index 000000000..59d00ab2f --- /dev/null +++ b/renderdoc/driver/shaders/dxbc/dxbc_reflect.h @@ -0,0 +1,38 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2017 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#pragma once + +namespace DXBC +{ +class DXBCFile; +} + +struct ShaderReflection; +struct ShaderBindpointMapping; + +#define D3Dx_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT 32 + +void MakeShaderReflection(DXBC::DXBCFile *dxbc, ShaderReflection *refl, + ShaderBindpointMapping *mapping); \ No newline at end of file diff --git a/renderdoc/driver/shaders/dxbc/renderdoc_dxbc.vcxproj b/renderdoc/driver/shaders/dxbc/renderdoc_dxbc.vcxproj index 2abffa656..8abea2bcb 100644 --- a/renderdoc/driver/shaders/dxbc/renderdoc_dxbc.vcxproj +++ b/renderdoc/driver/shaders/dxbc/renderdoc_dxbc.vcxproj @@ -59,7 +59,7 @@ RELEASE;%(PreprocessorDefinitions) - + MultiThreadedDLL false @@ -102,6 +102,7 @@ + Create @@ -111,6 +112,7 @@ + diff --git a/renderdoc/driver/shaders/dxbc/renderdoc_dxbc.vcxproj.filters b/renderdoc/driver/shaders/dxbc/renderdoc_dxbc.vcxproj.filters index b507aee89..0af9cdbba 100644 --- a/renderdoc/driver/shaders/dxbc/renderdoc_dxbc.vcxproj.filters +++ b/renderdoc/driver/shaders/dxbc/renderdoc_dxbc.vcxproj.filters @@ -8,6 +8,7 @@ PCH + @@ -19,6 +20,7 @@ PCH +