summaryrefslogtreecommitdiff
path: root/tools/gfx/d3d11/render-d3d11.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/gfx/d3d11/render-d3d11.cpp')
-rw-r--r--tools/gfx/d3d11/render-d3d11.cpp166
1 files changed, 163 insertions, 3 deletions
diff --git a/tools/gfx/d3d11/render-d3d11.cpp b/tools/gfx/d3d11/render-d3d11.cpp
index cf2ae75e2..4eba4edaf 100644
--- a/tools/gfx/d3d11/render-d3d11.cpp
+++ b/tools/gfx/d3d11/render-d3d11.cpp
@@ -139,14 +139,66 @@ public:
class DescriptorSetLayoutImpl : public DescriptorSetLayout
{
public:
+ // Each descriptor set for the D3D11 renderer stores distinct
+ // arrays for each kind of shader-visible entity D3D11 understands:
+ // shader resource views (SRVs), unordered access views (UAVs),
+ // constant buffers (CBs), and samplers.
+ //
+ // (This description will ignore compiled image/sampler pairs,
+ // since they aren't really well supported at present)
+ //
+ // Each descriptor range in an input `DescriptorSetLayout::Desc`
+ // will map to a range of entries in one of those arrays, but
+ // in general there can be multiple `DescriptorSlotType`s that
+ // map to the same `D3D11DescriptorSlotType`.
+ //
+ // Each `RangeInfo` in a D3D11 descriptor set layout represents
+ // of of the descriptor slot ranges in the original `Desc`,
+ // and stores the information that is relevant to its layout
+ // in our D3D11 implementation.
+
struct RangeInfo
{
+ /// The type of descriptors in the range, in D3D11 terms (SRVs, UAVs, etc.)
D3D11DescriptorSlotType type;
+
+ /// The start index of this range in the relevant descriptor-type-specific array.
+ ///
+ /// Note: This is *not* the same as the index of the range, both because multiple
+ /// `DescriptorSlotType`s might map to the same array in the D3D11 implementation,
+ /// and also because a given range might store multiple descriptors (so a 3-texture
+ /// range that comes after a 5-texture range will have an `arrayIndex` of 5 but
+ /// a range index of 1).
+ ///
UInt arrayIndex;
+
+ /// For the case of a combined image/sampler pair, the `arrayIndex` is an index
+ /// into the array of SRVs, and we store a separate index into the array of
+ /// samplers.
+ ///
UInt pairedSamplerArrayIndex;
};
List<RangeInfo> m_ranges;
+ // Because D3D11 does not support root constants as they appear in
+ // D3D12 and Vulkan, we need to map root-constant ranges in the original `Desc`
+ // over to ordinary constant buffers. Each root-constant range (of whatever
+ // size) will map to a constant-buffer range of a single buffer.
+ //
+ // In order to be able to properly allocate/initialize these root constant
+ // buffers, we store additional information about them in a flattened array
+ // that only stores information for root constant ranges.
+
+ struct RootConstantRangeInfo
+ {
+ /// Index of the `RangeInfo` corresponding to this root-constant range
+ Index rangeIndex;
+
+ /// Size of the original root-constant range, in bytes.
+ UInt size;
+ };
+ List<RootConstantRangeInfo> m_rootConstantRanges;
+
UInt m_counts[int(D3D11DescriptorSlotType::CountOf)];
};
@@ -174,6 +226,13 @@ public:
UInt index,
ResourceView* textureView,
SamplerState* sampler) override;
+ virtual void setRootConstants(
+ UInt range,
+ UInt offset,
+ UInt size,
+ void const* data) override;
+
+ D3D11Renderer* m_renderer = nullptr;
RefPtr<DescriptorSetLayoutImpl> m_layout;
@@ -1762,6 +1821,7 @@ Result D3D11Renderer::createDescriptorSetLayout(const DescriptorSetLayout::Desc&
DescriptorSetLayoutImpl::RangeInfo rangeInfo;
+ UInt slotCount = rangeDesc.count;
switch(rangeDesc.type)
{
default:
@@ -1776,6 +1836,11 @@ Result D3D11Renderer::createDescriptorSetLayout(const DescriptorSetLayout::Desc&
rangeInfo.type = D3D11DescriptorSlotType::CombinedTextureSampler;
break;
+ case DescriptorSlotType::RootConstant:
+ // A root-constant range will be treated as if it were
+ // a constant-buffer range with a single buffer in it.
+ //
+ slotCount = 1;
case DescriptorSlotType::UniformBuffer:
case DescriptorSlotType::DynamicUniformBuffer:
rangeInfo.type = D3D11DescriptorSlotType::ConstantBuffer;
@@ -1803,17 +1868,31 @@ Result D3D11Renderer::createDescriptorSetLayout(const DescriptorSetLayout::Desc&
rangeInfo.arrayIndex = counts[srvTypeIndex];
rangeInfo.pairedSamplerArrayIndex = counts[samplerTypeIndex];
- counts[srvTypeIndex] += rangeDesc.count;
- counts[samplerTypeIndex] += rangeDesc.count;
+ counts[srvTypeIndex] += slotCount;
+ counts[samplerTypeIndex] += slotCount;
}
else
{
auto typeIndex = int(rangeInfo.type);
rangeInfo.arrayIndex = counts[typeIndex];
- counts[typeIndex] += rangeDesc.count;
+ counts[typeIndex] += slotCount;
}
+ Index rangeIndex = descriptorSetLayoutImpl->m_ranges.getCount();
descriptorSetLayoutImpl->m_ranges.add(rangeInfo);
+
+ if(rangeDesc.type == DescriptorSlotType::RootConstant)
+ {
+ // If the range represents a root constant range, then
+ // we need to also store the information we will need when
+ // allocating a constant buffer to provide backing storage
+ // for the range.
+ //
+ DescriptorSetLayoutImpl::RootConstantRangeInfo rootConstantRangeInfo;
+ rootConstantRangeInfo.rangeIndex = rangeIndex;
+ rootConstantRangeInfo.size = rangeDesc.count;
+ descriptorSetLayoutImpl->m_rootConstantRanges.add(rootConstantRangeInfo);
+ }
}
for(int ii = 0; ii < int(D3D11DescriptorSlotType::CountOf); ++ii)
@@ -1860,12 +1939,55 @@ Result D3D11Renderer::createDescriptorSet(DescriptorSetLayout* layout, Descripto
RefPtr<DescriptorSetImpl> descriptorSetImpl = new DescriptorSetImpl();
+ descriptorSetImpl->m_renderer = this;
descriptorSetImpl->m_layout = layoutImpl;
descriptorSetImpl->m_cbs .setCount(layoutImpl->m_counts[int(D3D11DescriptorSlotType::ConstantBuffer)]);
descriptorSetImpl->m_srvs .setCount(layoutImpl->m_counts[int(D3D11DescriptorSlotType::ShaderResourceView)]);
descriptorSetImpl->m_uavs .setCount(layoutImpl->m_counts[int(D3D11DescriptorSlotType::UnorderedAccessView)]);
descriptorSetImpl->m_samplers.setCount(layoutImpl->m_counts[int(D3D11DescriptorSlotType::Sampler)]);
+ // If the layout includes any root constant ranges, then
+ // we will need to allocate a constant buffer for each
+ // range to provide "backing storage" for its data.
+ //
+ for(auto rootConstantRange : layoutImpl->m_rootConstantRanges)
+ {
+ // The root constant range will refer to a descriptor slot
+ // range that represents a range with a single constant
+ // buffer in it. We need to grab that range so that we
+ // know what constant-buffer bindign slot to fill in.
+ //
+ auto rangeIndex = rootConstantRange.rangeIndex;
+ auto bufferRange = layoutImpl->m_ranges[rangeIndex];
+
+ // We will allocate the constant buffer that provides
+ // backing storage directly using D3D11 API calls,
+ // rather than allocate it as a buffer resource.
+ //
+ // TODO: We could revisit that decision if allocating
+ // a buffer resource proves easier down the line.
+
+ // Note: A D3D11 constant buffer must be a multiple of 16 bytes
+ // in size, so we will round up the allocation size to match
+ // the requirement.
+ //
+ UINT size = (UINT) rootConstantRange.size;
+ size = (size + 15) & ~15;
+
+ D3D11_BUFFER_DESC bufferDesc;
+ bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ bufferDesc.ByteWidth = size;
+ bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.StructureByteStride = 0;
+ bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
+
+ Slang::ComPtr<ID3D11Buffer> buffer;
+ SLANG_RETURN_ON_FAIL(m_device->CreateBuffer(&bufferDesc, nullptr, buffer.writeRef()));
+
+ descriptorSetImpl->m_cbs[bufferRange.arrayIndex] = buffer;
+ }
+
*outDescriptorSet = descriptorSetImpl.detach();
return SLANG_OK;
}
@@ -2277,6 +2399,44 @@ void D3D11Renderer::DescriptorSetImpl::setCombinedTextureSampler(
m_srvs[rangeInfo.pairedSamplerArrayIndex + index] = srvImpl->m_srv;
}
+void D3D11Renderer::DescriptorSetImpl::setRootConstants(
+ UInt range,
+ UInt offset,
+ UInt size,
+ void const* data)
+{
+ // The `range` parameter represents the index of a descriptor
+ // slot range in the layout of this descriptor set.
+ //
+ // A root constant range will have been translated into
+ // a constnat buffer range at creation time for the layout.
+ //
+ auto& rangeInfo = m_layout->m_ranges[range];
+ assert(rangeInfo.type == D3D11DescriptorSlotType::ConstantBuffer);
+
+ // At the time the descriptor set was allocated, a
+ // constant buffer will have been created and bound
+ // into `m_cbs` to provide backing storage for the
+ // root constant range.
+ //
+ auto dxBuffer = m_cbs[rangeInfo.arrayIndex];
+ auto dxContext = m_renderer->m_immediateContext;
+
+ // Once we have the buffer that provides backing
+ // storage we simply need to map it and write
+ // the user-provided data into it.
+ //
+ D3D11_MAPPED_SUBRESOURCE mapped;
+ HRESULT hr = dxContext->Map(dxBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mapped);
+ if( FAILED(hr) )
+ {
+ SLANG_ASSERT(!"failed to map backing storage for root constant range");
+ return;
+ }
+ memcpy((char*)mapped.pData + offset, data, size);
+ dxContext->Unmap(dxBuffer, 0);
+}
+
void D3D11Renderer::setDescriptorSet(PipelineType pipelineType, PipelineLayout* layout, UInt index, DescriptorSet* descriptorSet)
{
auto pipelineLayoutImpl = (PipelineLayoutImpl*)layout;