mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-05-15 04:06:57 +02:00
[gl, vk, spv] Added component type handling for texture buffers and resolve pixel format variants
This commit is contained in:
parent
8fdef17def
commit
b25581a87c
11 changed files with 376 additions and 5 deletions
|
|
@ -672,6 +672,7 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo
|
||||||
.secondary_shift_left = cbuf.secondary_shift_left,
|
.secondary_shift_left = cbuf.secondary_shift_left,
|
||||||
.count = cbuf.count,
|
.count = cbuf.count,
|
||||||
.size_shift = DESCRIPTOR_SIZE_SHIFT,
|
.size_shift = DESCRIPTOR_SIZE_SHIFT,
|
||||||
|
.component_type = ReadTextureComponentType(env, cbuf),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
index = descriptors.Add(TextureDescriptor{
|
index = descriptors.Add(TextureDescriptor{
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,7 @@ struct TextureBufferDescriptor {
|
||||||
u32 secondary_shift_left;
|
u32 secondary_shift_left;
|
||||||
u32 count;
|
u32 count;
|
||||||
u32 size_shift;
|
u32 size_shift;
|
||||||
|
SamplerComponentType component_type;
|
||||||
|
|
||||||
auto operator<=>(const TextureBufferDescriptor&) const = default;
|
auto operator<=>(const TextureBufferDescriptor&) const = default;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,50 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <bit>
|
#include <bit>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
#include <optional>
|
||||||
#include "common/cityhash.h"
|
#include "common/cityhash.h"
|
||||||
#include "common/settings.h" // for enum class Settings::ShaderBackend
|
#include "common/settings.h" // for enum class Settings::ShaderBackend
|
||||||
#include "video_core/renderer_opengl/gl_compute_pipeline.h"
|
#include "video_core/renderer_opengl/gl_compute_pipeline.h"
|
||||||
#include "video_core/renderer_opengl/gl_shader_manager.h"
|
#include "video_core/renderer_opengl/gl_shader_manager.h"
|
||||||
#include "video_core/renderer_opengl/gl_shader_util.h"
|
#include "video_core/renderer_opengl/gl_shader_util.h"
|
||||||
|
#include "video_core/surface/surface.h"
|
||||||
|
|
||||||
namespace OpenGL {
|
namespace OpenGL {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
std::optional<VideoCore::Surface::PixelFormatNumeric>
|
||||||
|
NumericFromComponentType(Shader::SamplerComponentType component_type) {
|
||||||
|
using VideoCore::Surface::PixelFormatNumeric;
|
||||||
|
switch (component_type) {
|
||||||
|
case Shader::SamplerComponentType::Float:
|
||||||
|
return PixelFormatNumeric::Float;
|
||||||
|
case Shader::SamplerComponentType::Sint:
|
||||||
|
return PixelFormatNumeric::Sint;
|
||||||
|
case Shader::SamplerComponentType::Uint:
|
||||||
|
return PixelFormatNumeric::Uint;
|
||||||
|
default:
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoCore::Surface::PixelFormat ResolveTexelBufferFormat(
|
||||||
|
VideoCore::Surface::PixelFormat format, Shader::SamplerComponentType component_type) {
|
||||||
|
const auto desired_numeric = NumericFromComponentType(component_type);
|
||||||
|
if (!desired_numeric) {
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
const auto current_numeric = VideoCore::Surface::GetPixelFormatNumericType(format);
|
||||||
|
if (*desired_numeric == current_numeric) {
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
if (const auto variant =
|
||||||
|
VideoCore::Surface::FindPixelFormatVariant(format, *desired_numeric)) {
|
||||||
|
return *variant;
|
||||||
|
}
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
using Shader::ImageBufferDescriptor;
|
using Shader::ImageBufferDescriptor;
|
||||||
using Tegra::Texture::TexturePair;
|
using Tegra::Texture::TexturePair;
|
||||||
|
|
@ -174,8 +211,12 @@ void ComputePipeline::Configure() {
|
||||||
is_written = desc.is_written;
|
is_written = desc.is_written;
|
||||||
}
|
}
|
||||||
ImageView& image_view{texture_cache.GetImageView(views[texbuf_index].id)};
|
ImageView& image_view{texture_cache.GetImageView(views[texbuf_index].id)};
|
||||||
|
auto buffer_format = image_view.format;
|
||||||
|
if constexpr (!is_image) {
|
||||||
|
buffer_format = ResolveTexelBufferFormat(buffer_format, desc.component_type);
|
||||||
|
}
|
||||||
buffer_cache.BindComputeTextureBuffer(texbuf_index, image_view.GpuAddr(),
|
buffer_cache.BindComputeTextureBuffer(texbuf_index, image_view.GpuAddr(),
|
||||||
image_view.BufferSize(), image_view.format,
|
image_view.BufferSize(), buffer_format,
|
||||||
is_written, is_image);
|
is_written, is_image);
|
||||||
++texbuf_index;
|
++texbuf_index;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <bit>
|
#include <bit>
|
||||||
|
|
@ -18,6 +19,7 @@
|
||||||
#include "video_core/renderer_opengl/gl_shader_util.h"
|
#include "video_core/renderer_opengl/gl_shader_util.h"
|
||||||
#include "video_core/renderer_opengl/gl_state_tracker.h"
|
#include "video_core/renderer_opengl/gl_state_tracker.h"
|
||||||
#include "video_core/shader_notify.h"
|
#include "video_core/shader_notify.h"
|
||||||
|
#include "video_core/surface/surface.h"
|
||||||
#include "video_core/texture_cache/texture_cache.h"
|
#include "video_core/texture_cache/texture_cache.h"
|
||||||
|
|
||||||
#if defined(_MSC_VER) && defined(NDEBUG)
|
#if defined(_MSC_VER) && defined(NDEBUG)
|
||||||
|
|
@ -39,6 +41,38 @@ using VideoCommon::ImageId;
|
||||||
constexpr u32 MAX_TEXTURES = 64;
|
constexpr u32 MAX_TEXTURES = 64;
|
||||||
constexpr u32 MAX_IMAGES = 8;
|
constexpr u32 MAX_IMAGES = 8;
|
||||||
|
|
||||||
|
std::optional<VideoCore::Surface::PixelFormatNumeric>
|
||||||
|
NumericFromComponentType(Shader::SamplerComponentType component_type) {
|
||||||
|
using VideoCore::Surface::PixelFormatNumeric;
|
||||||
|
switch (component_type) {
|
||||||
|
case Shader::SamplerComponentType::Float:
|
||||||
|
return PixelFormatNumeric::Float;
|
||||||
|
case Shader::SamplerComponentType::Sint:
|
||||||
|
return PixelFormatNumeric::Sint;
|
||||||
|
case Shader::SamplerComponentType::Uint:
|
||||||
|
return PixelFormatNumeric::Uint;
|
||||||
|
default:
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoCore::Surface::PixelFormat ResolveTexelBufferFormat(
|
||||||
|
VideoCore::Surface::PixelFormat format, Shader::SamplerComponentType component_type) {
|
||||||
|
const auto desired_numeric = NumericFromComponentType(component_type);
|
||||||
|
if (!desired_numeric) {
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
const auto current_numeric = VideoCore::Surface::GetPixelFormatNumericType(format);
|
||||||
|
if (*desired_numeric == current_numeric) {
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
if (const auto variant =
|
||||||
|
VideoCore::Surface::FindPixelFormatVariant(format, *desired_numeric)) {
|
||||||
|
return *variant;
|
||||||
|
}
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
GLenum Stage(size_t stage_index) {
|
GLenum Stage(size_t stage_index) {
|
||||||
switch (stage_index) {
|
switch (stage_index) {
|
||||||
case 0:
|
case 0:
|
||||||
|
|
@ -397,8 +431,12 @@ bool GraphicsPipeline::ConfigureImpl(bool is_indexed) {
|
||||||
is_written = desc.is_written;
|
is_written = desc.is_written;
|
||||||
}
|
}
|
||||||
ImageView& image_view{texture_cache.GetImageView(texture_buffer_it->id)};
|
ImageView& image_view{texture_cache.GetImageView(texture_buffer_it->id)};
|
||||||
|
auto buffer_format = image_view.format;
|
||||||
|
if constexpr (!is_image) {
|
||||||
|
buffer_format = ResolveTexelBufferFormat(buffer_format, desc.component_type);
|
||||||
|
}
|
||||||
buffer_cache.BindGraphicsTextureBuffer(stage, index, image_view.GpuAddr(),
|
buffer_cache.BindGraphicsTextureBuffer(stage, index, image_view.GpuAddr(),
|
||||||
image_view.BufferSize(), image_view.format,
|
image_view.BufferSize(), buffer_format,
|
||||||
is_written, is_image);
|
is_written, is_image);
|
||||||
++index;
|
++index;
|
||||||
++texture_buffer_it;
|
++texture_buffer_it;
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
#include "video_core/shader_notify.h"
|
#include "video_core/shader_notify.h"
|
||||||
#include "video_core/vulkan_common/vulkan_device.h"
|
#include "video_core/vulkan_common/vulkan_device.h"
|
||||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
|
|
@ -40,6 +41,38 @@ ComputePipeline::ComputePipeline(const Device& device_, vk::PipelineCache& pipel
|
||||||
if (shader_notify) {
|
if (shader_notify) {
|
||||||
shader_notify->MarkShaderBuilding();
|
shader_notify->MarkShaderBuilding();
|
||||||
}
|
}
|
||||||
|
std::optional<VideoCore::Surface::PixelFormatNumeric>
|
||||||
|
NumericFromComponentType(Shader::SamplerComponentType component_type) {
|
||||||
|
using VideoCore::Surface::PixelFormatNumeric;
|
||||||
|
switch (component_type) {
|
||||||
|
case Shader::SamplerComponentType::Float:
|
||||||
|
return PixelFormatNumeric::Float;
|
||||||
|
case Shader::SamplerComponentType::Sint:
|
||||||
|
return PixelFormatNumeric::Sint;
|
||||||
|
case Shader::SamplerComponentType::Uint:
|
||||||
|
return PixelFormatNumeric::Uint;
|
||||||
|
default:
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoCore::Surface::PixelFormat ResolveTexelBufferFormat(
|
||||||
|
VideoCore::Surface::PixelFormat format, Shader::SamplerComponentType component_type) {
|
||||||
|
const auto desired_numeric = NumericFromComponentType(component_type);
|
||||||
|
if (!desired_numeric) {
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
const auto current_numeric = VideoCore::Surface::GetPixelFormatNumericType(format);
|
||||||
|
if (*desired_numeric == current_numeric) {
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
if (const auto variant =
|
||||||
|
VideoCore::Surface::FindPixelFormatVariant(format, *desired_numeric)) {
|
||||||
|
return *variant;
|
||||||
|
}
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
std::copy_n(info.constant_buffer_used_sizes.begin(), uniform_buffer_sizes.size(),
|
std::copy_n(info.constant_buffer_used_sizes.begin(), uniform_buffer_sizes.size(),
|
||||||
uniform_buffer_sizes.begin());
|
uniform_buffer_sizes.begin());
|
||||||
|
|
||||||
|
|
@ -182,8 +215,12 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
|
||||||
is_written = desc.is_written;
|
is_written = desc.is_written;
|
||||||
}
|
}
|
||||||
ImageView& image_view = texture_cache.GetImageView(views[index].id);
|
ImageView& image_view = texture_cache.GetImageView(views[index].id);
|
||||||
|
VideoCore::Surface::PixelFormat buffer_format = image_view.format;
|
||||||
|
if constexpr (!is_image) {
|
||||||
|
buffer_format = ResolveTexelBufferFormat(buffer_format, desc.component_type);
|
||||||
|
}
|
||||||
buffer_cache.BindComputeTextureBuffer(index, image_view.GpuAddr(),
|
buffer_cache.BindComputeTextureBuffer(index, image_view.GpuAddr(),
|
||||||
image_view.BufferSize(), image_view.format,
|
image_view.BufferSize(), buffer_format,
|
||||||
is_written, is_image);
|
is_written, is_image);
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <optional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <span>
|
#include <span>
|
||||||
|
|
||||||
|
|
@ -62,6 +63,37 @@ DescriptorLayoutBuilder MakeBuilder(const Device& device, std::span<const Shader
|
||||||
};
|
};
|
||||||
builder.Add(infos[index], stages.at(index));
|
builder.Add(infos[index], stages.at(index));
|
||||||
}
|
}
|
||||||
|
std::optional<VideoCore::Surface::PixelFormatNumeric>
|
||||||
|
NumericFromComponentType(Shader::SamplerComponentType component_type) {
|
||||||
|
using VideoCore::Surface::PixelFormatNumeric;
|
||||||
|
switch (component_type) {
|
||||||
|
case Shader::SamplerComponentType::Float:
|
||||||
|
return PixelFormatNumeric::Float;
|
||||||
|
case Shader::SamplerComponentType::Sint:
|
||||||
|
return PixelFormatNumeric::Sint;
|
||||||
|
case Shader::SamplerComponentType::Uint:
|
||||||
|
return PixelFormatNumeric::Uint;
|
||||||
|
default:
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoCore::Surface::PixelFormat ResolveTexelBufferFormat(
|
||||||
|
VideoCore::Surface::PixelFormat format, Shader::SamplerComponentType component_type) {
|
||||||
|
const auto desired_numeric = NumericFromComponentType(component_type);
|
||||||
|
if (!desired_numeric) {
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
const auto current_numeric = VideoCore::Surface::GetPixelFormatNumericType(format);
|
||||||
|
if (*desired_numeric == current_numeric) {
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
if (const auto variant =
|
||||||
|
VideoCore::Surface::FindPixelFormatVariant(format, *desired_numeric)) {
|
||||||
|
return *variant;
|
||||||
|
}
|
||||||
|
return format;
|
||||||
|
}
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -419,8 +451,12 @@ bool GraphicsPipeline::ConfigureImpl(bool is_indexed) {
|
||||||
is_written = desc.is_written;
|
is_written = desc.is_written;
|
||||||
}
|
}
|
||||||
ImageView& image_view{texture_cache.GetImageView(texture_buffer_it->id)};
|
ImageView& image_view{texture_cache.GetImageView(texture_buffer_it->id)};
|
||||||
|
VideoCore::Surface::PixelFormat buffer_format = image_view.format;
|
||||||
|
if constexpr (!is_image) {
|
||||||
|
buffer_format = ResolveTexelBufferFormat(buffer_format, desc.component_type);
|
||||||
|
}
|
||||||
buffer_cache.BindGraphicsTextureBuffer(stage, index, image_view.GpuAddr(),
|
buffer_cache.BindGraphicsTextureBuffer(stage, index, image_view.GpuAddr(),
|
||||||
image_view.BufferSize(), image_view.format,
|
image_view.BufferSize(), buffer_format,
|
||||||
is_written, is_image);
|
is_written, is_image);
|
||||||
++index;
|
++index;
|
||||||
++texture_buffer_it;
|
++texture_buffer_it;
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ using VideoCore::Surface::HasAlpha;
|
||||||
using VideoCore::Surface::IsPixelFormatASTC;
|
using VideoCore::Surface::IsPixelFormatASTC;
|
||||||
using VideoCore::Surface::IsPixelFormatInteger;
|
using VideoCore::Surface::IsPixelFormatInteger;
|
||||||
using VideoCore::Surface::SurfaceType;
|
using VideoCore::Surface::SurfaceType;
|
||||||
|
using VideoCore::Surface::PixelFormatNumeric;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
|
constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
|
||||||
|
|
@ -2315,6 +2316,19 @@ std::optional<u32> ImageView::LayerCountOverride(Shader::TextureType texture_typ
|
||||||
default:
|
default:
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<PixelFormatNumeric> ComponentNumericType(Shader::SamplerComponentType component) {
|
||||||
|
switch (component) {
|
||||||
|
case Shader::SamplerComponentType::Float:
|
||||||
|
return PixelFormatNumeric::Float;
|
||||||
|
case Shader::SamplerComponentType::Sint:
|
||||||
|
return PixelFormatNumeric::Sint;
|
||||||
|
case Shader::SamplerComponentType::Uint:
|
||||||
|
return PixelFormatNumeric::Uint;
|
||||||
|
default:
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VkImageView ImageView::DepthView() {
|
VkImageView ImageView::DepthView() {
|
||||||
|
|
@ -2382,7 +2396,29 @@ VkImageView ImageView::SampledView(Shader::TextureType texture_type,
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return Handle(texture_type);
|
const auto desired_numeric = ComponentNumericType(component_type);
|
||||||
|
if (!desired_numeric) {
|
||||||
|
return Handle(texture_type);
|
||||||
|
}
|
||||||
|
const PixelFormatNumeric current_numeric =
|
||||||
|
VideoCore::Surface::GetPixelFormatNumericType(format);
|
||||||
|
if (*desired_numeric == current_numeric) {
|
||||||
|
return Handle(texture_type);
|
||||||
|
}
|
||||||
|
const auto remapped_format =
|
||||||
|
VideoCore::Surface::FindPixelFormatVariant(format, *desired_numeric);
|
||||||
|
if (!remapped_format) {
|
||||||
|
return Handle(texture_type);
|
||||||
|
}
|
||||||
|
auto& cached_view = sampled_component_views[static_cast<size_t>(*desired_numeric)]
|
||||||
|
[static_cast<size_t>(texture_type)];
|
||||||
|
if (cached_view) {
|
||||||
|
return *cached_view;
|
||||||
|
}
|
||||||
|
const auto& info =
|
||||||
|
MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, true, *remapped_format);
|
||||||
|
cached_view = MakeView(info.format, VK_IMAGE_ASPECT_COLOR_BIT, texture_type);
|
||||||
|
return *cached_view;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkImageView ImageView::StorageView(Shader::TextureType texture_type,
|
VkImageView ImageView::StorageView(Shader::TextureType texture_type,
|
||||||
|
|
|
||||||
|
|
@ -275,6 +275,8 @@ private:
|
||||||
std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> typeless;
|
std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> typeless;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static constexpr size_t NUMERIC_VIEW_TYPES = 3;
|
||||||
|
|
||||||
[[nodiscard]] Shader::TextureType BaseTextureType() const noexcept;
|
[[nodiscard]] Shader::TextureType BaseTextureType() const noexcept;
|
||||||
[[nodiscard]] std::optional<u32> LayerCountOverride(Shader::TextureType texture_type) const noexcept;
|
[[nodiscard]] std::optional<u32> LayerCountOverride(Shader::TextureType texture_type) const noexcept;
|
||||||
[[nodiscard]] VkImageView DepthView(Shader::TextureType texture_type);
|
[[nodiscard]] VkImageView DepthView(Shader::TextureType texture_type);
|
||||||
|
|
@ -291,6 +293,8 @@ private:
|
||||||
std::unique_ptr<StorageViews> storage_views;
|
std::unique_ptr<StorageViews> storage_views;
|
||||||
std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> depth_views;
|
std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> depth_views;
|
||||||
std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> stencil_views;
|
std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> stencil_views;
|
||||||
|
std::array<std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES>, NUMERIC_VIEW_TYPES>
|
||||||
|
sampled_component_views;
|
||||||
vk::ImageView color_view;
|
vk::ImageView color_view;
|
||||||
vk::Image null_image;
|
vk::Image null_image;
|
||||||
VkImage image_handle = VK_NULL_HANDLE;
|
VkImage image_handle = VK_NULL_HANDLE;
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,46 @@ static Shader::TexturePixelFormat ConvertTexturePixelFormat(const Tegra::Texture
|
||||||
entry.a_type, entry.srgb_conversion));
|
entry.a_type, entry.srgb_conversion));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
[[nodiscard]] bool UsesSwizzleSource(const Tegra::Texture::TICEntry& entry,
|
||||||
|
Tegra::Texture::SwizzleSource source) {
|
||||||
|
const std::array swizzles{entry.x_source.Value(), entry.y_source.Value(),
|
||||||
|
entry.z_source.Value(), entry.w_source.Value()};
|
||||||
|
return std::ranges::any_of(swizzles, [source](Tegra::Texture::SwizzleSource current) {
|
||||||
|
return current == source;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] std::optional<Shader::SamplerComponentType> DepthStencilComponentFromSwizzle(
|
||||||
|
const Tegra::Texture::TICEntry& entry, VideoCore::Surface::PixelFormat pixel_format) {
|
||||||
|
using Tegra::Texture::SwizzleSource;
|
||||||
|
const bool uses_r = UsesSwizzleSource(entry, SwizzleSource::R);
|
||||||
|
const bool uses_g = UsesSwizzleSource(entry, SwizzleSource::G);
|
||||||
|
|
||||||
|
switch (pixel_format) {
|
||||||
|
case VideoCore::Surface::PixelFormat::D24_UNORM_S8_UINT:
|
||||||
|
case VideoCore::Surface::PixelFormat::D32_FLOAT_S8_UINT:
|
||||||
|
if (uses_r != uses_g) {
|
||||||
|
return uses_r ? Shader::SamplerComponentType::Depth
|
||||||
|
: Shader::SamplerComponentType::Stencil;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case VideoCore::Surface::PixelFormat::S8_UINT_D24_UNORM:
|
||||||
|
if (uses_r != uses_g) {
|
||||||
|
return uses_r ? Shader::SamplerComponentType::Stencil
|
||||||
|
: Shader::SamplerComponentType::Depth;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
static Shader::SamplerComponentType ConvertSamplerComponentType(
|
static Shader::SamplerComponentType ConvertSamplerComponentType(
|
||||||
const Tegra::Texture::TICEntry& entry) {
|
const Tegra::Texture::TICEntry& entry) {
|
||||||
const auto pixel_format = PixelFormatFromTextureInfo(entry.format, entry.r_type, entry.g_type,
|
const auto pixel_format = PixelFormatFromTextureInfo(entry.format, entry.r_type, entry.g_type,
|
||||||
|
|
@ -83,6 +123,9 @@ static Shader::SamplerComponentType ConvertSamplerComponentType(
|
||||||
return Shader::SamplerComponentType::Stencil;
|
return Shader::SamplerComponentType::Stencil;
|
||||||
}
|
}
|
||||||
if (surface_type == VideoCore::Surface::SurfaceType::DepthStencil) {
|
if (surface_type == VideoCore::Surface::SurfaceType::DepthStencil) {
|
||||||
|
if (const auto inferred = DepthStencilComponentFromSwizzle(entry, pixel_format)) {
|
||||||
|
return *inferred;
|
||||||
|
}
|
||||||
return entry.depth_texture != 0 ? Shader::SamplerComponentType::Depth
|
return entry.depth_texture != 0 ? Shader::SamplerComponentType::Depth
|
||||||
: Shader::SamplerComponentType::Stencil;
|
: Shader::SamplerComponentType::Stencil;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,126 @@ bool IsPixelFormatSignedInteger(PixelFormat format) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct NumericVariantSet {
|
||||||
|
PixelFormat float_format = PixelFormat::Invalid;
|
||||||
|
PixelFormat uint_format = PixelFormat::Invalid;
|
||||||
|
PixelFormat sint_format = PixelFormat::Invalid;
|
||||||
|
|
||||||
|
[[nodiscard]] std::optional<PixelFormat> Select(PixelFormatNumeric numeric) const {
|
||||||
|
PixelFormat candidate = PixelFormat::Invalid;
|
||||||
|
switch (numeric) {
|
||||||
|
case PixelFormatNumeric::Float:
|
||||||
|
candidate = float_format;
|
||||||
|
break;
|
||||||
|
case PixelFormatNumeric::Uint:
|
||||||
|
candidate = uint_format;
|
||||||
|
break;
|
||||||
|
case PixelFormatNumeric::Sint:
|
||||||
|
candidate = sint_format;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (candidate == PixelFormat::Invalid) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr NumericVariantSet MakeVariant(PixelFormat float_format, PixelFormat uint_format,
|
||||||
|
PixelFormat sint_format) {
|
||||||
|
return NumericVariantSet{
|
||||||
|
.float_format = float_format,
|
||||||
|
.uint_format = uint_format,
|
||||||
|
.sint_format = sint_format,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<NumericVariantSet> LookupNumericVariantSet(PixelFormat format) {
|
||||||
|
switch (format) {
|
||||||
|
case PixelFormat::R8_UNORM:
|
||||||
|
case PixelFormat::R8_SNORM:
|
||||||
|
case PixelFormat::R8_UINT:
|
||||||
|
case PixelFormat::R8_SINT:
|
||||||
|
return MakeVariant(PixelFormat::R8_UNORM, PixelFormat::R8_UINT, PixelFormat::R8_SINT);
|
||||||
|
case PixelFormat::R16_FLOAT:
|
||||||
|
case PixelFormat::R16_UNORM:
|
||||||
|
case PixelFormat::R16_SNORM:
|
||||||
|
case PixelFormat::R16_UINT:
|
||||||
|
case PixelFormat::R16_SINT:
|
||||||
|
return MakeVariant(PixelFormat::R16_FLOAT, PixelFormat::R16_UINT, PixelFormat::R16_SINT);
|
||||||
|
case PixelFormat::R32_FLOAT:
|
||||||
|
case PixelFormat::R32_UINT:
|
||||||
|
case PixelFormat::R32_SINT:
|
||||||
|
return MakeVariant(PixelFormat::R32_FLOAT, PixelFormat::R32_UINT, PixelFormat::R32_SINT);
|
||||||
|
case PixelFormat::R8G8_UNORM:
|
||||||
|
case PixelFormat::R8G8_SNORM:
|
||||||
|
case PixelFormat::R8G8_UINT:
|
||||||
|
case PixelFormat::R8G8_SINT:
|
||||||
|
return MakeVariant(PixelFormat::R8G8_UNORM, PixelFormat::R8G8_UINT, PixelFormat::R8G8_SINT);
|
||||||
|
case PixelFormat::R16G16_FLOAT:
|
||||||
|
case PixelFormat::R16G16_UNORM:
|
||||||
|
case PixelFormat::R16G16_SNORM:
|
||||||
|
case PixelFormat::R16G16_UINT:
|
||||||
|
case PixelFormat::R16G16_SINT:
|
||||||
|
return MakeVariant(PixelFormat::R16G16_FLOAT, PixelFormat::R16G16_UINT,
|
||||||
|
PixelFormat::R16G16_SINT);
|
||||||
|
case PixelFormat::R32G32_FLOAT:
|
||||||
|
case PixelFormat::R32G32_UINT:
|
||||||
|
case PixelFormat::R32G32_SINT:
|
||||||
|
return MakeVariant(PixelFormat::R32G32_FLOAT, PixelFormat::R32G32_UINT,
|
||||||
|
PixelFormat::R32G32_SINT);
|
||||||
|
case PixelFormat::R16G16B16A16_FLOAT:
|
||||||
|
case PixelFormat::R16G16B16A16_UNORM:
|
||||||
|
case PixelFormat::R16G16B16A16_SNORM:
|
||||||
|
case PixelFormat::R16G16B16A16_UINT:
|
||||||
|
case PixelFormat::R16G16B16A16_SINT:
|
||||||
|
return MakeVariant(PixelFormat::R16G16B16A16_FLOAT, PixelFormat::R16G16B16A16_UINT,
|
||||||
|
PixelFormat::R16G16B16A16_SINT);
|
||||||
|
case PixelFormat::R32G32B32A32_FLOAT:
|
||||||
|
case PixelFormat::R32G32B32A32_UINT:
|
||||||
|
case PixelFormat::R32G32B32A32_SINT:
|
||||||
|
return MakeVariant(PixelFormat::R32G32B32A32_FLOAT, PixelFormat::R32G32B32A32_UINT,
|
||||||
|
PixelFormat::R32G32B32A32_SINT);
|
||||||
|
case PixelFormat::A8B8G8R8_UNORM:
|
||||||
|
case PixelFormat::A8B8G8R8_SNORM:
|
||||||
|
case PixelFormat::A8B8G8R8_SRGB:
|
||||||
|
case PixelFormat::A8B8G8R8_UINT:
|
||||||
|
case PixelFormat::A8B8G8R8_SINT:
|
||||||
|
return MakeVariant(PixelFormat::A8B8G8R8_UNORM, PixelFormat::A8B8G8R8_UINT,
|
||||||
|
PixelFormat::A8B8G8R8_SINT);
|
||||||
|
case PixelFormat::A2B10G10R10_UNORM:
|
||||||
|
case PixelFormat::A2B10G10R10_UINT:
|
||||||
|
return MakeVariant(PixelFormat::A2B10G10R10_UNORM, PixelFormat::A2B10G10R10_UINT,
|
||||||
|
PixelFormat::Invalid);
|
||||||
|
default:
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
PixelFormatNumeric GetPixelFormatNumericType(PixelFormat format) {
|
||||||
|
if (IsPixelFormatInteger(format)) {
|
||||||
|
return IsPixelFormatSignedInteger(format) ? PixelFormatNumeric::Sint
|
||||||
|
: PixelFormatNumeric::Uint;
|
||||||
|
}
|
||||||
|
return PixelFormatNumeric::Float;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<PixelFormat> FindPixelFormatVariant(PixelFormat format,
|
||||||
|
PixelFormatNumeric target_numeric) {
|
||||||
|
const auto variants = LookupNumericVariantSet(format);
|
||||||
|
if (!variants) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
if (const auto candidate = variants->Select(target_numeric)) {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
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:
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,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"
|
||||||
|
|
@ -202,6 +203,17 @@ bool IsPixelFormatSRGB(PixelFormat format);
|
||||||
bool IsPixelFormatInteger(PixelFormat format);
|
bool IsPixelFormatInteger(PixelFormat format);
|
||||||
bool IsPixelFormatSignedInteger(PixelFormat format);
|
bool IsPixelFormatSignedInteger(PixelFormat format);
|
||||||
size_t PixelComponentSizeBitsInteger(PixelFormat format);
|
size_t PixelComponentSizeBitsInteger(PixelFormat format);
|
||||||
|
|
||||||
|
enum class PixelFormatNumeric {
|
||||||
|
Float,
|
||||||
|
Uint,
|
||||||
|
Sint,
|
||||||
|
};
|
||||||
|
|
||||||
|
PixelFormatNumeric GetPixelFormatNumericType(PixelFormat format);
|
||||||
|
std::optional<PixelFormat> FindPixelFormatVariant(PixelFormat format,
|
||||||
|
PixelFormatNumeric target_numeric);
|
||||||
|
|
||||||
std::pair<u32, u32> GetASTCBlockSize(PixelFormat format);
|
std::pair<u32, u32> GetASTCBlockSize(PixelFormat format);
|
||||||
u64 TranscodedAstcSize(u64 base_size, PixelFormat format);
|
u64 TranscodedAstcSize(u64 base_size, PixelFormat format);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue