diff options
4 files changed, 59 insertions, 84 deletions
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 8332b42aa..45bd1fc6c 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | |||
| @@ -288,7 +288,7 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa | |||
| 288 | depth_stencil_ci.maxDepthBounds = 0.0f; | 288 | depth_stencil_ci.maxDepthBounds = 0.0f; |
| 289 | 289 | ||
| 290 | std::array<VkPipelineColorBlendAttachmentState, Maxwell::NumRenderTargets> cb_attachments; | 290 | std::array<VkPipelineColorBlendAttachmentState, Maxwell::NumRenderTargets> cb_attachments; |
| 291 | const std::size_t num_attachments = renderpass_params.color_attachments.size(); | 291 | const auto num_attachments = static_cast<std::size_t>(renderpass_params.num_color_attachments); |
| 292 | for (std::size_t index = 0; index < num_attachments; ++index) { | 292 | for (std::size_t index = 0; index < num_attachments; ++index) { |
| 293 | static constexpr std::array COMPONENT_TABLE = { | 293 | static constexpr std::array COMPONENT_TABLE = { |
| 294 | VK_COLOR_COMPONENT_R_BIT, VK_COLOR_COMPONENT_G_BIT, VK_COLOR_COMPONENT_B_BIT, | 294 | VK_COLOR_COMPONENT_R_BIT, VK_COLOR_COMPONENT_G_BIT, VK_COLOR_COMPONENT_B_BIT, |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 8a1f57891..ef21b186b 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -1245,28 +1245,15 @@ std::size_t RasterizerVulkan::CalculateConstBufferSize( | |||
| 1245 | } | 1245 | } |
| 1246 | 1246 | ||
| 1247 | RenderPassParams RasterizerVulkan::GetRenderPassParams(Texceptions texceptions) const { | 1247 | RenderPassParams RasterizerVulkan::GetRenderPassParams(Texceptions texceptions) const { |
| 1248 | using namespace VideoCore::Surface; | ||
| 1249 | |||
| 1250 | const auto& regs = system.GPU().Maxwell3D().regs; | 1248 | const auto& regs = system.GPU().Maxwell3D().regs; |
| 1251 | RenderPassParams renderpass_params; | 1249 | RenderPassParams params; |
| 1252 | 1250 | params.num_color_attachments = static_cast<u8>(regs.rt_control.count); | |
| 1253 | for (std::size_t rt = 0; rt < static_cast<std::size_t>(regs.rt_control.count); ++rt) { | 1251 | std::transform(regs.rt.begin(), regs.rt.end(), params.color_formats.begin(), |
| 1254 | const auto& rendertarget = regs.rt[rt]; | 1252 | [](const auto& rt) { return static_cast<u8>(rt.format); }); |
| 1255 | if (rendertarget.Address() == 0 || rendertarget.format == Tegra::RenderTargetFormat::NONE) { | 1253 | params.texceptions = static_cast<u8>(texceptions.to_ullong()); |
| 1256 | continue; | 1254 | params.zeta_format = regs.zeta_enable ? static_cast<u8>(regs.zeta.format) : 0; |
| 1257 | } | 1255 | params.zeta_texception = texceptions[ZETA_TEXCEPTION_INDEX]; |
| 1258 | renderpass_params.color_attachments.push_back(RenderPassParams::ColorAttachment{ | 1256 | return params; |
| 1259 | static_cast<u32>(rt), PixelFormatFromRenderTargetFormat(rendertarget.format), | ||
| 1260 | texceptions[rt]}); | ||
| 1261 | } | ||
| 1262 | |||
| 1263 | renderpass_params.has_zeta = regs.zeta_enable; | ||
| 1264 | if (renderpass_params.has_zeta) { | ||
| 1265 | renderpass_params.zeta_pixel_format = PixelFormatFromDepthFormat(regs.zeta.format); | ||
| 1266 | renderpass_params.zeta_texception = texceptions[ZETA_TEXCEPTION_INDEX]; | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | return renderpass_params; | ||
| 1270 | } | 1257 | } |
| 1271 | 1258 | ||
| 1272 | } // namespace Vulkan | 1259 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_renderpass_cache.cpp b/src/video_core/renderer_vulkan/vk_renderpass_cache.cpp index 4e5286a69..3f71d005e 100644 --- a/src/video_core/renderer_vulkan/vk_renderpass_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_renderpass_cache.cpp | |||
| @@ -2,9 +2,11 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <cstring> | ||
| 5 | #include <memory> | 6 | #include <memory> |
| 6 | #include <vector> | 7 | #include <vector> |
| 7 | 8 | ||
| 9 | #include "common/cityhash.h" | ||
| 8 | #include "video_core/engines/maxwell_3d.h" | 10 | #include "video_core/engines/maxwell_3d.h" |
| 9 | #include "video_core/renderer_vulkan/maxwell_to_vk.h" | 11 | #include "video_core/renderer_vulkan/maxwell_to_vk.h" |
| 10 | #include "video_core/renderer_vulkan/vk_device.h" | 12 | #include "video_core/renderer_vulkan/vk_device.h" |
| @@ -13,6 +15,15 @@ | |||
| 13 | 15 | ||
| 14 | namespace Vulkan { | 16 | namespace Vulkan { |
| 15 | 17 | ||
| 18 | std::size_t RenderPassParams::Hash() const noexcept { | ||
| 19 | const u64 hash = Common::CityHash64(reinterpret_cast<const char*>(this), sizeof *this); | ||
| 20 | return static_cast<std::size_t>(hash); | ||
| 21 | } | ||
| 22 | |||
| 23 | bool RenderPassParams::operator==(const RenderPassParams& rhs) const noexcept { | ||
| 24 | return std::memcmp(&rhs, this, sizeof *this) == 0; | ||
| 25 | } | ||
| 26 | |||
| 16 | VKRenderPassCache::VKRenderPassCache(const VKDevice& device) : device{device} {} | 27 | VKRenderPassCache::VKRenderPassCache(const VKDevice& device) : device{device} {} |
| 17 | 28 | ||
| 18 | VKRenderPassCache::~VKRenderPassCache() = default; | 29 | VKRenderPassCache::~VKRenderPassCache() = default; |
| @@ -27,20 +38,22 @@ VkRenderPass VKRenderPassCache::GetRenderPass(const RenderPassParams& params) { | |||
| 27 | } | 38 | } |
| 28 | 39 | ||
| 29 | vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& params) const { | 40 | vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& params) const { |
| 41 | using namespace VideoCore::Surface; | ||
| 30 | std::vector<VkAttachmentDescription> descriptors; | 42 | std::vector<VkAttachmentDescription> descriptors; |
| 31 | std::vector<VkAttachmentReference> color_references; | 43 | std::vector<VkAttachmentReference> color_references; |
| 32 | 44 | ||
| 33 | for (std::size_t rt = 0; rt < params.color_attachments.size(); ++rt) { | 45 | const std::size_t num_attachments = static_cast<std::size_t>(params.num_color_attachments); |
| 34 | const auto attachment = params.color_attachments[rt]; | 46 | for (std::size_t rt = 0; rt < num_attachments; ++rt) { |
| 35 | const auto format = | 47 | const auto guest_format = static_cast<Tegra::RenderTargetFormat>(params.color_formats[rt]); |
| 36 | MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, attachment.pixel_format); | 48 | const PixelFormat pixel_format = PixelFormatFromRenderTargetFormat(guest_format); |
| 49 | const auto format = MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, pixel_format); | ||
| 37 | ASSERT_MSG(format.attachable, "Trying to attach a non-attachable format with format={}", | 50 | ASSERT_MSG(format.attachable, "Trying to attach a non-attachable format with format={}", |
| 38 | static_cast<u32>(attachment.pixel_format)); | 51 | static_cast<int>(pixel_format)); |
| 39 | 52 | ||
| 40 | // TODO(Rodrigo): Add eMayAlias when it's needed. | 53 | // TODO(Rodrigo): Add MAY_ALIAS_BIT when it's needed. |
| 41 | const auto color_layout = attachment.is_texception | 54 | const VkImageLayout color_layout = ((params.texceptions >> rt) & 1) != 0 |
| 42 | ? VK_IMAGE_LAYOUT_GENERAL | 55 | ? VK_IMAGE_LAYOUT_GENERAL |
| 43 | : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; | 56 | : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; |
| 44 | VkAttachmentDescription& descriptor = descriptors.emplace_back(); | 57 | VkAttachmentDescription& descriptor = descriptors.emplace_back(); |
| 45 | descriptor.flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT; | 58 | descriptor.flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT; |
| 46 | descriptor.format = format.format; | 59 | descriptor.format = format.format; |
| @@ -58,15 +71,17 @@ vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& param | |||
| 58 | } | 71 | } |
| 59 | 72 | ||
| 60 | VkAttachmentReference zeta_attachment_ref; | 73 | VkAttachmentReference zeta_attachment_ref; |
| 61 | if (params.has_zeta) { | 74 | const bool has_zeta = params.zeta_format != 0; |
| 62 | const auto format = | 75 | if (has_zeta) { |
| 63 | MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, params.zeta_pixel_format); | 76 | const auto guest_format = static_cast<Tegra::DepthFormat>(params.zeta_format); |
| 77 | const PixelFormat pixel_format = PixelFormatFromDepthFormat(guest_format); | ||
| 78 | const auto format = MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, pixel_format); | ||
| 64 | ASSERT_MSG(format.attachable, "Trying to attach a non-attachable format with format={}", | 79 | ASSERT_MSG(format.attachable, "Trying to attach a non-attachable format with format={}", |
| 65 | static_cast<u32>(params.zeta_pixel_format)); | 80 | static_cast<int>(pixel_format)); |
| 66 | 81 | ||
| 67 | const auto zeta_layout = params.zeta_texception | 82 | const VkImageLayout zeta_layout = params.zeta_texception != 0 |
| 68 | ? VK_IMAGE_LAYOUT_GENERAL | 83 | ? VK_IMAGE_LAYOUT_GENERAL |
| 69 | : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; | 84 | : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; |
| 70 | VkAttachmentDescription& descriptor = descriptors.emplace_back(); | 85 | VkAttachmentDescription& descriptor = descriptors.emplace_back(); |
| 71 | descriptor.flags = 0; | 86 | descriptor.flags = 0; |
| 72 | descriptor.format = format.format; | 87 | descriptor.format = format.format; |
| @@ -78,7 +93,7 @@ vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& param | |||
| 78 | descriptor.initialLayout = zeta_layout; | 93 | descriptor.initialLayout = zeta_layout; |
| 79 | descriptor.finalLayout = zeta_layout; | 94 | descriptor.finalLayout = zeta_layout; |
| 80 | 95 | ||
| 81 | zeta_attachment_ref.attachment = static_cast<u32>(params.color_attachments.size()); | 96 | zeta_attachment_ref.attachment = static_cast<u32>(num_attachments); |
| 82 | zeta_attachment_ref.layout = zeta_layout; | 97 | zeta_attachment_ref.layout = zeta_layout; |
| 83 | } | 98 | } |
| 84 | 99 | ||
| @@ -90,7 +105,7 @@ vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& param | |||
| 90 | subpass_description.colorAttachmentCount = static_cast<u32>(color_references.size()); | 105 | subpass_description.colorAttachmentCount = static_cast<u32>(color_references.size()); |
| 91 | subpass_description.pColorAttachments = color_references.data(); | 106 | subpass_description.pColorAttachments = color_references.data(); |
| 92 | subpass_description.pResolveAttachments = nullptr; | 107 | subpass_description.pResolveAttachments = nullptr; |
| 93 | subpass_description.pDepthStencilAttachment = params.has_zeta ? &zeta_attachment_ref : nullptr; | 108 | subpass_description.pDepthStencilAttachment = has_zeta ? &zeta_attachment_ref : nullptr; |
| 94 | subpass_description.preserveAttachmentCount = 0; | 109 | subpass_description.preserveAttachmentCount = 0; |
| 95 | subpass_description.pPreserveAttachments = nullptr; | 110 | subpass_description.pPreserveAttachments = nullptr; |
| 96 | 111 | ||
| @@ -101,7 +116,7 @@ vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& param | |||
| 101 | stage |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; | 116 | stage |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; |
| 102 | } | 117 | } |
| 103 | 118 | ||
| 104 | if (params.has_zeta) { | 119 | if (has_zeta) { |
| 105 | access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | | 120 | access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | |
| 106 | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; | 121 | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; |
| 107 | stage |= VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; | 122 | stage |= VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; |
diff --git a/src/video_core/renderer_vulkan/vk_renderpass_cache.h b/src/video_core/renderer_vulkan/vk_renderpass_cache.h index 921b6efb5..0e988b26b 100644 --- a/src/video_core/renderer_vulkan/vk_renderpass_cache.h +++ b/src/video_core/renderer_vulkan/vk_renderpass_cache.h | |||
| @@ -4,8 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <type_traits> |
| 8 | #include <tuple> | ||
| 9 | #include <unordered_map> | 8 | #include <unordered_map> |
| 10 | 9 | ||
| 11 | #include <boost/container/static_vector.hpp> | 10 | #include <boost/container/static_vector.hpp> |
| @@ -19,51 +18,25 @@ namespace Vulkan { | |||
| 19 | 18 | ||
| 20 | class VKDevice; | 19 | class VKDevice; |
| 21 | 20 | ||
| 22 | // TODO(Rodrigo): Optimize this structure for faster hashing | ||
| 23 | |||
| 24 | struct RenderPassParams { | 21 | struct RenderPassParams { |
| 25 | struct ColorAttachment { | 22 | u8 num_color_attachments; |
| 26 | u32 index = 0; | 23 | std::array<u8, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> color_formats; |
| 27 | VideoCore::Surface::PixelFormat pixel_format = VideoCore::Surface::PixelFormat::Invalid; | 24 | u8 texceptions; |
| 28 | bool is_texception = false; | 25 | |
| 29 | 26 | u8 zeta_format; | |
| 30 | std::size_t Hash() const noexcept { | 27 | u8 zeta_texception; |
| 31 | return static_cast<std::size_t>(pixel_format) | | 28 | |
| 32 | static_cast<std::size_t>(is_texception) << 6 | | 29 | std::size_t Hash() const noexcept; |
| 33 | static_cast<std::size_t>(index) << 7; | 30 | |
| 34 | } | 31 | bool operator==(const RenderPassParams& rhs) const noexcept; |
| 35 | |||
| 36 | bool operator==(const ColorAttachment& rhs) const noexcept { | ||
| 37 | return std::tie(index, pixel_format, is_texception) == | ||
| 38 | std::tie(rhs.index, rhs.pixel_format, rhs.is_texception); | ||
| 39 | } | ||
| 40 | }; | ||
| 41 | |||
| 42 | boost::container::static_vector<ColorAttachment, | ||
| 43 | Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> | ||
| 44 | color_attachments{}; | ||
| 45 | // TODO(Rodrigo): Unify has_zeta into zeta_pixel_format and zeta_component_type. | ||
| 46 | VideoCore::Surface::PixelFormat zeta_pixel_format = VideoCore::Surface::PixelFormat::Invalid; | ||
| 47 | bool has_zeta = false; | ||
| 48 | bool zeta_texception = false; | ||
| 49 | |||
| 50 | std::size_t Hash() const noexcept { | ||
| 51 | std::size_t hash = 0; | ||
| 52 | for (const auto& rt : color_attachments) { | ||
| 53 | boost::hash_combine(hash, rt.Hash()); | ||
| 54 | } | ||
| 55 | boost::hash_combine(hash, zeta_pixel_format); | ||
| 56 | boost::hash_combine(hash, has_zeta); | ||
| 57 | boost::hash_combine(hash, zeta_texception); | ||
| 58 | return hash; | ||
| 59 | } | ||
| 60 | 32 | ||
| 61 | bool operator==(const RenderPassParams& rhs) const { | 33 | bool operator!=(const RenderPassParams& rhs) const noexcept { |
| 62 | return std::tie(color_attachments, zeta_pixel_format, has_zeta, zeta_texception) == | 34 | return !operator==(rhs); |
| 63 | std::tie(rhs.color_attachments, rhs.zeta_pixel_format, rhs.has_zeta, | ||
| 64 | rhs.zeta_texception); | ||
| 65 | } | 35 | } |
| 66 | }; | 36 | }; |
| 37 | static_assert(std::has_unique_object_representations_v<RenderPassParams>); | ||
| 38 | static_assert(std::is_trivially_copyable_v<RenderPassParams>); | ||
| 39 | static_assert(std::is_trivially_constructible_v<RenderPassParams>); | ||
| 67 | 40 | ||
| 68 | } // namespace Vulkan | 41 | } // namespace Vulkan |
| 69 | 42 | ||