committed by
crueter
6 changed files with 562 additions and 23 deletions
-
395pending_changes.diff
-
22src/video_core/renderer_vulkan/vk_render_pass_cache.cpp
-
133src/video_core/renderer_vulkan/vk_scheduler.cpp
-
26src/video_core/renderer_vulkan/vk_scheduler.h
-
4src/video_core/renderer_vulkan/vk_texture_cache.cpp
-
5src/video_core/renderer_vulkan/vk_texture_cache.h
@ -0,0 +1,395 @@ |
|||
diff --git a/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp b/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp
|
|||
index 80ff75e3b9..5c8c41cf01 100644
|
|||
--- a/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp
|
|||
+++ b/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp
|
|||
@@ -43,6 +43,18 @@ using VideoCore::Surface::SurfaceType;
|
|||
} |
|||
} |
|||
|
|||
+ VkImageLayout AttachmentLayout(SurfaceType type) {
|
|||
+ switch (type) {
|
|||
+ case SurfaceType::ColorTexture:
|
|||
+ return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|||
+ case SurfaceType::Depth:
|
|||
+ case SurfaceType::Stencil:
|
|||
+ case SurfaceType::DepthStencil:
|
|||
+ return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
|||
+ }
|
|||
+ return VK_IMAGE_LAYOUT_GENERAL;
|
|||
+ }
|
|||
+
|
|||
VkAttachmentDescription AttachmentDescription(const Device& device, PixelFormat format, |
|||
VkSampleCountFlagBits samples) { |
|||
using MaxwellToVK::SurfaceFormat; |
|||
@@ -50,6 +62,7 @@ using VideoCore::Surface::SurfaceType;
|
|||
const SurfaceType surface_type = GetSurfaceType(format); |
|||
const bool has_stencil = surface_type == SurfaceType::DepthStencil || |
|||
surface_type == SurfaceType::Stencil; |
|||
+ const VkImageLayout attachment_layout = AttachmentLayout(surface_type);
|
|||
|
|||
return { |
|||
.flags = {}, |
|||
@@ -61,8 +74,8 @@ using VideoCore::Surface::SurfaceType;
|
|||
: VK_ATTACHMENT_LOAD_OP_DONT_CARE, |
|||
.stencilStoreOp = has_stencil ? VK_ATTACHMENT_STORE_OP_STORE |
|||
: VK_ATTACHMENT_STORE_OP_DONT_CARE, |
|||
- .initialLayout = VK_IMAGE_LAYOUT_GENERAL,
|
|||
- .finalLayout = VK_IMAGE_LAYOUT_GENERAL,
|
|||
+ .initialLayout = attachment_layout,
|
|||
+ .finalLayout = attachment_layout,
|
|||
}; |
|||
} |
|||
} // Anonymous namespace |
|||
@@ -84,7 +97,7 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) {
|
|||
const bool is_valid{format != PixelFormat::Invalid}; |
|||
references[index] = VkAttachmentReference{ |
|||
.attachment = is_valid ? num_colors : VK_ATTACHMENT_UNUSED, |
|||
- .layout = VK_IMAGE_LAYOUT_GENERAL,
|
|||
+ .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
|||
}; |
|||
if (is_valid) { |
|||
descriptions.push_back(AttachmentDescription(*device, format, key.samples)); |
|||
@@ -97,7 +110,7 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) {
|
|||
if (key.depth_format != PixelFormat::Invalid) { |
|||
depth_reference = VkAttachmentReference{ |
|||
.attachment = num_colors, |
|||
- .layout = VK_IMAGE_LAYOUT_GENERAL,
|
|||
+ .layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
|||
}; |
|||
descriptions.push_back(AttachmentDescription(*device, key.depth_format, key.samples)); |
|||
} |
|||
diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp
|
|||
index d109d22cab..8edabfb87a 100644
|
|||
--- a/src/video_core/renderer_vulkan/vk_scheduler.cpp
|
|||
+++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp
|
|||
@@ -4,6 +4,7 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project |
|||
// SPDX-License-Identifier: GPL-2.0-or-later |
|||
|
|||
+#include <array>
|
|||
#include <memory> |
|||
#include <mutex> |
|||
#include <thread> |
|||
@@ -98,12 +99,86 @@ void Scheduler::RequestRenderpass(const Framebuffer* framebuffer) {
|
|||
render_area.height == state.render_area.height) { |
|||
return; |
|||
} |
|||
- EndRenderPass();
|
|||
+ EndRenderPass(false);
|
|||
state.renderpass = renderpass; |
|||
state.framebuffer = framebuffer_handle; |
|||
state.render_area = render_area; |
|||
|
|||
- Record([renderpass, framebuffer_handle, render_area](vk::CommandBuffer cmdbuf) {
|
|||
+ const u32 framebuffer_image_count = framebuffer->NumImages();
|
|||
+ const auto framebuffer_images = framebuffer->Images();
|
|||
+ const auto framebuffer_ranges = framebuffer->ImageRanges();
|
|||
+ const auto framebuffer_layouts = framebuffer->ImageLayouts();
|
|||
+ std::array<VkImageLayout, 9> previous_layouts{};
|
|||
+ previous_layouts.fill(VK_IMAGE_LAYOUT_GENERAL);
|
|||
+ for (size_t i = 0; i < framebuffer_image_count; ++i) {
|
|||
+ const VkImage image = framebuffer_images[i];
|
|||
+ previous_layouts[i] = GetTrackedLayout(image);
|
|||
+ SetTrackedLayout(image, framebuffer_layouts[i]);
|
|||
+ }
|
|||
+
|
|||
+ Record([renderpass, framebuffer_handle, render_area, framebuffer_image_count,
|
|||
+ framebuffer_images, framebuffer_ranges, framebuffer_layouts,
|
|||
+ previous_layouts](vk::CommandBuffer cmdbuf) {
|
|||
+ std::array<VkImageMemoryBarrier, 9> barriers{};
|
|||
+ VkPipelineStageFlags src_stage_mask = 0;
|
|||
+ VkPipelineStageFlags dst_stage_mask = 0;
|
|||
+ size_t barrier_count = 0;
|
|||
+ for (size_t i = 0; i < framebuffer_image_count; ++i) {
|
|||
+ const VkImageLayout target_layout = framebuffer_layouts[i];
|
|||
+ if (target_layout == VK_IMAGE_LAYOUT_GENERAL || target_layout == VK_IMAGE_LAYOUT_UNDEFINED) {
|
|||
+ continue;
|
|||
+ }
|
|||
+
|
|||
+ const VkImageSubresourceRange& range = framebuffer_ranges[i];
|
|||
+ const VkImageLayout old_layout = previous_layouts[i];
|
|||
+ if (old_layout == target_layout) {
|
|||
+ continue;
|
|||
+ }
|
|||
+
|
|||
+ VkAccessFlags dst_access = 0;
|
|||
+ VkPipelineStageFlags dst_stage = 0;
|
|||
+
|
|||
+ if (range.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
|
|||
+ dst_access |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
|||
+ dst_stage |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
|||
+ }
|
|||
+ if (range.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
|||
+ dst_access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
|||
+ VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
|||
+ dst_stage |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
|||
+ VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
|||
+ }
|
|||
+
|
|||
+ VkPipelineStageFlags src_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
|||
+ VkAccessFlags src_access = 0;
|
|||
+ if (old_layout != VK_IMAGE_LAYOUT_UNDEFINED) {
|
|||
+ src_stage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
|
|||
+ src_access = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
|
|||
+ }
|
|||
+
|
|||
+ barriers[barrier_count++] = VkImageMemoryBarrier{
|
|||
+ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
|||
+ .pNext = nullptr,
|
|||
+ .srcAccessMask = src_access,
|
|||
+ .dstAccessMask = dst_access,
|
|||
+ .oldLayout = old_layout,
|
|||
+ .newLayout = target_layout,
|
|||
+ .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
|||
+ .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
|||
+ .image = framebuffer_images[i],
|
|||
+ .subresourceRange = range,
|
|||
+ };
|
|||
+ src_stage_mask |= src_stage;
|
|||
+ dst_stage_mask |= dst_stage;
|
|||
+ }
|
|||
+
|
|||
+ if (barrier_count > 0) {
|
|||
+ cmdbuf.PipelineBarrier(
|
|||
+ src_stage_mask != 0 ? src_stage_mask : VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
|||
+ dst_stage_mask != 0 ? dst_stage_mask : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
|||
+ 0, {}, {}, {barriers.data(), barrier_count});
|
|||
+ }
|
|||
+
|
|||
const VkRenderPassBeginInfo renderpass_bi{ |
|||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, |
|||
.pNext = nullptr, |
|||
@@ -119,13 +194,14 @@ void Scheduler::RequestRenderpass(const Framebuffer* framebuffer) {
|
|||
}; |
|||
cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE); |
|||
}); |
|||
- num_renderpass_images = framebuffer->NumImages();
|
|||
- renderpass_images = framebuffer->Images();
|
|||
- renderpass_image_ranges = framebuffer->ImageRanges();
|
|||
+ num_renderpass_images = framebuffer_image_count;
|
|||
+ renderpass_images = framebuffer_images;
|
|||
+ renderpass_image_ranges = framebuffer_ranges;
|
|||
+ renderpass_image_layouts = framebuffer_layouts;
|
|||
} |
|||
|
|||
void Scheduler::RequestOutsideRenderPassOperationContext() { |
|||
- EndRenderPass();
|
|||
+ EndRenderPass(true);
|
|||
} |
|||
|
|||
bool Scheduler::UpdateGraphicsPipeline(GraphicsPipeline* pipeline) { |
|||
@@ -267,21 +343,23 @@ void Scheduler::InvalidateState() {
|
|||
|
|||
void Scheduler::EndPendingOperations() { |
|||
query_cache->CounterReset(VideoCommon::QueryType::ZPassPixelCount64); |
|||
- EndRenderPass();
|
|||
+ EndRenderPass(true);
|
|||
} |
|||
|
|||
-void Scheduler::EndRenderPass()
|
|||
- {
|
|||
- if (!state.renderpass) {
|
|||
- return;
|
|||
- }
|
|||
+void Scheduler::EndRenderPass(bool force_general)
|
|||
+{
|
|||
+ if (!state.renderpass) {
|
|||
+ return;
|
|||
+ }
|
|||
|
|||
- query_cache->CounterEnable(VideoCommon::QueryType::ZPassPixelCount64, false);
|
|||
- query_cache->NotifySegment(false);
|
|||
+ query_cache->CounterEnable(VideoCommon::QueryType::ZPassPixelCount64, false);
|
|||
+ query_cache->NotifySegment(false);
|
|||
|
|||
+ if (force_general) {
|
|||
Record([num_images = num_renderpass_images, |
|||
images = renderpass_images, |
|||
- ranges = renderpass_image_ranges](vk::CommandBuffer cmdbuf) {
|
|||
+ ranges = renderpass_image_ranges,
|
|||
+ layouts = renderpass_image_layouts](vk::CommandBuffer cmdbuf) {
|
|||
std::array<VkImageMemoryBarrier, 9> barriers; |
|||
VkPipelineStageFlags src_stages = 0; |
|||
|
|||
@@ -308,6 +386,9 @@ void Scheduler::EndRenderPass()
|
|||
|
|||
src_stages |= this_stage; |
|||
|
|||
+ const VkImageLayout render_layout =
|
|||
+ layouts[i] != VK_IMAGE_LAYOUT_UNDEFINED ? layouts[i] : VK_IMAGE_LAYOUT_GENERAL;
|
|||
+
|
|||
barriers[i] = VkImageMemoryBarrier{ |
|||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, |
|||
.pNext = nullptr, |
|||
@@ -317,7 +398,7 @@ void Scheduler::EndRenderPass()
|
|||
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|||
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|||
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, |
|||
- .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
|||
+ .oldLayout = render_layout,
|
|||
.newLayout = VK_IMAGE_LAYOUT_GENERAL, |
|||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, |
|||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, |
|||
@@ -337,10 +418,26 @@ void Scheduler::EndRenderPass()
|
|||
); |
|||
}); |
|||
|
|||
- state.renderpass = nullptr;
|
|||
- num_renderpass_images = 0;
|
|||
+ for (size_t i = 0; i < num_renderpass_images; ++i) {
|
|||
+ SetTrackedLayout(renderpass_images[i], VK_IMAGE_LAYOUT_GENERAL);
|
|||
+ }
|
|||
+ } else {
|
|||
+ Record([](vk::CommandBuffer cmdbuf) {
|
|||
+ cmdbuf.EndRenderPass();
|
|||
+ });
|
|||
+ for (size_t i = 0; i < num_renderpass_images; ++i) {
|
|||
+ const VkImageLayout render_layout =
|
|||
+ renderpass_image_layouts[i] != VK_IMAGE_LAYOUT_UNDEFINED
|
|||
+ ? renderpass_image_layouts[i]
|
|||
+ : VK_IMAGE_LAYOUT_GENERAL;
|
|||
+ SetTrackedLayout(renderpass_images[i], render_layout);
|
|||
+ }
|
|||
} |
|||
|
|||
+ state.renderpass = nullptr;
|
|||
+ num_renderpass_images = 0;
|
|||
+}
|
|||
+
|
|||
|
|||
void Scheduler::AcquireNewChunk() { |
|||
std::scoped_lock rl{reserve_mutex}; |
|||
diff --git a/src/video_core/renderer_vulkan/vk_scheduler.h b/src/video_core/renderer_vulkan/vk_scheduler.h
|
|||
index 54ab8ba52b..2e0bbb24b1 100644
|
|||
--- a/src/video_core/renderer_vulkan/vk_scheduler.h
|
|||
+++ b/src/video_core/renderer_vulkan/vk_scheduler.h
|
|||
@@ -3,6 +3,7 @@
|
|||
|
|||
#pragma once |
|||
|
|||
+#include <array>
|
|||
#include <condition_variable> |
|||
#include <cstddef> |
|||
#include <functional> |
|||
@@ -10,6 +11,7 @@
|
|||
#include <thread> |
|||
#include <utility> |
|||
#include <queue> |
|||
+#include <unordered_map>
|
|||
|
|||
#include "common/alignment.h" |
|||
#include "common/common_types.h" |
|||
@@ -122,6 +124,10 @@ public:
|
|||
return *master_semaphore; |
|||
} |
|||
|
|||
+ void TrackImageLayout(VkImage image, VkImageLayout layout) noexcept {
|
|||
+ SetTrackedLayout(image, layout);
|
|||
+ }
|
|||
+
|
|||
std::mutex submit_mutex; |
|||
|
|||
private: |
|||
@@ -226,10 +232,26 @@ private:
|
|||
|
|||
void EndPendingOperations(); |
|||
|
|||
- void EndRenderPass();
|
|||
+ void EndRenderPass(bool force_general = true);
|
|||
|
|||
void AcquireNewChunk(); |
|||
|
|||
+ [[nodiscard]] static constexpr u64 ImageKey(VkImage image) noexcept {
|
|||
+ return static_cast<u64>(reinterpret_cast<uintptr_t>(image));
|
|||
+ }
|
|||
+
|
|||
+ [[nodiscard]] VkImageLayout GetTrackedLayout(VkImage image) const noexcept {
|
|||
+ const auto it = image_layout_cache.find(ImageKey(image));
|
|||
+ if (it == image_layout_cache.end()) {
|
|||
+ return VK_IMAGE_LAYOUT_GENERAL;
|
|||
+ }
|
|||
+ return it->second;
|
|||
+ }
|
|||
+
|
|||
+ void SetTrackedLayout(VkImage image, VkImageLayout layout) noexcept {
|
|||
+ image_layout_cache[ImageKey(image)] = layout;
|
|||
+ }
|
|||
+
|
|||
const Device& device; |
|||
StateTracker& state_tracker; |
|||
|
|||
@@ -249,6 +271,7 @@ private:
|
|||
u32 num_renderpass_images = 0; |
|||
std::array<VkImage, 9> renderpass_images{}; |
|||
std::array<VkImageSubresourceRange, 9> renderpass_image_ranges{}; |
|||
+ std::array<VkImageLayout, 9> renderpass_image_layouts{};
|
|||
|
|||
std::queue<std::unique_ptr<CommandChunk>> work_queue; |
|||
std::vector<std::unique_ptr<CommandChunk>> chunk_reserve; |
|||
@@ -257,6 +280,7 @@ private:
|
|||
std::mutex queue_mutex; |
|||
std::condition_variable_any event_cv; |
|||
std::jthread worker_thread; |
|||
+ std::unordered_map<u64, VkImageLayout> image_layout_cache;
|
|||
}; |
|||
|
|||
} // namespace Vulkan |
|||
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
|
|||
index 9b6d1704c3..b31eab5d72 100644
|
|||
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
|
|||
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
|
|||
@@ -2298,6 +2298,7 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
|
|||
|
|||
is_rescaled = is_rescaled_; |
|||
const auto& resolution = runtime.resolution; |
|||
+ image_layouts.fill(VK_IMAGE_LAYOUT_GENERAL);
|
|||
|
|||
u32 width = (std::numeric_limits<u32>::max)(); |
|||
u32 height = (std::numeric_limits<u32>::max)(); |
|||
@@ -2316,6 +2317,7 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
|
|||
num_layers = (std::max)(num_layers, color_buffer->range.extent.layers); |
|||
images[num_images] = color_buffer->ImageHandle(); |
|||
image_ranges[num_images] = MakeSubresourceRange(color_buffer); |
|||
+ image_layouts[num_images] = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|||
rt_map[index] = num_images; |
|||
samples = color_buffer->Samples(); |
|||
++num_images; |
|||
@@ -2332,6 +2334,7 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
|
|||
images[num_images] = depth_buffer->ImageHandle(); |
|||
const VkImageSubresourceRange subresource_range = MakeSubresourceRange(depth_buffer); |
|||
image_ranges[num_images] = subresource_range; |
|||
+ image_layouts[num_images] = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
|||
samples = depth_buffer->Samples(); |
|||
++num_images; |
|||
has_depth = (subresource_range.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0; |
|||
@@ -2393,6 +2396,7 @@ void TextureCacheRuntime::TransitionImageLayout(Image& image) {
|
|||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, |
|||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, barrier); |
|||
}); |
|||
+ scheduler.TrackImageLayout(image.Handle(), VK_IMAGE_LAYOUT_GENERAL);
|
|||
} |
|||
} |
|||
|
|||
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h
|
|||
index cd11cc8fc7..68937f9e2b 100644
|
|||
--- a/src/video_core/renderer_vulkan/vk_texture_cache.h
|
|||
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.h
|
|||
@@ -360,6 +360,10 @@ public:
|
|||
return image_ranges; |
|||
} |
|||
|
|||
+ [[nodiscard]] const std::array<VkImageLayout, 9>& ImageLayouts() const noexcept {
|
|||
+ return image_layouts;
|
|||
+ }
|
|||
+
|
|||
[[nodiscard]] bool HasAspectColorBit(size_t index) const noexcept { |
|||
return (image_ranges.at(rt_map[index]).aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != 0; |
|||
} |
|||
@@ -385,6 +389,7 @@ private:
|
|||
u32 num_images = 0; |
|||
std::array<VkImage, 9> images{}; |
|||
std::array<VkImageSubresourceRange, 9> image_ranges{}; |
|||
+ std::array<VkImageLayout, 9> image_layouts{};
|
|||
std::array<size_t, NUM_RT> rt_map{}; |
|||
bool has_depth{}; |
|||
bool has_stencil{}; |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue