|
|
|
@ -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; |
|
|
|
|