mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-09-09 13:36:35 +00:00
[vulkan] Re-wiring older ASTC decoding path + new helper function on wider ASTC textures
This commit is contained in:
@@ -44,7 +44,7 @@ layout(binding = BINDING_INPUT_BUFFER, std430) readonly restrict buffer InputBuf
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifdef VULKAN
|
#ifdef VULKAN
|
||||||
layout(binding = BINDING_OUTPUT_IMAGE, rgba32f) uniform writeonly restrict image2DArray dest_image;
|
layout(binding = BINDING_OUTPUT_IMAGE) uniform writeonly restrict image2DArray dest_image;
|
||||||
#else
|
#else
|
||||||
layout(binding = BINDING_OUTPUT_IMAGE, rgba8) uniform writeonly restrict image2DArray dest_image;
|
layout(binding = BINDING_OUTPUT_IMAGE, rgba8) uniform writeonly restrict image2DArray dest_image;
|
||||||
#endif
|
#endif
|
||||||
@@ -137,17 +137,6 @@ uvec4 ReplicateByteTo16(uvec4 value) {
|
|||||||
return value * 0x101;
|
return value * 0x101;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sRGB EOTF (decode: encoded value -> linear). Only used on the Vulkan path, where the
|
|
||||||
// destination image is a linear float format with no format-level sRGB tag of its own.
|
|
||||||
// Vectorized (single vec3 overload, no per-component scalar ternary) to match the style
|
|
||||||
// already used elsewhere in this file (see the HDR Mt piecewise selection) rather than the
|
|
||||||
// float/vec3 overload pair this replaces.
|
|
||||||
vec3 SRGBToLinear(vec3 c) {
|
|
||||||
const vec3 lo = c / 12.92;
|
|
||||||
const vec3 hi = pow(max((c + 0.055) / 1.055, vec3(0.0)), vec3(2.4));
|
|
||||||
return mix(hi, lo, lessThanEqual(c, vec3(0.04045)));
|
|
||||||
}
|
|
||||||
|
|
||||||
uint ReplicateBitTo7(uint value) {
|
uint ReplicateBitTo7(uint value) {
|
||||||
return value * 127;
|
return value * 127;
|
||||||
}
|
}
|
||||||
@@ -1405,9 +1394,6 @@ void DecompressBlock(ivec3 coord) {
|
|||||||
const vec4 Cf =
|
const vec4 Cf =
|
||||||
vec4((C0 * (uvec4(64) - weight_vec) + C1 * weight_vec + uvec4(32)) / 64);
|
vec4((C0 * (uvec4(64) - weight_vec) + C1 * weight_vec + uvec4(32)) / 64);
|
||||||
p = Cf / 65535.0f;
|
p = Cf / 65535.0f;
|
||||||
#ifdef VULKAN
|
|
||||||
p.yzw = mix(p.yzw, SRGBToLinear(p.yzw), bvec3((block_height_mask & 0x80000000u) != 0u));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef VULKAN
|
#ifdef VULKAN
|
||||||
@@ -1436,7 +1422,7 @@ void main() {
|
|||||||
uint offset = 0;
|
uint offset = 0;
|
||||||
offset += pos.z * layer_stride;
|
offset += pos.z * layer_stride;
|
||||||
offset += (block_y >> block_height) * block_size;
|
offset += (block_y >> block_height) * block_size;
|
||||||
offset += (block_y & (block_height_mask & 0x7FFFFFFFu)) << GOB_SIZE_SHIFT;
|
offset += (block_y & block_height_mask) << GOB_SIZE_SHIFT;
|
||||||
offset += (pos.x >> GOB_SIZE_X_SHIFT) << x_shift;
|
offset += (pos.x >> GOB_SIZE_X_SHIFT) << x_shift;
|
||||||
offset += swizzle;
|
offset += swizzle;
|
||||||
|
|
||||||
|
|||||||
@@ -564,7 +564,6 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
|
|||||||
VideoCore::Surface::DefaultBlockWidth(image.info.format),
|
VideoCore::Surface::DefaultBlockWidth(image.info.format),
|
||||||
VideoCore::Surface::DefaultBlockHeight(image.info.format),
|
VideoCore::Surface::DefaultBlockHeight(image.info.format),
|
||||||
};
|
};
|
||||||
const bool is_srgb = VideoCore::Surface::IsPixelFormatSRGB(image.info.format);
|
|
||||||
scheduler.RequestOutsideRenderPassOperationContext();
|
scheduler.RequestOutsideRenderPassOperationContext();
|
||||||
const VkPipeline vk_pipeline = *pipeline;
|
const VkPipeline vk_pipeline = *pipeline;
|
||||||
const VkImageAspectFlags aspect_mask = image.AspectMask();
|
const VkImageAspectFlags aspect_mask = image.AspectMask();
|
||||||
@@ -614,15 +613,14 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
|
|||||||
ASSERT(params.destination == (std::array<s32, 3>{0, 0, 0}));
|
ASSERT(params.destination == (std::array<s32, 3>{0, 0, 0}));
|
||||||
ASSERT(params.bytes_per_block_log2 == 4);
|
ASSERT(params.bytes_per_block_log2 == 4);
|
||||||
scheduler.Record([this, num_dispatches_x, num_dispatches_y, num_dispatches_z, block_dims,
|
scheduler.Record([this, num_dispatches_x, num_dispatches_y, num_dispatches_z, block_dims,
|
||||||
params, descriptor_data, is_srgb](vk::CommandBuffer cmdbuf) {
|
params, descriptor_data](vk::CommandBuffer cmdbuf) {
|
||||||
const AstcPushConstants uniforms{
|
const AstcPushConstants uniforms{
|
||||||
.blocks_dims = block_dims,
|
.blocks_dims = block_dims,
|
||||||
.layer_stride = params.layer_stride,
|
.layer_stride = params.layer_stride,
|
||||||
.block_size = params.block_size,
|
.block_size = params.block_size,
|
||||||
.x_shift = params.x_shift,
|
.x_shift = params.x_shift,
|
||||||
.block_height = params.block_height,
|
.block_height = params.block_height,
|
||||||
.block_height_mask =
|
.block_height_mask = params.block_height_mask,
|
||||||
params.block_height_mask | (is_srgb ? 0x8000'0000u : 0u),
|
|
||||||
};
|
};
|
||||||
const VkDescriptorSet set = descriptor_allocator.Commit();
|
const VkDescriptorSet set = descriptor_allocator.Commit();
|
||||||
device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data);
|
device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data);
|
||||||
|
|||||||
@@ -129,11 +129,6 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
|
|||||||
return usage;
|
return usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Whether an ASTC texture will be decoded via the GPU compute pass (ASTCDecoderPass /
|
|
||||||
// astc_decoder.comp) rather than the CPU ConvertImage path. Must stay the single source of
|
|
||||||
// truth for this decision: both the destination image's real format (below) and the
|
|
||||||
// AcceleratedUpload flag (Image::Image()) key off of it, and they must never disagree --
|
|
||||||
// the compute shader's declared storage image format has to match what was actually allocated.
|
|
||||||
[[nodiscard]] bool WillUseAcceleratedAstcDecode(const Device& device, const ImageInfo& info) {
|
[[nodiscard]] bool WillUseAcceleratedAstcDecode(const Device& device, const ImageInfo& info) {
|
||||||
if (!IsPixelFormatASTC(info.format) || device.IsOptimalAstcSupported()) {
|
if (!IsPixelFormatASTC(info.format) || device.IsOptimalAstcSupported()) {
|
||||||
return false;
|
return false;
|
||||||
@@ -146,13 +141,16 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
|
|||||||
info.size.depth == 1;
|
info.size.depth == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool WillUseWidenedAstcFormat(const Device& device, const ImageInfo& info) {
|
||||||
|
return WillUseAcceleratedAstcDecode(device, info) &&
|
||||||
|
!VideoCore::Surface::IsPixelFormatSRGB(info.format);
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] VkImageCreateInfo MakeImageCreateInfo(const Device& device, const ImageInfo& info,
|
[[nodiscard]] VkImageCreateInfo MakeImageCreateInfo(const Device& device, const ImageInfo& info,
|
||||||
std::optional<VkFormat> format_override = {}) {
|
std::optional<VkFormat> format_override = {}) {
|
||||||
auto format_info =
|
auto format_info =
|
||||||
MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, false, info.format);
|
MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, false, info.format);
|
||||||
if (format_override) {
|
if (format_override) {
|
||||||
// Accelerated ASTC HDR decode target: real (unclamped) values need a linear float
|
|
||||||
// format, not whatever the guest ASTC pixel format would normally map to.
|
|
||||||
format_info.format = *format_override;
|
format_info.format = *format_override;
|
||||||
format_info.attachable = false;
|
format_info.attachable = false;
|
||||||
format_info.storage = true;
|
format_info.storage = true;
|
||||||
@@ -1586,10 +1584,10 @@ Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu
|
|||||||
: VideoCommon::ImageBase(info_, gpu_addr_, cpu_addr_), scheduler{&runtime_.scheduler},
|
: VideoCommon::ImageBase(info_, gpu_addr_, cpu_addr_), scheduler{&runtime_.scheduler},
|
||||||
runtime{&runtime_},
|
runtime{&runtime_},
|
||||||
original_image(MakeImage(runtime_.device, runtime_.memory_allocator, info,
|
original_image(MakeImage(runtime_.device, runtime_.memory_allocator, info,
|
||||||
WillUseAcceleratedAstcDecode(runtime_.device, info)
|
WillUseWidenedAstcFormat(runtime_.device, info)
|
||||||
? std::span<const VkFormat>{}
|
? std::span<const VkFormat>{}
|
||||||
: runtime->ViewFormats(info.format),
|
: runtime->ViewFormats(info.format),
|
||||||
WillUseAcceleratedAstcDecode(runtime_.device, info)
|
WillUseWidenedAstcFormat(runtime_.device, info)
|
||||||
? std::make_optional(VK_FORMAT_R32G32B32A32_SFLOAT)
|
? std::make_optional(VK_FORMAT_R32G32B32A32_SFLOAT)
|
||||||
: std::nullopt)),
|
: std::nullopt)),
|
||||||
aspect_mask(ImageAspectMask(info.format)) {
|
aspect_mask(ImageAspectMask(info.format)) {
|
||||||
@@ -1622,7 +1620,7 @@ Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu
|
|||||||
Settings::values.astc_recompression.GetValue() ==
|
Settings::values.astc_recompression.GetValue() ==
|
||||||
Settings::AstcRecompression::Uncompressed) {
|
Settings::AstcRecompression::Uncompressed) {
|
||||||
const auto& device = runtime->device.GetLogical();
|
const auto& device = runtime->device.GetLogical();
|
||||||
const VkFormat storage_format = WillUseAcceleratedAstcDecode(runtime->device, info)
|
const VkFormat storage_format = WillUseWidenedAstcFormat(runtime->device, info)
|
||||||
? VK_FORMAT_R32G32B32A32_SFLOAT
|
? VK_FORMAT_R32G32B32A32_SFLOAT
|
||||||
: VK_FORMAT_A8B8G8R8_UNORM_PACK32;
|
: VK_FORMAT_A8B8G8R8_UNORM_PACK32;
|
||||||
for (s32 level = 0; level < info.resources.levels; ++level) {
|
for (s32 level = 0; level < info.resources.levels; ++level) {
|
||||||
@@ -1979,7 +1977,9 @@ VkImageView Image::StorageImageView(s32 level) noexcept {
|
|||||||
auto format_info =
|
auto format_info =
|
||||||
MaxwellToVK::SurfaceFormat(runtime->device, FormatType::Optimal, true, info.format);
|
MaxwellToVK::SurfaceFormat(runtime->device, FormatType::Optimal, true, info.format);
|
||||||
if (WillUseAcceleratedAstcDecode(runtime->device, info)) {
|
if (WillUseAcceleratedAstcDecode(runtime->device, info)) {
|
||||||
format_info.format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
format_info.format = WillUseWidenedAstcFormat(runtime->device, info)
|
||||||
|
? VK_FORMAT_R32G32B32A32_SFLOAT
|
||||||
|
: VK_FORMAT_A8B8G8R8_UNORM_PACK32;
|
||||||
}
|
}
|
||||||
view = MakeStorageView(runtime->device.GetLogical(), level, *(this->*current_image),
|
view = MakeStorageView(runtime->device.GetLogical(), level, *(this->*current_image),
|
||||||
format_info.format);
|
format_info.format);
|
||||||
@@ -2147,9 +2147,9 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
|
|||||||
SanitizeDepthStencilSwizzle(swizzle, device->SupportsDepthStencilSwizzleOne());
|
SanitizeDepthStencilSwizzle(swizzle, device->SupportsDepthStencilSwizzleOne());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uses_accelerated_astc_decode = WillUseAcceleratedAstcDecode(*device, image.info);
|
uses_widened_astc_format = WillUseWidenedAstcFormat(*device, image.info);
|
||||||
auto format_info = MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, true, format);
|
auto format_info = MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, true, format);
|
||||||
if (uses_accelerated_astc_decode) {
|
if (uses_widened_astc_format) {
|
||||||
format_info.format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
format_info.format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||||
}
|
}
|
||||||
const VkImageUsageFlags requested_view_usage = ImageUsageFlags(format_info, format);
|
const VkImageUsageFlags requested_view_usage = ImageUsageFlags(format_info, format);
|
||||||
@@ -2287,7 +2287,7 @@ VkImageView ImageView::StorageView(Shader::TextureType texture_type,
|
|||||||
if (image_format == Shader::ImageFormat::Typeless) {
|
if (image_format == Shader::ImageFormat::Typeless) {
|
||||||
if (!typeless_storage_view) {
|
if (!typeless_storage_view) {
|
||||||
auto info = MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, true, format);
|
auto info = MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, true, format);
|
||||||
if (uses_accelerated_astc_decode) {
|
if (uses_widened_astc_format) {
|
||||||
info.format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
info.format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||||
}
|
}
|
||||||
typeless_storage_view = MakeView(info.format, VK_IMAGE_ASPECT_COLOR_BIT);
|
typeless_storage_view = MakeView(info.format, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||||
|
|||||||
@@ -387,7 +387,7 @@ private:
|
|||||||
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
|
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
u32 buffer_size = 0;
|
u32 buffer_size = 0;
|
||||||
|
|
||||||
bool uses_accelerated_astc_decode = false;
|
bool uses_widened_astc_format = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ImageAlloc : public VideoCommon::ImageAllocBase {};
|
class ImageAlloc : public VideoCommon::ImageAllocBase {};
|
||||||
|
|||||||
Reference in New Issue
Block a user