This commit is contained in:
parent
02fc59f752
commit
ebc280e8a0
14 changed files with 353 additions and 143 deletions
|
@ -353,6 +353,10 @@ public:
|
|||
return buffer_bits;
|
||||
}
|
||||
|
||||
// No-op in OpenGL: Vulkan uses this to adjust attachment load ops.
|
||||
void UpdateLoadOps(const std::array<bool, NUM_RT>& /*discard_colors*/, bool /*discard_depth*/,
|
||||
bool /*discard_stencil*/) {}
|
||||
|
||||
private:
|
||||
OGLFramebuffer framebuffer;
|
||||
GLbitfield buffer_bits = GL_NONE;
|
||||
|
|
|
@ -525,14 +525,12 @@ void BeginRenderPass(vk::CommandBuffer& cmdbuf, const Framebuffer* framebuffer)
|
|||
if (dst_access == 0) {
|
||||
continue;
|
||||
}
|
||||
dst_access |= VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT;
|
||||
dst_stage |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
barriers[barrier_count++] = VkImageMemoryBarrier{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.pNext = nullptr,
|
||||
.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT |
|
||||
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
|
||||
VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
|
||||
.dstAccessMask = dst_access,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.newLayout = layout,
|
||||
|
@ -596,7 +594,7 @@ void EndRenderPass(vk::CommandBuffer& cmdbuf, const Framebuffer* framebuffer) {
|
|||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.pNext = nullptr,
|
||||
.srcAccessMask = src_access,
|
||||
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT |
|
||||
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
|
||||
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
|
||||
|
|
|
@ -175,6 +175,23 @@ public:
|
|||
std::array<f32, 4> words{};
|
||||
};
|
||||
|
||||
inline bool OverlapsSubresource(const VideoCommon::SubresourceRange& view_range,
|
||||
const VkImageSubresourceRange& fb_range) {
|
||||
const u32 view_level_begin = static_cast<u32>(view_range.base.level);
|
||||
const u32 view_level_end = view_level_begin + static_cast<u32>(view_range.extent.levels);
|
||||
const u32 fb_level_begin = fb_range.baseMipLevel;
|
||||
const u32 fb_level_end = fb_level_begin + fb_range.levelCount;
|
||||
|
||||
const u32 view_layer_begin = static_cast<u32>(view_range.base.layer);
|
||||
const u32 view_layer_end = view_layer_begin + static_cast<u32>(view_range.extent.layers);
|
||||
const u32 fb_layer_begin = fb_range.baseArrayLayer;
|
||||
const u32 fb_layer_end = fb_layer_begin + fb_range.layerCount;
|
||||
|
||||
const bool levels_overlap = view_level_begin < fb_level_end && fb_level_begin < view_level_end;
|
||||
const bool layers_overlap = view_layer_begin < fb_layer_end && fb_layer_begin < view_layer_end;
|
||||
return levels_overlap && layers_overlap;
|
||||
}
|
||||
|
||||
inline VkImageLayout DescriptorImageLayout(TextureCache& texture_cache,
|
||||
const Framebuffer* framebuffer,
|
||||
ImageView& image_view) {
|
||||
|
@ -191,21 +208,19 @@ inline VkImageLayout DescriptorImageLayout(TextureCache& texture_cache,
|
|||
if (images[index] != image_handle) {
|
||||
continue;
|
||||
}
|
||||
const VkImageAspectFlags aspect = ranges[index].aspectMask;
|
||||
if (aspect & VK_IMAGE_ASPECT_COLOR_BIT) {
|
||||
const VkImageSubresourceRange& fb_range = ranges[index];
|
||||
|
||||
// Only return feedback-loop layout if the descriptor's view overlaps the
|
||||
// subresource range actually attached in the framebuffer. This avoids
|
||||
// setting a layout that doesn't match the descriptor's subresource.
|
||||
static constexpr VkImageAspectFlags FeedbackAspects =
|
||||
VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
if ((fb_range.aspectMask & FeedbackAspects) == 0) {
|
||||
continue;
|
||||
}
|
||||
if (OverlapsSubresource(image_view.range, fb_range)) {
|
||||
return VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
|
||||
}
|
||||
const bool has_depth = (aspect & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
|
||||
const bool has_stencil = (aspect & VK_IMAGE_ASPECT_STENCIL_BIT) != 0;
|
||||
if (has_depth && has_stencil) {
|
||||
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
|
||||
}
|
||||
if (has_depth) {
|
||||
return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
|
||||
}
|
||||
if (has_stencil) {
|
||||
return VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
|
||||
}
|
||||
}
|
||||
return VK_IMAGE_LAYOUT_GENERAL;
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ using Tegra::Texture::TexturePair;
|
|||
using VideoCore::Surface::PixelFormat;
|
||||
using VideoCore::Surface::PixelFormatFromDepthFormat;
|
||||
using VideoCore::Surface::PixelFormatFromRenderTargetFormat;
|
||||
using VideoCore::Surface::GetFormatType;
|
||||
|
||||
constexpr size_t NUM_STAGES = Maxwell::MaxShaderStage;
|
||||
constexpr size_t MAX_IMAGE_ELEMENTS = 64;
|
||||
|
@ -123,13 +124,33 @@ PixelFormat DecodeFormat(u8 encoded_format) {
|
|||
}
|
||||
|
||||
RenderPassKey MakeRenderPassKey(const FixedPipelineState& state) {
|
||||
RenderPassKey key;
|
||||
RenderPassKey key{};
|
||||
std::ranges::transform(state.color_formats, key.color_formats.begin(), DecodeFormat);
|
||||
for (size_t index = 0; index < key.color_formats.size(); ++index) {
|
||||
if (key.color_formats[index] != PixelFormat::Invalid) {
|
||||
key.color_load_ops[index] = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
key.color_store_ops[index] = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
} else {
|
||||
key.color_load_ops[index] = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
key.color_store_ops[index] = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
}
|
||||
}
|
||||
if (state.depth_enabled != 0) {
|
||||
const auto depth_format{static_cast<Tegra::DepthFormat>(state.depth_format.Value())};
|
||||
key.depth_format = PixelFormatFromDepthFormat(depth_format);
|
||||
key.depth_load_op = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
key.depth_store_op = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
const auto depth_type = GetFormatType(key.depth_format);
|
||||
const bool has_stencil = depth_type == VideoCore::Surface::SurfaceType::DepthStencil ||
|
||||
depth_type == VideoCore::Surface::SurfaceType::Stencil;
|
||||
key.stencil_load_op = has_stencil ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
key.stencil_store_op = has_stencil ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
} else {
|
||||
key.depth_format = PixelFormat::Invalid;
|
||||
key.depth_load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
key.depth_store_op = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
key.stencil_load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
key.stencil_store_op = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
}
|
||||
key.samples = MaxwellToVK::MsaaMode(state.msaa_mode);
|
||||
return key;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "video_core/vulkan_common/vulkan_device.h"
|
||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||
|
||||
|
||||
namespace Vulkan {
|
||||
namespace {
|
||||
using VideoCore::Surface::PixelFormat;
|
||||
|
@ -43,42 +44,60 @@ using VideoCore::Surface::SurfaceType;
|
|||
}
|
||||
}
|
||||
|
||||
VkImageLayout AttachmentLayout(const Device& device, SurfaceType surface_type) {
|
||||
if (!device.SupportsAttachmentFeedbackLoopLayout()) {
|
||||
return VK_IMAGE_LAYOUT_GENERAL;
|
||||
}
|
||||
switch (surface_type) {
|
||||
case SurfaceType::ColorTexture:
|
||||
return VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
|
||||
case SurfaceType::Depth:
|
||||
return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
|
||||
case SurfaceType::Stencil:
|
||||
return VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
|
||||
case SurfaceType::DepthStencil:
|
||||
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
|
||||
default:
|
||||
return VK_IMAGE_LAYOUT_GENERAL;
|
||||
}
|
||||
VkImageLayout AttachmentLayout(const Device& device, SurfaceType surface_type, bool want_feedback_loop) {
|
||||
if (want_feedback_loop && device.SupportsAttachmentFeedbackLoopLayout()) {
|
||||
// Single layout works for color and depth/stencil images.
|
||||
return VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
|
||||
}
|
||||
|
||||
// Normal (non-feedback) attachment layouts
|
||||
switch (surface_type) {
|
||||
case SurfaceType::ColorTexture:
|
||||
return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
|
||||
case SurfaceType::Depth:
|
||||
return device.SupportsSeparateDepthStencilLayouts()
|
||||
? VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL
|
||||
: VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
|
||||
case SurfaceType::Stencil:
|
||||
return device.SupportsSeparateDepthStencilLayouts()
|
||||
? VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL
|
||||
: VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
|
||||
case SurfaceType::DepthStencil:
|
||||
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
|
||||
default:
|
||||
return VK_IMAGE_LAYOUT_GENERAL; // last-resort fallback
|
||||
}
|
||||
}
|
||||
|
||||
VkAttachmentDescription AttachmentDescription(const Device& device, PixelFormat format,
|
||||
VkSampleCountFlagBits samples) {
|
||||
VkSampleCountFlagBits samples,
|
||||
VkAttachmentLoadOp load_op,
|
||||
VkAttachmentStoreOp store_op,
|
||||
VkAttachmentLoadOp stencil_load_op,
|
||||
VkAttachmentStoreOp stencil_store_op,
|
||||
bool want_feedback_loop) {
|
||||
using MaxwellToVK::SurfaceFormat;
|
||||
|
||||
const SurfaceType surface_type = GetSurfaceType(format);
|
||||
const bool has_stencil = surface_type == SurfaceType::DepthStencil ||
|
||||
surface_type == SurfaceType::Stencil;
|
||||
const VkImageLayout layout = AttachmentLayout(device, surface_type);
|
||||
const VkImageLayout layout = AttachmentLayout(device, surface_type, want_feedback_loop);
|
||||
const VkAttachmentLoadOp resolved_stencil_load =
|
||||
has_stencil ? stencil_load_op : VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
const VkAttachmentStoreOp resolved_stencil_store =
|
||||
has_stencil ? stencil_store_op : VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
return {
|
||||
.flags = {},
|
||||
.format = SurfaceFormat(device, FormatType::Optimal, true, format).format,
|
||||
.samples = samples,
|
||||
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
|
||||
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
||||
.stencilLoadOp = has_stencil ? VK_ATTACHMENT_LOAD_OP_LOAD
|
||||
: VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||
.stencilStoreOp = has_stencil ? VK_ATTACHMENT_STORE_OP_STORE
|
||||
: VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
||||
.loadOp = load_op,
|
||||
.storeOp = store_op,
|
||||
.stencilLoadOp = resolved_stencil_load,
|
||||
.stencilStoreOp = resolved_stencil_store,
|
||||
.initialLayout = layout,
|
||||
.finalLayout = layout,
|
||||
};
|
||||
|
@ -97,6 +116,7 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) {
|
|||
std::array<VkAttachmentReference, 8> references{};
|
||||
u32 num_attachments{};
|
||||
u32 num_colors{};
|
||||
const bool supports_feedback_loop = device->SupportsAttachmentFeedbackLoopLayout();
|
||||
for (size_t index = 0; index < key.color_formats.size(); ++index) {
|
||||
const PixelFormat format{key.color_formats[index]};
|
||||
if (format == PixelFormat::Invalid) {
|
||||
|
@ -108,12 +128,17 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) {
|
|||
}
|
||||
|
||||
const SurfaceType surface_type = GetSurfaceType(format);
|
||||
const VkImageLayout layout = AttachmentLayout(*device, surface_type);
|
||||
const VkImageLayout layout = AttachmentLayout(*device, surface_type, supports_feedback_loop);
|
||||
references[index] = VkAttachmentReference{
|
||||
.attachment = num_colors,
|
||||
.layout = layout,
|
||||
};
|
||||
descriptions.push_back(AttachmentDescription(*device, format, key.samples));
|
||||
const VkAttachmentLoadOp load_op = key.color_load_ops[index];
|
||||
const VkAttachmentStoreOp store_op = key.color_store_ops[index];
|
||||
descriptions.push_back(AttachmentDescription(*device, format, key.samples, load_op, store_op,
|
||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||
VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
||||
supports_feedback_loop));
|
||||
num_attachments = static_cast<u32>(index + 1);
|
||||
++num_colors;
|
||||
}
|
||||
|
@ -122,18 +147,18 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) {
|
|||
VkAttachmentReference depth_reference{};
|
||||
if (has_depth) {
|
||||
const SurfaceType depth_type = GetSurfaceType(key.depth_format);
|
||||
const VkImageLayout depth_layout = AttachmentLayout(*device, depth_type);
|
||||
const VkImageLayout depth_layout = AttachmentLayout(*device, depth_type, supports_feedback_loop);
|
||||
depth_reference = VkAttachmentReference{
|
||||
.attachment = num_colors,
|
||||
.layout = depth_layout,
|
||||
};
|
||||
descriptions.push_back(AttachmentDescription(*device, key.depth_format, key.samples));
|
||||
descriptions.push_back(AttachmentDescription(*device, key.depth_format, key.samples,
|
||||
key.depth_load_op, key.depth_store_op,
|
||||
key.stencil_load_op, key.stencil_store_op,
|
||||
supports_feedback_loop));
|
||||
}
|
||||
const bool supports_feedback_loop = device->SupportsAttachmentFeedbackLoopLayout();
|
||||
const VkSubpassDescription subpass{
|
||||
.flags = supports_feedback_loop
|
||||
? VK_SUBPASS_DESCRIPTION_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT
|
||||
: 0u,
|
||||
.flags = 0u,
|
||||
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
.inputAttachmentCount = 0,
|
||||
.pInputAttachments = nullptr,
|
||||
|
@ -144,6 +169,11 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) {
|
|||
.preserveAttachmentCount = 0,
|
||||
.pPreserveAttachments = nullptr,
|
||||
};
|
||||
|
||||
VkDependencyFlags dependency_flags = VK_DEPENDENCY_BY_REGION_BIT;
|
||||
if (supports_feedback_loop) {
|
||||
dependency_flags |= VK_DEPENDENCY_FEEDBACK_LOOP_BIT_EXT;
|
||||
}
|
||||
const VkSubpassDependency dependency{
|
||||
.srcSubpass = 0, // Current subpass
|
||||
.dstSubpass = 0, // Same subpass (self-dependency)
|
||||
|
@ -153,9 +183,11 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) {
|
|||
.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||
.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
|
||||
.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT
|
||||
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
|
||||
.dependencyFlags = dependency_flags
|
||||
};
|
||||
const VkSubpassDependency* dependency_ptr = supports_feedback_loop ? &dependency : nullptr;
|
||||
const u32 dependency_count = supports_feedback_loop ? 1u : 0u;
|
||||
pair->second = device->GetLogical().CreateRenderPass({
|
||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
|
@ -164,10 +196,11 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) {
|
|||
.pAttachments = descriptions.empty() ? nullptr : descriptions.data(),
|
||||
.subpassCount = 1,
|
||||
.pSubpasses = &subpass,
|
||||
.dependencyCount = supports_feedback_loop ? 1u : 0u,
|
||||
.pDependencies = supports_feedback_loop ? &dependency : nullptr,
|
||||
.dependencyCount = dependency_count,
|
||||
.pDependencies = dependency_ptr,
|
||||
});
|
||||
return *pair->second;
|
||||
}
|
||||
|
||||
} // namespace Vulkan
|
||||
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <array>
|
||||
|
||||
#include "common/container_hash.h"
|
||||
#include "video_core/surface.h"
|
||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||
|
||||
|
@ -15,7 +17,13 @@ struct RenderPassKey {
|
|||
bool operator==(const RenderPassKey&) const noexcept = default;
|
||||
|
||||
std::array<VideoCore::Surface::PixelFormat, 8> color_formats;
|
||||
std::array<VkAttachmentLoadOp, 8> color_load_ops;
|
||||
std::array<VkAttachmentStoreOp, 8> color_store_ops;
|
||||
VideoCore::Surface::PixelFormat depth_format;
|
||||
VkAttachmentLoadOp depth_load_op;
|
||||
VkAttachmentStoreOp depth_store_op;
|
||||
VkAttachmentLoadOp stencil_load_op;
|
||||
VkAttachmentStoreOp stencil_store_op;
|
||||
VkSampleCountFlagBits samples;
|
||||
};
|
||||
|
||||
|
@ -25,11 +33,18 @@ namespace std {
|
|||
template <>
|
||||
struct hash<Vulkan::RenderPassKey> {
|
||||
[[nodiscard]] size_t operator()(const Vulkan::RenderPassKey& key) const noexcept {
|
||||
size_t value = static_cast<size_t>(key.depth_format) << 48;
|
||||
value ^= static_cast<size_t>(key.samples) << 52;
|
||||
size_t value = 0;
|
||||
for (size_t i = 0; i < key.color_formats.size(); ++i) {
|
||||
value ^= static_cast<size_t>(key.color_formats[i]) << (i * 6);
|
||||
Common::HashCombine(value, static_cast<size_t>(key.color_formats[i]));
|
||||
Common::HashCombine(value, static_cast<size_t>(key.color_load_ops[i]));
|
||||
Common::HashCombine(value, static_cast<size_t>(key.color_store_ops[i]));
|
||||
}
|
||||
Common::HashCombine(value, static_cast<size_t>(key.depth_format));
|
||||
Common::HashCombine(value, static_cast<size_t>(key.depth_load_op));
|
||||
Common::HashCombine(value, static_cast<size_t>(key.depth_store_op));
|
||||
Common::HashCombine(value, static_cast<size_t>(key.stencil_load_op));
|
||||
Common::HashCombine(value, static_cast<size_t>(key.stencil_store_op));
|
||||
Common::HashCombine(value, static_cast<size_t>(key.samples));
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -108,62 +108,62 @@ void Scheduler::RequestRenderpass(const Framebuffer* framebuffer) {
|
|||
renderpass_image_ranges = framebuffer->ImageRanges();
|
||||
renderpass_image_layouts = framebuffer->ImageLayouts();
|
||||
|
||||
if (device.SupportsAttachmentFeedbackLoopLayout()) {
|
||||
Record([num_images = num_renderpass_images, images = renderpass_images,
|
||||
ranges = renderpass_image_ranges,
|
||||
layouts = renderpass_image_layouts](vk::CommandBuffer cmdbuf) {
|
||||
std::array<VkImageMemoryBarrier, 9> barriers{};
|
||||
u32 barrier_count = 0;
|
||||
VkPipelineStageFlags dst_stages = 0;
|
||||
// Transition images into their render-pass attachment layouts when needed.
|
||||
Record([num_images = num_renderpass_images, images = renderpass_images,
|
||||
ranges = renderpass_image_ranges,
|
||||
layouts = renderpass_image_layouts](vk::CommandBuffer cmdbuf) {
|
||||
std::array<VkImageMemoryBarrier, 9> barriers{};
|
||||
u32 barrier_count = 0;
|
||||
VkPipelineStageFlags dst_stages = 0;
|
||||
|
||||
for (size_t i = 0; i < num_images; ++i) {
|
||||
const VkImageLayout layout = layouts[i];
|
||||
if (layout == VK_IMAGE_LAYOUT_GENERAL) {
|
||||
continue;
|
||||
}
|
||||
const VkImageSubresourceRange& range = ranges[i];
|
||||
VkAccessFlags dst_access = 0;
|
||||
VkPipelineStageFlags dst_stage = 0;
|
||||
if ((range.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != 0) {
|
||||
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)) != 0) {
|
||||
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;
|
||||
}
|
||||
if (dst_access == 0) {
|
||||
continue;
|
||||
}
|
||||
barriers[barrier_count++] = VkImageMemoryBarrier{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.pNext = nullptr,
|
||||
.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT |
|
||||
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
|
||||
VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
.dstAccessMask = dst_access,
|
||||
.oldLayout = layout,
|
||||
.newLayout = layout,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = images[i],
|
||||
.subresourceRange = range,
|
||||
};
|
||||
dst_stages |= dst_stage;
|
||||
for (size_t i = 0; i < num_images; ++i) {
|
||||
const VkImageLayout layout = layouts[i];
|
||||
if (layout == VK_IMAGE_LAYOUT_GENERAL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (barrier_count == 0) {
|
||||
return;
|
||||
const VkImageSubresourceRange& range = ranges[i];
|
||||
VkAccessFlags dst_access = 0;
|
||||
VkPipelineStageFlags dst_stage = 0;
|
||||
if ((range.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != 0) {
|
||||
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)) != 0) {
|
||||
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;
|
||||
}
|
||||
if (dst_access == 0) {
|
||||
continue;
|
||||
}
|
||||
// If transitioning to feedback-loop layout, also make shader reads available.
|
||||
if (layout == VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT) {
|
||||
dst_access |= VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT;
|
||||
dst_stage |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
}
|
||||
barriers[barrier_count++] = VkImageMemoryBarrier{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.pNext = nullptr,
|
||||
.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
|
||||
.dstAccessMask = dst_access,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.newLayout = layout,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = images[i],
|
||||
.subresourceRange = range,
|
||||
};
|
||||
dst_stages |= dst_stage;
|
||||
}
|
||||
|
||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, dst_stages, 0, {}, {},
|
||||
{barriers.data(), barrier_count});
|
||||
});
|
||||
}
|
||||
if (barrier_count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, dst_stages, 0, {}, {},
|
||||
{barriers.data(), barrier_count});
|
||||
});
|
||||
|
||||
Record([renderpass, framebuffer_handle, render_area](vk::CommandBuffer cmdbuf) {
|
||||
const VkRenderPassBeginInfo renderpass_bi{
|
||||
|
@ -373,7 +373,7 @@ void Scheduler::EndRenderPass()
|
|||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.pNext = nullptr,
|
||||
.srcAccessMask = src_access,
|
||||
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT
|
||||
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
|
||||
| VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
|
||||
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
|
||||
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
|
||||
|
@ -417,5 +417,3 @@ void Scheduler::AcquireNewChunk() {
|
|||
}
|
||||
|
||||
} // namespace Vulkan
|
||||
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ using VideoCore::Surface::HasAlpha;
|
|||
using VideoCore::Surface::IsPixelFormatASTC;
|
||||
using VideoCore::Surface::IsPixelFormatInteger;
|
||||
using VideoCore::Surface::SurfaceType;
|
||||
using VideoCore::Surface::GetFormatType;
|
||||
|
||||
namespace {
|
||||
constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
|
||||
|
@ -127,22 +128,32 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
|
|||
|
||||
[[nodiscard]] VkImageLayout AttachmentFeedbackLoopLayout(const Device& device,
|
||||
VkImageAspectFlags aspect_mask) {
|
||||
if (!device.SupportsAttachmentFeedbackLoopLayout()) {
|
||||
if (device.SupportsAttachmentFeedbackLoopLayout()) {
|
||||
static constexpr VkImageAspectFlags kSupportedAspects = VK_IMAGE_ASPECT_COLOR_BIT |
|
||||
VK_IMAGE_ASPECT_DEPTH_BIT |
|
||||
VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
if ((aspect_mask & kSupportedAspects) != 0) {
|
||||
return VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
|
||||
}
|
||||
return VK_IMAGE_LAYOUT_GENERAL;
|
||||
}
|
||||
// No feedback-loop extension: return optimal attachment layouts
|
||||
if ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != 0) {
|
||||
return VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
|
||||
return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
}
|
||||
const bool sep = device.SupportsSeparateDepthStencilLayouts();
|
||||
const bool has_depth = (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
|
||||
const bool has_stencil = (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0;
|
||||
if (has_depth && has_stencil) {
|
||||
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
|
||||
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
}
|
||||
if (has_depth) {
|
||||
return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
|
||||
return sep ? VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL
|
||||
: VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
}
|
||||
if (has_stencil) {
|
||||
return VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
|
||||
return sep ? VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL
|
||||
: VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
}
|
||||
return VK_IMAGE_LAYOUT_GENERAL;
|
||||
}
|
||||
|
@ -2316,11 +2327,13 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
|
|||
std::span<ImageView*, NUM_RT> color_buffers,
|
||||
ImageView* depth_buffer, bool is_rescaled_) {
|
||||
boost::container::small_vector<VkImageView, NUM_RT + 1> attachments;
|
||||
RenderPassKey renderpass_key{};
|
||||
s32 num_layers = 1;
|
||||
num_images = 0;
|
||||
num_color_buffers = 0;
|
||||
image_layouts.fill(VK_IMAGE_LAYOUT_GENERAL);
|
||||
this->runtime = &runtime;
|
||||
color_formats.fill(PixelFormat::Invalid);
|
||||
depth_format = PixelFormat::Invalid;
|
||||
|
||||
is_rescaled = is_rescaled_;
|
||||
const auto& resolution = runtime.resolution;
|
||||
|
@ -2330,7 +2343,7 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
|
|||
for (size_t index = 0; index < NUM_RT; ++index) {
|
||||
const ImageView* const color_buffer = color_buffers[index];
|
||||
if (!color_buffer) {
|
||||
renderpass_key.color_formats[index] = PixelFormat::Invalid;
|
||||
color_formats[index] = PixelFormat::Invalid;
|
||||
continue;
|
||||
}
|
||||
width = (std::min)(width, is_rescaled ? resolution.ScaleUp(color_buffer->size.width)
|
||||
|
@ -2338,7 +2351,7 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
|
|||
height = (std::min)(height, is_rescaled ? resolution.ScaleUp(color_buffer->size.height)
|
||||
: color_buffer->size.height);
|
||||
attachments.push_back(color_buffer->RenderTarget());
|
||||
renderpass_key.color_formats[index] = color_buffer->format;
|
||||
color_formats[index] = color_buffer->format;
|
||||
num_layers = (std::max)(num_layers, color_buffer->range.extent.layers);
|
||||
images[num_images] = color_buffer->ImageHandle();
|
||||
const VkImageSubresourceRange subresource_range = MakeSubresourceRange(color_buffer);
|
||||
|
@ -2356,7 +2369,7 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
|
|||
height = (std::min)(height, is_rescaled ? resolution.ScaleUp(depth_buffer->size.height)
|
||||
: depth_buffer->size.height);
|
||||
attachments.push_back(depth_buffer->RenderTarget());
|
||||
renderpass_key.depth_format = depth_buffer->format;
|
||||
depth_format = depth_buffer->format;
|
||||
num_layers = (std::max)(num_layers, depth_buffer->range.extent.layers);
|
||||
images[num_images] = depth_buffer->ImageHandle();
|
||||
const VkImageSubresourceRange subresource_range = MakeSubresourceRange(depth_buffer);
|
||||
|
@ -2368,11 +2381,10 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
|
|||
has_depth = (subresource_range.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
|
||||
has_stencil = (subresource_range.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0;
|
||||
} else {
|
||||
renderpass_key.depth_format = PixelFormat::Invalid;
|
||||
depth_format = PixelFormat::Invalid;
|
||||
}
|
||||
renderpass_key.samples = samples;
|
||||
|
||||
renderpass = runtime.render_pass_cache.Get(renderpass_key);
|
||||
std::array<bool, NUM_RT> no_discard{};
|
||||
UpdateLoadOps(no_discard, false, false);
|
||||
render_area.width = (std::min)(render_area.width, width);
|
||||
render_area.height = (std::min)(render_area.height, height);
|
||||
|
||||
|
@ -2390,6 +2402,64 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
|
|||
});
|
||||
}
|
||||
|
||||
RenderPassKey Framebuffer::BuildRenderPassKey() const {
|
||||
RenderPassKey key{};
|
||||
key.color_formats = color_formats;
|
||||
key.color_load_ops = color_load_ops;
|
||||
key.color_store_ops = color_store_ops;
|
||||
key.depth_format = depth_format;
|
||||
key.depth_load_op = depth_load_op;
|
||||
key.depth_store_op = depth_store_op;
|
||||
key.stencil_load_op = stencil_load_op;
|
||||
key.stencil_store_op = stencil_store_op;
|
||||
key.samples = samples;
|
||||
return key;
|
||||
}
|
||||
|
||||
void Framebuffer::UpdateLoadOps(const std::array<bool, NUM_RT>& discard_colors, bool discard_depth,
|
||||
bool discard_stencil) {
|
||||
for (size_t index = 0; index < NUM_RT; ++index) {
|
||||
if (color_formats[index] != PixelFormat::Invalid) {
|
||||
color_load_ops[index] = discard_colors[index] ? VK_ATTACHMENT_LOAD_OP_DONT_CARE
|
||||
: VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
color_store_ops[index] = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
} else {
|
||||
color_load_ops[index] = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
color_store_ops[index] = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
}
|
||||
}
|
||||
|
||||
if (depth_format != PixelFormat::Invalid) {
|
||||
const auto surface_type = GetFormatType(depth_format);
|
||||
const bool has_depth_aspect = surface_type == SurfaceType::Depth ||
|
||||
surface_type == SurfaceType::DepthStencil;
|
||||
const bool has_stencil_aspect = surface_type == SurfaceType::Stencil ||
|
||||
surface_type == SurfaceType::DepthStencil;
|
||||
if (has_depth_aspect) {
|
||||
depth_load_op = discard_depth ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
depth_store_op = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
} else {
|
||||
depth_load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
depth_store_op = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
}
|
||||
if (has_stencil_aspect) {
|
||||
stencil_load_op = discard_stencil ? VK_ATTACHMENT_LOAD_OP_DONT_CARE
|
||||
: VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
stencil_store_op = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
} else {
|
||||
stencil_load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
stencil_store_op = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
}
|
||||
} else {
|
||||
depth_load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
depth_store_op = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
stencil_load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
stencil_store_op = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
}
|
||||
|
||||
renderpass = runtime->render_pass_cache.Get(BuildRenderPassKey());
|
||||
}
|
||||
|
||||
void TextureCacheRuntime::AccelerateImageUpload(
|
||||
Image& image, const StagingBufferRef& map,
|
||||
std::span<const VideoCommon::SwizzleParameters> swizzles) {
|
||||
|
|
|
@ -4,8 +4,10 @@
|
|||
#pragma once
|
||||
|
||||
#include <span>
|
||||
#include <array>
|
||||
|
||||
#include "video_core/texture_cache/texture_cache_base.h"
|
||||
#include "video_core/renderer_vulkan/vk_render_pass_cache.h"
|
||||
|
||||
#include "shader_recompiler/shader_info.h"
|
||||
#include "video_core/renderer_vulkan/vk_compute_pass.h"
|
||||
|
@ -318,6 +320,9 @@ public:
|
|||
|
||||
~Framebuffer();
|
||||
|
||||
void UpdateLoadOps(const std::array<bool, NUM_RT>& discard_colors, bool discard_depth,
|
||||
bool discard_stencil);
|
||||
|
||||
Framebuffer(const Framebuffer&) = delete;
|
||||
Framebuffer& operator=(const Framebuffer&) = delete;
|
||||
|
||||
|
@ -391,9 +396,20 @@ private:
|
|||
std::array<VkImageSubresourceRange, 9> image_ranges{};
|
||||
std::array<VkImageLayout, 9> image_layouts{};
|
||||
std::array<size_t, NUM_RT> rt_map{};
|
||||
TextureCacheRuntime* runtime{};
|
||||
std::array<PixelFormat, NUM_RT> color_formats{};
|
||||
PixelFormat depth_format{PixelFormat::Invalid};
|
||||
std::array<VkAttachmentLoadOp, NUM_RT> color_load_ops{};
|
||||
std::array<VkAttachmentStoreOp, NUM_RT> color_store_ops{};
|
||||
VkAttachmentLoadOp depth_load_op{VK_ATTACHMENT_LOAD_OP_DONT_CARE};
|
||||
VkAttachmentStoreOp depth_store_op{VK_ATTACHMENT_STORE_OP_DONT_CARE};
|
||||
VkAttachmentLoadOp stencil_load_op{VK_ATTACHMENT_LOAD_OP_DONT_CARE};
|
||||
VkAttachmentStoreOp stencil_store_op{VK_ATTACHMENT_STORE_OP_DONT_CARE};
|
||||
bool has_depth{};
|
||||
bool has_stencil{};
|
||||
bool is_rescaled{};
|
||||
|
||||
[[nodiscard]] RenderPassKey BuildRenderPassKey() const;
|
||||
};
|
||||
|
||||
struct TextureCacheParams {
|
||||
|
|
|
@ -424,13 +424,43 @@ template <class P>
|
|||
void TextureCache<P>::UpdateRenderTargets(bool is_clear) {
|
||||
using namespace VideoCommon::Dirty;
|
||||
auto& flags = maxwell3d->dirty.flags;
|
||||
|
||||
discard_color_on_load.fill(false);
|
||||
discard_depth_on_load = false;
|
||||
discard_stencil_on_load = false;
|
||||
|
||||
const auto& regs = maxwell3d->regs;
|
||||
const bool clear_color = is_clear && (regs.clear_surface.R || regs.clear_surface.G ||
|
||||
regs.clear_surface.B || regs.clear_surface.A);
|
||||
const u32 clear_rt = regs.clear_surface.RT;
|
||||
const bool clear_depth = is_clear && regs.clear_surface.Z;
|
||||
const bool clear_stencil = is_clear && regs.clear_surface.S;
|
||||
|
||||
const auto prepare_color = [&](size_t index, ImageViewId& color_buffer_id) {
|
||||
const bool has_attachment = static_cast<bool>(color_buffer_id);
|
||||
const bool full_clear = has_attachment ? IsFullClear(color_buffer_id) : true;
|
||||
const bool valid_target = clear_rt < NUM_RT;
|
||||
const bool target_clear = clear_color && valid_target && clear_rt == index && has_attachment;
|
||||
discard_color_on_load[index] = !has_attachment || (target_clear && full_clear);
|
||||
PrepareImageView(color_buffer_id, true, target_clear && full_clear);
|
||||
};
|
||||
|
||||
const auto prepare_depth = [&](ImageViewId depth_buffer_id) {
|
||||
const bool has_attachment = static_cast<bool>(depth_buffer_id);
|
||||
const bool full_clear = has_attachment ? IsFullClear(depth_buffer_id) : true;
|
||||
discard_depth_on_load = !has_attachment || (clear_depth && full_clear);
|
||||
discard_stencil_on_load = !has_attachment || (clear_stencil && full_clear);
|
||||
const bool invalidate = has_attachment && full_clear && (clear_depth || clear_stencil);
|
||||
PrepareImageView(depth_buffer_id, true, invalidate);
|
||||
};
|
||||
|
||||
if (!flags[Dirty::RenderTargets]) {
|
||||
for (size_t index = 0; index < NUM_RT; ++index) {
|
||||
ImageViewId& color_buffer_id = render_targets.color_buffer_ids[index];
|
||||
PrepareImageView(color_buffer_id, true, is_clear && IsFullClear(color_buffer_id));
|
||||
prepare_color(index, color_buffer_id);
|
||||
}
|
||||
const ImageViewId depth_buffer_id = render_targets.depth_buffer_id;
|
||||
PrepareImageView(depth_buffer_id, true, is_clear && IsFullClear(depth_buffer_id));
|
||||
prepare_depth(depth_buffer_id);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -443,11 +473,11 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) {
|
|||
|
||||
for (size_t index = 0; index < NUM_RT; ++index) {
|
||||
ImageViewId& color_buffer_id = render_targets.color_buffer_ids[index];
|
||||
PrepareImageView(color_buffer_id, true, is_clear && IsFullClear(color_buffer_id));
|
||||
prepare_color(index, color_buffer_id);
|
||||
}
|
||||
const ImageViewId depth_buffer_id = render_targets.depth_buffer_id;
|
||||
|
||||
PrepareImageView(depth_buffer_id, true, is_clear && IsFullClear(depth_buffer_id));
|
||||
prepare_depth(depth_buffer_id);
|
||||
|
||||
for (size_t index = 0; index < NUM_RT; ++index) {
|
||||
render_targets.draw_buffers[index] = static_cast<u8>(maxwell3d->regs.rt_control.Map(index));
|
||||
|
@ -469,7 +499,9 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) {
|
|||
|
||||
template <class P>
|
||||
typename P::Framebuffer* TextureCache<P>::GetFramebuffer() {
|
||||
return &slot_framebuffers[GetFramebufferId(render_targets)];
|
||||
auto* framebuffer = &slot_framebuffers[GetFramebufferId(render_targets)];
|
||||
framebuffer->UpdateLoadOps(discard_color_on_load, discard_depth_on_load, discard_stencil_on_load);
|
||||
return framebuffer;
|
||||
}
|
||||
|
||||
template <class P>
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <limits>
|
||||
#include <mutex>
|
||||
#include <span>
|
||||
#include <array>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
@ -439,6 +440,9 @@ private:
|
|||
std::deque<TextureCacheGPUMap> gpu_page_table_storage;
|
||||
|
||||
RenderTargets render_targets;
|
||||
std::array<bool, NUM_RT> discard_color_on_load{};
|
||||
bool discard_depth_on_load{};
|
||||
bool discard_stencil_on_load{};
|
||||
|
||||
std::unordered_map<RenderTargets, FramebufferId> framebuffers;
|
||||
|
||||
|
|
|
@ -17,16 +17,6 @@
|
|||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#ifndef VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT
|
||||
#define VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT
|
||||
#endif
|
||||
#ifndef VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT
|
||||
#define VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT
|
||||
#endif
|
||||
#ifndef VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT
|
||||
#define VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT
|
||||
#endif
|
||||
|
||||
// Sanitize macros
|
||||
#undef CreateEvent
|
||||
#undef CreateSemaphore
|
||||
|
|
|
@ -1220,6 +1220,13 @@ void Device::RemoveUnsuitableExtensions() {
|
|||
features.attachment_feedback_loop_layout,
|
||||
VK_EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_EXTENSION_NAME);
|
||||
|
||||
// VK_KHR_separate_depth_stencil_layouts
|
||||
extensions.separate_depth_stencil_layouts =
|
||||
features.separate_depth_stencil_layouts.separateDepthStencilLayouts;
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.separate_depth_stencil_layouts,
|
||||
features.separate_depth_stencil_layouts,
|
||||
VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME);
|
||||
|
||||
/* */ // VK_EXT_extended_dynamic_state
|
||||
extensions.extended_dynamic_state = features.extended_dynamic_state.extendedDynamicState;
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.extended_dynamic_state,
|
||||
|
|
|
@ -34,7 +34,9 @@ VK_DEFINE_HANDLE(VmaAllocator)
|
|||
#define FOR_EACH_VK_FEATURE_1_2(FEATURE) \
|
||||
FEATURE(EXT, HostQueryReset, HOST_QUERY_RESET, host_query_reset) \
|
||||
FEATURE(KHR, 8BitStorage, 8BIT_STORAGE, bit8_storage) \
|
||||
FEATURE(KHR, TimelineSemaphore, TIMELINE_SEMAPHORE, timeline_semaphore)
|
||||
FEATURE(KHR, TimelineSemaphore, TIMELINE_SEMAPHORE, timeline_semaphore) \
|
||||
FEATURE(KHR, SeparateDepthStencilLayouts, SEPARATE_DEPTH_STENCIL_LAYOUTS, \
|
||||
separate_depth_stencil_layouts)
|
||||
|
||||
#define FOR_EACH_VK_FEATURE_1_3(FEATURE) \
|
||||
FEATURE(EXT, ShaderDemoteToHelperInvocation, SHADER_DEMOTE_TO_HELPER_INVOCATION, \
|
||||
|
@ -569,6 +571,11 @@ public:
|
|||
features.attachment_feedback_loop_layout.attachmentFeedbackLoopLayout;
|
||||
}
|
||||
|
||||
bool SupportsSeparateDepthStencilLayouts() const {
|
||||
return extensions.separate_depth_stencil_layouts &&
|
||||
features.separate_depth_stencil_layouts.separateDepthStencilLayouts;
|
||||
}
|
||||
|
||||
|
||||
/// Returns true if the device supports VK_EXT_vertex_input_dynamic_state.
|
||||
bool IsExtVertexInputDynamicStateSupported() const {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue