Merge pull request 'perf(sync): scope frame-loop barriers to swapchain image + real per-pass stages (#115)' (#137) from claude/issue-115 into master
This commit is contained in:
commit
82fd6916d9
6 changed files with 316 additions and 8 deletions
|
|
@ -35,6 +35,13 @@ export namespace Crafter {
|
|||
|
||||
RTPass(PipelineRTVulkan* p) : pipeline(p) {}
|
||||
|
||||
// An RT pass writes the swapchain image from the ray-tracing pipeline,
|
||||
// so the frame loop's barriers must wait on RAY_TRACING_SHADER — using
|
||||
// the compute stage here would under-synchronise and corrupt the image.
|
||||
VkPipelineStageFlags SwapchainStage() const override {
|
||||
return VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR;
|
||||
}
|
||||
|
||||
void Record(VkCommandBuffer cmd, std::uint32_t frameIdx, Window& window) override {
|
||||
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline->pipeline);
|
||||
// NVIDIA descriptor-heap AS-read workaround (issue #15 / #7): feed
|
||||
|
|
|
|||
|
|
@ -16,6 +16,10 @@ You should have received a copy of the GNU Lesser General Public
|
|||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
module;
|
||||
#ifndef CRAFTER_GRAPHICS_WINDOW_DOM
|
||||
#include "vulkan/vulkan.h"
|
||||
#endif // !CRAFTER_GRAPHICS_WINDOW_DOM
|
||||
export module Crafter.Graphics:RenderPass;
|
||||
import std;
|
||||
import :GraphicsTypes;
|
||||
|
|
@ -23,8 +27,74 @@ import :GraphicsTypes;
|
|||
export namespace Crafter {
|
||||
struct Window;
|
||||
|
||||
#ifndef CRAFTER_GRAPHICS_WINDOW_DOM
|
||||
// Conservative union of every pipeline stage that can write the swapchain
|
||||
// storage image: a compute pass via COMPUTE_SHADER, a ray-tracing pass via
|
||||
// RAY_TRACING_SHADER, plus TRANSFER for any blit/copy writer. Used as the
|
||||
// RenderPass default (a pass that doesn't narrow its own stage) and as the
|
||||
// fallback when there are no passes to derive a real union from. Far tighter
|
||||
// than ALL_COMMANDS, but never under-synchronises a polymorphic pass.
|
||||
inline constexpr VkPipelineStageFlags kSwapchainWriterStages =
|
||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
|
||||
| VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR
|
||||
| VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
#endif // !CRAFTER_GRAPHICS_WINDOW_DOM
|
||||
|
||||
struct RenderPass {
|
||||
virtual void Record(GraphicsCommandBuffer cmd, std::uint32_t frameIdx, Window& window) = 0;
|
||||
virtual ~RenderPass() = default;
|
||||
#ifndef CRAFTER_GRAPHICS_WINDOW_DOM
|
||||
// Pipeline stage at which this pass reads and writes the swapchain
|
||||
// storage image. The frame loop uses this to scope the inter-pass and
|
||||
// frame-edge barriers to the stages that actually touch the image
|
||||
// instead of ALL_COMMANDS. A subclass MUST narrow this to its real
|
||||
// stage (RTPass -> RAY_TRACING_SHADER, a compute pass -> COMPUTE_SHADER):
|
||||
// the default is the conservative writer union so an un-overridden pass
|
||||
// can never be under-synchronised, only over-synchronised.
|
||||
virtual VkPipelineStageFlags SwapchainStage() const { return kSwapchainWriterStages; }
|
||||
#endif // !CRAFTER_GRAPHICS_WINDOW_DOM
|
||||
};
|
||||
|
||||
#ifndef CRAFTER_GRAPHICS_WINDOW_DOM
|
||||
// Union of the swapchain-access stages declared by `passes` — the "real"
|
||||
// per-pass stage union the frame-edge barriers (acquire dst / present src)
|
||||
// narrow to: an all-compute frame yields COMPUTE_SHADER only, a frame with
|
||||
// any RT pass folds in RAY_TRACING_SHADER, and so on. Falls back to the
|
||||
// conservative writer union when there are no passes (the image is still
|
||||
// transitioned, just never written), so the barrier is always well-formed.
|
||||
inline VkPipelineStageFlags SwapchainStageUnion(std::span<RenderPass* const> passes) {
|
||||
if (passes.empty()) return kSwapchainWriterStages;
|
||||
VkPipelineStageFlags stages = 0;
|
||||
for (RenderPass* pass : passes) stages |= pass->SwapchainStage();
|
||||
return stages;
|
||||
}
|
||||
|
||||
// The inter-pass swapchain barrier (replacing the old queue-wide
|
||||
// VkMemoryBarrier at the #115 location). Scoped to the swapchain image's
|
||||
// single colour subresource so only that image's shader caches round-trip —
|
||||
// unrelated buffers/images stay resident — exactly as the intra-pass UI
|
||||
// barrier already does. The image is bound as a storage image and stays in
|
||||
// VK_IMAGE_LAYOUT_GENERAL, so this is a pure memory dependency (no layout
|
||||
// transition). The execution scope (stage masks) is supplied per pass pair
|
||||
// by the caller via vkCmdPipelineBarrier.
|
||||
inline VkImageMemoryBarrier BuildSwapchainInterPassBarrier(VkImage image) {
|
||||
return {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
|
||||
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = image,
|
||||
.subresourceRange = {
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
};
|
||||
}
|
||||
#endif // !CRAFTER_GRAPHICS_WINDOW_DOM
|
||||
}
|
||||
|
|
|
|||
|
|
@ -201,6 +201,15 @@ export namespace Crafter {
|
|||
|
||||
void Record(GraphicsCommandBuffer cmd, std::uint32_t frameIdx, Window& window) override;
|
||||
|
||||
#ifndef CRAFTER_GRAPHICS_WINDOW_DOM
|
||||
// A UI pass draws into the swapchain image entirely from compute
|
||||
// shaders (see Dispatch), so the frame loop's inter-pass / frame-edge
|
||||
// barriers only need to synchronise the COMPUTE_SHADER stage for it.
|
||||
VkPipelineStageFlags SwapchainStage() const override {
|
||||
return VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
|
||||
}
|
||||
#endif // !CRAFTER_GRAPHICS_WINDOW_DOM
|
||||
|
||||
UIDispatchHeader FillHeader(std::uint32_t itemBufferSlot,
|
||||
std::uint32_t itemCount,
|
||||
std::array<float,4> clipRectPx = {0.0f, 0.0f, 1e9f, 1e9f},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue