vk_renderpass_cache: Pack renderpass cache key to 12 bytes
This commit is contained in:
parent
26f2820ae3
commit
f665c92114
|
@ -288,7 +288,7 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
|
|||
depth_stencil_ci.maxDepthBounds = 0.0f;
|
||||
|
||||
std::array<VkPipelineColorBlendAttachmentState, Maxwell::NumRenderTargets> cb_attachments;
|
||||
const std::size_t num_attachments = renderpass_params.color_attachments.size();
|
||||
const auto num_attachments = static_cast<std::size_t>(renderpass_params.num_color_attachments);
|
||||
for (std::size_t index = 0; index < num_attachments; ++index) {
|
||||
static constexpr std::array COMPONENT_TABLE = {
|
||||
VK_COLOR_COMPONENT_R_BIT, VK_COLOR_COMPONENT_G_BIT, VK_COLOR_COMPONENT_B_BIT,
|
||||
|
|
|
@ -1245,28 +1245,15 @@ std::size_t RasterizerVulkan::CalculateConstBufferSize(
|
|||
}
|
||||
|
||||
RenderPassParams RasterizerVulkan::GetRenderPassParams(Texceptions texceptions) const {
|
||||
using namespace VideoCore::Surface;
|
||||
|
||||
const auto& regs = system.GPU().Maxwell3D().regs;
|
||||
RenderPassParams renderpass_params;
|
||||
|
||||
for (std::size_t rt = 0; rt < static_cast<std::size_t>(regs.rt_control.count); ++rt) {
|
||||
const auto& rendertarget = regs.rt[rt];
|
||||
if (rendertarget.Address() == 0 || rendertarget.format == Tegra::RenderTargetFormat::NONE) {
|
||||
continue;
|
||||
}
|
||||
renderpass_params.color_attachments.push_back(RenderPassParams::ColorAttachment{
|
||||
static_cast<u32>(rt), PixelFormatFromRenderTargetFormat(rendertarget.format),
|
||||
texceptions[rt]});
|
||||
}
|
||||
|
||||
renderpass_params.has_zeta = regs.zeta_enable;
|
||||
if (renderpass_params.has_zeta) {
|
||||
renderpass_params.zeta_pixel_format = PixelFormatFromDepthFormat(regs.zeta.format);
|
||||
renderpass_params.zeta_texception = texceptions[ZETA_TEXCEPTION_INDEX];
|
||||
}
|
||||
|
||||
return renderpass_params;
|
||||
RenderPassParams params;
|
||||
params.num_color_attachments = static_cast<u8>(regs.rt_control.count);
|
||||
std::transform(regs.rt.begin(), regs.rt.end(), params.color_formats.begin(),
|
||||
[](const auto& rt) { return static_cast<u8>(rt.format); });
|
||||
params.texceptions = static_cast<u8>(texceptions.to_ullong());
|
||||
params.zeta_format = regs.zeta_enable ? static_cast<u8>(regs.zeta.format) : 0;
|
||||
params.zeta_texception = texceptions[ZETA_TEXCEPTION_INDEX];
|
||||
return params;
|
||||
}
|
||||
|
||||
} // namespace Vulkan
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "common/cityhash.h"
|
||||
#include "video_core/engines/maxwell_3d.h"
|
||||
#include "video_core/renderer_vulkan/maxwell_to_vk.h"
|
||||
#include "video_core/renderer_vulkan/vk_device.h"
|
||||
|
@ -13,6 +15,15 @@
|
|||
|
||||
namespace Vulkan {
|
||||
|
||||
std::size_t RenderPassParams::Hash() const noexcept {
|
||||
const u64 hash = Common::CityHash64(reinterpret_cast<const char*>(this), sizeof *this);
|
||||
return static_cast<std::size_t>(hash);
|
||||
}
|
||||
|
||||
bool RenderPassParams::operator==(const RenderPassParams& rhs) const noexcept {
|
||||
return std::memcmp(&rhs, this, sizeof *this) == 0;
|
||||
}
|
||||
|
||||
VKRenderPassCache::VKRenderPassCache(const VKDevice& device) : device{device} {}
|
||||
|
||||
VKRenderPassCache::~VKRenderPassCache() = default;
|
||||
|
@ -27,18 +38,20 @@ VkRenderPass VKRenderPassCache::GetRenderPass(const RenderPassParams& params) {
|
|||
}
|
||||
|
||||
vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& params) const {
|
||||
using namespace VideoCore::Surface;
|
||||
std::vector<VkAttachmentDescription> descriptors;
|
||||
std::vector<VkAttachmentReference> color_references;
|
||||
|
||||
for (std::size_t rt = 0; rt < params.color_attachments.size(); ++rt) {
|
||||
const auto attachment = params.color_attachments[rt];
|
||||
const auto format =
|
||||
MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, attachment.pixel_format);
|
||||
const std::size_t num_attachments = static_cast<std::size_t>(params.num_color_attachments);
|
||||
for (std::size_t rt = 0; rt < num_attachments; ++rt) {
|
||||
const auto guest_format = static_cast<Tegra::RenderTargetFormat>(params.color_formats[rt]);
|
||||
const PixelFormat pixel_format = PixelFormatFromRenderTargetFormat(guest_format);
|
||||
const auto format = MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, pixel_format);
|
||||
ASSERT_MSG(format.attachable, "Trying to attach a non-attachable format with format={}",
|
||||
static_cast<u32>(attachment.pixel_format));
|
||||
static_cast<int>(pixel_format));
|
||||
|
||||
// TODO(Rodrigo): Add eMayAlias when it's needed.
|
||||
const auto color_layout = attachment.is_texception
|
||||
// TODO(Rodrigo): Add MAY_ALIAS_BIT when it's needed.
|
||||
const VkImageLayout color_layout = ((params.texceptions >> rt) & 1) != 0
|
||||
? VK_IMAGE_LAYOUT_GENERAL
|
||||
: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
VkAttachmentDescription& descriptor = descriptors.emplace_back();
|
||||
|
@ -58,13 +71,15 @@ vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& param
|
|||
}
|
||||
|
||||
VkAttachmentReference zeta_attachment_ref;
|
||||
if (params.has_zeta) {
|
||||
const auto format =
|
||||
MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, params.zeta_pixel_format);
|
||||
const bool has_zeta = params.zeta_format != 0;
|
||||
if (has_zeta) {
|
||||
const auto guest_format = static_cast<Tegra::DepthFormat>(params.zeta_format);
|
||||
const PixelFormat pixel_format = PixelFormatFromDepthFormat(guest_format);
|
||||
const auto format = MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, pixel_format);
|
||||
ASSERT_MSG(format.attachable, "Trying to attach a non-attachable format with format={}",
|
||||
static_cast<u32>(params.zeta_pixel_format));
|
||||
static_cast<int>(pixel_format));
|
||||
|
||||
const auto zeta_layout = params.zeta_texception
|
||||
const VkImageLayout zeta_layout = params.zeta_texception != 0
|
||||
? VK_IMAGE_LAYOUT_GENERAL
|
||||
: VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
VkAttachmentDescription& descriptor = descriptors.emplace_back();
|
||||
|
@ -78,7 +93,7 @@ vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& param
|
|||
descriptor.initialLayout = zeta_layout;
|
||||
descriptor.finalLayout = zeta_layout;
|
||||
|
||||
zeta_attachment_ref.attachment = static_cast<u32>(params.color_attachments.size());
|
||||
zeta_attachment_ref.attachment = static_cast<u32>(num_attachments);
|
||||
zeta_attachment_ref.layout = zeta_layout;
|
||||
}
|
||||
|
||||
|
@ -90,7 +105,7 @@ vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& param
|
|||
subpass_description.colorAttachmentCount = static_cast<u32>(color_references.size());
|
||||
subpass_description.pColorAttachments = color_references.data();
|
||||
subpass_description.pResolveAttachments = nullptr;
|
||||
subpass_description.pDepthStencilAttachment = params.has_zeta ? &zeta_attachment_ref : nullptr;
|
||||
subpass_description.pDepthStencilAttachment = has_zeta ? &zeta_attachment_ref : nullptr;
|
||||
subpass_description.preserveAttachmentCount = 0;
|
||||
subpass_description.pPreserveAttachments = nullptr;
|
||||
|
||||
|
@ -101,7 +116,7 @@ vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& param
|
|||
stage |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
}
|
||||
|
||||
if (params.has_zeta) {
|
||||
if (has_zeta) {
|
||||
access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||
stage |= VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <boost/container/static_vector.hpp>
|
||||
|
@ -19,51 +18,25 @@ namespace Vulkan {
|
|||
|
||||
class VKDevice;
|
||||
|
||||
// TODO(Rodrigo): Optimize this structure for faster hashing
|
||||
|
||||
struct RenderPassParams {
|
||||
struct ColorAttachment {
|
||||
u32 index = 0;
|
||||
VideoCore::Surface::PixelFormat pixel_format = VideoCore::Surface::PixelFormat::Invalid;
|
||||
bool is_texception = false;
|
||||
u8 num_color_attachments;
|
||||
std::array<u8, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> color_formats;
|
||||
u8 texceptions;
|
||||
|
||||
std::size_t Hash() const noexcept {
|
||||
return static_cast<std::size_t>(pixel_format) |
|
||||
static_cast<std::size_t>(is_texception) << 6 |
|
||||
static_cast<std::size_t>(index) << 7;
|
||||
}
|
||||
u8 zeta_format;
|
||||
u8 zeta_texception;
|
||||
|
||||
bool operator==(const ColorAttachment& rhs) const noexcept {
|
||||
return std::tie(index, pixel_format, is_texception) ==
|
||||
std::tie(rhs.index, rhs.pixel_format, rhs.is_texception);
|
||||
}
|
||||
};
|
||||
std::size_t Hash() const noexcept;
|
||||
|
||||
boost::container::static_vector<ColorAttachment,
|
||||
Tegra::Engines::Maxwell3D::Regs::NumRenderTargets>
|
||||
color_attachments{};
|
||||
// TODO(Rodrigo): Unify has_zeta into zeta_pixel_format and zeta_component_type.
|
||||
VideoCore::Surface::PixelFormat zeta_pixel_format = VideoCore::Surface::PixelFormat::Invalid;
|
||||
bool has_zeta = false;
|
||||
bool zeta_texception = false;
|
||||
bool operator==(const RenderPassParams& rhs) const noexcept;
|
||||
|
||||
std::size_t Hash() const noexcept {
|
||||
std::size_t hash = 0;
|
||||
for (const auto& rt : color_attachments) {
|
||||
boost::hash_combine(hash, rt.Hash());
|
||||
}
|
||||
boost::hash_combine(hash, zeta_pixel_format);
|
||||
boost::hash_combine(hash, has_zeta);
|
||||
boost::hash_combine(hash, zeta_texception);
|
||||
return hash;
|
||||
}
|
||||
|
||||
bool operator==(const RenderPassParams& rhs) const {
|
||||
return std::tie(color_attachments, zeta_pixel_format, has_zeta, zeta_texception) ==
|
||||
std::tie(rhs.color_attachments, rhs.zeta_pixel_format, rhs.has_zeta,
|
||||
rhs.zeta_texception);
|
||||
bool operator!=(const RenderPassParams& rhs) const noexcept {
|
||||
return !operator==(rhs);
|
||||
}
|
||||
};
|
||||
static_assert(std::has_unique_object_representations_v<RenderPassParams>);
|
||||
static_assert(std::is_trivially_copyable_v<RenderPassParams>);
|
||||
static_assert(std::is_trivially_constructible_v<RenderPassParams>);
|
||||
|
||||
} // namespace Vulkan
|
||||
|
||||
|
|
Reference in New Issue