blob: e16e14419cba057e42dd4aa828ddd0753741c96b [file] [log] [blame]
/*
* Copyright 2025 Rive
*/
#include "draw_pipeline_layout_vulkan.hpp"
#include "rive/renderer/stack_vector.hpp"
#include "rive/renderer/vulkan/vulkan_context.hpp"
#include "rive/renderer/vulkan/render_context_vulkan_impl.hpp"
#include "shaders/constants.glsl"
#include "pipeline_manager_vulkan.hpp"
namespace rive::gpu
{
DrawPipelineLayoutVulkan::DrawPipelineLayoutVulkan(
PipelineManagerVulkan* impl,
gpu::InterlockMode interlockMode,
DrawPipelineLayoutVulkan::Options options) :
m_vk(ref_rcp(impl->vulkanContext())),
m_interlockMode(interlockMode),
m_options(options)
{
// PLS planes get bound per flush as input attachments or storage
// textures.
StackVector<VkDescriptorSetLayoutBinding, PLS_PLANE_COUNT>
plsLayoutBindings;
if (!(m_options & Options::fixedFunctionColorOutput))
{
plsLayoutBindings.push_back({
.binding = COLOR_PLANE_IDX,
.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
});
}
if (interlockMode == gpu::InterlockMode::rasterOrdering ||
interlockMode == gpu::InterlockMode::atomics)
{
plsLayoutBindings.push_back({
.binding = CLIP_PLANE_IDX,
.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
});
if (interlockMode == gpu::InterlockMode::rasterOrdering)
{
plsLayoutBindings.push_back({
.binding = SCRATCH_COLOR_PLANE_IDX,
.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
});
}
plsLayoutBindings.push_back({
.binding = COVERAGE_PLANE_IDX,
.descriptorType = m_interlockMode == gpu::InterlockMode::atomics
? VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
: VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
});
}
else if (interlockMode == gpu::InterlockMode::msaa)
{
// TODO: pipeline layouts aren't currently keyed by loadAction, but if
// they were, we could only include this binding with
// preserveRenderTarget.
plsLayoutBindings.push_back({
.binding = MSAA_COLOR_SEED_IDX,
.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
});
}
if (plsLayoutBindings.size() > 0)
{
VkDescriptorSetLayoutCreateInfo plsLayoutInfo = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = plsLayoutBindings.size(),
.pBindings = plsLayoutBindings.data(),
};
VK_CHECK(
m_vk->CreateDescriptorSetLayout(m_vk->device,
&plsLayoutInfo,
nullptr,
&m_plsTextureDescriptorSetLayout));
}
VkDescriptorSetLayout pipelineDescriptorSetLayouts[] = {
impl->perFlushDescriptorSetLayout(),
impl->perDrawDescriptorSetLayout(),
impl->immutableSamplerDescriptorSetLayout(),
m_plsTextureDescriptorSetLayout,
};
static_assert(COLOR_PLANE_IDX == 0);
static_assert(CLIP_PLANE_IDX == 1);
static_assert(SCRATCH_COLOR_PLANE_IDX == 2);
static_assert(COVERAGE_PLANE_IDX == 3);
static_assert(BINDINGS_SET_COUNT == 4);
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.setLayoutCount = m_plsTextureDescriptorSetLayout != VK_NULL_HANDLE
? BINDINGS_SET_COUNT
: BINDINGS_SET_COUNT - 1u,
.pSetLayouts = pipelineDescriptorSetLayouts,
};
VK_CHECK(m_vk->CreatePipelineLayout(m_vk->device,
&pipelineLayoutCreateInfo,
nullptr,
&m_pipelineLayout));
}
DrawPipelineLayoutVulkan::~DrawPipelineLayoutVulkan()
{
m_vk->DestroyDescriptorSetLayout(m_vk->device,
m_plsTextureDescriptorSetLayout,
nullptr);
m_vk->DestroyPipelineLayout(m_vk->device, m_pipelineLayout, nullptr);
}
uint32_t DrawPipelineLayoutVulkan::colorAttachmentCount(
uint32_t subpassIndex) const
{
switch (m_interlockMode)
{
case gpu::InterlockMode::rasterOrdering:
assert(subpassIndex == 0);
return 4;
case gpu::InterlockMode::atomics:
assert(subpassIndex <= 1);
return 2u - subpassIndex; // Subpass 0 -> 2, subpass 1 -> 1.
case gpu::InterlockMode::clockwiseAtomic:
assert(subpassIndex == 0);
return 1;
case gpu::InterlockMode::msaa:
assert(subpassIndex == 0 || subpassIndex == 1);
return 1;
}
RIVE_UNREACHABLE();
}
} // namespace rive::gpu