[surface, vk, pipeline, texture_cache] Refactor image view handling and add normalized compatible format utility
This commit is contained in:
@@ -189,7 +189,7 @@ inline void PushImageDescriptors(TextureCache& texture_cache,
|
||||
const VideoCommon::ImageViewId image_view_id{(views++)->id};
|
||||
const VideoCommon::SamplerId sampler_id{*(samplers++)};
|
||||
ImageView& image_view{texture_cache.GetImageView(image_view_id)};
|
||||
const VkImageView vk_image_view{image_view.Handle(desc.type)};
|
||||
const VkImageView vk_image_view{image_view.SampledHandle(desc.type)};
|
||||
const Sampler& sampler{texture_cache.GetSampler(sampler_id)};
|
||||
const bool use_fallback_sampler{sampler.HasAddedAnisotropy() &&
|
||||
!image_view.SupportsAnisotropy()};
|
||||
|
||||
@@ -45,6 +45,7 @@ using VideoCore::Surface::BytesPerBlock;
|
||||
using VideoCore::Surface::HasAlpha;
|
||||
using VideoCore::Surface::IsPixelFormatASTC;
|
||||
using VideoCore::Surface::IsPixelFormatInteger;
|
||||
using VideoCore::Surface::NormalizedCompatibleFormat;
|
||||
using VideoCore::Surface::SurfaceType;
|
||||
|
||||
namespace {
|
||||
@@ -2040,7 +2041,8 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
|
||||
samples(ConvertSampleCount(image.info.num_samples)) {
|
||||
using Shader::TextureType;
|
||||
|
||||
const VkImageAspectFlags aspect_mask = ImageViewAspectMask(info);
|
||||
const VkImageAspectFlags aspect_mask_local = ImageViewAspectMask(info);
|
||||
aspect_mask = aspect_mask_local;
|
||||
std::array<SwizzleSource, 4> swizzle{
|
||||
SwizzleSource::R,
|
||||
SwizzleSource::G,
|
||||
@@ -2072,6 +2074,14 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
|
||||
.pNext = nullptr,
|
||||
.usage = view_usage,
|
||||
};
|
||||
view_usage_flags = view_usage;
|
||||
const VkComponentMapping components{
|
||||
.r = ComponentSwizzle(swizzle[0]),
|
||||
.g = ComponentSwizzle(swizzle[1]),
|
||||
.b = ComponentSwizzle(swizzle[2]),
|
||||
.a = ComponentSwizzle(swizzle[3]),
|
||||
};
|
||||
component_mapping = components;
|
||||
const VkImageViewCreateInfo create_info{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.pNext = &image_view_usage,
|
||||
@@ -2079,13 +2089,8 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
|
||||
.image = image.Handle(),
|
||||
.viewType = VkImageViewType{},
|
||||
.format = format_info.format,
|
||||
.components{
|
||||
.r = ComponentSwizzle(swizzle[0]),
|
||||
.g = ComponentSwizzle(swizzle[1]),
|
||||
.b = ComponentSwizzle(swizzle[2]),
|
||||
.a = ComponentSwizzle(swizzle[3]),
|
||||
},
|
||||
.subresourceRange = MakeSubresourceRange(aspect_mask, info.range),
|
||||
.components = components,
|
||||
.subresourceRange = MakeSubresourceRange(aspect_mask_local, info.range),
|
||||
};
|
||||
const auto create = [&](TextureType tex_type, std::optional<u32> num_layers) {
|
||||
VkImageViewCreateInfo ci{create_info};
|
||||
@@ -2098,6 +2103,7 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
|
||||
handle.SetObjectNameEXT(VideoCommon::Name(*this, gpu_addr).c_str());
|
||||
}
|
||||
image_views[static_cast<size_t>(tex_type)] = std::move(handle);
|
||||
view_layer_counts[static_cast<size_t>(tex_type)] = num_layers;
|
||||
};
|
||||
switch (info.type) {
|
||||
case VideoCommon::ImageViewType::e1D:
|
||||
@@ -2151,6 +2157,8 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageV
|
||||
|
||||
null_image = MakeImage(*device, runtime.memory_allocator, info, {});
|
||||
image_handle = *null_image;
|
||||
aspect_mask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
view_usage_flags = VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
for (u32 i = 0; i < Shader::NUM_TEXTURE_TYPES; i++) {
|
||||
image_views[i] = MakeView(VK_FORMAT_A8B8G8R8_UNORM_PACK32, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
}
|
||||
@@ -2215,6 +2223,24 @@ VkImageView ImageView::StorageView(Shader::TextureType texture_type,
|
||||
return *view;
|
||||
}
|
||||
|
||||
VkImageView ImageView::SampledHandle(Shader::TextureType texture_type) {
|
||||
if (!IsPixelFormatInteger(format)) {
|
||||
return Handle(texture_type);
|
||||
}
|
||||
const auto compatible_format = NormalizedCompatibleFormat(format);
|
||||
if (!compatible_format) {
|
||||
return Handle(texture_type);
|
||||
}
|
||||
auto& view = sampled_float_views[static_cast<size_t>(texture_type)];
|
||||
if (view) {
|
||||
return *view;
|
||||
}
|
||||
const auto format_info =
|
||||
MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, true, *compatible_format);
|
||||
view = CreateSampledView(texture_type, format_info.format);
|
||||
return *view;
|
||||
}
|
||||
|
||||
bool ImageView::IsRescaled() const noexcept {
|
||||
if (!slot_images) {
|
||||
return false;
|
||||
@@ -2242,6 +2268,30 @@ vk::ImageView ImageView::MakeView(VkFormat vk_format, VkImageAspectFlags aspect_
|
||||
});
|
||||
}
|
||||
|
||||
vk::ImageView ImageView::CreateSampledView(Shader::TextureType texture_type,
|
||||
VkFormat vk_format) const {
|
||||
const VkImageViewUsageCreateInfo usage_info{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.usage = view_usage_flags,
|
||||
};
|
||||
VkImageViewCreateInfo create_info{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.pNext = &usage_info,
|
||||
.flags = 0,
|
||||
.image = image_handle,
|
||||
.viewType = ImageViewType(texture_type),
|
||||
.format = vk_format,
|
||||
.components = component_mapping,
|
||||
.subresourceRange = MakeSubresourceRange(aspect_mask, range),
|
||||
};
|
||||
const auto idx = static_cast<size_t>(texture_type);
|
||||
if (view_layer_counts[idx]) {
|
||||
create_info.subresourceRange.layerCount = *view_layer_counts[idx];
|
||||
}
|
||||
return device->GetLogical().CreateImageView(create_info);
|
||||
}
|
||||
|
||||
Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& tsc) {
|
||||
const auto& device = runtime.device;
|
||||
// Check if custom border colors are supported
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include <span>
|
||||
|
||||
#include "video_core/texture_cache/texture_cache_base.h"
|
||||
@@ -242,6 +244,8 @@ public:
|
||||
return *image_views[static_cast<size_t>(texture_type)];
|
||||
}
|
||||
|
||||
[[nodiscard]] VkImageView SampledHandle(Shader::TextureType texture_type);
|
||||
|
||||
[[nodiscard]] VkImage ImageHandle() const noexcept {
|
||||
return image_handle;
|
||||
}
|
||||
@@ -269,11 +273,15 @@ private:
|
||||
};
|
||||
|
||||
[[nodiscard]] vk::ImageView MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask);
|
||||
[[nodiscard]] vk::ImageView CreateSampledView(Shader::TextureType texture_type,
|
||||
VkFormat vk_format) const;
|
||||
|
||||
const Device* device = nullptr;
|
||||
const SlotVector<Image>* slot_images = nullptr;
|
||||
|
||||
std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> image_views;
|
||||
std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> sampled_float_views;
|
||||
std::array<std::optional<u32>, Shader::NUM_TEXTURE_TYPES> view_layer_counts{};
|
||||
std::unique_ptr<StorageViews> storage_views;
|
||||
vk::ImageView depth_view;
|
||||
vk::ImageView stencil_view;
|
||||
@@ -282,6 +290,14 @@ private:
|
||||
VkImage image_handle = VK_NULL_HANDLE;
|
||||
VkImageView render_target = VK_NULL_HANDLE;
|
||||
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
VkComponentMapping component_mapping{
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
};
|
||||
VkImageAspectFlags aspect_mask = 0;
|
||||
VkImageUsageFlags view_usage_flags = 0;
|
||||
u32 buffer_size = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "common/math_util.h"
|
||||
#include "common/settings.h"
|
||||
@@ -408,6 +410,39 @@ bool IsPixelFormatSignedInteger(PixelFormat format) {
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<PixelFormat> NormalizedCompatibleFormat(PixelFormat format) {
|
||||
switch (format) {
|
||||
case PixelFormat::A8B8G8R8_UINT:
|
||||
return PixelFormat::A8B8G8R8_UNORM;
|
||||
case PixelFormat::A8B8G8R8_SINT:
|
||||
return PixelFormat::A8B8G8R8_SNORM;
|
||||
case PixelFormat::A2B10G10R10_UINT:
|
||||
return PixelFormat::A2B10G10R10_UNORM;
|
||||
case PixelFormat::R8_UINT:
|
||||
return PixelFormat::R8_UNORM;
|
||||
case PixelFormat::R8_SINT:
|
||||
return PixelFormat::R8_SNORM;
|
||||
case PixelFormat::R8G8_UINT:
|
||||
return PixelFormat::R8G8_UNORM;
|
||||
case PixelFormat::R8G8_SINT:
|
||||
return PixelFormat::R8G8_SNORM;
|
||||
case PixelFormat::R16_UINT:
|
||||
return PixelFormat::R16_UNORM;
|
||||
case PixelFormat::R16_SINT:
|
||||
return PixelFormat::R16_SNORM;
|
||||
case PixelFormat::R16G16_UINT:
|
||||
return PixelFormat::R16G16_UNORM;
|
||||
case PixelFormat::R16G16_SINT:
|
||||
return PixelFormat::R16G16_SNORM;
|
||||
case PixelFormat::R16G16B16A16_UINT:
|
||||
return PixelFormat::R16G16B16A16_UNORM;
|
||||
case PixelFormat::R16G16B16A16_SINT:
|
||||
return PixelFormat::R16G16B16A16_SNORM;
|
||||
default:
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
size_t PixelComponentSizeBitsInteger(PixelFormat format) {
|
||||
switch (format) {
|
||||
case PixelFormat::A8B8G8R8_SINT:
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <climits>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
@@ -515,6 +516,8 @@ bool IsPixelFormatInteger(PixelFormat format);
|
||||
|
||||
bool IsPixelFormatSignedInteger(PixelFormat format);
|
||||
|
||||
std::optional<PixelFormat> NormalizedCompatibleFormat(PixelFormat format);
|
||||
|
||||
size_t PixelComponentSizeBitsInteger(PixelFormat format);
|
||||
|
||||
std::pair<u32, u32> GetASTCBlockSize(PixelFormat format);
|
||||
|
||||
Reference in New Issue
Block a user