summaryrefslogtreecommitdiff
path: root/tools/gfx/vulkan/render-vk.h
diff options
context:
space:
mode:
authorlucy96chen <47800040+lucy96chen@users.noreply.github.com>2022-05-26 10:54:35 -0700
committerGitHub <noreply@github.com>2022-05-26 10:54:35 -0700
commit43e1b7cdc70b2fcac8a3e8ee72f5bc91726f4ec5 (patch)
tree1e4701b4ab324a199b81e1f6c671f6660f1050c5 /tools/gfx/vulkan/render-vk.h
parent5ff4f42c636a67724523e4fe60697cfac64908cd (diff)
Split render-vk.h/.cpp into a set of smaller files (#2244)
* Some preliminary work on splitting render-vk * render-vk split, tests currently crash on null reference * fixed circular include
Diffstat (limited to 'tools/gfx/vulkan/render-vk.h')
-rw-r--r--tools/gfx/vulkan/render-vk.h1795
1 files changed, 1 insertions, 1794 deletions
diff --git a/tools/gfx/vulkan/render-vk.h b/tools/gfx/vulkan/render-vk.h
index 5cec63787..cd4a79b07 100644
--- a/tools/gfx/vulkan/render-vk.h
+++ b/tools/gfx/vulkan/render-vk.h
@@ -18,1824 +18,31 @@ using namespace Slang;
enum
{
- kMaxRenderTargets = 8,
- kMaxTargets = kMaxRenderTargets + 1,
+
kMaxPushConstantSize = 256,
kMaxDescriptorSets = 8,
};
-class FramebufferImpl;
-class TransientResourceHeapImpl;
-class PipelineCommandEncoder;
-
-class DeviceImpl : public RendererBase
-{
-public:
- // Renderer implementation
- Result initVulkanInstanceAndDevice(const InteropHandle* handles, bool useValidationLayer);
- virtual SLANG_NO_THROW Result SLANG_MCALL initialize(const Desc& desc) override;
- virtual SLANG_NO_THROW Result SLANG_MCALL
- getFormatSupportedResourceStates(Format format, ResourceStateSet* outStates) override;
- virtual SLANG_NO_THROW Result SLANG_MCALL createTransientResourceHeap(
- const ITransientResourceHeap::Desc& desc, ITransientResourceHeap** outHeap) override;
- virtual SLANG_NO_THROW Result SLANG_MCALL
- createCommandQueue(const ICommandQueue::Desc& desc, ICommandQueue** outQueue) override;
- virtual SLANG_NO_THROW Result SLANG_MCALL createSwapchain(
- const ISwapchain::Desc& desc, WindowHandle window, ISwapchain** outSwapchain) override;
- virtual SLANG_NO_THROW Result SLANG_MCALL createFramebufferLayout(
- const IFramebufferLayout::Desc& desc, IFramebufferLayout** outLayout) override;
- virtual SLANG_NO_THROW Result SLANG_MCALL
- createFramebuffer(const IFramebuffer::Desc& desc, IFramebuffer** outFramebuffer) override;
- virtual SLANG_NO_THROW Result SLANG_MCALL createRenderPassLayout(
- const IRenderPassLayout::Desc& desc, IRenderPassLayout** outRenderPassLayout) override;
- virtual SLANG_NO_THROW Result SLANG_MCALL createTextureResource(
- const ITextureResource::Desc& desc,
- const ITextureResource::SubresourceData* initData,
- ITextureResource** outResource) override;
- virtual SLANG_NO_THROW Result SLANG_MCALL createBufferResource(
- const IBufferResource::Desc& desc,
- const void* initData,
- IBufferResource** outResource) override;
- virtual SLANG_NO_THROW Result SLANG_MCALL createBufferFromNativeHandle(
- InteropHandle handle,
- const IBufferResource::Desc& srcDesc,
- IBufferResource** outResource) override;
- virtual SLANG_NO_THROW Result SLANG_MCALL
- createSamplerState(ISamplerState::Desc const& desc, ISamplerState** outSampler) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL createTextureView(
- ITextureResource* texture,
- IResourceView::Desc const& desc,
- IResourceView** outView) override;
- virtual SLANG_NO_THROW Result SLANG_MCALL createBufferView(
- IBufferResource* buffer,
- IBufferResource* counterBuffer,
- IResourceView::Desc const& desc,
- IResourceView** outView) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL
- createInputLayout(IInputLayout::Desc const& desc, IInputLayout** outLayout) override;
-
- virtual Result createShaderObjectLayout(
- slang::TypeLayoutReflection* typeLayout, ShaderObjectLayoutBase** outLayout) override;
- virtual Result createShaderObject(
- ShaderObjectLayoutBase* layout, IShaderObject** outObject) override;
- virtual Result createMutableShaderObject(
- ShaderObjectLayoutBase* layout, IShaderObject** outObject) override;
- virtual SLANG_NO_THROW Result SLANG_MCALL
- createMutableRootShaderObject(IShaderProgram* program, IShaderObject** outObject) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL
- createShaderTable(const IShaderTable::Desc& desc, IShaderTable** outShaderTable) override;
- virtual SLANG_NO_THROW Result SLANG_MCALL createProgram(
- const IShaderProgram::Desc& desc,
- IShaderProgram** outProgram,
- ISlangBlob** outDiagnosticBlob) override;
- virtual SLANG_NO_THROW Result SLANG_MCALL createGraphicsPipelineState(
- const GraphicsPipelineStateDesc& desc, IPipelineState** outState) override;
- virtual SLANG_NO_THROW Result SLANG_MCALL createComputePipelineState(
- const ComputePipelineStateDesc& desc, IPipelineState** outState) override;
- virtual SLANG_NO_THROW Result SLANG_MCALL createRayTracingPipelineState(
- const RayTracingPipelineStateDesc& desc, IPipelineState** outState) override;
- virtual SLANG_NO_THROW Result SLANG_MCALL
- createQueryPool(const IQueryPool::Desc& desc, IQueryPool** outPool) override;
-
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL readTextureResource(
- ITextureResource* texture,
- ResourceState state,
- ISlangBlob** outBlob,
- Size* outRowPitch,
- Size* outPixelSize) override;
-
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL readBufferResource(
- IBufferResource* buffer, Offset offset, Size size, ISlangBlob** outBlob) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL getAccelerationStructurePrebuildInfo(
- const IAccelerationStructure::BuildInputs& buildInputs,
- IAccelerationStructure::PrebuildInfo* outPrebuildInfo) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL createAccelerationStructure(
- const IAccelerationStructure::CreateDesc& desc, IAccelerationStructure** outView) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL getTextureAllocationInfo(
- const ITextureResource::Desc& desc, Size* outSize, Size* outAlignment) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL getTextureRowAlignment(Size* outAlignment) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL
- createFence(const IFence::Desc& desc, IFence** outFence) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL waitForFences(
- GfxCount fenceCount,
- IFence** fences,
- uint64_t* fenceValues,
- bool waitForAll,
- uint64_t timeout) override;
-
- void waitForGpu();
-
- virtual SLANG_NO_THROW const DeviceInfo& SLANG_MCALL getDeviceInfo() const override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL
- getNativeDeviceHandles(InteropHandles* outHandles) override;
-
- ~DeviceImpl();
-
-public:
- VkBool32 handleDebugMessage(
- VkDebugReportFlagsEXT flags,
- VkDebugReportObjectTypeEXT objType,
- uint64_t srcObject,
- Size location, // TODO: Is "location" still needed for this function?
- int32_t msgCode,
- const char* pLayerPrefix,
- const char* pMsg);
-
- static VKAPI_ATTR VkBool32 VKAPI_CALL debugMessageCallback(
- VkDebugReportFlagsEXT flags,
- VkDebugReportObjectTypeEXT objType,
- uint64_t srcObject,
- Size location, // TODO: Is "location" still needed? Calls handleDebugMessage() which doesn't use it
- int32_t msgCode,
- const char* pLayerPrefix,
- const char* pMsg,
- void* pUserData);
-
- void _transitionImageLayout(
- VkImage image,
- VkFormat format,
- const TextureResource::Desc& desc,
- VkImageLayout oldLayout,
- VkImageLayout newLayout);
- void _transitionImageLayout(
- VkCommandBuffer commandBuffer,
- VkImage image,
- VkFormat format,
- const TextureResource::Desc& desc,
- VkImageLayout oldLayout,
- VkImageLayout newLayout);
-
- uint32_t getQueueFamilyIndex(ICommandQueue::QueueType queueType);
-
-public:
- // DeviceImpl members.
-
- DeviceInfo m_info;
- String m_adapterName;
-
- VkDebugReportCallbackEXT m_debugReportCallback = VK_NULL_HANDLE;
-
- VkDevice m_device = VK_NULL_HANDLE;
-
- VulkanModule m_module;
- VulkanApi m_api;
- VulkanDeviceQueue m_deviceQueue;
- uint32_t m_queueFamilyIndex;
- Desc m_desc;
- DescriptorSetAllocator descriptorSetAllocator;
- uint32_t m_queueAllocCount;
- // A list to hold objects that may have a strong back reference to the device
- // instance. Because of the pipeline cache in `RendererBase`, there could be a reference
- // cycle among `DeviceImpl`->`PipelineStateImpl`->`ShaderProgramImpl`->`DeviceImpl`.
- // Depending on whether a `PipelineState` objects gets stored in pipeline cache, there
- // may or may not be such a reference cycle.
- // We need to hold strong references to any objects that may become part of the reference
- // cycle here, so that when objects like `ShaderProgramImpl` lost all public refernces, we
- // can always safely break the strong reference in `ShaderProgramImpl::m_device` without
- // worrying the `ShaderProgramImpl` object getting destroyed after the completion of
- // `DeviceImpl::~DeviceImpl()'.
- ChunkedList<RefPtr<RefObject>, 1024> m_deviceObjectsWithPotentialBackReferences;
-
- VkSampler m_defaultSampler;
-
- RefPtr<FramebufferImpl> m_emptyFramebuffer;
-};
-
-class VKBufferHandleRAII
-{
-public:
- /// Initialize a buffer with specified size, and memory props
- Result init(
- const VulkanApi& api,
- Size bufferSize,
- VkBufferUsageFlags usage,
- VkMemoryPropertyFlags reqMemoryProperties,
- bool isShared = false,
- VkExternalMemoryHandleTypeFlagsKHR extMemHandleType = 0);
-
- /// Returns true if has been initialized
- bool isInitialized() const { return m_api != nullptr; }
-
- VKBufferHandleRAII()
- : m_api(nullptr)
- {}
-
- ~VKBufferHandleRAII()
- {
- if (m_api)
- {
- m_api->vkDestroyBuffer(m_api->m_device, m_buffer, nullptr);
- m_api->vkFreeMemory(m_api->m_device, m_memory, nullptr);
- }
- }
-
- VkBuffer m_buffer;
- VkDeviceMemory m_memory;
- const VulkanApi* m_api;
-};
-
-class InputLayoutImpl : public InputLayoutBase
-{
-public:
- List<VkVertexInputAttributeDescription> m_attributeDescs;
- List<VkVertexInputBindingDescription> m_streamDescs;
-};
-
-class BufferResourceImpl : public BufferResource
-{
-public:
- typedef BufferResource Parent;
-
- BufferResourceImpl(const IBufferResource::Desc& desc, DeviceImpl* renderer);
-
- ~BufferResourceImpl();
-
- RefPtr<DeviceImpl> m_renderer;
- VKBufferHandleRAII m_buffer;
- VKBufferHandleRAII m_uploadBuffer;
-
- virtual SLANG_NO_THROW DeviceAddress SLANG_MCALL getDeviceAddress() override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL
- getNativeResourceHandle(InteropHandle* outHandle) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL getSharedHandle(InteropHandle* outHandle) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL
- map(MemoryRange* rangeToRead, void** outPointer) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL unmap(MemoryRange* writtenRange) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL setDebugName(const char* name) override;
-};
-
-class FenceImpl : public FenceBase
-{
-public:
- VkSemaphore m_semaphore = VK_NULL_HANDLE;
- RefPtr<DeviceImpl> m_device;
- FenceImpl(DeviceImpl* device);
- ~FenceImpl();
-
- Result init(const IFence::Desc& desc);
-
- virtual SLANG_NO_THROW Result SLANG_MCALL getCurrentValue(uint64_t* outValue) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL setCurrentValue(uint64_t value) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL getSharedHandle(InteropHandle* outHandle) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL
- getNativeHandle(InteropHandle* outNativeHandle) override;
-};
-
-class TextureResourceImpl : public TextureResource
-{
-public:
- typedef TextureResource Parent;
- TextureResourceImpl(const Desc& desc, DeviceImpl* device);
- ~TextureResourceImpl();
-
- VkImage m_image = VK_NULL_HANDLE;
- VkFormat m_vkformat = VK_FORMAT_R8G8B8A8_UNORM;
- VkDeviceMemory m_imageMemory = VK_NULL_HANDLE;
- bool m_isWeakImageReference = false;
- RefPtr<DeviceImpl> m_device;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL
- getNativeResourceHandle(InteropHandle* outHandle) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL getSharedHandle(InteropHandle* outHandle) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL setDebugName(const char* name) override;
-};
-
-class SamplerStateImpl : public SamplerStateBase
-{
-public:
- VkSampler m_sampler;
- RefPtr<DeviceImpl> m_device;
- SamplerStateImpl(DeviceImpl* device);
- ~SamplerStateImpl();
- virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outHandle) override;
-};
-
-class ResourceViewImpl : public ResourceViewBase
-{
-public:
- enum class ViewType
- {
- Texture,
- TexelBuffer,
- PlainBuffer,
- };
-
-public:
- ResourceViewImpl(ViewType viewType, DeviceImpl* device)
- : m_type(viewType)
- , m_device(device)
- {}
- ViewType m_type;
- RefPtr<DeviceImpl> m_device;
-};
-
-class TextureResourceViewImpl : public ResourceViewImpl
-{
-public:
- TextureResourceViewImpl(DeviceImpl* device)
- : ResourceViewImpl(ViewType::Texture, device)
- {}
- ~TextureResourceViewImpl();
- RefPtr<TextureResourceImpl> m_texture;
- VkImageView m_view;
- VkImageLayout m_layout;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outHandle) override;
-};
-
-class TexelBufferResourceViewImpl : public ResourceViewImpl
-{
-public:
- TexelBufferResourceViewImpl(DeviceImpl* device);
- ~TexelBufferResourceViewImpl();
- RefPtr<BufferResourceImpl> m_buffer;
- VkBufferView m_view;
- virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outHandle) override;
-};
-
-class PlainBufferResourceViewImpl : public ResourceViewImpl
-{
-public:
- PlainBufferResourceViewImpl(DeviceImpl* device);
- RefPtr<BufferResourceImpl> m_buffer;
- VkDeviceSize offset;
- VkDeviceSize size;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outHandle) override;
-};
-
-class AccelerationStructureImpl : public AccelerationStructureBase
-{
-public:
- VkAccelerationStructureKHR m_vkHandle = VK_NULL_HANDLE;
- RefPtr<BufferResourceImpl> m_buffer;
- VkDeviceSize m_offset;
- VkDeviceSize m_size;
- RefPtr<DeviceImpl> m_device;
-
-public:
- virtual SLANG_NO_THROW DeviceAddress SLANG_MCALL getDeviceAddress() override;
- virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outHandle) override;
- ~AccelerationStructureImpl();
-};
-
-class FramebufferLayoutImpl : public FramebufferLayoutBase
-{
-public:
- VkRenderPass m_renderPass;
- DeviceImpl* m_renderer;
- Array<VkAttachmentDescription, kMaxTargets> m_targetDescs;
- Array<VkAttachmentReference, kMaxRenderTargets> m_colorReferences;
- VkAttachmentReference m_depthReference;
- bool m_hasDepthStencilTarget;
- uint32_t m_renderTargetCount;
- VkSampleCountFlagBits m_sampleCount = VK_SAMPLE_COUNT_1_BIT;
-
-public:
- ~FramebufferLayoutImpl();
- Result init(DeviceImpl* renderer, const IFramebufferLayout::Desc& desc);
-};
-
-class RenderPassLayoutImpl
- : public IRenderPassLayout
- , public ComObject
-{
-public:
- SLANG_COM_OBJECT_IUNKNOWN_ALL
- IRenderPassLayout* getInterface(const Guid& guid);
-
-public:
- VkRenderPass m_renderPass;
- RefPtr<DeviceImpl> m_renderer;
- ~RenderPassLayoutImpl();
-
- Result init(DeviceImpl* renderer, const IRenderPassLayout::Desc& desc);
-};
-
-class FramebufferImpl : public FramebufferBase
-{
-public:
- VkFramebuffer m_handle;
- ShortList<ComPtr<IResourceView>> renderTargetViews;
- ComPtr<IResourceView> depthStencilView;
- uint32_t m_width;
- uint32_t m_height;
- BreakableReference<DeviceImpl> m_renderer;
- VkClearValue m_clearValues[kMaxTargets];
- RefPtr<FramebufferLayoutImpl> m_layout;
-
-public:
- ~FramebufferImpl();
-
- Result init(DeviceImpl* renderer, const IFramebuffer::Desc& desc);
-};
-
-struct BoundVertexBuffer
-{
- RefPtr<BufferResourceImpl> m_buffer;
- int m_offset;
-};
-
-class PipelineStateImpl : public PipelineStateBase
-{
-public:
- PipelineStateImpl(DeviceImpl* device);
- ~PipelineStateImpl();
- // Turns `m_device` into a strong reference.
- // This method should be called before returning the pipeline state object to
- // external users (i.e. via an `IPipelineState` pointer).
- void establishStrongDeviceReference();
- virtual void comFree() override;
- void init(const GraphicsPipelineStateDesc& inDesc);
- void init(const ComputePipelineStateDesc& inDesc);
- void init(const RayTracingPipelineStateDesc& inDesc);
- Result createVKGraphicsPipelineState();
-
- Result createVKComputePipelineState();
-
- virtual Result ensureAPIPipelineStateCreated() override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outHandle) override;
-
- BreakableReference<DeviceImpl> m_device;
-
- VkPipeline m_pipeline = VK_NULL_HANDLE;
-};
-
-class RayTracingPipelineStateImpl : public PipelineStateImpl
-{
-public:
- Dictionary<String, Index> shaderGroupNameToIndex;
- Int shaderGroupCount;
-
- RayTracingPipelineStateImpl(DeviceImpl* device);
-
- uint32_t findEntryPointIndexByName(
- const Dictionary<String, Index>& entryPointNameToIndex, const char* name);
-
- Result createVKRayTracingPipelineState();
-
- virtual Result ensureAPIPipelineStateCreated() override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outHandle) override;
-};
-
-// In order to bind shader parameters to the correct locations, we need to
-// be able to describe those locations. Most shader parameters in Vulkan
-// simply consume a single `binding`, but we also need to deal with
-// parameters that represent push-constant ranges.
-//
-// In more complex cases we might be binding an entire "sub-object" like
-// a parameter block, an entry point, etc. For the general case, we need
-// to be able to represent a composite offset that includes offsets for
-// each of the cases that Vulkan supports.
-
-/// A "simple" binding offset that records `binding`, `set`, etc. offsets
-struct SimpleBindingOffset
-{
- /// An offset in GLSL/SPIR-V `binding`s
- uint32_t binding = 0;
-
- /// The descriptor `set` that the `binding` field should be understood as an index into
- uint32_t bindingSet = 0;
-
- /// The offset in push-constant ranges (not bytes)
- uint32_t pushConstantRange = 0;
-
- /// Create a default (zero) offset
- SimpleBindingOffset() {}
-
- /// Create an offset based on offset information in the given Slang `varLayout`
- SimpleBindingOffset(slang::VariableLayoutReflection* varLayout)
- {
- if (varLayout)
- {
- bindingSet = (uint32_t)varLayout->getBindingSpace(
- SLANG_PARAMETER_CATEGORY_DESCRIPTOR_TABLE_SLOT);
- binding =
- (uint32_t)varLayout->getOffset(SLANG_PARAMETER_CATEGORY_DESCRIPTOR_TABLE_SLOT);
- pushConstantRange =
- (uint32_t)varLayout->getOffset(SLANG_PARAMETER_CATEGORY_PUSH_CONSTANT_BUFFER);
- }
- }
-
- /// Add any values in the given `offset`
- void operator+=(SimpleBindingOffset const& offset)
- {
- binding += offset.binding;
- bindingSet += offset.bindingSet;
- pushConstantRange += offset.pushConstantRange;
- }
-};
-
-// While a "simple" binding offset representation will work in many cases,
-// once we need to deal with layout for programs with interface-type parameters
-// that have been statically specialized, we also need to track the offset
-// for where to bind any "pending" data that arises from the process of static
-// specialization.
-//
-// In order to conveniently track both the "primary" and "pending" offset information,
-// we will define a more complete `BindingOffset` type that combines simple
-// binding offsets for the primary and pending parts.
-
-/// A representation of the offset at which to bind a shader parameter or sub-object
-struct BindingOffset : SimpleBindingOffset
-{
- // Offsets for "primary" data are stored directly in the `BindingOffset`
- // via the inheritance from `SimpleBindingOffset`.
-
- /// Offset for any "pending" data
- SimpleBindingOffset pending;
-
- /// Create a default (zero) offset
- BindingOffset() {}
-
- /// Create an offset from a simple offset
- explicit BindingOffset(SimpleBindingOffset const& offset)
- : SimpleBindingOffset(offset)
- {}
-
- /// Create an offset based on offset information in the given Slang `varLayout`
- BindingOffset(slang::VariableLayoutReflection* varLayout)
- : SimpleBindingOffset(varLayout)
- , pending(varLayout->getPendingDataLayout())
- {}
-
- /// Add any values in the given `offset`
- void operator+=(SimpleBindingOffset const& offset) { SimpleBindingOffset::operator+=(offset); }
-
- /// Add any values in the given `offset`
- void operator+=(BindingOffset const& offset)
- {
- SimpleBindingOffset::operator+=(offset);
- pending += offset.pending;
- }
-};
-
-class ShaderObjectLayoutImpl : public ShaderObjectLayoutBase
-{
-public:
- // A shader object comprises three main kinds of state:
- //
- // * Zero or more bytes of ordinary ("uniform") data
- // * Zero or more *bindings* for textures, buffers, and samplers
- // * Zero or more *sub-objects* representing nested parameter blocks, etc.
- //
- // A shader object *layout* stores information that can be used to
- // organize these different kinds of state and optimize access to them.
- //
- // For example, both texture/buffer/sampler bindings and sub-objects
- // are organized into logical *binding ranges* by the Slang reflection
- // API, and a shader object layout will store information about those
- // ranges in a form that is usable for the Vulkan API:
-
- struct BindingRangeInfo
- {
- slang::BindingType bindingType;
- Index count;
- Index baseIndex;
-
- /// An index into the sub-object array if this binding range is treated
- /// as a sub-object.
- Index subObjectIndex;
-
- /// The `binding` offset to apply for this range
- uint32_t bindingOffset;
-
- /// The `set` offset to apply for this range
- uint32_t setOffset;
-
- // Note: The 99% case is that `setOffset` will be zero. For any shader object
- // that was allocated from an ordinary Slang type (anything other than a root
- // shader object in fact), all of the bindings will have been allocated into
- // a single logical descriptor set.
- //
- // TODO: Ideally we could refactor so that only the root shader object layout
- // stores a set offset for its binding ranges, and all other objects skip
- // storing a field that never actually matters.
- };
-
- // Sometimes we just want to iterate over the ranges that represnet
- // sub-objects while skipping over the others, because sub-object
- // ranges often require extra handling or more state.
- //
- // For that reason we also store pre-computed information about each
- // sub-object range.
-
- /// Offset information for a sub-object range
- struct SubObjectRangeOffset : BindingOffset
- {
- SubObjectRangeOffset() {}
-
- SubObjectRangeOffset(slang::VariableLayoutReflection* varLayout)
- : BindingOffset(varLayout)
- {
- if (auto pendingLayout = varLayout->getPendingDataLayout())
- {
- pendingOrdinaryData =
- (uint32_t)pendingLayout->getOffset(SLANG_PARAMETER_CATEGORY_UNIFORM);
- }
- }
-
- /// The offset for "pending" ordinary data related to this range
- uint32_t pendingOrdinaryData = 0;
- };
-
- /// Stride information for a sub-object range
- struct SubObjectRangeStride : BindingOffset
- {
- SubObjectRangeStride() {}
-
- SubObjectRangeStride(slang::TypeLayoutReflection* typeLayout)
- {
- if (auto pendingLayout = typeLayout->getPendingDataTypeLayout())
- {
- pendingOrdinaryData = (uint32_t)pendingLayout->getStride();
- }
- }
-
- /// The strid for "pending" ordinary data related to this range
- uint32_t pendingOrdinaryData = 0;
- };
-
- /// Information about a logical binding range as reported by Slang reflection
- struct SubObjectRangeInfo
- {
- /// The index of the binding range that corresponds to this sub-object range
- Index bindingRangeIndex;
-
- /// The layout expected for objects bound to this range (if known)
- RefPtr<ShaderObjectLayoutImpl> layout;
-
- /// The offset to use when binding the first object in this range
- SubObjectRangeOffset offset;
-
- /// Stride between consecutive objects in this range
- SubObjectRangeStride stride;
- };
-
- struct DescriptorSetInfo
- {
- List<VkDescriptorSetLayoutBinding> vkBindings;
- Slang::Int space = -1;
- VkDescriptorSetLayout descriptorSetLayout = VK_NULL_HANDLE;
- };
-
- struct Builder
- {
- public:
- Builder(DeviceImpl* renderer)
- : m_renderer(renderer)
- {}
-
- DeviceImpl* m_renderer;
- slang::TypeLayoutReflection* m_elementTypeLayout;
-
- /// The container type of this shader object. When `m_containerType` is
- /// `StructuredBuffer` or `UnsizedArray`, this shader object represents a collection
- /// instead of a single object.
- ShaderObjectContainerType m_containerType = ShaderObjectContainerType::None;
-
- List<BindingRangeInfo> m_bindingRanges;
- List<SubObjectRangeInfo> m_subObjectRanges;
-
- Index m_resourceViewCount = 0;
- Index m_samplerCount = 0;
- Index m_combinedTextureSamplerCount = 0;
- Index m_subObjectCount = 0;
- Index m_varyingInputCount = 0;
- Index m_varyingOutputCount = 0;
- List<DescriptorSetInfo> m_descriptorSetBuildInfos;
- Dictionary<Index, Index> m_mapSpaceToDescriptorSetIndex;
-
- /// The number of descriptor sets allocated by child/descendent objects
- uint32_t m_childDescriptorSetCount = 0;
-
- /// The total number of `binding`s consumed by this object and its children/descendents
- uint32_t m_totalBindingCount = 0;
-
- /// The push-constant ranges that belong to this object itself (if any)
- List<VkPushConstantRange> m_ownPushConstantRanges;
-
- /// The number of push-constant ranges owned by child/descendent objects
- uint32_t m_childPushConstantRangeCount = 0;
-
- uint32_t m_totalOrdinaryDataSize = 0;
-
- Index findOrAddDescriptorSet(Index space);
-
- static VkDescriptorType _mapDescriptorType(slang::BindingType slangBindingType);
-
- /// Add any descriptor ranges implied by this object containing a leaf
- /// sub-object described by `typeLayout`, at the given `offset`.
- void _addDescriptorRangesAsValue(
- slang::TypeLayoutReflection* typeLayout, BindingOffset const& offset);
-
- /// Add the descriptor ranges implied by a `ConstantBuffer<X>` where `X` is
- /// described by `elementTypeLayout`.
- ///
- /// The `containerOffset` and `elementOffset` are the binding offsets that
- /// should apply to the buffer itself and the contents of the buffer, respectively.
- ///
- void _addDescriptorRangesAsConstantBuffer(
- slang::TypeLayoutReflection* elementTypeLayout,
- BindingOffset const& containerOffset,
- BindingOffset const& elementOffset);
-
- /// Add the descriptor ranges implied by a `PushConstantBuffer<X>` where `X` is
- /// described by `elementTypeLayout`.
- ///
- /// The `containerOffset` and `elementOffset` are the binding offsets that
- /// should apply to the buffer itself and the contents of the buffer, respectively.
- ///
- void _addDescriptorRangesAsPushConstantBuffer(
- slang::TypeLayoutReflection* elementTypeLayout,
- BindingOffset const& containerOffset,
- BindingOffset const& elementOffset);
-
- /// Add binding ranges to this shader object layout, as implied by the given
- /// `typeLayout`
- void addBindingRanges(slang::TypeLayoutReflection* typeLayout);
-
- Result setElementTypeLayout(slang::TypeLayoutReflection* typeLayout);
-
- SlangResult build(ShaderObjectLayoutImpl** outLayout);
- };
-
- static Result createForElementType(
- DeviceImpl* renderer,
- slang::TypeLayoutReflection* elementType,
- ShaderObjectLayoutImpl** outLayout);
-
- ~ShaderObjectLayoutImpl();
-
- /// Get the number of descriptor sets that are allocated for this object itself
- /// (if it needed to be bound as a parameter block).
- ///
- uint32_t getOwnDescriptorSetCount() { return uint32_t(m_descriptorSetInfos.getCount()); }
-
- /// Get information about the descriptor sets that would be allocated to
- /// represent this object itself as a parameter block.
- ///
- List<DescriptorSetInfo> const& getOwnDescriptorSets() { return m_descriptorSetInfos; }
-
- /// Get the number of descriptor sets that would need to be allocated and bound
- /// to represent the children of this object if it were bound as a parameter
- /// block.
- ///
- /// To a first approximation, this is the number of (transitive) children
- /// that are declared as `ParameterBlock<X>`.
- ///
- uint32_t getChildDescriptorSetCount() { return m_childDescriptorSetCount; }
-
- /// Get the total number of descriptor sets that would need to be allocated and bound
- /// to represent this object and its children (transitively) as a parameter block.
- ///
- uint32_t getTotalDescriptorSetCount()
- {
- return getOwnDescriptorSetCount() + getChildDescriptorSetCount();
- }
-
- /// Get the total number of `binding`s required to represent this type and its
- /// (transitive) children.
- ///
- /// Note that this count does *not* include bindings that would be part of child
- /// parameter blocks, nor does it include the binding for an ordinary data buffer,
- /// if one is needed.
- ///
- uint32_t getTotalBindingCount() { return m_totalBindingCount; }
-
- /// Get the list of push constant ranges required to bind the state of this object itself.
- List<VkPushConstantRange> const& getOwnPushConstantRanges() const
- {
- return m_ownPushConstantRanges;
- }
-
- /// Get the number of push constant ranges required to bind the state of this object itself.
- uint32_t getOwnPushConstantRangeCount() { return (uint32_t)m_ownPushConstantRanges.getCount(); }
-
- /// Get the number of push constant ranges required to bind the state of the (transitive)
- /// children of this object.
- uint32_t getChildPushConstantRangeCount() { return m_childPushConstantRangeCount; }
-
- /// Get the total number of push constant ranges required to bind the state of this object
- /// and its (transitive) children.
- uint32_t getTotalPushConstantRangeCount()
- {
- return getOwnPushConstantRangeCount() + getChildPushConstantRangeCount();
- }
-
- uint32_t getTotalOrdinaryDataSize() const { return m_totalOrdinaryDataSize; }
-
- List<BindingRangeInfo> const& getBindingRanges() { return m_bindingRanges; }
-
- Index getBindingRangeCount() { return m_bindingRanges.getCount(); }
-
- BindingRangeInfo const& getBindingRange(Index index) { return m_bindingRanges[index]; }
-
- Index getResourceViewCount() { return m_resourceViewCount; }
- Index getSamplerCount() { return m_samplerCount; }
- Index getCombinedTextureSamplerCount() { return m_combinedTextureSamplerCount; }
- Index getSubObjectCount() { return m_subObjectCount; }
-
- SubObjectRangeInfo const& getSubObjectRange(Index index) { return m_subObjectRanges[index]; }
- List<SubObjectRangeInfo> const& getSubObjectRanges() { return m_subObjectRanges; }
-
- DeviceImpl* getDevice() { return static_cast<DeviceImpl*>(m_renderer); }
-
- slang::TypeReflection* getType() { return m_elementTypeLayout->getType(); }
-
-protected:
- Result _init(Builder const* builder);
-
- List<DescriptorSetInfo> m_descriptorSetInfos;
- List<BindingRangeInfo> m_bindingRanges;
- Index m_resourceViewCount = 0;
- Index m_samplerCount = 0;
- Index m_combinedTextureSamplerCount = 0;
- Index m_subObjectCount = 0;
- List<VkPushConstantRange> m_ownPushConstantRanges;
- uint32_t m_childPushConstantRangeCount = 0;
-
- uint32_t m_childDescriptorSetCount = 0;
- uint32_t m_totalBindingCount = 0;
- uint32_t m_totalOrdinaryDataSize = 0;
-
- List<SubObjectRangeInfo> m_subObjectRanges;
-};
-
-class EntryPointLayout : public ShaderObjectLayoutImpl
-{
- typedef ShaderObjectLayoutImpl Super;
-
-public:
- struct Builder : Super::Builder
- {
- Builder(DeviceImpl* device)
- : Super::Builder(device)
- {}
-
- Result build(EntryPointLayout** outLayout);
-
- void addEntryPointParams(slang::EntryPointLayout* entryPointLayout);
-
- slang::EntryPointLayout* m_slangEntryPointLayout = nullptr;
-
- VkShaderStageFlags m_shaderStageFlag;
- };
-
- Result _init(Builder const* builder);
-
- VkShaderStageFlags getShaderStageFlag() const { return m_shaderStageFlag; }
-
- slang::EntryPointLayout* getSlangLayout() const { return m_slangEntryPointLayout; };
-
- slang::EntryPointLayout* m_slangEntryPointLayout;
- VkShaderStageFlags m_shaderStageFlag;
-};
-
-class RootShaderObjectLayout : public ShaderObjectLayoutImpl
-{
- typedef ShaderObjectLayoutImpl Super;
-public:
- ~RootShaderObjectLayout();
- /// Information stored for each entry point of the program
- struct EntryPointInfo
- {
- /// Layout of the entry point
- RefPtr<EntryPointLayout> layout;
- /// Offset for binding the entry point, relative to the start of the program
- BindingOffset offset;
- };
- struct Builder : Super::Builder
- {
- Builder(
- DeviceImpl* renderer,
- slang::IComponentType* program,
- slang::ProgramLayout* programLayout)
- : Super::Builder(renderer)
- , m_program(program)
- , m_programLayout(programLayout)
- {}
- Result build(RootShaderObjectLayout** outLayout);
- void addGlobalParams(slang::VariableLayoutReflection* globalsLayout);
- void addEntryPoint(EntryPointLayout* entryPointLayout);
- slang::IComponentType* m_program;
- slang::ProgramLayout* m_programLayout;
- List<EntryPointInfo> m_entryPoints;
- /// Offset to apply to "pending" data from this object, sub-objects, and entry points
- SimpleBindingOffset m_pendingDataOffset;
- };
-
- Index findEntryPointIndex(VkShaderStageFlags stage);
-
- EntryPointInfo const& getEntryPoint(Index index) { return m_entryPoints[index]; }
-
- List<EntryPointInfo> const& getEntryPoints() const { return m_entryPoints; }
-
- static Result create(
- DeviceImpl* renderer,
- slang::IComponentType* program,
- slang::ProgramLayout* programLayout,
- RootShaderObjectLayout** outLayout);
-
- SimpleBindingOffset const& getPendingDataOffset() const { return m_pendingDataOffset; }
-
- slang::IComponentType* getSlangProgram() const { return m_program; }
- slang::ProgramLayout* getSlangProgramLayout() const { return m_programLayout; }
-
- /// Get all of the push constant ranges that will be bound for this object and all
- /// (transitive) sub-objects
- List<VkPushConstantRange> const& getAllPushConstantRanges() { return m_allPushConstantRanges; }
-
-protected:
- Result _init(Builder const* builder);
-
- /// Add all the descriptor sets implied by this root object and sub-objects
- Result addAllDescriptorSets();
-
- /// Recurisvely add descriptor sets defined by `layout` and sub-objects
- Result addAllDescriptorSetsRec(ShaderObjectLayoutImpl* layout);
-
- /// Recurisvely add descriptor sets defined by sub-objects of `layout`
- Result addChildDescriptorSetsRec(ShaderObjectLayoutImpl* layout);
-
- /// Add all the push-constant ranges implied by this root object and sub-objects
- Result addAllPushConstantRanges();
-
- /// Recurisvely add push-constant ranges defined by `layout` and sub-objects
- Result addAllPushConstantRangesRec(ShaderObjectLayoutImpl* layout);
-
- /// Recurisvely add push-constant ranges defined by sub-objects of `layout`
- Result addChildPushConstantRangesRec(ShaderObjectLayoutImpl* layout);
-
-public:
- ComPtr<slang::IComponentType> m_program;
- slang::ProgramLayout* m_programLayout = nullptr;
- List<EntryPointInfo> m_entryPoints;
- VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
- Array<VkDescriptorSetLayout, kMaxDescriptorSets> m_vkDescriptorSetLayouts;
- List<VkPushConstantRange> m_allPushConstantRanges;
- uint32_t m_totalPushConstantSize = 0;
-
- SimpleBindingOffset m_pendingDataOffset;
- DeviceImpl* m_renderer = nullptr;
-};
-
-class ShaderProgramImpl : public ShaderProgramBase
-{
-public:
- ShaderProgramImpl(DeviceImpl* device);
-
- ~ShaderProgramImpl();
-
- virtual void comFree() override;
-
- BreakableReference<DeviceImpl> m_device;
-
- Array<VkPipelineShaderStageCreateInfo, 8> m_stageCreateInfos;
- Array<String, 8> m_entryPointNames;
- Array<ComPtr<ISlangBlob>, 8> m_codeBlobs; //< To keep storage of code in scope
- Array<VkShaderModule, 8> m_modules;
- RefPtr<RootShaderObjectLayout> m_rootObjectLayout;
-
- VkPipelineShaderStageCreateInfo compileEntryPoint(
- const char* entryPointName,
- ISlangBlob* code,
- VkShaderStageFlagBits stage,
- VkShaderModule& outShaderModule);
-
- virtual Result createShaderModule(
- slang::EntryPointReflection* entryPointInfo, ComPtr<ISlangBlob> kernelCode) override;
-};
-
-class CommandBufferImpl;
-
-class PipelineCommandEncoder : public RefObject
-{
-public:
- CommandBufferImpl* m_commandBuffer;
- VkCommandBuffer m_vkCommandBuffer;
- VkCommandBuffer m_vkPreCommandBuffer = VK_NULL_HANDLE;
- VkPipeline m_boundPipelines[3] = {};
- DeviceImpl* m_device = nullptr;
- RefPtr<PipelineStateImpl> m_currentPipeline;
-
- VulkanApi* m_api;
-
- static int getBindPointIndex(VkPipelineBindPoint bindPoint);
-
- void init(CommandBufferImpl* commandBuffer);
-
- void endEncodingImpl();
-
- static void _uploadBufferData(
- VkCommandBuffer commandBuffer,
- TransientResourceHeapImpl* transientHeap,
- BufferResourceImpl* buffer,
- Offset offset,
- Size size,
- void* data);
-
- void uploadBufferDataImpl(IBufferResource* buffer, Offset offset, Size size, void* data);
-
- Result bindRootShaderObjectImpl(VkPipelineBindPoint bindPoint);
-
- Result setPipelineStateImpl(IPipelineState* state, IShaderObject** outRootObject);
-
- Result setPipelineStateWithRootObjectImpl(IPipelineState* state, IShaderObject* inObject);
-
- void bindRenderState(VkPipelineBindPoint pipelineBindPoint);
-};
-
-/// Context information required when binding shader objects to the pipeline
-struct RootBindingContext
-{
- /// The pipeline layout being used for binding
- VkPipelineLayout pipelineLayout;
-
- /// An allocator to use for descriptor sets during binding
- DescriptorSetAllocator* descriptorSetAllocator;
-
- /// The dvice being used
- DeviceImpl* device;
-
- /// The descriptor sets that are being allocated and bound
- VkDescriptorSet* descriptorSets;
-
- /// Information about all the push-constant ranges that should be bound
- ConstArrayView<VkPushConstantRange> pushConstantRanges;
-
- uint32_t descriptorSetCounter = 0;
-};
-
-struct CombinedTextureSamplerSlot
-{
- RefPtr<TextureResourceViewImpl> textureView;
- RefPtr<SamplerStateImpl> sampler;
- operator bool() { return textureView && sampler; }
-};
-
-class ShaderObjectImpl
- : public ShaderObjectBaseImpl<ShaderObjectImpl, ShaderObjectLayoutImpl, SimpleShaderObjectData>
-{
-public:
- static Result create(
- IDevice* device, ShaderObjectLayoutImpl* layout, ShaderObjectImpl** outShaderObject);
-
- RendererBase* getDevice();
-
- virtual SLANG_NO_THROW GfxCount SLANG_MCALL getEntryPointCount() override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL
- getEntryPoint(GfxIndex index, IShaderObject** outEntryPoint) override;
-
- virtual SLANG_NO_THROW const void* SLANG_MCALL getRawData() override;
-
- virtual SLANG_NO_THROW Size SLANG_MCALL getSize() override;
-
- // TODO: Changed size_t to Size? inSize assigned to an Index variable inside implementation
- virtual SLANG_NO_THROW Result SLANG_MCALL
- setData(ShaderOffset const& inOffset, void const* data, size_t inSize) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL
- setResource(ShaderOffset const& offset, IResourceView* resourceView) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL
- setSampler(ShaderOffset const& offset, ISamplerState* sampler) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL setCombinedTextureSampler(
- ShaderOffset const& offset, IResourceView* textureView, ISamplerState* sampler) override;
-
-protected:
- friend class RootShaderObjectLayout;
-
- Result init(IDevice* device, ShaderObjectLayoutImpl* layout);
-
- /// Write the uniform/ordinary data of this object into the given `dest` buffer at the given
- /// `offset`
- Result _writeOrdinaryData(
- PipelineCommandEncoder* encoder,
- IBufferResource* buffer,
- Offset offset,
- Size destSize,
- ShaderObjectLayoutImpl* specializedLayout);
-
-public:
- /// Write a single desriptor using the Vulkan API
- static void writeDescriptor(RootBindingContext& context, VkWriteDescriptorSet const& write);
-
- static void writeBufferDescriptor(
- RootBindingContext& context,
- BindingOffset const& offset,
- VkDescriptorType descriptorType,
- BufferResourceImpl* buffer,
- Offset bufferOffset,
- Size bufferSize);
-
- static void writeBufferDescriptor(
- RootBindingContext& context,
- BindingOffset const& offset,
- VkDescriptorType descriptorType,
- BufferResourceImpl* buffer);
-
- static void writePlainBufferDescriptor(
- RootBindingContext& context,
- BindingOffset const& offset,
- VkDescriptorType descriptorType,
- ArrayView<RefPtr<ResourceViewInternalBase>> resourceViews);
-
- static void writeTexelBufferDescriptor(
- RootBindingContext& context,
- BindingOffset const& offset,
- VkDescriptorType descriptorType,
- ArrayView<RefPtr<ResourceViewInternalBase>> resourceViews);
-
- static void writeTextureSamplerDescriptor(
- RootBindingContext& context,
- BindingOffset const& offset,
- VkDescriptorType descriptorType,
- ArrayView<CombinedTextureSamplerSlot> slots);
-
- static void writeAccelerationStructureDescriptor(
- RootBindingContext& context,
- BindingOffset const& offset,
- VkDescriptorType descriptorType,
- ArrayView<RefPtr<ResourceViewInternalBase>> resourceViews);
-
- static void writeTextureDescriptor(
- RootBindingContext& context,
- BindingOffset const& offset,
- VkDescriptorType descriptorType,
- ArrayView<RefPtr<ResourceViewInternalBase>> resourceViews);
-
- static void writeSamplerDescriptor(
- RootBindingContext& context,
- BindingOffset const& offset,
- VkDescriptorType descriptorType,
- ArrayView<RefPtr<SamplerStateImpl>> samplers);
-
- bool shouldAllocateConstantBuffer(TransientResourceHeapImpl* transientHeap);
-
- /// Ensure that the `m_ordinaryDataBuffer` has been created, if it is needed
- Result _ensureOrdinaryDataBufferCreatedIfNeeded(
- PipelineCommandEncoder* encoder, ShaderObjectLayoutImpl* specializedLayout);
-
-public:
- /// Bind this shader object as a "value"
- ///
- /// This is the mode used for binding sub-objects for existential-type
- /// fields, and is also used as part of the implementation of the
- /// parameter-block and constant-buffer cases.
- ///
- Result bindAsValue(
- PipelineCommandEncoder* encoder,
- RootBindingContext& context,
- BindingOffset const& offset,
- ShaderObjectLayoutImpl* specializedLayout);
-
- /// Allocate the descriptor sets needed for binding this object (but not nested parameter
- /// blocks)
- Result allocateDescriptorSets(
- PipelineCommandEncoder* encoder,
- RootBindingContext& context,
- BindingOffset const& offset,
- ShaderObjectLayoutImpl* specializedLayout);
-
- /// Bind this object as a `ParameterBlock<X>`.
- Result bindAsParameterBlock(
- PipelineCommandEncoder* encoder,
- RootBindingContext& context,
- BindingOffset const& inOffset,
- ShaderObjectLayoutImpl* specializedLayout);
-
- /// Bind the ordinary data buffer if needed.
- Result bindOrdinaryDataBufferIfNeeded(
- PipelineCommandEncoder* encoder,
- RootBindingContext& context,
- BindingOffset& ioOffset,
- ShaderObjectLayoutImpl* specializedLayout);
-
- /// Bind this object as a `ConstantBuffer<X>`.
- Result bindAsConstantBuffer(
- PipelineCommandEncoder* encoder,
- RootBindingContext& context,
- BindingOffset const& inOffset,
- ShaderObjectLayoutImpl* specializedLayout);
-
- List<RefPtr<ResourceViewInternalBase>> m_resourceViews;
-
- List<RefPtr<SamplerStateImpl>> m_samplers;
-
- List<CombinedTextureSamplerSlot> m_combinedTextureSamplers;
-
- // The transient constant buffer that holds the GPU copy of the constant data,
- // weak referenced.
- IBufferResource* m_constantBuffer = nullptr;
- // The offset into the transient constant buffer where the constant data starts.
- Offset m_constantBufferOffset = 0;
- Size m_constantBufferSize = 0;
-
- /// Dirty bit tracking whether the constant buffer needs to be updated.
- bool m_isConstantBufferDirty = true;
- /// The transient heap from which the constant buffer is allocated.
- TransientResourceHeapImpl* m_constantBufferTransientHeap;
- /// The version of the transient heap when the constant buffer is allocated.
- uint64_t m_constantBufferTransientHeapVersion;
-
- /// Get the layout of this shader object with specialization arguments considered
- ///
- /// This operation should only be called after the shader object has been
- /// fully filled in and finalized.
- ///
- Result _getSpecializedLayout(ShaderObjectLayoutImpl** outLayout);
-
- /// Create the layout for this shader object with specialization arguments considered
- ///
- /// This operation is virtual so that it can be customized by `ProgramVars`.
- ///
- virtual Result _createSpecializedLayout(ShaderObjectLayoutImpl** outLayout);
-
- RefPtr<ShaderObjectLayoutImpl> m_specializedLayout;
-};
-
-class MutableShaderObjectImpl
- : public MutableShaderObject<MutableShaderObjectImpl, ShaderObjectLayoutImpl>
-{};
-
-class EntryPointShaderObject : public ShaderObjectImpl
-{
- typedef ShaderObjectImpl Super;
-
-public:
- static Result create(
- IDevice* device, EntryPointLayout* layout, EntryPointShaderObject** outShaderObject);
-
- EntryPointLayout* getLayout();
-
- /// Bind this shader object as an entry point
- Result bindAsEntryPoint(
- PipelineCommandEncoder* encoder,
- RootBindingContext& context,
- BindingOffset const& inOffset,
- EntryPointLayout* layout);
-
-protected:
- Result init(IDevice* device, EntryPointLayout* layout);
-};
-
-class RootShaderObjectImpl : public ShaderObjectImpl
-{
- using Super = ShaderObjectImpl;
-
-public:
- // Override default reference counting behavior to disable lifetime management.
- // Root objects are managed by command buffer and does not need to be freed by the user.
- virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() override { return 1; }
- virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() override { return 1; }
-
-public:
- RootShaderObjectLayout* getLayout();
-
- RootShaderObjectLayout* getSpecializedLayout();
-
- List<RefPtr<EntryPointShaderObject>> const& getEntryPoints() const;
-
- virtual GfxCount SLANG_MCALL getEntryPointCount() override;
- virtual Result SLANG_MCALL getEntryPoint(GfxIndex index, IShaderObject** outEntryPoint) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL
- copyFrom(IShaderObject* object, ITransientResourceHeap* transientHeap) override;
-
- /// Bind this object as a root shader object
- Result bindAsRoot(
- PipelineCommandEncoder* encoder,
- RootBindingContext& context,
- RootShaderObjectLayout* layout);
-
- virtual Result collectSpecializationArgs(ExtendedShaderObjectTypeList& args) override;
-
-public:
- Result init(IDevice* device, RootShaderObjectLayout* layout);
-
-protected:
- virtual Result _createSpecializedLayout(ShaderObjectLayoutImpl** outLayout) override;
-
- List<RefPtr<EntryPointShaderObject>> m_entryPoints;
-};
-
-class ShaderTableImpl : public ShaderTableBase
-{
-public:
- uint32_t m_raygenTableSize;
- uint32_t m_missTableSize;
- uint32_t m_hitTableSize;
- uint32_t m_callableTableSize;
-
- DeviceImpl* m_device;
-
- virtual RefPtr<BufferResource> createDeviceBuffer(
- PipelineStateBase* pipeline,
- TransientResourceHeapBase* transientHeap,
- IResourceCommandEncoder* encoder) override;
-};
-
-class ResourceCommandEncoder
- : public IResourceCommandEncoder
- , public PipelineCommandEncoder
-{
-public:
- virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer(
- IBufferResource* dst,
- Offset dstOffset,
- IBufferResource* src,
- Offset srcOffset,
- Size size) override;
- virtual SLANG_NO_THROW void SLANG_MCALL
- uploadBufferData(IBufferResource* buffer, Offset offset, Size size, void* data) override;
- virtual SLANG_NO_THROW void SLANG_MCALL textureBarrier(
- GfxCount count,
- ITextureResource* const* textures,
- ResourceState src,
- ResourceState dst) override;
- virtual SLANG_NO_THROW void SLANG_MCALL bufferBarrier(
- GfxCount count,
- IBufferResource* const* buffers,
- ResourceState src,
- ResourceState dst) override;
- virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL
- writeTimestamp(IQueryPool* queryPool, GfxIndex index) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL copyTexture(
- ITextureResource* dst,
- ResourceState dstState,
- SubresourceRange dstSubresource,
- ITextureResource::Offset3D dstOffset,
- ITextureResource* src,
- ResourceState srcState,
- SubresourceRange srcSubresource,
- ITextureResource::Offset3D srcOffset,
- ITextureResource::Extents extent) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL uploadTextureData(
- ITextureResource* dst,
- SubresourceRange subResourceRange,
- ITextureResource::Offset3D offset,
- ITextureResource::Extents extend,
- ITextureResource::SubresourceData* subResourceData,
- GfxCount subResourceDataCount) override;
-
- void _clearColorImage(TextureResourceViewImpl* viewImpl, ClearValue* clearValue);
-
- void _clearDepthImage(
- TextureResourceViewImpl* viewImpl,
- ClearValue* clearValue,
- ClearResourceViewFlags::Enum flags);
-
- void _clearBuffer(
- VkBuffer buffer, uint64_t bufferSize, const IResourceView::Desc& desc, uint32_t clearValue);
-
- virtual SLANG_NO_THROW void SLANG_MCALL clearResourceView(
- IResourceView* view, ClearValue* clearValue, ClearResourceViewFlags::Enum flags) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL resolveResource(
- ITextureResource* source,
- ResourceState sourceState,
- SubresourceRange sourceRange,
- ITextureResource* dest,
- ResourceState destState,
- SubresourceRange destRange) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL resolveQuery(
- IQueryPool* queryPool,
- GfxIndex index,
- GfxCount count,
- IBufferResource* buffer,
- Offset offset) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL copyTextureToBuffer(
- IBufferResource* dst,
- Offset dstOffset,
- Size dstSize,
- Size dstRowStride,
- ITextureResource* src,
- ResourceState srcState,
- SubresourceRange srcSubresource,
- ITextureResource::Offset3D srcOffset,
- ITextureResource::Extents extent) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier(
- ITextureResource* texture,
- SubresourceRange subresourceRange,
- ResourceState src,
- ResourceState dst) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL
- beginDebugEvent(const char* name, float rgbColor[3]) override;
- virtual SLANG_NO_THROW void SLANG_MCALL endDebugEvent() override;
-};
-
-class RenderCommandEncoder
- : public IRenderCommandEncoder
- , public ResourceCommandEncoder
-{
-public:
- SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoder)
-public:
- List<VkViewport> m_viewports;
- List<VkRect2D> m_scissorRects;
-
-public:
- void beginPass(IRenderPassLayout* renderPass, IFramebuffer* framebuffer);
-
- virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL
- bindPipeline(IPipelineState* pipelineState, IShaderObject** outRootObject) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL bindPipelineWithRootObject(
- IPipelineState* pipelineState, IShaderObject* rootObject) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL
- setViewports(GfxCount count, const Viewport* viewports) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL
- setScissorRects(GfxCount count, const ScissorRect* rects) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL
- setPrimitiveTopology(PrimitiveTopology topology) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL setVertexBuffers(
- GfxIndex startSlot,
- GfxCount slotCount,
- IBufferResource* const* buffers,
- const Offset* offsets) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL
- setIndexBuffer(IBufferResource* buffer, Format indexFormat, Offset offset = 0) override;
-
- void prepareDraw();
-
- virtual SLANG_NO_THROW void SLANG_MCALL
- draw(GfxCount vertexCount, GfxIndex startVertex = 0) override;
- virtual SLANG_NO_THROW void SLANG_MCALL
- drawIndexed(GfxCount indexCount, GfxIndex startIndex = 0, GfxIndex baseVertex = 0) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL setStencilReference(uint32_t referenceValue) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL drawIndirect(
- GfxCount maxDrawCount,
- IBufferResource* argBuffer,
- Offset argOffset,
- IBufferResource* countBuffer,
- Offset countOffset) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL drawIndexedIndirect(
- GfxCount maxDrawCount,
- IBufferResource* argBuffer,
- Offset argOffset,
- IBufferResource* countBuffer,
- Offset countOffset) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL setSamplePositions(
- GfxCount samplesPerPixel,
- GfxCount pixelCount,
- const SamplePosition* samplePositions) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL drawInstanced(
- GfxCount vertexCount,
- GfxCount instanceCount,
- GfxIndex startVertex,
- GfxIndex startInstanceLocation) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL drawIndexedInstanced(
- GfxCount indexCount,
- GfxCount instanceCount,
- GfxIndex startIndexLocation,
- GfxIndex baseVertexLocation,
- GfxIndex startInstanceLocation) override;
-};
-
-class ComputeCommandEncoder
- : public IComputeCommandEncoder
- , public ResourceCommandEncoder
-{
-public:
- SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoder)
-public:
- virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL
- bindPipeline(IPipelineState* pipelineState, IShaderObject** outRootObject) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL bindPipelineWithRootObject(
- IPipelineState* pipelineState, IShaderObject* rootObject) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL dispatchCompute(int x, int y, int z) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL
- dispatchComputeIndirect(IBufferResource* argBuffer, Offset offset) override;
-};
-
-class RayTracingCommandEncoder
- : public IRayTracingCommandEncoder
- , public ResourceCommandEncoder
-{
-public:
- SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoder)
-public:
- void _memoryBarrier(
- int count,
- IAccelerationStructure* const* structures,
- AccessFlag srcAccess,
- AccessFlag destAccess);
-
- void _queryAccelerationStructureProperties(
- GfxCount accelerationStructureCount,
- IAccelerationStructure* const* accelerationStructures,
- GfxCount queryCount,
- AccelerationStructureQueryDesc* queryDescs);
-
- virtual SLANG_NO_THROW void SLANG_MCALL buildAccelerationStructure(
- const IAccelerationStructure::BuildDesc& desc,
- GfxCount propertyQueryCount,
- AccelerationStructureQueryDesc* queryDescs) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL copyAccelerationStructure(
- IAccelerationStructure* dest,
- IAccelerationStructure* src,
- AccelerationStructureCopyMode mode) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL queryAccelerationStructureProperties(
- GfxCount accelerationStructureCount,
- IAccelerationStructure* const* accelerationStructures,
- GfxCount queryCount,
- AccelerationStructureQueryDesc* queryDescs) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL
- serializeAccelerationStructure(DeviceAddress dest, IAccelerationStructure* source) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL deserializeAccelerationStructure(
- IAccelerationStructure* dest, DeviceAddress source) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL
- bindPipeline(IPipelineState* pipeline, IShaderObject** outRootObject) override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL bindPipelineWithRootObject(
- IPipelineState* pipelineState, IShaderObject* rootObject) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL dispatchRays(
- GfxIndex raygenShaderIndex,
- IShaderTable* shaderTable,
- GfxCount width,
- GfxCount height,
- GfxCount depth) override;
-
- virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override;
-};
-
-class CommandBufferImpl
- : public ICommandBuffer
- , public ComObject
-{
-public:
- // There are a pair of cyclic references between a `TransientResourceHeap` and
- // a `CommandBuffer` created from the heap. We need to break the cycle when
- // the public reference count of a command buffer drops to 0.
- SLANG_COM_OBJECT_IUNKNOWN_ALL
- ICommandBuffer* getInterface(const Guid& guid);
- virtual void comFree() override;
-
-public:
- VkCommandBuffer m_commandBuffer;
- VkCommandBuffer m_preCommandBuffer = VK_NULL_HANDLE;
- VkCommandPool m_pool;
- DeviceImpl* m_renderer;
- BreakableReference<TransientResourceHeapImpl> m_transientHeap;
- bool m_isPreCommandBufferEmpty = true;
- RootShaderObjectImpl m_rootObject;
-
- RefPtr<ResourceCommandEncoder> m_resourceCommandEncoder;
- RefPtr<ComputeCommandEncoder> m_computeCommandEncoder;
- RefPtr<RenderCommandEncoder> m_renderCommandEncoder;
- RefPtr<RayTracingCommandEncoder> m_rayTracingCommandEncoder;
-
- // Command buffers are deallocated by its command pool,
- // so no need to free individually.
- ~CommandBufferImpl() = default;
-
- Result init(DeviceImpl* renderer, VkCommandPool pool, TransientResourceHeapImpl* transientHeap);
-
- void beginCommandBuffer();
-
- Result createPreCommandBuffer();
-
- VkCommandBuffer getPreCommandBuffer();
-
-public:
- virtual SLANG_NO_THROW void SLANG_MCALL encodeRenderCommands(
- IRenderPassLayout* renderPass,
- IFramebuffer* framebuffer,
- IRenderCommandEncoder** outEncoder) override;
- virtual SLANG_NO_THROW void SLANG_MCALL
- encodeComputeCommands(IComputeCommandEncoder** outEncoder) override;
- virtual SLANG_NO_THROW void SLANG_MCALL
- encodeResourceCommands(IResourceCommandEncoder** outEncoder) override;
- virtual SLANG_NO_THROW void SLANG_MCALL
- encodeRayTracingCommands(IRayTracingCommandEncoder** outEncoder) override;
- virtual SLANG_NO_THROW void SLANG_MCALL close() override;
- virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outHandle) override;
-};
-
-class CommandQueueImpl
- : public ICommandQueue
- , public ComObject
-{
-public:
- SLANG_COM_OBJECT_IUNKNOWN_ALL
- ICommandQueue* getInterface(const Guid& guid);
-
-public:
- Desc m_desc;
- RefPtr<DeviceImpl> m_renderer;
- VkQueue m_queue;
- uint32_t m_queueFamilyIndex;
- struct FenceWaitInfo
- {
- RefPtr<FenceImpl> fence;
- uint64_t waitValue;
- };
- List<FenceWaitInfo> m_pendingWaitFences;
- VkSemaphore m_pendingWaitSemaphores[2] = {VK_NULL_HANDLE, VK_NULL_HANDLE};
- List<VkCommandBuffer> m_submitCommandBuffers;
- VkSemaphore m_semaphore;
- ~CommandQueueImpl();
-
- void init(DeviceImpl* renderer, VkQueue queue, uint32_t queueFamilyIndex);
-
- virtual SLANG_NO_THROW void SLANG_MCALL waitOnHost() override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outHandle) override;
-
- virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() override;
-
- virtual SLANG_NO_THROW Result SLANG_MCALL waitForFenceValuesOnDevice(
- GfxCount fenceCount, IFence** fences, uint64_t* waitValues) override;
-
- void queueSubmitImpl(
- uint32_t count,
- ICommandBuffer* const* commandBuffers,
- IFence* fence,
- uint64_t valueToSignal);
-
- virtual SLANG_NO_THROW void SLANG_MCALL executeCommandBuffers(
- GfxCount count,
- ICommandBuffer* const* commandBuffers,
- IFence* fence,
- uint64_t valueToSignal) override;
-};
-
-class TransientResourceHeapImpl
- : public TransientResourceHeapBaseImpl<DeviceImpl, BufferResourceImpl>
-{
-private:
- typedef TransientResourceHeapBaseImpl<DeviceImpl, BufferResourceImpl> Super;
-
-public:
- VkCommandPool m_commandPool;
- DescriptorSetAllocator m_descSetAllocator;
- List<VkFence> m_fences;
- Index m_fenceIndex = -1;
- List<RefPtr<CommandBufferImpl>> m_commandBufferPool;
- uint32_t m_commandBufferAllocId = 0;
- VkFence getCurrentFence() { return m_fences[m_fenceIndex]; }
- void advanceFence();
-
- Result init(const ITransientResourceHeap::Desc& desc, DeviceImpl* device);
- ~TransientResourceHeapImpl();
-
-public:
- virtual SLANG_NO_THROW Result SLANG_MCALL
- createCommandBuffer(ICommandBuffer** outCommandBuffer) override;
- virtual SLANG_NO_THROW Result SLANG_MCALL synchronizeAndReset() override;
-};
-
-class QueryPoolImpl : public QueryPoolBase
-{
-public:
- Result init(const IQueryPool::Desc& desc, DeviceImpl* device);
- ~QueryPoolImpl();
-
-public:
- virtual SLANG_NO_THROW Result SLANG_MCALL
- getResult(GfxIndex index, GfxCount count, uint64_t* data) override;
-
-public:
- VkQueryPool m_pool;
- RefPtr<DeviceImpl> m_device;
-};
-
-class SwapchainImpl
- : public ISwapchain
- , public ComObject
-{
-public:
- SLANG_COM_OBJECT_IUNKNOWN_ALL
- ISwapchain* getInterface(const Guid& guid);
-
-public:
- struct PlatformDesc
- {};
-
-#if SLANG_WINDOWS_FAMILY
- struct WinPlatformDesc : public PlatformDesc
- {
- HINSTANCE m_hinstance;
- HWND m_hwnd;
- };
-#else
- struct XPlatformDesc : public PlatformDesc
- {
- Display* m_display;
- Window m_window;
- };
-#endif
-public:
- VkSwapchainKHR m_swapChain;
- VkSurfaceKHR m_surface;
- VkSemaphore m_nextImageSemaphore; // Semaphore to signal after `acquireNextImage`.
- ISwapchain::Desc m_desc;
- VkFormat m_vkformat;
- RefPtr<CommandQueueImpl> m_queue;
- ShortList<RefPtr<TextureResourceImpl>> m_images;
- RefPtr<DeviceImpl> m_renderer;
- VulkanApi* m_api;
- uint32_t m_currentImageIndex = 0;
- WindowHandle m_windowHandle;
- void destroySwapchainAndImages();
-
- void getWindowSize(int* widthOut, int* heightOut) const;
-
- Result createSwapchainAndImages();
-
-public:
- ~SwapchainImpl();
-
- static Index _indexOfFormat(List<VkSurfaceFormatKHR>& formatsIn, VkFormat format);
-
- Result init(DeviceImpl* renderer, const ISwapchain::Desc& desc, WindowHandle window);
-
- virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() override { return m_desc; }
- virtual SLANG_NO_THROW Result SLANG_MCALL
- getImage(GfxIndex index, ITextureResource** outResource) override;
- virtual SLANG_NO_THROW Result SLANG_MCALL resize(GfxCount width, GfxCount height) override;
- virtual SLANG_NO_THROW Result SLANG_MCALL present() override;
- virtual SLANG_NO_THROW int SLANG_MCALL acquireNextImage() override;
- virtual SLANG_NO_THROW bool SLANG_MCALL isOccluded() override { return false; }
- virtual SLANG_NO_THROW Result SLANG_MCALL setFullScreenMode(bool mode) override;
-};
} // namespace vk
} // namespace gfx