diff --git a/qrenderdoc/Code/pyrenderdoc/cosmetics.i b/qrenderdoc/Code/pyrenderdoc/cosmetics.i index 2f7491383..554906d8e 100644 --- a/qrenderdoc/Code/pyrenderdoc/cosmetics.i +++ b/qrenderdoc/Code/pyrenderdoc/cosmetics.i @@ -171,7 +171,6 @@ fail: DEFINE_SAFE_EQUALITY(ActionDescription) DEFINE_SAFE_EQUALITY(CounterResult) DEFINE_SAFE_EQUALITY(APIEvent) -DEFINE_SAFE_EQUALITY(Bindpoint) DEFINE_SAFE_EQUALITY(BufferDescription) DEFINE_SAFE_EQUALITY(CaptureFileFormat) DEFINE_SAFE_EQUALITY(ConstantBlock) @@ -200,5 +199,3 @@ DEFINE_SAFE_EQUALITY(Scissor) DEFINE_SAFE_EQUALITY(ColorBlend) DEFINE_SAFE_EQUALITY(BoundVBuffer) DEFINE_SAFE_EQUALITY(VertexInputAttribute) -DEFINE_SAFE_EQUALITY(BoundResource) -DEFINE_SAFE_EQUALITY(BoundResourceArray) diff --git a/qrenderdoc/Code/pyrenderdoc/renderdoc.i b/qrenderdoc/Code/pyrenderdoc/renderdoc.i index 923380347..fddd036d1 100644 --- a/qrenderdoc/Code/pyrenderdoc/renderdoc.i +++ b/qrenderdoc/Code/pyrenderdoc/renderdoc.i @@ -365,7 +365,6 @@ TEMPLATE_ARRAY_INSTANTIATE(rdcarray, ActionDescription) TEMPLATE_ARRAY_INSTANTIATE(rdcarray, GPUCounter) TEMPLATE_ARRAY_INSTANTIATE(rdcarray, CounterResult) TEMPLATE_ARRAY_INSTANTIATE(rdcarray, APIEvent) -TEMPLATE_ARRAY_INSTANTIATE(rdcarray, Bindpoint) TEMPLATE_ARRAY_INSTANTIATE(rdcarray, BufferDescription) TEMPLATE_ARRAY_INSTANTIATE(rdcarray, CaptureFileFormat) TEMPLATE_ARRAY_INSTANTIATE(rdcarray, ConstantBlock) @@ -402,8 +401,6 @@ TEMPLATE_ARRAY_INSTANTIATE(rdcarray, ColorBlend) TEMPLATE_ARRAY_INSTANTIATE(rdcarray, BoundVBuffer) TEMPLATE_ARRAY_INSTANTIATE(rdcarray, Offset) TEMPLATE_ARRAY_INSTANTIATE(rdcarray, VertexInputAttribute) -TEMPLATE_ARRAY_INSTANTIATE(rdcarray, BoundResource) -TEMPLATE_ARRAY_INSTANTIATE(rdcarray, BoundResourceArray) TEMPLATE_ARRAY_INSTANTIATE(rdcarray, FloatVector) TEMPLATE_ARRAY_INSTANTIATE(rdcarray, GraphicsAPI) TEMPLATE_ARRAY_INSTANTIATE(rdcarray, GPUDevice) @@ -419,8 +416,6 @@ TEMPLATE_ARRAY_INSTANTIATE(rdcarray, DescriptorAccess) TEMPLATE_ARRAY_INSTANTIATE(rdcarray, DescriptorLogicalLocation) TEMPLATE_ARRAY_INSTANTIATE(rdcarray, UsedDescriptor) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, Attachment) -TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, BindingElement) -TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, DescriptorBinding) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, DynamicOffset) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, DescriptorSet) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, ImageData) @@ -431,26 +426,17 @@ TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, VertexBuffer) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, VertexAttribute) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, VertexBinding) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, ViewportScissor) -TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D11Pipe, ConstantBuffer) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D11Pipe, Layout) -TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D11Pipe, Sampler) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D11Pipe, StreamOutBind) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D11Pipe, VertexBuffer) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D11Pipe, View) -TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D12Pipe, ConstantBuffer) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D12Pipe, Layout) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D12Pipe, ResourceData) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D12Pipe, ResourceState) -TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D12Pipe, RootSignatureRange) -TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D12Pipe, Sampler) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D12Pipe, StreamOutBind) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D12Pipe, VertexBuffer) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, D3D12Pipe, View) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, GLPipe, Attachment) -TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, GLPipe, Buffer) -TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, GLPipe, ImageLoadStore) -TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, GLPipe, Sampler) -TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, GLPipe, Texture) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, GLPipe, VertexBuffer) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, GLPipe, VertexAttribute) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, GLPipe, TextureCompleteness) diff --git a/qrenderdoc/Windows/BufferViewer.cpp b/qrenderdoc/Windows/BufferViewer.cpp index 448faf505..de3e007fe 100644 --- a/qrenderdoc/Windows/BufferViewer.cpp +++ b/qrenderdoc/Windows/BufferViewer.cpp @@ -3315,7 +3315,7 @@ void BufferViewer::OnEventChanged(uint32_t eventId) // update with the current cbuffer for the current slot if(IsCBufferView()) { - UsedDescriptor cb = m_Ctx.CurPipelineState().GetConstantBlockDescriptor( + UsedDescriptor cb = m_Ctx.CurPipelineState().GetConstantBlock( m_CBufferSlot.stage, m_CBufferSlot.slot, m_CBufferSlot.arrayIdx); m_BufferID = cb.descriptor.resource; m_ByteOffset = cb.descriptor.byteOffset; diff --git a/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp index 285814664..71f8f0359 100644 --- a/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp @@ -1602,7 +1602,7 @@ void D3D11PipelineStateViewer::setState() ui->targetOutputs, }; - rdcarray outputs = m_Ctx.CurPipelineState().GetOutputTargetDescriptors(); + rdcarray outputs = m_Ctx.CurPipelineState().GetOutputTargets(); for(uint32_t i = 0; i < outputs.size(); i++) { addResourceRow(D3D11ViewTag(D3D11ViewTag::OMTarget, i, outputs[i]), NULL, NULL, @@ -1779,9 +1779,8 @@ void D3D11PipelineStateViewer::setState() } } - addResourceRow( - D3D11ViewTag(D3D11ViewTag::OMDepth, 0, m_Ctx.CurPipelineState().GetDepthTargetDescriptor()), - NULL, NULL, ui->targetOutputs); + addResourceRow(D3D11ViewTag(D3D11ViewTag::OMDepth, 0, m_Ctx.CurPipelineState().GetDepthTarget()), + NULL, NULL, ui->targetOutputs); ui->vsClasses->parentWidget()->setVisible(ui->vsClasses->topLevelItemCount() > 0); ui->hsClasses->parentWidget()->setVisible(ui->hsClasses->topLevelItemCount() > 0); @@ -2822,8 +2821,7 @@ void D3D11PipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const D3D11Pipe QList rows; - const rdcarray &samplers = - m_Ctx.CurPipelineState().GetSamplerDescriptors(sh.stage); + const rdcarray &samplers = m_Ctx.CurPipelineState().GetSamplers(sh.stage); for(int i = 0; i < samplers.count(); i++) { @@ -2895,8 +2893,7 @@ void D3D11PipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const D3D11Pipe QList rows; - const rdcarray &cblocks = - m_Ctx.CurPipelineState().GetConstantBlockDescriptors(sh.stage); + const rdcarray &cblocks = m_Ctx.CurPipelineState().GetConstantBlocks(sh.stage); for(int i = 0; i < cblocks.count(); i++) { @@ -3188,7 +3185,7 @@ void D3D11PipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const D3D11Pipe QList rows; - rdcarray rts = m_Ctx.CurPipelineState().GetOutputTargetDescriptors(); + rdcarray rts = m_Ctx.CurPipelineState().GetOutputTargets(); for(int i = 0; i < rts.count(); i++) { if(rts[i].view == ResourceId()) @@ -3280,8 +3277,7 @@ void D3D11PipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const D3D11Pipe else if(om.stencilReadOnly) extra = tr("Stencil Read-Only"); - rows.push_back( - exportViewHTML(m_Ctx.CurPipelineState().GetDepthTargetDescriptor(), 0, NULL, extra)); + rows.push_back(exportViewHTML(m_Ctx.CurPipelineState().GetDepthTarget(), 0, NULL, extra)); m_Common.exportHTMLTable(xml, { diff --git a/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.cpp index 9c536ad78..0ae413cbd 100644 --- a/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.cpp @@ -587,7 +587,7 @@ ResourceId D3D12PipelineStateViewer::GetResource(RDTreeWidgetItem *item) return cb.descriptor.resource; return m_Ctx.CurPipelineState() - .GetConstantBlockDescriptor(stage->stage, cb.index, cb.arrayElement) + .GetConstantBlock(stage->stage, cb.index, cb.arrayElement) .descriptor.resource; } @@ -2011,7 +2011,7 @@ void D3D12PipelineStateViewer::setState() ui->targetOutputs->beginUpdate(); ui->targetOutputs->clear(); { - rdcarray rts = m_Ctx.CurPipelineState().GetOutputTargetDescriptors(); + rdcarray rts = m_Ctx.CurPipelineState().GetOutputTargets(); for(uint32_t i = 0; i < rts.size(); i++) { DescriptorAccess access; @@ -2023,7 +2023,7 @@ void D3D12PipelineStateViewer::setState() targets[i] = true; } - Descriptor depth = m_Ctx.CurPipelineState().GetDepthTargetDescriptor(); + Descriptor depth = m_Ctx.CurPipelineState().GetDepthTarget(); addResourceRow(D3D12ViewTag(D3D12ViewTag::OMDepth, DescriptorAccess(), depth), NULL, false, ui->targetOutputs); } @@ -2838,7 +2838,7 @@ void D3D12PipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const D3D12Pipe QList rowsSampler; QList rowsCB; - for(const UsedDescriptor &used : m_Ctx.CurPipelineState().GetConstantBlockDescriptors(sh.stage)) + for(const UsedDescriptor &used : m_Ctx.CurPipelineState().GetConstantBlocks(sh.stage)) { if(used.access.stage != sh.stage) continue; @@ -2886,7 +2886,7 @@ void D3D12PipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const D3D12Pipe rowsCB.push_back({regname, name, (qulonglong)offset, (qulonglong)length, numvars}); } - for(const UsedDescriptor &used : m_Ctx.CurPipelineState().GetSamplerDescriptors(sh.stage)) + for(const UsedDescriptor &used : m_Ctx.CurPipelineState().GetSamplers(sh.stage)) { if(used.access.stage != sh.stage) continue; @@ -2990,7 +2990,7 @@ void D3D12PipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const D3D12Pipe } } - for(const UsedDescriptor &used : m_Ctx.CurPipelineState().GetReadOnlyDescriptors(sh.stage)) + for(const UsedDescriptor &used : m_Ctx.CurPipelineState().GetReadOnlyResources(sh.stage)) { if(used.access.stage != sh.stage) continue; @@ -3005,7 +3005,7 @@ void D3D12PipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const D3D12Pipe rowsRO.push_back(row); } - for(const UsedDescriptor &used : m_Ctx.CurPipelineState().GetReadWriteDescriptors(sh.stage)) + for(const UsedDescriptor &used : m_Ctx.CurPipelineState().GetReadWriteResources(sh.stage)) { if(used.access.stage != sh.stage) continue; @@ -3324,7 +3324,7 @@ void D3D12PipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const D3D12Pipe QList rows; - rdcarray rts = m_Ctx.CurPipelineState().GetOutputTargetDescriptors(); + rdcarray rts = m_Ctx.CurPipelineState().GetOutputTargets(); for(uint32_t i = 0; i < rts.size(); i++) { if(rts[i].resource == ResourceId()) @@ -3367,7 +3367,7 @@ void D3D12PipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const D3D12Pipe else if(om.stencilReadOnly) extra = tr("Stencil Read-Only"); - Descriptor depth = m_Ctx.CurPipelineState().GetDepthTargetDescriptor(); + Descriptor depth = m_Ctx.CurPipelineState().GetDepthTarget(); m_Common.exportHTMLTable(xml, { diff --git a/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.cpp index 2203f66a7..eebed9ee0 100644 --- a/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.cpp @@ -549,7 +549,7 @@ ResourceId GLPipelineStateViewer::GetResource(RDTreeWidgetItem *item) int cb = tag.value(); - return m_Ctx.CurPipelineState().GetConstantBlockDescriptor(stage->stage, cb, 0).descriptor.resource; + return m_Ctx.CurPipelineState().GetConstantBlock(stage->stage, cb, 0).descriptor.resource; } return ResourceId(); diff --git a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp index 6ae363941..96be11096 100644 --- a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp @@ -566,7 +566,7 @@ ResourceId VulkanPipelineStateViewer::GetResource(RDTreeWidgetItem *item) return cb.descriptor.resource; return m_Ctx.CurPipelineState() - .GetConstantBlockDescriptor(stage->stage, cb.index, cb.arrayElement) + .GetConstantBlock(stage->stage, cb.index, cb.arrayElement) .descriptor.resource; } @@ -3394,7 +3394,7 @@ void VulkanPipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const VKPipe:: QList rwRows; QList sampRows; - for(const UsedDescriptor &used : m_Ctx.CurPipelineState().GetConstantBlockDescriptors(sh.stage)) + for(const UsedDescriptor &used : m_Ctx.CurPipelineState().GetConstantBlocks(sh.stage)) { if(used.access.stage != sh.stage) continue; @@ -3483,7 +3483,7 @@ void VulkanPipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const VKPipe:: {slotname, name, (qulonglong)byteOffset, (qulonglong)length, numvars, bindByteSize}); } - for(const UsedDescriptor &used : m_Ctx.CurPipelineState().GetReadOnlyDescriptors(sh.stage)) + for(const UsedDescriptor &used : m_Ctx.CurPipelineState().GetReadOnlyResources(sh.stage)) { if(used.access.stage != sh.stage) continue; @@ -3506,7 +3506,7 @@ void VulkanPipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const VKPipe:: exportDescriptorHTML(used, sh.reflection, descriptor, dynamicOffset, roRows); } - for(const UsedDescriptor &used : m_Ctx.CurPipelineState().GetReadWriteDescriptors(sh.stage)) + for(const UsedDescriptor &used : m_Ctx.CurPipelineState().GetReadWriteResources(sh.stage)) { if(used.access.stage != sh.stage) continue; @@ -3529,7 +3529,7 @@ void VulkanPipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const VKPipe:: exportDescriptorHTML(used, sh.reflection, descriptor, dynamicOffset, rwRows); } - for(const UsedDescriptor &used : m_Ctx.CurPipelineState().GetSamplerDescriptors(sh.stage)) + for(const UsedDescriptor &used : m_Ctx.CurPipelineState().GetSamplers(sh.stage)) { if(used.access.stage != sh.stage) continue; diff --git a/qrenderdoc/Windows/ShaderMessageViewer.cpp b/qrenderdoc/Windows/ShaderMessageViewer.cpp index bac9047fb..026f8a786 100644 --- a/qrenderdoc/Windows/ShaderMessageViewer.cpp +++ b/qrenderdoc/Windows/ShaderMessageViewer.cpp @@ -187,9 +187,9 @@ ShaderMessageViewer::ShaderMessageViewer(ICaptureContext &ctx, ShaderStageMask s // only display sample information if one of the targets is multisampled m_Multisampled = false; - rdcarray outs = pipe.GetOutputTargetDescriptors(); - outs.push_back(pipe.GetDepthTargetDescriptor()); - outs.push_back(pipe.GetDepthResolveTargetDescriptor()); + rdcarray outs = pipe.GetOutputTargets(); + outs.push_back(pipe.GetDepthTarget()); + outs.push_back(pipe.GetDepthResolveTarget()); for(const Descriptor &o : outs) { if(o.resource == ResourceId()) @@ -498,7 +498,7 @@ ShaderMessageViewer::ShaderMessageViewer(ICaptureContext &ctx, ShaderStageMask s // select an actual output. Prefer the first colour output, but if there's no colour output // pick depth. - rdcarray cols = m_Ctx.CurPipelineState().GetOutputTargetDescriptors(); + rdcarray cols = m_Ctx.CurPipelineState().GetOutputTargets(); bool hascol = false; for(size_t i = 0; i < cols.size(); i++) hascol |= cols[i].resource != ResourceId(); diff --git a/qrenderdoc/Windows/ShaderViewer.cpp b/qrenderdoc/Windows/ShaderViewer.cpp index b009702a5..68063c33b 100644 --- a/qrenderdoc/Windows/ShaderViewer.cpp +++ b/qrenderdoc/Windows/ShaderViewer.cpp @@ -387,8 +387,8 @@ void ShaderViewer::editShader(ResourceId id, ShaderStage stage, const QString &e void ShaderViewer::cacheResources() { - m_ReadOnlyResources = m_Ctx.CurPipelineState().GetReadOnlyDescriptors(m_Stage, false); - m_ReadWriteResources = m_Ctx.CurPipelineState().GetReadWriteDescriptors(m_Stage, false); + m_ReadOnlyResources = m_Ctx.CurPipelineState().GetReadOnlyResources(m_Stage, false); + m_ReadWriteResources = m_Ctx.CurPipelineState().GetReadWriteResources(m_Stage, false); } void ShaderViewer::debugShader(const ShaderReflection *shader, ResourceId pipeline, @@ -2600,7 +2600,7 @@ QString ShaderViewer::stringRep(const ShaderVariable &var, uint32_t row) else if(type == VarType::ReadWriteResource) resList = m_ReadWriteResources; else if(type == VarType::Sampler) - resList = m_Ctx.CurPipelineState().GetSamplerDescriptors(m_Stage); + resList = m_Ctx.CurPipelineState().GetSamplers(m_Stage); int32_t bindIdx = resList.indexOf(varBind); @@ -3913,7 +3913,7 @@ void ShaderViewer::updateDebugState() } } - rdcarray samplers = m_Ctx.CurPipelineState().GetSamplerDescriptors(m_Stage); + rdcarray samplers = m_Ctx.CurPipelineState().GetSamplers(m_Stage); for(int i = 0; i < m_Trace->samplers.count(); i++) { @@ -4594,7 +4594,7 @@ RDTreeWidgetItem *ShaderViewer::makeSourceVariableNode(const SourceVariableMappi typeName = lit("Sampler"); - rdcarray samplers = m_Ctx.CurPipelineState().GetSamplerDescriptors(m_Stage); + rdcarray samplers = m_Ctx.CurPipelineState().GetSamplers(m_Stage); ShaderBindIndex bind = reg->GetBindIndex(); int32_t bindIdx = samplers.indexOf(bind); diff --git a/qrenderdoc/Windows/TextureViewer.cpp b/qrenderdoc/Windows/TextureViewer.cpp index 578ce8827..e79330b7a 100644 --- a/qrenderdoc/Windows/TextureViewer.cpp +++ b/qrenderdoc/Windows/TextureViewer.cpp @@ -259,7 +259,7 @@ rdcarray Following::GetOutputTargets(ICaptureContext &ctx) } else { - rdcarray ret = ctx.CurPipelineState().GetOutputTargetDescriptors(); + rdcarray ret = ctx.CurPipelineState().GetOutputTargets(); if(ret.isEmpty() && curAction != NULL && (curAction->flags & ActionFlags::Present)) { @@ -285,7 +285,7 @@ Descriptor Following::GetDepthTarget(ICaptureContext &ctx) if(copy || clear || compute) return Descriptor(); else - return ctx.CurPipelineState().GetDepthTargetDescriptor(); + return ctx.CurPipelineState().GetDepthTarget(); } Descriptor Following::GetDepthResolveTarget(ICaptureContext &ctx) @@ -296,7 +296,7 @@ Descriptor Following::GetDepthResolveTarget(ICaptureContext &ctx) if(copy || clear || compute) return Descriptor(); else - return ctx.CurPipelineState().GetDepthResolveTargetDescriptor(); + return ctx.CurPipelineState().GetDepthResolveTarget(); } rdcarray Following::GetReadWriteResources(ICaptureContext &ctx, ShaderStage stage, @@ -315,11 +315,11 @@ rdcarray Following::GetReadWriteResources(ICaptureContext &ctx, if(stage != ShaderStage::Pixel && stage != ShaderStage::Compute) return rdcarray(); - return ctx.CurPipelineState().GetReadWriteDescriptors(ShaderStage::Compute, onlyUsed); + return ctx.CurPipelineState().GetReadWriteResources(ShaderStage::Compute, onlyUsed); } else { - return ctx.CurPipelineState().GetReadWriteDescriptors(stage, onlyUsed); + return ctx.CurPipelineState().GetReadWriteResources(stage, onlyUsed); } } @@ -346,11 +346,11 @@ rdcarray Following::GetReadOnlyResources(ICaptureContext &ctx, S if(stage != ShaderStage::Pixel && stage != ShaderStage::Compute) return rdcarray(); - return ctx.CurPipelineState().GetReadOnlyDescriptors(ShaderStage::Compute, onlyUsed); + return ctx.CurPipelineState().GetReadOnlyResources(ShaderStage::Compute, onlyUsed); } else { - return ctx.CurPipelineState().GetReadOnlyDescriptors(stage, onlyUsed); + return ctx.CurPipelineState().GetReadOnlyResources(stage, onlyUsed); } } diff --git a/renderdoc/api/replay/common_pipestate.h b/renderdoc/api/replay/common_pipestate.h index cc96521e3..8999d5f37 100644 --- a/renderdoc/api/replay/common_pipestate.h +++ b/renderdoc/api/replay/common_pipestate.h @@ -240,125 +240,6 @@ struct StencilFace DECLARE_REFLECTION_STRUCT(StencilFace); -DOCUMENT("Information about a single resource bound to a slot in an API-specific way."); -struct BoundResource -{ - DOCUMENT(""); - BoundResource() - { - resourceId = ResourceId(); - dynamicallyUsed = true; - firstMip = -1; - firstSlice = -1; - typeCast = CompType::Typeless; - } - BoundResource(ResourceId id) - { - resourceId = id; - dynamicallyUsed = true; - firstMip = -1; - firstSlice = -1; - typeCast = CompType::Typeless; - } - - BoundResource(ResourceId id, Subresource subresource) - { - resourceId = id; - dynamicallyUsed = true; - firstMip = subresource.mip; - firstSlice = subresource.slice; - typeCast = CompType::Typeless; - } - BoundResource(const BoundResource &) = default; - BoundResource &operator=(const BoundResource &) = default; - - bool operator==(const BoundResource &o) const - { - return resourceId == o.resourceId && firstMip == o.firstMip && firstSlice == o.firstSlice && - typeCast == o.typeCast; - } - bool operator<(const BoundResource &o) const - { - if(resourceId != o.resourceId) - return resourceId < o.resourceId; - if(firstMip != o.firstMip) - return firstMip < o.firstMip; - if(firstSlice != o.firstSlice) - return firstSlice < o.firstSlice; - if(typeCast != o.typeCast) - return typeCast < o.typeCast; - return false; - } - DOCUMENT("A :class:`~renderdoc.ResourceId` identifying the bound resource."); - ResourceId resourceId; - DOCUMENT(R"(``True`` if this binding element is dynamically used. - -Some APIs provide fine-grained usage based on dynamic shader feedback, to support 'bindless' -scenarios where only a small sparse subset of bound resources are actually used. -)"); - bool dynamicallyUsed = true; - DOCUMENT("For textures, the highest mip level available on this binding, or -1 for all mips"); - int firstMip; - DOCUMENT("For textures, the first array slice available on this binding. or -1 for all slices."); - int firstSlice; - DOCUMENT( - "For textures, a :class:`~renderdoc.CompType` hint for how to interpret typeless textures."); - CompType typeCast; -}; - -DECLARE_REFLECTION_STRUCT(BoundResource); - -// TODO this should be replaced with an rdcmap -DOCUMENT(R"(Contains all of the bound resources at a particular bindpoint. In APIs that don't -support resource arrays, there will only be one bound resource. -)"); -struct BoundResourceArray -{ - DOCUMENT(""); - BoundResourceArray() = default; - BoundResourceArray(const BoundResourceArray &) = default; - BoundResourceArray &operator=(const BoundResourceArray &) = default; - BoundResourceArray(Bindpoint b) : bindPoint(b) {} - BoundResourceArray(Bindpoint b, const rdcarray &r) : bindPoint(b), resources(r) - { - dynamicallyUsedCount = (uint32_t)r.size(); - firstIndex = 0; - } - // for convenience for searching the array, we compare only using the BindPoint - bool operator==(const BoundResourceArray &o) const { return bindPoint == o.bindPoint; } - bool operator!=(const BoundResourceArray &o) const { return !(bindPoint == o.bindPoint); } - bool operator<(const BoundResourceArray &o) const { return bindPoint < o.bindPoint; } - DOCUMENT(R"(The bind point for this array of bound resources. - -:type: Bindpoint -)"); - Bindpoint bindPoint; - - DOCUMENT(R"(The resources at this bind point. - -:type: List[BoundResource] -)"); - rdcarray resources; - - DOCUMENT(R"(Lists how many bindings in :data:`resources` are dynamically used. - -Some APIs provide fine-grained usage based on dynamic shader feedback, to support 'bindless' -scenarios where only a small sparse subset of bound resources are actually used. - -If this information isn't present this will be set to a large number. -)"); - uint32_t dynamicallyUsedCount = ~0U; - DOCUMENT(R"(Gives the array index of the first binding in :data:`resource`. If only a small subset -of the resources are used by the shader then the array may be rebased such that the first element is -not array index 0. - -For more information see :data:`VKBindingElement.dynamicallyUsed`. -)"); - int32_t firstIndex = 0; -}; - -DECLARE_REFLECTION_STRUCT(BoundResourceArray); - DOCUMENT("Information about a single vertex or index buffer binding."); struct BoundVBuffer { @@ -1019,31 +900,6 @@ For normal descriptors this is empty. DECLARE_REFLECTION_STRUCT(UsedDescriptor); -DOCUMENT("Information about a single constant buffer binding."); -struct BoundCBuffer -{ - DOCUMENT(""); - BoundCBuffer() = default; - BoundCBuffer(const BoundCBuffer &) = default; - BoundCBuffer &operator=(const BoundCBuffer &) = default; - - DOCUMENT("A :class:`~renderdoc.ResourceId` identifying the buffer."); - ResourceId resourceId; - DOCUMENT("The offset in bytes from the start of the buffer to the constant data."); - uint64_t byteOffset = 0; - DOCUMENT("The size in bytes for the constant buffer. Access outside this size returns 0."); - uint64_t byteSize = 0; - - DOCUMENT(R"(The inline byte data for this constant buffer, if this binding is not backed by a -typical buffer. - -:type: bytes -)"); - bytebuf inlineData; -}; - -DECLARE_REFLECTION_STRUCT(BoundCBuffer); - DOCUMENT("Describes a 2-dimensional int offset"); struct Offset { diff --git a/renderdoc/api/replay/d3d11_pipestate.h b/renderdoc/api/replay/d3d11_pipestate.h index 0ca46a6d5..6d5eaef25 100644 --- a/renderdoc/api/replay/d3d11_pipestate.h +++ b/renderdoc/api/replay/d3d11_pipestate.h @@ -299,128 +299,6 @@ struct View DOCUMENT("Valid for texture arrays or 3D textures - the number of slices in the view."); uint32_t numSlices = 1; }; - -DOCUMENT("Describes a sampler state object."); -struct Sampler -{ - DOCUMENT(""); - Sampler() = default; - Sampler(const Sampler &) = default; - Sampler &operator=(const Sampler &) = default; - - bool operator==(const Sampler &o) const - { - return resourceId == o.resourceId && addressU == o.addressU && addressV == o.addressV && - addressW == o.addressW && borderColor == o.borderColor && - compareFunction == o.compareFunction && filter == o.filter && - maxAnisotropy == o.maxAnisotropy && maxLOD == o.maxLOD && minLOD == o.minLOD && - mipLODBias == o.mipLODBias; - } - bool operator<(const Sampler &o) const - { - if(!(resourceId == o.resourceId)) - return resourceId < o.resourceId; - if(!(addressU == o.addressU)) - return addressU < o.addressU; - if(!(addressV == o.addressV)) - return addressV < o.addressV; - if(!(addressW == o.addressW)) - return addressW < o.addressW; - if(!(borderColor == o.borderColor)) - return borderColor < o.borderColor; - if(!(compareFunction == o.compareFunction)) - return compareFunction < o.compareFunction; - if(!(filter == o.filter)) - return filter < o.filter; - if(!(maxAnisotropy == o.maxAnisotropy)) - return maxAnisotropy < o.maxAnisotropy; - if(!(maxLOD == o.maxLOD)) - return maxLOD < o.maxLOD; - if(!(minLOD == o.minLOD)) - return minLOD < o.minLOD; - if(!(mipLODBias == o.mipLODBias)) - return mipLODBias < o.mipLODBias; - return false; - } - DOCUMENT("The :class:`ResourceId` of the sampler state object."); - ResourceId resourceId; - DOCUMENT("The :class:`AddressMode` in the U direction."); - AddressMode addressU = AddressMode::Wrap; - DOCUMENT("The :class:`AddressMode` in the V direction."); - AddressMode addressV = AddressMode::Wrap; - DOCUMENT("The :class:`AddressMode` in the W direction."); - AddressMode addressW = AddressMode::Wrap; - DOCUMENT(R"(The RGBA border color. - -:type: Tuple[float,float,float,float] -)"); - rdcfixedarray borderColor = {0.0f, 0.0f, 0.0f, 0.0f}; - DOCUMENT("The :class:`CompareFunction` for comparison samplers."); - CompareFunction compareFunction = CompareFunction::AlwaysTrue; - DOCUMENT(R"(The filtering mode. - -:type: TextureFilter -)"); - TextureFilter filter; - DOCUMENT("The maximum anisotropic filtering level to use."); - uint32_t maxAnisotropy = 0; - DOCUMENT("The maximum mip level that can be used."); - float maxLOD = 0.0f; - DOCUMENT("The minimum mip level that can be used."); - float minLOD = 0.0f; - DOCUMENT("A bias to apply to the calculated mip level before sampling."); - float mipLODBias = 0.0f; - - DOCUMENT(R"(Check if the border color is used in this D3D11 sampler. - -:return: ``True`` if the border color is used, ``False`` otherwise. -:rtype: bool -)"); - bool UseBorder() const - { - return addressU == AddressMode::ClampBorder || addressV == AddressMode::ClampBorder || - addressW == AddressMode::ClampBorder; - } -}; - -DOCUMENT("Describes a constant buffer binding."); -struct ConstantBuffer -{ - DOCUMENT(""); - ConstantBuffer() = default; - ConstantBuffer(const ConstantBuffer &) = default; - ConstantBuffer &operator=(const ConstantBuffer &) = default; - - bool operator==(const ConstantBuffer &o) const - { - return resourceId == o.resourceId && vecOffset == o.vecOffset && vecCount == o.vecCount; - } - bool operator<(const ConstantBuffer &o) const - { - if(!(resourceId == o.resourceId)) - return resourceId < o.resourceId; - if(!(vecOffset == o.vecOffset)) - return vecOffset < o.vecOffset; - if(!(vecCount == o.vecCount)) - return vecCount < o.vecCount; - return false; - } - DOCUMENT("The :class:`ResourceId` of the buffer."); - ResourceId resourceId; - - DOCUMENT(R"(The offset of the buffer binding, in units of ``float4`` (16 bytes). - -If the capture isn't using the D3D11.1 binding methods, this offset will be 0. -)"); - uint32_t vecOffset = 0; - - DOCUMENT(R"(The size of the buffer binding, in units of ``float4`` (16 bytes). - -If the capture isn't using the D3D11.1 binding methods, this offset will be 4096 (64 kiB). -)"); - uint32_t vecCount = 0; -}; - DOCUMENT("Describes a D3D11 shader stage."); struct Shader { @@ -437,40 +315,10 @@ struct Shader :type: ShaderReflection )"); ShaderReflection *reflection = NULL; - DOCUMENT(R"(The bindpoint mapping data to match :data:`reflection`. - -:type: ShaderBindpointMapping -)"); - ShaderBindpointMapping bindpointMapping; DOCUMENT("A :class:`ShaderStage` identifying which stage this shader is bound to."); ShaderStage stage = ShaderStage::Vertex; - DOCUMENT(R"(The bound SRVs. - -:type: List[D3D11View] -)"); - rdcarray srvs; - - DOCUMENT(R"(The bound UAVs - only valid for the compute stage, other stages pull the UAVs from -the :data:`D3D11OutputMerger`. - -:type: List[D3D11View] -)"); - rdcarray uavs; - - DOCUMENT(R"(The bound samplers. - -:type: List[D3D11Sampler] -)"); - rdcarray samplers; - - DOCUMENT(R"(The bound constant buffers. - -:type: List[D3D11ConstantBuffer] -)"); - rdcarray constantBuffers; - DOCUMENT(R"(The bound class instance names. :type: List[str] @@ -702,12 +550,6 @@ struct OutputMerger DOCUMENT("Which slot in the output targets is the first UAV."); uint32_t uavStartSlot = 0; - DOCUMENT(R"(The bound UAVs. - -:type: List[D3D11View] -)"); - rdcarray uavs; - DOCUMENT(R"(The currently bound depth-stencil target. :type: D3D11View @@ -833,8 +675,6 @@ DECLARE_REFLECTION_STRUCT(D3D11Pipe::VertexBuffer); DECLARE_REFLECTION_STRUCT(D3D11Pipe::IndexBuffer); DECLARE_REFLECTION_STRUCT(D3D11Pipe::InputAssembly); DECLARE_REFLECTION_STRUCT(D3D11Pipe::View); -DECLARE_REFLECTION_STRUCT(D3D11Pipe::Sampler); -DECLARE_REFLECTION_STRUCT(D3D11Pipe::ConstantBuffer); DECLARE_REFLECTION_STRUCT(D3D11Pipe::Shader); DECLARE_REFLECTION_STRUCT(D3D11Pipe::StreamOutBind); DECLARE_REFLECTION_STRUCT(D3D11Pipe::StreamOut); diff --git a/renderdoc/api/replay/d3d12_pipestate.h b/renderdoc/api/replay/d3d12_pipestate.h index 986b464fe..341eab144 100644 --- a/renderdoc/api/replay/d3d12_pipestate.h +++ b/renderdoc/api/replay/d3d12_pipestate.h @@ -202,9 +202,6 @@ If the value is 0, strip cutting is disabled. Topology topology = Topology::Unknown; }; -// immediate indicates either a root parameter (not in a table), or static samplers -// rootElement is the index in the original root signature that this descriptor came from. - DOCUMENT("Describes the details of a D3D12 resource view - any one of UAV, SRV, RTV or DSV."); struct View { @@ -320,250 +317,6 @@ since single descriptors may only be dynamically skipped by control flow. float minLODClamp = 0.0f; }; -DOCUMENT("Describes the details of a sampler descriptor."); -struct Sampler -{ - DOCUMENT(""); - Sampler() = default; - Sampler(uint32_t binding) : bind(binding) {} - Sampler(const Sampler &) = default; - Sampler &operator=(const Sampler &) = default; - - bool operator==(const Sampler &o) const - { - return bind == o.bind && tableIndex == o.tableIndex && addressU == o.addressU && - addressV == o.addressV && addressW == o.addressW && - borderColorValue.uintValue == o.borderColorValue.uintValue && - borderColorType == o.borderColorType && unnormalized == o.unnormalized && - compareFunction == o.compareFunction && filter == o.filter && - maxAnisotropy == o.maxAnisotropy && maxLOD == o.maxLOD && minLOD == o.minLOD && - mipLODBias == o.mipLODBias; - } - bool operator<(const Sampler &o) const - { - if(!(bind == o.bind)) - return bind < o.bind; - if(!(tableIndex == o.tableIndex)) - return tableIndex < o.tableIndex; - if(!(addressU == o.addressU)) - return addressU < o.addressU; - if(!(addressV == o.addressV)) - return addressV < o.addressV; - if(!(addressW == o.addressW)) - return addressW < o.addressW; - if(!(borderColorValue.uintValue == o.borderColorValue.uintValue)) - return borderColorValue.uintValue < o.borderColorValue.uintValue; - if(!(borderColorType == o.borderColorType)) - return borderColorType < o.borderColorType; - if(!(unnormalized == o.unnormalized)) - return unnormalized < o.unnormalized; - if(!(compareFunction == o.compareFunction)) - return compareFunction < o.compareFunction; - if(!(filter == o.filter)) - return filter < o.filter; - if(!(maxAnisotropy == o.maxAnisotropy)) - return maxAnisotropy < o.maxAnisotropy; - if(!(maxLOD == o.maxLOD)) - return maxLOD < o.maxLOD; - if(!(minLOD == o.minLOD)) - return minLOD < o.minLOD; - if(!(mipLODBias == o.mipLODBias)) - return mipLODBias < o.mipLODBias; - return false; - } - DOCUMENT("The shader register that this sampler is bound to."); - uint32_t bind = ~0U; - DOCUMENT("The index in the the parent descriptor table where this descriptor came from."); - uint32_t tableIndex = ~0U; - - DOCUMENT("The :class:`AddressMode` in the U direction."); - AddressMode addressU = AddressMode::Wrap; - DOCUMENT("The :class:`AddressMode` in the V direction."); - AddressMode addressV = AddressMode::Wrap; - DOCUMENT("The :class:`AddressMode` in the W direction."); - AddressMode addressW = AddressMode::Wrap; - DOCUMENT(R"(For samplers - the RGBA border color value. Typically the float tuple inside will be used, -but the exact component type can be checked with :data:`borderColorType`. - -:type: PixelValue -)"); - PixelValue borderColorValue = {}; - DOCUMENT(R"(For samplers - the RGBA border color type. This determines how the data in -:data:`borderColorValue` will be interpreted. - -:type: CompType -)"); - CompType borderColorType = CompType::Float; - DOCUMENT("``True`` if unnormalized co-ordinates are used in this sampler."); - bool unnormalized = false; - DOCUMENT("The :class:`CompareFunction` for comparison samplers."); - CompareFunction compareFunction = CompareFunction::AlwaysTrue; - DOCUMENT(R"(The filtering mode. - -:type: TextureFilter -)"); - TextureFilter filter; - DOCUMENT("The maximum anisotropic filtering level to use."); - uint32_t maxAnisotropy = 0; - DOCUMENT("The maximum mip level that can be used."); - float maxLOD = 0.0f; - DOCUMENT("The minimum mip level that can be used."); - float minLOD = 0.0f; - DOCUMENT("A bias to apply to the calculated mip level before sampling."); - float mipLODBias = 0.0f; - - DOCUMENT(R"(Check if the border color is used in this D3D12 sampler. - -:return: ``True`` if the border color is used, ``False`` otherwise. -:rtype: bool -)"); - bool UseBorder() const - { - return addressU == AddressMode::ClampBorder || addressV == AddressMode::ClampBorder || - addressW == AddressMode::ClampBorder; - } -}; - -DOCUMENT("Describes the details of a constant buffer view descriptor."); -struct ConstantBuffer -{ - DOCUMENT(""); - ConstantBuffer() = default; - ConstantBuffer(uint32_t binding) : bind(binding) {} - ConstantBuffer(const ConstantBuffer &) = default; - ConstantBuffer &operator=(const ConstantBuffer &) = default; - - bool operator==(const ConstantBuffer &o) const - { - return bind == o.bind && tableIndex == o.tableIndex && resourceId == o.resourceId && - byteOffset == o.byteOffset && byteSize == o.byteSize && rootValues == o.rootValues; - } - bool operator<(const ConstantBuffer &o) const - { - if(!(bind == o.bind)) - return bind < o.bind; - if(!(tableIndex == o.tableIndex)) - return tableIndex < o.tableIndex; - if(!(resourceId == o.resourceId)) - return resourceId < o.resourceId; - if(!(byteOffset == o.byteOffset)) - return byteOffset < o.byteOffset; - if(!(byteSize == o.byteSize)) - return byteSize < o.byteSize; - if(!(rootValues == o.rootValues)) - return rootValues < o.rootValues; - return false; - } - DOCUMENT("The shader register that this constant buffer is bound to."); - uint32_t bind = ~0U; - DOCUMENT("The index in the the parent descriptor table where this descriptor came from."); - uint32_t tableIndex = ~0U; - - DOCUMENT("The :class:`ResourceId` of the underlying buffer resource."); - ResourceId resourceId; - DOCUMENT("The byte offset where the buffer view starts in the underlying buffer."); - uint64_t byteOffset = 0; - DOCUMENT("How many bytes are in this constant buffer view."); - uint32_t byteSize = 0; - - DOCUMENT(R"(If :data:`immediate` is ``True`` and this is a root constant, this contains the root -values set as interpreted as a series of DWORD values. - -:type: List[int] -)"); - rdcarray rootValues; -}; - -DOCUMENT("Contains information for a single root signature element range"); -struct RootSignatureRange -{ - DOCUMENT(""); - RootSignatureRange() = default; - RootSignatureRange(const RootSignatureRange &) = default; - RootSignatureRange &operator=(const RootSignatureRange &) = default; - - bool operator==(const RootSignatureRange &o) const - { - return immediate == o.immediate && rootSignatureIndex == o.rootSignatureIndex && - visibility == o.visibility && registerSpace == o.registerSpace && - dynamicallyUsedCount == o.dynamicallyUsedCount && firstUsedIndex == o.firstUsedIndex && - lastUsedIndex == o.lastUsedIndex && constantBuffers == o.constantBuffers && - samplers == o.samplers && views == o.views; - } - bool operator<(const RootSignatureRange &o) const - { - if(!(immediate == o.immediate)) - return immediate < o.immediate; - if(!(rootSignatureIndex == o.rootSignatureIndex)) - return rootSignatureIndex < o.rootSignatureIndex; - if(!(visibility == o.visibility)) - return visibility < o.visibility; - if(!(registerSpace == o.registerSpace)) - return registerSpace < o.registerSpace; - if(!(dynamicallyUsedCount == o.dynamicallyUsedCount)) - return dynamicallyUsedCount < o.dynamicallyUsedCount; - if(!(firstUsedIndex == o.firstUsedIndex)) - return firstUsedIndex < o.firstUsedIndex; - if(!(lastUsedIndex == o.lastUsedIndex)) - return lastUsedIndex < o.lastUsedIndex; - if(!(constantBuffers == o.constantBuffers)) - return constantBuffers < o.constantBuffers; - if(!(samplers == o.samplers)) - return samplers < o.samplers; - if(!(views == o.views)) - return views < o.views; - return false; - } - - DOCUMENT("``True`` if this root element is a root constant (i.e. not in a table)."); - bool immediate = false; - DOCUMENT("The index in the original root signature that this descriptor came from."); - uint32_t rootSignatureIndex = ~0U; - DOCUMENT("The :class:`BindType` contained by this element."); - BindType type = BindType::Unknown; - DOCUMENT("The :class:`ShaderStageMask` of this element."); - ShaderStageMask visibility = ShaderStageMask::All; - DOCUMENT("The register space of this element."); - uint32_t registerSpace; - DOCUMENT(R"(Lists how many bindings in :data:`views` are dynamically used. Useful to avoid -redundant iteration to determine whether any bindings are present. - -For more information see :data:`D3D12View.dynamicallyUsed`. -)"); - uint32_t dynamicallyUsedCount = ~0U; - DOCUMENT(R"(Gives the index of the first binding in :data:`views` that is dynamically used. Useful -to avoid redundant iteration in very large descriptor arrays with a small subset that are used. - -For more information see :data:`D3D12View.dynamicallyUsed`. -)"); - int32_t firstUsedIndex = 0; - DOCUMENT(R"(Gives the index of the first binding in :data:`views` that is dynamically used. Useful -to avoid redundant iteration in very large descriptor arrays with a small subset that are used. - -.. note:: - This may be set to a higher value than the number of bindings, if no dynamic use information is - available. Ensure that this is an additional check on the bind and the count is still respected. - -For more information see :data:`D3D12View.dynamicallyUsed`. -)"); - int32_t lastUsedIndex = 0x7fffffff; - DOCUMENT(R"(The constant buffers in this range. - -:type: List[D3D12ConstantBuffer] -)"); - rdcarray constantBuffers; - DOCUMENT(R"(The samplers in this range. - -:type: List[D3D12Sampler] -)"); - rdcarray samplers; - DOCUMENT(R"(The SRVs or UAVs in this range. - -:type: List[D3D12View] -)"); - rdcarray views; -}; - DOCUMENT("Describes a D3D12 shader stage."); struct Shader { @@ -580,11 +333,6 @@ struct Shader :type: ShaderReflection )"); ShaderReflection *reflection = NULL; - DOCUMENT(R"(The bindpoint mapping data to match :data:`reflection`. - -:type: ShaderBindpointMapping -)"); - ShaderBindpointMapping bindpointMapping; DOCUMENT("A :class:`ShaderStage` identifying which stage this shader is bound to."); ShaderStage stage = ShaderStage::Vertex; @@ -938,12 +686,6 @@ struct State )"); rdcarray descriptorHeaps; - DOCUMENT(R"(The root signature, as a range per element. - -:type: List[D3D12RootSignatureRange] -)"); - rdcarray rootElements; - DOCUMENT(R"(The input assembly pipeline stage. :type: D3D12InputAssembly @@ -1023,9 +765,6 @@ DECLARE_REFLECTION_STRUCT(D3D12Pipe::VertexBuffer); DECLARE_REFLECTION_STRUCT(D3D12Pipe::IndexBuffer); DECLARE_REFLECTION_STRUCT(D3D12Pipe::InputAssembly); DECLARE_REFLECTION_STRUCT(D3D12Pipe::View); -DECLARE_REFLECTION_STRUCT(D3D12Pipe::Sampler); -DECLARE_REFLECTION_STRUCT(D3D12Pipe::ConstantBuffer); -DECLARE_REFLECTION_STRUCT(D3D12Pipe::RootSignatureRange); DECLARE_REFLECTION_STRUCT(D3D12Pipe::Shader); DECLARE_REFLECTION_STRUCT(D3D12Pipe::StreamOutBind); DECLARE_REFLECTION_STRUCT(D3D12Pipe::StreamOut); diff --git a/renderdoc/api/replay/data_types.h b/renderdoc/api/replay/data_types.h index 11a308d91..e84a25bae 100644 --- a/renderdoc/api/replay/data_types.h +++ b/renderdoc/api/replay/data_types.h @@ -1792,12 +1792,6 @@ with software rendering, or with some functionality disabled due to lack of supp )"); bool degraded = false; - DOCUMENT(R"(``True`` if the driver mutates shader reflection structures from event to event. -Currently this is only true for OpenGL where the superfluous indirect in the binding model must be -worked around by re-sorting bindings. -)"); - bool shadersMutable = false; - DOCUMENT("(``True`` if the API supports shader debugging."); bool shaderDebugging = false; diff --git a/renderdoc/api/replay/gl_pipestate.h b/renderdoc/api/replay/gl_pipestate.h index aa0397793..1c425e4e3 100644 --- a/renderdoc/api/replay/gl_pipestate.h +++ b/renderdoc/api/replay/gl_pipestate.h @@ -218,11 +218,6 @@ struct Shader :type: ShaderReflection )"); ShaderReflection *reflection = NULL; - DOCUMENT(R"(The bindpoint mapping data to match :data:`reflection`. - -:type: ShaderBindpointMapping -)"); - ShaderBindpointMapping bindpointMapping; DOCUMENT("A :class:`ShaderStage` identifying which stage this shader is bound to."); ShaderStage stage = ShaderStage::Vertex; @@ -272,75 +267,6 @@ struct FixedVertexProcessing bool clipNegativeOneToOne = false; }; -DOCUMENT("Describes the details of a texture."); -struct Texture -{ - DOCUMENT(""); - Texture() = default; - Texture(const Texture &) = default; - Texture &operator=(const Texture &) = default; - - bool operator==(const Texture &o) const - { - return resourceId == o.resourceId && firstMip == o.firstMip && numMips == o.numMips && - type == o.type && swizzle == o.swizzle && depthReadChannel == o.depthReadChannel; - } - bool operator<(const Texture &o) const - { - if(!(resourceId == o.resourceId)) - return resourceId < o.resourceId; - if(!(firstMip == o.firstMip)) - return firstMip < o.firstMip; - if(!(numMips == o.numMips)) - return numMips < o.numMips; - if(!(type == o.type)) - return type < o.type; - if(!(swizzle == o.swizzle)) - return swizzle < o.swizzle; - if(!(depthReadChannel == o.depthReadChannel)) - return depthReadChannel < o.depthReadChannel; - return false; - } - DOCUMENT("The :class:`ResourceId` of the underlying resource the view refers to."); - ResourceId resourceId; - DOCUMENT("Valid for textures - the first mip that is available."); - uint32_t firstMip = 0; - DOCUMENT("Valid for textures - the number of mips that are available."); - uint32_t numMips = 0; - DOCUMENT("The :class:`TextureType` of the texture."); - TextureType type = TextureType::Unknown; - - DOCUMENT(R"(The swizzle applied to a texture. - -:type: TextureSwizzle4 -)"); - TextureSwizzle4 swizzle; - DOCUMENT(R"(The channel to read from in a depth-stencil texture. - -``-1`` for non depth-stencil textures. - -``0`` if depth should be read. - -``1`` if stencil should be read. -)"); - int32_t depthReadChannel = -1; - - DOCUMENT(R"(The details of the texture's (in)completeness. If this string is empty, the texture is -complete. Otherwise it contains an explanation of why the texture is believed to be incomplete. -)"); - rdcstr completeStatus; - - DOCUMENT(R"(The details of any type conflict on this binding. This can happen if -multiple uniforms are pointing to the same binding but with different types. In this case it is -impossible to disambiguate which binding was used. - - -If this string is empty, no conflict is present. Otherwise it contains the bindings which are -in conflict and their types. -)"); - rdcstr typeConflict; -}; - DOCUMENT("Describes the a texture completeness issue of a descriptor."); struct TextureCompleteness { @@ -377,180 +303,6 @@ in conflict and their types. rdcstr typeConflict; }; -DOCUMENT("Describes the sampler properties of a texture."); -struct Sampler -{ - DOCUMENT(""); - Sampler() = default; - Sampler(const Sampler &) = default; - Sampler &operator=(const Sampler &) = default; - - bool operator==(const Sampler &o) const - { - return resourceId == o.resourceId && addressS == o.addressS && addressT == o.addressT && - addressR == o.addressR && borderColor == o.borderColor && - compareFunction == o.compareFunction && filter == o.filter && - seamlessCubeMap == o.seamlessCubeMap && maxAnisotropy == o.maxAnisotropy && - maxLOD == o.maxLOD && minLOD == o.minLOD && mipLODBias == o.mipLODBias; - } - bool operator<(const Sampler &o) const - { - if(!(resourceId == o.resourceId)) - return resourceId < o.resourceId; - if(!(addressS == o.addressS)) - return addressS < o.addressS; - if(!(addressT == o.addressT)) - return addressT < o.addressT; - if(!(addressR == o.addressR)) - return addressR < o.addressR; - if(!(borderColor == o.borderColor)) - return borderColor < o.borderColor; - if(!(compareFunction == o.compareFunction)) - return compareFunction < o.compareFunction; - if(!(filter == o.filter)) - return filter < o.filter; - if(!(seamlessCubeMap == o.seamlessCubeMap)) - return seamlessCubeMap < o.seamlessCubeMap; - if(!(maxAnisotropy == o.maxAnisotropy)) - return maxAnisotropy < o.maxAnisotropy; - if(!(maxLOD == o.maxLOD)) - return maxLOD < o.maxLOD; - if(!(minLOD == o.minLOD)) - return minLOD < o.minLOD; - if(!(mipLODBias == o.mipLODBias)) - return mipLODBias < o.mipLODBias; - return false; - } - DOCUMENT("The :class:`ResourceId` of the sampler object, if a separate one is set."); - ResourceId resourceId; - DOCUMENT("The :class:`AddressMode` in the S direction."); - AddressMode addressS = AddressMode::Wrap; - DOCUMENT("The :class:`AddressMode` in the T direction."); - AddressMode addressT = AddressMode::Wrap; - DOCUMENT("The :class:`AddressMode` in the R direction."); - AddressMode addressR = AddressMode::Wrap; - DOCUMENT(R"(The RGBA border color. - -:type: Tuple[float,float,float,float] -)"); - rdcfixedarray borderColor = {0.0f, 0.0f, 0.0f, 0.0f}; - DOCUMENT("The :class:`CompareFunction` for comparison samplers."); - CompareFunction compareFunction = CompareFunction::AlwaysTrue; - DOCUMENT(R"(The filtering mode. - -:type: TextureFilter -)"); - TextureFilter filter; - DOCUMENT("``True`` if seamless cubemap filtering is enabled for this texture."); - bool seamlessCubeMap = false; - DOCUMENT("The maximum anisotropic filtering level to use."); - float maxAnisotropy = 0.0f; - DOCUMENT("The maximum mip level that can be used."); - float maxLOD = 0.0f; - DOCUMENT("The minimum mip level that can be used."); - float minLOD = 0.0f; - DOCUMENT("A bias to apply to the calculated mip level before sampling."); - float mipLODBias = 0.0f; - - DOCUMENT(R"(Check if the border color is used in this OpenGL sampler. - -:return: ``True`` if the border color is used, ``False`` otherwise. -:rtype: bool -)"); - bool UseBorder() const - { - return addressS == AddressMode::ClampBorder || addressT == AddressMode::ClampBorder || - addressR == AddressMode::ClampBorder; - } -}; - -DOCUMENT("Describes the properties of a buffer."); -struct Buffer -{ - DOCUMENT(""); - Buffer() = default; - Buffer(const Buffer &) = default; - Buffer &operator=(const Buffer &) = default; - - bool operator==(const Buffer &o) const - { - return resourceId == o.resourceId && byteOffset == o.byteOffset && byteSize == o.byteSize; - } - bool operator<(const Buffer &o) const - { - if(!(resourceId == o.resourceId)) - return resourceId < o.resourceId; - if(!(byteOffset == o.byteOffset)) - return byteOffset < o.byteOffset; - if(!(byteSize == o.byteSize)) - return byteSize < o.byteSize; - return false; - } - DOCUMENT("The :class:`ResourceId` of the buffer object."); - ResourceId resourceId; - DOCUMENT("The byte offset from the start of the buffer."); - uint64_t byteOffset = 0; - DOCUMENT("The byte size of the buffer."); - uint64_t byteSize = 0; -}; - -DOCUMENT("Describes the properties of a load/store image."); -struct ImageLoadStore -{ - DOCUMENT(""); - ImageLoadStore() = default; - ImageLoadStore(const ImageLoadStore &) = default; - ImageLoadStore &operator=(const ImageLoadStore &) = default; - - bool operator==(const ImageLoadStore &o) const - { - return resourceId == o.resourceId && mipLevel == o.mipLevel && layered == o.layered && - slice == o.slice && type == o.type && readAllowed == o.readAllowed && - writeAllowed == o.writeAllowed && imageFormat == o.imageFormat; - } - bool operator<(const ImageLoadStore &o) const - { - if(!(resourceId == o.resourceId)) - return resourceId < o.resourceId; - if(!(mipLevel == o.mipLevel)) - return mipLevel < o.mipLevel; - if(!(layered == o.layered)) - return layered < o.layered; - if(!(slice == o.slice)) - return slice < o.slice; - if(!(type == o.type)) - return type < o.type; - if(!(readAllowed == o.readAllowed)) - return readAllowed < o.readAllowed; - if(!(writeAllowed == o.writeAllowed)) - return writeAllowed < o.writeAllowed; - if(!(imageFormat == o.imageFormat)) - return imageFormat < o.imageFormat; - return false; - } - DOCUMENT("The :class:`ResourceId` of the texture object."); - ResourceId resourceId; - DOCUMENT("The mip of the texture that's used in the attachment."); - uint32_t mipLevel = 0; - DOCUMENT(R"(``True`` if multiple layers are bound together to the image. -``False`` if only one layer is bound. -)"); - bool layered = false; - DOCUMENT("The slice of the texture that's used in the attachment."); - uint32_t slice = 0; - DOCUMENT("The :class:`TextureType` of the texture."); - TextureType type = TextureType::Unknown; - DOCUMENT("``True`` if loading from the image is allowed."); - bool readAllowed = false; - DOCUMENT("``True`` if storing to the image is allowed."); - bool writeAllowed = false; - DOCUMENT(R"(The format that the image is bound as. - -:type: ResourceFormat -)"); - ResourceFormat imageFormat; -}; - DOCUMENT("Describes the current feedback state."); struct Feedback { @@ -927,40 +679,6 @@ struct State )"); FixedVertexProcessing vertexProcessing; - DOCUMENT(R"(The currently bound textures. - -:type: List[GLTexture] -)"); - rdcarray textures; - DOCUMENT(R"(The currently bound samplers. - - :type: List[GLSampler] -)"); - rdcarray samplers; - - DOCUMENT(R"(The currently bound atomic buffers. - -:type: List[GLBuffer] -)"); - rdcarray atomicBuffers; - DOCUMENT(R"(The currently bound uniform buffers. - -:type: List[GLBuffer] -)"); - rdcarray uniformBuffers; - - DOCUMENT(R"(The currently bound shader storage buffers. - -:type: List[GLBuffer] -)"); - rdcarray shaderStorageBuffers; - - DOCUMENT(R"(The currently bound load/store images. - -:type: List[GLImageLoadStore] -)"); - rdcarray images; - DOCUMENT(R"(The virtual descriptor storage. :type: ResourceId @@ -1029,11 +747,7 @@ DECLARE_REFLECTION_STRUCT(GLPipe::VertexBuffer); DECLARE_REFLECTION_STRUCT(GLPipe::VertexInput); DECLARE_REFLECTION_STRUCT(GLPipe::Shader); DECLARE_REFLECTION_STRUCT(GLPipe::FixedVertexProcessing); -DECLARE_REFLECTION_STRUCT(GLPipe::Texture); -DECLARE_REFLECTION_STRUCT(GLPipe::Sampler); DECLARE_REFLECTION_STRUCT(GLPipe::TextureCompleteness); -DECLARE_REFLECTION_STRUCT(GLPipe::Buffer); -DECLARE_REFLECTION_STRUCT(GLPipe::ImageLoadStore); DECLARE_REFLECTION_STRUCT(GLPipe::Feedback); DECLARE_REFLECTION_STRUCT(GLPipe::RasterizerState); DECLARE_REFLECTION_STRUCT(GLPipe::Rasterizer); diff --git a/renderdoc/api/replay/pipestate.h b/renderdoc/api/replay/pipestate.h index d32c5c4f3..45bdd59f4 100644 --- a/renderdoc/api/replay/pipestate.h +++ b/renderdoc/api/replay/pipestate.h @@ -246,16 +246,6 @@ requirements. )"); Scissor GetScissor(uint32_t index) const; - DOCUMENT(R"(Retrieves the current bindpoint mapping for a shader stage. - -This returns an empty bindpoint mapping if no shader is bound. - -:param ShaderStage stage: The shader stage to fetch. -:return: The bindpoint mapping for the given shader. -:rtype: ShaderBindpointMapping -)"); - const ShaderBindpointMapping &GetBindpointMapping(ShaderStage stage) const; - DOCUMENT(R"(Retrieves the shader reflection information for a shader stage. This returns ``None`` if no shader is bound. @@ -350,45 +340,6 @@ For some APIs that don't distinguish by entry point, this may be empty. )"); rdcarray GetVertexInputs() const; - DOCUMENT(R"(Retrieves the constant buffer at a given binding. - -:param ShaderStage stage: The shader stage to fetch from. -:param int BufIdx: The index in the shader's ConstantBlocks array to look up. -:param int ArrayIdx: For APIs that support arrays of constant buffers in a single binding, the index - in that array to look up. -:return: The constant buffer at the specified binding. -:rtype: BoundCBuffer -)"); - BoundCBuffer GetConstantBuffer(ShaderStage stage, uint32_t BufIdx, uint32_t ArrayIdx) const; - - DOCUMENT(R"(Retrieves the read-only resources bound to a particular shader stage. - -:param ShaderStage stage: The shader stage to fetch from. -:param bool onlyUsed: Return only a subset of resources containing those actually used by the - shader. -:return: The currently bound read-only resources. -:rtype: List[BoundResourceArray] -)"); - rdcarray GetReadOnlyResources(ShaderStage stage, bool onlyUsed = false) const; - - DOCUMENT(R"(Retrieves the samplers bound to a particular shader stage. - -:param ShaderStage stage: The shader stage to fetch from. -:return: The currently bound sampler resources. -:rtype: List[BoundResourceArray] -)"); - rdcarray GetSamplers(ShaderStage stage) const; - - DOCUMENT(R"(Retrieves the read/write resources bound to a particular shader stage. - -:param ShaderStage stage: The shader stage to fetch from. -:param bool onlyUsed: Return only a subset of resources containing those actually used by the - shader. -:return: The currently bound read/write resources. -:rtype: List[BoundResourceArray] -)"); - rdcarray GetReadWriteResources(ShaderStage stage, bool onlyUsed = false) const; - DOCUMENT(R"(Retrieves the current list of descriptor accesses, as cached from a call to :meth:`ReplayController.GetDescriptorAccess`. The return value is identical, this is here for convenience of access. @@ -415,8 +366,7 @@ convenience of access. :return: The constant buffer at the specified binding. :rtype: UsedDescriptor )"); - UsedDescriptor GetConstantBlockDescriptor(ShaderStage stage, uint32_t index, - uint32_t arrayIdx) const; + UsedDescriptor GetConstantBlock(ShaderStage stage, uint32_t index, uint32_t arrayIdx) const; DOCUMENT(R"(Retrieves the constant blocks used by a particular shader stage. @@ -425,7 +375,7 @@ convenience of access. :return: The currently bound constant blocks. :rtype: List[UsedDescriptor] )"); - rdcarray GetConstantBlockDescriptors(ShaderStage stage, bool onlyUsed = false) const; + rdcarray GetConstantBlocks(ShaderStage stage, bool onlyUsed = false) const; DOCUMENT(R"(Retrieves the read-only resources used by a particular shader stage. @@ -434,7 +384,7 @@ convenience of access. :return: The currently bound read-only resources. :rtype: List[UsedDescriptor] )"); - rdcarray GetReadOnlyDescriptors(ShaderStage stage, bool onlyUsed = false) const; + rdcarray GetReadOnlyResources(ShaderStage stage, bool onlyUsed = false) const; DOCUMENT(R"(Retrieves the samplers bound to a particular shader stage. @@ -443,7 +393,7 @@ convenience of access. :return: The currently bound sampler resources. :rtype: List[UsedDescriptor] )"); - rdcarray GetSamplerDescriptors(ShaderStage stage, bool onlyUsed = false) const; + rdcarray GetSamplers(ShaderStage stage, bool onlyUsed = false) const; DOCUMENT(R"(Retrieves the read/write resources used by a particular shader stage. @@ -452,49 +402,28 @@ convenience of access. :return: The currently bound read/write resources. :rtype: List[UsedDescriptor] )"); - rdcarray GetReadWriteDescriptors(ShaderStage stage, bool onlyUsed = false) const; - - DOCUMENT(R"(Retrieves the read/write resources bound to the depth-stencil output. - -:return: The currently bound depth-stencil resource. -:rtype: BoundResource -)"); - BoundResource GetDepthTarget() const; - - DOCUMENT(R"(Retrieves the read/write resources bound to the depth-stencil resolve output. - -:return: The currently bound depth-stencil resolve resource. -:rtype: BoundResource -)"); - BoundResource GetDepthResolveTarget() const; - - DOCUMENT(R"(Retrieves the resources bound to the color outputs. - -:return: The currently bound output targets. -:rtype: List[BoundResource] -)"); - rdcarray GetOutputTargets() const; + rdcarray GetReadWriteResources(ShaderStage stage, bool onlyUsed = false) const; DOCUMENT(R"(Retrieves the read/write resources bound to the depth-stencil output. :return: The currently bound depth-stencil resource. :rtype: Descriptor )"); - Descriptor GetDepthTargetDescriptor() const; + Descriptor GetDepthTarget() const; DOCUMENT(R"(Retrieves the read/write resources bound to the depth-stencil resolve output. :return: The currently bound depth-stencil resolve resource. :rtype: Descriptor )"); - Descriptor GetDepthResolveTargetDescriptor() const; + Descriptor GetDepthResolveTarget() const; DOCUMENT(R"(Retrieves the resources bound to the color outputs. :return: The currently bound output targets. :rtype: List[Descriptor] )"); - rdcarray GetOutputTargetDescriptors() const; + rdcarray GetOutputTargets() const; DOCUMENT(R"(Retrieves the current color blending states, per target. diff --git a/renderdoc/api/replay/pipestate.inl b/renderdoc/api/replay/pipestate.inl index 5a651c199..8bcd69eee 100644 --- a/renderdoc/api/replay/pipestate.inl +++ b/renderdoc/api/replay/pipestate.inl @@ -294,73 +294,6 @@ Scissor PipeState::GetScissor(uint32_t index) const return ret; } -const ShaderBindpointMapping &PipeState::GetBindpointMapping(ShaderStage stage) const -{ - if(IsCaptureLoaded()) - { - if(IsCaptureD3D11()) - { - switch(stage) - { - case ShaderStage::Vertex: return m_D3D11->vertexShader.bindpointMapping; - case ShaderStage::Domain: return m_D3D11->domainShader.bindpointMapping; - case ShaderStage::Hull: return m_D3D11->hullShader.bindpointMapping; - case ShaderStage::Geometry: return m_D3D11->geometryShader.bindpointMapping; - case ShaderStage::Pixel: return m_D3D11->pixelShader.bindpointMapping; - case ShaderStage::Compute: return m_D3D11->computeShader.bindpointMapping; - default: break; - } - } - else if(IsCaptureD3D12()) - { - switch(stage) - { - case ShaderStage::Vertex: return m_D3D12->vertexShader.bindpointMapping; - case ShaderStage::Domain: return m_D3D12->domainShader.bindpointMapping; - case ShaderStage::Hull: return m_D3D12->hullShader.bindpointMapping; - case ShaderStage::Geometry: return m_D3D12->geometryShader.bindpointMapping; - case ShaderStage::Pixel: return m_D3D12->pixelShader.bindpointMapping; - case ShaderStage::Compute: return m_D3D12->computeShader.bindpointMapping; - case ShaderStage::Amplification: return m_D3D12->ampShader.bindpointMapping; - case ShaderStage::Mesh: return m_D3D12->meshShader.bindpointMapping; - default: break; - } - } - else if(IsCaptureGL()) - { - switch(stage) - { - case ShaderStage::Vertex: return m_GL->vertexShader.bindpointMapping; - case ShaderStage::Tess_Control: return m_GL->tessControlShader.bindpointMapping; - case ShaderStage::Tess_Eval: return m_GL->tessEvalShader.bindpointMapping; - case ShaderStage::Geometry: return m_GL->geometryShader.bindpointMapping; - case ShaderStage::Fragment: return m_GL->fragmentShader.bindpointMapping; - case ShaderStage::Compute: return m_GL->computeShader.bindpointMapping; - default: break; - } - } - else if(IsCaptureVK()) - { - switch(stage) - { - case ShaderStage::Vertex: return m_Vulkan->vertexShader.bindpointMapping; - case ShaderStage::Tess_Control: return m_Vulkan->tessControlShader.bindpointMapping; - case ShaderStage::Tess_Eval: return m_Vulkan->tessEvalShader.bindpointMapping; - case ShaderStage::Geometry: return m_Vulkan->geometryShader.bindpointMapping; - case ShaderStage::Fragment: return m_Vulkan->fragmentShader.bindpointMapping; - case ShaderStage::Compute: return m_Vulkan->computeShader.bindpointMapping; - case ShaderStage::Task: return m_Vulkan->taskShader.bindpointMapping; - case ShaderStage::Mesh: return m_Vulkan->meshShader.bindpointMapping; - default: break; - } - } - } - - static ShaderBindpointMapping empty; - - return empty; -} - const ShaderReflection *PipeState::GetShaderReflection(ShaderStage stage) const { if(IsCaptureLoaded()) @@ -1001,825 +934,6 @@ int32_t PipeState::GetRasterizedStream() const return 0; } -BoundCBuffer PipeState::GetConstantBuffer(ShaderStage stage, uint32_t BufIdx, uint32_t ArrayIdx) const -{ - BoundCBuffer ret; - - if(IsCaptureLoaded()) - { - if(IsCaptureD3D11()) - { - if(!IsD3D11Stage(stage)) - return ret; - - const D3D11Pipe::Shader &s = GetD3D11Stage(stage); - - if(s.reflection != NULL && BufIdx < (uint32_t)s.reflection->constantBlocks.count()) - { - const Bindpoint &bind = - s.bindpointMapping.constantBlocks[s.reflection->constantBlocks[BufIdx].bindPoint]; - - if(bind.bind >= s.constantBuffers.count()) - return BoundCBuffer(); - - const D3D11Pipe::ConstantBuffer &descriptor = s.constantBuffers[bind.bind]; - - ret.resourceId = descriptor.resourceId; - ret.byteOffset = descriptor.vecOffset * 4 * sizeof(float); - ret.byteSize = descriptor.vecCount * 4 * sizeof(float); - } - } - else if(IsCaptureD3D12()) - { - if(!IsD3D12Stage(stage)) - return ret; - - const D3D12Pipe::Shader &s = GetD3D12Stage(stage); - - if(s.reflection != NULL && BufIdx < (uint32_t)s.reflection->constantBlocks.count()) - { - const Bindpoint &bind = - s.bindpointMapping.constantBlocks[s.reflection->constantBlocks[BufIdx].bindPoint]; - - int32_t shaderReg = bind.bind + (int32_t)ArrayIdx; - - bool found = false; - for(size_t i = 0; i < m_D3D12->rootElements.size() && !found; ++i) - { - const D3D12Pipe::RootSignatureRange &element = m_D3D12->rootElements[i]; - if((element.visibility & MaskForStage(stage)) == ShaderStageMask::Unknown) - continue; - - if(element.type == BindType::ConstantBuffer && - element.registerSpace == (uint32_t)bind.bindset) - { - for(size_t j = 0; j < element.constantBuffers.size(); ++j) - { - const D3D12Pipe::ConstantBuffer &cb = element.constantBuffers[j]; - if(cb.bind == (uint32_t)shaderReg) - { - found = true; - - ret.resourceId = cb.resourceId; - ret.byteOffset = cb.byteOffset; - ret.byteSize = cb.byteSize; - if(element.immediate) - { - ret.inlineData.resize(cb.rootValues.byteSize()); - memcpy(ret.inlineData.data(), cb.rootValues.data(), ret.inlineData.size()); - } - break; - } - } - } - } - } - } - else if(IsCaptureGL()) - { - if(!IsGLStage(stage)) - return ret; - - const GLPipe::Shader &s = GetGLStage(stage); - - if(s.reflection != NULL && BufIdx < (uint32_t)s.reflection->constantBlocks.count()) - { - if(s.reflection->constantBlocks[BufIdx].bindPoint >= 0) - { - int uboIdx = - s.bindpointMapping.constantBlocks[s.reflection->constantBlocks[BufIdx].bindPoint].bind; - if(uboIdx >= 0 && uboIdx < m_GL->uniformBuffers.count()) - { - const GLPipe::Buffer &b = m_GL->uniformBuffers[uboIdx]; - - ret.resourceId = b.resourceId; - ret.byteOffset = b.byteOffset; - ret.byteSize = b.byteSize; - - if(ret.byteSize == 0) - ret.byteSize = ~0ULL; - } - } - } - } - else if(IsCaptureVK()) - { - if(!IsVulkanStage(stage)) - return ret; - - const VKPipe::Pipeline &pipe = - stage == ShaderStage::Compute ? m_Vulkan->compute : m_Vulkan->graphics; - const VKPipe::Shader &s = GetVulkanStage(stage); - - if(s.reflection != NULL && BufIdx < (uint32_t)s.reflection->constantBlocks.count()) - { - const Bindpoint &bind = - s.bindpointMapping.constantBlocks[s.reflection->constantBlocks[BufIdx].bindPoint]; - - const VKPipe::BindingElement *descriptorBind = NULL; - if(bind.bindset < pipe.descriptorSets.count() && - bind.bind < pipe.descriptorSets[bind.bindset].bindings.count() && - ArrayIdx < pipe.descriptorSets[bind.bindset].bindings[bind.bind].binds.size()) - { - descriptorBind = &pipe.descriptorSets[bind.bindset].bindings[bind.bind].binds[ArrayIdx]; - } - - if(s.reflection->constantBlocks[BufIdx].bufferBacked == false || - (descriptorBind && descriptorBind->inlineBlock)) - { - if(s.reflection->constantBlocks[BufIdx].compileConstants) - { - ret.inlineData = s.specializationData; - ret.byteSize = ret.inlineData.size(); - } - else - { - ret.inlineData.resize((size_t)ret.byteSize); - - const bytebuf *src = NULL; - - // push constants have a magic bindset value higher than any descriptor set - if(bind.bindset < pipe.descriptorSets.count()) - { - if(bind.bind >= pipe.descriptorSets[bind.bindset].bindings.count() || - ArrayIdx >= pipe.descriptorSets[bind.bindset].bindings[bind.bind].binds.size()) - return BoundCBuffer(); - - src = &pipe.descriptorSets[bind.bindset].inlineData; - - ret.byteOffset = descriptorBind->byteOffset; - ret.byteSize = descriptorBind->byteSize; - } - else - { - src = &m_Vulkan->pushconsts; - - switch(stage) - { - case ShaderStage::Vertex: - ret.byteOffset = m_Vulkan->vertexShader.pushConstantRangeByteOffset; - ret.byteSize = m_Vulkan->vertexShader.pushConstantRangeByteSize; - break; - case ShaderStage::Tess_Control: - ret.byteOffset = m_Vulkan->tessControlShader.pushConstantRangeByteOffset; - ret.byteSize = m_Vulkan->tessControlShader.pushConstantRangeByteSize; - break; - case ShaderStage::Tess_Eval: - ret.byteOffset = m_Vulkan->tessEvalShader.pushConstantRangeByteOffset; - ret.byteSize = m_Vulkan->tessEvalShader.pushConstantRangeByteSize; - break; - case ShaderStage::Geometry: - ret.byteOffset = m_Vulkan->geometryShader.pushConstantRangeByteOffset; - ret.byteSize = m_Vulkan->geometryShader.pushConstantRangeByteSize; - break; - case ShaderStage::Fragment: - ret.byteOffset = m_Vulkan->fragmentShader.pushConstantRangeByteOffset; - ret.byteSize = m_Vulkan->fragmentShader.pushConstantRangeByteSize; - break; - case ShaderStage::Compute: - ret.byteOffset = m_Vulkan->computeShader.pushConstantRangeByteOffset; - ret.byteSize = m_Vulkan->computeShader.pushConstantRangeByteSize; - break; - case ShaderStage::Task: - ret.byteOffset = m_Vulkan->taskShader.pushConstantRangeByteOffset; - ret.byteSize = m_Vulkan->taskShader.pushConstantRangeByteSize; - break; - case ShaderStage::Mesh: - ret.byteOffset = m_Vulkan->meshShader.pushConstantRangeByteOffset; - ret.byteSize = m_Vulkan->meshShader.pushConstantRangeByteSize; - break; - default: break; - } - } - - if(ret.byteOffset > src->size()) - ret.byteSize = 0; - else if(ret.byteOffset + ret.byteSize > src->size()) - ret.byteSize = src->size() - ret.byteOffset; - - // consume the byteoffset here when copying data from the source data - ret.inlineData.resize((size_t)ret.byteSize); - memcpy(ret.inlineData.data(), src->data() + ret.byteOffset, (size_t)ret.byteSize); - ret.byteOffset = 0; - } - - return ret; - } - - if(descriptorBind == NULL) - return BoundCBuffer(); - - ret.resourceId = descriptorBind->resourceResourceId; - ret.byteOffset = descriptorBind->byteOffset; - ret.byteSize = descriptorBind->byteSize; - } - } - } - - return ret; -} - -rdcarray PipeState::GetSamplers(ShaderStage stage) const -{ - rdcarray ret; - - if(IsCaptureLoaded()) - { - if(IsCaptureD3D11()) - { - if(!IsD3D11Stage(stage)) - return ret; - - const D3D11Pipe::Shader &s = GetD3D11Stage(stage); - - ret.reserve(s.samplers.size()); - - for(int i = 0; i < s.samplers.count(); i++) - { - Bindpoint key(0, i); - BoundResource val; - - val.resourceId = s.samplers[i].resourceId; - - ret.push_back(BoundResourceArray(key, {val})); - } - - return ret; - } - else if(IsCaptureD3D12()) - { - if(!IsD3D12Stage(stage)) - return ret; - - const D3D12Pipe::Shader &s = GetD3D12Stage(stage); - - size_t size = s.bindpointMapping.samplers.size(); - ret.reserve(size); - - for(size_t bp = 0; bp < size; bp++) - { - const Bindpoint &bind = s.bindpointMapping.samplers[bp]; - ret.push_back(BoundResourceArray()); - ret.back().bindPoint = bind; - - uint32_t start = bind.bind; - uint32_t end = (bind.arraySize == ~0U) ? bind.arraySize : bind.bind + bind.arraySize; - - rdcarray &val = ret.back().resources; - - for(size_t i = 0; i < m_D3D12->rootElements.size(); ++i) - { - const D3D12Pipe::RootSignatureRange &element = m_D3D12->rootElements[i]; - if((element.visibility & MaskForStage(stage)) == ShaderStageMask::Unknown) - continue; - - if(element.type == BindType::Sampler && element.registerSpace == (uint32_t)bind.bindset) - { - val.reserve(val.size() + element.samplers.size()); - for(size_t j = 0; j < element.samplers.size(); ++j) - { - const D3D12Pipe::Sampler &samp = element.samplers[j]; - if(samp.bind >= start && samp.bind <= end) - { - val.push_back(BoundResource()); - // no resource ID to add here - } - } - } - } - } - - return ret; - } - else if(IsCaptureGL()) - { - if(!IsGLStage(stage)) - return ret; - - ret.reserve(m_GL->samplers.size()); - - for(int i = 0; i < m_GL->samplers.count(); i++) - { - Bindpoint key(0, i); - BoundResource val; - - val.resourceId = m_GL->samplers[i].resourceId; - - ret.push_back(BoundResourceArray(key, {val})); - } - - return ret; - } - else if(IsCaptureVK()) - { - if(!IsVulkanStage(stage)) - return ret; - - const rdcarray &descsets = stage == ShaderStage::Compute - ? m_Vulkan->compute.descriptorSets - : m_Vulkan->graphics.descriptorSets; - - ShaderStageMask mask = MaskForStage(stage); - - size_t size = 0; - for(int set = 0; set < descsets.count(); set++) - size += descsets[set].bindings.size(); - - ret.reserve(size); - - for(int set = 0; set < descsets.count(); set++) - { - const VKPipe::DescriptorSet &descset = descsets[set]; - for(int slot = 0; slot < descset.bindings.count(); slot++) - { - const VKPipe::DescriptorBinding &bind = descset.bindings[slot]; - if((bind.stageFlags & mask) == mask) - { - ret.push_back(BoundResourceArray()); - ret.back().bindPoint = Bindpoint(set, slot); - - rdcarray &val = ret.back().resources; - - val.reserve(val.size() + bind.descriptorCount); - for(uint32_t i = 0; i < bind.descriptorCount; i++) - { - if(bind.binds[i].type == BindType::Sampler || - bind.binds[i].type == BindType::ImageSampler) - { - val.push_back(BoundResource(bind.binds[i].samplerResourceId)); - - if(bind.binds[i].dynamicallyUsed) - ret.back().dynamicallyUsedCount++; - } - } - } - } - } - - return ret; - } - } - - return ret; -} - -rdcarray PipeState::GetReadOnlyResources(ShaderStage stage, bool onlyUsed) const -{ - rdcarray ret; - - if(IsCaptureLoaded()) - { - if(IsCaptureD3D11()) - { - if(!IsD3D11Stage(stage)) - return ret; - - const D3D11Pipe::Shader &s = GetD3D11Stage(stage); - - ret.reserve(s.srvs.size()); - - for(int i = 0; i < s.srvs.count(); i++) - { - Bindpoint key(0, i); - BoundResource val; - - val.resourceId = s.srvs[i].resourceResourceId; - val.firstMip = (int)s.srvs[i].firstMip; - val.firstSlice = (int)s.srvs[i].firstSlice; - val.typeCast = s.srvs[i].viewFormat.compType; - - ret.push_back(BoundResourceArray(key, {val})); - } - - return ret; - } - else if(IsCaptureD3D12()) - { - if(!IsD3D12Stage(stage)) - return ret; - - const D3D12Pipe::Shader &s = GetD3D12Stage(stage); - - size_t size = s.bindpointMapping.readOnlyResources.size(); - ret.reserve(size); - - for(size_t bp = 0; bp < size; bp++) - { - const Bindpoint &bind = s.bindpointMapping.readOnlyResources[bp]; - ret.push_back(BoundResourceArray()); - ret.back().bindPoint = bind; - - uint32_t start = bind.bind; - uint32_t end = (bind.arraySize == ~0U) ? bind.arraySize : bind.bind + bind.arraySize; - - rdcarray &val = ret.back().resources; - - ret.back().dynamicallyUsedCount = 0; - - for(size_t i = 0; i < m_D3D12->rootElements.size(); ++i) - { - const D3D12Pipe::RootSignatureRange &element = m_D3D12->rootElements[i]; - if((element.visibility & MaskForStage(stage)) == ShaderStageMask::Unknown) - continue; - - if(element.type == BindType::ReadOnlyResource && - element.registerSpace == (uint32_t)bind.bindset) - { - size_t firstIdx = 0; - size_t count = element.views.size(); - - if(onlyUsed && val.empty()) - { - firstIdx = (uint32_t)element.firstUsedIndex; - count = std::min(count - firstIdx, - size_t(element.lastUsedIndex - element.firstUsedIndex + 1)); - if(element.dynamicallyUsedCount == 0) - count = 0; - - ret.back().firstIndex = (int32_t)firstIdx; - } - - val.reserve(val.size() + count); - for(size_t j = firstIdx; j < firstIdx + count; ++j) - { - const D3D12Pipe::View &view = element.views[j]; - if(view.bind >= start && view.bind < end) - { - val.push_back(BoundResource()); - BoundResource &b = val.back(); - b.resourceId = view.resourceId; - b.dynamicallyUsed = view.dynamicallyUsed; - b.firstMip = (int)view.firstMip; - b.firstSlice = (int)view.firstSlice; - b.typeCast = view.viewFormat.compType; - - if(view.dynamicallyUsed) - ret.back().dynamicallyUsedCount++; - } - } - } - } - } - - return ret; - } - else if(IsCaptureGL()) - { - if(!IsGLStage(stage)) - return ret; - - ret.reserve(m_GL->textures.size()); - - for(int i = 0; i < m_GL->textures.count(); i++) - { - Bindpoint key(0, i); - BoundResource val; - - val.resourceId = m_GL->textures[i].resourceId; - val.firstMip = (int)m_GL->textures[i].firstMip; - val.firstSlice = 0; - val.typeCast = CompType::Typeless; - - ret.push_back(BoundResourceArray(key, {val})); - } - - return ret; - } - else if(IsCaptureVK()) - { - if(!IsVulkanStage(stage)) - return ret; - - const rdcarray &descsets = stage == ShaderStage::Compute - ? m_Vulkan->compute.descriptorSets - : m_Vulkan->graphics.descriptorSets; - - ShaderStageMask mask = MaskForStage(stage); - - size_t size = 0; - for(int set = 0; set < descsets.count(); set++) - size += descsets[set].bindings.size(); - - ret.reserve(size); - - for(int set = 0; set < descsets.count(); set++) - { - const VKPipe::DescriptorSet &descset = descsets[set]; - for(int slot = 0; slot < descset.bindings.count(); slot++) - { - const VKPipe::DescriptorBinding &bind = descset.bindings[slot]; - if((bind.stageFlags & mask) == mask) - { - ret.push_back(BoundResourceArray()); - ret.back().bindPoint = Bindpoint(set, slot); - - uint32_t count = bind.descriptorCount; - uint32_t firstIdx = 0; - - if(onlyUsed) - { - firstIdx = (uint32_t)bind.firstUsedIndex; - count = - std::min(count - firstIdx, uint32_t(bind.lastUsedIndex - bind.firstUsedIndex + 1)); - if(bind.dynamicallyUsedCount == 0) - count = 0; - } - - rdcarray &val = ret.back().resources; - val.reserve(count); - - ret.back().firstIndex = (int32_t)firstIdx; - ret.back().dynamicallyUsedCount = 0; - - BoundResource res; - for(uint32_t i = firstIdx; i < firstIdx + count; i++) - { - if(bind.binds[i].type == BindType::ImageSampler || - bind.binds[i].type == BindType::InputAttachment || - bind.binds[i].type == BindType::ReadOnlyImage || - bind.binds[i].type == BindType::ReadOnlyTBuffer) - { - res.resourceId = bind.binds[i].resourceResourceId; - res.dynamicallyUsed = bind.binds[i].dynamicallyUsed; - res.firstMip = (int)bind.binds[i].firstMip; - res.firstSlice = (int)bind.binds[i].firstSlice; - res.typeCast = bind.binds[i].viewFormat.compType; - val.push_back(res); - - if(bind.binds[i].dynamicallyUsed) - ret.back().dynamicallyUsedCount++; - } - else - { - // push empty resources so array indexing is still as expected - val.push_back(BoundResource()); - val.back().dynamicallyUsed = false; - } - } - - // if we didn't find any resources this is probably not a read-write bind, remove it - if(ret.back().dynamicallyUsedCount == 0) - ret.pop_back(); - } - } - } - - return ret; - } - } - - return ret; -} - -rdcarray PipeState::GetReadWriteResources(ShaderStage stage, bool onlyUsed) const -{ - rdcarray ret; - - if(IsCaptureLoaded()) - { - if(IsCaptureD3D11()) - { - if(!IsD3D11Stage(stage)) - return ret; - - if(stage == ShaderStage::Compute) - { - ret.reserve(m_D3D11->computeShader.uavs.size()); - - for(int i = 0; i < m_D3D11->computeShader.uavs.count(); i++) - { - Bindpoint key(0, i); - BoundResource val; - - val.resourceId = m_D3D11->computeShader.uavs[i].resourceResourceId; - val.firstMip = (int)m_D3D11->computeShader.uavs[i].firstMip; - val.firstSlice = (int)m_D3D11->computeShader.uavs[i].firstSlice; - val.typeCast = m_D3D11->computeShader.uavs[i].viewFormat.compType; - - ret.push_back(BoundResourceArray(key, {val})); - } - } - else - { - int uavstart = (int)m_D3D11->outputMerger.uavStartSlot; - - ret.reserve(m_D3D11->outputMerger.uavs.size() + std::max(0, uavstart)); - - // up to UAVStartSlot treat these bindings as empty. - for(int i = 0; i < uavstart; i++) - { - Bindpoint key(0, i); - BoundResource val; - - ret.push_back(BoundResourceArray(key, {val})); - } - - for(int i = 0; i < m_D3D11->outputMerger.uavs.count() - uavstart; i++) - { - Bindpoint key(0, i + uavstart); - BoundResource val; - - val.resourceId = m_D3D11->outputMerger.uavs[i].resourceResourceId; - val.firstMip = (int)m_D3D11->outputMerger.uavs[i].firstMip; - val.firstSlice = (int)m_D3D11->outputMerger.uavs[i].firstSlice; - val.typeCast = m_D3D11->outputMerger.uavs[i].viewFormat.compType; - - ret.push_back(BoundResourceArray(key, {val})); - } - } - } - else if(IsCaptureD3D12()) - { - if(!IsD3D12Stage(stage)) - return ret; - - const D3D12Pipe::Shader &s = GetD3D12Stage(stage); - - size_t size = s.bindpointMapping.readWriteResources.size(); - ret.reserve(size); - - for(size_t bp = 0; bp < size; bp++) - { - const Bindpoint &bind = s.bindpointMapping.readWriteResources[bp]; - ret.push_back(BoundResourceArray()); - ret.back().bindPoint = bind; - - uint32_t start = bind.bind; - uint32_t end = (bind.arraySize == ~0U) ? bind.arraySize : bind.bind + bind.arraySize; - - rdcarray &val = ret.back().resources; - - ret.back().dynamicallyUsedCount = 0; - - for(size_t i = 0; i < m_D3D12->rootElements.size(); ++i) - { - const D3D12Pipe::RootSignatureRange &element = m_D3D12->rootElements[i]; - if((element.visibility & MaskForStage(stage)) == ShaderStageMask::Unknown) - continue; - - if(element.type == BindType::ReadWriteResource && - element.registerSpace == (uint32_t)bind.bindset) - { - size_t firstIdx = 0; - size_t count = element.views.size(); - - if(onlyUsed && val.empty()) - { - firstIdx = (uint32_t)element.firstUsedIndex; - count = std::min(count - firstIdx, - size_t(element.lastUsedIndex - element.firstUsedIndex + 1)); - if(element.dynamicallyUsedCount == 0) - count = 0; - - ret.back().firstIndex = (int32_t)firstIdx; - } - - val.reserve(val.size() + count); - for(size_t j = firstIdx; j < firstIdx + count; ++j) - { - const D3D12Pipe::View &view = element.views[j]; - if(view.bind >= start && view.bind < end) - { - val.push_back(BoundResource()); - BoundResource &b = val.back(); - b.resourceId = view.resourceId; - b.dynamicallyUsed = view.dynamicallyUsed; - b.firstMip = (int)view.firstMip; - b.firstSlice = (int)view.firstSlice; - b.typeCast = view.viewFormat.compType; - - if(view.dynamicallyUsed) - ret.back().dynamicallyUsedCount++; - } - } - } - } - } - } - else if(IsCaptureGL()) - { - if(!IsGLStage(stage)) - return ret; - - ret.reserve(m_GL->images.size() + m_GL->atomicBuffers.size() + - m_GL->shaderStorageBuffers.size()); - - for(int i = 0; i < m_GL->images.count(); i++) - { - Bindpoint key(0, i); - BoundResource val; - - val.resourceId = m_GL->images[i].resourceId; - val.firstMip = (int)m_GL->images[i].mipLevel; - val.firstSlice = (int)m_GL->images[i].slice; - val.typeCast = m_GL->images[i].imageFormat.compType; - - ret.push_back(BoundResourceArray(key, {val})); - } - - for(int i = 0; i < m_GL->atomicBuffers.count(); i++) - { - Bindpoint key(0, i); - BoundResource val; - - val.resourceId = m_GL->atomicBuffers[i].resourceId; - - ret.push_back(BoundResourceArray(key, {val})); - } - - for(int i = 0; i < m_GL->shaderStorageBuffers.count(); i++) - { - Bindpoint key(0, i); - BoundResource val; - - val.resourceId = m_GL->shaderStorageBuffers[i].resourceId; - - ret.push_back(BoundResourceArray(key, {val})); - } - } - else if(IsCaptureVK()) - { - if(!IsVulkanStage(stage)) - return ret; - - const rdcarray &descsets = stage == ShaderStage::Compute - ? m_Vulkan->compute.descriptorSets - : m_Vulkan->graphics.descriptorSets; - - ShaderStageMask mask = MaskForStage(stage); - - size_t size = 0; - for(int set = 0; set < descsets.count(); set++) - size += descsets[set].bindings.size(); - - ret.reserve(size); - - for(int set = 0; set < descsets.count(); set++) - { - const VKPipe::DescriptorSet &descset = descsets[set]; - for(int slot = 0; slot < descset.bindings.count(); slot++) - { - const VKPipe::DescriptorBinding &bind = descset.bindings[slot]; - if((bind.stageFlags & mask) == mask) - { - ret.push_back(BoundResourceArray()); - ret.back().bindPoint = Bindpoint(set, slot); - - uint32_t count = bind.descriptorCount; - uint32_t firstIdx = 0; - - if(onlyUsed) - { - firstIdx = (uint32_t)bind.firstUsedIndex; - count = - std::min(count - firstIdx, uint32_t(bind.lastUsedIndex - bind.firstUsedIndex + 1)); - if(bind.dynamicallyUsedCount == 0) - count = 0; - } - - rdcarray &val = ret.back().resources; - val.reserve(count); - - ret.back().firstIndex = (int32_t)firstIdx; - ret.back().dynamicallyUsedCount = 0; - - BoundResource res; - for(uint32_t i = firstIdx; i < firstIdx + count; i++) - { - if(bind.binds[i].type == BindType::ReadWriteBuffer || - bind.binds[i].type == BindType::ReadWriteImage || - bind.binds[i].type == BindType::ReadWriteTBuffer) - { - res.resourceId = bind.binds[i].resourceResourceId; - res.dynamicallyUsed = bind.binds[i].dynamicallyUsed; - res.firstMip = (int)bind.binds[i].firstMip; - res.firstSlice = (int)bind.binds[i].firstSlice; - res.typeCast = bind.binds[i].viewFormat.compType; - val.push_back(res); - - if(bind.binds[i].dynamicallyUsed) - ret.back().dynamicallyUsedCount++; - } - else - { - // push empty resources so array indexing is still as expected - val.push_back(BoundResource()); - val.back().dynamicallyUsed = false; - } - } - - // if we didn't find any resources this is probably not a read-write bind, remove it - if(ret.back().dynamicallyUsedCount == 0) - ret.pop_back(); - } - } - } - } - } - - return ret; -} - rdcarray PipeState::GetAllUsedDescriptors(bool onlyUsed) const { rdcarray ret; @@ -1858,8 +972,7 @@ void PipeState::ApplyVulkanDynamicOffsets(UsedDescriptor &used) const } } -UsedDescriptor PipeState::GetConstantBlockDescriptor(ShaderStage stage, uint32_t index, - uint32_t arrayIdx) const +UsedDescriptor PipeState::GetConstantBlock(ShaderStage stage, uint32_t index, uint32_t arrayIdx) const { for(size_t i = 0; i < m_Access.size(); i++) { @@ -1880,7 +993,7 @@ UsedDescriptor PipeState::GetConstantBlockDescriptor(ShaderStage stage, uint32_t return UsedDescriptor(); } -rdcarray PipeState::GetConstantBlockDescriptors(ShaderStage stage, bool onlyUsed) const +rdcarray PipeState::GetConstantBlocks(ShaderStage stage, bool onlyUsed) const { rdcarray ret; @@ -1900,7 +1013,7 @@ rdcarray PipeState::GetConstantBlockDescriptors(ShaderStage stag return ret; } -rdcarray PipeState::GetReadOnlyDescriptors(ShaderStage stage, bool onlyUsed) const +rdcarray PipeState::GetReadOnlyResources(ShaderStage stage, bool onlyUsed) const { rdcarray ret; @@ -1920,7 +1033,7 @@ rdcarray PipeState::GetReadOnlyDescriptors(ShaderStage stage, bo return ret; } -rdcarray PipeState::GetSamplerDescriptors(ShaderStage stage, bool onlyUsed) const +rdcarray PipeState::GetSamplers(ShaderStage stage, bool onlyUsed) const { rdcarray ret; @@ -1940,7 +1053,7 @@ rdcarray PipeState::GetSamplerDescriptors(ShaderStage stage, boo return ret; } -rdcarray PipeState::GetReadWriteDescriptors(ShaderStage stage, bool onlyUsed) const +rdcarray PipeState::GetReadWriteResources(ShaderStage stage, bool onlyUsed) const { rdcarray ret; @@ -1956,169 +1069,8 @@ rdcarray PipeState::GetReadWriteDescriptors(ShaderStage stage, b return ret; } -BoundResource PipeState::GetDepthTarget() const -{ - if(IsCaptureLoaded()) - { - if(IsCaptureD3D11()) - { - BoundResource ret; - ret.resourceId = m_D3D11->outputMerger.depthTarget.resourceResourceId; - ret.firstMip = (int)m_D3D11->outputMerger.depthTarget.firstMip; - ret.firstSlice = (int)m_D3D11->outputMerger.depthTarget.firstSlice; - ret.typeCast = m_D3D11->outputMerger.depthTarget.viewFormat.compType; - return ret; - } - else if(IsCaptureD3D12()) - { - BoundResource ret; - ret.resourceId = m_D3D12->outputMerger.depthTarget.resourceId; - ret.firstMip = (int)m_D3D12->outputMerger.depthTarget.firstMip; - ret.firstSlice = (int)m_D3D12->outputMerger.depthTarget.firstSlice; - ret.typeCast = m_D3D12->outputMerger.depthTarget.viewFormat.compType; - return ret; - } - else if(IsCaptureGL()) - { - BoundResource ret; - ret.resourceId = m_GL->framebuffer.drawFBO.depthAttachment.resourceId; - ret.firstMip = (int)m_GL->framebuffer.drawFBO.depthAttachment.mipLevel; - ret.firstSlice = (int)m_GL->framebuffer.drawFBO.depthAttachment.slice; - ret.typeCast = CompType::Typeless; - return ret; - } - else if(IsCaptureVK()) - { - const VKPipe::RenderPass &rp = m_Vulkan->currentPass.renderpass; - const VKPipe::Framebuffer &fb = m_Vulkan->currentPass.framebuffer; - if(rp.depthstencilAttachment >= 0 && rp.depthstencilAttachment < fb.attachments.count()) - { - BoundResource ret; - ret.resourceId = fb.attachments[rp.depthstencilAttachment].imageResourceId; - ret.firstMip = (int)fb.attachments[rp.depthstencilAttachment].firstMip; - ret.firstSlice = (int)fb.attachments[rp.depthstencilAttachment].firstSlice; - ret.typeCast = fb.attachments[rp.depthstencilAttachment].viewFormat.compType; - return ret; - } - - return BoundResource(); - } - } - - return BoundResource(); -} - -BoundResource PipeState::GetDepthResolveTarget() const -{ - if(IsCaptureLoaded()) - { - if(IsCaptureVK()) - { - const VKPipe::RenderPass &rp = m_Vulkan->currentPass.renderpass; - const VKPipe::Framebuffer &fb = m_Vulkan->currentPass.framebuffer; - - if(rp.depthstencilResolveAttachment >= 0 && - rp.depthstencilResolveAttachment < fb.attachments.count()) - { - BoundResource ret; - ret.resourceId = fb.attachments[rp.depthstencilResolveAttachment].imageResourceId; - ret.firstMip = (int)fb.attachments[rp.depthstencilResolveAttachment].firstMip; - ret.firstSlice = (int)fb.attachments[rp.depthstencilResolveAttachment].firstSlice; - ret.typeCast = fb.attachments[rp.depthstencilResolveAttachment].viewFormat.compType; - return ret; - } - - return BoundResource(); - } - } - return BoundResource(); -} - -rdcarray PipeState::GetOutputTargets() const -{ - rdcarray ret; - - if(IsCaptureLoaded()) - { - if(IsCaptureD3D11()) - { - ret.resize(m_D3D11->outputMerger.renderTargets.count()); - for(int i = 0; i < m_D3D11->outputMerger.renderTargets.count(); i++) - { - ret[i].resourceId = m_D3D11->outputMerger.renderTargets[i].resourceResourceId; - ret[i].firstMip = (int)m_D3D11->outputMerger.renderTargets[i].firstMip; - ret[i].firstSlice = (int)m_D3D11->outputMerger.renderTargets[i].firstSlice; - ret[i].typeCast = m_D3D11->outputMerger.renderTargets[i].viewFormat.compType; - } - } - else if(IsCaptureD3D12()) - { - ret.resize(m_D3D12->outputMerger.renderTargets.count()); - for(int i = 0; i < m_D3D12->outputMerger.renderTargets.count(); i++) - { - ret[i].resourceId = m_D3D12->outputMerger.renderTargets[i].resourceId; - ret[i].firstMip = (int)m_D3D12->outputMerger.renderTargets[i].firstMip; - ret[i].firstSlice = (int)m_D3D12->outputMerger.renderTargets[i].firstSlice; - ret[i].typeCast = m_D3D12->outputMerger.renderTargets[i].viewFormat.compType; - } - } - else if(IsCaptureGL()) - { - ret.resize(m_GL->framebuffer.drawFBO.drawBuffers.count()); - for(int i = 0; i < m_GL->framebuffer.drawFBO.drawBuffers.count(); i++) - { - int db = m_GL->framebuffer.drawFBO.drawBuffers[i]; - - if(db >= 0) - { - ret[i].resourceId = m_GL->framebuffer.drawFBO.colorAttachments[db].resourceId; - ret[i].firstMip = (int)m_GL->framebuffer.drawFBO.colorAttachments[db].mipLevel; - ret[i].firstSlice = (int)m_GL->framebuffer.drawFBO.colorAttachments[db].slice; - ret[i].typeCast = CompType::Typeless; - } - } - } - else if(IsCaptureVK()) - { - const VKPipe::RenderPass &rp = m_Vulkan->currentPass.renderpass; - const VKPipe::Framebuffer &fb = m_Vulkan->currentPass.framebuffer; - - int idx = 0; - - ret.resize(rp.colorAttachments.count() + rp.resolveAttachments.count()); - for(int i = 0; i < rp.colorAttachments.count(); i++) - { - if(rp.colorAttachments[i] < (uint32_t)fb.attachments.count()) - { - ret[idx].resourceId = fb.attachments[rp.colorAttachments[i]].imageResourceId; - ret[idx].firstMip = (int)fb.attachments[rp.colorAttachments[i]].firstMip; - ret[idx].firstSlice = (int)fb.attachments[rp.colorAttachments[i]].firstSlice; - ret[idx].typeCast = fb.attachments[rp.colorAttachments[i]].viewFormat.compType; - } - - idx++; - } - - for(int i = 0; i < rp.resolveAttachments.count(); i++) - { - if(rp.resolveAttachments[i] < (uint32_t)fb.attachments.count()) - { - ret[idx].resourceId = fb.attachments[rp.resolveAttachments[i]].imageResourceId; - ret[idx].firstMip = (int)fb.attachments[rp.resolveAttachments[i]].firstMip; - ret[idx].firstSlice = (int)fb.attachments[rp.resolveAttachments[i]].firstSlice; - ret[idx].typeCast = fb.attachments[rp.resolveAttachments[i]].viewFormat.compType; - } - - idx++; - } - } - } - - return ret; -} - -Descriptor PipeState::GetDepthTargetDescriptor() const +Descriptor PipeState::GetDepthTarget() const { Descriptor ret; ret.type = DescriptorType::ReadWriteImage; @@ -2187,7 +1139,7 @@ Descriptor PipeState::GetDepthTargetDescriptor() const return ret; } -Descriptor PipeState::GetDepthResolveTargetDescriptor() const +Descriptor PipeState::GetDepthResolveTarget() const { Descriptor ret; ret.type = DescriptorType::ReadWriteImage; @@ -2221,7 +1173,7 @@ Descriptor PipeState::GetDepthResolveTargetDescriptor() const return ret; } -rdcarray PipeState::GetOutputTargetDescriptors() const +rdcarray PipeState::GetOutputTargets() const { rdcarray ret; diff --git a/renderdoc/api/replay/shader_types.h b/renderdoc/api/replay/shader_types.h index dabe53687..65a44c854 100644 --- a/renderdoc/api/replay/shader_types.h +++ b/renderdoc/api/replay/shader_types.h @@ -53,62 +53,6 @@ struct PointerVal DECLARE_STRINGISE_TYPE(PointerVal); -DOCUMENT("References a particular element in a :class:`Bindpoint`."); -struct BindpointIndex -{ - DOCUMENT(""); - BindpointIndex() - { - bindset = 0; - bind = 0; - arrayIndex = 0; - } - BindpointIndex(const BindpointIndex &) = default; - BindpointIndex &operator=(const BindpointIndex &) = default; - - BindpointIndex(int32_t s, int32_t b) - { - bindset = s; - bind = b; - arrayIndex = 0; - } - BindpointIndex(int32_t s, int32_t b, uint32_t a) - { - bindset = s; - bind = b; - arrayIndex = a; - } - - bool operator<(const BindpointIndex &o) const - { - if(!(bindset == o.bindset)) - return bindset < o.bindset; - if(!(bind == o.bind)) - return bind < o.bind; - return arrayIndex < o.arrayIndex; - } - bool operator>(const BindpointIndex &o) const - { - if(!(bindset == o.bindset)) - return bindset > o.bindset; - if(!(bind == o.bind)) - return bind > o.bind; - return arrayIndex > o.arrayIndex; - } - bool operator==(const BindpointIndex &o) const - { - return bindset == o.bindset && bind == o.bind && arrayIndex == o.arrayIndex; - } - DOCUMENT("The binding set."); - int32_t bindset; - DOCUMENT("The binding index."); - int32_t bind; - DOCUMENT("If this is an arrayed binding, the element in the array being referenced."); - uint32_t arrayIndex; -}; - -DECLARE_REFLECTION_STRUCT(BindpointIndex); - struct DescriptorAccess; DOCUMENT(R"(References a particular individual binding element in a shader interface. @@ -460,37 +404,6 @@ manually, but since it is common this helper is provided. return {value.u64v[0], pointerShader, uint32_t(value.u64v[1] & 0xFFFFFFFF)}; } - DOCUMENT(R"(Utility function for setting a bindpoint reference. - -See :class:`ShaderBindpointMapping` for the details of how bindpoints are interpreted. The type of -binding is given by the :data:`type` member. - -:param int bindset: The bind set. -:param int bind: The bind itself. -:param int arrayIndex: The array index, if the bind is an array. If it isn't an array this should be - set to 0. -)"); - inline void SetBinding(int32_t bindset, int32_t bind, uint32_t arrayIndex) - { - value.s32v[0] = bindset; - value.s32v[1] = bind; - value.u32v[2] = arrayIndex; - } - - DOCUMENT(R"(Utility function for getting the bindpoint referenced by this variable. - -.. note:: - - The return value is undefined if this variable is not a binding reference. - -:return: A :class:`BindpointIndex` with the binding referenced. -:rtype: BindpointIndex -)"); - inline BindpointIndex GetBinding() const - { - return BindpointIndex(value.s32v[0], value.s32v[1], value.u32v[2]); - } - DOCUMENT(R"(Utility function for setting a reference to a shader binding. The :class:`ShaderBindIndex` uniquely refers to a given shader binding in one of the shader interfaces @@ -898,7 +811,7 @@ struct ShaderDebugTrace DOCUMENT(R"(Constant buffer backed variables for this shader. Each entry in this list corresponds to a constant block with the same index in the -:data:`ShaderBindpointMapping.constantBlocks` list, which can be used to look up the metadata. +:data:`ShaderReflection.constantBlocks` list, which can be used to look up the metadata. Depending on the underlying shader representation, the constant block may retain any structure or it may have been vectorised and flattened. @@ -910,7 +823,7 @@ it may have been vectorised and flattened. DOCUMENT(R"(The read-only resource variables for this shader. The 'value' of the variable is always a single unsigned integer, which is the bindpoint - an index -into the :data:`ShaderBindpointMapping.readOnlyResources` list, which can be used to look up the +into the :data:`ShaderReflection.readOnlyResources` list, which can be used to look up the other metadata as well as find the binding from the pipeline state. :type: List[ShaderVariable] @@ -920,7 +833,7 @@ other metadata as well as find the binding from the pipeline state. DOCUMENT(R"(The read-write resource variables for this shader. The 'value' of the variable is always a single unsigned integer, which is the bindpoint - an index -into the :data:`ShaderBindpointMapping.readWriteResources` list, which can be used to look up the +into the :data:`ShaderReflection.readWriteResources` list, which can be used to look up the other metadata as well as find the binding from the pipeline state. :type: List[ShaderVariable] @@ -930,7 +843,7 @@ other metadata as well as find the binding from the pipeline state. DOCUMENT(R"(The sampler variables for this shader. The 'value' of the variable is always a single unsigned integer, which is the bindpoint - an index -into the :data:`ShaderBindpointMapping.samplers` list, which can be used to look up the +into the :data:`ShaderReflection.samplers` list, which can be used to look up the other metadata as well as find the binding from the pipeline state. :type: List[ShaderVariable] @@ -1246,7 +1159,7 @@ struct ConstantBlock bool operator==(const ConstantBlock &o) const { - return name == o.name && variables == o.variables && bindPoint == o.bindPoint && + return name == o.name && variables == o.variables && fixedBindSetOrSpace == o.fixedBindSetOrSpace && bufferBacked == o.bufferBacked && byteSize == o.byteSize && bufferBacked == o.bufferBacked && inlineDataBytes == o.inlineDataBytes && compileConstants == o.compileConstants; @@ -1255,8 +1168,6 @@ struct ConstantBlock { if(!(name == o.name)) return name < o.name; - if(!(bindPoint == o.bindPoint)) - return bindPoint < o.bindPoint; if(!(fixedBindNumber == o.fixedBindNumber)) return fixedBindNumber < o.fixedBindNumber; if(!(fixedBindSetOrSpace == o.fixedBindSetOrSpace)) @@ -1280,10 +1191,6 @@ struct ConstantBlock :type: List[ShaderConstant] )"); rdcarray variables; - DOCUMENT(R"(The bindpoint for this block. This is an index in the -:data:`ShaderBindpointMapping.constantBlocks` list. -)"); - int32_t bindPoint = 0; DOCUMENT(R"(The fixed binding number for this binding. The interpretation of this is API-specific and it is provided purely for informational purposes and has no bearing on how data is accessed or @@ -1356,24 +1263,24 @@ struct ShaderSampler bool operator==(const ShaderSampler &o) const { - return name == o.name && bindPoint == o.bindPoint; + return name == o.name && fixedBindNumber == o.fixedBindNumber && + fixedBindSetOrSpace == o.fixedBindSetOrSpace && bindArraySize == o.bindArraySize; } bool operator<(const ShaderSampler &o) const { if(!(name == o.name)) return name < o.name; - if(!(bindPoint == o.bindPoint)) - return bindPoint < o.bindPoint; + if(!(fixedBindNumber == o.fixedBindNumber)) + return fixedBindNumber < o.fixedBindNumber; + if(!(fixedBindSetOrSpace == o.fixedBindSetOrSpace)) + return fixedBindSetOrSpace < o.fixedBindSetOrSpace; + if(!(bindArraySize == o.bindArraySize)) + return bindArraySize < o.bindArraySize; return false; } DOCUMENT("The name of this sampler."); rdcstr name; - DOCUMENT(R"(The bindpoint for this block. This is an index in either the -:data:`ShaderBindpointMapping.samplers` list. -)"); - int32_t bindPoint; - DOCUMENT(R"(The fixed binding number for this binding. The interpretation of this is API-specific and it is provided purely for informational purposes and has no bearing on how data is accessed or described. Similarly some bindings don't have a fixed bind number and the value here should not be @@ -1435,7 +1342,7 @@ struct ShaderResource { return resType == o.resType && name == o.name && variableType == o.variableType && fixedBindNumber == o.fixedBindNumber && fixedBindSetOrSpace == o.fixedBindSetOrSpace && - bindPoint == o.bindPoint && isTexture == o.isTexture && hasSampler == o.hasSampler && + isTexture == o.isTexture && hasSampler == o.hasSampler && isInputAttachment == o.isInputAttachment && isReadOnly == o.isReadOnly; } bool operator<(const ShaderResource &o) const @@ -1476,12 +1383,6 @@ struct ShaderResource )"); ShaderConstantType variableType; - DOCUMENT(R"(The bindpoint for this block. This is an index in either the -:data:`ShaderBindpointMapping.readOnlyResources` list or -:data:`ShaderBindpointMapping.readWriteResources` list as appropriate (see :data:`isReadOnly`). -)"); - int32_t bindPoint; - DOCUMENT(R"(The fixed binding number for this binding. The interpretation of this is API-specific and it is provided purely for informational purposes and has no bearing on how data is accessed or described. Similarly some bindings don't have a fixed bind number and the value here should not be @@ -1746,9 +1647,7 @@ DECLARE_REFLECTION_STRUCT(ShaderDebugInfo); DOCUMENT(R"(The reflection and metadata fully describing a shader. -The information in this structure is API agnostic, and is matched up against a -:class:`ShaderBindpointMapping` instance to map the information here to the API's binding points -and resource binding scheme. +The information in this structure is API agnostic. )"); struct ShaderReflection { @@ -1853,140 +1752,3 @@ input payload (for mesh shaders) }; DECLARE_REFLECTION_STRUCT(ShaderReflection); - -DOCUMENT(R"(Declares the binding information for a single resource binding. - -See :class:`ShaderBindpointMapping` for how this mapping works in detail. -)"); -struct Bindpoint -{ - DOCUMENT(""); - Bindpoint() - { - bindset = 0; - bind = 0; - used = false; - arraySize = 1; - } - Bindpoint(const Bindpoint &) = default; - Bindpoint &operator=(const Bindpoint &) = default; - - Bindpoint(int32_t s, int32_t b) - { - bindset = s; - bind = b; - used = false; - arraySize = 1; - } - // construct out of an index, useful for searching bindpoint lists (since we only compare by - // bindset and bind) - Bindpoint(const BindpointIndex &idx) - { - bindset = idx.bindset; - bind = idx.bind; - used = false; - arraySize = 1; - } - - bool operator<(const Bindpoint &o) const - { - if(!(bindset == o.bindset)) - return bindset < o.bindset; - return bind < o.bind; - } - bool operator==(const Bindpoint &o) const { return bindset == o.bindset && bind == o.bind; } - DOCUMENT("The binding set."); - int32_t bindset; - DOCUMENT("The binding index."); - int32_t bind; - DOCUMENT("If this is an arrayed binding, the number of elements in the array."); - uint32_t arraySize; - DOCUMENT( - "``True`` if the shader actually uses this resource, otherwise it's declared but unused."); - bool used; -}; - -DECLARE_REFLECTION_STRUCT(Bindpoint); - -DOCUMENT(R"(This structure goes hand in hand with :class:`ShaderReflection` to determine how to map -from bindpoint indices in the resource lists there to API-specific binding points. The ``bindPoint`` -member in :class:`ShaderResource` or :class:`ConstantBlock` refers to an index in these associated -lists, which then map potentially sparsely and potentially in different orders to the appropriate -API registers, indices, or slots. - -API specific details: - -* Direct3D11 - All :data:`Bindpoint.bindset` values are 0 as D3D11 has no notion of sets, and the - only namespacing that exists is by shader stage and object type. Mostly this already exists with - the constant block, read only and read write resource lists. - - :data:`Bindpoint.arraySize` is likewise unused as D3D11 doesn't have arrayed resource bindings. - - :data:`Bindpoint.bind` refers to the register/slot binding within the appropriate type (SRVs for - read-only resources, UAV for read-write resources, samplers/constant buffers in each type). - -* OpenGL - Similarly to D3D11, :data:`Bindpoint.bindset` and :data:`Bindpoint.arraySize` are - unused as OpenGL does not have true binding sets or array resource binds. - - For OpenGL there may be many more duplicate :class:`Bindpoint` objects as the - :data:`Bindpoint.bind` refers to the index in the type-specific list, which is much more - granular on OpenGL. E.g. ``0`` may refer to images, storage buffers, and atomic buffers all within - the :data:`readWriteResources` list. The index is the uniform value of the binding. Since no - objects are namespaced by shader stage, the same value in two shaders refers to the same binding. - -* Direct3D12 - Since D3D12 doesn't have true resource arrays (they are linearised into sequential - registers) :data:`Bindpoint.arraySize` is not used. - - :data:`Bindpoint.bindset` corresponds to register spaces, with :data:`Bindpoint.bind` then - mapping to the register within that space. The root signature then maps these registers to - descriptors. - -* Vulkan - For Vulkan :data:`Bindpoint.bindset` corresponds to the index of the descriptor set, - and :data:`Bindpoint.bind` refers to the index of the descriptor within that set. - :data:`Bindpoint.arraySize` also is used as descriptors in Vulkan can be true arrays, bound all - at once to a single binding. -)"); -struct ShaderBindpointMapping -{ - DOCUMENT(""); - ShaderBindpointMapping() = default; - ShaderBindpointMapping(const ShaderBindpointMapping &) = default; - ShaderBindpointMapping &operator=(const ShaderBindpointMapping &) = default; - - DOCUMENT(R"(This maps input attributes as a simple swizzle on the -:data:`ShaderReflection.inputSignature` indices for APIs where this mapping is mutable at runtime. - -:type: List[int] -)"); - rdcarray inputAttributes; - - DOCUMENT(R"(Provides a list of :class:`Bindpoint` entries for remapping the -:data:`ShaderReflection.constantBlocks` list. - -:type: List[Bindpoint] -)"); - rdcarray constantBlocks; - - DOCUMENT(R"(Provides a list of :class:`Bindpoint` entries for remapping the -:data:`ShaderReflection.samplers` list. - -:type: List[Bindpoint] -)"); - rdcarray samplers; - - DOCUMENT(R"(Provides a list of :class:`Bindpoint` entries for remapping the -:data:`ShaderReflection.readOnlyResources` list. - -:type: List[Bindpoint] -)"); - rdcarray readOnlyResources; - - DOCUMENT(R"(Provides a list of :class:`Bindpoint` entries for remapping the -:data:`ShaderReflection.readWriteResources` list. - -:type: List[Bindpoint] -)"); - rdcarray readWriteResources; -}; - -DECLARE_REFLECTION_STRUCT(ShaderBindpointMapping); diff --git a/renderdoc/api/replay/vk_pipestate.h b/renderdoc/api/replay/vk_pipestate.h index 5f5d0fbaa..4912f7987 100644 --- a/renderdoc/api/replay/vk_pipestate.h +++ b/renderdoc/api/replay/vk_pipestate.h @@ -28,292 +28,6 @@ namespace VKPipe { -DOCUMENT("The contents of a single binding element within a descriptor set, possibly in an array."); -struct BindingElement -{ - DOCUMENT(""); - BindingElement() = default; - BindingElement(const BindingElement &) = default; - BindingElement &operator=(const BindingElement &) = default; - - bool operator==(const BindingElement &o) const - { - return type == o.type && dynamicallyUsed == o.dynamicallyUsed && - viewResourceId == o.viewResourceId && resourceResourceId == o.resourceResourceId && - samplerResourceId == o.samplerResourceId && immutableSampler == o.immutableSampler && - inlineBlock == o.inlineBlock && viewFormat == o.viewFormat && swizzle == o.swizzle && - firstMip == o.firstMip && firstSlice == o.firstSlice && numMips == o.numMips && - numSlices == o.numSlices && byteOffset == o.byteOffset && byteSize == o.byteSize && - filter == o.filter && addressU == o.addressU && addressV == o.addressV && - addressW == o.addressW && mipBias == o.mipBias && maxAnisotropy == o.maxAnisotropy && - compareFunction == o.compareFunction && minLOD == o.minLOD && maxLOD == o.maxLOD && - borderColorValue.uintValue == o.borderColorValue.uintValue && - borderColorType == o.borderColorType && unnormalized == o.unnormalized && - srgbBorder == o.srgbBorder && seamless == o.seamless; - } - bool operator<(const BindingElement &o) const - { - if(!(type == o.type)) - return type < o.type; - if(!(dynamicallyUsed == o.dynamicallyUsed)) - return dynamicallyUsed < o.dynamicallyUsed; - if(!(viewResourceId == o.viewResourceId)) - return viewResourceId < o.viewResourceId; - if(!(resourceResourceId == o.resourceResourceId)) - return resourceResourceId < o.resourceResourceId; - if(!(samplerResourceId == o.samplerResourceId)) - return samplerResourceId < o.samplerResourceId; - if(!(immutableSampler == o.immutableSampler)) - return immutableSampler < o.immutableSampler; - if(!(inlineBlock == o.inlineBlock)) - return inlineBlock < o.inlineBlock; - if(!(viewFormat == o.viewFormat)) - return viewFormat < o.viewFormat; - if(!(swizzle == o.swizzle)) - return swizzle < o.swizzle; - if(!(firstMip == o.firstMip)) - return firstMip < o.firstMip; - if(!(firstSlice == o.firstSlice)) - return firstSlice < o.firstSlice; - if(!(numMips == o.numMips)) - return numMips < o.numMips; - if(!(numSlices == o.numSlices)) - return numSlices < o.numSlices; - if(!(byteOffset == o.byteOffset)) - return byteOffset < o.byteOffset; - if(!(byteSize == o.byteSize)) - return byteSize < o.byteSize; - if(!(filter == o.filter)) - return filter < o.filter; - if(!(addressU == o.addressU)) - return addressU < o.addressU; - if(!(addressV == o.addressV)) - return addressV < o.addressV; - if(!(addressW == o.addressW)) - return addressW < o.addressW; - if(!(mipBias == o.mipBias)) - return mipBias < o.mipBias; - if(!(maxAnisotropy == o.maxAnisotropy)) - return maxAnisotropy < o.maxAnisotropy; - if(!(compareFunction == o.compareFunction)) - return compareFunction < o.compareFunction; - if(!(minLOD == o.minLOD)) - return minLOD < o.minLOD; - if(!(maxLOD == o.maxLOD)) - return maxLOD < o.maxLOD; - if(!(borderColorValue.uintValue == o.borderColorValue.uintValue)) - return borderColorValue.uintValue < o.borderColorValue.uintValue; - if(!(borderColorType == o.borderColorType)) - return borderColorType < o.borderColorType; - if(!(unnormalized == o.unnormalized)) - return unnormalized < o.unnormalized; - if(!(srgbBorder == o.srgbBorder)) - return srgbBorder < o.srgbBorder; - if(!(seamless == o.seamless)) - return seamless < o.seamless; - return false; - } - - DOCUMENT("The :class:`BindType` of this binding element."); - BindType type = BindType::Unknown; - DOCUMENT("The :class:`ResourceId` of the current view object, if one is in use."); - ResourceId viewResourceId; // bufferview, imageview, attachmentview - DOCUMENT("The :class:`ResourceId` of the current underlying buffer or image object."); - ResourceId resourceResourceId; // buffer, image, attachment - DOCUMENT("The :class:`ResourceId` of the current sampler object."); - ResourceId samplerResourceId; - DOCUMENT("``True`` if this is an immutable sampler binding."); - bool immutableSampler = false; - DOCUMENT(R"(``True`` if this binding element is dynamically used. - -If set to ``False`` this means that the binding was available to the shader but during execution it -was not referenced. The data gathered for setting this variable is conservative, meaning that only -accesses through arrays will have this calculated to reduce the required feedback bandwidth - single -non-arrayed descriptors may have this value set to ``True`` even if the shader did not use them, -since single descriptors may only be dynamically skipped by control flow. -)"); - bool dynamicallyUsed = true; - - DOCUMENT(R"(The format cast that the view uses. - -:type: ResourceFormat -)"); - ResourceFormat viewFormat; - - DOCUMENT(R"(The swizzle applied to a texture by the view. - -:type: TextureSwizzle4 -)"); - TextureSwizzle4 swizzle; - - DOCUMENT("For textures - the first mip level used in the view."); - uint32_t firstMip = 0; - DOCUMENT("For textures - the number of mip levels in the view."); - uint32_t numMips = 0; - - DOCUMENT("For 3D textures and texture arrays - the first slice used in the view."); - uint32_t firstSlice = 0; - DOCUMENT("For 3D textures and texture arrays - the number of array slices in the view."); - uint32_t numSlices = 0; - - DOCUMENT(R"(For buffers - the byte offset where the buffer view starts in the underlying buffer. - -For inline block uniforms (see :data:`inlineBlock`) this is the byte offset into the descriptor -set's inline block data. -)"); - uint64_t byteOffset = 0; - DOCUMENT("For buffers - how many bytes are in this buffer view."); - uint64_t byteSize = 0; - - DOCUMENT(R"(The filtering mode. - -:type: TextureFilter -)"); - TextureFilter filter; - DOCUMENT("For samplers - the :class:`AddressMode` in the U direction."); - AddressMode addressU = AddressMode::Wrap; - DOCUMENT("For samplers - the :class:`AddressMode` in the V direction."); - AddressMode addressV = AddressMode::Wrap; - DOCUMENT("For samplers - the :class:`AddressMode` in the W direction."); - AddressMode addressW = AddressMode::Wrap; - DOCUMENT("For samplers - a bias to apply to the calculated mip level before sampling."); - float mipBias = 0.0f; - DOCUMENT("For samplers - the maximum anisotropic filtering level to use."); - float maxAnisotropy = 0.0f; - DOCUMENT("For samplers - the :class:`CompareFunction` for comparison samplers."); - CompareFunction compareFunction = CompareFunction::AlwaysTrue; - DOCUMENT("For samplers and image views - the minimum mip level that can be used."); - float minLOD = 0.0f; - DOCUMENT("For samplers - the maximum mip level that can be used."); - float maxLOD = 0.0f; - DOCUMENT(R"(For samplers - the RGBA border color value. Typically the float tuple inside will be used, -but the exact component type can be checked with :data:`borderColorType`. - -:type: PixelValue -)"); - PixelValue borderColorValue = {}; - DOCUMENT(R"(For samplers - the RGBA border color type. This determines how the data in -:data:`borderColorValue` will be interpreted. - -:type: CompType -)"); - CompType borderColorType = CompType::Float; - DOCUMENT(R"(The swizzle applied to samplers. Primarily for ycbcr samplers applied before -conversion but for non-ycbcr samplers can be used for implementations that require sampler swizzle -information for border colors. - -:type: TextureSwizzle4 -)"); - TextureSwizzle4 samplerSwizzle; - DOCUMENT( - "For samplers - ``True`` if the border colour is swizzled with an sRGB formatted image."); - bool srgbBorder = false; - DOCUMENT("For samplers - ``True`` if unnormalized co-ordinates are used in this sampler."); - bool unnormalized = false; - - DOCUMENT("``True`` if this is an inline uniform block binding."); - bool inlineBlock = false; - - DOCUMENT("``True`` if this sampler is seamless across cubemap boundaries (the default)."); - bool seamless = true; - - DOCUMENT(R"(For samplers - the :class:`ResourceId` of the ycbcr conversion object associated with -this sampler. -)"); - ResourceId ycbcrSampler; - - DOCUMENT("For ycbcr samplers - the :class:`YcbcrConversion` used for conversion."); - YcbcrConversion ycbcrModel; - DOCUMENT("For ycbcr samplers - the :class:`YcbcrRange` used for conversion."); - YcbcrRange ycbcrRange; - DOCUMENT("For ycbcr samplers - the :class:`ChromaSampleLocation` X-axis chroma offset."); - ChromaSampleLocation xChromaOffset; - DOCUMENT("For ycbcr samplers - the :class:`ChromaSampleLocation` Y-axis chroma offset."); - ChromaSampleLocation yChromaOffset; - DOCUMENT("For ycbcr samplers - the :class:`FilterMode` describing the chroma filtering mode."); - FilterMode chromaFilter; - DOCUMENT("For ycbcr samplers - ``True`` if explicit reconstruction is force enabled."); - bool forceExplicitReconstruction; - - DOCUMENT(R"(For samplers - check if the border color is used in this Vulkan sampler. - -:return: ``True`` if the border color is used, ``False`` otherwise. -:rtype: bool -)"); - bool UseBorder() const - { - return addressU == AddressMode::ClampBorder || addressV == AddressMode::ClampBorder || - addressW == AddressMode::ClampBorder; - } -}; - -DOCUMENT("The contents of a single binding within a descriptor set, either arrayed or not."); -struct DescriptorBinding -{ - DOCUMENT(""); - DescriptorBinding() = default; - DescriptorBinding(const DescriptorBinding &) = default; - DescriptorBinding &operator=(const DescriptorBinding &) = default; - - bool operator==(const DescriptorBinding &o) const - { - return descriptorCount == o.descriptorCount && dynamicallyUsedCount == o.dynamicallyUsedCount && - firstUsedIndex == o.firstUsedIndex && lastUsedIndex == o.lastUsedIndex && - stageFlags == o.stageFlags && binds == o.binds; - } - bool operator<(const DescriptorBinding &o) const - { - if(!(descriptorCount == o.descriptorCount)) - return descriptorCount < o.descriptorCount; - if(!(dynamicallyUsedCount == o.dynamicallyUsedCount)) - return dynamicallyUsedCount < o.dynamicallyUsedCount; - if(!(firstUsedIndex == o.firstUsedIndex)) - return firstUsedIndex < o.firstUsedIndex; - if(!(lastUsedIndex == o.lastUsedIndex)) - return lastUsedIndex < o.lastUsedIndex; - if(!(stageFlags == o.stageFlags)) - return stageFlags < o.stageFlags; - if(!(binds == o.binds)) - return binds < o.binds; - return false; - } - DOCUMENT(R"(How many descriptors are in this binding array. -If this binding is empty/non-existant this value will be ``0``. -)"); - uint32_t descriptorCount = 0; - DOCUMENT(R"(Lists how many bindings in :data:`binds` are dynamically used. Useful to avoid -redundant iteration to determine whether any bindings are present. - -For more information see :data:`VKBindingElement.dynamicallyUsed`. -)"); - uint32_t dynamicallyUsedCount = ~0U; - DOCUMENT(R"(Gives the index of the first binding in :data:`binds` that is dynamically used. Useful -to avoid redundant iteration in very large descriptor arrays with a small subset that are used. - -For more information see :data:`VKBindingElement.dynamicallyUsed`. -)"); - int32_t firstUsedIndex = 0; - DOCUMENT(R"(Gives the index of the first binding in :data:`binds` that is dynamically used. Useful -to avoid redundant iteration in very large descriptor arrays with a small subset that are used. - -.. note:: - This may be set to a higher value than the number of bindings, if no dynamic use information is - available. Ensure that this is an additional check on the bind and the count is still respected. - -For more information see :data:`VKBindingElement.dynamicallyUsed`. -)"); - int32_t lastUsedIndex = 0x7fffffff; - DOCUMENT("The :class:`ShaderStageMask` where this binding is visible."); - ShaderStageMask stageFlags = ShaderStageMask::Unknown; - - DOCUMENT(R"(The binding elements. -If :data:`descriptorCount` is 1 then this list has only one element and the binding is not arrayed. - -:type: List[VKBindingElement] -)"); - rdcarray binds; -}; - DOCUMENT("A dynamic offset applied to a single descriptor access."); struct DynamicOffset { @@ -359,8 +73,7 @@ struct DescriptorSet { return layoutResourceId == o.layoutResourceId && descriptorSetResourceId == o.descriptorSetResourceId && - pushDescriptor == o.pushDescriptor && bindings == o.bindings && - inlineData == o.inlineData; + pushDescriptor == o.pushDescriptor; } bool operator<(const DescriptorSet &o) const { @@ -370,10 +83,6 @@ struct DescriptorSet return descriptorSetResourceId < o.descriptorSetResourceId; if(!(pushDescriptor == o.pushDescriptor)) return pushDescriptor < o.pushDescriptor; - if(!(bindings == o.bindings)) - return bindings < o.bindings; - if(!(inlineData == o.inlineData)) - return inlineData < o.inlineData; return false; } DOCUMENT("The :class:`ResourceId` of the descriptor set layout that matches this set."); @@ -383,20 +92,6 @@ struct DescriptorSet DOCUMENT("Indicates if this is a virtual 'push' descriptor set."); bool pushDescriptor = false; - DOCUMENT(R"(The bindings within this set. -This list is indexed by the binding, so it may be sparse (some entries do not contain any elements). - -:type: List[VKDescriptorBinding] -)"); - rdcarray bindings; - - DOCUMENT(R"(The inline byte data within this descriptor set. Individual bindings will have an -offset and size into this buffer. - -:type: bytes -)"); - bytebuf inlineData; - DOCUMENT(R"(A list of dynamic offsets to be applied to specific bindings, on top of the contents of their descriptors. @@ -639,11 +334,6 @@ struct Shader :type: ShaderReflection )"); ShaderReflection *reflection = NULL; - DOCUMENT(R"(The bindpoint mapping data to match :data:`reflection`. - -:type: ShaderBindpointMapping -)"); - ShaderBindpointMapping bindpointMapping; DOCUMENT("A :class:`ShaderStage` identifying which stage this shader is bound to."); ShaderStage stage = ShaderStage::Vertex; @@ -1518,8 +1208,6 @@ struct State }; // namespace VKPipe -DECLARE_REFLECTION_STRUCT(VKPipe::BindingElement); -DECLARE_REFLECTION_STRUCT(VKPipe::DescriptorBinding); DECLARE_REFLECTION_STRUCT(VKPipe::DynamicOffset); DECLARE_REFLECTION_STRUCT(VKPipe::DescriptorSet); DECLARE_REFLECTION_STRUCT(VKPipe::Pipeline); diff --git a/renderdoc/core/replay_proxy.cpp b/renderdoc/core/replay_proxy.cpp index 1d344d937..223db9524 100644 --- a/renderdoc/core/replay_proxy.cpp +++ b/renderdoc/core/replay_proxy.cpp @@ -1212,7 +1212,7 @@ ShaderReflection *ReplayProxy::Proxied_GetShader(ParamSerialiser ¶mser, ShaderReflection *ret = NULL; // only consider eventID part of the key on APIs where shaders are mutable - ShaderReflKey key(m_APIProps.shadersMutable ? m_EventID : 0, pipeline, shader, entry); + ShaderReflKey key(pipeline, shader, entry); if(retser.IsReading() && m_ShaderReflectionCache.find(key) != m_ShaderReflectionCache.end()) return m_ShaderReflectionCache[key]; diff --git a/renderdoc/core/replay_proxy.h b/renderdoc/core/replay_proxy.h index 38412f8e5..4b4190075 100644 --- a/renderdoc/core/replay_proxy.h +++ b/renderdoc/core/replay_proxy.h @@ -657,18 +657,13 @@ private: struct ShaderReflKey { ShaderReflKey() {} - ShaderReflKey(uint32_t eid, ResourceId p, ResourceId s, ShaderEntryPoint e) - : eventId(eid), pipeline(p), shader(s), entry(e) + ShaderReflKey(ResourceId p, ResourceId s, ShaderEntryPoint e) : pipeline(p), shader(s), entry(e) { } - uint32_t eventId; ResourceId pipeline, shader; ShaderEntryPoint entry; bool operator<(const ShaderReflKey &o) const { - if(eventId != o.eventId) - return eventId < o.eventId; - if(pipeline != o.pipeline) return pipeline < o.pipeline; diff --git a/renderdoc/data/glsl_shaders.cpp b/renderdoc/data/glsl_shaders.cpp index f40078ee0..2f5eeab11 100644 --- a/renderdoc/data/glsl_shaders.cpp +++ b/renderdoc/data/glsl_shaders.cpp @@ -268,9 +268,6 @@ void TestGLSLReflection(ShaderType testType, ReflectionMaker compile) REQUIRE(size >= min); \ CHECK(size == min); -#define MAPPING_VALID(mapping) \ - (mapping.inputAttributes.empty() || mapping.inputAttributes[0] != 0x12345678) - if(testType == ShaderType::GLSL || testType == ShaderType::GLSPIRV) { // test GL only features @@ -290,8 +287,7 @@ void main() { )"; ShaderReflection refl; - ShaderBindpointMapping mapping; - compile(ShaderStage::Fragment, source, "main", refl, mapping); + compile(ShaderStage::Fragment, source, "main", refl); if(testType == ShaderType::GLSPIRV) CHECK(refl.encoding == ShaderEncoding::OpenGLSPIRV); @@ -309,7 +305,6 @@ void main() { const ConstantBlock &cblock = refl.constantBlocks[0]; INFO("UBO: " << cblock.name.c_str()); - CHECK(cblock.bindPoint == 0); CHECK(!cblock.bufferBacked); REQUIRE_ARRAY_SIZE(cblock.variables.size(), 2); @@ -341,15 +336,6 @@ void main() { } } } - - if(MAPPING_VALID(mapping)) - { - REQUIRE_ARRAY_SIZE(mapping.constantBlocks.size(), 1); - { - // $Globals - CHECK(mapping.constantBlocks[0].used); - } - } }; SECTION("GL atomic counters") @@ -366,8 +352,7 @@ void main() { )"; ShaderReflection refl; - ShaderBindpointMapping mapping; - compile(ShaderStage::Fragment, source, "main", refl, mapping); + compile(ShaderStage::Fragment, source, "main", refl); REQUIRE_ARRAY_SIZE(refl.readOnlyResources.size(), 0); REQUIRE_ARRAY_SIZE(refl.constantBlocks.size(), 0); @@ -380,7 +365,9 @@ void main() { const ShaderResource &res = refl.readWriteResources[0]; INFO("read-write resource: " << res.name.c_str()); - CHECK(res.bindPoint == 0); + CHECK(res.fixedBindSetOrSpace == 0); + CHECK(res.fixedBindNumber == 0); + CHECK(res.bindArraySize == 1); CHECK(res.resType == TextureType::Buffer); CHECK(res.variableType.members.empty()); CHECK(res.variableType.baseType == VarType::UInt); @@ -388,18 +375,6 @@ void main() { CHECK(res.variableType.columns == 1); } } - - if(MAPPING_VALID(mapping)) - { - REQUIRE_ARRAY_SIZE(mapping.readWriteResources.size(), 1); - { - // atom - CHECK(mapping.readWriteResources[0].bindset == 0); - CHECK(mapping.readWriteResources[0].bind == 0); - CHECK(mapping.readWriteResources[0].arraySize == 1); - CHECK(mapping.readWriteResources[0].used); - } - } }; } else if(testType == ShaderType::Vulkan) @@ -421,8 +396,7 @@ void main() { } )"; ShaderReflection refl; - ShaderBindpointMapping mapping; - compile(ShaderStage::Fragment, source, "main", refl, mapping); + compile(ShaderStage::Fragment, source, "main", refl); CHECK(refl.encoding == ShaderEncoding::SPIRV); @@ -436,19 +410,9 @@ void main() { const ShaderSampler &samp = refl.samplers[0]; INFO("read-only resource: " << samp.name.c_str()); - CHECK(samp.bindPoint == 0); - } - } - - if(MAPPING_VALID(mapping)) - { - REQUIRE_ARRAY_SIZE(mapping.samplers.size(), 1); - { - // S - CHECK(mapping.samplers[0].bindset == 1); - CHECK(mapping.samplers[0].bind == 2); - CHECK(mapping.samplers[0].arraySize == 1); - CHECK(mapping.samplers[0].used); + CHECK(samp.fixedBindSetOrSpace == 1); + CHECK(samp.fixedBindNumber == 2); + CHECK(samp.bindArraySize == 1); } } @@ -459,7 +423,9 @@ void main() { const ShaderResource &res = refl.readOnlyResources[0]; INFO("read-only resource: " << res.name.c_str()); - CHECK(res.bindPoint == 0); + CHECK(res.fixedBindSetOrSpace == 2); + CHECK(res.fixedBindNumber == 4); + CHECK(res.bindArraySize == 1); CHECK(res.resType == TextureType::Texture2D); CHECK(res.variableType.members.empty()); CHECK(res.variableType.baseType == VarType::Float); @@ -470,30 +436,14 @@ void main() { const ShaderResource &res = refl.readOnlyResources[1]; INFO("read-only resource: " << res.name.c_str()); - CHECK(res.bindPoint == 1); + CHECK(res.fixedBindSetOrSpace == 2); + CHECK(res.fixedBindNumber == 5); + CHECK(res.bindArraySize == 1); CHECK(res.resType == TextureType::Texture2D); CHECK(res.variableType.members.empty()); CHECK(res.variableType.baseType == VarType::Float); } } - - if(MAPPING_VALID(mapping)) - { - REQUIRE_ARRAY_SIZE(mapping.readOnlyResources.size(), 2); - { - // T - CHECK(mapping.readOnlyResources[0].bindset == 2); - CHECK(mapping.readOnlyResources[0].bind == 4); - CHECK(mapping.readOnlyResources[0].arraySize == 1); - CHECK(mapping.readOnlyResources[0].used); - - // ST - CHECK(mapping.readOnlyResources[1].bindset == 2); - CHECK(mapping.readOnlyResources[1].bind == 5); - CHECK(mapping.readOnlyResources[1].arraySize == 1); - CHECK(mapping.readOnlyResources[1].used); - } - } }; SECTION("Vulkan specialization constants") @@ -510,8 +460,7 @@ void main() { )"; ShaderReflection refl; - ShaderBindpointMapping mapping; - compile(ShaderStage::Fragment, source, "main", refl, mapping); + compile(ShaderStage::Fragment, source, "main", refl); REQUIRE_ARRAY_SIZE(refl.readOnlyResources.size(), 0); REQUIRE_ARRAY_SIZE(refl.readWriteResources.size(), 0); @@ -524,7 +473,9 @@ void main() { const ConstantBlock &cblock = refl.constantBlocks[0]; INFO("UBO: " << cblock.name.c_str()); - CHECK(cblock.bindPoint == 0); + CHECK(cblock.fixedBindSetOrSpace == SpecializationConstantBindSet); + CHECK(cblock.fixedBindNumber == 0); + CHECK(cblock.bindArraySize == 1); CHECK(!cblock.bufferBacked); CHECK(cblock.byteSize == 0); @@ -564,18 +515,6 @@ void main() { } } } - - if(MAPPING_VALID(mapping)) - { - REQUIRE_ARRAY_SIZE(mapping.constantBlocks.size(), 1); - { - // spec constants - CHECK(mapping.constantBlocks[0].bindset == SpecializationConstantBindSet); - CHECK(mapping.constantBlocks[0].bind == 0); - CHECK(mapping.constantBlocks[0].arraySize == 1); - CHECK(mapping.constantBlocks[0].used); - } - } }; SECTION("Vulkan push constants") @@ -596,8 +535,7 @@ void main() { )"; ShaderReflection refl; - ShaderBindpointMapping mapping; - compile(ShaderStage::Fragment, source, "main", refl, mapping); + compile(ShaderStage::Fragment, source, "main", refl); REQUIRE_ARRAY_SIZE(refl.readOnlyResources.size(), 0); REQUIRE_ARRAY_SIZE(refl.readWriteResources.size(), 0); @@ -610,7 +548,9 @@ void main() { const ConstantBlock &cblock = refl.constantBlocks[0]; INFO("UBO: " << cblock.name.c_str()); - CHECK(cblock.bindPoint == 0); + CHECK(cblock.fixedBindSetOrSpace == PushConstantBindSet); + CHECK(cblock.fixedBindNumber == 0); + CHECK(cblock.bindArraySize == 1); CHECK(!cblock.bufferBacked); CHECK(cblock.byteSize == 16); @@ -655,18 +595,6 @@ void main() { } } } - - if(MAPPING_VALID(mapping)) - { - REQUIRE_ARRAY_SIZE(mapping.constantBlocks.size(), 1); - { - // push_data - CHECK(mapping.constantBlocks[0].bindset == PushConstantBindSet); - CHECK(mapping.constantBlocks[0].bind == 0); - CHECK(mapping.constantBlocks[0].arraySize == 1); - CHECK(mapping.constantBlocks[0].used); - } - } }; } else @@ -696,8 +624,7 @@ void main() { )"; ShaderReflection refl; - ShaderBindpointMapping mapping; - compile(ShaderStage::Fragment, source, "main", refl, mapping); + compile(ShaderStage::Fragment, source, "main", refl); REQUIRE_ARRAY_SIZE(refl.constantBlocks.size(), 0); REQUIRE_ARRAY_SIZE(refl.readOnlyResources.size(), 0); @@ -759,8 +686,7 @@ void main() { )"; ShaderReflection refl; - ShaderBindpointMapping mapping; - compile(ShaderStage::Fragment, source, "main", refl, mapping); + compile(ShaderStage::Fragment, source, "main", refl); REQUIRE_ARRAY_SIZE(refl.constantBlocks.size(), 0); REQUIRE_ARRAY_SIZE(refl.readOnlyResources.size(), 0); @@ -865,20 +791,6 @@ void main() { CHECK(sig.channelUsedMask == 0x1); } } - - if(MAPPING_VALID(mapping)) - { - REQUIRE_ARRAY_SIZE(mapping.inputAttributes.size(), 16); - for(size_t i = 0; i < mapping.inputAttributes.size(); i++) - { - if(i == 3) - CHECK((mapping.inputAttributes[i] == -1 || mapping.inputAttributes[i] == 1)); - else if(i == 6) - CHECK((mapping.inputAttributes[i] == -1 || mapping.inputAttributes[i] == 2)); - else - CHECK(mapping.inputAttributes[i] == -1); - } - } }; SECTION("constant buffers") @@ -909,8 +821,7 @@ void main() { )"; ShaderReflection refl; - ShaderBindpointMapping mapping; - compile(ShaderStage::Fragment, source, "main", refl, mapping); + compile(ShaderStage::Fragment, source, "main", refl); REQUIRE_ARRAY_SIZE(refl.readOnlyResources.size(), 0); REQUIRE_ARRAY_SIZE(refl.readWriteResources.size(), 0); @@ -926,7 +837,9 @@ void main() { const ConstantBlock &cblock = refl.constantBlocks[0]; INFO("UBO: " << cblock.name.c_str()); - CHECK(cblock.bindPoint == 0); + CHECK(cblock.fixedBindSetOrSpace == 0); + CHECK(cblock.fixedBindNumber == 8); + CHECK(cblock.bindArraySize == 1); CHECK(cblock.bufferBacked); CHECK(cblock.byteSize == 272); @@ -1074,18 +987,6 @@ void main() { } } } - - if(MAPPING_VALID(mapping)) - { - REQUIRE_ARRAY_SIZE(mapping.constantBlocks.size(), 1); - { - // ubo - CHECK(mapping.constantBlocks[0].bindset == 0); - CHECK(mapping.constantBlocks[0].bind == 8); - CHECK(mapping.constantBlocks[0].arraySize == 1); - CHECK(mapping.constantBlocks[0].used); - } - } }; SECTION("Textures") @@ -1106,8 +1007,7 @@ void main() { )"; ShaderReflection refl; - ShaderBindpointMapping mapping; - compile(ShaderStage::Fragment, source, "main", refl, mapping); + compile(ShaderStage::Fragment, source, "main", refl); REQUIRE_ARRAY_SIZE(refl.constantBlocks.size(), 0); REQUIRE_ARRAY_SIZE(refl.readWriteResources.size(), 0); @@ -1119,7 +1019,9 @@ void main() { const ShaderResource &res = refl.readOnlyResources[0]; INFO("read-only resource: " << res.name.c_str()); - CHECK(res.bindPoint == 0); + CHECK(res.fixedBindSetOrSpace == 0); + CHECK(res.fixedBindNumber == 3); + CHECK(res.bindArraySize == 1); CHECK(res.resType == TextureType::Texture2D); CHECK(res.variableType.members.empty()); CHECK(res.variableType.baseType == VarType::Float); @@ -1130,7 +1032,9 @@ void main() { const ShaderResource &res = refl.readOnlyResources[1]; INFO("read-only resource: " << res.name.c_str()); - CHECK(res.bindPoint == 1); + CHECK(res.fixedBindSetOrSpace == 0); + CHECK(res.fixedBindNumber == 5); + CHECK(res.bindArraySize == 1); CHECK(res.resType == TextureType::Texture3D); CHECK(res.variableType.members.empty()); CHECK(res.variableType.baseType == VarType::SInt); @@ -1141,36 +1045,14 @@ void main() { const ShaderResource &res = refl.readOnlyResources[2]; INFO("read-only resource: " << res.name.c_str()); - CHECK(res.bindPoint == 2); + CHECK(res.fixedBindSetOrSpace == 0); + CHECK(res.fixedBindNumber == 7); + CHECK(res.bindArraySize == 1); CHECK(res.resType == TextureType::Buffer); CHECK(res.variableType.members.empty()); CHECK(res.variableType.baseType == VarType::Float); } } - - if(MAPPING_VALID(mapping)) - { - REQUIRE_ARRAY_SIZE(mapping.readOnlyResources.size(), 3); - { - // tex2d - CHECK(mapping.readOnlyResources[0].bindset == 0); - CHECK(mapping.readOnlyResources[0].bind == 3); - CHECK(mapping.readOnlyResources[0].arraySize == 1); - CHECK(mapping.readOnlyResources[0].used); - - // tex3d - CHECK(mapping.readOnlyResources[1].bindset == 0); - CHECK(mapping.readOnlyResources[1].bind == 5); - CHECK(mapping.readOnlyResources[1].arraySize == 1); - CHECK(mapping.readOnlyResources[1].used); - - // texBuf - CHECK(mapping.readOnlyResources[2].bindset == 0); - CHECK(mapping.readOnlyResources[2].bind == 7); - CHECK(mapping.readOnlyResources[2].arraySize == 1); - CHECK(mapping.readOnlyResources[2].used); - } - } }; #define REQUIRE_ARRAY_SIZE(size, min) \ @@ -1264,8 +1146,7 @@ void main() { )"; ShaderReflection refl; - ShaderBindpointMapping mapping; - compile(ShaderStage::Fragment, source, "main", refl, mapping); + compile(ShaderStage::Fragment, source, "main", refl); REQUIRE_ARRAY_SIZE(refl.constantBlocks.size(), 1); { @@ -1740,8 +1621,7 @@ void main() { )"; ShaderReflection refl; - ShaderBindpointMapping mapping; - compile(ShaderStage::Fragment, source, "main", refl, mapping); + compile(ShaderStage::Fragment, source, "main", refl); REQUIRE_ARRAY_SIZE(refl.samplers.size(), 0); REQUIRE_ARRAY_SIZE(refl.constantBlocks.size(), 0); @@ -1757,7 +1637,9 @@ void main() { const ShaderResource &res = refl.readWriteResources[0]; INFO("read-write resource: " << res.name.c_str()); - CHECK(res.bindPoint == 0); + CHECK(res.fixedBindSetOrSpace == 0); + CHECK(res.fixedBindNumber == 2); + CHECK(res.bindArraySize == 1); CHECK(res.resType == TextureType::Buffer); REQUIRE_ARRAY_SIZE(res.variableType.members.size(), 3); @@ -1850,7 +1732,9 @@ void main() { const ShaderResource &res = refl.readWriteResources[1]; INFO("read-write resource: " << res.name.c_str()); - CHECK(res.bindPoint == 1); + CHECK(res.fixedBindSetOrSpace == 0); + CHECK(res.fixedBindNumber == 5); + CHECK(res.bindArraySize == 1); CHECK(res.resType == TextureType::Buffer); REQUIRE_ARRAY_SIZE(res.variableType.members.size(), 1); @@ -1975,24 +1859,6 @@ void main() { } } } - - if(MAPPING_VALID(mapping)) - { - REQUIRE_ARRAY_SIZE(mapping.readWriteResources.size(), 2); - { - // ssbo - CHECK(mapping.readWriteResources[0].bindset == 0); - CHECK(mapping.readWriteResources[0].bind == 2); - CHECK(mapping.readWriteResources[0].arraySize == 1); - CHECK(mapping.readWriteResources[0].used); - - // ssbo2 - CHECK(mapping.readWriteResources[1].bindset == 0); - CHECK(mapping.readWriteResources[1].bind == 5); - CHECK(mapping.readWriteResources[1].arraySize == 1); - CHECK(mapping.readWriteResources[1].used); - } - } }; SECTION("vertex shader fixed function outputs") @@ -2007,8 +1873,7 @@ void main() { )"; ShaderReflection refl; - ShaderBindpointMapping mapping; - compile(ShaderStage::Vertex, source, "main", refl, mapping); + compile(ShaderStage::Vertex, source, "main", refl); REQUIRE_ARRAY_SIZE(refl.samplers.size(), 0); REQUIRE_ARRAY_SIZE(refl.constantBlocks.size(), 0); @@ -2042,8 +1907,7 @@ void main() { )"; refl = ShaderReflection(); - mapping = ShaderBindpointMapping(); - compile(ShaderStage::Vertex, source2, "main", refl, mapping); + compile(ShaderStage::Vertex, source2, "main", refl); REQUIRE_ARRAY_SIZE(refl.samplers.size(), 0); REQUIRE_ARRAY_SIZE(refl.constantBlocks.size(), 0); @@ -2103,8 +1967,7 @@ void main() )"; ShaderReflection refl; - ShaderBindpointMapping mapping; - compile(ShaderStage::Vertex, source, "main", refl, mapping); + compile(ShaderStage::Vertex, source, "main", refl); REQUIRE_ARRAY_SIZE(refl.samplers.size(), 0); REQUIRE_ARRAY_SIZE(refl.constantBlocks.size(), 0); @@ -2293,8 +2156,7 @@ void main() )"; ShaderReflection refl; - ShaderBindpointMapping mapping; - compile(ShaderStage::Vertex, source, "main", refl, mapping); + compile(ShaderStage::Vertex, source, "main", refl); REQUIRE_ARRAY_SIZE(refl.outputSignature.size(), 11); { @@ -2464,8 +2326,7 @@ void main() )"; ShaderReflection refl; - ShaderBindpointMapping mapping; - compile(ShaderStage::Vertex, source, "main", refl, mapping); + compile(ShaderStage::Vertex, source, "main", refl); REQUIRE_ARRAY_SIZE(refl.samplers.size(), 0); REQUIRE_ARRAY_SIZE(refl.constantBlocks.size(), 0); @@ -2579,8 +2440,7 @@ void main() )"; ShaderReflection refl; - ShaderBindpointMapping mapping; - compile(ShaderStage::Geometry, source, "main", refl, mapping); + compile(ShaderStage::Geometry, source, "main", refl); REQUIRE_ARRAY_SIZE(refl.samplers.size(), 0); REQUIRE_ARRAY_SIZE(refl.constantBlocks.size(), 0); @@ -2677,8 +2537,7 @@ void main() { CHECK(size == min); ShaderReflection refl; - ShaderBindpointMapping mapping; - compile(ShaderStage::Fragment, source, "main", refl, mapping); + compile(ShaderStage::Fragment, source, "main", refl); // GLSL 'expands' these arrays size_t countRO = (testType == ShaderType::GLSL ? 7 : 1); @@ -2698,7 +2557,9 @@ void main() { const ShaderResource &res = refl.readOnlyResources[i]; INFO("read-only resource: " << res.name.c_str()); - CHECK(res.bindPoint == (int32_t)i); + CHECK(res.fixedBindSetOrSpace == 0); + CHECK(res.fixedBindNumber == 3 + i); + CHECK(res.bindArraySize == arraySizeRO); CHECK(res.resType == TextureType::Texture2D); CHECK(res.variableType.members.empty()); CHECK(res.variableType.baseType == VarType::Float); @@ -2706,20 +2567,6 @@ void main() { } } - if(MAPPING_VALID(mapping)) - { - REQUIRE_ARRAY_SIZE(mapping.readOnlyResources.size(), countRO); - { - for(size_t i = 0; i < countRO; i++) - { - CHECK(mapping.readOnlyResources[i].bindset == 0); - CHECK(mapping.readOnlyResources[i].bind == 3 + (int32_t)i); - CHECK(mapping.readOnlyResources[i].arraySize == arraySizeRO); - CHECK(mapping.readOnlyResources[i].used); - } - } - } - size_t countRW = (testType == ShaderType::GLSL ? 5 : 1); size_t arraySizeRW = (testType == ShaderType::GLSL ? 1 : 5); @@ -2736,7 +2583,9 @@ void main() { const ShaderResource &res = refl.readWriteResources[i]; INFO("read-write resource: " << res.name.c_str()); - CHECK(res.bindPoint == (int32_t)i); + CHECK(res.fixedBindSetOrSpace == 0); + CHECK(res.fixedBindNumber == 2 + i); + CHECK(res.bindArraySize == arraySizeRW); CHECK(res.resType == TextureType::Buffer); // due to a bug in glslang the reflection is broken for these SSBOs. So we can still run @@ -2775,20 +2624,6 @@ void main() { } } } - - if(MAPPING_VALID(mapping)) - { - REQUIRE_ARRAY_SIZE(mapping.readWriteResources.size(), countRW); - { - for(size_t i = 0; i < countRW; i++) - { - CHECK(mapping.readWriteResources[i].bindset == 0); - CHECK(mapping.readWriteResources[i].bind == 2 + (int32_t)i); - CHECK(mapping.readWriteResources[i].arraySize == arraySizeRW); - CHECK(mapping.readWriteResources[i].used); - } - } - } }; } diff --git a/renderdoc/data/glsl_shaders.h b/renderdoc/data/glsl_shaders.h index 137c6cd64..388f02ebc 100644 --- a/renderdoc/data/glsl_shaders.h +++ b/renderdoc/data/glsl_shaders.h @@ -40,9 +40,7 @@ rdcstr InsertSnippetAfterVersion(ShaderType type, const char *source, int len, c // for unit tests struct ShaderReflection; -struct ShaderBindpointMapping; enum class ShaderStage : uint8_t; -using ReflectionMaker = - std::function; +using ReflectionMaker = std::function; void TestGLSLReflection(ShaderType testType, ReflectionMaker compile); diff --git a/renderdoc/driver/d3d11/d3d11_replay.cpp b/renderdoc/driver/d3d11/d3d11_replay.cpp index dcb168f42..4657d6a95 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.cpp +++ b/renderdoc/driver/d3d11/d3d11_replay.cpp @@ -426,7 +426,6 @@ APIProperties D3D11Replay::GetAPIProperties() ret.localRenderer = GraphicsAPI::D3D11; ret.vendor = m_DriverInfo.vendor; ret.degraded = m_WARP; - ret.shadersMutable = false; ret.shaderDebugging = true; ret.pixelHistory = true; @@ -821,297 +820,11 @@ void D3D11Replay::SavePipelineState(uint32_t eventId) ShaderReflection *refl = NULL; if(shad != NULL) - { refl = &shad->GetDetails(); - dst.bindpointMapping = shad->GetMapping(); - } - else - { - dst.bindpointMapping = ShaderBindpointMapping(); - } dst.resourceId = rm->GetUnreplacedOriginalID(id); dst.reflection = refl; - dst.constantBuffers.resize(D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT); - for(size_t s = 0; s < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; s++) - { - dst.constantBuffers[s].resourceId = - rm->GetOriginalID(GetIDForDeviceChild(src.ConstantBuffers[s])); - dst.constantBuffers[s].vecOffset = src.CBOffsets[s]; - dst.constantBuffers[s].vecCount = src.CBCounts[s]; - } - - dst.samplers.resize(D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT); - for(size_t s = 0; s < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; s++) - { - D3D11Pipe::Sampler &samp = dst.samplers[s]; - - samp.resourceId = rm->GetOriginalID(GetIDForDeviceChild(src.Samplers[s])); - - if(samp.resourceId != ResourceId()) - { - D3D11_SAMPLER_DESC desc; - src.Samplers[s]->GetDesc(&desc); - - samp.addressU = MakeAddressMode(desc.AddressU); - samp.addressV = MakeAddressMode(desc.AddressV); - samp.addressW = MakeAddressMode(desc.AddressW); - - samp.borderColor = desc.BorderColor; - - samp.compareFunction = MakeCompareFunc(desc.ComparisonFunc); - samp.filter = MakeFilter(desc.Filter); - samp.maxAnisotropy = 0; - if(samp.filter.mip == FilterMode::Anisotropic) - samp.maxAnisotropy = desc.MaxAnisotropy; - samp.maxLOD = desc.MaxLOD; - samp.minLOD = desc.MinLOD; - samp.mipLODBias = desc.MipLODBias; - } - else - { - samp.addressU = samp.addressV = samp.addressW = AddressMode::ClampEdge; - - samp.borderColor = {1.0f, 1.0f, 1.0f, 1.0f}; - - samp.compareFunction = CompareFunction::Never; - samp.filter.filter = FilterFunction::Normal; - samp.filter.magnify = FilterMode::Linear; - samp.filter.minify = FilterMode::Linear; - samp.filter.mip = FilterMode::Linear; - samp.maxAnisotropy = 1; - samp.maxLOD = FLT_MAX; - samp.minLOD = -FLT_MAX; - samp.mipLODBias = 0.0f; - } - } - - dst.srvs.resize(D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT); - for(size_t s = 0; s < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; s++) - { - D3D11Pipe::View &view = dst.srvs[s]; - - view.viewResourceId = rm->GetOriginalID(GetIDForDeviceChild(src.SRVs[s])); - - if(view.viewResourceId != ResourceId()) - { - D3D11_SHADER_RESOURCE_VIEW_DESC desc; - src.SRVs[s]->GetDesc(&desc); - - view.viewFormat = MakeResourceFormat(desc.Format); - - ID3D11Resource *res = NULL; - src.SRVs[s]->GetResource(&res); - - view.structured = false; - view.bufferStructCount = 0; - - view.elementByteSize = - desc.Format == DXGI_FORMAT_UNKNOWN ? 1 : GetByteSize(1, 1, 1, desc.Format, 0); - - view.resourceResourceId = rm->GetOriginalID(GetIDForDeviceChild(res)); - - view.type = MakeTextureDim(desc.ViewDimension); - - if(desc.ViewDimension == D3D11_SRV_DIMENSION_BUFFER) - { - view.firstElement = desc.Buffer.FirstElement; - view.numElements = desc.Buffer.NumElements; - - D3D11_BUFFER_DESC bufdesc; - ((ID3D11Buffer *)res)->GetDesc(&bufdesc); - - view.structured = bufdesc.StructureByteStride > 0 && desc.Format == DXGI_FORMAT_UNKNOWN; - - if(view.structured) - view.elementByteSize = bufdesc.StructureByteStride; - } - else if(desc.ViewDimension == D3D11_SRV_DIMENSION_BUFFEREX) - { - view.firstElement = desc.BufferEx.FirstElement; - view.numElements = desc.BufferEx.NumElements; - view.bufferFlags = D3DBufferViewFlags(desc.BufferEx.Flags); - - D3D11_BUFFER_DESC bufdesc; - ((ID3D11Buffer *)res)->GetDesc(&bufdesc); - - view.structured = bufdesc.StructureByteStride > 0 && desc.Format == DXGI_FORMAT_UNKNOWN; - - if(view.structured) - view.elementByteSize = bufdesc.StructureByteStride; - } - else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE1D) - { - view.firstMip = desc.Texture1D.MostDetailedMip; - view.numMips = desc.Texture1D.MipLevels; - view.firstSlice = 0; - view.numSlices = 1; - } - else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE1DARRAY) - { - view.firstMip = desc.Texture1DArray.MostDetailedMip; - view.numMips = desc.Texture1DArray.MipLevels; - view.numSlices = desc.Texture1DArray.ArraySize; - view.firstSlice = desc.Texture1DArray.FirstArraySlice; - } - else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2D) - { - view.firstMip = desc.Texture2D.MostDetailedMip; - view.numMips = desc.Texture2D.MipLevels; - view.firstSlice = 0; - view.numSlices = 1; - } - else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2DARRAY) - { - view.firstMip = desc.Texture2DArray.MostDetailedMip; - view.numMips = desc.Texture2DArray.MipLevels; - view.firstSlice = desc.Texture2DArray.FirstArraySlice; - view.numSlices = desc.Texture2DArray.ArraySize; - } - else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2DMS) - { - view.firstMip = 0; - view.numMips = 1; - view.firstSlice = 0; - view.numSlices = 1; - } - else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY) - { - view.firstMip = 0; - view.numMips = 1; - view.numSlices = desc.Texture2DMSArray.ArraySize; - view.firstSlice = desc.Texture2DMSArray.FirstArraySlice; - } - else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE3D) - { - view.firstMip = desc.Texture3D.MostDetailedMip; - view.numMips = desc.Texture3D.MipLevels; - view.firstSlice = 0; - view.numSlices = 1; - } - else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURECUBE) - { - view.firstMip = desc.TextureCube.MostDetailedMip; - view.numMips = desc.TextureCube.MipLevels; - view.firstSlice = 0; - view.numSlices = 6; - } - else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURECUBEARRAY) - { - view.firstMip = desc.TextureCubeArray.MostDetailedMip; - view.numMips = desc.TextureCubeArray.MipLevels; - view.firstSlice = desc.TextureCubeArray.First2DArrayFace; - view.numSlices = desc.TextureCubeArray.NumCubes * 6; - } - - SAFE_RELEASE(res); - } - else - { - view = D3D11Pipe::View(); - } - } - - dst.uavs.resize(D3D11_1_UAV_SLOT_COUNT); - for(size_t s = 0; dst.stage == ShaderStage::Compute && s < D3D11_1_UAV_SLOT_COUNT; s++) - { - D3D11Pipe::View &view = dst.uavs[s]; - - view.viewResourceId = rm->GetOriginalID(GetIDForDeviceChild(rs->CSUAVs[s])); - - if(view.viewResourceId != ResourceId()) - { - D3D11_UNORDERED_ACCESS_VIEW_DESC desc; - rs->CSUAVs[s]->GetDesc(&desc); - - ID3D11Resource *res = NULL; - rs->CSUAVs[s]->GetResource(&res); - - view.structured = false; - view.bufferStructCount = 0; - - view.elementByteSize = - desc.Format == DXGI_FORMAT_UNKNOWN ? 1 : GetByteSize(1, 1, 1, desc.Format, 0); - - view.counterResourceId = ResourceId(); - - if(desc.ViewDimension == D3D11_UAV_DIMENSION_BUFFER && - (desc.Buffer.Flags & (D3D11_BUFFER_UAV_FLAG_APPEND | D3D11_BUFFER_UAV_FLAG_COUNTER))) - { - view.bufferStructCount = GetDebugManager()->GetStructCount(rs->CSUAVs[s]); - - view.counterResourceId = GetDebugManager()->GetCounterBufferID(rs->CSUAVs[s]); - } - - view.resourceResourceId = rm->GetOriginalID(GetIDForDeviceChild(res)); - - view.viewFormat = MakeResourceFormat(desc.Format); - view.type = MakeTextureDim(desc.ViewDimension); - - if(desc.ViewDimension == D3D11_UAV_DIMENSION_BUFFER) - { - view.numSlices = 1; - view.firstSlice = 0; - view.firstMip = 0; - view.numMips = 1; - - view.firstElement = desc.Buffer.FirstElement; - view.numElements = desc.Buffer.NumElements; - view.bufferFlags = D3DBufferViewFlags(desc.Buffer.Flags); - - D3D11_BUFFER_DESC bufdesc; - ((ID3D11Buffer *)res)->GetDesc(&bufdesc); - - view.structured = bufdesc.StructureByteStride > 0 && desc.Format == DXGI_FORMAT_UNKNOWN; - - if(view.structured) - view.elementByteSize = bufdesc.StructureByteStride; - } - else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE1D) - { - view.numSlices = 1; - view.firstSlice = 0; - view.firstMip = desc.Texture1D.MipSlice; - view.numMips = 1; - } - else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE1DARRAY) - { - view.numSlices = desc.Texture1DArray.ArraySize; - view.firstSlice = desc.Texture1DArray.FirstArraySlice; - view.firstMip = desc.Texture1DArray.MipSlice; - view.numMips = 1; - } - else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE2D) - { - view.numSlices = 1; - view.firstSlice = 0; - view.firstMip = desc.Texture2D.MipSlice; - view.numMips = 1; - } - else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE2DARRAY) - { - view.numSlices = desc.Texture2DArray.ArraySize; - view.firstSlice = desc.Texture2DArray.FirstArraySlice; - view.firstMip = desc.Texture2DArray.MipSlice; - view.numMips = 1; - } - else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE3D) - { - view.numSlices = desc.Texture3D.WSize; - view.firstSlice = desc.Texture3D.FirstWSlice; - view.firstMip = desc.Texture3D.MipSlice; - view.numMips = 1; - } - - SAFE_RELEASE(res); - } - else - { - view = D3D11Pipe::View(); - } - } - dst.classInstances.reserve(src.NumInstances); for(UINT s = 0; s < src.NumInstances; s++) { @@ -1339,99 +1052,6 @@ void D3D11Replay::SavePipelineState(uint32_t eventId) ret.outputMerger.uavStartSlot = rs->OM.UAVStartSlot; - ret.outputMerger.uavs.resize(D3D11_1_UAV_SLOT_COUNT); - for(size_t s = 0; s < D3D11_1_UAV_SLOT_COUNT; s++) - { - D3D11Pipe::View view; - - view.viewResourceId = rm->GetOriginalID(GetIDForDeviceChild(rs->OM.UAVs[s])); - - if(view.viewResourceId != ResourceId()) - { - D3D11_UNORDERED_ACCESS_VIEW_DESC desc; - rs->OM.UAVs[s]->GetDesc(&desc); - - ID3D11Resource *res = NULL; - rs->OM.UAVs[s]->GetResource(&res); - - view.structured = false; - view.bufferStructCount = 0; - view.elementByteSize = - desc.Format == DXGI_FORMAT_UNKNOWN ? 1 : GetByteSize(1, 1, 1, desc.Format, 0); - - if(desc.ViewDimension == D3D11_UAV_DIMENSION_BUFFER && - (desc.Buffer.Flags & (D3D11_BUFFER_UAV_FLAG_APPEND | D3D11_BUFFER_UAV_FLAG_COUNTER))) - { - view.bufferStructCount = GetDebugManager()->GetStructCount(rs->OM.UAVs[s]); - - view.counterResourceId = GetDebugManager()->GetCounterBufferID(rs->OM.UAVs[s]); - } - - view.resourceResourceId = rm->GetOriginalID(GetIDForDeviceChild(res)); - - view.viewFormat = MakeResourceFormat(desc.Format); - view.type = MakeTextureDim(desc.ViewDimension); - - if(desc.ViewDimension == D3D11_UAV_DIMENSION_BUFFER) - { - view.firstElement = desc.Buffer.FirstElement; - view.numElements = desc.Buffer.NumElements; - view.bufferFlags = D3DBufferViewFlags(desc.Buffer.Flags); - - D3D11_BUFFER_DESC bufdesc; - ((ID3D11Buffer *)res)->GetDesc(&bufdesc); - - view.structured = bufdesc.StructureByteStride > 0 && desc.Format == DXGI_FORMAT_UNKNOWN; - - if(view.structured) - view.elementByteSize = bufdesc.StructureByteStride; - } - else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE1D) - { - view.numSlices = 1; - view.firstSlice = 0; - view.firstMip = desc.Texture1D.MipSlice; - view.numMips = 1; - } - else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE1DARRAY) - { - view.numSlices = desc.Texture1DArray.ArraySize; - view.firstSlice = desc.Texture1DArray.FirstArraySlice; - view.firstMip = desc.Texture1DArray.MipSlice; - view.numMips = 1; - } - else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE2D) - { - view.numSlices = 1; - view.firstSlice = 0; - view.firstMip = desc.Texture2D.MipSlice; - view.numMips = 1; - } - else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE2DARRAY) - { - view.numSlices = desc.Texture2DArray.ArraySize; - view.firstSlice = desc.Texture2DArray.FirstArraySlice; - view.firstMip = desc.Texture2DArray.MipSlice; - view.numMips = 1; - } - else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE3D) - { - view.numSlices = desc.Texture3D.WSize; - view.firstSlice = desc.Texture3D.FirstWSlice; - view.firstMip = desc.Texture3D.MipSlice; - view.numMips = 1; - } - - SAFE_RELEASE(res); - } - else - { - view = D3D11Pipe::View(); - } - - ret.outputMerger.uavs[s] = view; - } - { D3D11Pipe::View &view = ret.outputMerger.depthTarget; diff --git a/renderdoc/driver/d3d11/d3d11_resources.cpp b/renderdoc/driver/d3d11/d3d11_resources.cpp index c0fb0c68e..074967587 100644 --- a/renderdoc/driver/d3d11/d3d11_resources.cpp +++ b/renderdoc/driver/d3d11/d3d11_resources.cpp @@ -93,7 +93,7 @@ void WrappedShader::ShaderEntry::BuildReflection() 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); + MakeShaderReflection(m_DXBCFile, m_Details); m_Details->resourceId = m_ID; DescriptorAccess access; @@ -101,50 +101,47 @@ void WrappedShader::ShaderEntry::BuildReflection() access.stage = m_Details->stage; access.byteSize = 1; - m_Access.reserve(m_Mapping.constantBlocks.size() + m_Mapping.samplers.size() + - m_Mapping.readOnlyResources.size() + m_Mapping.readWriteResources.size()); + m_Access.reserve(m_Details->constantBlocks.size() + m_Details->samplers.size() + + m_Details->readOnlyResources.size() + m_Details->readWriteResources.size()); - RDCASSERT(m_Mapping.constantBlocks.size() < 0xffff, m_Mapping.constantBlocks.size()); - for(uint16_t i = 0; i < m_Mapping.constantBlocks.size(); i++) + RDCASSERT(m_Details->constantBlocks.size() < 0xffff, m_Details->constantBlocks.size()); + for(uint16_t i = 0; i < m_Details->constantBlocks.size(); i++) { - access.staticallyUnused = !m_Mapping.constantBlocks[i].used; access.type = DescriptorType::ConstantBuffer; access.index = i; access.byteOffset = EncodeD3D11DescriptorIndex( - {access.stage, D3D11DescriptorMapping::CBs, (uint32_t)m_Mapping.constantBlocks[i].bind}); + {access.stage, D3D11DescriptorMapping::CBs, m_Details->constantBlocks[i].fixedBindNumber}); m_Access.push_back(access); } - RDCASSERT(m_Mapping.samplers.size() < 0xffff, m_Mapping.samplers.size()); - for(uint16_t i = 0; i < m_Mapping.samplers.size(); i++) + RDCASSERT(m_Details->samplers.size() < 0xffff, m_Details->samplers.size()); + for(uint16_t i = 0; i < m_Details->samplers.size(); i++) { - access.staticallyUnused = !m_Mapping.samplers[i].used; access.type = DescriptorType::Sampler; access.index = i; access.byteOffset = EncodeD3D11DescriptorIndex( - {access.stage, D3D11DescriptorMapping::Samplers, (uint32_t)m_Mapping.samplers[i].bind}); + {access.stage, D3D11DescriptorMapping::Samplers, m_Details->samplers[i].fixedBindNumber}); m_Access.push_back(access); } - RDCASSERT(m_Mapping.readOnlyResources.size() < 0xffff, m_Mapping.readOnlyResources.size()); - for(uint16_t i = 0; i < m_Mapping.readOnlyResources.size(); i++) + RDCASSERT(m_Details->readOnlyResources.size() < 0xffff, m_Details->readOnlyResources.size()); + for(uint16_t i = 0; i < m_Details->readOnlyResources.size(); i++) { - access.staticallyUnused = !m_Mapping.readOnlyResources[i].used; access.type = m_Details->readOnlyResources[i].descriptorType; access.index = i; access.byteOffset = EncodeD3D11DescriptorIndex({access.stage, D3D11DescriptorMapping::SRVs, - (uint32_t)m_Mapping.readOnlyResources[i].bind}); + m_Details->readOnlyResources[i].fixedBindNumber}); m_Access.push_back(access); } - RDCASSERT(m_Mapping.readWriteResources.size() < 0xffff, m_Mapping.readWriteResources.size()); - for(uint16_t i = 0; i < m_Mapping.readWriteResources.size(); i++) + RDCASSERT(m_Details->readWriteResources.size() < 0xffff, m_Details->readWriteResources.size()); + for(uint16_t i = 0; i < m_Details->readWriteResources.size(); i++) { - access.staticallyUnused = !m_Mapping.readWriteResources[i].used; access.type = m_Details->readWriteResources[i].descriptorType; access.index = i; - access.byteOffset = EncodeD3D11DescriptorIndex({access.stage, D3D11DescriptorMapping::UAVs, - (uint32_t)m_Mapping.readWriteResources[i].bind}); + access.byteOffset = + EncodeD3D11DescriptorIndex({access.stage, D3D11DescriptorMapping::UAVs, + m_Details->readWriteResources[i].fixedBindNumber}); m_Access.push_back(access); } } diff --git a/renderdoc/driver/d3d11/d3d11_resources.h b/renderdoc/driver/d3d11/d3d11_resources.h index 76ca0785a..b8c6f32b8 100644 --- a/renderdoc/driver/d3d11/d3d11_resources.h +++ b/renderdoc/driver/d3d11/d3d11_resources.h @@ -1010,14 +1010,6 @@ public: return *m_Details; } - const ShaderBindpointMapping &GetMapping() - { - if(!m_Built && GetDXBC() != NULL) - BuildReflection(); - m_Built = true; - return m_Mapping; - } - const rdcarray &GetDescriptorAccess() { if(!m_Built && GetDXBC() != NULL) @@ -1042,7 +1034,6 @@ public: bool m_Built = false; DXBC::DXBCContainer *m_DXBCFile; ShaderReflection *m_Details; - ShaderBindpointMapping m_Mapping; rdcarray m_Access; friend class WrappedShader; @@ -1093,11 +1084,6 @@ public: SCOPED_LOCK(m_ShaderListLock); return m_ShaderList[m_ID]->GetDetails(); } - const ShaderBindpointMapping &GetMapping() - { - SCOPED_LOCK(m_ShaderListLock); - return m_ShaderList[m_ID]->GetMapping(); - } const rdcarray &GetDescriptorAccess() { SCOPED_LOCK(m_ShaderListLock); diff --git a/renderdoc/driver/d3d12/d3d12_commands.cpp b/renderdoc/driver/d3d12/d3d12_commands.cpp index ffbe8480d..a187b2c08 100644 --- a/renderdoc/driver/d3d12/d3d12_commands.cpp +++ b/renderdoc/driver/d3d12/d3d12_commands.cpp @@ -1925,17 +1925,16 @@ void D3D12CommandData::AddCPUUsage(ResourceId id, ResourceUsage usage) void D3D12CommandData::AddUsageForBindInRootSig(const D3D12RenderState &state, D3D12ActionTreeNode &actionNode, const D3D12RenderState::RootSignature *rootsig, - D3D12_DESCRIPTOR_RANGE_TYPE type, const Bindpoint &b) + D3D12_DESCRIPTOR_RANGE_TYPE type, uint32_t space, + uint32_t bind, uint32_t rangeSize) { static bool hugeRangeWarned = false; ActionDescription &a = actionNode.action; uint32_t eid = a.eventId; - const uint32_t space = b.bindset; - const uint32_t bind = b.bind; // use a 'clamped' range size to avoid annoying overflow issues - const uint32_t rangeSize = b.arraySize == ~0U ? 0x10000000 : b.arraySize; + rangeSize = RDCMIN(rangeSize, 0x10000000U); D3D12ResourceManager *rm = m_pDevice->GetResourceManager(); @@ -2058,7 +2057,7 @@ void D3D12CommandData::AddUsageForBindInRootSig(const D3D12RenderState &state, continue; } - bool allInRange = (bind >= range.BaseShaderRegister && b.arraySize <= range.NumDescriptors); + bool allInRange = (bind >= range.BaseShaderRegister && rangeSize <= range.NumDescriptors); // move to the first descriptor in the range which is in the binding we want desc += (bind - range.BaseShaderRegister); @@ -2117,7 +2116,7 @@ void D3D12CommandData::AddUsage(const D3D12RenderState &state, D3D12ActionTreeNo if(state.pipe != ResourceId()) pipe = rm->GetCurrentAs(state.pipe); - const ShaderBindpointMapping *bindMap[NumShaderStages] = {}; + const ShaderReflection *refls[NumShaderStages] = {}; if((a.flags & ActionFlags::Dispatch) && state.compute.rootsig != ResourceId()) { @@ -2127,7 +2126,7 @@ void D3D12CommandData::AddUsage(const D3D12RenderState &state, D3D12ActionTreeNo { WrappedID3D12Shader *sh = (WrappedID3D12Shader *)pipe->compute->CS.pShaderBytecode; - bindMap[uint32_t(ShaderStage::Compute)] = &sh->GetMapping(); + refls[uint32_t(ShaderStage::Compute)] = &sh->GetDetails(); } } else if(state.graphics.rootsig != ResourceId()) @@ -2155,7 +2154,7 @@ void D3D12CommandData::AddUsage(const D3D12RenderState &state, D3D12ActionTreeNo WrappedID3D12Shader *sh = (WrappedID3D12Shader *)srcArr[stage]->pShaderBytecode; if(sh) - bindMap[stage] = &sh->GetMapping(); + refls[stage] = &sh->GetDetails(); } } @@ -2204,33 +2203,27 @@ void D3D12CommandData::AddUsage(const D3D12RenderState &state, D3D12ActionTreeNo // signature. We have to do this kind of N:N lookup because of D3D12's bad design, but this // should be a better way around to do it than iterating over the root signature and finding a // bind for each element - for(size_t sh = 0; sh < ARRAY_COUNT(bindMap); sh++) + for(size_t sh = 0; sh < ARRAY_COUNT(refls); sh++) { - if(!bindMap[sh]) + if(!refls[sh]) continue; - for(const Bindpoint &b : bindMap[sh]->constantBlocks) + for(const ConstantBlock &b : refls[sh]->constantBlocks) { - if(!b.used) - continue; - - AddUsageForBindInRootSig(state, actionNode, rootsig, D3D12_DESCRIPTOR_RANGE_TYPE_CBV, b); + AddUsageForBindInRootSig(state, actionNode, rootsig, D3D12_DESCRIPTOR_RANGE_TYPE_CBV, + b.fixedBindSetOrSpace, b.fixedBindNumber, b.bindArraySize); } - for(const Bindpoint &b : bindMap[sh]->readOnlyResources) + for(const ShaderResource &r : refls[sh]->readOnlyResources) { - if(!b.used) - continue; - - AddUsageForBindInRootSig(state, actionNode, rootsig, D3D12_DESCRIPTOR_RANGE_TYPE_SRV, b); + AddUsageForBindInRootSig(state, actionNode, rootsig, D3D12_DESCRIPTOR_RANGE_TYPE_SRV, + r.fixedBindSetOrSpace, r.fixedBindNumber, r.bindArraySize); } - for(const Bindpoint &b : bindMap[sh]->readWriteResources) + for(const ShaderResource &r : refls[sh]->readWriteResources) { - if(!b.used) - continue; - - AddUsageForBindInRootSig(state, actionNode, rootsig, D3D12_DESCRIPTOR_RANGE_TYPE_UAV, b); + AddUsageForBindInRootSig(state, actionNode, rootsig, D3D12_DESCRIPTOR_RANGE_TYPE_UAV, + r.fixedBindSetOrSpace, r.fixedBindNumber, r.bindArraySize); } } } diff --git a/renderdoc/driver/d3d12/d3d12_commands.h b/renderdoc/driver/d3d12/d3d12_commands.h index ccd15c6f8..67bd2aa1c 100644 --- a/renderdoc/driver/d3d12/d3d12_commands.h +++ b/renderdoc/driver/d3d12/d3d12_commands.h @@ -403,7 +403,8 @@ struct D3D12CommandData void AddUsageForBindInRootSig(const D3D12RenderState &state, D3D12ActionTreeNode &actionNode, const D3D12RenderState::RootSignature *rootsig, - D3D12_DESCRIPTOR_RANGE_TYPE type, const Bindpoint &b); + D3D12_DESCRIPTOR_RANGE_TYPE type, uint32_t space, uint32_t bind, + uint32_t rangeSize); void AddResourceUsage(D3D12ActionTreeNode &actionNode, ResourceId id, uint32_t EID, ResourceUsage usage); diff --git a/renderdoc/driver/d3d12/d3d12_replay.cpp b/renderdoc/driver/d3d12/d3d12_replay.cpp index 4fb0a4747..e3c992541 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.cpp +++ b/renderdoc/driver/d3d12/d3d12_replay.cpp @@ -302,7 +302,6 @@ APIProperties D3D12Replay::GetAPIProperties() ret.localRenderer = GraphicsAPI::D3D12; ret.vendor = m_DriverInfo.vendor; ret.degraded = false; - ret.shadersMutable = false; ret.rgpCapture = (m_DriverInfo.vendor == GPUVendor::AMD || m_DriverInfo.vendor == GPUVendor::Samsung) && m_RGP != NULL && m_RGP->DriverSupportsInterop(); @@ -1006,29 +1005,6 @@ void D3D12Replay::FillResourceView(D3D12Pipe::View &view, const D3D12Descriptor desc->GetHeap()->SetToViewCache(desc->GetHeapIndex(), view); } -void D3D12Replay::FillSampler(D3D12Pipe::Sampler &samp, const D3D12_SAMPLER_DESC2 &sampDesc) -{ - samp.addressU = MakeAddressMode(sampDesc.AddressU); - samp.addressV = MakeAddressMode(sampDesc.AddressV); - samp.addressW = MakeAddressMode(sampDesc.AddressW); - - samp.borderColorValue.uintValue = sampDesc.UintBorderColor; - samp.borderColorType = - ((sampDesc.Flags & D3D12_SAMPLER_FLAG_UINT_BORDER_COLOR) != 0 ? CompType::UInt - : CompType::Float); - - samp.unnormalized = (sampDesc.Flags & D3D12_SAMPLER_FLAG_NON_NORMALIZED_COORDINATES) != 0; - - samp.compareFunction = MakeCompareFunc(sampDesc.ComparisonFunc); - samp.filter = MakeFilter(sampDesc.Filter); - samp.maxAnisotropy = 0; - if(samp.filter.minify == FilterMode::Anisotropic) - samp.maxAnisotropy = sampDesc.MaxAnisotropy; - samp.maxLOD = sampDesc.MaxLOD; - samp.minLOD = sampDesc.MinLOD; - samp.mipLODBias = sampDesc.MipLODBias; -} - void D3D12Replay::FillDescriptor(Descriptor &dst, const D3D12Descriptor *src) { D3D12ResourceManager *rm = m_pDevice->GetResourceManager(); @@ -1303,608 +1279,6 @@ ShaderStageMask ToShaderStageMask(D3D12_SHADER_VISIBILITY vis) } } -void D3D12Replay::FillRootElements(uint32_t eventId, const D3D12RenderState::RootSignature &rootSig, - const ShaderBindpointMapping *mappings[NumShaderStages], - rdcarray &rootElements) -{ - if(rootSig.rootsig == ResourceId()) - return; - - D3D12ResourceManager *rm = m_pDevice->GetResourceManager(); - - const D3D12DynamicShaderFeedback &usage = m_BindlessFeedback.Usage[eventId]; - - const D3D12FeedbackBindIdentifier *curUsage = usage.used.begin(); - const D3D12FeedbackBindIdentifier *lastUsage = usage.used.end(); - D3D12FeedbackBindIdentifier curIdentifier = {}; - - WrappedID3D12RootSignature *sig = - m_pDevice->GetResourceManager()->GetCurrentAs(rootSig.rootsig); - - size_t numReserve = sig->sig.Parameters.size() + sig->sig.StaticSamplers.size(); - - for(size_t rootEl = 0; rootEl < sig->sig.Parameters.size(); rootEl++) - if(sig->sig.Parameters[rootEl].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE) - numReserve += sig->sig.Parameters[rootEl].ranges.size(); - - rootElements.reserve(numReserve); - - size_t ridx = 0; - - for(size_t rootEl = 0; rootEl < sig->sig.Parameters.size(); rootEl++) - { - curIdentifier.rootEl = rootEl; - - const D3D12RootSignatureParameter &p = sig->sig.Parameters[rootEl]; - - if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS) - { - rootElements.resize_for_index(ridx); - D3D12Pipe::RootSignatureRange &element = rootElements[ridx++]; - element.immediate = true; - element.rootSignatureIndex = (uint32_t)rootEl; - element.type = BindType::ConstantBuffer; - element.registerSpace = p.Constants.RegisterSpace; - element.visibility = ToShaderStageMask(p.ShaderVisibility); - - element.samplers.clear(); - element.constantBuffers.clear(); - element.views.clear(); - - element.constantBuffers.push_back(D3D12Pipe::ConstantBuffer(p.Constants.ShaderRegister)); - D3D12Pipe::ConstantBuffer &cb = element.constantBuffers.back(); - cb.resourceId = ResourceId(); - cb.byteOffset = 0; - cb.byteSize = uint32_t(sizeof(uint32_t) * p.Constants.Num32BitValues); - - if(rootEl < rootSig.sigelems.size()) - { - const D3D12RenderState::SignatureElement &e = rootSig.sigelems[rootEl]; - if(e.type == eRootConst) - cb.rootValues.assign(e.constants.data(), - RDCMIN(e.constants.size(), (size_t)p.Constants.Num32BitValues)); - } - - if(cb.rootValues.empty()) - cb.rootValues.resize(p.Constants.Num32BitValues); - } - else if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV) - { - rootElements.resize_for_index(ridx); - D3D12Pipe::RootSignatureRange &element = rootElements[ridx++]; - element.immediate = true; - element.rootSignatureIndex = (uint32_t)rootEl; - element.type = BindType::ConstantBuffer; - element.registerSpace = p.Descriptor.RegisterSpace; - element.visibility = ToShaderStageMask(p.ShaderVisibility); - - element.samplers.clear(); - element.constantBuffers.clear(); - element.views.clear(); - - element.constantBuffers.push_back(D3D12Pipe::ConstantBuffer(p.Descriptor.ShaderRegister)); - D3D12Pipe::ConstantBuffer &cb = element.constantBuffers.back(); - - if(rootEl < rootSig.sigelems.size()) - { - const D3D12RenderState::SignatureElement &e = rootSig.sigelems[rootEl]; - if(e.type == eRootCBV) - { - ID3D12Resource *res = rm->GetCurrentAs(e.id); - - cb.resourceId = rm->GetOriginalID(e.id); - cb.byteOffset = e.offset; - if(res) - cb.byteSize = uint32_t(res->GetDesc().Width - cb.byteOffset); - else - cb.byteSize = 0; - } - } - } - else if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV) - { - rootElements.resize_for_index(ridx); - D3D12Pipe::RootSignatureRange &element = rootElements[ridx++]; - element.immediate = true; - element.rootSignatureIndex = (uint32_t)rootEl; - element.type = BindType::ReadOnlyResource; - element.registerSpace = p.Descriptor.RegisterSpace; - element.visibility = ToShaderStageMask(p.ShaderVisibility); - - element.samplers.clear(); - element.constantBuffers.clear(); - element.views.clear(); - - element.views.push_back(D3D12Pipe::View(p.Descriptor.ShaderRegister)); - D3D12Pipe::View &view = element.views.back(); - - view.dynamicallyUsed = true; - - if(rootEl < rootSig.sigelems.size()) - { - const D3D12RenderState::SignatureElement &e = rootSig.sigelems[rootEl]; - if(e.type == eRootSRV) - { - ID3D12Resource *res = rm->GetCurrentAs(e.id); - - // parameters from resource/view - view.resourceId = rm->GetOriginalID(e.id); - view.type = TextureType::Buffer; - view.viewFormat = MakeResourceFormat(DXGI_FORMAT_R32_UINT); - - view.elementByteSize = sizeof(uint32_t); - view.firstElement = e.offset / sizeof(uint32_t); - if(res) - view.numElements = uint32_t((res->GetDesc().Width - e.offset) / sizeof(uint32_t)); - else - view.numElements = 0; - } - } - } - else if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV) - { - rootElements.resize_for_index(ridx); - D3D12Pipe::RootSignatureRange &element = rootElements[ridx++]; - element.immediate = true; - element.rootSignatureIndex = (uint32_t)rootEl; - element.type = BindType::ReadWriteResource; - element.registerSpace = p.Descriptor.RegisterSpace; - element.visibility = ToShaderStageMask(p.ShaderVisibility); - - element.samplers.clear(); - element.constantBuffers.clear(); - element.views.clear(); - - element.views.push_back(D3D12Pipe::View(p.Descriptor.ShaderRegister)); - D3D12Pipe::View &view = element.views.back(); - - view.dynamicallyUsed = true; - - if(rootEl < rootSig.sigelems.size()) - { - const D3D12RenderState::SignatureElement &e = rootSig.sigelems[rootEl]; - if(e.type == eRootUAV) - { - ID3D12Resource *res = rm->GetCurrentAs(e.id); - - // parameters from resource/view - view.resourceId = rm->GetOriginalID(e.id); - view.type = TextureType::Buffer; - view.viewFormat = MakeResourceFormat(DXGI_FORMAT_R32_UINT); - - view.elementByteSize = sizeof(uint32_t); - view.firstElement = e.offset / sizeof(uint32_t); - if(res) - view.numElements = uint32_t((res->GetDesc().Width - e.offset) / sizeof(uint32_t)); - else - view.numElements = 0; - } - } - } - else if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE) - { - const D3D12RenderState::SignatureElement *e = NULL; - WrappedID3D12DescriptorHeap *heap = NULL; - - if(rootEl < rootSig.sigelems.size() && rootSig.sigelems[rootEl].type == eRootTable) - { - e = &rootSig.sigelems[rootEl]; - - heap = rm->GetCurrentAs(e->id); - } - - UINT prevTableOffset = 0; - - for(size_t r = 0; r < p.ranges.size(); r++) - { - const D3D12_DESCRIPTOR_RANGE1 &range = p.ranges[r]; - - curIdentifier.rangeIndex = r; - - // Here we diverge slightly from how root signatures store data. A descriptor table can - // contain multiple ranges which can each contain different types. D3D12Pipe treats - // each range as a separate RootElement - rootElements.resize_for_index(ridx); - D3D12Pipe::RootSignatureRange &element = rootElements[ridx++]; - - element.immediate = false; - element.rootSignatureIndex = (uint32_t)rootEl; - element.registerSpace = range.RegisterSpace; - element.visibility = ToShaderStageMask(p.ShaderVisibility); - - element.samplers.clear(); - element.constantBuffers.clear(); - element.views.clear(); - - UINT shaderReg = range.BaseShaderRegister; - - D3D12Descriptor *desc = NULL; - - UINT offset = range.OffsetInDescriptorsFromTableStart; - - if(range.OffsetInDescriptorsFromTableStart == D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) - offset = prevTableOffset; - - UINT num = range.NumDescriptors; - - if(heap) - { - desc = (D3D12Descriptor *)heap->GetCPUDescriptorHandleForHeapStart().ptr; - const D3D12Descriptor *endDesc = desc + heap->GetNumDescriptors(); - desc += e->offset; - desc += offset; - - if(desc >= endDesc) - { - RDCERR("Binding points past end of corresponding heap."); - num = 0; - } - else if(desc + num >= endDesc) - { - const UINT availDescriptors = UINT(endDesc - desc); - - const Bindpoint *highestBind = NULL; - UINT maxBindReg = shaderReg + availDescriptors; - - // Find shader binds that map any or all of this range to see if we can trim it - for(ShaderStage stage = ShaderStage::Vertex; stage < ShaderStage::Count; ++stage) - { - const ShaderBindpointMapping *mapping = mappings[(uint32_t)stage]; - if((element.visibility & MaskForStage(stage)) != ShaderStageMask::Unknown) - { - // This range is visible to this shader stage, check its mappings - const rdcarray &bps = range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV - ? mapping->readWriteResources - : mapping->readOnlyResources; - for(size_t b = 0; b < bps.size(); ++b) - { - if(bps[b].bindset == (int32_t)element.registerSpace && - bps[b].bind >= (int32_t)shaderReg) - { - UINT bindEnd = bps[b].arraySize == ~0U ? ~0U : bps[b].bind + bps[b].arraySize; - if(highestBind == NULL || bindEnd > maxBindReg) - { - highestBind = &bps[b]; - maxBindReg = bindEnd; - } - } - } - } - } - - // If we didn't find a bindpoint, this will evaluate to simply availDescriptors - the - // number of remaining entries in the heap. If we did find a bind in this range, it - // will trim to the max register used by bindings in the range. - num = RDCMIN(availDescriptors, maxBindReg - shaderReg); - } - } - else if(num == UINT_MAX) - { - RDCWARN( - "Heap not available on replay with unbounded descriptor range, clamping to 1 " - "descriptor."); - num = 1; - } - - prevTableOffset = offset + num; - - if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER) - { - element.type = BindType::Sampler; - - element.samplers.reserve(num); - - for(UINT i = 0; i < num; i++, shaderReg++) - { - element.samplers.push_back(D3D12Pipe::Sampler(shaderReg)); - D3D12Pipe::Sampler &samp = element.samplers.back(); - samp.tableIndex = offset + i; - - if(desc) - { - const D3D12_SAMPLER_DESC2 &sampDesc = desc->GetSampler(); - FillSampler(samp, sampDesc); - desc++; - } - } - } - else if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_CBV) - { - element.type = BindType::ConstantBuffer; - - element.constantBuffers.reserve(num); - - for(UINT i = 0; i < num; i++, shaderReg++) - { - element.constantBuffers.push_back(D3D12Pipe::ConstantBuffer(shaderReg)); - D3D12Pipe::ConstantBuffer &cb = element.constantBuffers.back(); - cb.tableIndex = offset + i; - - if(desc) - { - const D3D12_CONSTANT_BUFFER_VIEW_DESC &cbv = desc->GetCBV(); - WrappedID3D12Resource::GetResIDFromAddr(cbv.BufferLocation, cb.resourceId, - cb.byteOffset); - cb.resourceId = rm->GetOriginalID(cb.resourceId); - cb.byteSize = cbv.SizeInBytes; - - desc++; - } - } - } - else if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV || - range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV) - { - if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV) - element.type = BindType::ReadOnlyResource; - else - element.type = BindType::ReadWriteResource; - - element.firstUsedIndex = -1; - element.lastUsedIndex = -1; - element.dynamicallyUsedCount = 0; - - element.views.reserve(num); - - for(UINT i = 0; i < num; i++, shaderReg++) - { - element.views.push_back(D3D12Pipe::View(shaderReg)); - D3D12Pipe::View &view = element.views.back(); - view.tableIndex = offset + i; - - if(usage.valid) - { - curIdentifier.descIndex = i; - - // if the usage data is valid we expect entries for all descriptors that are used. - // Note that because of the messed up root signature/binding split, some of these - // entries will just be statically inserted and not actually from dynamic feedback - // - // usage data is only valid when at least one array exists to have feedback - if(curUsage >= lastUsage) - { - // if we exhausted the list, all other elements are unused - view.dynamicallyUsed = false; - } - else - { - // we never saw the current value of curUsage (which is odd, we should have - // when iterating over all descriptors. This could only happen if there's some - // layout mismatch or a feedback bug that lead to an invalid entry in the list). - // Keep advancing until we get to one that is >= our current bind - while(*curUsage < curIdentifier && curUsage < lastUsage) - { - curUsage++; - } - - // the next used bind is equal to this one. Mark it as dynamically used, and consume - if(curUsage < lastUsage && *curUsage == curIdentifier) - { - view.dynamicallyUsed = true; - curUsage++; - } - // the next used bind is after the current one, this is not used. - else if(curUsage < lastUsage && curIdentifier < *curUsage) - { - view.dynamicallyUsed = false; - } - } - } - else - { - view.dynamicallyUsed = true; - } - - if(view.dynamicallyUsed) - { - element.dynamicallyUsedCount++; - // we iterate in forward order, so we can unconditinoally set the last bind to the - // current one, and only set the first bind if we haven't encountered one before - element.lastUsedIndex = i; - - if(element.firstUsedIndex < 0) - element.firstUsedIndex = i; - } - - if(desc) - { - FillResourceView(view, desc); - desc++; - } - } - - // if no bindings were set these will still be negative. Set them to something sensible. - if(element.firstUsedIndex < 0) - { - element.firstUsedIndex = 0; - element.lastUsedIndex = 0x7fffffff; - } - } - } - } - } - - // direct heap access resources - { - D3D12RenderState &rs = m_pDevice->GetQueue()->GetCommandData()->m_RenderState; - WrappedID3D12DescriptorHeap *resourceHeap = NULL; - WrappedID3D12DescriptorHeap *samplerHeap = NULL; - for(ResourceId id : rs.heaps) - { - WrappedID3D12DescriptorHeap *heap = - (WrappedID3D12DescriptorHeap *)rm->GetCurrentAs(id); - D3D12_DESCRIPTOR_HEAP_DESC desc = heap->GetDesc(); - if(desc.Type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) - resourceHeap = heap; - else - samplerHeap = heap; - } - - D3D12Pipe::RootSignatureRange *element = NULL; - while(curUsage < lastUsage && curUsage->directAccess) - { - ShaderStageMask visibility = (ShaderStageMask)(1 << (int)curUsage->shaderStage); - if(element == NULL || (element->visibility != visibility) || - (element->type != curUsage->bindType)) - { - rootElements.resize_for_index(ridx); - element = &rootElements[ridx++]; - element->immediate = false; - element->rootSignatureIndex = ~0U; - element->type = curUsage->bindType; - element->visibility = visibility; - element->registerSpace = ~0U; - element->dynamicallyUsedCount = 0; - element->samplers.clear(); - element->constantBuffers.clear(); - element->views.clear(); - } - if(curUsage->bindType == BindType::Sampler) - { - if(samplerHeap) - { - D3D12Descriptor *desc = - (D3D12Descriptor *)samplerHeap->GetCPUDescriptorHandleForHeapStart().ptr; - desc += curUsage->descIndex; - element->samplers.push_back(D3D12Pipe::Sampler()); - D3D12Pipe::Sampler &samp = element->samplers.back(); - const D3D12_SAMPLER_DESC2 &sampDesc = desc->GetSampler(); - FillSampler(samp, sampDesc); - samp.tableIndex = curUsage->descIndex; - element->dynamicallyUsedCount++; - } - else - { - RDCERR("Access to sampler heap detected with no sampler heap bound"); - } - } - else if(curUsage->bindType == BindType::ConstantBuffer) - { - if(resourceHeap) - { - D3D12Descriptor *desc = - (D3D12Descriptor *)resourceHeap->GetCPUDescriptorHandleForHeapStart().ptr; - desc += curUsage->descIndex; - element->constantBuffers.push_back(D3D12Pipe::ConstantBuffer()); - D3D12Pipe::ConstantBuffer &cb = element->constantBuffers.back(); - - const D3D12_CONSTANT_BUFFER_VIEW_DESC &cbv = desc->GetCBV(); - WrappedID3D12Resource::GetResIDFromAddr(cbv.BufferLocation, cb.resourceId, cb.byteOffset); - cb.resourceId = rm->GetOriginalID(cb.resourceId); - cb.byteSize = cbv.SizeInBytes; - cb.tableIndex = curUsage->descIndex; - element->dynamicallyUsedCount++; - } - else - { - RDCERR("Access to resource heap detected with no resource heap bound"); - } - } - else - { - if(resourceHeap) - { - D3D12Descriptor *desc = - (D3D12Descriptor *)resourceHeap->GetCPUDescriptorHandleForHeapStart().ptr; - desc += curUsage->descIndex; - D3D12Pipe::View view; - FillResourceView(view, desc); - view.tableIndex = curUsage->descIndex; - element->views.push_back(view); - element->dynamicallyUsedCount++; - } - else - { - RDCERR("Access to resource heap detected with no resource heap bound"); - } - } - curUsage++; - } - } - - // Each static sampler gets its own RootElement - for(size_t i = 0; i < sig->sig.StaticSamplers.size(); i++) - { - D3D12_STATIC_SAMPLER_DESC1 &sampDesc = sig->sig.StaticSamplers[i]; - - rootElements.resize_for_index(ridx); - D3D12Pipe::RootSignatureRange &element = rootElements[ridx++]; - element.immediate = true; - element.rootSignatureIndex = (uint32_t)i; - element.type = BindType::Sampler; - element.registerSpace = sampDesc.RegisterSpace; - element.visibility = ToShaderStageMask(sampDesc.ShaderVisibility); - - element.samplers.clear(); - element.constantBuffers.clear(); - element.views.clear(); - - element.samplers.push_back(D3D12Pipe::Sampler(sampDesc.ShaderRegister)); - D3D12Pipe::Sampler &samp = element.samplers[0]; - - samp.addressU = MakeAddressMode(sampDesc.AddressU); - samp.addressV = MakeAddressMode(sampDesc.AddressV); - samp.addressW = MakeAddressMode(sampDesc.AddressW); - - samp.borderColorType = CompType::Float; - - if(sampDesc.BorderColor == D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK) - { - samp.borderColorValue.floatValue[0] = 0.0f; - samp.borderColorValue.floatValue[1] = 0.0f; - samp.borderColorValue.floatValue[2] = 0.0f; - samp.borderColorValue.floatValue[3] = 0.0f; - } - else if(sampDesc.BorderColor == D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK) - { - samp.borderColorValue.floatValue[0] = 0.0f; - samp.borderColorValue.floatValue[1] = 0.0f; - samp.borderColorValue.floatValue[2] = 0.0f; - samp.borderColorValue.floatValue[3] = 1.0f; - } - else if(sampDesc.BorderColor == D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE) - { - samp.borderColorValue.floatValue[0] = 1.0f; - samp.borderColorValue.floatValue[1] = 1.0f; - samp.borderColorValue.floatValue[2] = 1.0f; - samp.borderColorValue.floatValue[3] = 1.0f; - } - else if(sampDesc.BorderColor == D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK_UINT) - { - samp.borderColorValue.uintValue[0] = 0; - samp.borderColorValue.uintValue[1] = 0; - samp.borderColorValue.uintValue[2] = 0; - samp.borderColorValue.uintValue[3] = 1; - samp.borderColorType = CompType::UInt; - } - else if(sampDesc.BorderColor == D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE_UINT) - { - samp.borderColorValue.uintValue[0] = 1; - samp.borderColorValue.uintValue[1] = 1; - samp.borderColorValue.uintValue[2] = 1; - samp.borderColorValue.uintValue[3] = 1; - samp.borderColorType = CompType::UInt; - } - else - { - RDCERR("Unexpected static border colour: %u", sampDesc.BorderColor); - } - - samp.unnormalized = (sampDesc.Flags & D3D12_SAMPLER_FLAG_NON_NORMALIZED_COORDINATES) != 0; - - samp.compareFunction = MakeCompareFunc(sampDesc.ComparisonFunc); - samp.filter = MakeFilter(sampDesc.Filter); - samp.maxAnisotropy = 0; - if(samp.filter.minify == FilterMode::Anisotropic) - samp.maxAnisotropy = sampDesc.MaxAnisotropy; - samp.maxLOD = sampDesc.MaxLOD; - samp.minLOD = sampDesc.MinLOD; - samp.mipLODBias = sampDesc.MipLODBias; - } - - rootElements.resize(ridx); -} - void D3D12Replay::SavePipelineState(uint32_t eventId) { if(!m_D3D12PipelineState) @@ -1995,7 +1369,6 @@ void D3D12Replay::SavePipelineState(uint32_t eventId) state.computeShader.resourceId = rm->GetUnreplacedOriginalID(sh->GetResourceID()); state.computeShader.stage = ShaderStage::Compute; state.computeShader.reflection = &sh->GetDetails(); - state.computeShader.bindpointMapping = sh->GetMapping(); } else if(pipe) { @@ -2038,13 +1411,11 @@ void D3D12Replay::SavePipelineState(uint32_t eventId) if(sh) { dst.resourceId = rm->GetUnreplacedOriginalID(sh->GetResourceID()); - dst.bindpointMapping = sh->GetMapping(); dst.reflection = &sh->GetDetails(); } else { dst.resourceId = ResourceId(); - dst.bindpointMapping = ShaderBindpointMapping(); dst.reflection = NULL; } } @@ -2054,26 +1425,10 @@ void D3D12Replay::SavePipelineState(uint32_t eventId) // Root Signature ///////////////////////////////////////////////// { - const ShaderBindpointMapping *mappings[NumShaderStages]; - mappings[(uint32_t)ShaderStage::Vertex] = &state.vertexShader.bindpointMapping; - mappings[(uint32_t)ShaderStage::Hull] = &state.hullShader.bindpointMapping; - mappings[(uint32_t)ShaderStage::Domain] = &state.domainShader.bindpointMapping; - mappings[(uint32_t)ShaderStage::Geometry] = &state.geometryShader.bindpointMapping; - mappings[(uint32_t)ShaderStage::Pixel] = &state.pixelShader.bindpointMapping; - mappings[(uint32_t)ShaderStage::Compute] = &state.computeShader.bindpointMapping; - mappings[(uint32_t)ShaderStage::Amplification] = &state.ampShader.bindpointMapping; - mappings[(uint32_t)ShaderStage::Mesh] = &state.meshShader.bindpointMapping; - if(pipe && pipe->IsCompute()) - { - FillRootElements(eventId, rs.compute, mappings, state.rootElements); state.rootSignatureResourceId = rm->GetOriginalID(rs.compute.rootsig); - } else if(pipe) - { - FillRootElements(eventId, rs.graphics, mappings, state.rootElements); state.rootSignatureResourceId = rm->GetOriginalID(rs.graphics.rootsig); - } } state.descriptorHeaps.clear(); @@ -2481,7 +1836,6 @@ rdcarray D3D12Replay::GetDescriptors(ResourceId descriptorStore, } else if(desc->GetType() != D3D12DescriptorType::Sampler) { - D3D12Pipe::View view; FillDescriptor(ret[dst], desc); } dst++; @@ -4063,16 +3417,14 @@ void D3D12Replay::FillCBufferVariables(ResourceId pipeline, ResourceId shader, S WrappedID3D12Shader *sh = (WrappedID3D12Shader *)res; const ShaderReflection &refl = sh->GetDetails(); - const ShaderBindpointMapping &mapping = sh->GetMapping(); - if(cbufSlot >= (uint32_t)mapping.constantBlocks.count()) + if(cbufSlot >= (uint32_t)refl.constantBlocks.count()) { RDCERR("Invalid cbuffer slot"); return; } const ConstantBlock &c = refl.constantBlocks[cbufSlot]; - const Bindpoint &bind = mapping.constantBlocks[c.bindPoint]; // check if the data actually comes from root constants const D3D12RenderState &rs = m_pDevice->GetQueue()->GetCommandData()->m_RenderState; @@ -4103,8 +3455,8 @@ void D3D12Replay::FillCBufferVariables(ResourceId pipeline, ResourceId shader, S if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS && (ToShaderStageMask(p.ShaderVisibility) & reflMask) && - p.Constants.RegisterSpace == (UINT)bind.bindset && - p.Constants.ShaderRegister == (UINT)bind.bind) + p.Constants.RegisterSpace == c.fixedBindSetOrSpace && + p.Constants.ShaderRegister == c.fixedBindNumber) { size_t dstSize = sig->sig.Parameters[i].Constants.Num32BitValues * sizeof(uint32_t); rootData.resize(dstSize); diff --git a/renderdoc/driver/d3d12/d3d12_replay.h b/renderdoc/driver/d3d12/d3d12_replay.h index 57aba4136..6cd9ff30d 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.h +++ b/renderdoc/driver/d3d12/d3d12_replay.h @@ -268,11 +268,7 @@ public: bool dxil); private: - void FillRootElements(uint32_t eventId, const D3D12RenderState::RootSignature &rootSig, - const ShaderBindpointMapping *mappings[NumShaderStages], - rdcarray &rootElements); void FillResourceView(D3D12Pipe::View &view, const D3D12Descriptor *desc); - void FillSampler(D3D12Pipe::Sampler &view, const D3D12_SAMPLER_DESC2 &desc); void FillDescriptor(Descriptor &dst, const D3D12Descriptor *src); void FillSamplerDescriptor(SamplerDescriptor &dst, const D3D12_SAMPLER_DESC2 &src); @@ -300,7 +296,6 @@ private: struct D3D12DynamicShaderFeedback { bool compute = false, valid = false; - rdcarray used; rdcarray access; }; diff --git a/renderdoc/driver/d3d12/d3d12_resources.cpp b/renderdoc/driver/d3d12/d3d12_resources.cpp index 2d50217ba..029eaf092 100644 --- a/renderdoc/driver/d3d12/d3d12_resources.cpp +++ b/renderdoc/driver/d3d12/d3d12_resources.cpp @@ -657,7 +657,7 @@ void WrappedID3D12PipelineState::ShaderEntry::BuildReflection() 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); + MakeShaderReflection(m_DXBCFile, m_Details); m_Details->resourceId = GetResourceID(); } @@ -749,7 +749,6 @@ void WrappedID3D12PipelineState::ProcessDescriptorAccess() continue; const ShaderReflection &refl = shad->GetDetails(); - const ShaderBindpointMapping &mapping = shad->GetMapping(); D3D12_SHADER_VISIBILITY visibility; switch(refl.stage) @@ -770,85 +769,81 @@ void WrappedID3D12PipelineState::ProcessDescriptorAccess() // we will store the root signature element in byteSize to be decoded into descriptorStore later access.byteSize = 0; - staticDescriptorAccess.reserve(staticDescriptorAccess.size() + mapping.constantBlocks.size() + - mapping.samplers.size() + mapping.readOnlyResources.size() + - mapping.readWriteResources.size()); + staticDescriptorAccess.reserve(staticDescriptorAccess.size() + refl.constantBlocks.size() + + refl.samplers.size() + refl.readOnlyResources.size() + + refl.readWriteResources.size()); - RDCASSERT(mapping.constantBlocks.size() < 0xffff, mapping.constantBlocks.size()); - for(uint16_t i = 0; i < mapping.constantBlocks.size(); i++) + RDCASSERT(refl.constantBlocks.size() < 0xffff, refl.constantBlocks.size()); + for(uint16_t i = 0; i < refl.constantBlocks.size(); i++) { - const Bindpoint &bind = mapping.constantBlocks[i]; + const ConstantBlock &bind = refl.constantBlocks[i]; // arrayed descriptors will be handled with bindless feedback - if(bind.arraySize > 1) + if(bind.bindArraySize > 1) continue; - access.staticallyUnused = !bind.used; access.type = DescriptorType::ConstantBuffer; access.index = i; rdctie(access.byteSize, access.byteOffset) = FindMatchingRootParameter(sig, visibility, D3D12_DESCRIPTOR_RANGE_TYPE_CBV, - (uint32_t)bind.bindset, (uint32_t)bind.bind); + bind.fixedBindSetOrSpace, bind.fixedBindNumber); if(access.byteSize != ~0U) staticDescriptorAccess.push_back(access); } - RDCASSERT(mapping.samplers.size() < 0xffff, mapping.samplers.size()); - for(uint16_t i = 0; i < mapping.samplers.size(); i++) + RDCASSERT(refl.samplers.size() < 0xffff, refl.samplers.size()); + for(uint16_t i = 0; i < refl.samplers.size(); i++) { - const Bindpoint &bind = mapping.samplers[i]; + const ShaderSampler &bind = refl.samplers[i]; // arrayed descriptors will be handled with bindless feedback - if(bind.arraySize > 1) + if(bind.bindArraySize > 1) continue; - access.staticallyUnused = !bind.used; access.type = DescriptorType::Sampler; access.index = i; rdctie(access.byteSize, access.byteOffset) = FindMatchingRootParameter(sig, visibility, D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, - (uint32_t)bind.bindset, (uint32_t)bind.bind); + bind.fixedBindSetOrSpace, bind.fixedBindNumber); if(access.byteSize != ~0U) staticDescriptorAccess.push_back(access); } - RDCASSERT(mapping.readOnlyResources.size() < 0xffff, mapping.readOnlyResources.size()); - for(uint16_t i = 0; i < mapping.readOnlyResources.size(); i++) + RDCASSERT(refl.readOnlyResources.size() < 0xffff, refl.readOnlyResources.size()); + for(uint16_t i = 0; i < refl.readOnlyResources.size(); i++) { - const Bindpoint &bind = mapping.readOnlyResources[i]; + const ShaderResource &bind = refl.readOnlyResources[i]; // arrayed descriptors will be handled with bindless feedback - if(bind.arraySize > 1) + if(bind.bindArraySize > 1) continue; - access.staticallyUnused = !bind.used; access.type = refl.readOnlyResources[i].descriptorType; access.index = i; rdctie(access.byteSize, access.byteOffset) = FindMatchingRootParameter(sig, visibility, D3D12_DESCRIPTOR_RANGE_TYPE_SRV, - (uint32_t)bind.bindset, (uint32_t)bind.bind); + bind.fixedBindSetOrSpace, bind.fixedBindNumber); if(access.byteSize != ~0U) staticDescriptorAccess.push_back(access); } - RDCASSERT(mapping.readWriteResources.size() < 0xffff, mapping.readWriteResources.size()); - for(uint16_t i = 0; i < mapping.readWriteResources.size(); i++) + RDCASSERT(refl.readWriteResources.size() < 0xffff, refl.readWriteResources.size()); + for(uint16_t i = 0; i < refl.readWriteResources.size(); i++) { - const Bindpoint &bind = mapping.readWriteResources[i]; + const ShaderResource &bind = refl.readWriteResources[i]; // arrayed descriptors will be handled with bindless feedback - if(bind.arraySize > 1) + if(bind.bindArraySize > 1) continue; - access.staticallyUnused = !bind.used; access.type = refl.readWriteResources[i].descriptorType; access.index = i; rdctie(access.byteSize, access.byteOffset) = FindMatchingRootParameter(sig, visibility, D3D12_DESCRIPTOR_RANGE_TYPE_UAV, - (uint32_t)bind.bindset, (uint32_t)bind.bind); + bind.fixedBindSetOrSpace, bind.fixedBindNumber); if(access.byteSize != ~0U) staticDescriptorAccess.push_back(access); diff --git a/renderdoc/driver/d3d12/d3d12_resources.h b/renderdoc/driver/d3d12/d3d12_resources.h index e45874c01..76c0bfbd6 100644 --- a/renderdoc/driver/d3d12/d3d12_resources.h +++ b/renderdoc/driver/d3d12/d3d12_resources.h @@ -837,14 +837,6 @@ public: return *m_Details; } - const ShaderBindpointMapping &GetMapping() - { - if(!m_Built && GetDXBC() != NULL) - BuildReflection(); - m_Built = true; - return m_Mapping; - } - private: void TryReplaceOriginalByteCode(); @@ -858,7 +850,6 @@ public: bool m_Built; DXBC::DXBCContainer *m_DXBCFile; ShaderReflection *m_Details; - ShaderBindpointMapping m_Mapping; static std::map m_Shaders; }; diff --git a/renderdoc/driver/d3d12/d3d12_shader_feedback.cpp b/renderdoc/driver/d3d12/d3d12_shader_feedback.cpp index 8def11227..0a7800f70 100644 --- a/renderdoc/driver/d3d12/d3d12_shader_feedback.cpp +++ b/renderdoc/driver/d3d12/d3d12_shader_feedback.cpp @@ -65,23 +65,9 @@ struct D3D12FeedbackKey struct D3D12FeedbackSlot { -public: - D3D12FeedbackSlot() - { - slot = 0; - used = 0; - } - void SetSlot(uint32_t s) { slot = s; } - void SetStaticUsed() { used = 0x1; } - bool StaticUsed() const { return used != 0x0; } - uint32_t Slot() const { return slot; } - - uint32_t numDescriptors = 1; - DescriptorAccess access; -private: - uint32_t slot : 31; - uint32_t used : 1; + uint32_t slot = 0; + uint32_t numDescriptors = 1; }; static const uint32_t numReservedSlots = 4; @@ -194,7 +180,7 @@ static bool AnnotateDXBCShader(const DXBC::DXBCContainer *dxbc, uint32_t space, editor.InsertOperation(i++, oper(OPCODE_UMIN, {temp(t).swizzle(0), imm(maxSlot), idx})); // resource base plus index editor.InsertOperation( - i++, oper(OPCODE_IADD, {temp(t).swizzle(0), temp(t).swizzle(0), imm(it->second.Slot())})); + i++, oper(OPCODE_IADD, {temp(t).swizzle(0), temp(t).swizzle(0), imm(it->second.slot)})); // multiply by 4 for byte index editor.InsertOperation(i++, oper(OPCODE_ISHL, {temp(t).swizzle(0), temp(t).swizzle(0), imm(2)})); @@ -334,11 +320,7 @@ static bool AnnotateDXILShader(const DXBC::DXBCContainer *dxbc, uint32_t space, if(it == slots.end()) continue; - // static used i.e. not arrayed? ignore - if(it->second.StaticUsed()) - continue; - - uint32_t feedbackSlot = it->second.Slot(); + uint32_t feedbackSlot = it->second.slot; // we assume all feedback slots are non-zero, so that a 0 base slot can be used as an // identifier for 'this resource isn't annotated' @@ -393,11 +375,7 @@ static bool AnnotateDXILShader(const DXBC::DXBCContainer *dxbc, uint32_t space, if(it == slots.end()) continue; - // static used i.e. not arrayed? ignore - if(it->second.StaticUsed()) - continue; - - uint32_t feedbackSlot = it->second.Slot(); + uint32_t feedbackSlot = it->second.slot; // we assume all feedback slots are non-zero, so that a 0 base slot can be used as an // identifier for 'this resource isn't annotated' @@ -692,10 +670,8 @@ static bool AnnotateDXILShader(const DXBC::DXBCContainer *dxbc, uint32_t space, // not annotated if(it == slots.end()) continue; - // static used i.e. not arrayed? ignore - if(it->second.StaticUsed()) - continue; - slotInfo = {it->second.Slot(), key.bind}; + + slotInfo = {it->second.slot, key.bind}; } if(slotInfo.first == 0) continue; @@ -870,7 +846,7 @@ static bool AnnotateDXILShader(const DXBC::DXBCContainer *dxbc, uint32_t space, // idx to the createHandleFromHeap op idxArg, // base slot - editor.CreateConstant(it->second.Slot()), + editor.CreateConstant(it->second.slot), })); // slotPlusBaseClamped = min(slotPlusBase, maxSlot) @@ -952,27 +928,12 @@ static bool AddArraySlots(WrappedID3D12PipelineState::ShaderEntry *shad, uint32_ // descriptor storage side will be calculated later when finalising this with the root // signature information. - slots[key].SetSlot(numSlots); slots[key].numDescriptors = RDCMIN(maxDescriptors, ro.bindArraySize); slots[key].access = access; + slots[key].slot = numSlots; numSlots += slots[key].numDescriptors; dynamicUsed = true; } - else if(ro.bindArraySize <= 1) - { - // since the eventual descriptor range iteration won't know which descriptors map to arrays - // and which to fixed slots, it can't mark fixed descriptors as dynamically used itself. So - // instead we don't reserve a slot and set the top bit for these binds to indicate that - // they're fixed used. This allows for overlap between an array and a fixed resource which is - // allowed - D3D12FeedbackKey key; - key.stage = refl.stage; - key.type = DXBCBytecode::TYPE_RESOURCE; - key.space = ro.fixedBindSetOrSpace; - key.bind = ro.fixedBindNumber; - - slots[key].SetStaticUsed(); - } } for(size_t i = 0; i < refl.readWriteResources.size(); i++) @@ -993,27 +954,12 @@ static bool AddArraySlots(WrappedID3D12PipelineState::ShaderEntry *shad, uint32_ // descriptor storage side will be calculated later when finalising this with the root // signature information. - slots[key].SetSlot(numSlots); slots[key].numDescriptors = RDCMIN(maxDescriptors, rw.bindArraySize); slots[key].access = access; + slots[key].slot = numSlots; numSlots += slots[key].numDescriptors; dynamicUsed = true; } - else if(rw.bindArraySize <= 1) - { - // since the eventual descriptor range iteration won't know which descriptors map to arrays - // and which to fixed slots, it can't mark fixed descriptors as dynamically used itself. So - // instead we don't reserve a slot and set the top bit for these binds to indicate that - // they're fixed used. This allows for overlap between an array and a fixed resource which is - // allowed - D3D12FeedbackKey key; - key.stage = refl.stage; - key.type = DXBCBytecode::TYPE_UNORDERED_ACCESS_VIEW; - key.space = rw.fixedBindSetOrSpace; - key.bind = rw.fixedBindNumber; - - slots[key].SetStaticUsed(); - } } if(shad->GetDXBC()->m_Version.Major < 6 || @@ -1030,13 +976,13 @@ static bool AddArraySlots(WrappedID3D12PipelineState::ShaderEntry *shad, uint32_ D3D12FeedbackKey key = GetDirectHeapAccessKey(false); if(slots.find(key) == slots.end()) { - slots[key].SetSlot(numSlots); slots[key].numDescriptors = maxDescriptors; + slots[key].slot = numSlots; numSlots += maxDescriptors; key = GetDirectHeapAccessKey(true); - slots[key].SetSlot(numSlots); slots[key].numDescriptors = D3D12_MAX_SHADER_VISIBLE_SAMPLER_HEAP_SIZE; + slots[key].slot = numSlots; numSlots += D3D12_MAX_SHADER_VISIBLE_SAMPLER_HEAP_SIZE; } @@ -1488,191 +1434,20 @@ bool D3D12Replay::FetchShaderFeedback(uint32_t eventId) { result.valid = true; - // now we iterate over descriptor ranges and find which (of potentially multiple) registers - // each descriptor maps to and store the index if it's dynamically or statically used. We do - // this here so it only happens once instead of doing it when looking up the data. - - D3D12FeedbackKey curKey; - D3D12FeedbackBindIdentifier curIdentifier = {}; - // don't iterate the last signature element because that's ours! - for(size_t rootEl = 0; rootEl < modsig.Parameters.size() - 1; rootEl++) - { - curIdentifier.rootEl = rootEl; - - const D3D12RootSignatureParameter &p = modsig.Parameters[rootEl]; - - // only tables need feedback data, others all are treated as dynamically used - if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE) - { - for(size_t r = 0; r < p.ranges.size(); r++) - { - const D3D12_DESCRIPTOR_RANGE1 &range = p.ranges[r]; - - curIdentifier.rangeIndex = r; - - curKey.space = range.RegisterSpace; - - UINT num = range.NumDescriptors; - ShaderStageMask visMask = ShaderStageMask::Unknown; - // see which shader's binds we should look up for this range - switch(p.ShaderVisibility) - { - case D3D12_SHADER_VISIBILITY_ALL: - visMask = result.compute ? ShaderStageMask::Compute : ShaderStageMask::All; - break; - case D3D12_SHADER_VISIBILITY_VERTEX: visMask = ShaderStageMask::Vertex; break; - case D3D12_SHADER_VISIBILITY_HULL: visMask = ShaderStageMask::Hull; break; - case D3D12_SHADER_VISIBILITY_DOMAIN: visMask = ShaderStageMask::Domain; break; - case D3D12_SHADER_VISIBILITY_GEOMETRY: visMask = ShaderStageMask::Geometry; break; - case D3D12_SHADER_VISIBILITY_PIXEL: visMask = ShaderStageMask::Pixel; break; - case D3D12_SHADER_VISIBILITY_AMPLIFICATION: - visMask = ShaderStageMask::Amplification; - break; - case D3D12_SHADER_VISIBILITY_MESH: visMask = ShaderStageMask::Mesh; break; - default: RDCERR("Unexpected shader visibility %d", p.ShaderVisibility); return true; - } - - // set the key type - if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV) - curKey.type = DXBCBytecode::TYPE_RESOURCE; - else if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV) - curKey.type = DXBCBytecode::TYPE_UNORDERED_ACCESS_VIEW; - - for(ShaderStage st : values()) - { - curKey.stage = st; - if(visMask & MaskForStage(st)) - { - curIdentifier.descIndex = 0; - curKey.bind = range.BaseShaderRegister; - - // the feedback entries start here - auto slotIt = slots.lower_bound(curKey); - - // iterate over the declared range. This could be unbounded, so we might exit - // another way - for(uint32_t i = 0; i < num; i++) - { - // stop when we've run out of recorded used slots - if(slotIt == slots.end()) - break; - - uint32_t space = slotIt->first.space; - uint32_t bind = slotIt->first.bind; - uint32_t numDescriptors = slotIt->second.numDescriptors; - - // stop if the next used slot is in another space or is another type - if(space > curKey.space || slotIt->first.type != curKey.type) - break; - - // if the next bind is definitely outside this range, early out now instead of - // iterating fruitlessly - if((bind - range.BaseShaderRegister) > num) - break; - - uint32_t lastBind = bind + RDCCLAMP(numDescriptors, 1U, maxDescriptors); - - // if this slot's array covers the current bind, check the result - if(bind <= curKey.bind && curKey.bind < lastBind) - { - // if it's static used by having a fixed result declared, it's used - const bool staticUsed = slotIt->second.StaticUsed(); - - // otherwise check the feedback we got - const uint32_t baseSlot = slotIt->second.Slot(); - const uint32_t arrayIndex = curKey.bind - bind; - - if(staticUsed || slotsData[baseSlot + arrayIndex]) - result.used.push_back(curIdentifier); - } - - curKey.bind++; - curIdentifier.descIndex++; - - // if we've passed this slot, move to the next one. Because we're iterating a - // contiguous range of binds the next slot will be enough for the next iteration - if(curKey.bind >= lastBind) - slotIt++; - } - } - } - } - } - } - - for(D3D12FeedbackKey directAccessKey : - {GetDirectHeapAccessKey(false), GetDirectHeapAccessKey(true)}) - { - auto slotIt = slots.find(directAccessKey); - if(slotIt != slots.end()) - { - const D3D12FeedbackSlot &feedbackSlots = slots.at(directAccessKey); - for(uint32_t i = feedbackSlots.Slot(); - i < feedbackSlots.Slot() + feedbackSlots.numDescriptors; ++i) - { - if((slotsData[i] & magicFeedbackValue) == magicFeedbackValue) - { - uint32_t usedSlot = i - feedbackSlots.Slot(); - D3D12FeedbackBindIdentifier directAccessIdentifier = {}; - directAccessIdentifier.descIndex = usedSlot; - directAccessIdentifier.rootEl = ~0U; - directAccessIdentifier.rangeIndex = ~0U; - directAccessIdentifier.directAccess = true; - - ShaderStageMask feedbackStages = - ShaderStageMask((slotsData[i] & magicFeedbackStageMask) >> magicFeedbackStageShift); - - DescriptorType descriptorType = DescriptorType(slotsData[i] & magicFeedbackTypeMask); - - if(descriptorType == DescriptorType::Sampler) - { - directAccessIdentifier.bindType = BindType::Sampler; - } - else if(IsConstantBlockDescriptor(descriptorType)) - { - directAccessIdentifier.bindType = BindType::ConstantBuffer; - } - else if(IsReadOnlyDescriptor(descriptorType)) - { - directAccessIdentifier.bindType = BindType::ReadOnlyResource; - } - else if(IsReadWriteDescriptor(descriptorType)) - { - directAccessIdentifier.bindType = BindType::ReadWriteResource; - } - else - { - continue; - } - - // add a usage for each stage that reported it used - for(ShaderStage stage : values()) - { - if(MaskForStage(stage) & feedbackStages) - { - directAccessIdentifier.shaderStage = stage; - result.used.push_back(directAccessIdentifier); - } - } - } - } - } - } - D3D12FeedbackKey resourceDirectAccessKey = GetDirectHeapAccessKey(false), samplerDirectAccessKey = GetDirectHeapAccessKey(true); for(auto it = slots.begin(); it != slots.end(); ++it) { if(it->first == resourceDirectAccessKey || it->first == samplerDirectAccessKey) { - for(uint32_t i = it->second.Slot(); i < it->second.Slot() + it->second.numDescriptors; ++i) + for(uint32_t i = it->second.slot; i < it->second.slot + it->second.numDescriptors; ++i) { if((slotsData[i] & magicFeedbackValue) == magicFeedbackValue) { DescriptorAccess access; access.index = DescriptorAccess::NoShaderBinding; - access.byteOffset = access.arrayElement = i - it->second.Slot(); + access.byteOffset = access.arrayElement = i - it->second.slot; access.byteSize = 1; // descriptorStore will be set before this is returned by the replay, it's implicit // from the type @@ -1732,7 +1507,7 @@ bool D3D12Replay::FetchShaderFeedback(uint32_t eventId) for(uint32_t i = 0; i < it->second.numDescriptors; i++) { - const uint32_t baseSlot = it->second.Slot(); + const uint32_t baseSlot = it->second.slot; const uint32_t arrayIndex = i; if(slotsData[baseSlot + arrayIndex]) @@ -1748,8 +1523,6 @@ bool D3D12Replay::FetchShaderFeedback(uint32_t eventId) } } } - - std::sort(result.used.begin(), result.used.end()); } else if((pipelinestats->VSInvocations == 0 || !dynamicAccessPerStage[0]) && (pipelinestats->HSInvocations == 0 || !dynamicAccessPerStage[1]) && diff --git a/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp b/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp index 19e6f91a0..90edc0fe7 100644 --- a/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp +++ b/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp @@ -1380,8 +1380,7 @@ bool D3D12DebugAPIWrapper::CalculateSampleGather( void GatherConstantBuffers(WrappedID3D12Device *pDevice, const DXBCBytecode::Program &program, const D3D12RenderState::RootSignature &rootsig, - const ShaderReflection &refl, const ShaderBindpointMapping &mapping, - DXBCDebug::GlobalState &global, + const ShaderReflection &refl, DXBCDebug::GlobalState &global, rdcarray &sourceVars) { WrappedID3D12RootSignature *pD3D12RootSig = @@ -1598,8 +1597,8 @@ ShaderDebugTrace *D3D12Replay::DebugVertex(uint32_t eventId, uint32_t vertid, ui ThreadState &state = interpreter->activeLane(); // Fetch constant buffer data from root signature - GatherConstantBuffers(m_pDevice, *dxbc->GetDXBCByteCode(), rs.graphics, refl, - pso->VS()->GetMapping(), global, ret->sourceVars); + GatherConstantBuffers(m_pDevice, *dxbc->GetDXBCByteCode(), rs.graphics, refl, global, + ret->sourceVars); for(size_t i = 0; i < state.inputs.size(); i++) { @@ -2575,8 +2574,8 @@ void ExtractInputsPS(PSInput IN, ThreadState &state = interpreter->activeLane(); // Fetch constant buffer data from root signature - GatherConstantBuffers(m_pDevice, *dxbc->GetDXBCByteCode(), rs.graphics, refl, - origPSO->PS()->GetMapping(), global, ret->sourceVars); + GatherConstantBuffers(m_pDevice, *dxbc->GetDXBCByteCode(), rs.graphics, refl, global, + ret->sourceVars); global.sampleEvalRegisterMask = sampleEvalRegisterMask; @@ -2734,8 +2733,8 @@ ShaderDebugTrace *D3D12Replay::DebugThread(uint32_t eventId, GlobalState &global = interpreter->global; ThreadState &state = interpreter->activeLane(); - GatherConstantBuffers(m_pDevice, *dxbc->GetDXBCByteCode(), rs.compute, refl, - pso->CS()->GetMapping(), global, ret->sourceVars); + GatherConstantBuffers(m_pDevice, *dxbc->GetDXBCByteCode(), rs.compute, refl, global, + ret->sourceVars); for(int i = 0; i < 3; i++) { diff --git a/renderdoc/driver/gl/gl_common.h b/renderdoc/driver/gl/gl_common.h index dc6bd2f57..dafcf77ed 100644 --- a/renderdoc/driver/gl/gl_common.h +++ b/renderdoc/driver/gl/gl_common.h @@ -621,13 +621,10 @@ struct ShaderBindpointMapping; void EvaluateVertexAttributeBinds(GLuint curProg, const ShaderReflection *refl, bool spirv, rdcarray &vertexAttrBindings); -void EvaluateSPIRVBindpointMapping(GLuint curProg, int shadIdx, const ShaderReflection *refl, - ShaderBindpointMapping &mapping); - -void GetBindpointMapping(GLuint curProg, int shadIdx, const ShaderReflection *refl, - ShaderBindpointMapping &mapping); - -void ResortBindings(ShaderReflection *refl, ShaderBindpointMapping *mapping); +void GetCurrentBinding(GLuint curProg, ShaderReflection *refl, const ShaderResource &resource, + uint32_t &slot, bool &used); +void GetCurrentBinding(GLuint curProg, ShaderReflection *refl, const ConstantBlock &cblock, + uint32_t &slot, bool &used); // calls glBlitFramebuffer but ensures no state can interfere like scissor or color mask // pops state for only a single drawbuffer! diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index 9ab7ad24c..84dcf4778 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -5447,7 +5447,7 @@ void WrappedOpenGL::AddUsage(const ActionDescription &a) rs.FetchState(this); ShaderReflection *refl[NumShaderStages] = {NULL}; - ShaderBindpointMapping mapping[NumShaderStages]; + GLuint progForStage[NumShaderStages] = {}; GLuint curProg = 0; GL.glGetIntegerv(eGL_CURRENT_PROGRAM, (GLint *)&curProg); @@ -5471,7 +5471,7 @@ void WrappedOpenGL::AddUsage(const ActionDescription &a) curProg = rm->GetCurrentResource(pipeDetails.stagePrograms[i]).name; refl[i] = m_Shaders[pipeDetails.stageShaders[i]].reflection; - GetBindpointMapping(curProg, (int)i, refl[i], mapping[i]); + progForStage[i] = curProg; } } } @@ -5485,7 +5485,7 @@ void WrappedOpenGL::AddUsage(const ActionDescription &a) if(progDetails.stageShaders[i] != ResourceId()) { refl[i] = m_Shaders[progDetails.stageShaders[i]].reflection; - GetBindpointMapping(curProg, (int)i, refl[i], mapping[i]); + progForStage[i] = curProg; } } } @@ -5502,47 +5502,59 @@ void WrappedOpenGL::AddUsage(const ActionDescription &a) { if(!cblock.bufferBacked) continue; - if(cblock.bindPoint < 0 || cblock.bindPoint >= mapping[i].constantBlocks.count()) + + uint32_t slot = 0; + bool used = false; + GetCurrentBinding(progForStage[i], refl[i], cblock, slot, used); + + if(!used) continue; - int32_t bind = mapping[i].constantBlocks[cblock.bindPoint].bind; - - if(rs.UniformBinding[bind].res.name) - m_ResourceUses[rm->GetResID(rs.UniformBinding[bind].res)].push_back(cb); + if(rs.UniformBinding[slot].res.name) + m_ResourceUses[rm->GetResID(rs.UniformBinding[slot].res)].push_back(cb); } for(const ShaderResource &res : refl[i]->readWriteResources) { - int32_t bind = mapping[i].readWriteResources[res.bindPoint].bind; + uint32_t slot = 0; + bool used = false; + GetCurrentBinding(progForStage[i], refl[i], res, slot, used); + + if(!used) + continue; if(res.isTexture) { - if(rs.Images[bind].res.name) - m_ResourceUses[rm->GetResID(rs.Images[bind].res)].push_back(rw); + if(slot < ARRAY_COUNT(rs.Images) && rs.Images[slot].res.name) + m_ResourceUses[rm->GetResID(rs.Images[slot].res)].push_back(rw); } else { if(res.variableType.columns == 1 && res.variableType.rows == 1 && res.variableType.baseType == VarType::UInt) { - if(rs.AtomicCounter[bind].res.name) - m_ResourceUses[rm->GetResID(rs.AtomicCounter[bind].res)].push_back(rw); + if(slot < ARRAY_COUNT(rs.AtomicCounter) && rs.AtomicCounter[slot].res.name) + m_ResourceUses[rm->GetResID(rs.AtomicCounter[slot].res)].push_back(rw); } else { - if(rs.ShaderStorage[bind].res.name) - m_ResourceUses[rm->GetResID(rs.ShaderStorage[bind].res)].push_back(rw); + if(slot < ARRAY_COUNT(rs.ShaderStorage) && rs.ShaderStorage[slot].res.name) + m_ResourceUses[rm->GetResID(rs.ShaderStorage[slot].res)].push_back(rw); } } } for(const ShaderResource &res : refl[i]->readOnlyResources) { - int32_t bind = mapping[i].readOnlyResources[res.bindPoint].bind; + uint32_t slot = 0; + bool used = false; + GetCurrentBinding(progForStage[i], refl[i], res, slot, used); + + if(!used) + continue; GLResource *texList = NULL; const int32_t listSize = (int32_t)ARRAY_COUNT(rs.Tex2D); - ; switch(res.resType) { @@ -5561,8 +5573,8 @@ void WrappedOpenGL::AddUsage(const ActionDescription &a) case TextureType::Count: RDCERR("Invalid shader resource type"); break; } - if(texList != NULL && bind >= 0 && bind < listSize && texList[bind].name != 0) - m_ResourceUses[rm->GetResID(texList[bind])].push_back(ro); + if(texList != NULL && slot < listSize && texList[slot].name != 0) + m_ResourceUses[rm->GetResID(texList[slot])].push_back(ro); } } } diff --git a/renderdoc/driver/gl/gl_driver.h b/renderdoc/driver/gl/gl_driver.h index 57d5eb666..249fd162a 100644 --- a/renderdoc/driver/gl/gl_driver.h +++ b/renderdoc/driver/gl/gl_driver.h @@ -735,9 +735,6 @@ public: rdcarray specIDs; rdcarray specValues; - // pre-calculated bindpoint mapping for SPIR-V shaders. NOT valid for normal GLSL shaders - ShaderBindpointMapping mapping; - void ProcessCompilation(WrappedOpenGL &drv, ResourceId id, GLuint realShader); void ProcessSPIRVCompilation(WrappedOpenGL &drv, ResourceId id, GLuint realShader, const GLchar *pEntryPoint, GLuint numSpecializationConstants, @@ -797,7 +794,6 @@ public: if(shadId != ResourceId()) { stages.refls[i] = m_Shaders[shadId].reflection; - stages.mappings[i] = &m_Shaders[shadId].mapping; } } } diff --git a/renderdoc/driver/gl/gl_replay.cpp b/renderdoc/driver/gl/gl_replay.cpp index c8d77665b..a4a61c222 100644 --- a/renderdoc/driver/gl/gl_replay.cpp +++ b/renderdoc/driver/gl/gl_replay.cpp @@ -222,7 +222,6 @@ APIProperties GLReplay::GetAPIProperties() ret.localRenderer = GraphicsAPI::OpenGL; ret.degraded = m_Degraded; ret.vendor = m_DriverInfo.vendor; - ret.shadersMutable = true; ret.pixelHistory = true; return ret; @@ -1044,8 +1043,6 @@ void GLReplay::SavePipelineState(uint32_t eventId) GLint numTexUnits = 8; drv.glGetIntegerv(eGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numTexUnits); - pipe.textures.resize(numTexUnits); - pipe.samplers.resize(numTexUnits); GLenum activeTexture = eGL_TEXTURE0; drv.glGetIntegerv(eGL_ACTIVE_TEXTURE, (GLint *)&activeTexture); @@ -1057,15 +1054,14 @@ void GLReplay::SavePipelineState(uint32_t eventId) pipe.fragmentShader.stage = ShaderStage::Fragment; pipe.computeShader.stage = ShaderStage::Compute; - GLuint curProg = 0; - drv.glGetIntegerv(eGL_CURRENT_PROGRAM, (GLint *)&curProg); - GLPipe::Shader *stages[NumShaderStages] = { &pipe.vertexShader, &pipe.tessControlShader, &pipe.tessEvalShader, &pipe.geometryShader, &pipe.fragmentShader, &pipe.computeShader, }; ShaderReflection *refls[NumShaderStages] = {NULL}; - ShaderBindpointMapping *mappings[NumShaderStages] = {NULL}; + ResourceId progIds[NumShaderStages]; + ResourceId shadIds[NumShaderStages]; + GLuint progForStage[NumShaderStages] = {}; bool spirv[NumShaderStages] = {false}; for(size_t i = 0; i < NumShaderStages; i++) @@ -1075,123 +1071,89 @@ void GLReplay::SavePipelineState(uint32_t eventId) stages[i]->programResourceId = stages[i]->shaderResourceId = ResourceId(); stages[i]->reflection = NULL; - stages[i]->bindpointMapping = ShaderBindpointMapping(); } rdcarray vertexAttrBindings; - if(curProg == 0) + { - drv.glGetIntegerv(eGL_PROGRAM_PIPELINE_BINDING, (GLint *)&curProg); + GLuint curProg = 0; + drv.glGetIntegerv(eGL_CURRENT_PROGRAM, (GLint *)&curProg); if(curProg == 0) { - for(GLint unit = 0; unit < numTexUnits; unit++) + GLuint curPipe = 0; + drv.glGetIntegerv(eGL_PROGRAM_PIPELINE_BINDING, (GLint *)&curPipe); + + if(curPipe != 0) { - RDCEraseEl(pipe.textures[unit]); - RDCEraseEl(pipe.samplers[unit]); + ResourceId id = rm->GetResID(ProgramPipeRes(ctx, curPipe)); + const WrappedOpenGL::PipelineData &pipeDetails = m_pDriver->m_Pipelines[id]; + + pipe.pipelineResourceId = rm->GetUnreplacedOriginalID(id); + + for(size_t i = 0; i < ARRAY_COUNT(pipeDetails.stageShaders); i++) + { + if(!stages[i]) + continue; + + if(pipeDetails.stageShaders[i] != ResourceId()) + { + progIds[i] = pipeDetails.stagePrograms[i]; + shadIds[i] = pipeDetails.stageShaders[i]; + + progForStage[i] = rm->GetCurrentResource(pipeDetails.stagePrograms[i]).name; + } + } } } else { - ResourceId id = rm->GetResID(ProgramPipeRes(ctx, curProg)); - auto &pipeDetails = m_pDriver->m_Pipelines[id]; + ResourceId id = rm->GetResID(ProgramRes(ctx, curProg)); + const WrappedOpenGL::ProgramData &progDetails = m_pDriver->m_Programs[id]; - pipe.pipelineResourceId = rm->GetUnreplacedOriginalID(id); + pipe.pipelineResourceId = ResourceId(); - for(size_t i = 0; i < ARRAY_COUNT(pipeDetails.stageShaders); i++) + for(size_t i = 0; i < ARRAY_COUNT(progDetails.stageShaders); i++) { if(!stages[i]) continue; - if(pipeDetails.stageShaders[i] != ResourceId()) + if(progDetails.stageShaders[i] != ResourceId()) { - curProg = rm->GetCurrentResource(pipeDetails.stagePrograms[i]).name; + progIds[i] = id; + shadIds[i] = progDetails.stageShaders[i]; - auto &shaderDetails = m_pDriver->m_Shaders[pipeDetails.stageShaders[i]]; - - if(shaderDetails.reflection->resourceId == ResourceId()) - stages[i]->reflection = refls[i] = NULL; - else - stages[i]->reflection = refls[i] = shaderDetails.reflection; - - if(!shaderDetails.spirvWords.empty()) - { - stages[i]->bindpointMapping = shaderDetails.mapping; - spirv[i] = true; - - EvaluateSPIRVBindpointMapping(curProg, (int)i, refls[i], stages[i]->bindpointMapping); - - if(i == 0) - EvaluateVertexAttributeBinds(curProg, refls[i], true, vertexAttrBindings); - } - else - { - GetBindpointMapping(curProg, (int)i, refls[i], stages[i]->bindpointMapping); - - if(i == 0) - EvaluateVertexAttributeBinds(curProg, refls[i], false, vertexAttrBindings); - } - - mappings[i] = &stages[i]->bindpointMapping; - - stages[i]->programResourceId = rm->GetUnreplacedOriginalID(pipeDetails.stagePrograms[i]); - stages[i]->shaderResourceId = rm->GetUnreplacedOriginalID(pipeDetails.stageShaders[i]); - } - else - { - stages[i]->programResourceId = stages[i]->shaderResourceId = ResourceId(); + progForStage[i] = curProg; } } } } - else + + for(size_t i = 0; i < NumShaderStages; i++) { - ResourceId id = rm->GetResID(ProgramRes(ctx, curProg)); - auto &progDetails = m_pDriver->m_Programs[id]; - - pipe.pipelineResourceId = ResourceId(); - - for(size_t i = 0; i < ARRAY_COUNT(progDetails.stageShaders); i++) + if(progForStage[i]) { - if(!stages[i]) - continue; + progForStage[i] = rm->GetCurrentResource(progIds[i]).name; + stages[i]->programResourceId = rm->GetUnreplacedOriginalID(progIds[i]); + stages[i]->shaderResourceId = rm->GetUnreplacedOriginalID(shadIds[i]); - if(progDetails.stageShaders[i] != ResourceId()) - { - auto &shaderDetails = m_pDriver->m_Shaders[progDetails.stageShaders[i]]; + const WrappedOpenGL::ShaderData &shaderDetails = m_pDriver->m_Shaders[shadIds[i]]; - if(shaderDetails.reflection->resourceId == ResourceId()) - stages[i]->reflection = refls[i] = NULL; - else - stages[i]->reflection = refls[i] = shaderDetails.reflection; - - if(!shaderDetails.spirvWords.empty()) - { - stages[i]->bindpointMapping = shaderDetails.mapping; - spirv[i] = true; - - EvaluateSPIRVBindpointMapping(curProg, (int)i, refls[i], stages[i]->bindpointMapping); - - if(i == 0) - EvaluateVertexAttributeBinds(curProg, refls[i], true, vertexAttrBindings); - } - else - { - GetBindpointMapping(curProg, (int)i, refls[i], stages[i]->bindpointMapping); - - if(i == 0) - EvaluateVertexAttributeBinds(curProg, refls[i], false, vertexAttrBindings); - } - - mappings[i] = &stages[i]->bindpointMapping; - - stages[i]->programResourceId = rm->GetUnreplacedOriginalID(id); - stages[i]->shaderResourceId = rm->GetUnreplacedOriginalID(progDetails.stageShaders[i]); - } + if(shaderDetails.reflection->resourceId == ResourceId()) + stages[i]->reflection = refls[i] = NULL; else - { - stages[i]->programResourceId = stages[i]->shaderResourceId = ResourceId(); - } + stages[i]->reflection = refls[i] = shaderDetails.reflection; + + if(!shaderDetails.spirvWords.empty()) + spirv[i] = true; + + if(i == 0) + EvaluateVertexAttributeBinds(progForStage[i], refls[i], spirv[i], vertexAttrBindings); + } + else if(stages[i]) + { + stages[i]->programResourceId = stages[i]->shaderResourceId = ResourceId(); + stages[i]->reflection = NULL; } } @@ -1203,59 +1165,55 @@ void GLReplay::SavePipelineState(uint32_t eventId) pipe.vertexInput.attributes[i].boundShaderInput = -1; } - // !!!NOTE!!! This function will MODIFY the refls[] binding arrays. - // See inside this function for what it does and why. - for(size_t i = 0; i < ARRAY_COUNT(refls); i++) - { - // don't resort if it's SPIR-V - if(spirv[i]) - continue; - - ResortBindings(refls[i], mappings[i]); - } - pipe.textureCompleteness.clear(); for(size_t s = 0; s < NumShaderStages; s++) { - if(!refls[s]) + ShaderReflection *refl = refls[s]; + + if(!refl) continue; + GLuint prog = progForStage[s]; + DescriptorAccess access; access.descriptorStore = m_pDriver->m_DescriptorsID; - access.stage = refls[s]->stage; + access.stage = refl->stage; access.byteSize = 1; - const ShaderBindpointMapping &mapping = stages[s]->bindpointMapping; + m_Access.reserve(m_Access.size() + refl->constantBlocks.size() + + refl->readOnlyResources.size() + refl->readWriteResources.size()); - m_Access.reserve(m_Access.size() + mapping.constantBlocks.size() + - mapping.readOnlyResources.size() + mapping.readWriteResources.size()); - - RDCASSERT(mapping.constantBlocks.size() < 0xffff, mapping.constantBlocks.size()); - for(uint16_t i = 0; i < mapping.constantBlocks.size(); i++) + RDCASSERT(refl->constantBlocks.size() < 0xffff, refl->constantBlocks.size()); + for(uint16_t i = 0; i < refl->constantBlocks.size(); i++) { - int32_t bindset = mapping.constantBlocks[i].bindset; - int32_t bind = mapping.constantBlocks[i].bind; + uint32_t slot = 0; + bool used = false; + GetCurrentBinding(prog, refl, refl->constantBlocks[i], slot, used); - access.staticallyUnused = !mapping.constantBlocks[i].used; + access.staticallyUnused = !used; access.type = DescriptorType::ConstantBuffer; access.index = i; - if(bindset < 0) + if(!refl->constantBlocks[i].bufferBacked) access.byteOffset = EncodeGLDescriptorIndex({GLDescriptorMapping::BareUniforms, (uint32_t)s}); else access.byteOffset = - EncodeGLDescriptorIndex({GLDescriptorMapping::UniformBinding, (uint32_t)bind}); + EncodeGLDescriptorIndex({GLDescriptorMapping::UniformBinding, (uint32_t)slot}); m_Access.push_back(access); } - RDCASSERT(mapping.readOnlyResources.size() < 0xffff, mapping.readOnlyResources.size()); - for(uint16_t i = 0; i < mapping.readOnlyResources.size(); i++) + RDCASSERT(refl->readOnlyResources.size() < 0xffff, refl->readOnlyResources.size()); + for(uint16_t i = 0; i < refl->readOnlyResources.size(); i++) { - access.staticallyUnused = !mapping.readOnlyResources[i].used; + uint32_t slot = 0; + bool used = false; + GetCurrentBinding(prog, refl, refl->readOnlyResources[i], slot, used); + + access.staticallyUnused = !used; GLDescriptorMapping descType = GLDescriptorMapping::Tex2D; - switch(refls[s]->readOnlyResources[i].resType) + switch(refl->readOnlyResources[i].resType) { case TextureType::Buffer: descType = GLDescriptorMapping::TexBuffer; break; case TextureType::Texture1D: descType = GLDescriptorMapping::Tex1D; break; @@ -1270,7 +1228,7 @@ void GLReplay::SavePipelineState(uint32_t eventId) case TextureType::TextureCubeArray: descType = GLDescriptorMapping::TexCubeArray; break; case TextureType::Unknown: case TextureType::Count: - RDCERR("Invalid resource type on binding %s", refls[s]->readOnlyResources[i].name.c_str()); + RDCERR("Invalid resource type on binding %s", refl->readOnlyResources[i].name.c_str()); break; } @@ -1278,8 +1236,7 @@ void GLReplay::SavePipelineState(uint32_t eventId) if(descType == GLDescriptorMapping::TexBuffer) access.type = DescriptorType::TypedBuffer; access.index = i; - access.byteOffset = - EncodeGLDescriptorIndex({descType, (uint32_t)mapping.readOnlyResources[i].bind}); + access.byteOffset = EncodeGLDescriptorIndex({descType, slot}); m_Access.push_back(access); // checking texture completeness is a pretty expensive operation since it requires a lot of @@ -1290,10 +1247,10 @@ void GLReplay::SavePipelineState(uint32_t eventId) // samplers don't change (or are only ever used consistently with the same texture) amounts // to one entry per texture. // Note that textures can't change target, so we don't need to icnlude the target in the key - drv.glActiveTexture(GLenum(eGL_TEXTURE0 + mapping.readOnlyResources[i].bind)); + drv.glActiveTexture(GLenum(eGL_TEXTURE0 + slot)); GLenum binding = eGL_NONE; - switch(refls[s]->readOnlyResources[i].resType) + switch(refl->readOnlyResources[i].resType) { case TextureType::Unknown: binding = eGL_NONE; break; case TextureType::Buffer: binding = eGL_TEXTURE_BINDING_BUFFER; break; @@ -1339,17 +1296,21 @@ void GLReplay::SavePipelineState(uint32_t eventId) } } - RDCASSERT(mapping.readWriteResources.size() < 0xffff, mapping.readWriteResources.size()); - for(uint16_t i = 0; i < mapping.readWriteResources.size(); i++) + RDCASSERT(refl->readWriteResources.size() < 0xffff, refl->readWriteResources.size()); + for(uint16_t i = 0; i < refl->readWriteResources.size(); i++) { - access.staticallyUnused = !mapping.readWriteResources[i].used; + uint32_t slot = 0; + bool used = false; + GetCurrentBinding(prog, refl, refl->readWriteResources[i], slot, used); + + access.staticallyUnused = !used; GLDescriptorMapping descType = GLDescriptorMapping::Images; - if(refls[s]->readWriteResources[i].isTexture) + if(refl->readWriteResources[i].isTexture) { access.type = DescriptorType::ReadWriteImage; - if(refls[s]->readWriteResources[i].resType == TextureType::Buffer) + if(refl->readWriteResources[i].resType == TextureType::Buffer) access.type = DescriptorType::ReadWriteTypedBuffer; } else @@ -1357,131 +1318,138 @@ void GLReplay::SavePipelineState(uint32_t eventId) access.type = DescriptorType::ReadWriteBuffer; descType = GLDescriptorMapping::ShaderStorage; - if(refls[s]->readWriteResources[i].variableType.rows == 1 && - refls[s]->readWriteResources[i].variableType.columns == 1 && - refls[s]->readWriteResources[i].variableType.baseType == VarType::UInt) + if(refl->readWriteResources[i].variableType.rows == 1 && + refl->readWriteResources[i].variableType.columns == 1 && + refl->readWriteResources[i].variableType.baseType == VarType::UInt) { descType = GLDescriptorMapping::AtomicCounter; } } access.index = i; - access.byteOffset = - EncodeGLDescriptorIndex({descType, (uint32_t)mapping.readWriteResources[i].bind}); + access.byteOffset = EncodeGLDescriptorIndex({descType, slot}); m_Access.push_back(access); } } + // GL is ass-backwards in its handling of texture units. When a shader is active + // the types in the glsl samplers inform which targets are used from which texture units + // + // So texture unit 5 can have a 2D bound (texture 52) and a Cube bound (texture 77). + // * if a uniform sampler2D has value 5 then the 2D texture is used, and we sample from 52 + // * if a uniform samplerCube has value 5 then the Cube texture is used, and we sample from 77 + // It's illegal for both a sampler2D and samplerCube to both have the same value (or any two + // different types). It makes it all rather pointless and needlessly complex. + // + // What we have to do then, is consider the program, look at the values of the uniforms, and + // then check if two uniforms with different types point to the same binding + for(uint32_t unit = 0; unit < (uint32_t)numTexUnits; unit++) { - // search for conflicts by looking at all stages - for(uint32_t unit = 0; unit < (uint32_t)numTexUnits; unit++) + rdcstr typeConflict; + GLenum binding = eGL_NONE; + GLenum target = eGL_NONE; + TextureType resType = TextureType::Unknown; + rdcstr firstBindName; + + rdcarray descriptorsReferenced; + + for(const DescriptorAccess &access : m_Access) { - rdcstr typeConflict; - GLenum binding = eGL_NONE; - GLenum target = eGL_NONE; - TextureType resType = TextureType::Unknown; - rdcstr firstBindName; + // only look at read-only descriptors, these are the texture units that can clash + if(!IsReadOnlyDescriptor(access.type)) + continue; - rdcarray descriptorsReferenced; - - for(const DescriptorAccess &access : m_Access) + ShaderReflection *refl = refls[(uint32_t)access.stage]; + if(refl == NULL) { - // only look at read-only descriptors, these are the texture units that can clash - if(!IsReadOnlyDescriptor(access.type)) - continue; - - ShaderReflection *refl = refls[(uint32_t)access.stage]; - if(refl == NULL) - { - RDCERR("Unexpected NULL reflection on %s shader with a descriptor access", - ToStr(access.stage).c_str()); - continue; - } - - uint32_t accessedUnit = DecodeGLDescriptorIndex(access.byteOffset).idx; - - // accessed the same unit, check its binding - if(accessedUnit == unit) - { - if(!descriptorsReferenced.contains(access.byteOffset)) - descriptorsReferenced.push_back(access.byteOffset); - - const ShaderResource &res = refl->readOnlyResources[access.index]; - GLenum t = eGL_NONE; - - switch(res.resType) - { - case TextureType::Unknown: target = eGL_NONE; break; - case TextureType::Buffer: target = eGL_TEXTURE_BUFFER; break; - case TextureType::Texture1D: target = eGL_TEXTURE_1D; break; - case TextureType::Texture1DArray: target = eGL_TEXTURE_1D_ARRAY; break; - case TextureType::Texture2D: target = eGL_TEXTURE_2D; break; - case TextureType::TextureRect: target = eGL_TEXTURE_RECTANGLE; break; - case TextureType::Texture2DArray: target = eGL_TEXTURE_2D_ARRAY; break; - case TextureType::Texture2DMS: target = eGL_TEXTURE_2D_MULTISAMPLE; break; - case TextureType::Texture2DMSArray: target = eGL_TEXTURE_2D_MULTISAMPLE_ARRAY; break; - case TextureType::Texture3D: target = eGL_TEXTURE_3D; break; - case TextureType::TextureCube: target = eGL_TEXTURE_CUBE_MAP; break; - case TextureType::TextureCubeArray: target = eGL_TEXTURE_CUBE_MAP_ARRAY; break; - case TextureType::Count: RDCERR("Invalid shader resource type"); break; - } - - if(target != eGL_NONE) - t = TextureBinding(target); - - if(binding == eGL_NONE) - { - binding = t; - firstBindName = res.name; - resType = res.resType; - } - else if(binding == t) - { - // two uniforms with the same type pointing to the same slot is fine - binding = t; - } - else if(binding != t) - { - RDCERR("Two uniforms pointing to texture unit %d with types %s and %s", unit, - ToStr(binding).c_str(), ToStr(t).c_str()); - - if(typeConflict.empty()) - { - typeConflict = StringFormat::Fmt("First binding found '%s' is %s", - firstBindName.c_str(), ToStr(resType).c_str()); - } - - typeConflict += - StringFormat::Fmt(", '%s' is %s", res.name.c_str(), ToStr(res.resType).c_str()); - } - } + RDCERR("Unexpected NULL reflection on %s shader with a descriptor access", + ToStr(access.stage).c_str()); + continue; } - // if we found a type conflict, add an entry for all descriptors - if(!typeConflict.empty()) + uint32_t accessedUnit = DecodeGLDescriptorIndex(access.byteOffset).idx; + + // accessed the same unit, check its binding + if(accessedUnit == unit) { - for(uint32_t descriptor : descriptorsReferenced) + if(!descriptorsReferenced.contains(access.byteOffset)) + descriptorsReferenced.push_back(access.byteOffset); + + const ShaderResource &res = refl->readOnlyResources[access.index]; + GLenum t = eGL_NONE; + + switch(res.resType) { - bool found = false; - for(GLPipe::TextureCompleteness &completeness : pipe.textureCompleteness) + case TextureType::Unknown: target = eGL_NONE; break; + case TextureType::Buffer: target = eGL_TEXTURE_BUFFER; break; + case TextureType::Texture1D: target = eGL_TEXTURE_1D; break; + case TextureType::Texture1DArray: target = eGL_TEXTURE_1D_ARRAY; break; + case TextureType::Texture2D: target = eGL_TEXTURE_2D; break; + case TextureType::TextureRect: target = eGL_TEXTURE_RECTANGLE; break; + case TextureType::Texture2DArray: target = eGL_TEXTURE_2D_ARRAY; break; + case TextureType::Texture2DMS: target = eGL_TEXTURE_2D_MULTISAMPLE; break; + case TextureType::Texture2DMSArray: target = eGL_TEXTURE_2D_MULTISAMPLE_ARRAY; break; + case TextureType::Texture3D: target = eGL_TEXTURE_3D; break; + case TextureType::TextureCube: target = eGL_TEXTURE_CUBE_MAP; break; + case TextureType::TextureCubeArray: target = eGL_TEXTURE_CUBE_MAP_ARRAY; break; + case TextureType::Count: RDCERR("Invalid shader resource type"); break; + } + + if(target != eGL_NONE) + t = TextureBinding(target); + + if(binding == eGL_NONE) + { + binding = t; + firstBindName = res.name; + resType = res.resType; + } + else if(binding == t) + { + // two uniforms with the same type pointing to the same slot is fine + binding = t; + } + else if(binding != t) + { + RDCERR("Two uniforms pointing to texture unit %d with types %s and %s", unit, + ToStr(binding).c_str(), ToStr(t).c_str()); + + if(typeConflict.empty()) { - if(completeness.descriptorByteOffset == descriptor) - { - // don't worry about overwriting, the descriptor byte offset is unique to the unit so - // we should only set this at most once - completeness.typeConflict = typeConflict; - found = true; - } + typeConflict = StringFormat::Fmt("First binding found '%s' is %s", + firstBindName.c_str(), ToStr(resType).c_str()); } - if(!found) + typeConflict += + StringFormat::Fmt(", '%s' is %s", res.name.c_str(), ToStr(res.resType).c_str()); + } + } + } + + // if we found a type conflict, add an entry for all descriptors + if(!typeConflict.empty()) + { + for(uint32_t descriptor : descriptorsReferenced) + { + bool found = false; + for(GLPipe::TextureCompleteness &completeness : pipe.textureCompleteness) + { + if(completeness.descriptorByteOffset == descriptor) { - GLPipe::TextureCompleteness completeness; - completeness.descriptorByteOffset = descriptor; + // don't worry about overwriting, the descriptor byte offset is unique to the unit so + // we should only set this at most once completeness.typeConflict = typeConflict; - pipe.textureCompleteness.push_back(completeness); + found = true; } } + + if(!found) + { + GLPipe::TextureCompleteness completeness; + completeness.descriptorByteOffset = descriptor; + completeness.typeConflict = typeConflict; + pipe.textureCompleteness.push_back(completeness); + } } } } @@ -1536,421 +1504,8 @@ void GLReplay::SavePipelineState(uint32_t eventId) } } - // GL is ass-backwards in its handling of texture units. When a shader is active - // the types in the glsl samplers inform which targets are used from which texture units - // - // So texture unit 5 can have a 2D bound (texture 52) and a Cube bound (texture 77). - // * if a uniform sampler2D has value 5 then the 2D texture is used, and we sample from 52 - // * if a uniform samplerCube has value 5 then the Cube texture is used, and we sample from 77 - // It's illegal for both a sampler2D and samplerCube to both have the same value (or any two - // different types). It makes it all rather pointless and needlessly complex. - // - // What we have to do then, is consider the program, look at the values of the uniforms, and - // then get the appropriate current binding based on the uniform type. We can warn/alert the - // user if we hit the illegal case of two uniforms with different types but the same value - // - // Handling is different if no shaders are active, but we don't consider that case. - - for(GLint unit = 0; unit < numTexUnits; unit++) - { - GLenum binding = eGL_NONE; - GLenum target = eGL_NONE; - TextureType resType = TextureType::Unknown; - rdcstr firstBindName; - rdcstr typeConflict; - - for(size_t s = 0; s < ARRAY_COUNT(refls); s++) - { - if(refls[s] == NULL) - continue; - - for(const ShaderResource &res : refls[s]->readOnlyResources) - { - // bindPoint is the uniform value for this sampler - if(mappings[s]->readOnlyResources[res.bindPoint].bind == unit) - { - GLenum t = eGL_NONE; - - switch(res.resType) - { - case TextureType::Unknown: target = eGL_NONE; break; - case TextureType::Buffer: target = eGL_TEXTURE_BUFFER; break; - case TextureType::Texture1D: target = eGL_TEXTURE_1D; break; - case TextureType::Texture1DArray: target = eGL_TEXTURE_1D_ARRAY; break; - case TextureType::Texture2D: target = eGL_TEXTURE_2D; break; - case TextureType::TextureRect: target = eGL_TEXTURE_RECTANGLE; break; - case TextureType::Texture2DArray: target = eGL_TEXTURE_2D_ARRAY; break; - case TextureType::Texture2DMS: target = eGL_TEXTURE_2D_MULTISAMPLE; break; - case TextureType::Texture2DMSArray: target = eGL_TEXTURE_2D_MULTISAMPLE_ARRAY; break; - case TextureType::Texture3D: target = eGL_TEXTURE_3D; break; - case TextureType::TextureCube: target = eGL_TEXTURE_CUBE_MAP; break; - case TextureType::TextureCubeArray: target = eGL_TEXTURE_CUBE_MAP_ARRAY; break; - case TextureType::Count: RDCERR("Invalid shader resource type"); break; - } - - if(target != eGL_NONE) - t = TextureBinding(target); - - if(binding == eGL_NONE) - { - binding = t; - firstBindName = res.name; - resType = res.resType; - } - else if(binding == t) - { - // two uniforms with the same type pointing to the same slot is fine - binding = t; - } - else if(binding != t) - { - RDCERR("Two uniforms pointing to texture unit %d with types %s and %s", unit, - ToStr(binding).c_str(), ToStr(t).c_str()); - - if(typeConflict.empty()) - { - typeConflict = StringFormat::Fmt("First binding found '%s' is %s", - firstBindName.c_str(), ToStr(resType).c_str()); - } - - typeConflict += - StringFormat::Fmt(", '%s' is %s", res.name.c_str(), ToStr(res.resType).c_str()); - } - } - } - } - - if(binding != eGL_NONE) - { - drv.glActiveTexture(GLenum(eGL_TEXTURE0 + unit)); - - GLuint tex = 0; - - if(binding == eGL_TEXTURE_CUBE_MAP_ARRAY && !HasExt[ARB_texture_cube_map_array]) - tex = 0; - else - drv.glGetIntegerv(binding, (GLint *)&tex); - - pipe.textures[unit].typeConflict = typeConflict; - - if(tex == 0) - { - pipe.textures[unit].resourceId = ResourceId(); - pipe.textures[unit].firstMip = 0; - pipe.textures[unit].numMips = 1; - pipe.textures[unit].type = TextureType::Unknown; - pipe.textures[unit].depthReadChannel = -1; - pipe.textures[unit].swizzle.red = TextureSwizzle::Red; - pipe.textures[unit].swizzle.green = TextureSwizzle::Green; - pipe.textures[unit].swizzle.blue = TextureSwizzle::Blue; - pipe.textures[unit].swizzle.alpha = TextureSwizzle::Alpha; - - RDCEraseEl(pipe.samplers[unit].borderColor); - pipe.samplers[unit].addressS = AddressMode::Wrap; - pipe.samplers[unit].addressT = AddressMode::Wrap; - pipe.samplers[unit].addressR = AddressMode::Wrap; - pipe.samplers[unit].compareFunction = CompareFunction::AlwaysTrue; - pipe.samplers[unit].filter = TextureFilter(); - pipe.samplers[unit].seamlessCubeMap = false; - pipe.samplers[unit].maxAnisotropy = 0.0f; - pipe.samplers[unit].maxLOD = 0.0f; - pipe.samplers[unit].minLOD = 0.0f; - pipe.samplers[unit].mipLODBias = 0.0f; - } - else - { - GLint firstMip = 0, numMips = 1; - - if(target != eGL_TEXTURE_BUFFER) - { - drv.glGetTextureParameterivEXT(tex, target, eGL_TEXTURE_BASE_LEVEL, &firstMip); - drv.glGetTextureParameterivEXT(tex, target, eGL_TEXTURE_MAX_LEVEL, &numMips); - - numMips = numMips - firstMip + 1; - } - - pipe.textures[unit].resourceId = rm->GetOriginalID(rm->GetResID(TextureRes(ctx, tex))); - pipe.textures[unit].firstMip = (uint32_t)firstMip; - pipe.textures[unit].numMips = (uint32_t)numMips; - pipe.textures[unit].type = resType; - - pipe.textures[unit].depthReadChannel = -1; - - GLenum levelQueryType = - target == eGL_TEXTURE_CUBE_MAP ? eGL_TEXTURE_CUBE_MAP_POSITIVE_X : target; - GLenum fmt = eGL_NONE; - drv.glGetTexLevelParameteriv(levelQueryType, 0, eGL_TEXTURE_INTERNAL_FORMAT, (GLint *)&fmt); - if(IsDepthStencilFormat(fmt)) - { - GLint depthMode = eGL_DEPTH_COMPONENT; - - if(HasExt[ARB_stencil_texturing]) - drv.glGetTextureParameterivEXT(tex, target, eGL_DEPTH_STENCIL_TEXTURE_MODE, &depthMode); - - if(depthMode == eGL_DEPTH_COMPONENT) - pipe.textures[unit].depthReadChannel = 0; - else if(depthMode == eGL_STENCIL_INDEX) - pipe.textures[unit].depthReadChannel = 1; - } - - GLenum swizzles[4] = {eGL_RED, eGL_GREEN, eGL_BLUE, eGL_ALPHA}; - if(target != eGL_TEXTURE_BUFFER && - (HasExt[ARB_texture_swizzle] || HasExt[EXT_texture_swizzle])) - GetTextureSwizzle(tex, target, swizzles); - - pipe.textures[unit].swizzle.red = MakeSwizzle(swizzles[0]); - pipe.textures[unit].swizzle.green = MakeSwizzle(swizzles[1]); - pipe.textures[unit].swizzle.blue = MakeSwizzle(swizzles[2]); - pipe.textures[unit].swizzle.alpha = MakeSwizzle(swizzles[3]); - - GLuint samp = 0; - if(HasExt[ARB_sampler_objects]) - drv.glGetIntegerv(eGL_SAMPLER_BINDING, (GLint *)&samp); - - pipe.samplers[unit].resourceId = rm->GetOriginalID(rm->GetResID(SamplerRes(ctx, samp))); - - // checking texture completeness is a pretty expensive operation since it requires a lot of - // queries against the driver's texture properties. - // We assume that if a texture and sampler are complete at any point, even if their - // properties change mid-frame they will stay complete. Similarly if they are _incomplete_ - // they will stay incomplete. Thus we can cache the results for a given pair, which if - // samplers don't change (or are only ever used consistently with the same texture) amounts - // to one entry per texture. - // Note that textures can't change target, so we don't need to icnlude the target in the key - CompleteCacheKey complete = {tex, samp}; - - auto it = m_CompleteCache.find(complete); - if(it == m_CompleteCache.end()) - it = m_CompleteCache.insert( - it, std::make_pair(complete, GetTextureCompleteStatus(target, tex, samp))); - pipe.textures[unit].completeStatus = it->second; - - if(target != eGL_TEXTURE_BUFFER && target != eGL_TEXTURE_2D_MULTISAMPLE && - target != eGL_TEXTURE_2D_MULTISAMPLE_ARRAY) - { - if(samp != 0) - drv.glGetSamplerParameterfv(samp, eGL_TEXTURE_BORDER_COLOR, - pipe.samplers[unit].borderColor.data()); - else - drv.glGetTextureParameterfvEXT(tex, target, eGL_TEXTURE_BORDER_COLOR, - pipe.samplers[unit].borderColor.data()); - - GLint v; - v = 0; - if(samp != 0) - drv.glGetSamplerParameteriv(samp, eGL_TEXTURE_WRAP_S, &v); - else - drv.glGetTextureParameterivEXT(tex, target, eGL_TEXTURE_WRAP_S, &v); - pipe.samplers[unit].addressS = MakeAddressMode((GLenum)v); - - v = 0; - if(samp != 0) - drv.glGetSamplerParameteriv(samp, eGL_TEXTURE_WRAP_T, &v); - else - drv.glGetTextureParameterivEXT(tex, target, eGL_TEXTURE_WRAP_T, &v); - pipe.samplers[unit].addressT = MakeAddressMode((GLenum)v); - - v = 0; - if(samp != 0) - drv.glGetSamplerParameteriv(samp, eGL_TEXTURE_WRAP_R, &v); - else - drv.glGetTextureParameterivEXT(tex, target, eGL_TEXTURE_WRAP_R, &v); - pipe.samplers[unit].addressR = MakeAddressMode((GLenum)v); - - // GLES 3 is always seamless - if(IsGLES && GLCoreVersion > 30) - { - pipe.samplers[unit].seamlessCubeMap = true; - } - else - { - // toggle on proper GL, GLES 2 this is always going to be false - pipe.samplers[unit].seamlessCubeMap = rs.Enabled[GLRenderState::eEnabled_TexCubeSeamless]; - } - - v = 0; - if(samp != 0) - drv.glGetSamplerParameteriv(samp, eGL_TEXTURE_COMPARE_FUNC, &v); - else - drv.glGetTextureParameterivEXT(tex, target, eGL_TEXTURE_COMPARE_FUNC, &v); - pipe.samplers[unit].compareFunction = MakeCompareFunc((GLenum)v); - - GLint minf = 0; - GLint magf = 0; - if(samp != 0) - drv.glGetSamplerParameteriv(samp, eGL_TEXTURE_MIN_FILTER, &minf); - else - drv.glGetTextureParameterivEXT(tex, target, eGL_TEXTURE_MIN_FILTER, &minf); - - if(samp != 0) - drv.glGetSamplerParameteriv(samp, eGL_TEXTURE_MAG_FILTER, &magf); - else - drv.glGetTextureParameterivEXT(tex, target, eGL_TEXTURE_MAG_FILTER, &magf); - - if(HasExt[ARB_texture_filter_anisotropic]) - { - if(samp != 0) - drv.glGetSamplerParameterfv(samp, eGL_TEXTURE_MAX_ANISOTROPY, - &pipe.samplers[unit].maxAnisotropy); - else - drv.glGetTextureParameterfvEXT(tex, target, eGL_TEXTURE_MAX_ANISOTROPY, - &pipe.samplers[unit].maxAnisotropy); - } - else - { - pipe.samplers[unit].maxAnisotropy = 0.0f; - } - - pipe.samplers[unit].filter = - MakeFilter((GLenum)minf, (GLenum)magf, pipe.samplers[unit].maxAnisotropy); - - v = 0; - if(samp != 0) - drv.glGetSamplerParameteriv(samp, eGL_TEXTURE_COMPARE_MODE, &v); - else - drv.glGetTextureParameterivEXT(tex, target, eGL_TEXTURE_COMPARE_MODE, &v); - pipe.samplers[unit].filter.filter = (GLenum)v == eGL_COMPARE_REF_TO_TEXTURE - ? FilterFunction::Comparison - : FilterFunction::Normal; - - if(samp != 0) - drv.glGetSamplerParameterfv(samp, eGL_TEXTURE_MAX_LOD, &pipe.samplers[unit].maxLOD); - else - drv.glGetTextureParameterfvEXT(tex, target, eGL_TEXTURE_MAX_LOD, - &pipe.samplers[unit].maxLOD); - - if(samp != 0) - drv.glGetSamplerParameterfv(samp, eGL_TEXTURE_MIN_LOD, &pipe.samplers[unit].minLOD); - else - drv.glGetTextureParameterfvEXT(tex, target, eGL_TEXTURE_MIN_LOD, - &pipe.samplers[unit].minLOD); - - if(!IsGLES) - { - if(samp != 0) - drv.glGetSamplerParameterfv(samp, eGL_TEXTURE_LOD_BIAS, - &pipe.samplers[unit].mipLODBias); - else - drv.glGetTextureParameterfvEXT(tex, target, eGL_TEXTURE_LOD_BIAS, - &pipe.samplers[unit].mipLODBias); - } - else - { - pipe.samplers[unit].mipLODBias = 0.0f; - } - } - else - { - // texture buffers don't support sampling - RDCEraseEl(pipe.samplers[unit].borderColor); - pipe.samplers[unit].addressS = AddressMode::Wrap; - pipe.samplers[unit].addressT = AddressMode::Wrap; - pipe.samplers[unit].addressR = AddressMode::Wrap; - pipe.samplers[unit].compareFunction = CompareFunction::AlwaysTrue; - pipe.samplers[unit].filter = TextureFilter(); - pipe.samplers[unit].seamlessCubeMap = false; - pipe.samplers[unit].maxAnisotropy = 0.0f; - pipe.samplers[unit].maxLOD = 0.0f; - pipe.samplers[unit].minLOD = 0.0f; - pipe.samplers[unit].mipLODBias = 0.0f; - } - } - } - else - { - // what should we do in this case? there could be something bound just not used, - // it'd be nice to return that - } - } - drv.glActiveTexture(activeTexture); - pipe.uniformBuffers.resize(ARRAY_COUNT(rs.UniformBinding)); - for(size_t b = 0; b < pipe.uniformBuffers.size(); b++) - { - if(rs.UniformBinding[b].res.name == 0) - { - pipe.uniformBuffers[b].resourceId = ResourceId(); - pipe.uniformBuffers[b].byteOffset = pipe.uniformBuffers[b].byteSize = 0; - } - else - { - pipe.uniformBuffers[b].resourceId = rm->GetOriginalID(rm->GetResID(rs.UniformBinding[b].res)); - pipe.uniformBuffers[b].byteOffset = rs.UniformBinding[b].start; - pipe.uniformBuffers[b].byteSize = rs.UniformBinding[b].size; - } - } - - pipe.atomicBuffers.resize(ARRAY_COUNT(rs.AtomicCounter)); - for(size_t b = 0; b < pipe.atomicBuffers.size(); b++) - { - if(rs.AtomicCounter[b].res.name == 0) - { - pipe.atomicBuffers[b].resourceId = ResourceId(); - pipe.atomicBuffers[b].byteOffset = pipe.atomicBuffers[b].byteSize = 0; - } - else - { - pipe.atomicBuffers[b].resourceId = rm->GetOriginalID(rm->GetResID(rs.AtomicCounter[b].res)); - pipe.atomicBuffers[b].byteOffset = rs.AtomicCounter[b].start; - pipe.atomicBuffers[b].byteSize = rs.AtomicCounter[b].size; - } - } - - pipe.shaderStorageBuffers.resize(ARRAY_COUNT(rs.ShaderStorage)); - for(size_t b = 0; b < pipe.shaderStorageBuffers.size(); b++) - { - if(rs.ShaderStorage[b].res.name == 0) - { - pipe.shaderStorageBuffers[b].resourceId = ResourceId(); - pipe.shaderStorageBuffers[b].byteOffset = pipe.shaderStorageBuffers[b].byteSize = 0; - } - else - { - pipe.shaderStorageBuffers[b].resourceId = - rm->GetOriginalID(rm->GetResID(rs.ShaderStorage[b].res)); - pipe.shaderStorageBuffers[b].byteOffset = rs.ShaderStorage[b].start; - pipe.shaderStorageBuffers[b].byteSize = rs.ShaderStorage[b].size; - } - } - - pipe.images.resize(ARRAY_COUNT(rs.Images)); - for(size_t i = 0; i < pipe.images.size(); i++) - { - if(rs.Images[i].res.name == 0) - { - RDCEraseEl(pipe.images[i]); - } - else - { - ResourceId id = rm->GetResID(rs.Images[i].res); - pipe.images[i].resourceId = rm->GetOriginalID(id); - pipe.images[i].mipLevel = rs.Images[i].level; - pipe.images[i].layered = rs.Images[i].layered; - pipe.images[i].slice = rs.Images[i].layer; - if(rs.Images[i].access == eGL_READ_ONLY) - { - pipe.images[i].readAllowed = true; - pipe.images[i].writeAllowed = false; - } - else if(rs.Images[i].access == eGL_WRITE_ONLY) - { - pipe.images[i].readAllowed = false; - pipe.images[i].writeAllowed = true; - } - else - { - pipe.images[i].readAllowed = true; - pipe.images[i].writeAllowed = true; - } - pipe.images[i].imageFormat = MakeResourceFormat(eGL_TEXTURE_2D, rs.Images[i].format); - - CacheTexture(id); - - pipe.images[i].type = m_CachedTextures[id].type; - } - } - // Vertex post processing and rasterization RDCCOMPILE_ASSERT(ARRAY_COUNT(rs.Viewports) == ARRAY_COUNT(rs.DepthRanges), @@ -3283,7 +2838,7 @@ void GLReplay::FillCBufferVariables(ResourceId pipeline, ResourceId shader, Shad } else { - if(shaderDetails.mapping.constantBlocks[cbufSlot].bindset == SpecializationConstantBindSet) + if(cblock.fixedBindSetOrSpace == SpecializationConstantBindSet) { rdcarray specconsts; diff --git a/renderdoc/driver/gl/gl_shader_refl.cpp b/renderdoc/driver/gl/gl_shader_refl.cpp index 766bfabc0..d635161c1 100644 --- a/renderdoc/driver/gl/gl_shader_refl.cpp +++ b/renderdoc/driver/gl/gl_shader_refl.cpp @@ -1783,7 +1783,6 @@ void MakeShaderReflection(GLenum shadType, GLuint sepProg, ShaderReflection &ref rdcarray &reslist = (res.isReadOnly ? roresources : rwresources); - res.bindPoint = (int32_t)reslist.size(); reslist.push_back(res); // array of samplers @@ -1794,7 +1793,6 @@ void MakeShaderReflection(GLenum shadType, GLuint sepProg, ShaderReflection &ref { rdcstr arrname = StringFormat::Fmt("%s[%d]", name.c_str(), i); - res.bindPoint = (int32_t)reslist.size(); res.name = arrname; reslist.push_back(res); @@ -1802,7 +1800,7 @@ void MakeShaderReflection(GLenum shadType, GLuint sepProg, ShaderReflection &ref } } - rdcarray ssbos; + rdcarray ssbos; uint32_t ssboMembers = 0; GLint numSSBOs = 0; @@ -1830,7 +1828,6 @@ void MakeShaderReflection(GLenum shadType, GLuint sepProg, ShaderReflection &ref res.variableType.matrixByteStride = 0; res.variableType.name = "buffer"; res.variableType.baseType = VarType::UInt; - res.bindPoint = (int32_t)rwresources.size(); res.name = nm; res.descriptorType = DescriptorType::ReadWriteBuffer; @@ -1855,8 +1852,8 @@ void MakeShaderReflection(GLenum shadType, GLuint sepProg, ShaderReflection &ref } } + ssbos.push_back(rwresources.size()); rwresources.push_back(res); - ssbos.push_back(res.bindPoint); // only count members from the first array index if(!isArray || arrayIdx == 0) @@ -1993,7 +1990,6 @@ void MakeShaderReflection(GLenum shadType, GLuint sepProg, ShaderReflection &ref ConstantBlock cblock; cblock.name = uboNames[i]; cblock.bufferBacked = true; - cblock.bindPoint = (int32_t)refl.constantBlocks.size(); GLenum bufSize = eGL_BUFFER_DATA_SIZE; GL.glGetProgramResourceiv(sepProg, eGL_UNIFORM_BLOCK, i, 1, &bufSize, 1, NULL, @@ -2017,7 +2013,6 @@ void MakeShaderReflection(GLenum shadType, GLuint sepProg, ShaderReflection &ref ConstantBlock globals; globals.name = "$Globals"; globals.bufferBacked = false; - globals.bindPoint = (int32_t)refl.constantBlocks.size(); // global uniforms have no defined order, location will be per implementation, so sort instead // alphabetically @@ -2460,15 +2455,9 @@ void EvaluateVertexAttributeBinds(GLuint curProg, const ShaderReflection *refl, } } -void GetBindpointMapping(GLuint curProg, int shadIdx, const ShaderReflection *refl, - ShaderBindpointMapping &mapping) +void GetCurrentBinding(GLuint curProg, ShaderReflection *refl, const ShaderResource &resource, + uint32_t &slot, bool &used) { - if(!refl) - { - mapping = ShaderBindpointMapping(); - return; - } - // in case of bugs, we readback into this array instead of a single int GLint dummyReadback[32]; @@ -2477,30 +2466,53 @@ void GetBindpointMapping(GLuint curProg, int shadIdx, const ShaderReflection *re dummyReadback[i] = 0x6c7b8a9d; #endif - const GLenum refEnum[] = { + const GLenum refEnums[] = { eGL_REFERENCED_BY_VERTEX_SHADER, eGL_REFERENCED_BY_TESS_CONTROL_SHADER, eGL_REFERENCED_BY_TESS_EVALUATION_SHADER, eGL_REFERENCED_BY_GEOMETRY_SHADER, eGL_REFERENCED_BY_FRAGMENT_SHADER, eGL_REFERENCED_BY_COMPUTE_SHADER, }; - mapping.readOnlyResources.resize(refl->readOnlyResources.size()); - for(size_t i = 0; i < refl->readOnlyResources.size(); i++) + const GLenum refEnum = refEnums[(uint32_t)refl->stage]; + + const GLenum atomicRefEnums[] = { + eGL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER, + eGL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER, + eGL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER, + eGL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER, + eGL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER, + eGL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER, + }; + + const GLenum atomicRefEnum = atomicRefEnums[(uint32_t)refl->stage]; + + if(refl->encoding == ShaderEncoding::OpenGLSPIRV) { - if(refl->readOnlyResources[i].isTexture) + if(resource.isTexture && resource.fixedBindNumber != ~0U) + { + GL.glGetUniformiv(curProg, resource.fixedBindNumber, dummyReadback); + slot = dummyReadback[0]; + used = true; + } + } + else if(resource.isReadOnly) + { + if(resource.isTexture) { // normal sampler or image load/store - GLint loc = GL.glGetUniformLocation(curProg, refl->readOnlyResources[i].name.c_str()); + GLint loc = GL.glGetUniformLocation(curProg, resource.name.c_str()); if(loc >= 0) { GL.glGetUniformiv(curProg, loc, dummyReadback); - mapping.readOnlyResources[i].bindset = 0; - mapping.readOnlyResources[i].bind = dummyReadback[0]; - mapping.readOnlyResources[i].arraySize = 1; + slot = dummyReadback[0]; + } + else + { + slot = 0; } // handle sampler arrays, use the base name - rdcstr name = refl->readOnlyResources[i].name; + rdcstr name = resource.name; if(name.back() == ']') { do @@ -2515,42 +2527,40 @@ void GetBindpointMapping(GLuint curProg, int shadIdx, const ShaderReflection *re if(idx == GL_INVALID_INDEX) { - mapping.readOnlyResources[i].used = false; + used = false; } else { - GLint used = 0; - GL.glGetProgramResourceiv(curProg, eGL_UNIFORM, idx, 1, &refEnum[shadIdx], 1, NULL, &used); - mapping.readOnlyResources[i].used = (used != 0); + GLint glUsed = 0; + GL.glGetProgramResourceiv(curProg, eGL_UNIFORM, idx, 1, &refEnum, 1, NULL, &glUsed); + used = (glUsed != 0); } } else { - mapping.readOnlyResources[i].bindset = -1; - mapping.readOnlyResources[i].bind = -1; - mapping.readOnlyResources[i].used = false; - mapping.readOnlyResources[i].arraySize = 1; + slot = 0; + used = false; } } - - mapping.readWriteResources.resize(refl->readWriteResources.size()); - for(size_t i = 0; i < refl->readWriteResources.size(); i++) + else { - if(refl->readWriteResources[i].isTexture) + if(resource.isTexture) { // image load/store - GLint loc = GL.glGetUniformLocation(curProg, refl->readWriteResources[i].name.c_str()); + GLint loc = GL.glGetUniformLocation(curProg, resource.name.c_str()); if(loc >= 0) { GL.glGetUniformiv(curProg, loc, dummyReadback); - mapping.readWriteResources[i].bindset = 0; - mapping.readWriteResources[i].bind = dummyReadback[0]; - mapping.readWriteResources[i].arraySize = 1; + slot = dummyReadback[0]; + } + else + { + slot = 0; } // handle sampler arrays, use the base name - rdcstr name = refl->readWriteResources[i].name; + rdcstr name = resource.name; if(name.back() == ']') { do @@ -2565,31 +2575,27 @@ void GetBindpointMapping(GLuint curProg, int shadIdx, const ShaderReflection *re if(idx == GL_INVALID_INDEX) { - mapping.readWriteResources[i].used = false; + used = false; } else { - GLint used = 0; - GL.glGetProgramResourceiv(curProg, eGL_UNIFORM, idx, 1, &refEnum[shadIdx], 1, NULL, &used); - mapping.readWriteResources[i].used = (used != 0); + GLint glUsed = 0; + GL.glGetProgramResourceiv(curProg, eGL_UNIFORM, idx, 1, &refEnum, 1, NULL, &glUsed); + used = (glUsed != 0); } } - else if(!refl->readWriteResources[i].isTexture) + else { - if(refl->readWriteResources[i].variableType.columns == 1 && - refl->readWriteResources[i].variableType.rows == 1 && - refl->readWriteResources[i].variableType.baseType == VarType::UInt) + if(resource.variableType.columns == 1 && resource.variableType.rows == 1 && + resource.variableType.baseType == VarType::UInt) { // atomic uint - GLuint idx = GL.glGetProgramResourceIndex(curProg, eGL_UNIFORM, - refl->readWriteResources[i].name.c_str()); + GLuint idx = GL.glGetProgramResourceIndex(curProg, eGL_UNIFORM, resource.name.c_str()); if(idx == GL_INVALID_INDEX) { - mapping.readWriteResources[i].bindset = -1; - mapping.readWriteResources[i].bind = -1; - mapping.readWriteResources[i].used = false; - mapping.readWriteResources[i].arraySize = 1; + slot = 0; + used = false; } else { @@ -2600,44 +2606,28 @@ void GetBindpointMapping(GLuint curProg, int shadIdx, const ShaderReflection *re if(atomicIndex == GL_INVALID_INDEX) { - mapping.readWriteResources[i].bindset = -1; - mapping.readWriteResources[i].bind = -1; - mapping.readWriteResources[i].used = false; - mapping.readWriteResources[i].arraySize = 1; + slot = 0; + used = false; } else { if(IsGLES) { prop = eGL_BUFFER_BINDING; - mapping.readWriteResources[i].bindset = 0; GL.glGetProgramResourceiv(curProg, eGL_ATOMIC_COUNTER_BUFFER, atomicIndex, 1, &prop, - 1, NULL, &mapping.readWriteResources[i].bind); - GLint used = 0; + 1, NULL, (GLint *)&slot); + GLint glUsed = 0; GL.glGetProgramResourceiv(curProg, eGL_ATOMIC_COUNTER_BUFFER, atomicIndex, 1, - &refEnum[shadIdx], 1, NULL, &used); - mapping.readWriteResources[i].used = (used != 0); - mapping.readWriteResources[i].arraySize = 1; + &refEnum, 1, NULL, &glUsed); + used = (glUsed != 0); } else { - const GLenum atomicRefEnum[] = { - eGL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER, - eGL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER, - eGL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER, - eGL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER, - eGL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER, - eGL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER, - }; - mapping.readWriteResources[i].bindset = 0; - GL.glGetActiveAtomicCounterBufferiv(curProg, atomicIndex, - eGL_ATOMIC_COUNTER_BUFFER_BINDING, - &mapping.readWriteResources[i].bind); - GLint used = 0; - GL.glGetActiveAtomicCounterBufferiv(curProg, atomicIndex, atomicRefEnum[shadIdx], - &used); - mapping.readWriteResources[i].used = (used != 0); - mapping.readWriteResources[i].arraySize = 1; + GL.glGetActiveAtomicCounterBufferiv( + curProg, atomicIndex, eGL_ATOMIC_COUNTER_BUFFER_BINDING, (GLint *)&slot); + GLint glUsed = 0; + GL.glGetActiveAtomicCounterBufferiv(curProg, atomicIndex, atomicRefEnum, &glUsed); + used = (glUsed != 0); } } } @@ -2645,115 +2635,26 @@ void GetBindpointMapping(GLuint curProg, int shadIdx, const ShaderReflection *re else { // shader storage buffer object - GLuint idx = GL.glGetProgramResourceIndex(curProg, eGL_SHADER_STORAGE_BLOCK, - refl->readWriteResources[i].name.c_str()); + GLuint idx = + GL.glGetProgramResourceIndex(curProg, eGL_SHADER_STORAGE_BLOCK, resource.name.c_str()); if(idx == GL_INVALID_INDEX) { - mapping.readWriteResources[i].bindset = -1; - mapping.readWriteResources[i].bind = -1; - mapping.readWriteResources[i].used = false; - mapping.readWriteResources[i].arraySize = 1; + slot = 0; + used = false; } else { GLenum prop = eGL_BUFFER_BINDING; - mapping.readWriteResources[i].bindset = 0; GL.glGetProgramResourceiv(curProg, eGL_SHADER_STORAGE_BLOCK, idx, 1, &prop, 1, NULL, - &mapping.readWriteResources[i].bind); - GLint used = 0; - GL.glGetProgramResourceiv(curProg, eGL_SHADER_STORAGE_BLOCK, idx, 1, &refEnum[shadIdx], 1, - NULL, &used); - mapping.readWriteResources[i].used = (used != 0); - mapping.readWriteResources[i].arraySize = 1; + (GLint *)&slot); + GLint glUsed = 0; + GL.glGetProgramResourceiv(curProg, eGL_SHADER_STORAGE_BLOCK, idx, 1, &refEnum, 1, NULL, + &glUsed); + used = (glUsed != 0); } } } - else - { - mapping.readWriteResources[i].bindset = -1; - mapping.readWriteResources[i].bind = -1; - mapping.readWriteResources[i].used = false; - mapping.readWriteResources[i].arraySize = 1; - } - } - - mapping.constantBlocks.resize(refl->constantBlocks.size()); - for(size_t i = 0; i < refl->constantBlocks.size(); i++) - { - if(refl->constantBlocks[i].bufferBacked) - { - GLint loc = GL.glGetUniformBlockIndex(curProg, refl->constantBlocks[i].name.c_str()); - if(loc >= 0) - { - GL.glGetActiveUniformBlockiv(curProg, loc, eGL_UNIFORM_BLOCK_BINDING, dummyReadback); - mapping.constantBlocks[i].bindset = 0; - mapping.constantBlocks[i].bind = dummyReadback[0]; - mapping.constantBlocks[i].arraySize = 1; - } - } - else - { - mapping.constantBlocks[i].bindset = -1; - mapping.constantBlocks[i].bind = -1; - mapping.constantBlocks[i].arraySize = 1; - } - - if(!refl->constantBlocks[i].bufferBacked) - { - mapping.constantBlocks[i].used = true; - } - else - { - GLuint idx = GL.glGetProgramResourceIndex(curProg, eGL_UNIFORM_BLOCK, - refl->constantBlocks[i].name.c_str()); - if(idx == GL_INVALID_INDEX) - { - mapping.constantBlocks[i].used = false; - } - else - { - GLint used = 0; - GL.glGetProgramResourceiv(curProg, eGL_UNIFORM_BLOCK, idx, 1, &refEnum[shadIdx], 1, NULL, - &used); - mapping.constantBlocks[i].used = (used != 0); - } - } - } - - GLint numVAttribBindings = 16; - GL.glGetIntegerv(eGL_MAX_VERTEX_ATTRIBS, &numVAttribBindings); - - mapping.inputAttributes.resize(numVAttribBindings); - for(int32_t i = 0; i < numVAttribBindings; i++) - mapping.inputAttributes[i] = -1; - - // override identity map with bindings - if(shadIdx == 0) - { - for(int32_t i = 0; i < refl->inputSignature.count(); i++) - { - // skip system inputs, as some drivers will return a location for them - if(refl->inputSignature[i].systemValue != ShaderBuiltin::Undefined) - continue; - - int32_t matrixRow = 0; - rdcstr varName = refl->inputSignature[i].varName; - - int32_t offs = varName.find(":col"); - if(offs >= 0) - { - matrixRow = varName[offs + 4] - '0'; - varName.resize(offs); - } - - GLint loc = GL.glGetAttribLocation(curProg, varName.c_str()); - - if(loc >= 0 && loc < numVAttribBindings) - { - mapping.inputAttributes[loc + matrixRow] = i; - } - } } #if ENABLED(RDOC_DEVEL) @@ -2763,13 +2664,15 @@ void GetBindpointMapping(GLuint curProg, int shadIdx, const ShaderReflection *re #endif } -void EvaluateSPIRVBindpointMapping(GLuint curProg, int shadIdx, const ShaderReflection *refl, - ShaderBindpointMapping &mapping) +void GetCurrentBinding(GLuint curProg, ShaderReflection *refl, const ConstantBlock &cblock, + uint32_t &slot, bool &used) { - // this is similar in principle to GetBindpointMapping - we want to look up the actual uniform - // values right now and replace the bindpoint mapping list. However for SPIR-V we can't call - // glGetUniformLocation. Instead we assume the *current* bind value is a location, and we - // overwrite it with the read uniform value. + if(refl->encoding == ShaderEncoding::OpenGLSPIRV) + { + // It's fuzzy on whether UBOs can be remapped with glUniformBlockBinding so for now we hope that + // anyone using UBOs and SPIR-V will at least specify immutable bindings in the SPIR-V. + return; + } // in case of bugs, we readback into this array instead of a single int GLint dummyReadback[32]; @@ -2779,258 +2682,50 @@ void EvaluateSPIRVBindpointMapping(GLuint curProg, int shadIdx, const ShaderRefl dummyReadback[i] = 0x6c7b8a9d; #endif - // GL_ARB_gl_spirv spec says that glBindAttribLocation does nothing on SPIR-V, so we don't have to - // remap inputAttributes. + const GLenum refEnums[] = { + eGL_REFERENCED_BY_VERTEX_SHADER, eGL_REFERENCED_BY_TESS_CONTROL_SHADER, + eGL_REFERENCED_BY_TESS_EVALUATION_SHADER, eGL_REFERENCED_BY_GEOMETRY_SHADER, + eGL_REFERENCED_BY_FRAGMENT_SHADER, eGL_REFERENCED_BY_COMPUTE_SHADER, + }; - // It's fuzzy on whether UBOs can be remapped with glUniformBlockBinding so for now we hope that - // anyone using UBOs and SPIR-V will at least specify immutable bindings in the SPIR-V. - for(size_t i = 0; i < mapping.constantBlocks.size(); i++) + const GLenum refEnum = refEnums[(uint32_t)refl->stage]; + + if(cblock.bufferBacked) { - Bindpoint &bind = mapping.constantBlocks[i]; - - if(!bind.used) - continue; - - if(bind.bind < 0) + GLint loc = GL.glGetUniformBlockIndex(curProg, cblock.name.c_str()); + if(loc >= 0) { - RDCERR("Invalid constant block binding found: '%s' = %d", - refl->constantBlocks[i].name.c_str(), bind.bind); - bind.bind = 0; + GL.glGetActiveUniformBlockiv(curProg, loc, eGL_UNIFORM_BLOCK_BINDING, dummyReadback); + slot = dummyReadback[0]; } } - - // shouldn't have any separate samplers - this is GL - RDCASSERT(mapping.samplers.size() == 0); - - // for other resources we handle textures only, other resource types are assumed to have valid fix - // binds already. Any negative inputs are locations, so get the uniform value and assign it as the - // binding index. - for(size_t i = 0; i < refl->readOnlyResources.size(); i++) + else { - if(!mapping.readOnlyResources[i].used) - continue; + slot = 0; + } - if(refl->readOnlyResources[i].isTexture && mapping.readOnlyResources[i].bind < 0) + if(!cblock.bufferBacked) + { + used = true; + } + else + { + GLuint idx = GL.glGetProgramResourceIndex(curProg, eGL_UNIFORM_BLOCK, cblock.name.c_str()); + if(idx == GL_INVALID_INDEX) { - GL.glGetUniformiv(curProg, -mapping.readOnlyResources[i].bind, dummyReadback); - mapping.readOnlyResources[i].bind = dummyReadback[0]; - - if(mapping.readOnlyResources[i].bind < 0) - { - RDCERR("Invalid uniform value retrieved: '%s' = %d", - refl->readOnlyResources[i].name.c_str(), mapping.readOnlyResources[i].bind); - mapping.readOnlyResources[i].bind = 0; - } + used = false; } else { - if(mapping.readOnlyResources[i].bind < 0) - { - RDCERR("Invalid read-only resource binding found: '%s' = %d", - refl->readOnlyResources[i].name.c_str(), mapping.readOnlyResources[i].bind); - mapping.readOnlyResources[i].bind = 0; - } + GLint glUsed = 0; + GL.glGetProgramResourceiv(curProg, eGL_UNIFORM_BLOCK, idx, 1, &refEnum, 1, NULL, &glUsed); + used = (glUsed != 0); } } - for(size_t i = 0; i < refl->readWriteResources.size(); i++) - { - if(!mapping.readWriteResources[i].used) - continue; - - if(refl->readWriteResources[i].isTexture && mapping.readWriteResources[i].bind < 0) - { - GL.glGetUniformiv(curProg, -mapping.readWriteResources[i].bind, dummyReadback); - mapping.readWriteResources[i].bind = dummyReadback[0]; - - if(mapping.readWriteResources[i].bind < 0) - { - RDCERR("Invalid uniform value retrieved: '%s' = %d", - refl->readWriteResources[i].name.c_str(), mapping.readWriteResources[i].bind); - mapping.readWriteResources[i].bind = 0; - } - } - else - { - if(mapping.readWriteResources[i].bind < 0) - { - RDCERR("Invalid read-only resource binding found: '%s' = %d", - refl->readWriteResources[i].name.c_str(), mapping.readWriteResources[i].bind); - mapping.readWriteResources[i].bind = 0; - } - } - } - - for(size_t i = 0; i < mapping.inputAttributes.size(); i++) - if(mapping.inputAttributes[i] < 0) - mapping.inputAttributes[i] = -1; - - // ensure the mapping contains a value for all valid vertex attribs, even if it doesn't use them. - GLint numVAttribBindings = 16; - GL.glGetIntegerv(eGL_MAX_VERTEX_ATTRIBS, &numVAttribBindings); - - // if more vertex attribs exist, resize and set them all to -1 - if(numVAttribBindings > mapping.inputAttributes.count()) - { - size_t prevSize = mapping.inputAttributes.size(); - mapping.inputAttributes.resize(numVAttribBindings); - for(size_t i = prevSize; i < mapping.inputAttributes.size(); i++) - mapping.inputAttributes[i] = -1; - } - #if ENABLED(RDOC_DEVEL) for(size_t i = 1; i < ARRAY_COUNT(dummyReadback); i++) if(dummyReadback[i] != 0x6c7b8a9d) RDCERR("Invalid uniform readback - data beyond first element modified!"); #endif } - -// first int - the mapping index, second int - the binding -typedef rdcarray > Permutation; - -// copy permutation by value since we mutate it to track the algorithm -static void ApplyPermutation(Permutation permutation, std::function DoSwap) -{ - // permutations can always be decomposed into a series of disjoint cycles (one or more). Think - // of - // e.g: - // - // 0 1 2 3 4 5 6 7 8 9 10 11 12 - // 8 0 4 5 2 11 1 12 6 3 10 9 7 - // - // this is multiple cycles: 0 -> 8, 8 -> 6, 6 -> 1, 1 -> 0 - // 2 -> 4, 4 -> 2 - // 3 -> 5, 5 -> 11, 11 -> 9, 9 -> 3 - // 7 -> 12, 12 -> 7 - // 10 -> 10 - // - // The general case is we just iterate along the permutation, find the first element that - // isn't in - // the right place, and then follow the cycle along - swapping the first element along into - // place - // until we eventually find that the cycle closes and we've swapped the first element into the - // right place. As we go we set the permutation values to an invalid marker so we know that - // they've been processed by a previous cycle when we continue with the iteration. - // - // This boils down to nothing in the case where the cycle is 2 long, it's just one swap. - - size_t processedIdx = permutation.size(); - - for(size_t i = 0; i < permutation.size(); i++) - { - size_t dst = permutation[i].first; - - // check if i is already in place or is already processed - if(i == dst || dst == processedIdx) - continue; - - size_t src = i; - - do - { - // do this swap - DoSwap(src, dst); - - // mark this permutation as processed - permutation[src].first = processedIdx; - - // move onto the next link in the cycle - src = dst; - dst = permutation[src].first; - - // stop when we reach the start again - we've already done the swap to put this into place - } while(dst != i); - - // close the cycle marking the last one as processed - permutation[src].first = processedIdx; - } -} - -void ResortBindings(ShaderReflection *refl, ShaderBindpointMapping *mapping) -{ - // In addition to the annoyance with texture unit handling in GL below, there's also an additional - // problem with the way bindings are handled. Nominally we have a set of bindings reflected out - // from the shader - these may come in alphabetical, declaration, location, or some other - // implementation defined order. We want a single fixed set of bindings so that the same shader - // always presents the same set of bindings to the user. However we can't use this reflected order - // as the set, because the mapping from these binds to the actual API slots used is *mutable*. If - // it were fixed at shader compile/specification time then we could sort it once after reflection - // and then go on with our lives, however because it's mutable we have to do the sort here based - // on the latest uniform values. - // - // Other alternatives would be to never sort, but then we land ourselves in a quagmire where the - // bindings could be "diffuse, normals, shadow, depthbuffer" in reflected order, but then - // depthbuffer could be assigned to slot 0 - then we are listing the textures in an arbitrary - // unsorted order. It's not possible to sort by current binding anywhere above this level because - // we don't want to do this in any of the generic code. No matter how we represent the bindings, - // this fundamentally comes down to two competing orders: The order that actually makes sense (but - // is mutable), and the order that is fixed at reflection time (but is useless). - // - // In general the hope is that no-one actually makes use of this ability to remap uniform values - // at runtime, and in practice everyone either uses the layout qualifiers in shaders to fix the - // bindings are shader compile time anyway (hah), or they reflect the samplers and set them one - // time, then leave them fixed. In the worst case, if an application does actually remap the - // uniforms from action to action, they will end up seeing the bindings re-order themselves in the - // UI. - // This might be confusing, but it's a) technically what the application is actually doing, from a - // certain perspective, and b) limited to a very small niche of people that are doing something - // kind of ridiculous. - // - // So here we re-sort the actual reflection data and bindpoint mapping so that the 'bind' is in - // ascending order. It looks ugly because it is ugly. - - if(!refl || !mapping) - return; - - Permutation permutation; - - // sort by the binding - struct permutation_sort - { - bool operator()(const rdcpair &a, const rdcpair &b) const - { - return a.second < b.second; - } - }; - - permutation.resize(mapping->readOnlyResources.size()); - for(size_t i = 0; i < mapping->readOnlyResources.size(); i++) - permutation[i] = make_rdcpair(i, mapping->readOnlyResources[i].bind); - - std::sort(permutation.begin(), permutation.end(), permutation_sort()); - - // apply the permutation to the mapping array, and update the bindPoint values in the shader - // reflection to match, so that the re-order is applied - ApplyPermutation(permutation, [mapping](size_t a, size_t b) { - std::swap(mapping->readOnlyResources[a], mapping->readOnlyResources[b]); - }); - - for(size_t i = 0; i < permutation.size(); i++) - refl->readOnlyResources[permutation[i].first].bindPoint = (int)i; - - permutation.resize(mapping->readWriteResources.size()); - for(size_t i = 0; i < mapping->readWriteResources.size(); i++) - permutation[i] = make_rdcpair(i, mapping->readWriteResources[i].bind); - - std::sort(permutation.begin(), permutation.end(), permutation_sort()); - - ApplyPermutation(permutation, [mapping](size_t a, size_t b) { - std::swap(mapping->readWriteResources[a], mapping->readWriteResources[b]); - }); - - for(size_t i = 0; i < permutation.size(); i++) - refl->readWriteResources[permutation[i].first].bindPoint = (int)i; - - permutation.resize(mapping->constantBlocks.size()); - for(size_t i = 0; i < mapping->constantBlocks.size(); i++) - permutation[i] = make_rdcpair(i, mapping->constantBlocks[i].bind); - - std::sort(permutation.begin(), permutation.end(), permutation_sort()); - - ApplyPermutation(permutation, [mapping](size_t a, size_t b) { - std::swap(mapping->constantBlocks[a], mapping->constantBlocks[b]); - }); - - for(size_t i = 0; i < permutation.size(); i++) - refl->constantBlocks[permutation[i].first].bindPoint = (int)i; -} diff --git a/renderdoc/driver/gl/wrappers/gl_emulated.cpp b/renderdoc/driver/gl/wrappers/gl_emulated.cpp index 0a0696664..b0f6b3986 100644 --- a/renderdoc/driver/gl/wrappers/gl_emulated.cpp +++ b/renderdoc/driver/gl/wrappers/gl_emulated.cpp @@ -4076,7 +4076,7 @@ GLint APIENTRY _testStub_AttribLocation(GLuint program, const GLchar *name) } void MakeOfflineShaderReflection(ShaderStage stage, const rdcstr &source, const rdcstr &entryPoint, - ShaderReflection &refl, ShaderBindpointMapping &mapping) + ShaderReflection &refl) { rdcspv::Init(); RenderDoc::Inst().RegisterShutdownFunction(&rdcspv::Shutdown); @@ -4126,8 +4126,6 @@ void MakeOfflineShaderReflection(ShaderStage stage, const rdcstr &source, const GL.glGetIntegerv = &_testStub_GetIntegerv; GL.glGetAttribLocation = &_testStub_AttribLocation; - GetBindpointMapping(fakeProg, (int)stage, &refl, mapping); - RDCEraseEl(HasExt); GL = GLDispatchTable(); GL.DriverForEmulation(NULL); @@ -4137,7 +4135,7 @@ void MakeOfflineShaderReflection(ShaderStage stage, const rdcstr &source, const // current driver. Unused by default but you can change the unit test below to call this function // instead of MakeOfflineShaderReflection. void MakeOnlineShaderReflection(ShaderStage stage, const rdcstr &source, const rdcstr &entryPoint, - ShaderReflection &refl, ShaderBindpointMapping &mapping) + ShaderReflection &refl) { RDResult status = ResultCode::APIUnsupported; IReplayDriver *driver = NULL; @@ -4171,15 +4169,6 @@ void MakeOnlineShaderReflection(ShaderStage stage, const rdcstr &source, const r refl = *driver->GetShader(ResourceId(), id, ShaderEntryPoint("main", ShaderStage::Fragment)); - // hack the mapping so that tests can skip checks of mapping when using online compilation (see - // MAPPING_VALID) - mapping.inputAttributes.resize(1); - mapping.inputAttributes[0] = 0x12345678; - - // Note that we can't fill out ShaderBindpointMapping easily on the actual driver through the - // replay interface - WARN("Using online reflection - all checks with ShaderBindpointMapping will fail"); - driver->FreeCustomShader(id); driver->Shutdown(); diff --git a/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp index 6d6245a2b..d31ed0ff9 100644 --- a/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp @@ -77,7 +77,7 @@ void WrappedOpenGL::ShaderData::ProcessSPIRVCompilation(WrappedOpenGL &drv, Reso } spirv.MakeReflection(GraphicsAPI::OpenGL, ShaderStage(ShaderIdx(type)), pEntryPoint, specInfo, - *reflection, mapping, patchData); + *reflection, patchData); version = 460; diff --git a/renderdoc/driver/shaders/dxbc/dxbc_reflect.cpp b/renderdoc/driver/shaders/dxbc/dxbc_reflect.cpp index cea8f03d8..cde6b7524 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_reflect.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_reflect.cpp @@ -142,7 +142,7 @@ static ShaderConstant MakeConstantBufferVariable(bool cbufferPacking, const DXBC static void MakeResourceList(bool srv, DXBC::DXBCContainer *dxbc, const rdcarray &in, - rdcarray &mapping, rdcarray &refl) + rdcarray &refl) { for(size_t i = 0; i < in.size(); i++) { @@ -250,8 +250,6 @@ static void MakeResourceList(bool srv, DXBC::DXBCContainer *dxbc, } } - res.bindPoint = (int32_t)i; - res.fixedBindNumber = r.reg; res.fixedBindSetOrSpace = r.space; res.bindArraySize = r.bindCount == 0 ? ~0U : r.bindCount; @@ -274,19 +272,11 @@ static void MakeResourceList(bool srv, DXBC::DXBCContainer *dxbc, : DescriptorType::ReadWriteBuffer; } - Bindpoint map; - map.arraySize = r.bindCount == 0 ? ~0U : r.bindCount; - map.bindset = r.space; - map.bind = r.reg; - map.used = true; - - mapping[i] = map; refl[i] = res; } } -void MakeShaderReflection(DXBC::DXBCContainer *dxbc, ShaderReflection *refl, - ShaderBindpointMapping *mapping) +void MakeShaderReflection(DXBC::DXBCContainer *dxbc, ShaderReflection *refl) { if(dxbc == NULL || !RenderDoc::Inst().IsReplayApp()) return; @@ -405,11 +395,6 @@ void MakeShaderReflection(DXBC::DXBCContainer *dxbc, ShaderReflection *refl, default: refl->outputTopology = Topology::Unknown; break; } - mapping->inputAttributes.resize(D3Dx_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT); - for(int s = 0; s < D3Dx_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; s++) - mapping->inputAttributes[s] = s; - - mapping->constantBlocks.resize(dxbcRefl->CBuffers.size()); refl->constantBlocks.resize(dxbcRefl->CBuffers.size()); for(size_t i = 0; i < dxbcRefl->CBuffers.size(); i++) { @@ -418,20 +403,11 @@ void MakeShaderReflection(DXBC::DXBCContainer *dxbc, ShaderReflection *refl, cb.name = dxbcRefl->CBuffers[i].name; cb.bufferBacked = true; cb.byteSize = dxbcRefl->CBuffers[i].descriptor.byteSize; - cb.bindPoint = (int32_t)i; cb.fixedBindNumber = dxbcRefl->CBuffers[i].reg; cb.fixedBindSetOrSpace = dxbcRefl->CBuffers[i].space; cb.bindArraySize = dxbcRefl->CBuffers[i].bindCount; - Bindpoint map; - map.arraySize = dxbcRefl->CBuffers[i].bindCount; - map.bindset = dxbcRefl->CBuffers[i].space; - map.bind = dxbcRefl->CBuffers[i].reg; - map.used = true; - - mapping->constantBlocks[i] = map; - cb.variables.reserve(dxbcRefl->CBuffers[i].variables.size()); for(size_t v = 0; v < dxbcRefl->CBuffers[i].variables.size(); v++) { @@ -441,36 +417,23 @@ void MakeShaderReflection(DXBC::DXBCContainer *dxbc, ShaderReflection *refl, FixupEmptyStructs(cb.variables); } - mapping->samplers.resize(dxbcRefl->Samplers.size()); refl->samplers.resize(dxbcRefl->Samplers.size()); for(size_t i = 0; i < dxbcRefl->Samplers.size(); i++) { ShaderSampler &s = refl->samplers[i]; s.name = dxbcRefl->Samplers[i].name; - s.bindPoint = (int32_t)i; s.fixedBindNumber = dxbcRefl->Samplers[i].reg; s.fixedBindSetOrSpace = dxbcRefl->Samplers[i].space; s.bindArraySize = dxbcRefl->Samplers[i].bindCount; - - Bindpoint map; - map.arraySize = 1; - map.bindset = dxbcRefl->Samplers[i].space; - map.bind = dxbcRefl->Samplers[i].reg; - map.used = true; - - mapping->samplers[i] = map; } - mapping->readOnlyResources.resize(dxbcRefl->SRVs.size()); refl->readOnlyResources.resize(dxbcRefl->SRVs.size()); - MakeResourceList(true, dxbc, dxbcRefl->SRVs, mapping->readOnlyResources, refl->readOnlyResources); + MakeResourceList(true, dxbc, dxbcRefl->SRVs, refl->readOnlyResources); - mapping->readWriteResources.resize(dxbcRefl->UAVs.size()); refl->readWriteResources.resize(dxbcRefl->UAVs.size()); - MakeResourceList(false, dxbc, dxbcRefl->UAVs, mapping->readWriteResources, - refl->readWriteResources); + MakeResourceList(false, dxbc, dxbcRefl->UAVs, refl->readWriteResources); uint32_t numInterfaces = 0; for(size_t i = 0; i < dxbcRefl->Interfaces.variables.size(); i++) diff --git a/renderdoc/driver/shaders/dxbc/dxbc_reflect.h b/renderdoc/driver/shaders/dxbc/dxbc_reflect.h index b075cf6a3..aeb948b26 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_reflect.h +++ b/renderdoc/driver/shaders/dxbc/dxbc_reflect.h @@ -30,9 +30,7 @@ class DXBCContainer; } struct ShaderReflection; -struct ShaderBindpointMapping; #define D3Dx_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT 32 -void MakeShaderReflection(DXBC::DXBCContainer *dxbc, ShaderReflection *refl, - ShaderBindpointMapping *mapping); +void MakeShaderReflection(DXBC::DXBCContainer *dxbc, ShaderReflection *refl); diff --git a/renderdoc/driver/shaders/spirv/spirv_reflect.cpp b/renderdoc/driver/shaders/spirv/spirv_reflect.cpp index 059f55c2c..27162989c 100644 --- a/renderdoc/driver/shaders/spirv/spirv_reflect.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_reflect.cpp @@ -256,36 +256,36 @@ void AddXFBAnnotations(const ShaderReflection &refl, const SPIRVPatchData &patch } } -const int32_t INVALID_BIND = -INT_MAX; +const uint32_t INVALID_BIND = ~0U; template -struct bindpair +struct sortedbind { - Bindpoint map; T bindres; rdcspv::Id id; - bindpair() = default; - bindpair(const Bindpoint &m, rdcspv::Id id, const T &res) : map(m), bindres(res) {} - bool operator<(const bindpair &o) const + sortedbind() = default; + sortedbind(rdcspv::Id id, const T &res) : bindres(res), id(id) {} + bool operator<(const sortedbind &o) const { - if(map.bindset != o.map.bindset) - return map.bindset < o.map.bindset; + if(bindres.fixedBindSetOrSpace != o.bindres.fixedBindSetOrSpace) + return bindres.fixedBindSetOrSpace < o.bindres.fixedBindSetOrSpace; // sort invalid/not set binds to the end - if(map.bind == INVALID_BIND && o.map.bind == INVALID_BIND) // equal + if(bindres.fixedBindNumber == INVALID_BIND && o.bindres.fixedBindNumber == INVALID_BIND) // equal return false; - if(map.bind == INVALID_BIND) // invalid bind not less than anything + if(bindres.fixedBindNumber == INVALID_BIND) // invalid bind not less than anything return false; - if(o.map.bind == INVALID_BIND) // anything is less than invalid bind + if(o.bindres.fixedBindNumber == INVALID_BIND) // anything is less than invalid bind return true; - return map.bind < o.map.bind; + return bindres.fixedBindNumber < o.bindres.fixedBindNumber; } }; -typedef bindpair cblockpair; -typedef bindpair shaderrespair; +typedef sortedbind sortedcblock; +typedef sortedbind sortedres; +typedef sortedbind sortedsamp; static uint32_t GetDescSet(uint32_t set) { @@ -894,8 +894,7 @@ rdcarray Reflector::EntryPoints() const void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage stage, const rdcstr &entryPoint, const rdcarray &specInfo, - ShaderReflection &reflection, ShaderBindpointMapping &mapping, - SPIRVPatchData &patchData) const + ShaderReflection &reflection, SPIRVPatchData &patchData) const { // set global properties reflection.entryPoint = entryPoint; @@ -916,8 +915,6 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st } } - bool multiEntryModule = entries.size() > 1; - if(!entry) { RDCERR("Entry point %s for stage %s not found in module", entryPoint.c_str(), @@ -1153,8 +1150,9 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st // arrays of elements, which can be appended to in any order and then sorted rdcarray inputs; rdcarray outputs; - rdcarray cblocks; - rdcarray samplers, roresources, rwresources; + rdcarray cblocks; + rdcarray samplers; + rdcarray roresources, rwresources; // for pointer types, mapping of inner type ID to index in list (assigned sequentially) SparseIdMap pointerTypes; @@ -1215,9 +1213,8 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st const bool used = usedIds.find(global.id) != usedIds.end(); - // if there are multiple entry points in this module only include signature parameters that - // are explicitly used. - if(multiEntryModule && !used) + // only include signature parameters that are explicitly used. + if(!used) continue; // we want to skip any members of the builtin interface block that are completely unused and @@ -1333,11 +1330,9 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st const DataType *varType = &dataTypes[dataTypes[global.type].InnerType()]; // if the outer type is an array, get the length and peel it off. - bool isArray = false; uint32_t arraySize = 1; if(varType->type == DataType::ArrayType) { - isArray = true; // runtime arrays have no length if(varType->length != Id()) arraySize = EvaluateConstant(varType->length, specInfo).value.u32v[0]; @@ -1358,29 +1353,31 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st if(ssbo) effectiveStorage = StorageClass::StorageBuffer; - Bindpoint bindmap; + uint32_t bindset; // set something crazy so this doesn't overlap with a real buffer binding if(pushConst) - bindmap.bindset = PushConstantBindSet; + bindset = PushConstantBindSet; else - bindmap.bindset = GetDescSet(decorations[global.id].set); + bindset = GetDescSet(decorations[global.id].set); - bindmap.bind = GetBinding(decorations[global.id].binding); + uint32_t bind = GetBinding(decorations[global.id].binding); - // On GL if we have a location and no binding, put that in as the bind. It will be overwritten - // dynamically with the actual value read from glGetUniform. This should only happen for + // On GL if we have a location and no binding, put that in as the bind. It is not used + // otherwise on GL as the bindings are dynamic. This should only happen for // bare uniforms and not for texture/buffer type uniforms which should have a binding if(sourceAPI == GraphicsAPI::OpenGL && (decorations[global.id].flags & (Decorations::HasLocation | Decorations::HasBinding)) == Decorations::HasLocation) { - bindmap.bind = -int32_t(decorations[global.id].location); + bind = decorations[global.id].location; + } + else if(sourceAPI == GraphicsAPI::OpenGL && + (decorations[global.id].flags & Decorations::HasLocation) == Decorations::NoFlags) + { + bind = ~0U; } - bindmap.arraySize = isArray ? arraySize : 1; - bindmap.used = usedIds.find(global.id) != usedIds.end(); - - if(multiEntryModule && !bindmap.used) + if(usedIds.find(global.id) == usedIds.end()) { // ignore this variable that's not in the entry point's used interface } @@ -1406,14 +1403,11 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st res.variableType.baseType = VarType::UInt; res.variableType.name = varType->name; - bindmap.bindset = 0; - bindmap.bind = GetBinding(decorations[global.id].binding); - res.fixedBindSetOrSpace = 0; res.fixedBindNumber = GetBinding(decorations[global.id].binding); - res.bindArraySize = isArray ? arraySize : 1; + res.bindArraySize = arraySize; - rwresources.push_back(shaderrespair(bindmap, global.id, res)); + rwresources.push_back(sortedres(global.id, res)); } else if(varType->IsOpaqueType()) { @@ -1421,7 +1415,7 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st // should have gotten a location // above, which will be rewritten later when looking up the pipeline state since it's // mutable from action to action in theory. - RDCASSERT(!bindmap.used || bindmap.bind != INVALID_BIND); + RDCASSERT(bind != INVALID_BIND); // opaque type - buffers, images, etc ShaderResource res; @@ -1430,17 +1424,19 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st if(res.name.empty()) res.name = StringFormat::Fmt("res%u", global.id.value()); - res.fixedBindSetOrSpace = bindmap.bindset; - res.fixedBindNumber = bindmap.bind; - res.bindArraySize = isArray ? arraySize : 1; + res.fixedBindSetOrSpace = bindset; + res.fixedBindNumber = bind; + res.bindArraySize = arraySize; if(varType->type == DataType::SamplerType) { - res.resType = TextureType::Unknown; - res.isTexture = false; - res.isReadOnly = true; + ShaderSampler samp; + samp.name = res.name; + samp.fixedBindSetOrSpace = bindset; + samp.fixedBindNumber = bind; + samp.bindArraySize = arraySize; - samplers.push_back(shaderrespair(bindmap, global.id, res)); + samplers.push_back(sortedsamp(global.id, samp)); } else { @@ -1486,7 +1482,7 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st if(!res.isTexture) res.descriptorType = DescriptorType::TypedBuffer; - roresources.push_back(shaderrespair(bindmap, global.id, res)); + roresources.push_back(sortedres(global.id, res)); } else { @@ -1494,7 +1490,7 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st if(!res.isTexture) res.descriptorType = DescriptorType::ReadWriteTypedBuffer; - rwresources.push_back(shaderrespair(bindmap, global.id, res)); + rwresources.push_back(sortedres(global.id, res)); } } } @@ -1526,7 +1522,7 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st MakeConstantBlockVariable(constant, pointerTypes, effectiveStorage, *varType, strings[global.id], decorations[global.id], specInfo); - if(isArray) + if(arraySize > 1) constant.type.elements = arraySize; else constant.type.elements = 0; @@ -1554,7 +1550,7 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st // it's push constants (which is handled elsewhere). On GL we should have gotten a // location above, which will be rewritten later when looking up the pipeline state since // it's mutable from action to action in theory. - RDCASSERT(!bindmap.used || pushConst || bindmap.bind != INVALID_BIND); + RDCASSERT(pushConst || bind != INVALID_BIND); if(ssbo) { @@ -1568,9 +1564,9 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st res.resType = TextureType::Buffer; res.descriptorType = DescriptorType::ReadWriteBuffer; - res.fixedBindNumber = bindmap.bind; - res.fixedBindSetOrSpace = bindmap.bindset; - res.bindArraySize = isArray ? arraySize : 1; + res.fixedBindNumber = bind; + res.fixedBindSetOrSpace = bindset; + res.bindArraySize = arraySize; res.variableType.columns = 0; res.variableType.rows = 0; @@ -1580,7 +1576,7 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st MakeConstantBlockVariables(effectiveStorage, *varType, 0, 0, res.variableType.members, pointerTypes, specInfo); - rwresources.push_back(shaderrespair(bindmap, global.id, res)); + rwresources.push_back(sortedres(global.id, res)); } else { @@ -1592,9 +1588,9 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st cblock.bufferBacked = !pushConst; cblock.inlineDataBytes = pushConst; - cblock.fixedBindNumber = bindmap.bind; - cblock.fixedBindSetOrSpace = bindmap.bindset; - cblock.bindArraySize = isArray ? arraySize : 1; + cblock.fixedBindNumber = bind; + cblock.fixedBindSetOrSpace = bindset; + cblock.bindArraySize = arraySize; MakeConstantBlockVariables(effectiveStorage, *varType, 0, 0, cblock.variables, pointerTypes, specInfo); @@ -1604,7 +1600,7 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st else cblock.byteSize = 0; - cblocks.push_back(cblockpair(bindmap, global.id, cblock)); + cblocks.push_back(sortedcblock(global.id, cblock)); } } } @@ -1648,19 +1644,12 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st specblock.inlineDataBytes = true; specblock.compileConstants = true; specblock.byteSize = 0; + specblock.fixedBindSetOrSpace = SpecializationConstantBindSet; // set the binding number to some huge value to try to sort it to the end specblock.fixedBindNumber = 0x8000000; + specblock.bindArraySize = 1; - Bindpoint bindmap; - - // set something crazy so this doesn't overlap with a real buffer binding - // also identify this as specialization constant data - bindmap.bindset = SpecializationConstantBindSet; - bindmap.bind = INVALID_BIND; - bindmap.arraySize = 1; - bindmap.used = true; - - cblocks.push_back(cblockpair(bindmap, Id(), specblock)); + cblocks.push_back(sortedcblock(Id(), specblock)); } if(!globalsblock.variables.empty()) @@ -1669,17 +1658,12 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st globalsblock.bufferBacked = false; globalsblock.inlineDataBytes = false; globalsblock.byteSize = (uint32_t)globalsblock.variables.size(); - globalsblock.bindPoint = (int)cblocks.size(); + globalsblock.fixedBindSetOrSpace = 0; // set the binding number to some huge value to try to sort it to the end globalsblock.fixedBindNumber = 0x8000001; + globalsblock.bindArraySize = 1; - Bindpoint bindmap; - bindmap.bindset = 0; - bindmap.bind = INVALID_BIND; - bindmap.arraySize = 1; - bindmap.used = true; - - cblocks.push_back(cblockpair(bindmap, Id(), globalsblock)); + cblocks.push_back(sortedcblock(Id(), globalsblock)); } reflection.taskPayload = taskPayloadBlock; @@ -1788,15 +1772,7 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st if(reflection.inputSignature[i].systemValue == ShaderBuiltin::Undefined) numInputs = RDCMAX(numInputs, (size_t)reflection.inputSignature[i].regIndex + 1); - mapping.inputAttributes.resize(numInputs); - for(size_t i = 0; i < numInputs; i++) - mapping.inputAttributes[i] = -1; - - for(size_t i = 0; i < reflection.inputSignature.size(); i++) - if(reflection.inputSignature[i].systemValue == ShaderBuiltin::Undefined) - mapping.inputAttributes[reflection.inputSignature[i].regIndex] = (int32_t)i; - - for(cblockpair &cb : cblocks) + for(sortedcblock &cb : cblocks) { // sort the variables within each block because we want them in offset order but they don't have // to be declared in offset order in the SPIR-V. @@ -1808,68 +1784,53 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st std::sort(roresources.begin(), roresources.end()); std::sort(rwresources.begin(), rwresources.end()); - mapping.constantBlocks.resize(cblocks.size()); reflection.constantBlocks.resize(cblocks.size()); - - mapping.samplers.resize(samplers.size()); reflection.samplers.resize(samplers.size()); - - mapping.readOnlyResources.resize(roresources.size()); reflection.readOnlyResources.resize(roresources.size()); - - mapping.readWriteResources.resize(rwresources.size()); reflection.readWriteResources.resize(rwresources.size()); for(size_t i = 0; i < cblocks.size(); i++) { - mapping.constantBlocks[i] = cblocks[i].map; patchData.cblockInterface.push_back(cblocks[i].id); + reflection.constantBlocks[i] = cblocks[i].bindres; // fix up any bind points marked with INVALID_BIND. They were sorted to the end // but from here on we want to just be able to index with the bind point // without any special casing. - if(mapping.constantBlocks[i].bind == INVALID_BIND) - mapping.constantBlocks[i].bind = 0; - reflection.constantBlocks[i] = cblocks[i].bindres; - reflection.constantBlocks[i].bindPoint = (int32_t)i; + if(reflection.constantBlocks[i].fixedBindNumber == INVALID_BIND) + reflection.constantBlocks[i].fixedBindNumber = 0; } for(size_t i = 0; i < samplers.size(); i++) { - mapping.samplers[i] = samplers[i].map; patchData.samplerInterface.push_back(samplers[i].id); + reflection.samplers[i] = samplers[i].bindres; // fix up any bind points marked with INVALID_BIND. They were sorted to the end // but from here on we want to just be able to index with the bind point // without any special casing. - if(mapping.samplers[i].bind == INVALID_BIND) - mapping.samplers[i].bind = 0; - reflection.samplers[i].name = samplers[i].bindres.name; - reflection.samplers[i].bindPoint = (int32_t)i; + if(reflection.samplers[i].fixedBindNumber == INVALID_BIND) + reflection.samplers[i].fixedBindNumber = 0; } for(size_t i = 0; i < roresources.size(); i++) { - mapping.readOnlyResources[i] = roresources[i].map; patchData.roInterface.push_back(roresources[i].id); + reflection.readOnlyResources[i] = roresources[i].bindres; // fix up any bind points marked with INVALID_BIND. They were sorted to the end // but from here on we want to just be able to index with the bind point // without any special casing. - if(mapping.readOnlyResources[i].bind == INVALID_BIND) - mapping.readOnlyResources[i].bind = 0; - reflection.readOnlyResources[i] = roresources[i].bindres; - reflection.readOnlyResources[i].bindPoint = (int32_t)i; + if(reflection.readOnlyResources[i].fixedBindNumber == INVALID_BIND) + reflection.readOnlyResources[i].fixedBindNumber = 0; } for(size_t i = 0; i < rwresources.size(); i++) { - mapping.readWriteResources[i] = rwresources[i].map; patchData.rwInterface.push_back(rwresources[i].id); + reflection.readWriteResources[i] = rwresources[i].bindres; // fix up any bind points marked with INVALID_BIND. They were sorted to the end // but from here on we want to just be able to index with the bind point // without any special casing. - if(mapping.readWriteResources[i].bind == INVALID_BIND) - mapping.readWriteResources[i].bind = 0; - reflection.readWriteResources[i] = rwresources[i].bindres; - reflection.readWriteResources[i].bindPoint = (int32_t)i; + if(reflection.readWriteResources[i].fixedBindNumber == INVALID_BIND) + reflection.readWriteResources[i].fixedBindNumber = 0; } // go through each pointer type and populate it. This may generate more pointer types so we repeat @@ -2405,7 +2366,7 @@ TEST_CASE("Validate SPIR-V reflection", "[spirv][reflection]") { ShaderType type = ShaderType::Vulkan; auto compiler = [&type](ShaderStage stage, const rdcstr &source, const rdcstr &entryPoint, - ShaderReflection &refl, ShaderBindpointMapping &mapping) { + ShaderReflection &refl) { rdcspv::Init(); RenderDoc::Inst().RegisterShutdownFunction(&rdcspv::Shutdown); @@ -2426,7 +2387,7 @@ TEST_CASE("Validate SPIR-V reflection", "[spirv][reflection]") SPIRVPatchData patchData; spv.MakeReflection(type == ShaderType::Vulkan ? GraphicsAPI::Vulkan : GraphicsAPI::OpenGL, - stage, entryPoint, {}, refl, mapping, patchData); + stage, entryPoint, {}, refl, patchData); }; // test both Vulkan and GL SPIR-V reflection diff --git a/renderdoc/driver/shaders/spirv/spirv_reflect.h b/renderdoc/driver/shaders/spirv/spirv_reflect.h index 17c66ae7c..7ca587580 100644 --- a/renderdoc/driver/shaders/spirv/spirv_reflect.h +++ b/renderdoc/driver/shaders/spirv/spirv_reflect.h @@ -32,7 +32,6 @@ enum class GraphicsAPI : uint32_t; enum class ShaderStage : uint8_t; enum class ShaderBuiltin : uint32_t; struct ShaderReflection; -struct ShaderBindpointMapping; struct SPIRVInterfaceAccess { @@ -103,9 +102,9 @@ public: rdcarray EntryPoints() const; - void MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage stage, const rdcstr &entryPoint, - const rdcarray &specInfo, ShaderReflection &reflection, - ShaderBindpointMapping &mapping, SPIRVPatchData &patchData) const; + void MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage stage, + const rdcstr &entryPoint, const rdcarray &specInfo, + ShaderReflection &reflection, SPIRVPatchData &patchData) const; private: virtual void PreParse(uint32_t maxId); diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index 7c208072e..8eac8a338 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -5145,8 +5145,6 @@ void WrappedVulkan::AddUsage(VulkanActionTreeNode &actionNode, rdcarray shaderStages; if(action.flags & ActionFlags::Dispatch) { @@ -5172,154 +5170,27 @@ void WrappedVulkan::AddUsage(VulkanActionTreeNode &actionNode, rdcarrayGetOriginalID(pipe); ResourceId origShad = GetResourceManager()->GetOriginalID(sh.module); - // 5 is the compute shader's index (VS, TCS, TES, GS, FS, CS) - const rdcarray &descSets = - (compute ? state.compute.descSets : state.graphics.descSets); - - RDCASSERT(sh.mapping); - - struct ResUsageType + for(const ConstantBlock &constantBlock : sh.refl->constantBlocks) { - ResUsageType(rdcarray &a, ResourceUsage u) : bindmap(a), usage(u) {} - rdcarray &bindmap; - ResourceUsage usage; - }; + // ignore push constants + if(!constantBlock.bufferBacked) + continue; - ResUsageType types[] = { - ResUsageType(sh.mapping->readOnlyResources, ResourceUsage::VS_Resource), - ResUsageType(sh.mapping->readWriteResources, ResourceUsage::VS_RWResource), - ResUsageType(sh.mapping->constantBlocks, ResourceUsage::VS_Constants), - }; + AddUsageForBind(actionNode, debugMessages, constantBlock.fixedBindSetOrSpace, + constantBlock.fixedBindNumber, + ResourceUsage(uint32_t(ResourceUsage::VS_Constants) + shad)); + } - DebugMessage msg; - msg.eventId = eid; - msg.category = MessageCategory::Execution; - msg.messageID = 0; - msg.source = MessageSource::IncorrectAPIUse; - msg.severity = MessageSeverity::High; - - for(size_t t = 0; t < ARRAY_COUNT(types); t++) + for(const ShaderResource &res : sh.refl->readOnlyResources) { - for(size_t i = 0; i < types[t].bindmap.size(); i++) - { - if(!types[t].bindmap[i].used) - continue; + AddUsageForBind(actionNode, debugMessages, res.fixedBindSetOrSpace, res.fixedBindNumber, + ResourceUsage(uint32_t(ResourceUsage::VS_Resource) + shad)); + } - // ignore push constants - if(t == 2 && !sh.refl->constantBlocks[i].bufferBacked) - continue; - - int32_t bindset = types[t].bindmap[i].bindset; - int32_t bind = types[t].bindmap[i].bind; - - if(bindset >= (int32_t)descSets.size() || descSets[bindset].descSet == ResourceId()) - { - msg.description = - StringFormat::Fmt("Shader referenced a descriptor set %i that was not bound", bindset); - debugMessages.push_back(msg); - continue; - } - - DescriptorSetInfo &descset = m_DescriptorSetState[descSets[bindset].descSet]; - DescSetLayout &layout = c.m_DescSetLayout[descset.layout]; - - ResourceId layoutId = GetResourceManager()->GetOriginalID(descset.layout); - - if(layout.bindings.empty()) - { - msg.description = - StringFormat::Fmt("Shader referenced a descriptor set %i that was not bound", bindset); - debugMessages.push_back(msg); - continue; - } - - if(bind >= (int32_t)layout.bindings.size()) - { - msg.description = StringFormat::Fmt( - "Shader referenced a bind %i in descriptor set %i that does not exist. Mismatched " - "descriptor set?", - bind, bindset); - debugMessages.push_back(msg); - continue; - } - - // no object to mark for usage with inline blocks - if(layout.bindings[bind].layoutDescType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) - continue; - - ResourceUsage usage = ResourceUsage(uint32_t(types[t].usage) + shad); - - if(bind >= (int32_t)descset.data.binds.size()) - { - msg.description = StringFormat::Fmt( - "Shader referenced a bind %i in descriptor set %i that does not exist. Mismatched " - "descriptor set?", - bind, bindset); - debugMessages.push_back(msg); - continue; - } - - uint32_t descriptorCount = layout.bindings[bind].descriptorCount; - if(layout.bindings[bind].variableSize) - descriptorCount = descset.data.variableDescriptorCount; - - if(descriptorCount > 1000) - { - if(!hugeRangeWarned) - RDCWARN("Skipping large, most likely 'bindless', descriptor range"); - hugeRangeWarned = true; - continue; - } - - for(uint32_t a = 0; a < descriptorCount; a++) - { - if(!descset.data.binds[bind]) - continue; - - DescriptorSetSlot &slot = descset.data.binds[bind][a]; - - // handled as part of the framebuffer attachments - if(slot.type == DescriptorSlotType::InputAttachment) - continue; - - // ignore unwritten descriptors - if(slot.type == DescriptorSlotType::Unwritten) - continue; - - // we don't mark samplers with usage - if(slot.type == DescriptorSlotType::Sampler) - continue; - - ResourceId id; - - switch(slot.type) - { - case DescriptorSlotType::CombinedImageSampler: - case DescriptorSlotType::SampledImage: - case DescriptorSlotType::StorageImage: - if(slot.resource != ResourceId()) - id = c.m_ImageView[slot.resource].image; - break; - case DescriptorSlotType::UniformTexelBuffer: - case DescriptorSlotType::StorageTexelBuffer: - if(slot.resource != ResourceId()) - id = c.m_BufferView[slot.resource].buffer; - break; - case DescriptorSlotType::UniformBuffer: - case DescriptorSlotType::UniformBufferDynamic: - case DescriptorSlotType::StorageBuffer: - case DescriptorSlotType::StorageBufferDynamic: - case DescriptorSlotType::AccelerationStructure: - if(slot.resource != ResourceId()) - id = slot.resource; - break; - default: RDCERR("Unexpected type %d", slot.type); break; - } - - if(id != ResourceId()) - actionNode.resourceUsage.push_back(make_rdcpair(id, EventUsage(eid, usage))); - } - } + for(const ShaderResource &res : sh.refl->readWriteResources) + { + AddUsageForBind(actionNode, debugMessages, res.fixedBindSetOrSpace, res.fixedBindNumber, + ResourceUsage(uint32_t(ResourceUsage::VS_RWResource) + shad)); } } @@ -5330,6 +5201,134 @@ void WrappedVulkan::AddUsage(VulkanActionTreeNode &actionNode, rdcarray &debugMessages, uint32_t bindset, + uint32_t bind, ResourceUsage usage) +{ + static bool hugeRangeWarned = false; + uint32_t eid = actionNode.action.eventId; + + const VulkanRenderState &state = m_BakedCmdBufferInfo[m_LastCmdBufferID].state; + const rdcarray &descSets = + ((actionNode.action.flags & ActionFlags::Dispatch) ? state.compute.descSets + : state.graphics.descSets); + + VulkanCreationInfo &c = m_CreationInfo; + + DebugMessage msg; + msg.eventId = eid; + msg.category = MessageCategory::Execution; + msg.messageID = 0; + msg.source = MessageSource::IncorrectAPIUse; + msg.severity = MessageSeverity::High; + + if(bindset >= descSets.size() || descSets[bindset].descSet == ResourceId()) + { + msg.description = + StringFormat::Fmt("Shader referenced a descriptor set %i that was not bound", bindset); + debugMessages.push_back(msg); + return; + } + + DescriptorSetInfo &descset = m_DescriptorSetState[descSets[bindset].descSet]; + DescSetLayout &layout = c.m_DescSetLayout[descset.layout]; + + ResourceId layoutId = GetResourceManager()->GetOriginalID(descset.layout); + + if(layout.bindings.empty()) + { + msg.description = + StringFormat::Fmt("Shader referenced a descriptor set %i that was not bound", bindset); + debugMessages.push_back(msg); + return; + } + + if(bind >= layout.bindings.size()) + { + msg.description = StringFormat::Fmt( + "Shader referenced a bind %i in descriptor set %i that does not exist. Mismatched " + "descriptor set?", + bind, bindset); + debugMessages.push_back(msg); + return; + } + + // no object to mark for usage with inline blocks + if(layout.bindings[bind].layoutDescType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) + return; + + if(bind >= descset.data.binds.size()) + { + msg.description = StringFormat::Fmt( + "Shader referenced a bind %i in descriptor set %i that does not exist. Mismatched " + "descriptor set?", + bind, bindset); + debugMessages.push_back(msg); + return; + } + + uint32_t descriptorCount = layout.bindings[bind].descriptorCount; + if(layout.bindings[bind].variableSize) + descriptorCount = descset.data.variableDescriptorCount; + + if(descriptorCount > 1000) + { + if(!hugeRangeWarned) + RDCWARN("Skipping large, most likely 'bindless', descriptor range"); + hugeRangeWarned = true; + return; + } + + for(uint32_t a = 0; a < descriptorCount; a++) + { + if(!descset.data.binds[bind]) + return; + + DescriptorSetSlot &slot = descset.data.binds[bind][a]; + + // handled as part of the framebuffer attachments + if(slot.type == DescriptorSlotType::InputAttachment) + return; + + // ignore unwritten descriptors + if(slot.type == DescriptorSlotType::Unwritten) + return; + + // we don't mark samplers with usage + if(slot.type == DescriptorSlotType::Sampler) + return; + + ResourceId id; + + switch(slot.type) + { + case DescriptorSlotType::CombinedImageSampler: + case DescriptorSlotType::SampledImage: + case DescriptorSlotType::StorageImage: + if(slot.resource != ResourceId()) + id = c.m_ImageView[slot.resource].image; + break; + case DescriptorSlotType::UniformTexelBuffer: + case DescriptorSlotType::StorageTexelBuffer: + if(slot.resource != ResourceId()) + id = c.m_BufferView[slot.resource].buffer; + break; + case DescriptorSlotType::UniformBuffer: + case DescriptorSlotType::UniformBufferDynamic: + case DescriptorSlotType::StorageBuffer: + case DescriptorSlotType::StorageBufferDynamic: + case DescriptorSlotType::AccelerationStructure: + if(slot.resource != ResourceId()) + id = slot.resource; + break; + default: RDCERR("Unexpected type %d", slot.type); break; + } + + if(id != ResourceId()) + actionNode.resourceUsage.push_back(make_rdcpair(id, EventUsage(eid, usage))); + } +} + void WrappedVulkan::AddFramebufferUsage(VulkanActionTreeNode &actionNode, const VulkanRenderState &renderState) { diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index bc8cd3f0e..575628da1 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -1119,6 +1119,9 @@ private: void AddEvent(); void AddUsage(VulkanActionTreeNode &actionNode, rdcarray &debugMessages); + void AddUsageForBind(VulkanActionTreeNode &actionNode, rdcarray &debugMessages, + uint32_t bindset, uint32_t bind, ResourceUsage usage); + void AddFramebufferUsage(VulkanActionTreeNode &actionNode, const VulkanRenderState &renderState); void AddFramebufferUsageAllChildren(VulkanActionTreeNode &actionNode, const VulkanRenderState &renderState); diff --git a/renderdoc/driver/vulkan/vk_info.cpp b/renderdoc/driver/vulkan/vk_info.cpp index 881f19947..485a92d75 100644 --- a/renderdoc/driver/vulkan/vk_info.cpp +++ b/renderdoc/driver/vulkan/vk_info.cpp @@ -832,88 +832,88 @@ void VulkanCreationInfo::Pipeline::Shader::ProcessStaticDescriptorAccess( // we will store the descriptor set in byteSize to be decoded into descriptorStore later access.byteSize = 0; - staticDescriptorAccess.reserve(staticDescriptorAccess.size() + mapping->constantBlocks.size() + - mapping->samplers.size() + mapping->readOnlyResources.size() + - mapping->readWriteResources.size()); + staticDescriptorAccess.reserve(staticDescriptorAccess.size() + refl->constantBlocks.size() + + refl->samplers.size() + refl->readOnlyResources.size() + + refl->readWriteResources.size()); - RDCASSERT(mapping->constantBlocks.size() < 0xffff, mapping->constantBlocks.size()); - for(uint16_t i = 0; i < mapping->constantBlocks.size(); i++) + RDCASSERT(refl->constantBlocks.size() < 0xffff, refl->constantBlocks.size()); + for(uint16_t i = 0; i < refl->constantBlocks.size(); i++) { - const Bindpoint &bind = mapping->constantBlocks[i]; + const ConstantBlock &bind = refl->constantBlocks[i]; // arrayed descriptors will be handled with bindless feedback - if(bind.arraySize > 1) + if(bind.bindArraySize > 1) continue; - access.staticallyUnused = !bind.used; access.type = DescriptorType::ConstantBuffer; access.index = i; - if(bind.bindset == PushConstantBindSet) + if(bind.fixedBindSetOrSpace == PushConstantBindSet) { - access.byteSize = bind.bindset; + access.byteSize = bind.fixedBindSetOrSpace; access.byteOffset = 0; staticDescriptorAccess.push_back(access); } - else if(bind.bindset == SpecializationConstantBindSet) + else if(bind.fixedBindSetOrSpace == SpecializationConstantBindSet) { - access.byteSize = bind.bindset; + access.byteSize = bind.fixedBindSetOrSpace; access.byteOffset = 0; staticDescriptorAccess.push_back(access); } else { - access.byteSize = bind.bindset; - access.byteOffset = setLayoutInfos[bind.bindset]->bindings[bind.bind].elemOffset + - setLayoutInfos[bind.bindset]->inlineByteSize; + access.byteSize = bind.fixedBindSetOrSpace; + access.byteOffset = + setLayoutInfos[bind.fixedBindSetOrSpace]->bindings[bind.fixedBindNumber].elemOffset + + setLayoutInfos[bind.fixedBindSetOrSpace]->inlineByteSize; staticDescriptorAccess.push_back(access); } } - RDCASSERT(mapping->samplers.size() < 0xffff, mapping->samplers.size()); - for(uint16_t i = 0; i < mapping->samplers.size(); i++) + RDCASSERT(refl->samplers.size() < 0xffff, refl->samplers.size()); + for(uint16_t i = 0; i < refl->samplers.size(); i++) { - const Bindpoint &bind = mapping->samplers[i]; + const ShaderSampler &bind = refl->samplers[i]; // arrayed descriptors will be handled with bindless feedback - if(bind.arraySize > 1) + if(bind.bindArraySize > 1) continue; - access.staticallyUnused = !bind.used; access.type = DescriptorType::Sampler; access.index = i; - access.byteSize = bind.bindset; - access.byteOffset = setLayoutInfos[bind.bindset]->bindings[bind.bind].elemOffset; + access.byteSize = bind.fixedBindSetOrSpace; + access.byteOffset = + setLayoutInfos[bind.fixedBindSetOrSpace]->bindings[bind.fixedBindNumber].elemOffset; staticDescriptorAccess.push_back(access); } - RDCASSERT(mapping->readOnlyResources.size() < 0xffff, mapping->readOnlyResources.size()); - for(uint16_t i = 0; i < mapping->readOnlyResources.size(); i++) + RDCASSERT(refl->readOnlyResources.size() < 0xffff, refl->readOnlyResources.size()); + for(uint16_t i = 0; i < refl->readOnlyResources.size(); i++) { - const Bindpoint &bind = mapping->readOnlyResources[i]; + const ShaderResource &bind = refl->readOnlyResources[i]; // arrayed descriptors will be handled with bindless feedback - if(bind.arraySize > 1) + if(bind.bindArraySize > 1) continue; - access.staticallyUnused = !bind.used; access.type = refl->readOnlyResources[i].descriptorType; access.index = i; - access.byteSize = bind.bindset; - access.byteOffset = setLayoutInfos[bind.bindset]->bindings[bind.bind].elemOffset; + access.byteSize = bind.fixedBindSetOrSpace; + access.byteOffset = + setLayoutInfos[bind.fixedBindSetOrSpace]->bindings[bind.fixedBindNumber].elemOffset; staticDescriptorAccess.push_back(access); } - RDCASSERT(mapping->readWriteResources.size() < 0xffff, mapping->readWriteResources.size()); - for(uint16_t i = 0; i < mapping->readWriteResources.size(); i++) + RDCASSERT(refl->readWriteResources.size() < 0xffff, refl->readWriteResources.size()); + for(uint16_t i = 0; i < refl->readWriteResources.size(); i++) { - const Bindpoint &bind = mapping->readWriteResources[i]; + const ShaderResource &bind = refl->readWriteResources[i]; // arrayed descriptors will be handled with bindless feedback - if(bind.arraySize > 1) + if(bind.bindArraySize > 1) continue; - access.staticallyUnused = !bind.used; access.type = refl->readWriteResources[i].descriptorType; access.index = i; - access.byteSize = bind.bindset; - access.byteOffset = setLayoutInfos[bind.bindset]->bindings[bind.bind].elemOffset; + access.byteSize = bind.fixedBindSetOrSpace; + access.byteOffset = + setLayoutInfos[bind.fixedBindSetOrSpace]->bindings[bind.fixedBindNumber].elemOffset; staticDescriptorAccess.push_back(access); } } @@ -1036,7 +1036,6 @@ void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan, pCreateInfo->pStages[i].stage, shad.specialization); shad.refl = reflData.refl; - shad.mapping = &reflData.mapping; shad.patchData = &reflData.patchData; } @@ -1657,7 +1656,6 @@ void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan, Vulk pCreateInfo->stage.stage, shad.specialization); shad.refl = reflData.refl; - shad.mapping = &reflData.mapping; shad.patchData = &reflData.patchData; } @@ -2444,7 +2442,7 @@ void VulkanCreationInfo::ShaderModuleReflection::Init(VulkanResourceManager *res stageIndex = StageIndex(stage); spv.MakeReflection(GraphicsAPI::Vulkan, ShaderStage(stageIndex), entryPoint, specInfo, *refl, - mapping, patchData); + patchData); refl->resourceId = resourceMan->GetOriginalID(id); } diff --git a/renderdoc/driver/vulkan/vk_info.h b/renderdoc/driver/vulkan/vk_info.h index 7ece69c36..4e1a0c57c 100644 --- a/renderdoc/driver/vulkan/vk_info.h +++ b/renderdoc/driver/vulkan/vk_info.h @@ -212,7 +212,6 @@ struct VulkanCreationInfo rdcstr entryPoint; rdcstr disassembly; ShaderReflection *refl; - ShaderBindpointMapping mapping; SPIRVPatchData patchData; std::map instructionLines; @@ -275,7 +274,6 @@ struct VulkanCreationInfo ShaderStage stage = ShaderStage::Count; rdcstr entryPoint; ShaderReflection *refl = NULL; - ShaderBindpointMapping *mapping = NULL; SPIRVPatchData *patchData = NULL; rdcarray specialization; diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index b7848dc3b..a592aaea8 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -187,7 +187,6 @@ APIProperties VulkanReplay::GetAPIProperties() ret.pipelineType = GraphicsAPI::Vulkan; ret.localRenderer = GraphicsAPI::Vulkan; ret.degraded = false; - ret.shadersMutable = false; ret.rgpCapture = (m_DriverInfo.vendor == GPUVendor::AMD || m_DriverInfo.vendor == GPUVendor::Samsung) && m_RGP != NULL && m_RGP->DriverSupportsInterop(); @@ -979,11 +978,12 @@ void VulkanReplay::GetBufferData(ResourceId buff, uint64_t offset, uint64_t len, for(size_t i = 0; i < NumShaderStages; i++) { // set up the defaults - if(p.shaders[i].mapping && p.shaders[i].refl) + if(p.shaders[i].refl) { - for(size_t cb = 0; cb < p.shaders[i].mapping->constantBlocks.size(); cb++) + for(size_t cb = 0; cb < p.shaders[i].refl->constantBlocks.size(); cb++) { - if(p.shaders[i].mapping->constantBlocks[cb].bindset == SpecializationConstantBindSet) + if(p.shaders[i].refl->constantBlocks[cb].fixedBindSetOrSpace == + SpecializationConstantBindSet) { for(const ShaderConstant &sc : p.shaders[i].refl->constantBlocks[cb].variables) { @@ -1197,8 +1197,6 @@ void VulkanReplay::SavePipelineState(uint32_t eventId) stage.entryPoint = p.shaders[i].entryPoint; stage.stage = ShaderStage::Compute; - if(p.shaders[i].mapping) - stage.bindpointMapping = *p.shaders[i].mapping; if(p.shaders[i].refl) stage.reflection = p.shaders[i].refl; @@ -1218,11 +1216,12 @@ void VulkanReplay::SavePipelineState(uint32_t eventId) stage.specializationData.clear(); // set up the defaults - if(p.shaders[i].mapping && p.shaders[i].refl) + if(p.shaders[i].refl) { - for(size_t cb = 0; cb < p.shaders[i].mapping->constantBlocks.size(); cb++) + for(size_t cb = 0; cb < p.shaders[i].refl->constantBlocks.size(); cb++) { - if(p.shaders[i].mapping->constantBlocks[cb].bindset == SpecializationConstantBindSet) + if(p.shaders[i].refl->constantBlocks[cb].fixedBindSetOrSpace == + SpecializationConstantBindSet) { for(const ShaderConstant &sc : p.shaders[i].refl->constantBlocks[cb].variables) { @@ -1329,8 +1328,6 @@ void VulkanReplay::SavePipelineState(uint32_t eventId) stages[i]->entryPoint = p.shaders[i].entryPoint; stages[i]->stage = StageFromIndex(i); - if(p.shaders[i].mapping) - stages[i]->bindpointMapping = *p.shaders[i].mapping; if(p.shaders[i].refl) stages[i]->reflection = p.shaders[i].refl; @@ -1351,11 +1348,12 @@ void VulkanReplay::SavePipelineState(uint32_t eventId) stages[i]->requiredSubgroupSize = p.shaders[i].requiredSubgroupSize; // set up the defaults - if(p.shaders[i].mapping && p.shaders[i].refl) + if(p.shaders[i].refl) { - for(size_t cb = 0; cb < p.shaders[i].mapping->constantBlocks.size(); cb++) + for(size_t cb = 0; cb < p.shaders[i].refl->constantBlocks.size(); cb++) { - if(p.shaders[i].mapping->constantBlocks[cb].bindset == SpecializationConstantBindSet) + if(p.shaders[i].refl->constantBlocks[cb].fixedBindSetOrSpace == + SpecializationConstantBindSet) { for(const ShaderConstant &sc : p.shaders[i].refl->constantBlocks[cb].variables) { @@ -2082,58 +2080,19 @@ void VulkanReplay::SavePipelineState(uint32_t eventId) for(size_t p = 0; p < ARRAY_COUNT(srcs); p++) { - bool hasUsedBinds = false; - const BindpointIndex *usedBindsData = NULL; - size_t usedBindsSize = 0; - - { - bool curCompute = (p == 1); - if(usage.valid && usage.compute == curCompute) - { - hasUsedBinds = true; - usedBindsData = usage.used.data(); - usedBindsSize = usage.used.size(); - } - - const ActionDescription *action = m_pDriver->GetAction(eventId); - if(action) - { - bool isDispatch = bool(action->flags & ActionFlags::Dispatch); - - // ifor compute stage on draws, and non-compute stages on dispatches, pretend all - // resources are dynamically unused, to prevent the lack of data from causing large arrays - // to be force-expanded - if((curCompute && !isDispatch) || (!curCompute && isDispatch)) - { - hasUsedBinds = true; - usedBindsData = NULL; - usedBindsSize = 0; - } - } - } - - BindpointIndex curBind; - for(size_t i = 0; i < srcs[p]->size(); i++) { ResourceId sourceSet = (*srcs[p])[i].descSet; - const uint32_t *srcOffset = (*srcs[p])[i].offsets.begin(); VKPipe::DescriptorSet &destSet = (*dsts[p])[i]; if(sourceSet == ResourceId()) { - destSet.inlineData.clear(); destSet.descriptorSetResourceId = ResourceId(); destSet.pushDescriptor = false; destSet.layoutResourceId = ResourceId(); - destSet.bindings.clear(); continue; } - destSet.inlineData = m_pDriver->m_DescriptorSetState[sourceSet].data.inlineBytes; - - curBind.bindset = (uint32_t)i; - ResourceId layoutId = m_pDriver->m_DescriptorSetState[sourceSet].layout; destSet.descriptorSetResourceId = rm->GetOriginalID(sourceSet); @@ -2141,111 +2100,6 @@ void VulkanReplay::SavePipelineState(uint32_t eventId) VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR); destSet.layoutResourceId = rm->GetOriginalID(layoutId); - destSet.bindings.resize(m_pDriver->m_DescriptorSetState[sourceSet].data.binds.size()); - for(size_t b = 0; b < m_pDriver->m_DescriptorSetState[sourceSet].data.binds.size(); b++) - { - DescriptorSetSlot *sourceSlots = m_pDriver->m_DescriptorSetState[sourceSet].data.binds[b]; - VKPipe::DescriptorBinding &destSlots = destSet.bindings[b]; - const DescSetLayout::Binding &layoutBind = c.m_DescSetLayout[layoutId].bindings[b]; - - curBind.bind = (uint32_t)b; - - destSlots.descriptorCount = layoutBind.descriptorCount; - - if(layoutBind.layoutDescType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) - destSlots.descriptorCount = 1; - else if(layoutBind.variableSize) - destSlots.descriptorCount = - m_pDriver->m_DescriptorSetState[sourceSet].data.variableDescriptorCount; - - destSlots.stageFlags = (ShaderStageMask)layoutBind.stageFlags; - - destSlots.firstUsedIndex = -1; - destSlots.lastUsedIndex = -1; - destSlots.dynamicallyUsedCount = 0; - - destSlots.binds.resize(destSlots.descriptorCount); - for(uint32_t a = 0; a < destSlots.descriptorCount; a++) - { - const DescriptorSetSlot &srcel = sourceSlots[a]; - VKPipe::BindingElement &dstel = destSlots.binds[a]; - - // clear it so we don't have to manually reset all elements back to normal - memset(&dstel, 0, sizeof(dstel)); - - curBind.arrayIndex = a; - - // if we have a list of used binds, and this is an array descriptor (so would be - // expected to be in the list), check it for dynamic usage. - if(destSlots.descriptorCount > 1 && hasUsedBinds) - { - // if we exhausted the list, all other elements are unused - if(usedBindsSize == 0) - { - dstel.dynamicallyUsed = false; - } - else - { - // we never saw the current value of usedBindsData (which is odd, we should have - // when iterating over all descriptors. This could only happen if there's some - // layout mismatch or a feedback bug that lead to an invalid entry in the list). - // Keep advancing until we get to one that is >= our current bind - while(curBind > *usedBindsData && usedBindsSize) - { - usedBindsData++; - usedBindsSize--; - } - - // the next used bind is equal to this one. Mark it as dynamically used, and consume - if(usedBindsSize > 0 && curBind == *usedBindsData) - { - dstel.dynamicallyUsed = true; - usedBindsData++; - usedBindsSize--; - } - // the next used bind is after the current one, this is not used. - else if(usedBindsSize > 0 && curBind < *usedBindsData) - { - dstel.dynamicallyUsed = false; - } - } - } - else - { - dstel.dynamicallyUsed = true; - } - - if(dstel.dynamicallyUsed) - { - destSlots.dynamicallyUsedCount++; - // we iterate in forward order, so we can unconditinoally set the last bind to the - // current one, and only set the first bind if we haven't encountered one before - destSlots.lastUsedIndex = a; - - if(destSlots.firstUsedIndex < 0) - destSlots.firstUsedIndex = a; - } - - if(layoutBind.immutableSampler) - dstel.immutableSampler = true; - - FillBindingElement(dstel, srcel); - - if(srcel.type == DescriptorSlotType::StorageBufferDynamic || - srcel.type == DescriptorSlotType::UniformBufferDynamic) - { - dstel.byteOffset += *srcOffset; - srcOffset++; - } - } - - // if no bindings were set these will still be negative. Set them to something sensible. - if(destSlots.firstUsedIndex < 0) - { - destSlots.firstUsedIndex = 0; - destSlots.lastUsedIndex = 0x7fffffff; - } - } } } } @@ -2308,179 +2162,6 @@ void VulkanReplay::SavePipelineState(uint32_t eventId) } } -void VulkanReplay::FillBindingElement(VKPipe::BindingElement &dstel, const DescriptorSetSlot &srcel) -{ - DescriptorSlotType descriptorType = srcel.type; - - VulkanResourceManager *rm = m_pDriver->GetResourceManager(); - VulkanCreationInfo &c = m_pDriver->m_CreationInfo; - - switch(descriptorType) - { - case DescriptorSlotType::Sampler: dstel.type = BindType::Sampler; break; - case DescriptorSlotType::CombinedImageSampler: dstel.type = BindType::ImageSampler; break; - case DescriptorSlotType::SampledImage: dstel.type = BindType::ReadOnlyImage; break; - case DescriptorSlotType::StorageImage: dstel.type = BindType::ReadWriteImage; break; - case DescriptorSlotType::UniformTexelBuffer: dstel.type = BindType::ReadOnlyTBuffer; break; - case DescriptorSlotType::StorageTexelBuffer: dstel.type = BindType::ReadWriteTBuffer; break; - case DescriptorSlotType::UniformBuffer: dstel.type = BindType::ConstantBuffer; break; - case DescriptorSlotType::StorageBuffer: - case DescriptorSlotType::AccelerationStructure: dstel.type = BindType::ReadWriteBuffer; break; - case DescriptorSlotType::UniformBufferDynamic: dstel.type = BindType::ConstantBuffer; break; - case DescriptorSlotType::StorageBufferDynamic: dstel.type = BindType::ReadWriteBuffer; break; - case DescriptorSlotType::InputAttachment: dstel.type = BindType::InputAttachment; break; - case DescriptorSlotType::InlineBlock: dstel.type = BindType::ConstantBuffer; break; - case DescriptorSlotType::Unwritten: - case DescriptorSlotType::Count: dstel.type = BindType::Unknown; break; - } - - // first handle the sampler separately because it might be in a combined descriptor - if(descriptorType == DescriptorSlotType::Sampler || - descriptorType == DescriptorSlotType::CombinedImageSampler) - { - if(srcel.sampler != ResourceId()) - { - dstel.samplerResourceId = srcel.sampler; - - const VulkanCreationInfo::Sampler &sampl = c.m_Sampler[dstel.samplerResourceId]; - - dstel.samplerResourceId = rm->GetOriginalID(dstel.samplerResourceId); - - // sampler info - dstel.filter = - MakeFilter(sampl.minFilter, sampl.magFilter, sampl.mipmapMode, - sampl.maxAnisotropy >= 1.0f, sampl.compareEnable, sampl.reductionMode); - dstel.addressU = MakeAddressMode(sampl.address[0]); - dstel.addressV = MakeAddressMode(sampl.address[1]); - dstel.addressW = MakeAddressMode(sampl.address[2]); - dstel.mipBias = sampl.mipLodBias; - dstel.maxAnisotropy = sampl.maxAnisotropy; - dstel.compareFunction = MakeCompareFunc(sampl.compareOp); - dstel.minLOD = sampl.minLod; - dstel.maxLOD = sampl.maxLod; - MakeBorderColor(sampl.borderColor, dstel.borderColorValue.floatValue); - dstel.borderColorType = CompType::Float; - dstel.unnormalized = sampl.unnormalizedCoordinates; - dstel.seamless = sampl.seamless; - - if(sampl.ycbcr != ResourceId()) - { - const VulkanCreationInfo::YCbCrSampler &ycbcr = c.m_YCbCrSampler[sampl.ycbcr]; - dstel.ycbcrSampler = rm->GetOriginalID(sampl.ycbcr); - - dstel.ycbcrModel = ycbcr.ycbcrModel; - dstel.ycbcrRange = ycbcr.ycbcrRange; - Convert(dstel.samplerSwizzle, ycbcr.componentMapping); - dstel.xChromaOffset = ycbcr.xChromaOffset; - dstel.yChromaOffset = ycbcr.yChromaOffset; - dstel.chromaFilter = ycbcr.chromaFilter; - dstel.forceExplicitReconstruction = ycbcr.forceExplicitReconstruction; - } - else - { - Convert(dstel.samplerSwizzle, sampl.componentMapping); - dstel.srgbBorder = sampl.srgbBorder; - } - - if(sampl.customBorder) - { - if(sampl.borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT) - { - dstel.borderColorValue.uintValue = sampl.customBorderColor.uint32; - dstel.borderColorType = CompType::UInt; - } - else - { - dstel.borderColorValue.floatValue = sampl.customBorderColor.float32; - } - } - } - } - - // now look at the 'base' type. Sampler is excluded from these ifs - if(descriptorType == DescriptorSlotType::SampledImage || - descriptorType == DescriptorSlotType::CombinedImageSampler || - descriptorType == DescriptorSlotType::InputAttachment || - descriptorType == DescriptorSlotType::StorageImage) - { - ResourceId viewid = srcel.resource; - - if(viewid != ResourceId()) - { - dstel.viewResourceId = rm->GetOriginalID(viewid); - dstel.resourceResourceId = rm->GetOriginalID(c.m_ImageView[viewid].image); - dstel.viewFormat = MakeResourceFormat(c.m_ImageView[viewid].format); - - Convert(dstel.swizzle, c.m_ImageView[viewid].componentMapping); - dstel.firstMip = c.m_ImageView[viewid].range.baseMipLevel; - dstel.firstSlice = c.m_ImageView[viewid].range.baseArrayLayer; - dstel.numMips = c.m_ImageView[viewid].range.levelCount; - dstel.numSlices = c.m_ImageView[viewid].range.layerCount; - - if(c.m_ImageView[viewid].viewType == VK_IMAGE_VIEW_TYPE_3D) - dstel.firstSlice = dstel.numSlices = 0; - - // cheeky hack, store image layout enum in byteOffset as it's not used for images - dstel.byteOffset = convert(srcel.imageLayout); - - dstel.minLOD = c.m_ImageView[viewid].minLOD; - } - else - { - dstel.viewResourceId = ResourceId(); - dstel.resourceResourceId = ResourceId(); - dstel.firstMip = 0; - dstel.firstSlice = 0; - dstel.numMips = 1; - dstel.numSlices = 1; - dstel.minLOD = 0.0f; - } - } - else if(descriptorType == DescriptorSlotType::UniformTexelBuffer || - descriptorType == DescriptorSlotType::StorageTexelBuffer) - { - ResourceId viewid = srcel.resource; - - if(viewid != ResourceId()) - { - dstel.viewResourceId = rm->GetOriginalID(viewid); - dstel.resourceResourceId = rm->GetOriginalID(c.m_BufferView[viewid].buffer); - dstel.byteOffset = c.m_BufferView[viewid].offset; - dstel.viewFormat = MakeResourceFormat(c.m_BufferView[viewid].format); - dstel.byteSize = c.m_BufferView[viewid].size; - } - else - { - dstel.viewResourceId = ResourceId(); - dstel.resourceResourceId = ResourceId(); - dstel.byteOffset = 0; - dstel.byteSize = 0; - } - } - else if(descriptorType == DescriptorSlotType::InlineBlock) - { - dstel.viewResourceId = ResourceId(); - dstel.resourceResourceId = ResourceId(); - dstel.inlineBlock = true; - dstel.byteOffset = srcel.offset; - dstel.byteSize = srcel.range; - } - else if(descriptorType == DescriptorSlotType::StorageBuffer || - descriptorType == DescriptorSlotType::StorageBufferDynamic || - descriptorType == DescriptorSlotType::UniformBuffer || - descriptorType == DescriptorSlotType::UniformBufferDynamic || - descriptorType == DescriptorSlotType::AccelerationStructure) - { - dstel.viewResourceId = ResourceId(); - - if(srcel.resource != ResourceId()) - dstel.resourceResourceId = rm->GetOriginalID(srcel.resource); - - dstel.byteOffset = srcel.offset; - dstel.byteSize = srcel.GetRange(); - } -} - void VulkanReplay::FillSamplerDescriptor(SamplerDescriptor &dstel, const DescriptorSetSlot &srcel) { VulkanResourceManager *rm = m_pDriver->GetResourceManager(); @@ -3032,7 +2713,6 @@ void VulkanReplay::FillCBufferVariables(ResourceId pipeline, ResourceId shader, } ShaderReflection &refl = *it->second.GetReflection(stage, entryPoint, pipeline).refl; - ShaderBindpointMapping &mapping = it->second.GetReflection(stage, entryPoint, pipeline).mapping; if(cbufSlot >= (uint32_t)refl.constantBlocks.count()) { @@ -3048,27 +2728,26 @@ void VulkanReplay::FillCBufferVariables(ResourceId pipeline, ResourceId shader, (refl.stage == ShaderStage::Compute) ? m_pDriver->m_RenderState.compute.descSets : m_pDriver->m_RenderState.graphics.descSets; - Bindpoint bind = mapping.constantBlocks[c.bindPoint]; - - if(bind.bindset < descSets.count()) + if(c.fixedBindSetOrSpace < descSets.size()) { - ResourceId set = descSets[bind.bindset].descSet; + ResourceId set = descSets[c.fixedBindSetOrSpace].descSet; const WrappedVulkan::DescriptorSetInfo &setData = m_pDriver->m_DescriptorSetState[set]; ResourceId layoutId = setData.layout; - if(bind.bind < m_pDriver->m_CreationInfo.m_DescSetLayout[layoutId].bindings.count()) + if(c.fixedBindNumber < m_pDriver->m_CreationInfo.m_DescSetLayout[layoutId].bindings.size()) { const DescSetLayout::Binding &layoutBind = - m_pDriver->m_CreationInfo.m_DescSetLayout[layoutId].bindings[bind.bind]; + m_pDriver->m_CreationInfo.m_DescSetLayout[layoutId].bindings[c.fixedBindNumber]; if(layoutBind.layoutDescType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) { bytebuf inlineData; - inlineData.assign(setData.data.inlineBytes.data() + setData.data.binds[bind.bind]->offset, - layoutBind.variableSize ? setData.data.variableDescriptorCount - : layoutBind.descriptorCount); + inlineData.assign( + setData.data.inlineBytes.data() + setData.data.binds[c.fixedBindNumber]->offset, + layoutBind.variableSize ? setData.data.variableDescriptorCount + : layoutBind.descriptorCount); StandardFillCBufferVariables(refl.resourceId, c.variables, outvars, inlineData); return; } @@ -3080,7 +2759,7 @@ void VulkanReplay::FillCBufferVariables(ResourceId pipeline, ResourceId shader, else { // specialised path to display specialization constants - if(mapping.constantBlocks[c.bindPoint].bindset == SpecializationConstantBindSet) + if(c.fixedBindSetOrSpace == SpecializationConstantBindSet) { auto pipeIt = m_pDriver->m_CreationInfo.m_Pipeline.find(pipeline); diff --git a/renderdoc/driver/vulkan/vk_replay.h b/renderdoc/driver/vulkan/vk_replay.h index fcb31fabd..1726903c4 100644 --- a/renderdoc/driver/vulkan/vk_replay.h +++ b/renderdoc/driver/vulkan/vk_replay.h @@ -255,7 +255,6 @@ struct VulkanPostVSData struct VKDynamicShaderFeedback { bool compute = false, valid = false; - rdcarray used; rdcarray access; rdcarray messages; }; @@ -497,7 +496,6 @@ private: bool FetchShaderFeedback(uint32_t eventId); void ClearFeedbackCache(); - void FillBindingElement(VKPipe::BindingElement &dstel, const DescriptorSetSlot &srcel); void FillDescriptor(Descriptor &dstel, const DescriptorSetSlot &srcel); void FillSamplerDescriptor(SamplerDescriptor &dstel, const DescriptorSetSlot &srcel); diff --git a/renderdoc/driver/vulkan/vk_shader_feedback.cpp b/renderdoc/driver/vulkan/vk_shader_feedback.cpp index 77756c1a0..39c128a81 100644 --- a/renderdoc/driver/vulkan/vk_shader_feedback.cpp +++ b/renderdoc/driver/vulkan/vk_shader_feedback.cpp @@ -2161,43 +2161,14 @@ bool VulkanReplay::FetchShaderFeedback(uint32_t eventId) { uint32_t *readbackData = (uint32_t *)(data.data() + it->second.offset); - BindpointIndex used; - - ShaderReflection *refl = stageRefls[(uint32_t)it->first.stage]; - if(refl) - { - if(it->first.index.category == DescriptorCategory::ConstantBlock) - { - used.bindset = refl->constantBlocks[it->first.index.index].fixedBindSetOrSpace; - used.bind = refl->constantBlocks[it->first.index.index].fixedBindNumber; - } - else if(it->first.index.category == DescriptorCategory::Sampler) - { - used.bindset = refl->samplers[it->first.index.index].fixedBindSetOrSpace; - used.bind = refl->samplers[it->first.index.index].fixedBindNumber; - } - else if(it->first.index.category == DescriptorCategory::ReadOnlyResource) - { - used.bindset = refl->readOnlyResources[it->first.index.index].fixedBindSetOrSpace; - used.bind = refl->readOnlyResources[it->first.index.index].fixedBindNumber; - } - else if(it->first.index.category == DescriptorCategory::ReadWriteResource) - { - used.bindset = refl->readWriteResources[it->first.index.index].fixedBindSetOrSpace; - used.bind = refl->readWriteResources[it->first.index.index].fixedBindNumber; - } - } - DescriptorAccess access = it->second.access; for(uint32_t i = 0; i < it->second.numEntries; i++) { if(readbackData[i]) { - used.arrayIndex = i; access.arrayElement = i; - result.used.push_back(used); result.access.push_back(access); } diff --git a/renderdoc/replay/renderdoc_serialise.inl b/renderdoc/replay/renderdoc_serialise.inl index c540b2000..06bbfcecd 100644 --- a/renderdoc/replay/renderdoc_serialise.inl +++ b/renderdoc/replay/renderdoc_serialise.inl @@ -119,29 +119,6 @@ void DoSerialise(SerialiserType &ser, ResourceFormat &el) SIZE_CHECK(6); } -template -void DoSerialise(SerialiserType &ser, Bindpoint &el) -{ - SERIALISE_MEMBER(bindset); - SERIALISE_MEMBER(bind); - SERIALISE_MEMBER(arraySize); - SERIALISE_MEMBER(used); - - SIZE_CHECK(16); -} - -template -void DoSerialise(SerialiserType &ser, ShaderBindpointMapping &el) -{ - SERIALISE_MEMBER(inputAttributes); - SERIALISE_MEMBER(constantBlocks); - SERIALISE_MEMBER(samplers); - SERIALISE_MEMBER(readOnlyResources); - SERIALISE_MEMBER(readWriteResources); - - SIZE_CHECK(120); -} - template void DoSerialise(SerialiserType &ser, SigParameter &el) { @@ -197,7 +174,6 @@ void DoSerialise(SerialiserType &ser, ConstantBlock &el) { SERIALISE_MEMBER(name); SERIALISE_MEMBER(variables); - SERIALISE_MEMBER(bindPoint); SERIALISE_MEMBER(fixedBindNumber); SERIALISE_MEMBER(fixedBindSetOrSpace); SERIALISE_MEMBER(bindArraySize); @@ -212,7 +188,6 @@ template void DoSerialise(SerialiserType &ser, ShaderSampler &el) { SERIALISE_MEMBER(name); - SERIALISE_MEMBER(bindPoint); SERIALISE_MEMBER(fixedBindNumber); SERIALISE_MEMBER(fixedBindSetOrSpace); SERIALISE_MEMBER(bindArraySize); @@ -227,7 +202,6 @@ void DoSerialise(SerialiserType &ser, ShaderResource &el) SERIALISE_MEMBER(descriptorType); SERIALISE_MEMBER(name); SERIALISE_MEMBER(variableType); - SERIALISE_MEMBER(bindPoint); SERIALISE_MEMBER(fixedBindNumber); SERIALISE_MEMBER(fixedBindSetOrSpace); SERIALISE_MEMBER(bindArraySize); @@ -236,7 +210,7 @@ void DoSerialise(SerialiserType &ser, ShaderResource &el) SERIALISE_MEMBER(isInputAttachment); SERIALISE_MEMBER(isReadOnly); - SIZE_CHECK(128); + SIZE_CHECK(120); } template @@ -508,7 +482,6 @@ void DoSerialise(SerialiserType &ser, APIProperties &el) SERIALISE_MEMBER(localRenderer); SERIALISE_MEMBER(vendor); SERIALISE_MEMBER(degraded); - SERIALISE_MEMBER(shadersMutable); SERIALISE_MEMBER(shaderDebugging); SERIALISE_MEMBER(pixelHistory); @@ -1316,49 +1289,16 @@ void DoSerialise(SerialiserType &ser, D3D11Pipe::View &el) SIZE_CHECK(72); } -template -void DoSerialise(SerialiserType &ser, D3D11Pipe::Sampler &el) -{ - SERIALISE_MEMBER(resourceId); - SERIALISE_MEMBER(addressU); - SERIALISE_MEMBER(addressV); - SERIALISE_MEMBER(addressW); - SERIALISE_MEMBER(borderColor); - SERIALISE_MEMBER(compareFunction); - SERIALISE_MEMBER(filter); - SERIALISE_MEMBER(maxAnisotropy); - SERIALISE_MEMBER(maxLOD); - SERIALISE_MEMBER(minLOD); - SERIALISE_MEMBER(mipLODBias); - - SIZE_CHECK(56); -} - -template -void DoSerialise(SerialiserType &ser, D3D11Pipe::ConstantBuffer &el) -{ - SERIALISE_MEMBER(resourceId); - SERIALISE_MEMBER(vecOffset); - SERIALISE_MEMBER(vecCount); - - SIZE_CHECK(16); -} - template void DoSerialise(SerialiserType &ser, D3D11Pipe::Shader &el) { SERIALISE_MEMBER(resourceId); // don't serialise reflection, just set it to NULL. See the definition of SERIALISE_MEMBER_DUMMY SERIALISE_MEMBER_OPT_EMPTY(reflection); - SERIALISE_MEMBER(bindpointMapping); SERIALISE_MEMBER(stage); - SERIALISE_MEMBER(srvs); - SERIALISE_MEMBER(uavs); - SERIALISE_MEMBER(samplers); - SERIALISE_MEMBER(constantBuffers); SERIALISE_MEMBER(classInstances); - SIZE_CHECK(264); + SIZE_CHECK(48); } template @@ -1443,12 +1383,11 @@ void DoSerialise(SerialiserType &ser, D3D11Pipe::OutputMerger &el) SERIALISE_MEMBER(blendState); SERIALISE_MEMBER(renderTargets); SERIALISE_MEMBER(uavStartSlot); - SERIALISE_MEMBER(uavs); SERIALISE_MEMBER(depthTarget); SERIALISE_MEMBER(depthReadOnly); SERIALISE_MEMBER(stencilReadOnly); - SIZE_CHECK(272); + SIZE_CHECK(248); } template @@ -1484,7 +1423,7 @@ void DoSerialise(SerialiserType &ser, D3D11Pipe::State &el) SERIALISE_MEMBER(predication); - SIZE_CHECK(2104); + SIZE_CHECK(784); } #pragma endregion D3D11 pipeline state @@ -1540,24 +1479,6 @@ void DoSerialise(SerialiserType &ser, D3D12Pipe::InputAssembly &el) SIZE_CHECK(80); } -template -void DoSerialise(SerialiserType &ser, D3D12Pipe::RootSignatureRange &el) -{ - SERIALISE_MEMBER(immediate); - SERIALISE_MEMBER(rootSignatureIndex); - SERIALISE_MEMBER(type); - SERIALISE_MEMBER(visibility); - SERIALISE_MEMBER(registerSpace); - SERIALISE_MEMBER(dynamicallyUsedCount); - SERIALISE_MEMBER(firstUsedIndex); - SERIALISE_MEMBER(lastUsedIndex); - SERIALISE_MEMBER(constantBuffers); - SERIALISE_MEMBER(samplers); - SERIALISE_MEMBER(views); - - SIZE_CHECK(104); -} - template void DoSerialise(SerialiserType &ser, D3D12Pipe::View &el) { @@ -1587,51 +1508,15 @@ void DoSerialise(SerialiserType &ser, D3D12Pipe::View &el) SIZE_CHECK(72); } - -template -void DoSerialise(SerialiserType &ser, D3D12Pipe::Sampler &el) -{ - SERIALISE_MEMBER(bind); - SERIALISE_MEMBER(tableIndex); - SERIALISE_MEMBER(addressU); - SERIALISE_MEMBER(addressV); - SERIALISE_MEMBER(addressW); - SERIALISE_MEMBER(borderColorValue); - SERIALISE_MEMBER(borderColorType); - SERIALISE_MEMBER(unnormalized); - SERIALISE_MEMBER(compareFunction); - SERIALISE_MEMBER(filter); - SERIALISE_MEMBER(maxAnisotropy); - SERIALISE_MEMBER(maxLOD); - SERIALISE_MEMBER(minLOD); - SERIALISE_MEMBER(mipLODBias); - - SIZE_CHECK(52); -} - -template -void DoSerialise(SerialiserType &ser, D3D12Pipe::ConstantBuffer &el) -{ - SERIALISE_MEMBER(bind); - SERIALISE_MEMBER(tableIndex); - SERIALISE_MEMBER(resourceId); - SERIALISE_MEMBER(byteOffset); - SERIALISE_MEMBER(byteSize); - SERIALISE_MEMBER(rootValues); - - SIZE_CHECK(56); -} - template void DoSerialise(SerialiserType &ser, D3D12Pipe::Shader &el) { SERIALISE_MEMBER(resourceId); // don't serialise reflection, just set it to NULL. See the definition of SERIALISE_MEMBER_DUMMY SERIALISE_MEMBER_OPT_EMPTY(reflection); - SERIALISE_MEMBER(bindpointMapping); SERIALISE_MEMBER(stage); - SIZE_CHECK(144); + SIZE_CHECK(24); } template @@ -1753,7 +1638,6 @@ void DoSerialise(SerialiserType &ser, D3D12Pipe::State &el) SERIALISE_MEMBER(pipelineResourceId); SERIALISE_MEMBER(rootSignatureResourceId); SERIALISE_MEMBER(descriptorHeaps); - SERIALISE_MEMBER(rootElements); SERIALISE_MEMBER(inputAssembly); @@ -1774,7 +1658,7 @@ void DoSerialise(SerialiserType &ser, D3D12Pipe::State &el) SERIALISE_MEMBER(resourceStates); - SIZE_CHECK(1704); + SIZE_CHECK(720); } #pragma endregion D3D12 pipeline state @@ -1830,12 +1714,11 @@ void DoSerialise(SerialiserType &ser, GLPipe::Shader &el) // don't serialise reflection, just set it to NULL. See the definition of SERIALISE_MEMBER_DUMMY SERIALISE_MEMBER_OPT_EMPTY(reflection); - SERIALISE_MEMBER(bindpointMapping); SERIALISE_MEMBER(stage); SERIALISE_MEMBER(subroutines); - SIZE_CHECK(176); + SIZE_CHECK(56); } template @@ -1851,21 +1734,6 @@ void DoSerialise(SerialiserType &ser, GLPipe::FixedVertexProcessing &el) SIZE_CHECK(36); } -template -void DoSerialise(SerialiserType &ser, GLPipe::Texture &el) -{ - SERIALISE_MEMBER(resourceId); - SERIALISE_MEMBER(firstMip); - SERIALISE_MEMBER(numMips); - SERIALISE_MEMBER(type); - SERIALISE_MEMBER(swizzle); - SERIALISE_MEMBER(depthReadChannel); - SERIALISE_MEMBER(completeStatus); - SERIALISE_MEMBER(typeConflict); - - SIZE_CHECK(80); -} - template void DoSerialise(SerialiserType &ser, GLPipe::TextureCompleteness &el) { @@ -1876,50 +1744,6 @@ void DoSerialise(SerialiserType &ser, GLPipe::TextureCompleteness &el) SIZE_CHECK(56); } -template -void DoSerialise(SerialiserType &ser, GLPipe::Sampler &el) -{ - SERIALISE_MEMBER(resourceId); - SERIALISE_MEMBER(addressS); - SERIALISE_MEMBER(addressT); - SERIALISE_MEMBER(addressR); - SERIALISE_MEMBER(borderColor); - SERIALISE_MEMBER(compareFunction); - SERIALISE_MEMBER(filter); - SERIALISE_MEMBER(seamlessCubeMap); - SERIALISE_MEMBER(maxAnisotropy); - SERIALISE_MEMBER(maxLOD); - SERIALISE_MEMBER(minLOD); - SERIALISE_MEMBER(mipLODBias); - - SIZE_CHECK(56); -} - -template -void DoSerialise(SerialiserType &ser, GLPipe::Buffer &el) -{ - SERIALISE_MEMBER(resourceId); - SERIALISE_MEMBER(byteOffset); - SERIALISE_MEMBER(byteSize); - - SIZE_CHECK(24); -} - -template -void DoSerialise(SerialiserType &ser, GLPipe::ImageLoadStore &el) -{ - SERIALISE_MEMBER(resourceId); - SERIALISE_MEMBER(mipLevel); - SERIALISE_MEMBER(layered); - SERIALISE_MEMBER(slice); - SERIALISE_MEMBER(type); - SERIALISE_MEMBER(readAllowed); - SERIALISE_MEMBER(writeAllowed); - SERIALISE_MEMBER(imageFormat); - - SIZE_CHECK(32); -} - template void DoSerialise(SerialiserType &ser, GLPipe::Feedback &el) { @@ -2072,13 +1896,6 @@ void DoSerialise(SerialiserType &ser, GLPipe::State &el) SERIALISE_MEMBER(vertexProcessing); - SERIALISE_MEMBER(textures); - SERIALISE_MEMBER(samplers); - SERIALISE_MEMBER(atomicBuffers); - SERIALISE_MEMBER(uniformBuffers); - SERIALISE_MEMBER(shaderStorageBuffers); - SERIALISE_MEMBER(images); - SERIALISE_MEMBER(descriptorStore); SERIALISE_MEMBER(descriptorCount); SERIALISE_MEMBER(descriptorByteSize); @@ -2094,73 +1911,13 @@ void DoSerialise(SerialiserType &ser, GLPipe::State &el) SERIALISE_MEMBER(hints); - SIZE_CHECK(1992); + SIZE_CHECK(1128); } #pragma endregion OpenGL pipeline state #pragma region Vulkan pipeline state -template -void DoSerialise(SerialiserType &ser, VKPipe::BindingElement &el) -{ - SERIALISE_MEMBER(type); - SERIALISE_MEMBER(viewResourceId); - SERIALISE_MEMBER(resourceResourceId); - SERIALISE_MEMBER(samplerResourceId); - SERIALISE_MEMBER(immutableSampler); - SERIALISE_MEMBER(dynamicallyUsed); - SERIALISE_MEMBER(viewFormat); - SERIALISE_MEMBER(swizzle); - SERIALISE_MEMBER(firstMip); - SERIALISE_MEMBER(numMips); - SERIALISE_MEMBER(firstSlice); - SERIALISE_MEMBER(numSlices); - - SERIALISE_MEMBER(byteOffset); - SERIALISE_MEMBER(byteSize); - - SERIALISE_MEMBER(filter); - SERIALISE_MEMBER(addressU); - SERIALISE_MEMBER(addressV); - SERIALISE_MEMBER(addressW); - SERIALISE_MEMBER(mipBias); - SERIALISE_MEMBER(maxAnisotropy); - SERIALISE_MEMBER(compareFunction); - SERIALISE_MEMBER(minLOD); - SERIALISE_MEMBER(maxLOD); - SERIALISE_MEMBER(borderColorValue); - SERIALISE_MEMBER(borderColorType); - SERIALISE_MEMBER(samplerSwizzle); - SERIALISE_MEMBER(unnormalized); - SERIALISE_MEMBER(inlineBlock); - - SERIALISE_MEMBER(ycbcrSampler); - - SERIALISE_MEMBER(ycbcrModel); - SERIALISE_MEMBER(ycbcrRange); - SERIALISE_MEMBER(xChromaOffset); - SERIALISE_MEMBER(yChromaOffset); - SERIALISE_MEMBER(chromaFilter); - SERIALISE_MEMBER(forceExplicitReconstruction); - - SIZE_CHECK(152); -}; - -template -void DoSerialise(SerialiserType &ser, VKPipe::DescriptorBinding &el) -{ - SERIALISE_MEMBER(descriptorCount); - SERIALISE_MEMBER(dynamicallyUsedCount); - SERIALISE_MEMBER(firstUsedIndex); - SERIALISE_MEMBER(lastUsedIndex); - SERIALISE_MEMBER(stageFlags); - - SERIALISE_MEMBER(binds); - - SIZE_CHECK(48); -} - template void DoSerialise(SerialiserType &ser, VKPipe::DynamicOffset &el) { @@ -2177,13 +1934,9 @@ void DoSerialise(SerialiserType &ser, VKPipe::DescriptorSet &el) SERIALISE_MEMBER(descriptorSetResourceId); SERIALISE_MEMBER(pushDescriptor); - SERIALISE_MEMBER(bindings); - - SERIALISE_MEMBER(inlineData); - SERIALISE_MEMBER(dynamicOffsets); - SIZE_CHECK(96); + SIZE_CHECK(48); } template @@ -2270,7 +2023,6 @@ void DoSerialise(SerialiserType &ser, VKPipe::Shader &el) // don't serialise reflection, just set it to NULL. See the definition of SERIALISE_MEMBER_DUMMY SERIALISE_MEMBER_OPT_EMPTY(reflection); - SERIALISE_MEMBER(bindpointMapping); SERIALISE_MEMBER(stage); SERIALISE_MEMBER(pushConstantRangeByteOffset); @@ -2278,7 +2030,7 @@ void DoSerialise(SerialiserType &ser, VKPipe::Shader &el) SERIALISE_MEMBER(specializationData); SERIALISE_MEMBER(specializationIds); - SIZE_CHECK(224); + SIZE_CHECK(104); } template @@ -2556,7 +2308,7 @@ void DoSerialise(SerialiserType &ser, VKPipe::State &el) SERIALISE_MEMBER(conditionalRendering); - SIZE_CHECK(2704); + SIZE_CHECK(1744); } #pragma endregion Vulkan pipeline state @@ -2566,8 +2318,6 @@ INSTANTIATE_SERIALISE_TYPE(SectionProperties) INSTANTIATE_SERIALISE_TYPE(EnvironmentModification) INSTANTIATE_SERIALISE_TYPE(CaptureOptions) INSTANTIATE_SERIALISE_TYPE(ResourceFormat) -INSTANTIATE_SERIALISE_TYPE(Bindpoint) -INSTANTIATE_SERIALISE_TYPE(ShaderBindpointMapping) INSTANTIATE_SERIALISE_TYPE(SigParameter) INSTANTIATE_SERIALISE_TYPE(ShaderConstantType) INSTANTIATE_SERIALISE_TYPE(ShaderConstant) @@ -2630,16 +2380,12 @@ INSTANTIATE_SERIALISE_TYPE(DescriptorLogicalLocation) INSTANTIATE_SERIALISE_TYPE(D3D11Pipe::Layout) INSTANTIATE_SERIALISE_TYPE(D3D11Pipe::InputAssembly) INSTANTIATE_SERIALISE_TYPE(D3D11Pipe::View) -INSTANTIATE_SERIALISE_TYPE(D3D11Pipe::Sampler) INSTANTIATE_SERIALISE_TYPE(D3D11Pipe::Shader) INSTANTIATE_SERIALISE_TYPE(D3D11Pipe::Rasterizer) INSTANTIATE_SERIALISE_TYPE(D3D11Pipe::OutputMerger) INSTANTIATE_SERIALISE_TYPE(D3D11Pipe::State) INSTANTIATE_SERIALISE_TYPE(D3D12Pipe::Layout) INSTANTIATE_SERIALISE_TYPE(D3D12Pipe::InputAssembly) -INSTANTIATE_SERIALISE_TYPE(D3D12Pipe::RootSignatureRange) -INSTANTIATE_SERIALISE_TYPE(D3D12Pipe::ConstantBuffer) -INSTANTIATE_SERIALISE_TYPE(D3D12Pipe::Sampler) INSTANTIATE_SERIALISE_TYPE(D3D12Pipe::View) INSTANTIATE_SERIALISE_TYPE(D3D12Pipe::Shader) INSTANTIATE_SERIALISE_TYPE(D3D12Pipe::Rasterizer) @@ -2650,8 +2396,6 @@ INSTANTIATE_SERIALISE_TYPE(D3D12Pipe::State) INSTANTIATE_SERIALISE_TYPE(GLPipe::VertexAttribute) INSTANTIATE_SERIALISE_TYPE(GLPipe::VertexInput) INSTANTIATE_SERIALISE_TYPE(GLPipe::Shader) -INSTANTIATE_SERIALISE_TYPE(GLPipe::Sampler) -INSTANTIATE_SERIALISE_TYPE(GLPipe::ImageLoadStore) INSTANTIATE_SERIALISE_TYPE(GLPipe::Rasterizer) INSTANTIATE_SERIALISE_TYPE(GLPipe::DepthState) INSTANTIATE_SERIALISE_TYPE(GLPipe::StencilState) @@ -2659,8 +2403,6 @@ INSTANTIATE_SERIALISE_TYPE(GLPipe::BlendState) INSTANTIATE_SERIALISE_TYPE(GLPipe::Attachment) INSTANTIATE_SERIALISE_TYPE(GLPipe::FrameBuffer) INSTANTIATE_SERIALISE_TYPE(GLPipe::State) -INSTANTIATE_SERIALISE_TYPE(VKPipe::BindingElement) -INSTANTIATE_SERIALISE_TYPE(VKPipe::DescriptorBinding) INSTANTIATE_SERIALISE_TYPE(VKPipe::DescriptorSet) INSTANTIATE_SERIALISE_TYPE(VKPipe::Pipeline) INSTANTIATE_SERIALISE_TYPE(VKPipe::VertexAttribute)