mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-10-11 22:49:56 +00:00
GS:VK: Cleanup render pass handling.
Rewrite render pass builder. Make a begin/end present render pass function. Rename `depth_sampling` to `depth_feedback`.
This commit is contained in:
@@ -144,6 +144,13 @@ static constexpr const char* s_required_device_extensions[] = {
|
||||
VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME,
|
||||
};
|
||||
|
||||
static constexpr VkPipelineStageFlags2 s_color_feedback_src_stage = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
static constexpr VkPipelineStageFlags2 s_color_feedback_src_access = VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT
|
||||
| VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
static constexpr VkPipelineStageFlags2 s_depth_feedback_src_stage = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT
|
||||
| VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT;
|
||||
static constexpr VkPipelineStageFlags2 s_depth_feedback_src_access = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT
|
||||
| VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||
GSDeviceVK::GSDeviceVK()
|
||||
{
|
||||
#ifdef ENABLE_OGL_DEBUG
|
||||
@@ -1059,7 +1066,7 @@ VkRenderPass GSDeviceVK::GetRenderPass(VkFormat color_format, VkFormat depth_for
|
||||
VkAttachmentLoadOp color_load_op, VkAttachmentStoreOp color_store_op,
|
||||
VkAttachmentLoadOp depth_load_op, VkAttachmentStoreOp depth_store_op,
|
||||
VkAttachmentLoadOp stencil_load_op, VkAttachmentStoreOp stencil_store_op,
|
||||
bool color_feedback_loop, bool depth_sampling)
|
||||
bool color_feedback_loop, bool depth_feedback_loop)
|
||||
{
|
||||
RenderPassCacheKey key = {};
|
||||
key.color_format = color_format;
|
||||
@@ -1071,7 +1078,7 @@ VkRenderPass GSDeviceVK::GetRenderPass(VkFormat color_format, VkFormat depth_for
|
||||
key.stencil_load_op = stencil_load_op;
|
||||
key.stencil_store_op = stencil_store_op;
|
||||
key.color_feedback_loop = color_feedback_loop;
|
||||
key.depth_sampling = depth_sampling;
|
||||
key.depth_feedback_loop = depth_feedback_loop;
|
||||
|
||||
auto it = m_render_pass_cache.find(key.key);
|
||||
if (it != m_render_pass_cache.end())
|
||||
@@ -1669,129 +1676,63 @@ void GSDeviceVK::DisableDebugUtils()
|
||||
|
||||
VkRenderPass GSDeviceVK::CreateCachedRenderPass(RenderPassCacheKey key)
|
||||
{
|
||||
VkAttachmentReference color_reference;
|
||||
VkAttachmentReference* color_reference_ptr = nullptr;
|
||||
VkAttachmentReference depth_reference;
|
||||
VkAttachmentReference* depth_reference_ptr = nullptr;
|
||||
std::array<VkAttachmentReference, 2> input_reference;
|
||||
u32 num_subpass_inputs = 0;
|
||||
std::array<VkSubpassDependency, 2> subpass_dependencies;
|
||||
u32 num_subpass_dependencies = 0;
|
||||
std::array<VkAttachmentDescription, 2> attachments;
|
||||
u32 num_attachments = 0;
|
||||
Vulkan::RenderPassBuilder rpb;
|
||||
|
||||
const GSTextureVK::Layout color_layout =
|
||||
key.color_feedback_loop ? GSTextureVK::Layout::FeedbackLoop : GSTextureVK::Layout::ColorAttachment;
|
||||
|
||||
const GSTextureVK::Layout depth_layout =
|
||||
key.depth_feedback_loop ?
|
||||
(m_features.depth_feedback ? GSTextureVK::Layout::FeedbackLoop : GSTextureVK::Layout::General) :
|
||||
GSTextureVK::Layout::DepthStencilAttachment;
|
||||
|
||||
const VkDependencyFlags feedback_dependency = GetFeedbackBarrierDependencyFlags();
|
||||
|
||||
if (key.color_feedback_loop)
|
||||
{
|
||||
rpb.SetColorFeedbackBarrier(
|
||||
s_color_feedback_src_stage, s_color_feedback_src_access,
|
||||
VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, static_cast<VkAccessFlags>(GetFeedbackLoopInputAccessFlags()),
|
||||
feedback_dependency);
|
||||
if (m_features.framebuffer_fetch)
|
||||
rpb.AddSubpassFlags(VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_EXT);
|
||||
}
|
||||
|
||||
if (key.depth_feedback_loop)
|
||||
{
|
||||
rpb.SetDepthFeedbackBarrier(
|
||||
s_depth_feedback_src_stage, s_depth_feedback_src_access,
|
||||
VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, static_cast<VkAccessFlags>(GetFeedbackLoopInputAccessFlags()),
|
||||
feedback_dependency);
|
||||
}
|
||||
|
||||
if (key.color_format != VK_FORMAT_UNDEFINED)
|
||||
{
|
||||
const VkImageLayout layout = key.color_feedback_loop ? GetFeedbackLoopLayout() : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
VkAttachmentDescription& attachment = attachments[num_attachments] = {};
|
||||
attachment.format = static_cast<VkFormat>(key.color_format);
|
||||
attachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
attachment.loadOp = static_cast<VkAttachmentLoadOp>(key.color_load_op);
|
||||
attachment.storeOp = static_cast<VkAttachmentStoreOp>(key.color_store_op);
|
||||
attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
attachment.initialLayout = layout;
|
||||
attachment.finalLayout = layout;
|
||||
color_reference.attachment = num_attachments;
|
||||
color_reference.layout = layout;
|
||||
color_reference_ptr = &color_reference;
|
||||
|
||||
if (key.color_feedback_loop)
|
||||
{
|
||||
if (!UseFeedbackLoopLayout())
|
||||
{
|
||||
input_reference[num_subpass_inputs].attachment = num_attachments;
|
||||
input_reference[num_subpass_inputs].layout = layout;
|
||||
num_subpass_inputs++;
|
||||
}
|
||||
|
||||
if (!m_features.framebuffer_fetch)
|
||||
{
|
||||
// don't need the framebuffer-local dependency when we have rasterization order attachment access
|
||||
VkSubpassDependency& subpass_dependency = subpass_dependencies[num_subpass_dependencies++];
|
||||
subpass_dependency.srcSubpass = 0;
|
||||
subpass_dependency.dstSubpass = 0;
|
||||
subpass_dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
subpass_dependency.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
subpass_dependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
subpass_dependency.dstAccessMask = static_cast<VkAccessFlags>(GetFeedbackLoopInputAccessFlags());
|
||||
subpass_dependency.dependencyFlags = GetFeedbackBarrierDependencyFlags();
|
||||
}
|
||||
}
|
||||
|
||||
num_attachments++;
|
||||
rpb.AddColorAttachment(
|
||||
GSTextureVK::GetVkImageLayout(color_layout),
|
||||
static_cast<VkFormat>(key.color_format),
|
||||
static_cast<VkAttachmentLoadOp>(key.color_load_op),
|
||||
static_cast<VkAttachmentStoreOp>(key.color_store_op),
|
||||
key.color_feedback_loop,
|
||||
!UseFeedbackLoopLayout(),
|
||||
!m_features.framebuffer_fetch);
|
||||
}
|
||||
|
||||
if (key.depth_format != VK_FORMAT_UNDEFINED)
|
||||
{
|
||||
const VkImageLayout layout =
|
||||
key.depth_sampling ?
|
||||
((m_features.depth_feedback && UseFeedbackLoopLayout()) ?
|
||||
VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT :
|
||||
VK_IMAGE_LAYOUT_GENERAL) :
|
||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
VkAttachmentDescription& attachment = attachments[num_attachments] = {};
|
||||
attachment.format = static_cast<VkFormat>(key.depth_format);
|
||||
attachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
attachment.loadOp = static_cast<VkAttachmentLoadOp>(key.depth_load_op);
|
||||
attachment.storeOp = static_cast<VkAttachmentStoreOp>(key.depth_store_op);
|
||||
attachment.stencilLoadOp = static_cast<VkAttachmentLoadOp>(key.stencil_load_op);
|
||||
attachment.stencilStoreOp = static_cast<VkAttachmentStoreOp>(key.stencil_store_op);
|
||||
attachment.initialLayout = layout;
|
||||
attachment.finalLayout = layout;
|
||||
depth_reference.attachment = num_attachments;
|
||||
depth_reference.layout = layout;
|
||||
depth_reference_ptr = &depth_reference;
|
||||
|
||||
if (key.depth_sampling)
|
||||
{
|
||||
if (!UseFeedbackLoopLayout())
|
||||
{
|
||||
input_reference[num_subpass_inputs].attachment = num_attachments;
|
||||
input_reference[num_subpass_inputs].layout = layout;
|
||||
num_subpass_inputs++;
|
||||
}
|
||||
|
||||
if (!m_features.framebuffer_fetch)
|
||||
{
|
||||
// don't need the framebuffer-local dependency when we have rasterization order attachment access
|
||||
VkSubpassDependency& subpass_dependency = subpass_dependencies[num_subpass_dependencies++];
|
||||
subpass_dependency.srcSubpass = 0;
|
||||
subpass_dependency.dstSubpass = 0;
|
||||
subpass_dependency.srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||
subpass_dependency.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
subpass_dependency.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||
subpass_dependency.dstAccessMask = static_cast<VkAccessFlags>(GetFeedbackLoopInputAccessFlags());
|
||||
subpass_dependency.dependencyFlags = GetFeedbackBarrierDependencyFlags();
|
||||
}
|
||||
}
|
||||
|
||||
num_attachments++;
|
||||
rpb.AddDepthStencilAttachment(
|
||||
GSTextureVK::GetVkImageLayout(depth_layout),
|
||||
static_cast<VkFormat>(key.depth_format),
|
||||
static_cast<VkAttachmentLoadOp>(key.depth_load_op),
|
||||
static_cast<VkAttachmentStoreOp>(key.depth_store_op),
|
||||
static_cast<VkAttachmentLoadOp>(key.stencil_load_op),
|
||||
static_cast<VkAttachmentStoreOp>(key.stencil_store_op),
|
||||
key.depth_feedback_loop,
|
||||
!UseFeedbackLoopLayout(),
|
||||
!m_features.framebuffer_fetch);
|
||||
}
|
||||
|
||||
VkSubpassDescription subpass = {};
|
||||
if (key.color_feedback_loop && m_features.framebuffer_fetch)
|
||||
subpass.flags |= VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_EXT;
|
||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
subpass.inputAttachmentCount = num_subpass_inputs;
|
||||
subpass.pInputAttachments = num_subpass_inputs ? input_reference.data() : nullptr;
|
||||
subpass.colorAttachmentCount = color_reference_ptr ? 1 : 0;
|
||||
subpass.pColorAttachments = color_reference_ptr;
|
||||
subpass.pDepthStencilAttachment = depth_reference_ptr;
|
||||
|
||||
VkRenderPassCreateInfo pass_info = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO};
|
||||
pass_info.attachmentCount = num_attachments;
|
||||
pass_info.pAttachments = attachments.data();
|
||||
pass_info.subpassCount = 1;
|
||||
pass_info.pSubpasses = &subpass;
|
||||
pass_info.dependencyCount = num_subpass_dependencies;
|
||||
pass_info.pDependencies = num_subpass_dependencies ? subpass_dependencies.data() : nullptr;
|
||||
|
||||
VkRenderPass pass;
|
||||
const VkResult res = vkCreateRenderPass(m_device, &pass_info, nullptr, &pass);
|
||||
if (res != VK_SUCCESS)
|
||||
{
|
||||
LOG_VULKAN_ERROR(res, "vkCreateRenderPass failed: ");
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
VkRenderPass pass = rpb.Create(m_device);
|
||||
|
||||
m_render_pass_cache.emplace(key.key, pass);
|
||||
return pass;
|
||||
@@ -2588,17 +2529,13 @@ GSDevice::PresentResult GSDeviceVK::BeginPresent(bool frame_skip)
|
||||
if (!frame_skip && m_current)
|
||||
static_cast<GSTextureVK*>(m_current)->TransitionToLayout(GSTextureVK::Layout::ShaderReadOnly);
|
||||
|
||||
const VkFramebuffer fb = swap_chain_texture->GetFramebuffer(false);
|
||||
if (fb == VK_NULL_HANDLE)
|
||||
return GSDevice::PresentResult::FrameSkipped;
|
||||
GSVector4i render_area(0, 0, swap_chain_texture->GetWidth(), swap_chain_texture->GetHeight());
|
||||
|
||||
VkRenderPassBeginInfo rp = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO};
|
||||
rp.renderPass = GetRenderPass(swap_chain_texture->GetVkFormat(), VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE);
|
||||
rp.framebuffer = fb;
|
||||
rp.renderArea = {{0, 0}, {static_cast<u32>(swap_chain_texture->GetWidth()), static_cast<u32>(swap_chain_texture->GetHeight())}};
|
||||
rp.clearValueCount = 1;
|
||||
rp.pClearValues = &s_present_clear_color;
|
||||
vkCmdBeginRenderPass(GetCurrentCommandBuffer(), &rp, VK_SUBPASS_CONTENTS_INLINE);
|
||||
if (!BeginPresentRenderPass(GetRenderPass(swap_chain_texture->GetVkFormat(), VK_FORMAT_UNDEFINED,
|
||||
VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE), render_area, swap_chain_texture))
|
||||
{
|
||||
return GSDevice::PresentResult::FrameSkipped;
|
||||
}
|
||||
|
||||
const VkViewport vp{0.0f, 0.0f, static_cast<float>(swap_chain_texture->GetWidth()), static_cast<float>(swap_chain_texture->GetHeight()), 0.0f, 1.0f};
|
||||
const VkRect2D scissor{{0, 0}, {static_cast<u32>(swap_chain_texture->GetWidth()), static_cast<u32>(swap_chain_texture->GetHeight())}};
|
||||
@@ -2612,10 +2549,8 @@ void GSDeviceVK::EndPresent()
|
||||
{
|
||||
RenderImGui();
|
||||
|
||||
VkCommandBuffer cmdbuffer = GetCurrentCommandBuffer();
|
||||
vkCmdEndRenderPass(cmdbuffer);
|
||||
m_is_presenting = false;
|
||||
m_swap_chain->GetCurrentTexture()->TransitionToLayout(cmdbuffer, GSTextureVK::Layout::PresentSrc);
|
||||
EndPresentRenderPass();
|
||||
m_swap_chain->GetCurrentTexture()->TransitionToLayout(GetCurrentCommandBuffer(), GSTextureVK::Layout::PresentSrc);
|
||||
g_perfmon.Put(GSPerfMon::RenderPasses, 1);
|
||||
|
||||
SubmitCommandBuffer(m_swap_chain.get());
|
||||
@@ -4166,24 +4101,29 @@ bool GSDeviceVK::CreatePipelineLayouts()
|
||||
|
||||
bool GSDeviceVK::CreateRenderPasses()
|
||||
{
|
||||
#define GET(dest, rt, depth, fbl, dsp, opa, opb, opc) \
|
||||
const auto CreateHelper = [&](VkFormat rt, VkFormat depth, bool feedback_rt, bool feedback_depth,
|
||||
VkAttachmentLoadOp load_rt, VkAttachmentLoadOp load_depth, VkAttachmentLoadOp load_stencil)
|
||||
{
|
||||
return GetRenderPass(
|
||||
rt,
|
||||
depth,
|
||||
(rt != VK_FORMAT_UNDEFINED) ? load_rt : VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||
(rt != VK_FORMAT_UNDEFINED) ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
||||
(depth != VK_FORMAT_UNDEFINED) ? load_depth : VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||
(depth != VK_FORMAT_UNDEFINED) ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
||||
(depth != VK_FORMAT_UNDEFINED) ? load_stencil : VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||
VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
||||
feedback_rt,
|
||||
feedback_depth
|
||||
);
|
||||
};
|
||||
|
||||
#define GET(dest, rt, depth, fbc, fbd, opc, opd, ops) \
|
||||
do \
|
||||
{ \
|
||||
dest = GetRenderPass( \
|
||||
(rt), (depth), ((rt) != VK_FORMAT_UNDEFINED) ? (opa) : VK_ATTACHMENT_LOAD_OP_DONT_CARE, /* color load */ \
|
||||
((rt) != VK_FORMAT_UNDEFINED) ? VK_ATTACHMENT_STORE_OP_STORE : \
|
||||
VK_ATTACHMENT_STORE_OP_DONT_CARE, /* color store */ \
|
||||
((depth) != VK_FORMAT_UNDEFINED) ? (opb) : VK_ATTACHMENT_LOAD_OP_DONT_CARE, /* depth load */ \
|
||||
((depth) != VK_FORMAT_UNDEFINED) ? VK_ATTACHMENT_STORE_OP_STORE : \
|
||||
VK_ATTACHMENT_STORE_OP_DONT_CARE, /* depth store */ \
|
||||
((depth) != VK_FORMAT_UNDEFINED) ? (opc) : VK_ATTACHMENT_LOAD_OP_DONT_CARE, /* stencil load */ \
|
||||
VK_ATTACHMENT_STORE_OP_DONT_CARE, /* stencil store */ \
|
||||
(fbl), /* feedback loop */ \
|
||||
(dsp) /* depth sampling */ \
|
||||
); \
|
||||
if (dest == VK_NULL_HANDLE) \
|
||||
return false; \
|
||||
} while (0)
|
||||
(dest) = CreateHelper(rt, depth, fbc, fbd, opc, opd, ops); \
|
||||
if (!(dest)) return false; \
|
||||
} while (false)
|
||||
|
||||
const VkFormat rt_format = LookupNativeFormat(GSTexture::Format::Color);
|
||||
const VkFormat colclip_rt_format = LookupNativeFormat(GSTexture::Format::ColorClip);
|
||||
@@ -4197,23 +4137,24 @@ bool GSDeviceVK::CreateRenderPasses()
|
||||
{
|
||||
for (u32 stencil = 0; stencil < 2; stencil++)
|
||||
{
|
||||
for (u32 fbl = 0; fbl < 2; fbl++)
|
||||
for (u32 feedback_rt = 0; feedback_rt < 2; feedback_rt++)
|
||||
{
|
||||
for (u32 dsp = 0; dsp < 2; dsp++)
|
||||
for (u32 feedback_depth = 0; feedback_depth < 2; feedback_depth++)
|
||||
{
|
||||
for (u32 opa = VK_ATTACHMENT_LOAD_OP_LOAD; opa <= VK_ATTACHMENT_LOAD_OP_DONT_CARE; opa++)
|
||||
for (u32 load_rt = VK_ATTACHMENT_LOAD_OP_LOAD; load_rt <= VK_ATTACHMENT_LOAD_OP_DONT_CARE; load_rt++)
|
||||
{
|
||||
for (u32 opb = VK_ATTACHMENT_LOAD_OP_LOAD; opb <= VK_ATTACHMENT_LOAD_OP_DONT_CARE; opb++)
|
||||
for (u32 load_depth = VK_ATTACHMENT_LOAD_OP_LOAD; load_depth <= VK_ATTACHMENT_LOAD_OP_DONT_CARE; load_depth++)
|
||||
{
|
||||
const VkFormat rp_rt_format =
|
||||
(rt != 0) ? ((colclip != 0) ? colclip_rt_format : rt_format) : VK_FORMAT_UNDEFINED;
|
||||
const VkFormat rp_rt_format = (rt != 0) ? ((colclip != 0) ? colclip_rt_format : rt_format) : VK_FORMAT_UNDEFINED;
|
||||
const VkFormat rp_depth_format = (ds != 0) ? depth_format : VK_FORMAT_UNDEFINED;
|
||||
const VkAttachmentLoadOp opc = (!stencil || !m_features.stencil_buffer) ?
|
||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE :
|
||||
VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
GET(m_tfx_render_pass[rt][ds][colclip][stencil][fbl][dsp][opa][opb], rp_rt_format,
|
||||
rp_depth_format, (fbl != 0), (dsp != 0), static_cast<VkAttachmentLoadOp>(opa),
|
||||
static_cast<VkAttachmentLoadOp>(opb), static_cast<VkAttachmentLoadOp>(opc));
|
||||
const VkAttachmentLoadOp load_stencil = (!stencil || !m_features.stencil_buffer) ?
|
||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
|
||||
GET(m_tfx_render_pass[rt][ds][colclip][stencil][feedback_rt][feedback_depth][load_rt][load_depth],
|
||||
rp_rt_format, rp_depth_format, feedback_rt, feedback_depth,
|
||||
static_cast<VkAttachmentLoadOp>(load_rt),
|
||||
static_cast<VkAttachmentLoadOp>(load_depth),
|
||||
static_cast<VkAttachmentLoadOp>(load_stencil));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5703,9 +5644,9 @@ void GSDeviceVK::BeginRenderPass(VkRenderPass rp, const GSVector4i& rect)
|
||||
begin_info.renderArea.offset.y = rect.y;
|
||||
begin_info.renderArea.extent.width = rect.width();
|
||||
begin_info.renderArea.extent.height = rect.height();
|
||||
vkCmdBeginRenderPass(GetCurrentCommandBuffer(), &begin_info, VK_SUBPASS_CONTENTS_INLINE);
|
||||
|
||||
m_command_buffer_render_passes++;
|
||||
vkCmdBeginRenderPass(GetCurrentCommandBuffer(), &begin_info, VK_SUBPASS_CONTENTS_INLINE);
|
||||
}
|
||||
|
||||
void GSDeviceVK::BeginClearRenderPass(VkRenderPass rp, const GSVector4i& rect, const VkClearValue* cv, u32 cv_count)
|
||||
@@ -5726,6 +5667,8 @@ void GSDeviceVK::BeginClearRenderPass(VkRenderPass rp, const GSVector4i& rect, c
|
||||
begin_info.clearValueCount = cv_count;
|
||||
begin_info.pClearValues = cv;
|
||||
vkCmdBeginRenderPass(GetCurrentCommandBuffer(), &begin_info, VK_SUBPASS_CONTENTS_INLINE);
|
||||
|
||||
m_command_buffer_render_passes++;
|
||||
}
|
||||
|
||||
void GSDeviceVK::BeginClearRenderPass(VkRenderPass rp, const GSVector4i& rect, u32 clear_color)
|
||||
@@ -5743,6 +5686,30 @@ void GSDeviceVK::BeginClearRenderPass(VkRenderPass rp, const GSVector4i& rect, f
|
||||
BeginClearRenderPass(rp, rect, &cv, 1);
|
||||
}
|
||||
|
||||
bool GSDeviceVK::BeginPresentRenderPass(VkRenderPass rp, const GSVector4i& rect, GSTextureVK* swap_chain)
|
||||
{
|
||||
if (m_current_render_pass != VK_NULL_HANDLE)
|
||||
EndRenderPass();
|
||||
|
||||
VkFramebuffer fb = swap_chain->GetFramebuffer(false);
|
||||
|
||||
if (fb == VK_NULL_HANDLE)
|
||||
return false;
|
||||
|
||||
VkRenderPassBeginInfo begin_info = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO};
|
||||
begin_info.renderPass = rp;
|
||||
begin_info.framebuffer = fb;
|
||||
begin_info.renderArea.offset.x = rect.x;
|
||||
begin_info.renderArea.offset.y = rect.y;
|
||||
begin_info.renderArea.extent.width = rect.width();
|
||||
begin_info.renderArea.extent.height = rect.height();
|
||||
begin_info.clearValueCount = 1;
|
||||
begin_info.pClearValues = &s_present_clear_color;
|
||||
vkCmdBeginRenderPass(GetCurrentCommandBuffer(), &begin_info, VK_SUBPASS_CONTENTS_INLINE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GSDeviceVK::EndRenderPass()
|
||||
{
|
||||
if (m_current_render_pass == VK_NULL_HANDLE)
|
||||
@@ -5754,6 +5721,15 @@ void GSDeviceVK::EndRenderPass()
|
||||
vkCmdEndRenderPass(GetCurrentCommandBuffer());
|
||||
}
|
||||
|
||||
void GSDeviceVK::EndPresentRenderPass()
|
||||
{
|
||||
g_perfmon.Put(GSPerfMon::RenderPasses, 1);
|
||||
|
||||
vkCmdEndRenderPass(GetCurrentCommandBuffer());
|
||||
|
||||
m_is_presenting = false;
|
||||
}
|
||||
|
||||
void GSDeviceVK::SetViewport(const VkViewport& viewport)
|
||||
{
|
||||
if (std::memcmp(&viewport, &m_viewport, sizeof(VkViewport)) == 0)
|
||||
@@ -6688,8 +6664,8 @@ void GSDeviceVK::FeedbackBarrier(GSTextureVK* rt, GSTextureVK* ds)
|
||||
if (rt)
|
||||
{
|
||||
VkImageMemoryBarrier2& barrier = barriers[num_barriers++] = barrier_template;
|
||||
barrier.srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
barrier.srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
barrier.srcStageMask = s_color_feedback_src_stage;
|
||||
barrier.srcAccessMask = s_color_feedback_src_access;
|
||||
barrier.image = rt->GetImage();
|
||||
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
}
|
||||
@@ -6697,8 +6673,8 @@ void GSDeviceVK::FeedbackBarrier(GSTextureVK* rt, GSTextureVK* ds)
|
||||
if (ds)
|
||||
{
|
||||
VkImageMemoryBarrier2& barrier = barriers[num_barriers++] = barrier_template;
|
||||
barrier.srcStageMask = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT;
|
||||
barrier.srcAccessMask = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||
barrier.srcStageMask = s_depth_feedback_src_stage;
|
||||
barrier.srcAccessMask = s_depth_feedback_src_access;
|
||||
barrier.image = ds->GetImage();
|
||||
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
}
|
||||
|
||||
@@ -89,8 +89,8 @@ public:
|
||||
VkAttachmentLoadOp depth_load_op = VK_ATTACHMENT_LOAD_OP_LOAD,
|
||||
VkAttachmentStoreOp depth_store_op = VK_ATTACHMENT_STORE_OP_STORE,
|
||||
VkAttachmentLoadOp stencil_load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||
VkAttachmentStoreOp stencil_store_op = VK_ATTACHMENT_STORE_OP_DONT_CARE, bool color_feedback_loop = false,
|
||||
bool depth_sampling = false);
|
||||
VkAttachmentStoreOp stencil_store_op = VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
||||
bool color_feedback_loop = false, bool depth_feedback_loop = false);
|
||||
|
||||
// Gets a non-clearing version of the specified render pass. Slow, don't call in hot path.
|
||||
VkRenderPass GetRenderPassForRestarting(VkRenderPass pass);
|
||||
@@ -176,7 +176,7 @@ private:
|
||||
u32 stencil_load_op : 2;
|
||||
u32 stencil_store_op : 1;
|
||||
u32 color_feedback_loop : 1;
|
||||
u32 depth_sampling : 1;
|
||||
u32 depth_feedback_loop : 1;
|
||||
};
|
||||
|
||||
u32 key;
|
||||
@@ -545,10 +545,10 @@ public:
|
||||
/// Returns true if Vulkan is suitable as a default for the devices in the system.
|
||||
static bool IsSuitableDefaultRenderer();
|
||||
|
||||
__fi VkRenderPass GetTFXRenderPass(bool rt, bool ds, bool colclip, bool stencil, bool fbl, bool dsp,
|
||||
VkAttachmentLoadOp rt_op, VkAttachmentLoadOp ds_op) const
|
||||
__fi VkRenderPass GetTFXRenderPass(bool rt, bool ds, bool colclip, bool stencil,
|
||||
bool rt_feedback, bool depth_feedback, VkAttachmentLoadOp rt_op, VkAttachmentLoadOp ds_op) const
|
||||
{
|
||||
return m_tfx_render_pass[rt][ds][colclip][stencil][fbl][dsp][rt_op][ds_op];
|
||||
return m_tfx_render_pass[rt][ds][colclip][stencil][rt_feedback][depth_feedback][rt_op][ds_op];
|
||||
}
|
||||
__fi VkSampler GetPointSampler() const { return m_point_sampler; }
|
||||
__fi VkSampler GetLinearSampler() const { return m_linear_sampler; }
|
||||
@@ -687,7 +687,9 @@ public:
|
||||
void BeginClearRenderPass(VkRenderPass rp, const GSVector4i& rect, const VkClearValue* cv, u32 cv_count);
|
||||
void BeginClearRenderPass(VkRenderPass rp, const GSVector4i& rect, u32 clear_color);
|
||||
void BeginClearRenderPass(VkRenderPass rp, const GSVector4i& rect, float depth, u8 stencil);
|
||||
bool BeginPresentRenderPass(VkRenderPass rp, const GSVector4i& rect, GSTextureVK* swap_chain);
|
||||
void EndRenderPass();
|
||||
void EndPresentRenderPass();
|
||||
|
||||
void SetViewport(const VkViewport& viewport);
|
||||
void SetScissor(const GSVector4i& scissor);
|
||||
|
||||
@@ -35,7 +35,7 @@ static constexpr const VkComponentMapping s_identity_swizzle {
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
};
|
||||
|
||||
static VkImageLayout GetVkImageLayout(GSTextureVK::Layout layout)
|
||||
VkImageLayout GSTextureVK::GetVkImageLayout(GSTextureVK::Layout layout)
|
||||
{
|
||||
static constexpr VkImageLayout s_vk_layout_mapping[] = {
|
||||
VK_IMAGE_LAYOUT_UNDEFINED, // Undefined
|
||||
|
||||
@@ -36,6 +36,8 @@ public:
|
||||
|
||||
~GSTextureVK() override;
|
||||
|
||||
static VkImageLayout GetVkImageLayout(Layout layout);
|
||||
|
||||
static std::unique_ptr<GSTextureVK> Create(Usage usage, Format format, int width, int height, int levels);
|
||||
static std::unique_ptr<GSTextureVK> Adopt(
|
||||
VkImage image, Usage usage, Format format, int width, int height, int levels, VkFormat vk_format);
|
||||
|
||||
@@ -115,6 +115,178 @@ void Vulkan::LogVulkanResult(const char* func_name, VkResult res, const char* ms
|
||||
Console.Error("(%s) %s (%d: %s)", func_name, real_msg.c_str(), static_cast<int>(res), VkResultToString(res));
|
||||
}
|
||||
|
||||
void Vulkan::RenderPassBuilder::SetColorFeedbackBarrier(
|
||||
VkPipelineStageFlags src_stage, VkAccessFlags src_access,
|
||||
VkPipelineStageFlags dst_stage, VkAccessFlags dst_access,
|
||||
VkDependencyFlags dependency)
|
||||
{
|
||||
m_feedback_barriers.color_src_stage = src_stage;
|
||||
m_feedback_barriers.color_src_access = src_access;
|
||||
m_feedback_barriers.color_dst_stage = dst_stage;
|
||||
m_feedback_barriers.color_dst_access = dst_access;
|
||||
m_feedback_barriers.color_dependency = dependency;
|
||||
}
|
||||
|
||||
void Vulkan::RenderPassBuilder::SetDepthFeedbackBarrier(
|
||||
VkPipelineStageFlags src_stage, VkAccessFlags src_access,
|
||||
VkPipelineStageFlags dst_stage, VkAccessFlags dst_access,
|
||||
VkDependencyFlags dependency)
|
||||
{
|
||||
m_feedback_barriers.depth_src_stage = src_stage;
|
||||
m_feedback_barriers.depth_src_access = src_access;
|
||||
m_feedback_barriers.depth_dst_stage = dst_stage;
|
||||
m_feedback_barriers.depth_dst_access = dst_access;
|
||||
m_feedback_barriers.depth_dependency = dependency;
|
||||
}
|
||||
|
||||
void Vulkan::RenderPassBuilder::AddColorAttachment(
|
||||
VkImageLayout layout, VkFormat format, VkAttachmentLoadOp load_op, VkAttachmentStoreOp store_op,
|
||||
bool feedback_loop, bool input_reference, bool subpass_self_dependency)
|
||||
{
|
||||
pxAssert(m_num_color_attachments < MAX_COLOR_ATTACHMENTS);
|
||||
|
||||
m_attachments[m_num_attachments].flags = 0;
|
||||
m_attachments[m_num_attachments].format = format;
|
||||
m_attachments[m_num_attachments].samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
m_attachments[m_num_attachments].loadOp = load_op;
|
||||
m_attachments[m_num_attachments].storeOp = store_op;
|
||||
m_attachments[m_num_attachments].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
m_attachments[m_num_attachments].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
m_attachments[m_num_attachments].initialLayout = layout;
|
||||
m_attachments[m_num_attachments].finalLayout = layout;
|
||||
|
||||
m_color_reference[m_num_color_attachments].attachment = m_num_attachments;
|
||||
m_color_reference[m_num_color_attachments].layout = layout;
|
||||
m_num_color_attachments++;
|
||||
|
||||
if (feedback_loop)
|
||||
{
|
||||
if (input_reference)
|
||||
{
|
||||
m_input_reference[m_num_subpass_inputs].attachment = m_num_attachments;
|
||||
m_input_reference[m_num_subpass_inputs].layout = layout;
|
||||
m_num_subpass_inputs++;
|
||||
}
|
||||
|
||||
if (subpass_self_dependency)
|
||||
{
|
||||
m_subpass_dependency[m_num_subpass_dependencies].srcSubpass = 0;
|
||||
m_subpass_dependency[m_num_subpass_dependencies].dstSubpass = 0;
|
||||
m_subpass_dependency[m_num_subpass_dependencies].srcStageMask = m_feedback_barriers.color_src_stage;
|
||||
m_subpass_dependency[m_num_subpass_dependencies].dstStageMask = m_feedback_barriers.color_dst_stage;
|
||||
m_subpass_dependency[m_num_subpass_dependencies].srcAccessMask = m_feedback_barriers.color_src_access;
|
||||
m_subpass_dependency[m_num_subpass_dependencies].dstAccessMask = m_feedback_barriers.color_dst_access;
|
||||
m_subpass_dependency[m_num_subpass_dependencies].dependencyFlags = m_feedback_barriers.color_dependency;
|
||||
m_num_subpass_dependencies++;
|
||||
}
|
||||
}
|
||||
|
||||
m_num_attachments++;
|
||||
}
|
||||
|
||||
void Vulkan::RenderPassBuilder::AddDepthStencilAttachment(
|
||||
VkImageLayout layout, VkFormat depth_format, VkAttachmentLoadOp depth_load_op, VkAttachmentStoreOp depth_store_op,
|
||||
VkAttachmentLoadOp stencil_load_op, VkAttachmentStoreOp stencil_store_op,
|
||||
bool feedback_loop, bool input_reference, bool subpass_self_dependency)
|
||||
{
|
||||
pxAssert(m_num_attachments < std::size(m_attachments));
|
||||
|
||||
m_attachments[m_num_attachments].flags = 0;
|
||||
m_attachments[m_num_attachments].format = depth_format;
|
||||
m_attachments[m_num_attachments].samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
m_attachments[m_num_attachments].loadOp = depth_load_op;
|
||||
m_attachments[m_num_attachments].storeOp = depth_store_op;
|
||||
m_attachments[m_num_attachments].stencilLoadOp = stencil_load_op;
|
||||
m_attachments[m_num_attachments].stencilStoreOp = stencil_store_op;
|
||||
m_attachments[m_num_attachments].initialLayout = layout;
|
||||
m_attachments[m_num_attachments].finalLayout = layout;
|
||||
|
||||
pxAssert(!m_has_depth_attachment);
|
||||
m_depth_reference.attachment = m_num_attachments;
|
||||
m_depth_reference.layout = layout;
|
||||
m_has_depth_attachment = true;
|
||||
|
||||
if (feedback_loop)
|
||||
{
|
||||
if (input_reference)
|
||||
{
|
||||
m_input_reference[m_num_subpass_inputs].attachment = m_num_attachments;
|
||||
m_input_reference[m_num_subpass_inputs].layout = layout;
|
||||
m_num_subpass_inputs++;
|
||||
}
|
||||
|
||||
if (subpass_self_dependency)
|
||||
{
|
||||
m_subpass_dependency[m_num_subpass_dependencies].srcSubpass = 0;
|
||||
m_subpass_dependency[m_num_subpass_dependencies].dstSubpass = 0;
|
||||
m_subpass_dependency[m_num_subpass_dependencies].srcStageMask = m_feedback_barriers.depth_src_stage;
|
||||
m_subpass_dependency[m_num_subpass_dependencies].dstStageMask = m_feedback_barriers.depth_dst_stage;
|
||||
m_subpass_dependency[m_num_subpass_dependencies].srcAccessMask = m_feedback_barriers.depth_src_access;
|
||||
m_subpass_dependency[m_num_subpass_dependencies].dstAccessMask = m_feedback_barriers.depth_dst_access;
|
||||
m_subpass_dependency[m_num_subpass_dependencies].dependencyFlags = m_feedback_barriers.depth_dependency;
|
||||
m_num_subpass_dependencies++;
|
||||
}
|
||||
}
|
||||
|
||||
m_num_attachments++;
|
||||
}
|
||||
|
||||
void Vulkan::RenderPassBuilder::AddSubpassFlags(VkSubpassDescriptionFlags subpass_flags)
|
||||
{
|
||||
m_subpass_flags |= subpass_flags;
|
||||
}
|
||||
|
||||
VkRenderPass Vulkan::RenderPassBuilder::Create(VkDevice device)
|
||||
{
|
||||
VkSubpassDescription subpass = {};
|
||||
subpass.flags = m_subpass_flags;
|
||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
subpass.inputAttachmentCount = m_num_subpass_inputs;
|
||||
subpass.pInputAttachments = m_input_reference.data();
|
||||
subpass.colorAttachmentCount = m_num_color_attachments;
|
||||
subpass.pColorAttachments = m_color_reference.data();
|
||||
subpass.pDepthStencilAttachment = m_has_depth_attachment ? &m_depth_reference : nullptr;
|
||||
|
||||
VkRenderPassCreateInfo pass_info = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO};
|
||||
pass_info.attachmentCount = m_num_attachments;
|
||||
pass_info.pAttachments = m_attachments.data();
|
||||
pass_info.subpassCount = 1u;
|
||||
pass_info.pSubpasses = &subpass;
|
||||
pass_info.dependencyCount = m_num_subpass_dependencies;
|
||||
pass_info.pDependencies = m_subpass_dependency.data();
|
||||
|
||||
VkRenderPass pass;
|
||||
const VkResult res = vkCreateRenderPass(device, &pass_info, nullptr, &pass);
|
||||
if (res != VK_SUCCESS)
|
||||
{
|
||||
LOG_VULKAN_ERROR(res, "vkCreateRenderPass() failed: ");
|
||||
}
|
||||
|
||||
return pass;
|
||||
}
|
||||
|
||||
void Vulkan::RenderPassBuilder::Clear()
|
||||
{
|
||||
m_color_reference = {};
|
||||
m_num_color_attachments = 0;
|
||||
|
||||
m_depth_reference = {};
|
||||
m_has_depth_attachment = false;
|
||||
|
||||
m_input_reference = {};
|
||||
m_num_subpass_inputs = 0;
|
||||
|
||||
m_subpass_dependency = {};
|
||||
m_num_subpass_dependencies = 0;
|
||||
|
||||
m_attachments = {};
|
||||
m_num_attachments = 0;
|
||||
|
||||
m_feedback_barriers = {};
|
||||
|
||||
m_subpass_flags = 0;
|
||||
}
|
||||
|
||||
Vulkan::DescriptorSetLayoutBuilder::DescriptorSetLayoutBuilder()
|
||||
{
|
||||
Clear();
|
||||
@@ -957,96 +1129,6 @@ void Vulkan::FramebufferBuilder::SetRenderPass(VkRenderPass render_pass)
|
||||
m_ci.renderPass = render_pass;
|
||||
}
|
||||
|
||||
Vulkan::RenderPassBuilder::RenderPassBuilder()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void Vulkan::RenderPassBuilder::Clear()
|
||||
{
|
||||
m_ci = {};
|
||||
m_ci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||
m_attachments = {};
|
||||
m_attachment_references = {};
|
||||
m_num_attachment_references = 0;
|
||||
m_subpasses = {};
|
||||
}
|
||||
|
||||
VkRenderPass Vulkan::RenderPassBuilder::Create(VkDevice device, bool clear /*= true*/)
|
||||
{
|
||||
VkRenderPass rp;
|
||||
VkResult res = vkCreateRenderPass(device, &m_ci, nullptr, &rp);
|
||||
if (res != VK_SUCCESS)
|
||||
{
|
||||
LOG_VULKAN_ERROR(res, "vkCreateRenderPass() failed: ");
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
return rp;
|
||||
}
|
||||
|
||||
u32 Vulkan::RenderPassBuilder::AddAttachment(VkFormat format, VkSampleCountFlagBits samples, VkAttachmentLoadOp load_op,
|
||||
VkAttachmentStoreOp store_op, VkImageLayout initial_layout, VkImageLayout final_layout)
|
||||
{
|
||||
pxAssert(m_ci.attachmentCount < MAX_ATTACHMENTS);
|
||||
|
||||
const u32 index = m_ci.attachmentCount;
|
||||
VkAttachmentDescription& ad = m_attachments[index];
|
||||
ad.format = format;
|
||||
ad.samples = samples;
|
||||
ad.loadOp = load_op;
|
||||
ad.storeOp = store_op;
|
||||
ad.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
ad.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
ad.initialLayout = initial_layout;
|
||||
ad.finalLayout = final_layout;
|
||||
|
||||
m_ci.attachmentCount++;
|
||||
m_ci.pAttachments = m_attachments.data();
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
u32 Vulkan::RenderPassBuilder::AddSubpass()
|
||||
{
|
||||
pxAssert(m_ci.subpassCount < MAX_SUBPASSES);
|
||||
|
||||
const u32 index = m_ci.subpassCount;
|
||||
VkSubpassDescription& sp = m_subpasses[index];
|
||||
sp.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
|
||||
m_ci.subpassCount++;
|
||||
m_ci.pSubpasses = m_subpasses.data();
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void Vulkan::RenderPassBuilder::AddSubpassColorAttachment(u32 subpass, u32 attachment, VkImageLayout layout)
|
||||
{
|
||||
pxAssert(subpass < m_ci.subpassCount && m_num_attachment_references < MAX_ATTACHMENT_REFERENCES);
|
||||
|
||||
VkAttachmentReference& ar = m_attachment_references[m_num_attachment_references++];
|
||||
ar.attachment = attachment;
|
||||
ar.layout = layout;
|
||||
|
||||
VkSubpassDescription& sp = m_subpasses[subpass];
|
||||
if (sp.colorAttachmentCount == 0)
|
||||
sp.pColorAttachments = &ar;
|
||||
sp.colorAttachmentCount++;
|
||||
}
|
||||
|
||||
void Vulkan::RenderPassBuilder::AddSubpassDepthAttachment(u32 subpass, u32 attachment, VkImageLayout layout)
|
||||
{
|
||||
pxAssert(subpass < m_ci.subpassCount && m_num_attachment_references < MAX_ATTACHMENT_REFERENCES);
|
||||
|
||||
VkAttachmentReference& ar = m_attachment_references[m_num_attachment_references++];
|
||||
ar.attachment = attachment;
|
||||
ar.layout = layout;
|
||||
|
||||
VkSubpassDescription& sp = m_subpasses[subpass];
|
||||
sp.pDepthStencilAttachment = &ar;
|
||||
}
|
||||
|
||||
Vulkan::BufferViewBuilder::BufferViewBuilder()
|
||||
{
|
||||
Clear();
|
||||
|
||||
@@ -25,6 +25,70 @@ namespace Vulkan
|
||||
const char* VkResultToString(VkResult res);
|
||||
void LogVulkanResult(const char* func_name, VkResult res, const char* msg, ...);
|
||||
|
||||
// Only allows single subpass render passes.
|
||||
class RenderPassBuilder
|
||||
{
|
||||
public:
|
||||
static constexpr u32 MAX_COLOR_ATTACHMENTS = 1;
|
||||
static constexpr u32 MAX_ATTACHMENTS = MAX_COLOR_ATTACHMENTS + 1;
|
||||
|
||||
void AddColorAttachment(VkImageLayout layout, VkFormat format,
|
||||
VkAttachmentLoadOp load_op, VkAttachmentStoreOp store_op,
|
||||
bool feedback_loop, bool input_reference, bool subpass_self_dependency);
|
||||
|
||||
void AddDepthStencilAttachment(VkImageLayout layout, VkFormat depth_format,
|
||||
VkAttachmentLoadOp depth_load_op, VkAttachmentStoreOp depth_store_op,
|
||||
VkAttachmentLoadOp stencil_load_op, VkAttachmentStoreOp stencil_store_op,
|
||||
bool feedback_loop, bool input_reference, bool subpass_self_dependency);
|
||||
|
||||
void SetColorFeedbackBarrier(
|
||||
VkPipelineStageFlags src_stage, VkAccessFlags src_access,
|
||||
VkPipelineStageFlags dst_stage, VkAccessFlags dst_access,
|
||||
VkDependencyFlags dependency);
|
||||
void SetDepthFeedbackBarrier(
|
||||
VkPipelineStageFlags src_stage, VkAccessFlags src_access,
|
||||
VkPipelineStageFlags dst_stage, VkAccessFlags dst_access,
|
||||
VkDependencyFlags dependency);
|
||||
|
||||
void AddSubpassFlags(VkSubpassDescriptionFlags subpass_flags);
|
||||
|
||||
void Clear();
|
||||
|
||||
VkRenderPass Create(VkDevice device);
|
||||
private:
|
||||
std::array<VkAttachmentReference, MAX_COLOR_ATTACHMENTS> m_color_reference{};
|
||||
u32 m_num_color_attachments = 0;
|
||||
|
||||
VkAttachmentReference m_depth_reference{};
|
||||
bool m_has_depth_attachment = false;
|
||||
|
||||
std::array<VkAttachmentReference, MAX_ATTACHMENTS> m_input_reference{};
|
||||
u32 m_num_subpass_inputs = 0;
|
||||
|
||||
std::array<VkSubpassDependency, MAX_ATTACHMENTS> m_subpass_dependency{};
|
||||
u32 m_num_subpass_dependencies = 0;
|
||||
|
||||
std::array<VkAttachmentDescription, MAX_ATTACHMENTS> m_attachments{};
|
||||
u32 m_num_attachments = 0;
|
||||
|
||||
VkSubpassDescriptionFlags m_subpass_flags = 0;
|
||||
|
||||
struct
|
||||
{
|
||||
VkPipelineStageFlags color_src_stage;
|
||||
VkAccessFlags color_src_access;
|
||||
VkPipelineStageFlags color_dst_stage;
|
||||
VkAccessFlags color_dst_access;
|
||||
VkDependencyFlags color_dependency;
|
||||
|
||||
VkPipelineStageFlags depth_src_stage;
|
||||
VkAccessFlags depth_src_access;
|
||||
VkPipelineStageFlags depth_dst_stage;
|
||||
VkAccessFlags depth_dst_access;
|
||||
VkDependencyFlags depth_dependency;
|
||||
} m_feedback_barriers{};
|
||||
};
|
||||
|
||||
class DescriptorSetLayoutBuilder
|
||||
{
|
||||
public:
|
||||
@@ -293,37 +357,6 @@ namespace Vulkan
|
||||
std::array<VkImageView, MAX_ATTACHMENTS> m_images;
|
||||
};
|
||||
|
||||
class RenderPassBuilder
|
||||
{
|
||||
enum : u32
|
||||
{
|
||||
MAX_ATTACHMENTS = 2,
|
||||
MAX_ATTACHMENT_REFERENCES = 2,
|
||||
MAX_SUBPASSES = 1,
|
||||
};
|
||||
|
||||
public:
|
||||
RenderPassBuilder();
|
||||
|
||||
void Clear();
|
||||
|
||||
VkRenderPass Create(VkDevice device, bool clear = true);
|
||||
|
||||
u32 AddAttachment(VkFormat format, VkSampleCountFlagBits samples, VkAttachmentLoadOp load_op,
|
||||
VkAttachmentStoreOp store_op, VkImageLayout initial_layout, VkImageLayout final_layout);
|
||||
|
||||
u32 AddSubpass();
|
||||
void AddSubpassColorAttachment(u32 subpass, u32 attachment, VkImageLayout layout);
|
||||
void AddSubpassDepthAttachment(u32 subpass, u32 attachment, VkImageLayout layout);
|
||||
|
||||
private:
|
||||
VkRenderPassCreateInfo m_ci;
|
||||
std::array<VkAttachmentDescription, MAX_ATTACHMENTS> m_attachments;
|
||||
std::array<VkAttachmentReference, MAX_ATTACHMENT_REFERENCES> m_attachment_references;
|
||||
u32 m_num_attachment_references = 0;
|
||||
std::array<VkSubpassDescription, MAX_SUBPASSES> m_subpasses;
|
||||
};
|
||||
|
||||
class BufferViewBuilder
|
||||
{
|
||||
public:
|
||||
|
||||
Reference in New Issue
Block a user