Browse Source

[surface, vk, pipeline, texture_cache] Refactor image view handling and add normalized compatible format utility

true-eds-graphics
CamilleLaVey 4 weeks ago
parent
commit
6a230bec1a
  1. 2
      src/video_core/renderer_vulkan/pipeline_helper.h
  2. 66
      src/video_core/renderer_vulkan/vk_texture_cache.cpp
  3. 16
      src/video_core/renderer_vulkan/vk_texture_cache.h
  4. 35
      src/video_core/surface.cpp
  5. 3
      src/video_core/surface.h

2
src/video_core/renderer_vulkan/pipeline_helper.h

@ -189,7 +189,7 @@ inline void PushImageDescriptors(TextureCache& texture_cache,
const VideoCommon::ImageViewId image_view_id{(views++)->id}; const VideoCommon::ImageViewId image_view_id{(views++)->id};
const VideoCommon::SamplerId sampler_id{*(samplers++)}; const VideoCommon::SamplerId sampler_id{*(samplers++)};
ImageView& image_view{texture_cache.GetImageView(image_view_id)}; 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 Sampler& sampler{texture_cache.GetSampler(sampler_id)};
const bool use_fallback_sampler{sampler.HasAddedAnisotropy() && const bool use_fallback_sampler{sampler.HasAddedAnisotropy() &&
!image_view.SupportsAnisotropy()}; !image_view.SupportsAnisotropy()};

66
src/video_core/renderer_vulkan/vk_texture_cache.cpp

@ -45,6 +45,7 @@ using VideoCore::Surface::BytesPerBlock;
using VideoCore::Surface::HasAlpha; using VideoCore::Surface::HasAlpha;
using VideoCore::Surface::IsPixelFormatASTC; using VideoCore::Surface::IsPixelFormatASTC;
using VideoCore::Surface::IsPixelFormatInteger; using VideoCore::Surface::IsPixelFormatInteger;
using VideoCore::Surface::NormalizedCompatibleFormat;
using VideoCore::Surface::SurfaceType; using VideoCore::Surface::SurfaceType;
namespace { namespace {
@ -2040,7 +2041,8 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
samples(ConvertSampleCount(image.info.num_samples)) { samples(ConvertSampleCount(image.info.num_samples)) {
using Shader::TextureType; 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{ std::array<SwizzleSource, 4> swizzle{
SwizzleSource::R, SwizzleSource::R,
SwizzleSource::G, SwizzleSource::G,
@ -2072,6 +2074,14 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
.pNext = nullptr, .pNext = nullptr,
.usage = view_usage, .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{ const VkImageViewCreateInfo create_info{
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.pNext = &image_view_usage, .pNext = &image_view_usage,
@ -2079,13 +2089,8 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
.image = image.Handle(), .image = image.Handle(),
.viewType = VkImageViewType{}, .viewType = VkImageViewType{},
.format = format_info.format, .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) { const auto create = [&](TextureType tex_type, std::optional<u32> num_layers) {
VkImageViewCreateInfo ci{create_info}; VkImageViewCreateInfo ci{create_info};
@ -2098,6 +2103,7 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
handle.SetObjectNameEXT(VideoCommon::Name(*this, gpu_addr).c_str()); handle.SetObjectNameEXT(VideoCommon::Name(*this, gpu_addr).c_str());
} }
image_views[static_cast<size_t>(tex_type)] = std::move(handle); 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) { switch (info.type) {
case VideoCommon::ImageViewType::e1D: case VideoCommon::ImageViewType::e1D:
@ -2151,6 +2157,8 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageV
null_image = MakeImage(*device, runtime.memory_allocator, info, {}); null_image = MakeImage(*device, runtime.memory_allocator, info, {});
image_handle = *null_image; 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++) { for (u32 i = 0; i < Shader::NUM_TEXTURE_TYPES; i++) {
image_views[i] = MakeView(VK_FORMAT_A8B8G8R8_UNORM_PACK32, VK_IMAGE_ASPECT_COLOR_BIT); 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; 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 { bool ImageView::IsRescaled() const noexcept {
if (!slot_images) { if (!slot_images) {
return false; 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) { Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& tsc) {
const auto& device = runtime.device; const auto& device = runtime.device;
// Check if custom border colors are supported // Check if custom border colors are supported

16
src/video_core/renderer_vulkan/vk_texture_cache.h

@ -3,6 +3,8 @@
#pragma once #pragma once
#include <array>
#include <optional>
#include <span> #include <span>
#include "video_core/texture_cache/texture_cache_base.h" #include "video_core/texture_cache/texture_cache_base.h"
@ -242,6 +244,8 @@ public:
return *image_views[static_cast<size_t>(texture_type)]; return *image_views[static_cast<size_t>(texture_type)];
} }
[[nodiscard]] VkImageView SampledHandle(Shader::TextureType texture_type);
[[nodiscard]] VkImage ImageHandle() const noexcept { [[nodiscard]] VkImage ImageHandle() const noexcept {
return image_handle; return image_handle;
} }
@ -269,11 +273,15 @@ private:
}; };
[[nodiscard]] vk::ImageView MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask); [[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 Device* device = nullptr;
const SlotVector<Image>* slot_images = 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> 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; std::unique_ptr<StorageViews> storage_views;
vk::ImageView depth_view; vk::ImageView depth_view;
vk::ImageView stencil_view; vk::ImageView stencil_view;
@ -282,6 +290,14 @@ private:
VkImage image_handle = VK_NULL_HANDLE; VkImage image_handle = VK_NULL_HANDLE;
VkImageView render_target = VK_NULL_HANDLE; VkImageView render_target = VK_NULL_HANDLE;
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT; 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; u32 buffer_size = 0;
}; };

35
src/video_core/surface.cpp

@ -4,6 +4,8 @@
// SPDX-FileCopyrightText: 2014 Citra Emulator Project // SPDX-FileCopyrightText: 2014 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <optional>
#include "common/common_types.h" #include "common/common_types.h"
#include "common/math_util.h" #include "common/math_util.h"
#include "common/settings.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) { size_t PixelComponentSizeBitsInteger(PixelFormat format) {
switch (format) { switch (format) {
case PixelFormat::A8B8G8R8_SINT: case PixelFormat::A8B8G8R8_SINT:

3
src/video_core/surface.h

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <climits> #include <climits>
#include <optional>
#include <utility> #include <utility>
#include "common/assert.h" #include "common/assert.h"
#include "common/common_types.h" #include "common/common_types.h"
@ -515,6 +516,8 @@ bool IsPixelFormatInteger(PixelFormat format);
bool IsPixelFormatSignedInteger(PixelFormat format); bool IsPixelFormatSignedInteger(PixelFormat format);
std::optional<PixelFormat> NormalizedCompatibleFormat(PixelFormat format);
size_t PixelComponentSizeBitsInteger(PixelFormat format); size_t PixelComponentSizeBitsInteger(PixelFormat format);
std::pair<u32, u32> GetASTCBlockSize(PixelFormat format); std::pair<u32, u32> GetASTCBlockSize(PixelFormat format);

Loading…
Cancel
Save