diff --git a/docs/release-logs/0.4.1.md b/docs/release-logs/0.4.1.md index 91a68496f..986269e7c 100644 --- a/docs/release-logs/0.4.1.md +++ b/docs/release-logs/0.4.1.md @@ -10,10 +10,11 @@ - Improvements to C++ core guideline conformance ([See PR #103](https://github.com/crud89/LiteFX/pull/103)). - New event infrastructure. ([See PR #81](https://github.com/crud89/LiteFX/pull/81)) - Add support for user-defined debug markers. ([See PR #82](https://github.com/crud89/LiteFX/pull/82)) -- Improved resource allocation and binding: ([See PR #83](https://github.com/crud89/LiteFX/pull/83) and [PR #110](https://github.com/crud89/LiteFX/pull/110)) +- Improved resource allocation and binding: ([See PR #83](https://github.com/crud89/LiteFX/pull/83), [PR #110](https://github.com/crud89/LiteFX/pull/110) and [PR #111](https://github.com/crud89/LiteFX/pull/111)) - Resources can now be created without querying the descriptor set layout or descriptor layout in advance. - When allocating descriptor sets, default bindings can be provided to make bind-once scenarios more straightforward. - Descriptor sets can also be allocated without providing any binding index (in which case continous counting is assumed) or resources (which enables late binding or resource updating). + - Descriptor set binding has been simplified by caching last used pipeline on command buffers. - Improved handling of temporary command buffers. ([See PR #89](https://github.com/crud89/LiteFX/pull/89)) - Command buffers can now be submitted with shared ownership to a command queue, which then stores them and releases the references, if the submit fence is passed (during `waitFor`). - Command buffer transfers can now receive resources with shared ownership. Resource references are released in a similar fashion. diff --git a/src/Backends/DirectX12/include/litefx/backends/dx12.hpp b/src/Backends/DirectX12/include/litefx/backends/dx12.hpp index 170c60c7c..1143e1638 100644 --- a/src/Backends/DirectX12/include/litefx/backends/dx12.hpp +++ b/src/Backends/DirectX12/include/litefx/backends/dx12.hpp @@ -901,6 +901,9 @@ namespace LiteFX::Rendering::Backends { /// void use(const DirectX12PipelineState& pipeline) const noexcept override; + /// + void bind(const DirectX12DescriptorSet& descriptorSet) const override; + /// void bind(const DirectX12DescriptorSet& descriptorSet, const DirectX12PipelineState& pipeline) const noexcept override; diff --git a/src/Backends/DirectX12/src/command_buffer.cpp b/src/Backends/DirectX12/src/command_buffer.cpp index 28445e46a..07ee31bb7 100644 --- a/src/Backends/DirectX12/src/command_buffer.cpp +++ b/src/Backends/DirectX12/src/command_buffer.cpp @@ -15,6 +15,7 @@ class DirectX12CommandBuffer::DirectX12CommandBufferImpl : public Implement> m_sharedResources; + const DirectX12PipelineState* m_lastPipeline = nullptr; public: DirectX12CommandBufferImpl(DirectX12CommandBuffer* parent, const DirectX12Queue& queue) : @@ -328,9 +329,18 @@ void DirectX12CommandBuffer::transfer(SharedPtr source, IDirect void DirectX12CommandBuffer::use(const DirectX12PipelineState& pipeline) const noexcept { + m_impl->m_lastPipeline = &pipeline; pipeline.use(*this); } +void DirectX12CommandBuffer::bind(const DirectX12DescriptorSet& descriptorSet) const +{ + if (m_impl->m_lastPipeline) [[likely]] + m_impl->m_queue.device().bindDescriptorSet(*this, descriptorSet, *m_impl->m_lastPipeline); + else + throw RuntimeException("No pipeline has been used on the command buffer before attempting to bind the descriptor set."); +} + void DirectX12CommandBuffer::bind(const DirectX12DescriptorSet& descriptorSet, const DirectX12PipelineState& pipeline) const noexcept { m_impl->m_queue.device().bindDescriptorSet(*this, descriptorSet, pipeline); diff --git a/src/Backends/Vulkan/include/litefx/backends/vulkan.hpp b/src/Backends/Vulkan/include/litefx/backends/vulkan.hpp index 2aa76b2a8..fcd5d782b 100644 --- a/src/Backends/Vulkan/include/litefx/backends/vulkan.hpp +++ b/src/Backends/Vulkan/include/litefx/backends/vulkan.hpp @@ -914,6 +914,9 @@ namespace LiteFX::Rendering::Backends { /// void use(const VulkanPipelineState& pipeline) const noexcept override; + /// + void bind(const VulkanDescriptorSet& descriptorSet) const override; + /// void bind(const VulkanDescriptorSet& descriptorSet, const VulkanPipelineState& pipeline) const noexcept override; diff --git a/src/Backends/Vulkan/src/command_buffer.cpp b/src/Backends/Vulkan/src/command_buffer.cpp index 6b6322edf..cbc78b270 100644 --- a/src/Backends/Vulkan/src/command_buffer.cpp +++ b/src/Backends/Vulkan/src/command_buffer.cpp @@ -15,6 +15,7 @@ class VulkanCommandBuffer::VulkanCommandBufferImpl : public Implement m_commandPool; Array> m_sharedResources; + const VulkanPipelineState* m_lastPipeline = nullptr; public: VulkanCommandBufferImpl(VulkanCommandBuffer* parent, const VulkanQueue& queue) : @@ -398,9 +399,18 @@ void VulkanCommandBuffer::transfer(SharedPtr source, IVulkanBuffer void VulkanCommandBuffer::use(const VulkanPipelineState& pipeline) const noexcept { + m_impl->m_lastPipeline = &pipeline; pipeline.use(*this); } +void VulkanCommandBuffer::bind(const VulkanDescriptorSet& descriptorSet) const +{ + if (m_impl->m_lastPipeline) [[likely]] + m_impl->m_lastPipeline->bind(*this, descriptorSet); + else + throw RuntimeException("No pipeline has been used on the command buffer before attempting to bind the descriptor set."); +} + void VulkanCommandBuffer::bind(const VulkanDescriptorSet& descriptorSet, const VulkanPipelineState& pipeline) const noexcept { pipeline.bind(*this, descriptorSet); diff --git a/src/Rendering/include/litefx/rendering.hpp b/src/Rendering/include/litefx/rendering.hpp index 94a3d36d5..14c4d615e 100644 --- a/src/Rendering/include/litefx/rendering.hpp +++ b/src/Rendering/include/litefx/rendering.hpp @@ -533,6 +533,9 @@ namespace LiteFX::Rendering { /// virtual void use(const pipeline_type& pipeline) const noexcept = 0; + /// + virtual void bind(const descriptor_set_type& descriptorSet) const = 0; + /// virtual void bind(const descriptor_set_type& descriptorSet, const pipeline_type& pipeline) const noexcept = 0; @@ -615,6 +618,10 @@ namespace LiteFX::Rendering { this->use(dynamic_cast(pipeline)); } + void cmdBind(const IDescriptorSet& descriptorSet) const override { + this->bind(dynamic_cast(descriptorSet)); + } + void cmdBind(const IDescriptorSet& descriptorSet, const IPipeline& pipeline) const noexcept override { this->bind(dynamic_cast(descriptorSet), dynamic_cast(pipeline)); } diff --git a/src/Rendering/include/litefx/rendering_api.hpp b/src/Rendering/include/litefx/rendering_api.hpp index 924e17568..8a43e150c 100644 --- a/src/Rendering/include/litefx/rendering_api.hpp +++ b/src/Rendering/include/litefx/rendering_api.hpp @@ -4167,8 +4167,15 @@ namespace LiteFX::Rendering { this->cmdUse(pipeline); } - // TODO: Allow bind to last used pipeline (throw, if no pipeline is in use). - //void bind(const IDescriptorSet& descriptorSet) const; + /// + /// Binds the provided descriptor to the last pipeline that was used by the command buffer. + /// + /// The descriptor set to bind. + /// Thrown, if no pipeline has been used before attempting to bind the descriptor set. + /// + void bind(const IDescriptorSet& descriptorSet) const { + this->cmdBind(descriptorSet); + } /// /// Binds the provided descriptor set to the provided pipeline. @@ -4359,6 +4366,7 @@ namespace LiteFX::Rendering { virtual void cmdTransfer(SharedPtr source, IImage& target, UInt32 sourceSubresource, UInt32 targetSubresource, UInt32 subresources) const = 0; virtual void cmdTransfer(SharedPtr source, IBuffer& target, UInt32 firstSubresource, UInt32 targetElement, UInt32 subresources) const = 0; virtual void cmdUse(const IPipeline& pipeline) const noexcept = 0; + virtual void cmdBind(const IDescriptorSet& descriptorSet) const = 0; virtual void cmdBind(const IDescriptorSet& descriptorSet, const IPipeline& pipeline) const noexcept = 0; virtual void cmdBind(const IVertexBuffer& buffer) const noexcept = 0; virtual void cmdBind(const IIndexBuffer& buffer) const noexcept = 0; diff --git a/src/Samples/BasicRendering/src/sample.cpp b/src/Samples/BasicRendering/src/sample.cpp index 0c5df79e6..d88da522f 100644 --- a/src/Samples/BasicRendering/src/sample.cpp +++ b/src/Samples/BasicRendering/src/sample.cpp @@ -390,8 +390,8 @@ void SampleApp::drawFrame() transformBuffer.map(reinterpret_cast(&transform), sizeof(transform), backBuffer); // Bind both descriptor sets to the pipeline. - commandBuffer->bind(cameraBindings, geometryPipeline); - commandBuffer->bind(transformBindings, geometryPipeline); + commandBuffer->bind(cameraBindings); + commandBuffer->bind(transformBindings); // Bind the vertex and index buffers. commandBuffer->bind(vertexBuffer);