vk_renderpass_cache: Commonize setup between renderpass and dynamic rendering implementations
* Also fix small issue that caused broken rendering on the latter
This commit is contained in:
@ -236,7 +236,7 @@ void RendererVulkan::BeginRendering(Frame* frame) {
|
||||
instance.GetDevice().updateDescriptorSetWithTemplate(set, present_update_template,
|
||||
present_textures[0]);
|
||||
|
||||
renderpass_cache.ExitRenderpass();
|
||||
renderpass_cache.EndRendering();
|
||||
scheduler.Record([this, framebuffer = frame->framebuffer, width = frame->width,
|
||||
height = frame->height, set,
|
||||
pipeline_index = current_pipeline](vk::CommandBuffer cmdbuf) {
|
||||
@ -569,7 +569,7 @@ void RendererVulkan::LoadColorToActiveVkTexture(u8 color_r, u8 color_g, u8 color
|
||||
},
|
||||
};
|
||||
|
||||
renderpass_cache.ExitRenderpass();
|
||||
renderpass_cache.EndRendering();
|
||||
scheduler.Record([image = texture.image, clear_color](vk::CommandBuffer cmdbuf) {
|
||||
const vk::ImageSubresourceRange range = {
|
||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
|
@ -331,7 +331,7 @@ bool BlitHelper::BlitDepthStencil(Surface& source, Surface& dest,
|
||||
vk::DescriptorSet set = desc_manager.AllocateSet(two_textures_descriptor_layout);
|
||||
device.updateDescriptorSetWithTemplate(set, two_textures_update_template, textures[0]);
|
||||
|
||||
renderpass_cache.EnterRenderpass(nullptr, &dest, dst_render_area);
|
||||
renderpass_cache.BeginRendering(nullptr, &dest, dst_render_area);
|
||||
scheduler.Record([blit, set, this](vk::CommandBuffer cmdbuf) {
|
||||
const vk::PipelineLayout layout = two_textures_pipeline_layout;
|
||||
|
||||
@ -364,7 +364,7 @@ void BlitHelper::BlitD24S8ToR32(Surface& source, Surface& dest,
|
||||
vk::DescriptorSet set = desc_manager.AllocateSet(compute_descriptor_layout);
|
||||
device.updateDescriptorSetWithTemplate(set, compute_update_template, textures[0]);
|
||||
|
||||
renderpass_cache.ExitRenderpass();
|
||||
renderpass_cache.EndRendering();
|
||||
scheduler.Record([this, set, blit, src_image = source.Image(),
|
||||
dst_image = dest.Image()](vk::CommandBuffer cmdbuf) {
|
||||
const std::array pre_barriers = {
|
||||
|
@ -163,7 +163,7 @@ void D24S8toRGBA8::Reinterpret(Surface& source, VideoCore::Rect2D src_rect, Surf
|
||||
vk::DescriptorSet set = desc_manager.AllocateSet(descriptor_layout);
|
||||
device.updateDescriptorSetWithTemplate(set, update_template, textures[0]);
|
||||
|
||||
runtime.GetRenderpassCache().ExitRenderpass();
|
||||
runtime.GetRenderpassCache().EndRendering();
|
||||
scheduler.Record([this, set, src_rect, src_image = source.Image(),
|
||||
dst_image = dest.Image()](vk::CommandBuffer cmdbuf) {
|
||||
const std::array pre_barriers = {
|
||||
|
@ -496,7 +496,7 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
|
||||
UploadUniforms(accelerate);
|
||||
|
||||
// Begin the renderpass
|
||||
renderpass_cache.EnterRenderpass(framebuffer);
|
||||
renderpass_cache.BeginRendering(framebuffer);
|
||||
|
||||
// Sync the viewport
|
||||
// Viewport can have negative offsets or larger dimensions than our framebuffer sub-rect.
|
||||
|
@ -43,17 +43,13 @@ void RenderpassCache::ClearFramebuffers() {
|
||||
framebuffers.clear();
|
||||
}
|
||||
|
||||
void RenderpassCache::EnterRenderpass(Surface* const color, Surface* const depth_stencil,
|
||||
void RenderpassCache::BeginRendering(Surface* const color, Surface* const depth_stencil,
|
||||
vk::Rect2D render_area, bool do_clear, vk::ClearValue clear) {
|
||||
return EnterRenderpass(Framebuffer{color, depth_stencil, render_area}, do_clear, clear);
|
||||
return BeginRendering(Framebuffer{color, depth_stencil, render_area}, do_clear, clear);
|
||||
}
|
||||
|
||||
void RenderpassCache::EnterRenderpass(const Framebuffer& framebuffer, bool do_clear,
|
||||
void RenderpassCache::BeginRendering(const Framebuffer& framebuffer, bool do_clear,
|
||||
vk::ClearValue clear) {
|
||||
if (dynamic_rendering) {
|
||||
return BeginRendering(framebuffer, do_clear, clear);
|
||||
}
|
||||
|
||||
RenderingInfo new_info = {
|
||||
.color{
|
||||
.aspect = vk::ImageAspectFlagBits::eColor,
|
||||
@ -63,30 +59,84 @@ void RenderpassCache::EnterRenderpass(const Framebuffer& framebuffer, bool do_cl
|
||||
.depth{
|
||||
.aspect = vk::ImageAspectFlagBits::eDepth,
|
||||
.image = framebuffer.Image(SurfaceType::DepthStencil),
|
||||
.image_view = framebuffer.ImageView(SurfaceType::Color),
|
||||
.image_view = framebuffer.ImageView(SurfaceType::DepthStencil),
|
||||
},
|
||||
.render_area = framebuffer.RenderArea(),
|
||||
.clear = clear,
|
||||
.do_clear = do_clear,
|
||||
};
|
||||
|
||||
const PixelFormat color_format = framebuffer.Format(SurfaceType::Color);
|
||||
const PixelFormat depth_format = framebuffer.Format(SurfaceType::DepthStencil);
|
||||
if (depth_format == PixelFormat::D24S8) {
|
||||
if (framebuffer.HasStencil()) {
|
||||
new_info.depth.aspect |= vk::ImageAspectFlagBits::eStencil;
|
||||
}
|
||||
|
||||
const bool is_dirty = scheduler.IsStateDirty(StateFlags::Renderpass);
|
||||
if (info == new_info && rendering && !is_dirty) {
|
||||
// If the provided rendering context is active we are done
|
||||
if (info == new_info && rendering) {
|
||||
cmd_count++;
|
||||
return;
|
||||
}
|
||||
|
||||
const vk::RenderPass renderpass = GetRenderpass(color_format, depth_format, do_clear);
|
||||
EndRendering();
|
||||
info = new_info;
|
||||
rendering = true;
|
||||
|
||||
// Begin the render scope
|
||||
if (dynamic_rendering) {
|
||||
DynamicRendering(framebuffer);
|
||||
} else {
|
||||
EnterRenderpass(framebuffer);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderpassCache::DynamicRendering(const Framebuffer& framebuffer) {
|
||||
const bool has_stencil = framebuffer.HasStencil();
|
||||
scheduler.Record([info = info, has_stencil](vk::CommandBuffer cmdbuf) {
|
||||
u32 cursor = 0;
|
||||
std::array<vk::RenderingAttachmentInfoKHR, 2> infos{};
|
||||
|
||||
const auto Prepare = [&](vk::ImageView image_view) {
|
||||
if (!image_view) {
|
||||
cursor++;
|
||||
return;
|
||||
}
|
||||
|
||||
infos[cursor++] = vk::RenderingAttachmentInfoKHR{
|
||||
.imageView = image_view,
|
||||
.imageLayout = vk::ImageLayout::eGeneral,
|
||||
.loadOp =
|
||||
info.do_clear ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad,
|
||||
.storeOp = vk::AttachmentStoreOp::eStore,
|
||||
.clearValue = info.clear,
|
||||
};
|
||||
};
|
||||
|
||||
Prepare(info.color.image_view);
|
||||
Prepare(info.depth.image_view);
|
||||
|
||||
const u32 color_attachment_count = info.color ? 1u : 0u;
|
||||
const vk::RenderingAttachmentInfoKHR* depth_info = info.depth ? &infos[1] : nullptr;
|
||||
const vk::RenderingAttachmentInfoKHR* stencil_info = has_stencil ? &infos[1] : nullptr;
|
||||
const vk::RenderingInfoKHR rendering_info = {
|
||||
.renderArea = info.render_area,
|
||||
.layerCount = 1,
|
||||
.colorAttachmentCount = color_attachment_count,
|
||||
.pColorAttachments = &infos[0],
|
||||
.pDepthAttachment = depth_info,
|
||||
.pStencilAttachment = stencil_info,
|
||||
};
|
||||
|
||||
cmdbuf.beginRenderingKHR(rendering_info);
|
||||
});
|
||||
}
|
||||
|
||||
void RenderpassCache::EnterRenderpass(const Framebuffer& framebuffer) {
|
||||
const PixelFormat color_format = framebuffer.Format(SurfaceType::Color);
|
||||
const PixelFormat depth_format = framebuffer.Format(SurfaceType::DepthStencil);
|
||||
const vk::RenderPass renderpass = GetRenderpass(color_format, depth_format, info.do_clear);
|
||||
|
||||
const FramebufferInfo framebuffer_info = {
|
||||
.color = new_info.color.image_view,
|
||||
.depth = new_info.depth.image_view,
|
||||
.color = info.color.image_view,
|
||||
.depth = info.depth.image_view,
|
||||
.width = framebuffer.Width(),
|
||||
.height = framebuffer.Height(),
|
||||
};
|
||||
@ -96,10 +146,7 @@ void RenderpassCache::EnterRenderpass(const Framebuffer& framebuffer, bool do_cl
|
||||
it->second = CreateFramebuffer(framebuffer_info, renderpass);
|
||||
}
|
||||
|
||||
if (rendering) {
|
||||
ExitRenderpass();
|
||||
}
|
||||
scheduler.Record([render_area = new_info.render_area, clear, renderpass,
|
||||
scheduler.Record([render_area = info.render_area, clear = info.clear, renderpass,
|
||||
framebuffer = it->second](vk::CommandBuffer cmdbuf) {
|
||||
const vk::RenderPassBeginInfo renderpass_begin_info = {
|
||||
.renderPass = renderpass,
|
||||
@ -111,13 +158,9 @@ void RenderpassCache::EnterRenderpass(const Framebuffer& framebuffer, bool do_cl
|
||||
|
||||
cmdbuf.beginRenderPass(renderpass_begin_info, vk::SubpassContents::eInline);
|
||||
});
|
||||
|
||||
scheduler.MarkStateNonDirty(StateFlags::Renderpass);
|
||||
info = new_info;
|
||||
rendering = true;
|
||||
}
|
||||
|
||||
void RenderpassCache::ExitRenderpass() {
|
||||
void RenderpassCache::EndRendering() {
|
||||
if (!rendering) {
|
||||
return;
|
||||
}
|
||||
@ -191,81 +234,6 @@ void RenderpassCache::ExitRenderpass() {
|
||||
}
|
||||
}
|
||||
|
||||
void RenderpassCache::BeginRendering(const Framebuffer& framebuffer, bool do_clear,
|
||||
vk::ClearValue clear) {
|
||||
RenderingInfo new_info = {
|
||||
.color{
|
||||
.aspect = vk::ImageAspectFlagBits::eColor,
|
||||
.image = framebuffer.Image(SurfaceType::Color),
|
||||
.image_view = framebuffer.ImageView(SurfaceType::Color),
|
||||
},
|
||||
.depth{
|
||||
.aspect = vk::ImageAspectFlagBits::eDepth,
|
||||
.image = framebuffer.Image(SurfaceType::DepthStencil),
|
||||
.image_view = framebuffer.ImageView(SurfaceType::DepthStencil),
|
||||
},
|
||||
.render_area = framebuffer.RenderArea(),
|
||||
.clear = clear,
|
||||
.do_clear = do_clear,
|
||||
};
|
||||
|
||||
const bool has_stencil = framebuffer.Format(SurfaceType::DepthStencil) == PixelFormat::D24S8;
|
||||
if (has_stencil) {
|
||||
new_info.depth.aspect |= vk::ImageAspectFlagBits::eStencil;
|
||||
}
|
||||
|
||||
const bool is_dirty = scheduler.IsStateDirty(StateFlags::Renderpass);
|
||||
if (info == new_info && rendering && !is_dirty) {
|
||||
cmd_count++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (rendering) {
|
||||
ExitRenderpass();
|
||||
}
|
||||
scheduler.Record([new_info, has_stencil](vk::CommandBuffer cmdbuf) {
|
||||
u32 cursor = 0;
|
||||
std::array<vk::RenderingAttachmentInfoKHR, 2> infos{};
|
||||
|
||||
const auto Prepare = [&](vk::ImageView image_view) {
|
||||
if (!image_view) {
|
||||
cursor++;
|
||||
return;
|
||||
}
|
||||
|
||||
infos[cursor++] = vk::RenderingAttachmentInfoKHR{
|
||||
.imageView = image_view,
|
||||
.imageLayout = vk::ImageLayout::eGeneral,
|
||||
.loadOp =
|
||||
new_info.do_clear ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad,
|
||||
.storeOp = vk::AttachmentStoreOp::eStore,
|
||||
.clearValue = new_info.clear,
|
||||
};
|
||||
};
|
||||
|
||||
Prepare(new_info.color.image_view);
|
||||
Prepare(new_info.depth.image_view);
|
||||
|
||||
const u32 color_attachment_count = new_info.color ? 1u : 0u;
|
||||
const vk::RenderingAttachmentInfoKHR* depth_info = new_info.depth ? &infos[1] : nullptr;
|
||||
const vk::RenderingAttachmentInfoKHR* stencil_info = has_stencil ? &infos[1] : nullptr;
|
||||
const vk::RenderingInfoKHR rendering_info = {
|
||||
.renderArea = new_info.render_area,
|
||||
.layerCount = 1,
|
||||
.colorAttachmentCount = color_attachment_count,
|
||||
.pColorAttachments = &infos[0],
|
||||
.pDepthAttachment = depth_info,
|
||||
.pStencilAttachment = stencil_info,
|
||||
};
|
||||
|
||||
cmdbuf.beginRenderingKHR(rendering_info);
|
||||
});
|
||||
|
||||
scheduler.MarkStateNonDirty(StateFlags::Renderpass);
|
||||
info = new_info;
|
||||
rendering = true;
|
||||
}
|
||||
|
||||
void RenderpassCache::CreatePresentRenderpass(vk::Format format) {
|
||||
if (!present_renderpass) {
|
||||
present_renderpass =
|
||||
@ -276,6 +244,8 @@ void RenderpassCache::CreatePresentRenderpass(vk::Format format) {
|
||||
|
||||
vk::RenderPass RenderpassCache::GetRenderpass(VideoCore::PixelFormat color,
|
||||
VideoCore::PixelFormat depth, bool is_clear) {
|
||||
std::scoped_lock lock{cache_mutex};
|
||||
|
||||
const u32 color_index =
|
||||
color == VideoCore::PixelFormat::Invalid ? MAX_COLOR_FORMATS : static_cast<u32>(color);
|
||||
const u32 depth_index = depth == VideoCore::PixelFormat::Invalid
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include <compare>
|
||||
#include <cstring>
|
||||
#include <mutex>
|
||||
#include <variant>
|
||||
#include "common/hash.h"
|
||||
#include "video_core/rasterizer_cache/pixel_format.h"
|
||||
@ -53,13 +54,13 @@ public:
|
||||
void ClearFramebuffers();
|
||||
|
||||
/// Begins a new renderpass only when no other renderpass is currently active
|
||||
void EnterRenderpass(const Framebuffer& framebuffer, bool do_clear = false,
|
||||
void BeginRendering(const Framebuffer& framebuffer, bool do_clear = false,
|
||||
vk::ClearValue clear = {});
|
||||
void EnterRenderpass(Surface* const color, Surface* const depth_stencil, vk::Rect2D render_area,
|
||||
void BeginRendering(Surface* const color, Surface* const depth_stencil, vk::Rect2D render_area,
|
||||
bool do_clear = false, vk::ClearValue clear = {});
|
||||
|
||||
/// Exits from any currently active renderpass instance
|
||||
void ExitRenderpass();
|
||||
void EndRendering();
|
||||
|
||||
/// Creates the renderpass used when rendering to the swapchain
|
||||
void CreatePresentRenderpass(vk::Format format);
|
||||
@ -75,7 +76,10 @@ public:
|
||||
|
||||
private:
|
||||
/// Begins a new rendering scope using dynamic rendering
|
||||
void BeginRendering(const Framebuffer& framebuffer, bool do_clear, vk::ClearValue clear);
|
||||
void DynamicRendering(const Framebuffer& framebuffer);
|
||||
|
||||
/// Begins a new rendering scope using renderpasses
|
||||
void EnterRenderpass(const Framebuffer& framebuffer);
|
||||
|
||||
/// Creates a renderpass configured appropriately and stores it in cached_renderpasses
|
||||
vk::RenderPass CreateRenderPass(vk::Format color, vk::Format depth,
|
||||
@ -123,6 +127,7 @@ private:
|
||||
bool rendering = false;
|
||||
bool dynamic_rendering = false;
|
||||
u32 cmd_count{};
|
||||
std::mutex cache_mutex;
|
||||
};
|
||||
|
||||
} // namespace Vulkan
|
||||
|
@ -121,7 +121,7 @@ void Scheduler::SubmitExecution(vk::Semaphore signal_semaphore, vk::Semaphore wa
|
||||
const u64 signal_value = master_semaphore.NextTick();
|
||||
state = StateFlags::AllDirty;
|
||||
|
||||
renderpass_cache.ExitRenderpass();
|
||||
renderpass_cache.EndRendering();
|
||||
Record(
|
||||
[signal_semaphore, wait_semaphore, handle, signal_value, this](vk::CommandBuffer cmdbuf) {
|
||||
MICROPROFILE_SCOPE(Vulkan_Submit);
|
||||
|
@ -263,7 +263,7 @@ Allocation TextureRuntime::Allocate(u32 width, u32 height, u32 levels, bool is_m
|
||||
vk::Device device = instance.GetDevice();
|
||||
vk::UniqueImageView image_view = device.createImageViewUnique(view_info);
|
||||
|
||||
renderpass_cache.ExitRenderpass();
|
||||
renderpass_cache.EndRendering();
|
||||
scheduler.Record([image, aspect](vk::CommandBuffer cmdbuf) {
|
||||
const vk::ImageMemoryBarrier init_barrier = {
|
||||
.srcAccessMask = vk::AccessFlagBits::eNone,
|
||||
@ -305,7 +305,7 @@ void TextureRuntime::Recycle(const HostTextureTag tag, Allocation&& alloc) {
|
||||
}
|
||||
|
||||
bool TextureRuntime::ClearTexture(Surface& surface, const VideoCore::TextureClear& clear) {
|
||||
renderpass_cache.ExitRenderpass();
|
||||
renderpass_cache.EndRendering();
|
||||
|
||||
const RecordParams params = {
|
||||
.aspect = surface.alloc.aspect,
|
||||
@ -445,9 +445,9 @@ void TextureRuntime::ClearTextureWithRenderpass(Surface& surface,
|
||||
},
|
||||
};
|
||||
|
||||
renderpass_cache.EnterRenderpass(color_surface, depth_surface, render_area, true,
|
||||
renderpass_cache.BeginRendering(color_surface, depth_surface, render_area, true,
|
||||
MakeClearValue(clear.value));
|
||||
renderpass_cache.ExitRenderpass();
|
||||
renderpass_cache.EndRendering();
|
||||
|
||||
scheduler.Record([params, access_flag, pipeline_flags](vk::CommandBuffer cmdbuf) {
|
||||
const vk::ImageMemoryBarrier post_barrier = {
|
||||
@ -474,7 +474,7 @@ void TextureRuntime::ClearTextureWithRenderpass(Surface& surface,
|
||||
|
||||
bool TextureRuntime::CopyTextures(Surface& source, Surface& dest,
|
||||
const VideoCore::TextureCopy& copy) {
|
||||
renderpass_cache.ExitRenderpass();
|
||||
renderpass_cache.EndRendering();
|
||||
|
||||
const RecordParams params = {
|
||||
.aspect = source.alloc.aspect,
|
||||
@ -603,7 +603,7 @@ bool TextureRuntime::BlitTextures(Surface& source, Surface& dest,
|
||||
return blit_helper.BlitDepthStencil(source, dest, blit);
|
||||
}
|
||||
|
||||
renderpass_cache.ExitRenderpass();
|
||||
renderpass_cache.EndRendering();
|
||||
|
||||
const RecordParams params = {
|
||||
.aspect = source.alloc.aspect,
|
||||
@ -735,7 +735,7 @@ void TextureRuntime::GenerateMipmaps(Surface& surface) {
|
||||
return;
|
||||
}
|
||||
|
||||
renderpass_cache.ExitRenderpass();
|
||||
renderpass_cache.EndRendering();
|
||||
|
||||
// Always use the allocation width on custom textures
|
||||
u32 current_width = surface.alloc.width;
|
||||
@ -823,7 +823,7 @@ Surface::~Surface() {
|
||||
}
|
||||
|
||||
void Surface::Upload(const VideoCore::BufferTextureCopy& upload, const StagingData& staging) {
|
||||
runtime->renderpass_cache.ExitRenderpass();
|
||||
runtime->renderpass_cache.EndRendering();
|
||||
|
||||
const bool is_scaled = res_scale != 1;
|
||||
if (is_scaled) {
|
||||
@ -919,7 +919,7 @@ void Surface::Upload(const VideoCore::BufferTextureCopy& upload, const StagingDa
|
||||
}
|
||||
|
||||
void Surface::Download(const VideoCore::BufferTextureCopy& download, const StagingData& staging) {
|
||||
runtime->renderpass_cache.ExitRenderpass();
|
||||
runtime->renderpass_cache.EndRendering();
|
||||
|
||||
// For depth stencil downloads always use the compute shader fallback
|
||||
// to avoid having the interleave the data later. These should(?) be
|
||||
|
@ -263,6 +263,10 @@ public:
|
||||
return static_cast<bool>(image_views[Index(type)]);
|
||||
}
|
||||
|
||||
bool HasStencil() const noexcept {
|
||||
return Format(VideoCore::SurfaceType::DepthStencil) == VideoCore::PixelFormat::D24S8;
|
||||
}
|
||||
|
||||
u32 Width() const noexcept {
|
||||
return width;
|
||||
}
|
||||
|
Reference in New Issue
Block a user