mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-05-15 04:06:57 +02:00
fuckit, prepare for accelerate gpu
This commit is contained in:
parent
3a7392d4be
commit
ea6344b031
20 changed files with 65 additions and 1641 deletions
|
|
@ -16,7 +16,6 @@ enum class IntSetting(override val key: String) : AbstractIntSetting {
|
||||||
RENDERER_BACKEND("backend"),
|
RENDERER_BACKEND("backend"),
|
||||||
RENDERER_VRAM_USAGE_MODE("vram_usage_mode"),
|
RENDERER_VRAM_USAGE_MODE("vram_usage_mode"),
|
||||||
RENDERER_NVDEC_EMULATION("nvdec_emulation"),
|
RENDERER_NVDEC_EMULATION("nvdec_emulation"),
|
||||||
RENDERER_ASTC_DECODE_METHOD("accelerate_astc"),
|
|
||||||
RENDERER_ASTC_RECOMPRESSION("astc_recompression"),
|
RENDERER_ASTC_RECOMPRESSION("astc_recompression"),
|
||||||
RENDERER_ACCURACY("gpu_accuracy"),
|
RENDERER_ACCURACY("gpu_accuracy"),
|
||||||
RENDERER_RESOLUTION("resolution_setup"),
|
RENDERER_RESOLUTION("resolution_setup"),
|
||||||
|
|
|
||||||
|
|
@ -325,15 +325,6 @@ abstract class SettingsItem(
|
||||||
valuesId = R.array.rendererNvdecValues
|
valuesId = R.array.rendererNvdecValues
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
put(
|
|
||||||
SingleChoiceSetting(
|
|
||||||
IntSetting.RENDERER_ASTC_DECODE_METHOD,
|
|
||||||
titleId = R.string.accelerate_astc,
|
|
||||||
descriptionId = R.string.accelerate_astc_description,
|
|
||||||
choicesId = R.array.astcDecodingMethodNames,
|
|
||||||
valuesId = R.array.astcDecodingMethodValues
|
|
||||||
)
|
|
||||||
)
|
|
||||||
put(
|
put(
|
||||||
SingleChoiceSetting(
|
SingleChoiceSetting(
|
||||||
IntSetting.RENDERER_ASTC_RECOMPRESSION,
|
IntSetting.RENDERER_ASTC_RECOMPRESSION,
|
||||||
|
|
|
||||||
|
|
@ -268,7 +268,6 @@ class SettingsFragmentPresenter(
|
||||||
add(IntSetting.DMA_ACCURACY.key)
|
add(IntSetting.DMA_ACCURACY.key)
|
||||||
add(IntSetting.MAX_ANISOTROPY.key)
|
add(IntSetting.MAX_ANISOTROPY.key)
|
||||||
add(IntSetting.RENDERER_VRAM_USAGE_MODE.key)
|
add(IntSetting.RENDERER_VRAM_USAGE_MODE.key)
|
||||||
add(IntSetting.RENDERER_ASTC_DECODE_METHOD.key)
|
|
||||||
add(IntSetting.RENDERER_ASTC_RECOMPRESSION.key)
|
add(IntSetting.RENDERER_ASTC_RECOMPRESSION.key)
|
||||||
|
|
||||||
add(BooleanSetting.SYNC_MEMORY_OPERATIONS.key)
|
add(BooleanSetting.SYNC_MEMORY_OPERATIONS.key)
|
||||||
|
|
|
||||||
|
|
@ -123,25 +123,13 @@
|
||||||
<item>1</item> <!-- Aggressive -->
|
<item>1</item> <!-- Aggressive -->
|
||||||
</integer-array>
|
</integer-array>
|
||||||
|
|
||||||
<!-- ASTC Decoding Method Choices -->
|
|
||||||
<string-array name="astcDecodingMethodNames">
|
|
||||||
<item>@string/accelerate_astc_cpu</item>
|
|
||||||
<item>@string/accelerate_astc_gpu</item>
|
|
||||||
<item>@string/accelerate_astc_async</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<!-- ASTC Decoding Method Values -->
|
|
||||||
<integer-array name="astcDecodingMethodValues">
|
|
||||||
<item>0</item> <!-- CPU -->
|
|
||||||
<item>1</item> <!-- GPU -->
|
|
||||||
<item>2</item> <!-- CPU Asynchronously -->
|
|
||||||
</integer-array>
|
|
||||||
|
|
||||||
<!-- ASTC Recompression Method Choices -->
|
<!-- ASTC Recompression Method Choices -->
|
||||||
<string-array name="astcRecompressionMethodNames">
|
<string-array name="astcRecompressionMethodNames">
|
||||||
<item>@string/astc_recompression_uncompressed</item>
|
<item>@string/astc_recompression_uncompressed</item>
|
||||||
<item>@string/astc_recompression_bc1</item>
|
<item>@string/astc_recompression_bc1</item>
|
||||||
<item>@string/astc_recompression_bc3</item>
|
<item>@string/astc_recompression_bc3</item>
|
||||||
|
<item>@string/astc_recompression_bc7</item>
|
||||||
|
<item>@string/astc_recompression_etc2</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- ASTC Recompression Method Values -->
|
<!-- ASTC Recompression Method Values -->
|
||||||
|
|
@ -149,6 +137,8 @@
|
||||||
<item>0</item> <!-- Uncompressed -->
|
<item>0</item> <!-- Uncompressed -->
|
||||||
<item>1</item> <!-- BC1 -->
|
<item>1</item> <!-- BC1 -->
|
||||||
<item>2</item> <!-- BC3 -->
|
<item>2</item> <!-- BC3 -->
|
||||||
|
<item>3</item> <!-- BC7 -->
|
||||||
|
<item>4</item> <!-- ETC2 -->
|
||||||
</integer-array>
|
</integer-array>
|
||||||
|
|
||||||
<!-- NVDEC Emulation Choices -->
|
<!-- NVDEC Emulation Choices -->
|
||||||
|
|
|
||||||
|
|
@ -1033,6 +1033,8 @@
|
||||||
<string name="astc_recompression_uncompressed">Uncompressed</string>
|
<string name="astc_recompression_uncompressed">Uncompressed</string>
|
||||||
<string name="astc_recompression_bc1" translatable="false">BC1</string>
|
<string name="astc_recompression_bc1" translatable="false">BC1</string>
|
||||||
<string name="astc_recompression_bc3" translatable="false">BC3</string>
|
<string name="astc_recompression_bc3" translatable="false">BC3</string>
|
||||||
|
<string name="astc_recompression_bc7" translatable="false">BC7</string>
|
||||||
|
<string name="astc_recompression_etc2" translatable="false">ETC2</string>
|
||||||
|
|
||||||
<!-- ASTC Recompression Method Choices -->
|
<!-- ASTC Recompression Method Choices -->
|
||||||
<string name="vram_usage_conservative">Conservative</string>
|
<string name="vram_usage_conservative">Conservative</string>
|
||||||
|
|
|
||||||
|
|
@ -430,15 +430,6 @@ struct Values {
|
||||||
#endif
|
#endif
|
||||||
"max_anisotropy",
|
"max_anisotropy",
|
||||||
Category::RendererAdvanced};
|
Category::RendererAdvanced};
|
||||||
SwitchableSetting<AstcDecodeMode, true> accelerate_astc{linkage,
|
|
||||||
#ifdef ANDROID
|
|
||||||
AstcDecodeMode::Cpu,
|
|
||||||
#else
|
|
||||||
AstcDecodeMode::Gpu,
|
|
||||||
#endif
|
|
||||||
"accelerate_astc",
|
|
||||||
Category::RendererAdvanced};
|
|
||||||
|
|
||||||
SwitchableSetting<AstcRecompression, true> astc_recompression{linkage,
|
SwitchableSetting<AstcRecompression, true> astc_recompression{linkage,
|
||||||
AstcRecompression::Uncompressed,
|
AstcRecompression::Uncompressed,
|
||||||
"astc_recompression",
|
"astc_recompression",
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ ENUM(TimeZone, Auto, Default, Cet, Cst6Cdt, Cuba, Eet, Egypt, Eire, Est, Est5Edt
|
||||||
Roc, Rok, Singapore, Turkey, Uct, Universal, Utc, WSu, Wet, Zulu);
|
Roc, Rok, Singapore, Turkey, Uct, Universal, Utc, WSu, Wet, Zulu);
|
||||||
ENUM(AnisotropyMode, Automatic, Default, X2, X4, X8, X16, X32, X64, None);
|
ENUM(AnisotropyMode, Automatic, Default, X2, X4, X8, X16, X32, X64, None);
|
||||||
ENUM(AstcDecodeMode, Cpu, Gpu, CpuAsynchronous);
|
ENUM(AstcDecodeMode, Cpu, Gpu, CpuAsynchronous);
|
||||||
ENUM(AstcRecompression, Uncompressed, Bc1, Bc3);
|
ENUM(AstcRecompression, Uncompressed, Bc1, Bc3, Bc7, Etc2);
|
||||||
ENUM(VSyncMode, Immediate, Mailbox, Fifo, FifoRelaxed);
|
ENUM(VSyncMode, Immediate, Mailbox, Fifo, FifoRelaxed);
|
||||||
ENUM(VramUsageMode, Conservative, Aggressive);
|
ENUM(VramUsageMode, Conservative, Aggressive);
|
||||||
ENUM(RendererBackend, OpenGL_GLSL, Vulkan, Null, OpenGL_GLASM, OpenGL_SPIRV);
|
ENUM(RendererBackend, OpenGL_GLSL, Vulkan, Null, OpenGL_GLASM, OpenGL_SPIRV);
|
||||||
|
|
|
||||||
|
|
@ -209,14 +209,6 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent)
|
||||||
tr("Specifies how videos should be decoded.\nIt can either use the CPU or the GPU for "
|
tr("Specifies how videos should be decoded.\nIt can either use the CPU or the GPU for "
|
||||||
"decoding, or perform no decoding at all (black screen on videos).\n"
|
"decoding, or perform no decoding at all (black screen on videos).\n"
|
||||||
"In most cases, GPU decoding provides the best performance."));
|
"In most cases, GPU decoding provides the best performance."));
|
||||||
INSERT(Settings,
|
|
||||||
accelerate_astc,
|
|
||||||
tr("ASTC Decoding Method:"),
|
|
||||||
tr("This option controls how ASTC textures should be decoded.\n"
|
|
||||||
"CPU: Use the CPU for decoding.\n"
|
|
||||||
"GPU: Use the GPU's compute shaders to decode ASTC textures (recommended).\n"
|
|
||||||
"CPU Asynchronously: Use the CPU to decode ASTC textures on demand. Eliminates"
|
|
||||||
"ASTC decoding\nstuttering but may present artifacts."));
|
|
||||||
INSERT(
|
INSERT(
|
||||||
Settings,
|
Settings,
|
||||||
astc_recompression,
|
astc_recompression,
|
||||||
|
|
|
||||||
|
|
@ -279,8 +279,6 @@ add_library(video_core STATIC
|
||||||
texture_cache/types.h
|
texture_cache/types.h
|
||||||
texture_cache/util.cpp
|
texture_cache/util.cpp
|
||||||
texture_cache/util.h
|
texture_cache/util.h
|
||||||
textures/astc.h
|
|
||||||
textures/astc.cpp
|
|
||||||
textures/bcn.cpp
|
textures/bcn.cpp
|
||||||
textures/bcn.h
|
textures/bcn.h
|
||||||
textures/decoders.cpp
|
textures/decoders.cpp
|
||||||
|
|
|
||||||
|
|
@ -1075,16 +1075,14 @@ void DecompressBlock(ivec3 coord) {
|
||||||
uint colvals_index = 0;
|
uint colvals_index = 0;
|
||||||
DecodeColorValues(color_endpoint_mode, num_partitions, color_data_bits, color_values);
|
DecodeColorValues(color_endpoint_mode, num_partitions, color_data_bits, color_values);
|
||||||
for (uint i = 0; i < num_partitions; i++) {
|
for (uint i = 0; i < num_partitions; i++) {
|
||||||
ComputeEndpoints(endpoints0[i], endpoints1[i], color_endpoint_mode[i], color_values,
|
ComputeEndpoints(endpoints0[i], endpoints1[i], color_endpoint_mode[i], color_values, colvals_index);
|
||||||
colvals_index);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
color_endpoint_data = local_buff;
|
color_endpoint_data = local_buff;
|
||||||
color_endpoint_data = bitfieldReverse(color_endpoint_data).wzyx;
|
color_endpoint_data = bitfieldReverse(color_endpoint_data).wzyx;
|
||||||
const uint clear_byte_start = (weight_bits >> 3) + 1;
|
const uint clear_byte_start = (weight_bits >> 3) + 1;
|
||||||
|
|
||||||
const uint byte_insert = ExtractBits(color_endpoint_data, int(clear_byte_start - 1) * 8, 8) &
|
const uint byte_insert = ExtractBits(color_endpoint_data, int(clear_byte_start - 1) * 8, 8) & uint(((1 << (weight_bits % 8)) - 1));
|
||||||
uint(((1 << (weight_bits % 8)) - 1));
|
|
||||||
const uint vec_index = (clear_byte_start - 1) >> 2;
|
const uint vec_index = (clear_byte_start - 1) >> 2;
|
||||||
color_endpoint_data[vec_index] = bitfieldInsert(color_endpoint_data[vec_index], byte_insert,
|
color_endpoint_data[vec_index] = bitfieldInsert(color_endpoint_data[vec_index], byte_insert,
|
||||||
int((clear_byte_start - 1) % 4) * 8, 8);
|
int((clear_byte_start - 1) % 4) * 8, 8);
|
||||||
|
|
@ -1115,8 +1113,7 @@ void DecompressBlock(ivec3 coord) {
|
||||||
const uvec4 C0 = ReplicateByteTo16(endpoints0[local_partition]);
|
const uvec4 C0 = ReplicateByteTo16(endpoints0[local_partition]);
|
||||||
const uvec4 C1 = ReplicateByteTo16(endpoints1[local_partition]);
|
const uvec4 C1 = ReplicateByteTo16(endpoints1[local_partition]);
|
||||||
const uvec4 weight_vec = GetUnquantizedWeightVector(j, i, size_params, plane_index, dual_plane);
|
const uvec4 weight_vec = GetUnquantizedWeightVector(j, i, size_params, plane_index, dual_plane);
|
||||||
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);
|
|
||||||
const vec4 p = (Cf / 65535.0f);
|
const vec4 p = (Cf / 65535.0f);
|
||||||
imageStore(dest_image, coord + ivec3(i, j, 0), p.gbar);
|
imageStore(dest_image, coord + ivec3(i, j, 0), p.gbar);
|
||||||
}
|
}
|
||||||
|
|
@ -1124,11 +1121,11 @@ void DecompressBlock(ivec3 coord) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint SwizzleOffset(uvec2 pos) {
|
uint SwizzleOffset(uvec2 pos) {
|
||||||
return ((pos.x & 32u) << 3u) |
|
return ((pos.x & 32u) << 3u)
|
||||||
((pos.y & 6u) << 5u) |
|
| ((pos.y & 6u) << 5u)
|
||||||
((pos.x & 16u) << 1u) |
|
| ((pos.x & 16u) << 1u)
|
||||||
((pos.y & 1u) << 4u) |
|
| ((pos.y & 1u) << 4u)
|
||||||
(pos.x & 15u);
|
| (pos.x & 15u);
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||||
|
|
@ -235,9 +235,7 @@ void ApplySwizzle(GLuint handle, PixelFormat format, std::array<SwizzleSource, 4
|
||||||
[[nodiscard]] bool CanBeAccelerated(const TextureCacheRuntime& runtime,
|
[[nodiscard]] bool CanBeAccelerated(const TextureCacheRuntime& runtime,
|
||||||
const VideoCommon::ImageInfo& info) {
|
const VideoCommon::ImageInfo& info) {
|
||||||
if (IsPixelFormatASTC(info.format) && info.size.depth == 1 && !runtime.HasNativeASTC()) {
|
if (IsPixelFormatASTC(info.format) && info.size.depth == 1 && !runtime.HasNativeASTC()) {
|
||||||
return Settings::values.accelerate_astc.GetValue() == Settings::AstcDecodeMode::Gpu &&
|
return true;
|
||||||
Settings::values.astc_recompression.GetValue() ==
|
|
||||||
Settings::AstcRecompression::Uncompressed;
|
|
||||||
}
|
}
|
||||||
// Disable other accelerated uploads for now as they don't implement swizzled uploads
|
// Disable other accelerated uploads for now as they don't implement swizzled uploads
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -266,15 +264,6 @@ void ApplySwizzle(GLuint handle, PixelFormat format, std::array<SwizzleSource, 4
|
||||||
return format_info.compatibility_class == store_class;
|
return format_info.compatibility_class == store_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool CanBeDecodedAsync(const TextureCacheRuntime& runtime,
|
|
||||||
const VideoCommon::ImageInfo& info) {
|
|
||||||
if (IsPixelFormatASTC(info.format) && !runtime.HasNativeASTC()) {
|
|
||||||
return Settings::values.accelerate_astc.GetValue() ==
|
|
||||||
Settings::AstcDecodeMode::CpuAsynchronous;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] CopyOrigin MakeCopyOrigin(VideoCommon::Offset3D offset,
|
[[nodiscard]] CopyOrigin MakeCopyOrigin(VideoCommon::Offset3D offset,
|
||||||
VideoCommon::SubresourceLayers subresource, GLenum target) {
|
VideoCommon::SubresourceLayers subresource, GLenum target) {
|
||||||
switch (target) {
|
switch (target) {
|
||||||
|
|
@ -443,18 +432,15 @@ OGLTexture MakeImage(const VideoCommon::ImageInfo& info, GLenum gl_internal_form
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool IsAstcRecompressionEnabled() {
|
[[nodiscard]] bool IsAstcRecompressionEnabled() {
|
||||||
return Settings::values.astc_recompression.GetValue() !=
|
return Settings::values.astc_recompression.GetValue() != Settings::AstcRecompression::Uncompressed;
|
||||||
Settings::AstcRecompression::Uncompressed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] GLenum SelectAstcFormat(PixelFormat format, bool is_srgb) {
|
[[nodiscard]] GLenum SelectAstcFormat(PixelFormat format, bool is_srgb) {
|
||||||
switch (Settings::values.astc_recompression.GetValue()) {
|
switch (Settings::values.astc_recompression.GetValue()) {
|
||||||
case Settings::AstcRecompression::Bc1:
|
case Settings::AstcRecompression::Bc1:
|
||||||
return is_srgb ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT : GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
return is_srgb ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT : GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||||
break;
|
|
||||||
case Settings::AstcRecompression::Bc3:
|
case Settings::AstcRecompression::Bc3:
|
||||||
return is_srgb ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT : GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
return is_srgb ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT : GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
return is_srgb ? GL_SRGB8_ALPHA8 : GL_RGBA8;
|
return is_srgb ? GL_SRGB8_ALPHA8 : GL_RGBA8;
|
||||||
}
|
}
|
||||||
|
|
@ -693,12 +679,9 @@ bool TextureCacheRuntime::HasNativeASTC() const noexcept {
|
||||||
return device.HasASTC();
|
return device.HasASTC();
|
||||||
}
|
}
|
||||||
|
|
||||||
Image::Image(TextureCacheRuntime& runtime_, const VideoCommon::ImageInfo& info_, GPUVAddr gpu_addr_,
|
Image::Image(TextureCacheRuntime& runtime_, const VideoCommon::ImageInfo& info_, GPUVAddr gpu_addr_, VAddr cpu_addr_)
|
||||||
VAddr cpu_addr_)
|
|
||||||
: VideoCommon::ImageBase(info_, gpu_addr_, cpu_addr_), runtime{&runtime_} {
|
: VideoCommon::ImageBase(info_, gpu_addr_, cpu_addr_), runtime{&runtime_} {
|
||||||
if (CanBeDecodedAsync(*runtime, info)) {
|
if (CanBeAccelerated(*runtime, info)) {
|
||||||
flags |= ImageFlagBits::AsynchronousDecode;
|
|
||||||
} else if (CanBeAccelerated(*runtime, info)) {
|
|
||||||
flags |= ImageFlagBits::AcceleratedUpload;
|
flags |= ImageFlagBits::AcceleratedUpload;
|
||||||
}
|
}
|
||||||
if (IsConverted(runtime->device, info.format, info.type)) {
|
if (IsConverted(runtime->device, info.format, info.type)) {
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
|
@ -25,14 +28,11 @@
|
||||||
#include "video_core/texture_cache/accelerated_swizzle.h"
|
#include "video_core/texture_cache/accelerated_swizzle.h"
|
||||||
#include "video_core/texture_cache/types.h"
|
#include "video_core/texture_cache/types.h"
|
||||||
#include "video_core/texture_cache/util.h"
|
#include "video_core/texture_cache/util.h"
|
||||||
#include "video_core/textures/astc.h"
|
|
||||||
#include "video_core/textures/decoders.h"
|
#include "video_core/textures/decoders.h"
|
||||||
|
|
||||||
namespace OpenGL {
|
namespace OpenGL {
|
||||||
|
|
||||||
using namespace HostShaders;
|
using namespace HostShaders;
|
||||||
using namespace Tegra::Texture::ASTC;
|
|
||||||
|
|
||||||
using VideoCommon::Extent2D;
|
using VideoCommon::Extent2D;
|
||||||
using VideoCommon::Extent3D;
|
using VideoCommon::Extent3D;
|
||||||
using VideoCommon::ImageCopy;
|
using VideoCommon::ImageCopy;
|
||||||
|
|
@ -141,10 +141,8 @@ void UtilShaders::BlockLinearUpload2D(Image& image, const StagingBufferMap& map,
|
||||||
glUniform1ui(5, params.x_shift);
|
glUniform1ui(5, params.x_shift);
|
||||||
glUniform1ui(6, params.block_height);
|
glUniform1ui(6, params.block_height);
|
||||||
glUniform1ui(7, params.block_height_mask);
|
glUniform1ui(7, params.block_height_mask);
|
||||||
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BINDING_INPUT_BUFFER, map.buffer, input_offset,
|
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BINDING_INPUT_BUFFER, map.buffer, input_offset, image.guest_size_bytes - swizzle.buffer_offset);
|
||||||
image.guest_size_bytes - swizzle.buffer_offset);
|
glBindImageTexture(BINDING_OUTPUT_IMAGE, image.StorageHandle(), swizzle.level, GL_TRUE, 0, GL_WRITE_ONLY, store_format);
|
||||||
glBindImageTexture(BINDING_OUTPUT_IMAGE, image.StorageHandle(), swizzle.level, GL_TRUE, 0,
|
|
||||||
GL_WRITE_ONLY, store_format);
|
|
||||||
glDispatchCompute(num_dispatches_x, num_dispatches_y, image.info.resources.layers);
|
glDispatchCompute(num_dispatches_x, num_dispatches_y, image.info.resources.layers);
|
||||||
}
|
}
|
||||||
program_manager.RestoreGuestCompute();
|
program_manager.RestoreGuestCompute();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||||
|
|
@ -251,6 +251,12 @@ FormatInfo SurfaceFormat(const Device& device, FormatType format_type, bool with
|
||||||
case Settings::AstcRecompression::Bc3:
|
case Settings::AstcRecompression::Bc3:
|
||||||
tuple.format = is_srgb ? VK_FORMAT_BC3_SRGB_BLOCK : VK_FORMAT_BC3_UNORM_BLOCK;
|
tuple.format = is_srgb ? VK_FORMAT_BC3_SRGB_BLOCK : VK_FORMAT_BC3_UNORM_BLOCK;
|
||||||
break;
|
break;
|
||||||
|
case Settings::AstcRecompression::Bc7:
|
||||||
|
tuple.format = is_srgb ? VK_FORMAT_BC7_SRGB_BLOCK : VK_FORMAT_BC7_UNORM_BLOCK;
|
||||||
|
break;
|
||||||
|
case Settings::AstcRecompression::Etc2:
|
||||||
|
tuple.format = is_srgb ? VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK : VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Transcode on hardware that doesn't support BCn natively
|
// Transcode on hardware that doesn't support BCn natively
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||||
|
|
@ -558,13 +558,11 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
|
||||||
const VkImageAspectFlags aspect_mask = image.AspectMask();
|
const VkImageAspectFlags aspect_mask = image.AspectMask();
|
||||||
const VkImage vk_image = image.Handle();
|
const VkImage vk_image = image.Handle();
|
||||||
const bool is_initialized = image.ExchangeInitialization();
|
const bool is_initialized = image.ExchangeInitialization();
|
||||||
scheduler.Record([vk_pipeline, vk_image, aspect_mask,
|
scheduler.Record([vk_pipeline, vk_image, aspect_mask, is_initialized](vk::CommandBuffer cmdbuf) {
|
||||||
is_initialized](vk::CommandBuffer cmdbuf) {
|
|
||||||
const VkImageMemoryBarrier image_barrier{
|
const VkImageMemoryBarrier image_barrier{
|
||||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.srcAccessMask = static_cast<VkAccessFlags>(is_initialized ? VK_ACCESS_SHADER_WRITE_BIT
|
.srcAccessMask = VkAccessFlags(is_initialized ? VK_ACCESS_SHADER_WRITE_BIT : VK_ACCESS_NONE),
|
||||||
: VK_ACCESS_NONE),
|
|
||||||
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
|
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
|
||||||
.oldLayout = is_initialized ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_UNDEFINED,
|
.oldLayout = is_initialized ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
|
@ -579,9 +577,7 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
cmdbuf.PipelineBarrier(is_initialized ? VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
|
cmdbuf.PipelineBarrier(is_initialized ? VK_PIPELINE_STAGE_ALL_COMMANDS_BIT : VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, image_barrier);
|
||||||
: VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
|
||||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, image_barrier);
|
|
||||||
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, vk_pipeline);
|
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, vk_pipeline);
|
||||||
});
|
});
|
||||||
for (const VideoCommon::SwizzleParameters& swizzle : swizzles) {
|
for (const VideoCommon::SwizzleParameters& swizzle : swizzles) {
|
||||||
|
|
@ -591,8 +587,7 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
|
||||||
const u32 num_dispatches_z = image.info.resources.layers;
|
const u32 num_dispatches_z = image.info.resources.layers;
|
||||||
|
|
||||||
compute_pass_descriptor_queue.Acquire();
|
compute_pass_descriptor_queue.Acquire();
|
||||||
compute_pass_descriptor_queue.AddBuffer(map.buffer, input_offset,
|
compute_pass_descriptor_queue.AddBuffer(map.buffer, input_offset, image.guest_size_bytes - swizzle.buffer_offset);
|
||||||
image.guest_size_bytes - swizzle.buffer_offset);
|
|
||||||
compute_pass_descriptor_queue.AddImage(image.StorageImageView(swizzle.level));
|
compute_pass_descriptor_queue.AddImage(image.StorageImageView(swizzle.level));
|
||||||
const void* const descriptor_data{compute_pass_descriptor_queue.UpdateData()};
|
const void* const descriptor_data{compute_pass_descriptor_queue.UpdateData()};
|
||||||
|
|
||||||
|
|
@ -601,8 +596,7 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
|
||||||
ASSERT(params.origin == (std::array<u32, 3>{0, 0, 0}));
|
ASSERT(params.origin == (std::array<u32, 3>{0, 0, 0}));
|
||||||
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](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,
|
||||||
|
|
@ -637,8 +631,7 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, image_barrier);
|
||||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, image_barrier);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -848,13 +848,11 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, Scheduler& sched
|
||||||
RenderPassCache& render_pass_cache_,
|
RenderPassCache& render_pass_cache_,
|
||||||
DescriptorPool& descriptor_pool,
|
DescriptorPool& descriptor_pool,
|
||||||
ComputePassDescriptorQueue& compute_pass_descriptor_queue)
|
ComputePassDescriptorQueue& compute_pass_descriptor_queue)
|
||||||
: device{device_}, scheduler{scheduler_}, memory_allocator{memory_allocator_},
|
: device{device_}, scheduler{scheduler_}, memory_allocator{memory_allocator_}
|
||||||
staging_buffer_pool{staging_buffer_pool_}, blit_image_helper{blit_image_helper_},
|
, staging_buffer_pool{staging_buffer_pool_}, blit_image_helper{blit_image_helper_}
|
||||||
render_pass_cache{render_pass_cache_}, resolution{Settings::values.resolution_info} {
|
, render_pass_cache{render_pass_cache_}, resolution{Settings::values.resolution_info}
|
||||||
if (Settings::values.accelerate_astc.GetValue() == Settings::AstcDecodeMode::Gpu) {
|
{
|
||||||
astc_decoder_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool,
|
astc_decoder_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool, compute_pass_descriptor_queue, memory_allocator);
|
||||||
compute_pass_descriptor_queue, memory_allocator);
|
|
||||||
}
|
|
||||||
if (device.IsStorageImageMultisampleSupported()) {
|
if (device.IsStorageImageMultisampleSupported()) {
|
||||||
msaa_copy_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool, compute_pass_descriptor_queue);
|
msaa_copy_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool, compute_pass_descriptor_queue);
|
||||||
}
|
}
|
||||||
|
|
@ -1562,20 +1560,7 @@ Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu
|
||||||
runtime->ViewFormats(info.format))),
|
runtime->ViewFormats(info.format))),
|
||||||
aspect_mask(ImageAspectMask(info.format)) {
|
aspect_mask(ImageAspectMask(info.format)) {
|
||||||
if (IsPixelFormatASTC(info.format) && !runtime->device.IsOptimalAstcSupported()) {
|
if (IsPixelFormatASTC(info.format) && !runtime->device.IsOptimalAstcSupported()) {
|
||||||
switch (Settings::values.accelerate_astc.GetValue()) {
|
flags |= VideoCommon::ImageFlagBits::AcceleratedUpload;
|
||||||
case Settings::AstcDecodeMode::Gpu:
|
|
||||||
if (Settings::values.astc_recompression.GetValue() ==
|
|
||||||
Settings::AstcRecompression::Uncompressed &&
|
|
||||||
info.size.depth == 1) {
|
|
||||||
flags |= VideoCommon::ImageFlagBits::AcceleratedUpload;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Settings::AstcDecodeMode::CpuAsynchronous:
|
|
||||||
flags |= VideoCommon::ImageFlagBits::AsynchronousDecode;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
flags |= VideoCommon::ImageFlagBits::Converted;
|
flags |= VideoCommon::ImageFlagBits::Converted;
|
||||||
flags |= VideoCommon::ImageFlagBits::CostlyLoad;
|
flags |= VideoCommon::ImageFlagBits::CostlyLoad;
|
||||||
}
|
}
|
||||||
|
|
@ -1588,13 +1573,10 @@ Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu
|
||||||
}
|
}
|
||||||
current_image = &Image::original_image;
|
current_image = &Image::original_image;
|
||||||
storage_image_views.resize(info.resources.levels);
|
storage_image_views.resize(info.resources.levels);
|
||||||
if (IsPixelFormatASTC(info.format) && !runtime->device.IsOptimalAstcSupported() &&
|
if (IsPixelFormatASTC(info.format) && !runtime->device.IsOptimalAstcSupported()) {
|
||||||
Settings::values.astc_recompression.GetValue() ==
|
|
||||||
Settings::AstcRecompression::Uncompressed) {
|
|
||||||
const auto& device = runtime->device.GetLogical();
|
const auto& device = runtime->device.GetLogical();
|
||||||
for (s32 level = 0; level < info.resources.levels; ++level) {
|
for (s32 level = 0; level < info.resources.levels; ++level) {
|
||||||
storage_image_views[level] =
|
storage_image_views[level] = MakeStorageView(device, level, *original_image, VK_FORMAT_A8B8G8R8_UNORM_PACK32);
|
||||||
MakeStorageView(device, level, *original_image, VK_FORMAT_A8B8G8R8_UNORM_PACK32);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
||||||
|
|
@ -444,15 +444,17 @@ std::pair<u32, u32> GetASTCBlockSize(PixelFormat format) {
|
||||||
|
|
||||||
u64 TranscodedAstcSize(u64 base_size, PixelFormat format) {
|
u64 TranscodedAstcSize(u64 base_size, PixelFormat format) {
|
||||||
constexpr u64 RGBA8_PIXEL_SIZE = 4;
|
constexpr u64 RGBA8_PIXEL_SIZE = 4;
|
||||||
const u64 base_block_size = static_cast<u64>(DefaultBlockWidth(format)) *
|
const u64 base_block_size = u64(DefaultBlockWidth(format)) * u64(DefaultBlockHeight(format)) * RGBA8_PIXEL_SIZE;
|
||||||
static_cast<u64>(DefaultBlockHeight(format)) * RGBA8_PIXEL_SIZE;
|
|
||||||
const u64 uncompressed_size = (base_size * base_block_size) / BytesPerBlock(format);
|
const u64 uncompressed_size = (base_size * base_block_size) / BytesPerBlock(format);
|
||||||
|
|
||||||
switch (Settings::values.astc_recompression.GetValue()) {
|
switch (Settings::values.astc_recompression.GetValue()) {
|
||||||
case Settings::AstcRecompression::Bc1:
|
case Settings::AstcRecompression::Bc1:
|
||||||
return uncompressed_size / 8;
|
return uncompressed_size / 8;
|
||||||
case Settings::AstcRecompression::Bc3:
|
case Settings::AstcRecompression::Bc3:
|
||||||
return uncompressed_size / 4;
|
return uncompressed_size / 4;
|
||||||
|
case Settings::AstcRecompression::Bc7:
|
||||||
|
return uncompressed_size / 4;
|
||||||
|
case Settings::AstcRecompression::Etc2:
|
||||||
|
return uncompressed_size / 4; //6=RGB, 4=RGBA
|
||||||
default:
|
default:
|
||||||
return uncompressed_size;
|
return uncompressed_size;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2317,13 +2317,10 @@ ImageViewId TextureCache<P>::FindOrEmplaceImageView(ImageId image_id, const Imag
|
||||||
template <class P>
|
template <class P>
|
||||||
void TextureCache<P>::RegisterImage(ImageId image_id) {
|
void TextureCache<P>::RegisterImage(ImageId image_id) {
|
||||||
ImageBase& image = slot_images[image_id];
|
ImageBase& image = slot_images[image_id];
|
||||||
ASSERT_MSG(False(image.flags & ImageFlagBits::Registered),
|
ASSERT(False(image.flags & ImageFlagBits::Registered) && "Trying to register an already registered image");
|
||||||
"Trying to register an already registered image");
|
|
||||||
image.flags |= ImageFlagBits::Registered;
|
image.flags |= ImageFlagBits::Registered;
|
||||||
u64 tentative_size = (std::max)(image.guest_size_bytes, image.unswizzled_size_bytes);
|
u64 tentative_size = (std::max)(image.guest_size_bytes, image.unswizzled_size_bytes);
|
||||||
if ((IsPixelFormatASTC(image.info.format) &&
|
if ((IsPixelFormatASTC(image.info.format) && True(image.flags & ImageFlagBits::AcceleratedUpload)) || True(image.flags & ImageFlagBits::Converted)) {
|
||||||
True(image.flags & ImageFlagBits::AcceleratedUpload)) ||
|
|
||||||
True(image.flags & ImageFlagBits::Converted)) {
|
|
||||||
tentative_size = TranscodedAstcSize(tentative_size, image.info.format);
|
tentative_size = TranscodedAstcSize(tentative_size, image.info.format);
|
||||||
}
|
}
|
||||||
total_used_memory += Common::AlignUp(tentative_size, 1024);
|
total_used_memory += Common::AlignUp(tentative_size, 1024);
|
||||||
|
|
@ -2495,9 +2492,7 @@ void TextureCache<P>::DeleteImage(ImageId image_id, bool immediate_delete) {
|
||||||
total_used_memory -= GetScaledImageSizeBytes(image);
|
total_used_memory -= GetScaledImageSizeBytes(image);
|
||||||
}
|
}
|
||||||
u64 tentative_size = (std::max)(image.guest_size_bytes, image.unswizzled_size_bytes);
|
u64 tentative_size = (std::max)(image.guest_size_bytes, image.unswizzled_size_bytes);
|
||||||
if ((IsPixelFormatASTC(image.info.format) &&
|
if ((IsPixelFormatASTC(image.info.format) && True(image.flags & ImageFlagBits::AcceleratedUpload)) || True(image.flags & ImageFlagBits::Converted)) {
|
||||||
True(image.flags & ImageFlagBits::AcceleratedUpload)) ||
|
|
||||||
True(image.flags & ImageFlagBits::Converted)) {
|
|
||||||
tentative_size = TranscodedAstcSize(tentative_size, image.info.format);
|
tentative_size = TranscodedAstcSize(tentative_size, image.info.format);
|
||||||
}
|
}
|
||||||
total_used_memory -= Common::AlignUp(tentative_size, 1024);
|
total_used_memory -= Common::AlignUp(tentative_size, 1024);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||||
|
|
@ -33,7 +33,6 @@
|
||||||
#include "video_core/texture_cache/formatter.h"
|
#include "video_core/texture_cache/formatter.h"
|
||||||
#include "video_core/texture_cache/samples_helper.h"
|
#include "video_core/texture_cache/samples_helper.h"
|
||||||
#include "video_core/texture_cache/util.h"
|
#include "video_core/texture_cache/util.h"
|
||||||
#include "video_core/textures/astc.h"
|
|
||||||
#include "video_core/textures/bcn.h"
|
#include "video_core/textures/bcn.h"
|
||||||
#include "video_core/textures/decoders.h"
|
#include "video_core/textures/decoders.h"
|
||||||
|
|
||||||
|
|
@ -608,23 +607,18 @@ u32 CalculateConvertedSizeBytes(const ImageInfo& info) noexcept {
|
||||||
return info.size.width * BytesPerBlock(info.format);
|
return info.size.width * BytesPerBlock(info.format);
|
||||||
}
|
}
|
||||||
static constexpr Extent2D TILE_SIZE{1, 1};
|
static constexpr Extent2D TILE_SIZE{1, 1};
|
||||||
if (IsPixelFormatASTC(info.format) && Settings::values.astc_recompression.GetValue() !=
|
if (IsPixelFormatASTC(info.format) && Settings::values.astc_recompression.GetValue() != Settings::AstcRecompression::Uncompressed) {
|
||||||
Settings::AstcRecompression::Uncompressed) {
|
const u32 bpp_div = Settings::values.astc_recompression.GetValue() == Settings::AstcRecompression::Bc1 ? 2 : 1;
|
||||||
const u32 bpp_div =
|
|
||||||
Settings::values.astc_recompression.GetValue() == Settings::AstcRecompression::Bc1 ? 2
|
|
||||||
: 1;
|
|
||||||
// NumBlocksPerLayer doesn't account for this correctly, so we have to do it manually.
|
// NumBlocksPerLayer doesn't account for this correctly, so we have to do it manually.
|
||||||
u32 output_size = 0;
|
u32 output_size = 0;
|
||||||
for (s32 i = 0; i < info.resources.levels; i++) {
|
for (s32 i = 0; i < info.resources.levels; i++) {
|
||||||
const auto mip_size = AdjustMipSize(info.size, i);
|
const auto mip_size = AdjustMipSize(info.size, i);
|
||||||
const u32 plane_dim =
|
const u32 plane_dim = Common::AlignUp(mip_size.width, 4U) * Common::AlignUp(mip_size.height, 4U);
|
||||||
Common::AlignUp(mip_size.width, 4U) * Common::AlignUp(mip_size.height, 4U);
|
|
||||||
output_size += (plane_dim * info.size.depth * info.resources.layers) / bpp_div;
|
output_size += (plane_dim * info.size.depth * info.resources.layers) / bpp_div;
|
||||||
}
|
}
|
||||||
return output_size;
|
return output_size;
|
||||||
}
|
}
|
||||||
return NumBlocksPerLayer(info, TILE_SIZE) * info.resources.layers *
|
return NumBlocksPerLayer(info, TILE_SIZE) * info.resources.layers * ConvertedBytesPerBlock(info.format);
|
||||||
ConvertedBytesPerBlock(info.format);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 CalculateLayerStride(const ImageInfo& info) noexcept {
|
u32 CalculateLayerStride(const ImageInfo& info) noexcept {
|
||||||
|
|
@ -922,8 +916,7 @@ boost::container::small_vector<BufferImageCopy, 16> UnswizzleImage(Tegra::Memory
|
||||||
return copies;
|
return copies;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConvertImage(std::span<const u8> input, const ImageInfo& info, std::span<u8> output,
|
void ConvertImage(std::span<const u8> input, const ImageInfo& info, std::span<u8> output, std::span<BufferImageCopy> copies) {
|
||||||
std::span<BufferImageCopy> copies) {
|
|
||||||
u32 output_offset = 0;
|
u32 output_offset = 0;
|
||||||
Common::ScratchBuffer<u8> decode_scratch;
|
Common::ScratchBuffer<u8> decode_scratch;
|
||||||
|
|
||||||
|
|
@ -939,56 +932,9 @@ void ConvertImage(std::span<const u8> input, const ImageInfo& info, std::span<u8
|
||||||
|
|
||||||
const auto input_offset = input.subspan(copy.buffer_offset);
|
const auto input_offset = input.subspan(copy.buffer_offset);
|
||||||
copy.buffer_offset = output_offset;
|
copy.buffer_offset = output_offset;
|
||||||
|
ASSERT(!IsPixelFormatASTC(info.format) && "CPU ASTC decoder is phased out");
|
||||||
const auto recompression_setting = Settings::values.astc_recompression.GetValue();
|
DecompressBCn(input_offset, output.subspan(output_offset), copy, info.format);
|
||||||
const bool astc = IsPixelFormatASTC(info.format);
|
output_offset += copy.image_extent.width * copy.image_extent.height * copy.image_subresource.num_layers * ConvertedBytesPerBlock(info.format);
|
||||||
|
|
||||||
if (astc && recompression_setting == Settings::AstcRecompression::Uncompressed) {
|
|
||||||
Tegra::Texture::ASTC::Decompress(
|
|
||||||
input_offset, copy.image_extent.width, copy.image_extent.height,
|
|
||||||
copy.image_subresource.num_layers * copy.image_extent.depth, tile_size.width,
|
|
||||||
tile_size.height, output.subspan(output_offset));
|
|
||||||
|
|
||||||
output_offset += copy.image_extent.width * copy.image_extent.height *
|
|
||||||
copy.image_subresource.num_layers *
|
|
||||||
BytesPerBlock(PixelFormat::A8B8G8R8_UNORM);
|
|
||||||
} else if (astc) {
|
|
||||||
// BC1 uses 0.5 bytes per texel
|
|
||||||
// BC3 uses 1 byte per texel
|
|
||||||
const auto compress = recompression_setting == Settings::AstcRecompression::Bc1
|
|
||||||
? Tegra::Texture::BCN::CompressBC1
|
|
||||||
: Tegra::Texture::BCN::CompressBC3;
|
|
||||||
const auto bpp_div = recompression_setting == Settings::AstcRecompression::Bc1 ? 2 : 1;
|
|
||||||
|
|
||||||
const u32 plane_dim = copy.image_extent.width * copy.image_extent.height;
|
|
||||||
const u32 level_size = plane_dim * copy.image_extent.depth *
|
|
||||||
copy.image_subresource.num_layers *
|
|
||||||
BytesPerBlock(PixelFormat::A8B8G8R8_UNORM);
|
|
||||||
decode_scratch.resize_destructive(level_size);
|
|
||||||
|
|
||||||
Tegra::Texture::ASTC::Decompress(
|
|
||||||
input_offset, copy.image_extent.width, copy.image_extent.height,
|
|
||||||
copy.image_subresource.num_layers * copy.image_extent.depth, tile_size.width,
|
|
||||||
tile_size.height, decode_scratch);
|
|
||||||
|
|
||||||
compress(decode_scratch, copy.image_extent.width, copy.image_extent.height,
|
|
||||||
copy.image_subresource.num_layers * copy.image_extent.depth,
|
|
||||||
output.subspan(output_offset));
|
|
||||||
|
|
||||||
const u32 aligned_plane_dim = Common::AlignUp(copy.image_extent.width, 4) *
|
|
||||||
Common::AlignUp(copy.image_extent.height, 4);
|
|
||||||
|
|
||||||
copy.buffer_size =
|
|
||||||
(aligned_plane_dim * copy.image_extent.depth * copy.image_subresource.num_layers) /
|
|
||||||
bpp_div;
|
|
||||||
output_offset += static_cast<u32>(copy.buffer_size);
|
|
||||||
} else {
|
|
||||||
DecompressBCn(input_offset, output.subspan(output_offset), copy, info.format);
|
|
||||||
output_offset += copy.image_extent.width * copy.image_extent.height *
|
|
||||||
copy.image_subresource.num_layers *
|
|
||||||
ConvertedBytesPerBlock(info.format);
|
|
||||||
}
|
|
||||||
|
|
||||||
copy.buffer_row_length = mip_size.width;
|
copy.buffer_row_length = mip_size.width;
|
||||||
copy.buffer_image_height = mip_size.height;
|
copy.buffer_image_height = mip_size.height;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,11 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
namespace Tegra::Texture::ASTC {
|
|
||||||
|
|
||||||
void Decompress(std::span<const uint8_t> data, uint32_t width, uint32_t height, uint32_t depth,
|
|
||||||
uint32_t block_width, uint32_t block_height, std::span<uint8_t> output);
|
|
||||||
|
|
||||||
} // namespace Tegra::Texture::ASTC
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue