mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-05-25 19:47:06 +02:00
[surface, vk, pipeline, texture_cache] Refactor image view handling and add normalized compatible format utility
This commit is contained in:
parent
18dabbaaff
commit
6a230bec1a
5 changed files with 113 additions and 9 deletions
|
|
@ -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()};
|
||||||
|
|
|
||||||
|
|
@ -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{
|
.components = components,
|
||||||
.r = ComponentSwizzle(swizzle[0]),
|
.subresourceRange = MakeSubresourceRange(aspect_mask_local, info.range),
|
||||||
.g = ComponentSwizzle(swizzle[1]),
|
|
||||||
.b = ComponentSwizzle(swizzle[2]),
|
|
||||||
.a = ComponentSwizzle(swizzle[3]),
|
|
||||||
},
|
|
||||||
.subresourceRange = MakeSubresourceRange(aspect_mask, 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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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…
Add table
Add a link
Reference in a new issue