mirror of
https://github.com/azahar-emu/azahar.git
synced 2026-06-06 02:33:44 -04:00
renderer_vulkan: Implement multisample pipeline/renderpass support
Allows multi-sample render passes and graphics pipelines to be created, using sample-rate shading rather than coverage-based MSAA.
This commit is contained in:
parent
fdf022753c
commit
ff7b039c5c
5 changed files with 182 additions and 29 deletions
|
|
@ -163,8 +163,9 @@ bool GraphicsPipeline::Build(bool fail_on_compile_required) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const vk::PipelineMultisampleStateCreateInfo multisampling = {
|
const vk::PipelineMultisampleStateCreateInfo multisampling = {
|
||||||
.rasterizationSamples = vk::SampleCountFlagBits::e1,
|
.rasterizationSamples = vk::SampleCountFlagBits(info.state.attachments.sample_count),
|
||||||
.sampleShadingEnable = false,
|
.sampleShadingEnable = true,
|
||||||
|
.minSampleShading = 1.0f,
|
||||||
};
|
};
|
||||||
|
|
||||||
const vk::PipelineColorBlendAttachmentState colorblend_attachment = {
|
const vk::PipelineColorBlendAttachmentState colorblend_attachment = {
|
||||||
|
|
@ -275,7 +276,8 @@ bool GraphicsPipeline::Build(bool fail_on_compile_required) {
|
||||||
.pDynamicState = &dynamic_info,
|
.pDynamicState = &dynamic_info,
|
||||||
.layout = pipeline_layout,
|
.layout = pipeline_layout,
|
||||||
.renderPass = renderpass_cache.GetRenderpass(info.state.attachments.color,
|
.renderPass = renderpass_cache.GetRenderpass(info.state.attachments.color,
|
||||||
info.state.attachments.depth, false),
|
info.state.attachments.depth, false,
|
||||||
|
info.state.attachments.sample_count),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (fail_on_compile_required) {
|
if (fail_on_compile_required) {
|
||||||
|
|
|
||||||
|
|
@ -214,6 +214,7 @@ static_assert(std::is_trivial_v<VertexLayout>);
|
||||||
struct AttachmentInfo {
|
struct AttachmentInfo {
|
||||||
VideoCore::PixelFormat color;
|
VideoCore::PixelFormat color;
|
||||||
VideoCore::PixelFormat depth;
|
VideoCore::PixelFormat depth;
|
||||||
|
u8 sample_count;
|
||||||
|
|
||||||
static consteval u64 StructHash() {
|
static consteval u64 StructHash() {
|
||||||
constexpr u64 STRUCT_VERSION = 0;
|
constexpr u64 STRUCT_VERSION = 0;
|
||||||
|
|
@ -225,7 +226,7 @@ struct AttachmentInfo {
|
||||||
LAYOUT_HASH,
|
LAYOUT_HASH,
|
||||||
|
|
||||||
// fields
|
// fields
|
||||||
FIELD_HASH(color), FIELD_HASH(depth));
|
FIELD_HASH(color), FIELD_HASH(depth), FIELD_HASH(sample_count));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
static_assert(std::is_trivial_v<AttachmentInfo>);
|
static_assert(std::is_trivial_v<AttachmentInfo>);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <boost/container/static_vector.hpp>
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "video_core/rasterizer_cache/pixel_format.h"
|
#include "video_core/rasterizer_cache/pixel_format.h"
|
||||||
#include "video_core/renderer_vulkan/vk_instance.h"
|
#include "video_core/renderer_vulkan/vk_instance.h"
|
||||||
|
|
@ -37,7 +39,7 @@ void RenderManager::BeginRendering(const Framebuffer* framebuffer,
|
||||||
.framebuffer = framebuffer->Handle(),
|
.framebuffer = framebuffer->Handle(),
|
||||||
.render_pass = framebuffer->RenderPass(),
|
.render_pass = framebuffer->RenderPass(),
|
||||||
.render_area = render_area,
|
.render_area = render_area,
|
||||||
.clear = {},
|
.clears = {},
|
||||||
.do_clear = false,
|
.do_clear = false,
|
||||||
};
|
};
|
||||||
images = framebuffer->Images();
|
images = framebuffer->Images();
|
||||||
|
|
@ -58,8 +60,8 @@ void RenderManager::BeginRendering(const RenderPass& new_pass) {
|
||||||
.renderPass = info.render_pass,
|
.renderPass = info.render_pass,
|
||||||
.framebuffer = info.framebuffer,
|
.framebuffer = info.framebuffer,
|
||||||
.renderArea = info.render_area,
|
.renderArea = info.render_area,
|
||||||
.clearValueCount = info.do_clear ? 1u : 0u,
|
.clearValueCount = info.do_clear ? 2u : 0u,
|
||||||
.pClearValues = &info.clear,
|
.pClearValues = info.clears.data(),
|
||||||
};
|
};
|
||||||
cmdbuf.beginRenderPass(renderpass_begin_info, vk::SubpassContents::eInline);
|
cmdbuf.beginRenderPass(renderpass_begin_info, vk::SubpassContents::eInline);
|
||||||
});
|
});
|
||||||
|
|
@ -77,7 +79,7 @@ void RenderManager::EndRendering() {
|
||||||
u32 num_barriers = 0;
|
u32 num_barriers = 0;
|
||||||
vk::PipelineStageFlags pipeline_flags{};
|
vk::PipelineStageFlags pipeline_flags{};
|
||||||
vk::AccessFlags src_access_flags{};
|
vk::AccessFlags src_access_flags{};
|
||||||
std::array<vk::ImageMemoryBarrier, 2> barriers;
|
std::array<vk::ImageMemoryBarrier, 4> barriers;
|
||||||
for (u32 i = 0; i < images.size(); i++) {
|
for (u32 i = 0; i < images.size(); i++) {
|
||||||
if (!images[i]) {
|
if (!images[i]) {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -138,7 +140,8 @@ void RenderManager::EndRendering() {
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::RenderPass RenderManager::GetRenderpass(VideoCore::PixelFormat color,
|
vk::RenderPass RenderManager::GetRenderpass(VideoCore::PixelFormat color,
|
||||||
VideoCore::PixelFormat depth, bool is_clear) {
|
VideoCore::PixelFormat depth, bool is_clear,
|
||||||
|
u8 sample_count) {
|
||||||
std::scoped_lock lock{cache_mutex};
|
std::scoped_lock lock{cache_mutex};
|
||||||
|
|
||||||
const u32 color_index =
|
const u32 color_index =
|
||||||
|
|
@ -151,13 +154,23 @@ vk::RenderPass RenderManager::GetRenderpass(VideoCore::PixelFormat color,
|
||||||
ASSERT_MSG(color_index <= NumColorFormats && depth_index <= NumDepthFormats,
|
ASSERT_MSG(color_index <= NumColorFormats && depth_index <= NumDepthFormats,
|
||||||
"Invalid color index {} and/or depth_index {}", color_index, depth_index);
|
"Invalid color index {} and/or depth_index {}", color_index, depth_index);
|
||||||
|
|
||||||
vk::UniqueRenderPass& renderpass = cached_renderpasses[color_index][depth_index][is_clear];
|
ASSERT_MSG(sample_count && std::has_single_bit(sample_count) && sample_count <= MaxSamples,
|
||||||
|
"Invalid sample count {}", static_cast<u32>(sample_count));
|
||||||
|
|
||||||
|
const u32 samples_index = static_cast<u32>(std::bit_width(sample_count) - 1);
|
||||||
|
|
||||||
|
vk::UniqueRenderPass& renderpass =
|
||||||
|
cached_renderpasses[color_index][depth_index][samples_index][is_clear];
|
||||||
if (!renderpass) {
|
if (!renderpass) {
|
||||||
const vk::Format color_format = instance.GetTraits(color).native;
|
const vk::Format color_format = instance.GetTraits(color).native;
|
||||||
const vk::Format depth_format = instance.GetTraits(depth).native;
|
const vk::Format depth_format = instance.GetTraits(depth).native;
|
||||||
const vk::AttachmentLoadOp load_op =
|
const vk::AttachmentLoadOp load_op =
|
||||||
is_clear ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad;
|
is_clear ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad;
|
||||||
renderpass = CreateRenderPass(color_format, depth_format, load_op);
|
|
||||||
|
renderpass = (sample_count > 1)
|
||||||
|
? CreateRenderPassMSAA(color_format, depth_format, load_op,
|
||||||
|
static_cast<vk::SampleCountFlagBits>(sample_count))
|
||||||
|
: CreateRenderPass(color_format, depth_format, load_op);
|
||||||
}
|
}
|
||||||
|
|
||||||
return *renderpass;
|
return *renderpass;
|
||||||
|
|
@ -165,27 +178,27 @@ vk::RenderPass RenderManager::GetRenderpass(VideoCore::PixelFormat color,
|
||||||
|
|
||||||
vk::UniqueRenderPass RenderManager::CreateRenderPass(vk::Format color, vk::Format depth,
|
vk::UniqueRenderPass RenderManager::CreateRenderPass(vk::Format color, vk::Format depth,
|
||||||
vk::AttachmentLoadOp load_op) const {
|
vk::AttachmentLoadOp load_op) const {
|
||||||
u32 attachment_count = 0;
|
|
||||||
std::array<vk::AttachmentDescription, 2> attachments;
|
|
||||||
|
|
||||||
|
boost::container::static_vector<vk::AttachmentDescription, 2> attachments{};
|
||||||
bool use_color = false;
|
bool use_color = false;
|
||||||
vk::AttachmentReference color_attachment_ref{};
|
vk::AttachmentReference color_attachment_ref{};
|
||||||
bool use_depth = false;
|
bool use_depth = false;
|
||||||
vk::AttachmentReference depth_attachment_ref{};
|
vk::AttachmentReference depth_attachment_ref{};
|
||||||
|
|
||||||
if (color != vk::Format::eUndefined) {
|
if (color != vk::Format::eUndefined) {
|
||||||
attachments[attachment_count] = vk::AttachmentDescription{
|
attachments.emplace_back(vk::AttachmentDescription{
|
||||||
.format = color,
|
.format = color,
|
||||||
|
.samples = vk::SampleCountFlagBits::e1,
|
||||||
.loadOp = load_op,
|
.loadOp = load_op,
|
||||||
.storeOp = vk::AttachmentStoreOp::eStore,
|
.storeOp = vk::AttachmentStoreOp::eStore,
|
||||||
.stencilLoadOp = vk::AttachmentLoadOp::eDontCare,
|
.stencilLoadOp = vk::AttachmentLoadOp::eDontCare,
|
||||||
.stencilStoreOp = vk::AttachmentStoreOp::eDontCare,
|
.stencilStoreOp = vk::AttachmentStoreOp::eDontCare,
|
||||||
.initialLayout = vk::ImageLayout::eGeneral,
|
.initialLayout = vk::ImageLayout::eGeneral,
|
||||||
.finalLayout = vk::ImageLayout::eGeneral,
|
.finalLayout = vk::ImageLayout::eGeneral,
|
||||||
};
|
});
|
||||||
|
|
||||||
color_attachment_ref = vk::AttachmentReference{
|
color_attachment_ref = vk::AttachmentReference{
|
||||||
.attachment = attachment_count++,
|
.attachment = static_cast<u32>(attachments.size() - 1),
|
||||||
.layout = vk::ImageLayout::eGeneral,
|
.layout = vk::ImageLayout::eGeneral,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -193,18 +206,19 @@ vk::UniqueRenderPass RenderManager::CreateRenderPass(vk::Format color, vk::Forma
|
||||||
}
|
}
|
||||||
|
|
||||||
if (depth != vk::Format::eUndefined) {
|
if (depth != vk::Format::eUndefined) {
|
||||||
attachments[attachment_count] = vk::AttachmentDescription{
|
attachments.emplace_back(vk::AttachmentDescription{
|
||||||
.format = depth,
|
.format = depth,
|
||||||
|
.samples = vk::SampleCountFlagBits::e1,
|
||||||
.loadOp = load_op,
|
.loadOp = load_op,
|
||||||
.storeOp = vk::AttachmentStoreOp::eStore,
|
.storeOp = vk::AttachmentStoreOp::eStore,
|
||||||
.stencilLoadOp = load_op,
|
.stencilLoadOp = load_op,
|
||||||
.stencilStoreOp = vk::AttachmentStoreOp::eStore,
|
.stencilStoreOp = vk::AttachmentStoreOp::eStore,
|
||||||
.initialLayout = vk::ImageLayout::eGeneral,
|
.initialLayout = vk::ImageLayout::eGeneral,
|
||||||
.finalLayout = vk::ImageLayout::eGeneral,
|
.finalLayout = vk::ImageLayout::eGeneral,
|
||||||
};
|
});
|
||||||
|
|
||||||
depth_attachment_ref = vk::AttachmentReference{
|
depth_attachment_ref = vk::AttachmentReference{
|
||||||
.attachment = attachment_count++,
|
.attachment = static_cast<u32>(attachments.size() - 1),
|
||||||
.layout = vk::ImageLayout::eGeneral,
|
.layout = vk::ImageLayout::eGeneral,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -217,12 +231,11 @@ vk::UniqueRenderPass RenderManager::CreateRenderPass(vk::Format color, vk::Forma
|
||||||
.pInputAttachments = nullptr,
|
.pInputAttachments = nullptr,
|
||||||
.colorAttachmentCount = use_color ? 1u : 0u,
|
.colorAttachmentCount = use_color ? 1u : 0u,
|
||||||
.pColorAttachments = &color_attachment_ref,
|
.pColorAttachments = &color_attachment_ref,
|
||||||
.pResolveAttachments = 0,
|
|
||||||
.pDepthStencilAttachment = use_depth ? &depth_attachment_ref : nullptr,
|
.pDepthStencilAttachment = use_depth ? &depth_attachment_ref : nullptr,
|
||||||
};
|
};
|
||||||
|
|
||||||
const vk::RenderPassCreateInfo renderpass_info = {
|
const vk::RenderPassCreateInfo renderpass_info = {
|
||||||
.attachmentCount = attachment_count,
|
.attachmentCount = static_cast<u32>(attachments.size()),
|
||||||
.pAttachments = attachments.data(),
|
.pAttachments = attachments.data(),
|
||||||
.subpassCount = 1,
|
.subpassCount = 1,
|
||||||
.pSubpasses = &subpass,
|
.pSubpasses = &subpass,
|
||||||
|
|
@ -233,4 +246,132 @@ vk::UniqueRenderPass RenderManager::CreateRenderPass(vk::Format color, vk::Forma
|
||||||
return instance.GetDevice().createRenderPassUnique(renderpass_info);
|
return instance.GetDevice().createRenderPassUnique(renderpass_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vk::UniqueRenderPass RenderManager::CreateRenderPassMSAA(
|
||||||
|
vk::Format color, vk::Format depth, vk::AttachmentLoadOp load_op,
|
||||||
|
vk::SampleCountFlagBits sample_count) const {
|
||||||
|
boost::container::static_vector<vk::AttachmentDescription2, 4> attachments{};
|
||||||
|
|
||||||
|
vk::AttachmentReference2 color_resolve_attachment = {.attachment = VK_ATTACHMENT_UNUSED};
|
||||||
|
vk::AttachmentReference2 depth_resolve_attachment = {.attachment = VK_ATTACHMENT_UNUSED};
|
||||||
|
|
||||||
|
bool use_color = false;
|
||||||
|
vk::AttachmentReference2 color_attachment_ref{};
|
||||||
|
bool use_depth = false;
|
||||||
|
vk::AttachmentReference2 depth_attachment_ref{};
|
||||||
|
|
||||||
|
if (color != vk::Format::eUndefined) {
|
||||||
|
attachments.emplace_back(vk::AttachmentDescription2{
|
||||||
|
.format = color,
|
||||||
|
.samples = vk::SampleCountFlagBits::e1,
|
||||||
|
.loadOp = load_op,
|
||||||
|
.storeOp = vk::AttachmentStoreOp::eStore,
|
||||||
|
.stencilLoadOp = vk::AttachmentLoadOp::eDontCare,
|
||||||
|
.stencilStoreOp = vk::AttachmentStoreOp::eDontCare,
|
||||||
|
.initialLayout = vk::ImageLayout::eGeneral,
|
||||||
|
.finalLayout = vk::ImageLayout::eGeneral,
|
||||||
|
});
|
||||||
|
|
||||||
|
color_attachment_ref = vk::AttachmentReference2{
|
||||||
|
.attachment = static_cast<u32>(attachments.size() - 1),
|
||||||
|
.layout = vk::ImageLayout::eGeneral,
|
||||||
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||||
|
};
|
||||||
|
|
||||||
|
use_color = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depth != vk::Format::eUndefined) {
|
||||||
|
attachments.emplace_back(vk::AttachmentDescription2{
|
||||||
|
.format = depth,
|
||||||
|
.samples = vk::SampleCountFlagBits::e1,
|
||||||
|
.loadOp = load_op,
|
||||||
|
.storeOp = vk::AttachmentStoreOp::eStore,
|
||||||
|
.stencilLoadOp = load_op,
|
||||||
|
.stencilStoreOp = vk::AttachmentStoreOp::eStore,
|
||||||
|
.initialLayout = vk::ImageLayout::eGeneral,
|
||||||
|
.finalLayout = vk::ImageLayout::eGeneral,
|
||||||
|
});
|
||||||
|
|
||||||
|
depth_attachment_ref = vk::AttachmentReference2{
|
||||||
|
.attachment = static_cast<u32>(attachments.size() - 1),
|
||||||
|
.layout = vk::ImageLayout::eGeneral,
|
||||||
|
.aspectMask = vk::ImageAspectFlagBits::eDepth,
|
||||||
|
};
|
||||||
|
|
||||||
|
use_depth = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In the case of MSAA, each attachment gets an additional MSAA attachment that now becomes the
|
||||||
|
// main attachment and the original attachments now get resolved into
|
||||||
|
if (sample_count > vk::SampleCountFlagBits::e1) {
|
||||||
|
if (color != vk::Format::eUndefined) {
|
||||||
|
attachments.emplace_back(vk::AttachmentDescription2{
|
||||||
|
.format = color,
|
||||||
|
.samples = sample_count,
|
||||||
|
.loadOp = load_op,
|
||||||
|
.storeOp = vk::AttachmentStoreOp::eStore,
|
||||||
|
.stencilLoadOp = vk::AttachmentLoadOp::eDontCare,
|
||||||
|
.stencilStoreOp = vk::AttachmentStoreOp::eDontCare,
|
||||||
|
.initialLayout = vk::ImageLayout::eGeneral,
|
||||||
|
.finalLayout = vk::ImageLayout::eGeneral,
|
||||||
|
});
|
||||||
|
|
||||||
|
color_resolve_attachment = color_attachment_ref;
|
||||||
|
|
||||||
|
color_attachment_ref = vk::AttachmentReference2{
|
||||||
|
.attachment = static_cast<u32>(attachments.size() - 1),
|
||||||
|
.layout = vk::ImageLayout::eGeneral,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depth != vk::Format::eUndefined) {
|
||||||
|
attachments.emplace_back(vk::AttachmentDescription2{
|
||||||
|
.format = depth,
|
||||||
|
.samples = sample_count,
|
||||||
|
.loadOp = load_op,
|
||||||
|
.storeOp = vk::AttachmentStoreOp::eStore,
|
||||||
|
.stencilLoadOp = load_op,
|
||||||
|
.stencilStoreOp = vk::AttachmentStoreOp::eStore,
|
||||||
|
.initialLayout = vk::ImageLayout::eGeneral,
|
||||||
|
.finalLayout = vk::ImageLayout::eGeneral,
|
||||||
|
});
|
||||||
|
|
||||||
|
depth_resolve_attachment = depth_attachment_ref;
|
||||||
|
|
||||||
|
depth_attachment_ref = vk::AttachmentReference2{
|
||||||
|
.attachment = static_cast<u32>(attachments.size() - 1),
|
||||||
|
.layout = vk::ImageLayout::eGeneral,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const vk::StructureChain<vk::SubpassDescription2, vk::SubpassDescriptionDepthStencilResolve>
|
||||||
|
subpass = {
|
||||||
|
vk::SubpassDescription2{
|
||||||
|
.pipelineBindPoint = vk::PipelineBindPoint::eGraphics,
|
||||||
|
.inputAttachmentCount = 0,
|
||||||
|
.pInputAttachments = nullptr,
|
||||||
|
.colorAttachmentCount = use_color ? 1u : 0u,
|
||||||
|
.pColorAttachments = &color_attachment_ref,
|
||||||
|
.pResolveAttachments = &color_resolve_attachment,
|
||||||
|
.pDepthStencilAttachment = use_depth ? &depth_attachment_ref : nullptr,
|
||||||
|
},
|
||||||
|
vk::SubpassDescriptionDepthStencilResolve{
|
||||||
|
.depthResolveMode = vk::ResolveModeFlagBits::eSampleZero,
|
||||||
|
.stencilResolveMode = vk::ResolveModeFlagBits::eSampleZero,
|
||||||
|
.pDepthStencilResolveAttachment = &depth_resolve_attachment},
|
||||||
|
};
|
||||||
|
|
||||||
|
const vk::RenderPassCreateInfo2 renderpass_info = {
|
||||||
|
.attachmentCount = static_cast<u32>(attachments.size()),
|
||||||
|
.pAttachments = attachments.data(),
|
||||||
|
.subpassCount = 1,
|
||||||
|
.pSubpasses = &subpass.get(),
|
||||||
|
.dependencyCount = 0,
|
||||||
|
.pDependencies = nullptr,
|
||||||
|
};
|
||||||
|
|
||||||
|
return instance.GetDevice().createRenderPass2Unique(renderpass_info);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <bit>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "common/math_util.h"
|
#include "common/math_util.h"
|
||||||
|
|
@ -23,20 +24,22 @@ struct RenderPass {
|
||||||
vk::Framebuffer framebuffer;
|
vk::Framebuffer framebuffer;
|
||||||
vk::RenderPass render_pass;
|
vk::RenderPass render_pass;
|
||||||
vk::Rect2D render_area;
|
vk::Rect2D render_area;
|
||||||
vk::ClearValue clear;
|
std::array<vk::ClearValue, 2> clears;
|
||||||
u32 do_clear;
|
u32 do_clear;
|
||||||
|
|
||||||
bool operator==(const RenderPass& other) const noexcept {
|
bool operator==(const RenderPass& other) const noexcept {
|
||||||
return std::tie(framebuffer, render_pass, render_area, do_clear) ==
|
return std::tie(framebuffer, render_pass, render_area, do_clear) ==
|
||||||
std::tie(other.framebuffer, other.render_pass, other.render_area,
|
std::tie(other.framebuffer, other.render_pass, other.render_area,
|
||||||
other.do_clear) &&
|
other.do_clear) &&
|
||||||
std::memcmp(&clear, &other.clear, sizeof(vk::ClearValue)) == 0;
|
std::memcmp(&clears, &other.clears, sizeof(clears)) == 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class RenderManager {
|
class RenderManager {
|
||||||
static constexpr u32 NumColorFormats = static_cast<u32>(VideoCore::PixelFormat::NumColorFormat);
|
static constexpr u32 NumColorFormats = static_cast<u32>(VideoCore::PixelFormat::NumColorFormat);
|
||||||
static constexpr u32 NumDepthFormats = static_cast<u32>(VideoCore::PixelFormat::NumDepthFormat);
|
static constexpr u32 NumDepthFormats = static_cast<u32>(VideoCore::PixelFormat::NumDepthFormat);
|
||||||
|
static constexpr size_t MaxSamples = 8;
|
||||||
|
static_assert(std::has_single_bit(MaxSamples));
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit RenderManager(const Instance& instance, Scheduler& scheduler);
|
explicit RenderManager(const Instance& instance, Scheduler& scheduler);
|
||||||
|
|
@ -53,20 +56,26 @@ public:
|
||||||
|
|
||||||
/// Returns the renderpass associated with the color-depth format pair
|
/// Returns the renderpass associated with the color-depth format pair
|
||||||
vk::RenderPass GetRenderpass(VideoCore::PixelFormat color, VideoCore::PixelFormat depth,
|
vk::RenderPass GetRenderpass(VideoCore::PixelFormat color, VideoCore::PixelFormat depth,
|
||||||
bool is_clear);
|
bool is_clear, u8 sample_count = 1);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Creates a renderpass configured appropriately and stores it in cached_renderpasses
|
/// Creates a renderpass configured appropriately and stores it in cached_renderpasses
|
||||||
vk::UniqueRenderPass CreateRenderPass(vk::Format color, vk::Format depth,
|
vk::UniqueRenderPass CreateRenderPass(vk::Format color, vk::Format depth,
|
||||||
vk::AttachmentLoadOp load_op) const;
|
vk::AttachmentLoadOp load_op) const;
|
||||||
|
|
||||||
|
/// Creates an MSAA renderpass configured appropriately and stores it in cached_renderpasses
|
||||||
|
vk::UniqueRenderPass CreateRenderPassMSAA(vk::Format color, vk::Format depth,
|
||||||
|
vk::AttachmentLoadOp load_op,
|
||||||
|
vk::SampleCountFlagBits sample_count) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Instance& instance;
|
const Instance& instance;
|
||||||
Scheduler& scheduler;
|
Scheduler& scheduler;
|
||||||
vk::UniqueRenderPass cached_renderpasses[NumColorFormats + 1][NumDepthFormats + 1][2];
|
vk::UniqueRenderPass cached_renderpasses[NumColorFormats + 1][NumDepthFormats + 1]
|
||||||
|
[std::bit_width(MaxSamples)][2];
|
||||||
std::mutex cache_mutex;
|
std::mutex cache_mutex;
|
||||||
std::array<vk::Image, 2> images;
|
std::array<vk::Image, 4> images;
|
||||||
std::array<vk::ImageAspectFlags, 2> aspects;
|
std::array<vk::ImageAspectFlags, 4> aspects;
|
||||||
bool shadow_rendering{};
|
bool shadow_rendering{};
|
||||||
RenderPass pass{};
|
RenderPass pass{};
|
||||||
u32 num_draws{};
|
u32 num_draws{};
|
||||||
|
|
|
||||||
|
|
@ -142,13 +142,13 @@ private:
|
||||||
static_assert(sizeof(GSConfigEntry) == 48);
|
static_assert(sizeof(GSConfigEntry) == 48);
|
||||||
|
|
||||||
struct PLConfigEntry {
|
struct PLConfigEntry {
|
||||||
static constexpr u8 EXPECTED_VERSION = 0;
|
static constexpr u8 EXPECTED_VERSION = 1;
|
||||||
|
|
||||||
u64 version; // Surprise tool that can help us later
|
u64 version; // Surprise tool that can help us later
|
||||||
|
|
||||||
StaticPipelineInfo pl_info;
|
StaticPipelineInfo pl_info;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(PLConfigEntry) == 152);
|
static_assert(sizeof(PLConfigEntry) == 160);
|
||||||
|
|
||||||
class CacheFile;
|
class CacheFile;
|
||||||
class CacheEntry {
|
class CacheEntry {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue