From b76d04e47db0c5394efc6745b9dfdc49f6860987 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Sat, 1 Aug 2026 02:41:09 -0400 Subject: [PATCH] ASTC adjustments --- src/video_core/host_shaders/astc_decoder.comp | 22 +++++++++---------- .../renderer_vulkan/vk_texture_cache.cpp | 15 ++++++++++++- .../vulkan_common/vulkan_device.cpp | 9 ++++++-- src/video_core/vulkan_common/vulkan_device.h | 8 +++++++ 4 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/video_core/host_shaders/astc_decoder.comp b/src/video_core/host_shaders/astc_decoder.comp index 1694f1bc35..86a9c0a4d2 100644 --- a/src/video_core/host_shaders/astc_decoder.comp +++ b/src/video_core/host_shaders/astc_decoder.comp @@ -77,14 +77,8 @@ uvec4 local_buff; uvec4 color_endpoint_data; int color_bitsread = 0; -// Global "vector" to be pushed into when decoding -// At most will require BLOCK_WIDTH x BLOCK_HEIGHT in single plane mode -// At most will require BLOCK_WIDTH x BLOCK_HEIGHT x 2 in dual plane mode -// So the maximum would be 144 (12 x 12) elements, x 2 for two planes -#define DIVCEIL(number, divisor) (number + divisor - 1) / divisor -#define ARRAY_NUM_ELEMENTS 144 -#define VECTOR_ARRAY_SIZE DIVCEIL(ARRAY_NUM_ELEMENTS * 2, 4) -uint result_vector[ARRAY_NUM_ELEMENTS * 2]; +#define MAX_WEIGHT_VALUES 64 +uint result_vector[MAX_WEIGHT_VALUES]; int result_index = 0; uint result_vector_max_index; @@ -492,7 +486,7 @@ void DecodeColorValues(uvec4 modes, uint num_partitions, uint color_data_bits, o A = ReplicateBitTo9((bitval & 1)); switch (encoding) { case JUST_BITS: - color_values[++out_index] = FastReplicateTo8(bitval, bitlen); + color_values[out_index++] = FastReplicateTo8(bitval, bitlen); break; case TRIT: { D = QuintTritValue(val); @@ -571,7 +565,7 @@ void DecodeColorValues(uvec4 modes, uint num_partitions, uint color_data_bits, o uint T = (D * C) + B; T ^= A; T = (A & 0x80) | (T >> 2); - color_values[++out_index] = T; + color_values[out_index++] = T; } } } @@ -753,12 +747,12 @@ void ComputeEndpoints(out uvec4 ep1, out uvec4 ep2, uint color_endpoint_mode, ui #define READ_UINT_VALUES(N) \ uvec4 V[2]; \ for (uint i = 0; i < N; i++) { \ - V[i / 4][i % 4] = color_values[++colvals_index]; \ + V[i / 4][i % 4] = color_values[colvals_index++]; \ } #define READ_INT_VALUES(N) \ ivec4 V[2]; \ for (uint i = 0; i < N; i++) { \ - V[i / 4][i % 4] = int(color_values[++colvals_index]); \ + V[i / 4][i % 4] = int(color_values[colvals_index++]); \ } switch (color_endpoint_mode) { @@ -1225,6 +1219,10 @@ void DecompressBlock(ivec3 coord) { FillError(coord); return; } + if (GetNumWeightValues(size_params, dual_plane) > MAX_WEIGHT_VALUES) { + FillError(coord); + return; + } uint partition_index = 1; uvec4 color_endpoint_mode = uvec4(0); uint ced_pointer = 0; diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index f9acf66889..eac67335f0 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -270,6 +270,10 @@ constexpr VkBorderColor ConvertBorderColor(const std::array& color) { } } +[[nodiscard]] bool IsLdrAstcFormat(VkFormat format) { + return format >= VK_FORMAT_ASTC_4x4_UNORM_BLOCK && format <= VK_FORMAT_ASTC_12x12_SRGB_BLOCK; +} + [[nodiscard]] VkImageAspectFlags ImageViewAspectMask(const VideoCommon::ImageViewInfo& info) { if (info.IsRenderTarget()) { return ImageAspectMask(info.format); @@ -2483,9 +2487,18 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI .pNext = nullptr, .usage = clamped_view_usage, }; + const VkImageViewASTCDecodeModeEXT astc_decode_mode{ + .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT, + .pNext = &image_view_usage, + .decodeMode = VK_FORMAT_R8G8B8A8_UNORM, + }; + const void* view_next = &image_view_usage; + if (device->IsExtAstcDecodeModeSupported() && IsLdrAstcFormat(format_info.format)) { + view_next = &astc_decode_mode; + } const VkImageViewCreateInfo create_info{ .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - .pNext = &image_view_usage, + .pNext = view_next, .flags = 0, .image = image.Handle(), .viewType = VkImageViewType{}, diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index b7c735cdc0..5b0b247375 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -953,8 +953,7 @@ bool Device::ComputeIsOptimalAstcSupported() const { VK_FORMAT_ASTC_12x10_UNORM_BLOCK, VK_FORMAT_ASTC_12x10_SRGB_BLOCK, VK_FORMAT_ASTC_12x12_UNORM_BLOCK, VK_FORMAT_ASTC_12x12_SRGB_BLOCK, }; - if (!features.features.textureCompressionASTC_LDR || - !features.texture_compression_astc_hdr.textureCompressionASTC_HDR) { + if (!features.features.textureCompressionASTC_LDR) { return false; } const auto format_feature_usage{VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | @@ -1505,6 +1504,12 @@ void Device::RemoveUnsuitableExtensions() { features.subgroup_size_control, VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME); + // VK_EXT_texture_compression_astc_hdr + extensions.texture_compression_astc_hdr = false; + RemoveExtensionFeatureIfUnsuitable(extensions.texture_compression_astc_hdr, + features.texture_compression_astc_hdr, + VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_EXTENSION_NAME); + // VK_EXT_transform_feedback extensions.transform_feedback = features.transform_feedback.transformFeedback && diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 0d354615ff..89238a4015 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -85,6 +85,7 @@ VK_DEFINE_HANDLE(VmaAllocator) // Define miscellaneous extensions which may be used by the implementation here. #define FOR_EACH_VK_EXTENSION(EXTENSION) \ + EXTENSION(EXT, ASTC_DECODE_MODE, astc_decode_mode) \ EXTENSION(EXT, CONDITIONAL_RENDERING, conditional_rendering) \ EXTENSION(EXT, CONSERVATIVE_RASTERIZATION, conservative_rasterization) \ EXTENSION(EXT, DEPTH_RANGE_UNRESTRICTED, depth_range_unrestricted) \ @@ -911,10 +912,17 @@ FN_MAX_LIMIT_LIST features.shader_atomic_int64.shaderSharedInt64Atomics; } + /// Returns true if the device supports VK_EXT_conditional_rendering. bool IsExtConditionalRendering() const { return extensions.conditional_rendering; } + /// Returns true if the device supports VK_EXT_astc_decode_mode. + bool IsExtAstcDecodeModeSupported() const { + return extensions.astc_decode_mode; + } + + /// Returns true if the device supports VK_EXT_external_memory_host. bool IsExtExternalMemoryHostSupported() const { return extensions.external_memory_host; }