mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-10-07 06:18:23 +00:00
Remove astc recompression method
This commit is contained in:
@@ -256,8 +256,6 @@ add_library(video_core STATIC
|
||||
texture_cache/util.h
|
||||
textures/astc.h
|
||||
textures/astc.cpp
|
||||
textures/bcn.cpp
|
||||
textures/bcn.h
|
||||
textures/decoders.cpp
|
||||
textures/decoders.h
|
||||
textures/texture.cpp
|
||||
@@ -406,7 +404,7 @@ if (ENABLE_OPENGL)
|
||||
endif()
|
||||
|
||||
target_link_libraries(video_core PUBLIC common core)
|
||||
target_link_libraries(video_core PUBLIC shader_recompiler stb bc_decoder gpu_logging)
|
||||
target_link_libraries(video_core PUBLIC shader_recompiler bc_decoder gpu_logging)
|
||||
if (ENABLE_OPENGL)
|
||||
target_link_libraries(video_core PUBLIC glad)
|
||||
endif()
|
||||
|
||||
@@ -235,9 +235,7 @@ void ApplySwizzle(GLuint handle, PixelFormat format, std::array<SwizzleSource, 4
|
||||
[[nodiscard]] bool CanBeAccelerated(const TextureCacheRuntime& runtime,
|
||||
const VideoCommon::ImageInfo& info) {
|
||||
if (IsPixelFormatASTC(info.format) && info.size.depth == 1 && !runtime.HasNativeASTC()) {
|
||||
return Settings::values.accelerate_astc.GetValue() == Settings::AstcDecodeMode::Gpu &&
|
||||
Settings::values.astc_recompression.GetValue() ==
|
||||
Settings::AstcRecompression::Uncompressed;
|
||||
return Settings::values.accelerate_astc.GetValue() == Settings::AstcDecodeMode::Gpu;
|
||||
}
|
||||
// Disable other accelerated uploads for now as they don't implement swizzled uploads
|
||||
return false;
|
||||
@@ -442,23 +440,6 @@ OGLTexture MakeImage(const VideoCommon::ImageInfo& info, GLenum gl_internal_form
|
||||
return GL_R32UI;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsAstcRecompressionEnabled() {
|
||||
return Settings::values.astc_recompression.GetValue() !=
|
||||
Settings::AstcRecompression::Uncompressed;
|
||||
}
|
||||
|
||||
[[nodiscard]] GLenum SelectAstcFormat(PixelFormat format, bool is_srgb) {
|
||||
switch (Settings::values.astc_recompression.GetValue()) {
|
||||
case Settings::AstcRecompression::Bc1:
|
||||
return is_srgb ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT : GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||
break;
|
||||
case Settings::AstcRecompression::Bc3:
|
||||
return is_srgb ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT : GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
break;
|
||||
default:
|
||||
return is_srgb ? GL_SRGB8_ALPHA8 : GL_RGBA8;
|
||||
}
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
TextureCacheRuntime::TextureCacheRuntime(const Device& device_, ProgramManager& program_manager,
|
||||
@@ -708,11 +689,6 @@ Image::Image(TextureCacheRuntime& runtime_, const VideoCommon::ImageInfo& info_,
|
||||
gl_internal_format = is_srgb ? GL_SRGB8_ALPHA8 : GL_RGBA8;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
|
||||
if (IsPixelFormatASTC(info.format) && IsAstcRecompressionEnabled()) {
|
||||
gl_internal_format = SelectAstcFormat(info.format, is_srgb);
|
||||
gl_format = GL_NONE;
|
||||
}
|
||||
} else {
|
||||
const auto& tuple = MaxwellToGL::GetFormatTuple(info.format);
|
||||
gl_internal_format = tuple.internal_format;
|
||||
@@ -1109,10 +1085,6 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
|
||||
if (True(image.flags & ImageFlagBits::Converted)) {
|
||||
const bool is_srgb = IsPixelFormatSRGB(info.format);
|
||||
internal_format = is_srgb ? GL_SRGB8_ALPHA8 : GL_RGBA8;
|
||||
|
||||
if (IsPixelFormatASTC(info.format) && IsAstcRecompressionEnabled()) {
|
||||
internal_format = SelectAstcFormat(info.format, is_srgb);
|
||||
}
|
||||
} else {
|
||||
internal_format = MaxwellToGL::GetFormatTuple(format).internal_format;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging.h"
|
||||
#include "common/settings.h"
|
||||
#include "video_core/engines/maxwell_3d.h"
|
||||
#include "video_core/renderer_vulkan/maxwell_to_vk.h"
|
||||
#include "video_core/surface.h"
|
||||
@@ -246,21 +245,11 @@ FormatInfo SurfaceFormat(const Device& device, FormatType format_type, bool with
|
||||
bool const is_srgb = with_srgb && VideoCore::Surface::IsPixelFormatSRGB(pixel_format);
|
||||
// Transcode on hardware that doesn't support ASTC natively
|
||||
if (!device.IsOptimalAstcSupported() && VideoCore::Surface::IsPixelFormatASTC(pixel_format)) {
|
||||
switch (Settings::values.astc_recompression.GetValue()) {
|
||||
case Settings::AstcRecompression::Uncompressed:
|
||||
if (is_srgb) {
|
||||
tuple.format = VK_FORMAT_A8B8G8R8_SRGB_PACK32;
|
||||
} else {
|
||||
tuple.format = VK_FORMAT_A8B8G8R8_UNORM_PACK32;
|
||||
tuple.usage |= usage_storage;
|
||||
}
|
||||
break;
|
||||
case Settings::AstcRecompression::Bc1:
|
||||
tuple.format = is_srgb ? VK_FORMAT_BC1_RGBA_SRGB_BLOCK : VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
|
||||
break;
|
||||
case Settings::AstcRecompression::Bc3:
|
||||
tuple.format = is_srgb ? VK_FORMAT_BC3_SRGB_BLOCK : VK_FORMAT_BC3_UNORM_BLOCK;
|
||||
break;
|
||||
if (is_srgb) {
|
||||
tuple.format = VK_FORMAT_A8B8G8R8_SRGB_PACK32;
|
||||
} else {
|
||||
tuple.format = VK_FORMAT_A8B8G8R8_UNORM_PACK32;
|
||||
tuple.usage |= usage_storage;
|
||||
}
|
||||
}
|
||||
if (!device.IsOptimalBcnSupported() && VideoCore::Surface::IsPixelFormatBCn(pixel_format)) {
|
||||
|
||||
@@ -155,9 +155,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
|
||||
if (Settings::values.accelerate_astc.GetValue() != Settings::AstcDecodeMode::Gpu) {
|
||||
return false;
|
||||
}
|
||||
return Settings::values.astc_recompression.GetValue() ==
|
||||
Settings::AstcRecompression::Uncompressed &&
|
||||
info.size.depth == 1;
|
||||
return info.size.depth == 1;
|
||||
}
|
||||
|
||||
[[nodiscard]] VkImageCreateInfo MakeImageCreateInfo(const Device& device, const ImageInfo& info,
|
||||
@@ -1880,8 +1878,9 @@ Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu
|
||||
case Settings::AstcDecodeMode::Gpu:
|
||||
if (WillUseAcceleratedAstcDecode(runtime->device, info)) {
|
||||
flags |= VideoCommon::ImageFlagBits::AcceleratedUpload;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
[[fallthrough]];
|
||||
case Settings::AstcDecodeMode::CpuAsynchronous:
|
||||
flags |= VideoCommon::ImageFlagBits::AsynchronousDecode;
|
||||
break;
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "common/math_util.h"
|
||||
#include "common/settings.h"
|
||||
#include "video_core/surface.h"
|
||||
|
||||
namespace VideoCore::Surface {
|
||||
@@ -469,14 +468,7 @@ u64 TranscodedAstcSize(u64 base_size, PixelFormat format) {
|
||||
static_cast<u64>(DefaultBlockHeight(format)) * RGBA8_PIXEL_SIZE;
|
||||
const u64 uncompressed_size = (base_size * base_block_size) / BytesPerBlock(format);
|
||||
|
||||
switch (Settings::values.astc_recompression.GetValue()) {
|
||||
case Settings::AstcRecompression::Bc1:
|
||||
return uncompressed_size / 8;
|
||||
case Settings::AstcRecompression::Bc3:
|
||||
return uncompressed_size / 4;
|
||||
default:
|
||||
return uncompressed_size;
|
||||
}
|
||||
return uncompressed_size;
|
||||
}
|
||||
|
||||
} // namespace VideoCore::Surface
|
||||
|
||||
@@ -95,6 +95,7 @@ struct ImageBase {
|
||||
u32 scale_rating = 0;
|
||||
u64 scale_tick = 0;
|
||||
bool has_scaled = false;
|
||||
u32 guest_data_checks = 0;
|
||||
|
||||
size_t channel = 0;
|
||||
|
||||
@@ -105,6 +106,7 @@ struct ImageBase {
|
||||
VAddr cpu_addr_end = 0;
|
||||
|
||||
u64 modification_tick = 0;
|
||||
u64 guest_data_hash = 0;
|
||||
size_t lru_index = SIZE_MAX;
|
||||
|
||||
std::array<u32, MAX_MIP_LEVELS> mip_level_offsets{};
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <boost/container/small_vector.hpp>
|
||||
|
||||
#include "common/alignment.h"
|
||||
#include "common/cityhash.h"
|
||||
#include "common/settings.h"
|
||||
#include "common/slot_vector.h"
|
||||
#include "video_core/control/channel_state.h"
|
||||
@@ -1074,6 +1075,29 @@ void TextureCache<P>::DownloadImageIntoBuffer(typename TextureCache<P>::Image* i
|
||||
}
|
||||
}
|
||||
|
||||
template <class P>
|
||||
bool TextureCache<P>::IsAstcDataUnchanged(Image& image) {
|
||||
static constexpr u32 CHECK_THRESHOLD = 4;
|
||||
if (False(image.flags & ImageFlagBits::Converted) ||
|
||||
True(image.flags & ImageFlagBits::GpuModified) ||
|
||||
!IsPixelFormatASTC(image.info.format)) {
|
||||
return false;
|
||||
}
|
||||
if (image.guest_data_checks < CHECK_THRESHOLD) {
|
||||
++image.guest_data_checks;
|
||||
return false;
|
||||
}
|
||||
Tegra::Memory::GpuGuestMemory<u8, Tegra::Memory::GuestMemoryFlags::UnsafeRead> guest_data(
|
||||
*gpu_memory, image.gpu_addr, image.guest_size_bytes, &swizzle_data_buffer);
|
||||
const u64 hash = Common::CityHash64(reinterpret_cast<const char*>(guest_data.data()),
|
||||
image.guest_size_bytes);
|
||||
if (image.guest_data_hash == hash) {
|
||||
return true;
|
||||
}
|
||||
image.guest_data_hash = hash;
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class P>
|
||||
void TextureCache<P>::RefreshContents(Image& image, ImageId image_id) {
|
||||
if (False(image.flags & ImageFlagBits::CpuModified)) {
|
||||
@@ -1085,6 +1109,10 @@ void TextureCache<P>::RefreshContents(Image& image, ImageId image_id) {
|
||||
|
||||
TrackImage(image, image_id);
|
||||
|
||||
if (IsAstcDataUnchanged(image)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (image.info.num_samples > 1 && !runtime.CanUploadMSAA()) {
|
||||
LOG_WARNING(HW_GPU, "MSAA image uploads are not implemented");
|
||||
runtime.TransitionImageLayout(image);
|
||||
|
||||
@@ -298,6 +298,8 @@ private:
|
||||
|
||||
void RefreshContents(Image& image, ImageId image_id);
|
||||
|
||||
[[nodiscard]] bool IsAstcDataUnchanged(Image& image);
|
||||
|
||||
/// Upload data from guest to an image
|
||||
template <typename StagingBuffer>
|
||||
void UploadImageContents(Image& image, StagingBuffer& staging_buffer);
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "common/common_types.h"
|
||||
#include "common/div_ceil.h"
|
||||
#include "common/scratch_buffer.h"
|
||||
#include "common/settings.h"
|
||||
#include "video_core/compatible_formats.h"
|
||||
#include "video_core/engines/maxwell_3d.h"
|
||||
#include "video_core/guest_memory.h"
|
||||
@@ -34,7 +33,6 @@
|
||||
#include "video_core/texture_cache/samples_helper.h"
|
||||
#include "video_core/texture_cache/util.h"
|
||||
#include "video_core/textures/astc.h"
|
||||
#include "video_core/textures/bcn.h"
|
||||
#include "video_core/textures/decoders.h"
|
||||
|
||||
namespace VideoCommon {
|
||||
@@ -608,21 +606,6 @@ u32 CalculateConvertedSizeBytes(const ImageInfo& info) noexcept {
|
||||
return info.size.width * BytesPerBlock(info.format);
|
||||
}
|
||||
static constexpr Extent2D TILE_SIZE{1, 1};
|
||||
if (IsPixelFormatASTC(info.format) && Settings::values.astc_recompression.GetValue() !=
|
||||
Settings::AstcRecompression::Uncompressed) {
|
||||
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.
|
||||
u32 output_size = 0;
|
||||
for (s32 i = 0; i < info.resources.levels; i++) {
|
||||
const auto mip_size = AdjustMipSize(info.size, i);
|
||||
const u32 plane_dim =
|
||||
Common::AlignUp(mip_size.width, 4U) * Common::AlignUp(mip_size.height, 4U);
|
||||
output_size += (plane_dim * info.size.depth * info.resources.layers) / bpp_div;
|
||||
}
|
||||
return output_size;
|
||||
}
|
||||
return NumBlocksPerLayer(info, TILE_SIZE) * info.resources.layers *
|
||||
ConvertedBytesPerBlock(info.format);
|
||||
}
|
||||
@@ -925,7 +908,6 @@ boost::container::small_vector<BufferImageCopy, 16> UnswizzleImage(Tegra::Memory
|
||||
void ConvertImage(std::span<const u8> input, const ImageInfo& info, std::span<u8> output,
|
||||
std::span<BufferImageCopy> copies) {
|
||||
u32 output_offset = 0;
|
||||
Common::ScratchBuffer<u8> decode_scratch;
|
||||
|
||||
const Extent2D tile_size = DefaultBlockSize(info.format);
|
||||
for (BufferImageCopy& copy : copies) {
|
||||
@@ -940,10 +922,7 @@ void ConvertImage(std::span<const u8> input, const ImageInfo& info, std::span<u8
|
||||
const auto input_offset = input.subspan(copy.buffer_offset);
|
||||
copy.buffer_offset = output_offset;
|
||||
|
||||
const auto recompression_setting = Settings::values.astc_recompression.GetValue();
|
||||
const bool astc = IsPixelFormatASTC(info.format);
|
||||
|
||||
if (astc && recompression_setting == Settings::AstcRecompression::Uncompressed) {
|
||||
if (IsPixelFormatASTC(info.format)) {
|
||||
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,
|
||||
@@ -952,36 +931,6 @@ void ConvertImage(std::span<const u8> input, const ImageInfo& info, std::span<u8
|
||||
output_offset += copy.image_extent.width * copy.image_extent.height *
|
||||
copy.image_extent.depth * 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 *
|
||||
@@ -995,11 +944,7 @@ void ConvertImage(std::span<const u8> input, const ImageInfo& info, std::span<u8
|
||||
}
|
||||
|
||||
bool CanConvertFromGuest(const ImageInfo& info) {
|
||||
if (!IsPixelFormatASTC(info.format) || info.type == ImageType::Linear) {
|
||||
return false;
|
||||
}
|
||||
return Settings::values.astc_recompression.GetValue() ==
|
||||
Settings::AstcRecompression::Uncompressed;
|
||||
return IsPixelFormatASTC(info.format) && info.type != ImageType::Linear;
|
||||
}
|
||||
|
||||
boost::container::small_vector<BufferImageCopy, 16> ConvertImageFromGuest(
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <stb_dxt.h>
|
||||
#include <string.h>
|
||||
#include "common/alignment.h"
|
||||
#include "video_core/textures/bcn.h"
|
||||
#include "video_core/textures/workers.h"
|
||||
|
||||
namespace Tegra::Texture::BCN {
|
||||
|
||||
using BCNCompressor = void(u8* block_output, const u8* block_input, bool any_alpha);
|
||||
|
||||
template <u32 BytesPerBlock, bool ThresholdAlpha = false>
|
||||
void CompressBCN(std::span<const uint8_t> data, uint32_t width, uint32_t height, uint32_t depth,
|
||||
std::span<uint8_t> output, BCNCompressor f) {
|
||||
constexpr u8 alpha_threshold = 128;
|
||||
constexpr u32 bytes_per_px = 4;
|
||||
const u32 plane_dim = width * height;
|
||||
|
||||
Common::ThreadWorker& workers{GetThreadWorkers()};
|
||||
|
||||
for (u32 z = 0; z < depth; z++) {
|
||||
for (u32 y = 0; y < height; y += 4) {
|
||||
auto compress_row = [z, y, width, height, plane_dim, f, data, output]() {
|
||||
for (u32 x = 0; x < width; x += 4) {
|
||||
// Gather 4x4 block of RGBA texels
|
||||
u8 input_colors[4][4][4];
|
||||
bool any_alpha = false;
|
||||
|
||||
for (u32 j = 0; j < 4; j++) {
|
||||
for (u32 i = 0; i < 4; i++) {
|
||||
const size_t coord =
|
||||
(z * plane_dim + (y + j) * width + (x + i)) * bytes_per_px;
|
||||
|
||||
if ((x + i < width) && (y + j < height)) {
|
||||
if constexpr (ThresholdAlpha) {
|
||||
if (data[coord + 3] >= alpha_threshold) {
|
||||
input_colors[j][i][0] = data[coord + 0];
|
||||
input_colors[j][i][1] = data[coord + 1];
|
||||
input_colors[j][i][2] = data[coord + 2];
|
||||
input_colors[j][i][3] = 255;
|
||||
} else {
|
||||
any_alpha = true;
|
||||
memset(input_colors[j][i], 0, bytes_per_px);
|
||||
}
|
||||
} else {
|
||||
memcpy(input_colors[j][i], &data[coord], bytes_per_px);
|
||||
}
|
||||
} else {
|
||||
memset(input_colors[j][i], 0, bytes_per_px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const u32 bytes_per_row = BytesPerBlock * Common::DivideUp(width, 4U);
|
||||
const u32 bytes_per_plane = bytes_per_row * Common::DivideUp(height, 4U);
|
||||
f(output.data() + z * bytes_per_plane + (y / 4) * bytes_per_row +
|
||||
(x / 4) * BytesPerBlock,
|
||||
reinterpret_cast<u8*>(input_colors), any_alpha);
|
||||
}
|
||||
};
|
||||
workers.QueueWork(std::move(compress_row));
|
||||
}
|
||||
workers.WaitForRequests();
|
||||
}
|
||||
}
|
||||
|
||||
void CompressBC1(std::span<const uint8_t> data, uint32_t width, uint32_t height, uint32_t depth,
|
||||
std::span<uint8_t> output) {
|
||||
CompressBCN<8, true>(data, width, height, depth, output,
|
||||
[](u8* block_output, const u8* block_input, bool any_alpha) {
|
||||
stb_compress_bc1_block(block_output, block_input, any_alpha,
|
||||
STB_DXT_NORMAL);
|
||||
});
|
||||
}
|
||||
|
||||
void CompressBC3(std::span<const uint8_t> data, uint32_t width, uint32_t height, uint32_t depth,
|
||||
std::span<uint8_t> output) {
|
||||
CompressBCN<16, false>(data, width, height, depth, output,
|
||||
[](u8* block_output, const u8* block_input, bool any_alpha) {
|
||||
stb_compress_bc3_block(block_output, block_input, STB_DXT_NORMAL);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace Tegra::Texture::BCN
|
||||
@@ -1,16 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <span>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Tegra::Texture::BCN {
|
||||
|
||||
void CompressBC1(std::span<const u8> data, u32 width, u32 height, u32 depth, std::span<u8> output);
|
||||
|
||||
void CompressBC3(std::span<const u8> data, u32 width, u32 height, u32 depth, std::span<u8> output);
|
||||
|
||||
} // namespace Tegra::Texture::BCN
|
||||
Reference in New Issue
Block a user