blob: ab35510d589fe1ae42f09d2aa1a156af77164d24 [file] [log] [blame]
/*
* Copyright 2025 Rive
*/
#pragma once
#include <vulkan/vulkan.h>
#include "rive/renderer/vulkan/vulkan_context.hpp"
#include "rive/renderer/gpu.hpp"
namespace rive::gpu
{
class DrawPipelineLayoutVulkan;
class PipelineManagerVulkan;
// Rive-specific options for configuring a render pass.
enum class RenderPassOptionsVulkan
{
none = 0,
// No need to attach the COLOR texture as an input attachment. There are
// no advanced blend modes so we can use built-in hardware blending.
fixedFunctionColorOutput = 1 << 0,
// rasterOrdering or msaa only: The render pass has a fullscreen draw at
// the end that resolves rendering data into the renderTarget. (e.g., by
// transferring color from offscreen or manually averaging MSAA.)
manuallyResolved = 1 << 1,
// rasterOrdering mode only: Store all transient attachments to memory
// so the render pass can be interrupted and restarted.
rasterOrderingInterruptible = 1 << 2,
// rasterOrdering mode only: This render pass is resuming after an
// interrupt; load all transient attachments from memory.
rasterOrderingResume = 1 << 3,
// Atomic mode only: Use an offscreen texture to render color, but also
// attach the real target texture at the COALESCED_ATOMIC_RESOLVE index,
// and render to it directly in the atomic resolve step.
atomicCoalescedResolveAndTransfer = 1 << 4,
// MSAA only, while using LoadAction::preserveRenderTarget: We have to
// initialize the (transient) MSAA color attachment from an offscreen
// texture bound as an input attachment, because the final render target
// itself can't be bound as an input attachment.
msaaSeedFromOffscreenTexture = 1 << 5,
};
RIVE_MAKE_ENUM_BITSET(RenderPassOptionsVulkan);
constexpr static int RENDER_PASS_OPTION_COUNT = 6;
// This masks out RenderPassOptions that don't affect layout, allowing different
// render passes to reference the same VkPipelineLayout where possible.
// e.g., RenderPassOptions that deal with interrupting a render pass don't
// affect layout.
constexpr static RenderPassOptionsVulkan RENDER_PASS_OPTIONS_LAYOUT_MASK =
~(RenderPassOptionsVulkan::rasterOrderingInterruptible |
RenderPassOptionsVulkan::rasterOrderingResume);
class RenderPassVulkan
{
public:
constexpr static uint64_t FORMAT_BIT_COUNT = 9;
constexpr static uint64_t LOAD_OP_BIT_COUNT = 2;
constexpr static uint64_t KEY_NO_INTERLOCK_MODE_BIT_COUNT =
FORMAT_BIT_COUNT + RENDER_PASS_OPTION_COUNT + LOAD_OP_BIT_COUNT;
constexpr static uint64_t KEY_BIT_COUNT =
KEY_NO_INTERLOCK_MODE_BIT_COUNT + gpu::INTERLOCK_MODE_BIT_COUNT;
static_assert(KEY_BIT_COUNT <= 32);
// Shader unique keys also include the interlock mode, so we don't always
// need it in the render pass key.
static uint32_t KeyNoInterlockMode(RenderPassOptionsVulkan,
VkFormat renderTargetFormat,
gpu::LoadAction);
static uint32_t Key(gpu::InterlockMode,
RenderPassOptionsVulkan,
VkFormat renderTargetFormat,
gpu::LoadAction);
RenderPassVulkan(PipelineManagerVulkan*,
gpu::InterlockMode,
RenderPassOptionsVulkan,
VkFormat renderTargetFormat,
gpu::LoadAction);
~RenderPassVulkan();
RenderPassVulkan(const RenderPassVulkan&) = delete;
RenderPassVulkan& operator=(const RenderPassVulkan&) = delete;
const DrawPipelineLayoutVulkan* drawPipelineLayout() const
{
return m_drawPipelineLayout;
}
operator VkRenderPass() const { return m_renderPass; }
private:
const rcp<VulkanContext> m_vk;
// Raw pointer into impl->m_drawPipelineLayouts. RenderContextVulkanImpl
// ensures the pipline layouts outlive this RenderPass instance.
const DrawPipelineLayoutVulkan* m_drawPipelineLayout = nullptr;
VkRenderPass m_renderPass = VK_NULL_HANDLE;
};
} // namespace rive::gpu