From a3a8964d46a21626bf4e28bee955a7d83d83ee72 Mon Sep 17 00:00:00 2001 From: Steveice10 <1269164+Steveice10@users.noreply.github.com> Date: Thu, 12 Jan 2023 00:43:40 -0800 Subject: [PATCH] renderer_vulkan: Centralize pixel format trait management. (#18) * renderer_vulkan: Centralize pixel format trait management. * renderer_vulkan: Add D24 <-> D32 conversion support. --- src/video_core/renderer_vulkan/vk_common.h | 48 ------ .../renderer_vulkan/vk_instance.cpp | 151 +++++++++++------- src/video_core/renderer_vulkan/vk_instance.h | 11 +- .../renderer_vulkan/vk_rasterizer.cpp | 6 +- .../renderer_vulkan/vk_renderpass_cache.cpp | 11 +- .../renderer_vulkan/vk_texture_runtime.cpp | 60 +++---- .../renderer_vulkan/vk_texture_runtime.h | 4 +- src/video_core/texture/texture_decode.cpp | 20 +++ src/video_core/texture/texture_decode.h | 4 + 9 files changed, 155 insertions(+), 160 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_common.h b/src/video_core/renderer_vulkan/vk_common.h index 89cb7ff10..bd228fd9f 100644 --- a/src/video_core/renderer_vulkan/vk_common.h +++ b/src/video_core/renderer_vulkan/vk_common.h @@ -18,51 +18,3 @@ #define VMA_STATIC_VULKAN_FUNCTIONS 0 #define VMA_DYNAMIC_VULKAN_FUNCTIONS 1 - -namespace Vulkan { - -/// Return the image aspect associated on the provided format -constexpr vk::ImageAspectFlags GetImageAspect(vk::Format format) { - switch (format) { - case vk::Format::eD16UnormS8Uint: - case vk::Format::eD24UnormS8Uint: - case vk::Format::eD32SfloatS8Uint: - return vk::ImageAspectFlagBits::eStencil | vk::ImageAspectFlagBits::eDepth; - break; - case vk::Format::eD16Unorm: - case vk::Format::eX8D24UnormPack32: - case vk::Format::eD32Sfloat: - return vk::ImageAspectFlagBits::eDepth; - break; - default: - return vk::ImageAspectFlagBits::eColor; - } -} - -/// Returns a bit mask with the required usage of a format with a particular aspect -constexpr vk::ImageUsageFlags GetImageUsage(vk::ImageAspectFlags aspect) { - auto usage = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst | - vk::ImageUsageFlagBits::eTransferSrc; - - if (aspect & vk::ImageAspectFlagBits::eDepth) { - return usage | vk::ImageUsageFlagBits::eDepthStencilAttachment; - } else { - return usage | vk::ImageUsageFlagBits::eStorage | vk::ImageUsageFlagBits::eColorAttachment; - } -} - -/// Returns a bit mask with the required features of a format with a particular aspect -constexpr vk::FormatFeatureFlags GetFormatFeatures(vk::ImageAspectFlags aspect) { - auto usage = vk::FormatFeatureFlagBits::eSampledImage | - vk::FormatFeatureFlagBits::eTransferDst | vk::FormatFeatureFlagBits::eTransferSrc | - vk::FormatFeatureFlagBits::eBlitSrc | vk::FormatFeatureFlagBits::eBlitDst; - - if (aspect & vk::ImageAspectFlagBits::eDepth) { - return usage | vk::FormatFeatureFlagBits::eDepthStencilAttachment; - } else { - return usage | vk::FormatFeatureFlagBits::eStorageImage | - vk::FormatFeatureFlagBits::eColorAttachment; - } -} - -} // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index 2ba4620c5..b49d3e205 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -276,6 +276,80 @@ FormatTraits Instance::GetTraits(VideoCore::PixelFormat pixel_format) const { return format_table[index]; } +vk::ImageAspectFlags MakeAspect(VideoCore::SurfaceType type) { + switch (type) { + case VideoCore::SurfaceType::Color: + case VideoCore::SurfaceType::Texture: + case VideoCore::SurfaceType::Fill: + return vk::ImageAspectFlagBits::eColor; + case VideoCore::SurfaceType::Depth: + return vk::ImageAspectFlagBits::eDepth; + case VideoCore::SurfaceType::DepthStencil: + return vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil; + default: + LOG_CRITICAL(Render_Vulkan, "Invalid surface type {}", type); + UNREACHABLE(); + } + + return vk::ImageAspectFlagBits::eColor; +} + +FormatTraits Instance::DetermineTraits(VideoCore::PixelFormat pixel_format, vk::Format format) { + const vk::ImageAspectFlags format_aspect = + MakeAspect(VideoCore::GetFormatType(pixel_format)); + const vk::FormatProperties format_properties = physical_device.getFormatProperties(format); + + const vk::FormatFeatureFlagBits attachment_usage = + (format_aspect & vk::ImageAspectFlagBits::eDepth) + ? vk::FormatFeatureFlagBits::eDepthStencilAttachment + : vk::FormatFeatureFlagBits::eColorAttachmentBlend; + + const vk::FormatFeatureFlags storage_usage = vk::FormatFeatureFlagBits::eStorageImage; + const vk::FormatFeatureFlags transfer_usage = vk::FormatFeatureFlagBits::eSampledImage; + const vk::FormatFeatureFlags blit_usage = + vk::FormatFeatureFlagBits::eBlitSrc | vk::FormatFeatureFlagBits::eBlitDst; + + const bool supports_transfer = + (format_properties.optimalTilingFeatures & transfer_usage) == transfer_usage; + const bool supports_blit = (format_properties.optimalTilingFeatures & blit_usage) == blit_usage; + const bool supports_attachment = + (format_properties.optimalTilingFeatures & attachment_usage) == attachment_usage && + pixel_format != VideoCore::PixelFormat::RGB8; + const bool supports_storage = + (format_properties.optimalTilingFeatures & storage_usage) == storage_usage; + const bool requires_conversion = + // Requires component flip. + pixel_format == VideoCore::PixelFormat::RGBA8 || + // Requires (de)interleaving. + pixel_format == VideoCore::PixelFormat::D24S8; + + // Find the most inclusive usage flags for this format + vk::ImageUsageFlags best_usage; + if (supports_blit || supports_transfer) { + best_usage |= vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst | + vk::ImageUsageFlagBits::eTransferSrc; + } + if (supports_attachment) { + best_usage |= (format_aspect & vk::ImageAspectFlagBits::eDepth) + ? vk::ImageUsageFlagBits::eDepthStencilAttachment + : vk::ImageUsageFlagBits::eColorAttachment; + } + if (supports_storage) { + best_usage |= vk::ImageUsageFlagBits::eStorage; + } + + return FormatTraits{ + .transfer_support = supports_transfer, + .blit_support = supports_blit, + .attachment_support = supports_attachment, + .storage_support = supports_storage, + .requires_conversion = requires_conversion, + .usage = best_usage, + .aspect = format_aspect, + .native = format, + }; +} + void Instance::CreateFormatTable() { constexpr std::array pixel_formats = { VideoCore::PixelFormat::RGBA8, VideoCore::PixelFormat::RGB8, @@ -288,73 +362,32 @@ void Instance::CreateFormatTable() { VideoCore::PixelFormat::D16, VideoCore::PixelFormat::D24, VideoCore::PixelFormat::D24S8}; - const vk::FormatFeatureFlags storage_usage = vk::FormatFeatureFlagBits::eStorageImage; - const vk::FormatFeatureFlags transfer_usage = vk::FormatFeatureFlagBits::eSampledImage; - const vk::FormatFeatureFlags blit_usage = - vk::FormatFeatureFlagBits::eBlitSrc | vk::FormatFeatureFlagBits::eBlitDst; - for (const auto& pixel_format : pixel_formats) { - const vk::Format format = ToVkFormat(pixel_format); - const vk::FormatProperties properties = physical_device.getFormatProperties(format); - const vk::ImageAspectFlags aspect = GetImageAspect(format); + const auto format = ToVkFormat(pixel_format); + FormatTraits traits = DetermineTraits(pixel_format, format); - const vk::FormatFeatureFlagBits attachment_usage = - (aspect & vk::ImageAspectFlagBits::eDepth) - ? vk::FormatFeatureFlagBits::eDepthStencilAttachment - : vk::FormatFeatureFlagBits::eColorAttachmentBlend; - - const bool supports_transfer = - (properties.optimalTilingFeatures & transfer_usage) == transfer_usage; - const bool supports_blit = (properties.optimalTilingFeatures & blit_usage) == blit_usage; - bool supports_attachment = - (properties.optimalTilingFeatures & attachment_usage) == attachment_usage; - const bool supports_storage = - (properties.optimalTilingFeatures & storage_usage) == storage_usage; - - // Find the most inclusive usage flags for this format - vk::ImageUsageFlags best_usage; - if (supports_blit || supports_transfer) { - best_usage |= vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst | - vk::ImageUsageFlagBits::eTransferSrc; - } - if (supports_attachment) { - best_usage |= (aspect & vk::ImageAspectFlagBits::eDepth) - ? vk::ImageUsageFlagBits::eDepthStencilAttachment - : vk::ImageUsageFlagBits::eColorAttachment; - } - if (supports_storage) { - best_usage |= vk::ImageUsageFlagBits::eStorage; - } - - // Always fallback to RGBA8 or D32(S8) for convenience - vk::Format fallback = vk::Format::eR8G8B8A8Unorm; - if (aspect & vk::ImageAspectFlagBits::eDepth) { - fallback = vk::Format::eD32Sfloat; - if (aspect & vk::ImageAspectFlagBits::eStencil) { - fallback = vk::Format::eD32SfloatS8Uint; + const bool is_suitable = + traits.transfer_support && traits.attachment_support && + (traits.blit_support || traits.aspect & vk::ImageAspectFlagBits::eDepth); + // Fall back if the native format is not suitable. + if (!is_suitable) { + // Always fallback to RGBA8 or D32(S8) for convenience + auto fallback = vk::Format::eR8G8B8A8Unorm; + if (traits.aspect & vk::ImageAspectFlagBits::eDepth) { + fallback = vk::Format::eD32Sfloat; + if (traits.aspect & vk::ImageAspectFlagBits::eStencil) { + fallback = vk::Format::eD32SfloatS8Uint; + } } - } - - // Report completely unsupported formats - if (!supports_blit && !supports_attachment && !supports_storage) { LOG_WARNING(Render_Vulkan, "Format {} unsupported, falling back unconditionally to {}", vk::to_string(format), vk::to_string(fallback)); - } - - if (pixel_format == VideoCore::PixelFormat::RGB8) { - supports_attachment = false; + traits = DetermineTraits(pixel_format, fallback); + // Always requires conversion if backing format does not match. + traits.requires_conversion = true; } const u32 index = static_cast(pixel_format); - format_table[index] = FormatTraits{ - .transfer_support = supports_transfer, - .blit_support = supports_blit, - .attachment_support = supports_attachment, - .storage_support = supports_storage, - .usage = best_usage, - .native = format, - .fallback = fallback, - }; + format_table[index] = traits; } } diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h index d81714de6..fa6a11758 100644 --- a/src/video_core/renderer_vulkan/vk_instance.h +++ b/src/video_core/renderer_vulkan/vk_instance.h @@ -23,9 +23,11 @@ struct FormatTraits { bool blit_support = false; ///< True if the format supports blit operations bool attachment_support = false; ///< True if the format supports being used as an attachment bool storage_support = false; ///< True if the format supports storage operations - vk::ImageUsageFlags usage{}; ///< Most supported usage for the native format - vk::Format native = vk::Format::eUndefined; ///< Closest possible native format - vk::Format fallback = vk::Format::eUndefined; ///< Best fallback format + bool requires_conversion = + false; ///< True if the format requires conversion to the native format + vk::ImageUsageFlags usage{}; ///< Most supported usage for the native format + vk::ImageAspectFlags aspect; ///< Aspect flags of the format + vk::Format native = vk::Format::eUndefined; ///< Closest possible native format }; /// The global Vulkan instance @@ -202,7 +204,8 @@ public: private: /// Returns the optimal supported usage for the requested format - vk::FormatFeatureFlags GetFormatFeatures(vk::Format format); + [[nodiscard]] FormatTraits DetermineTraits(VideoCore::PixelFormat pixel_format, + vk::Format format); /// Creates the format compatibility table for the current device void CreateFormatTable(); diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 556209b85..ca0c7680c 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -63,8 +63,10 @@ RasterizerVulkan::RasterizerVulkan(Frontend::EmuWindow& emu_window, const Instan : instance{instance}, scheduler{scheduler}, runtime{runtime}, renderpass_cache{renderpass_cache}, desc_manager{desc_manager}, res_cache{*this, runtime}, pipeline_cache{instance, scheduler, renderpass_cache, desc_manager}, - null_surface{NULL_PARAMS, vk::Format::eR8G8B8A8Unorm, NULL_USAGE, runtime}, - null_storage_surface{NULL_PARAMS, vk::Format::eR32Uint, NULL_STORAGE_USAGE, runtime}, + null_surface{NULL_PARAMS, vk::Format::eR8G8B8A8Unorm, NULL_USAGE, + vk::ImageAspectFlagBits::eColor, runtime}, + null_storage_surface{NULL_PARAMS, vk::Format::eR32Uint, NULL_STORAGE_USAGE, + vk::ImageAspectFlagBits::eColor, runtime}, stream_buffer{instance, scheduler, BUFFER_USAGE, STREAM_BUFFER_SIZE}, texture_buffer{instance, scheduler, TEX_BUFFER_USAGE, TextureBufferSize(instance)}, texture_lf_buffer{instance, scheduler, TEX_BUFFER_USAGE, TextureBufferSize(instance)} { diff --git a/src/video_core/renderer_vulkan/vk_renderpass_cache.cpp b/src/video_core/renderer_vulkan/vk_renderpass_cache.cpp index f8966b28d..8dd41fb91 100644 --- a/src/video_core/renderer_vulkan/vk_renderpass_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_renderpass_cache.cpp @@ -47,15 +47,8 @@ RenderpassCache::RenderpassCache(const Instance& instance, Scheduler& scheduler) const FormatTraits color_traits = instance.GetTraits(ToFormatColor(color)); const FormatTraits depth_traits = instance.GetTraits(ToFormatDepth(depth)); - const vk::Format color_format = color_traits.transfer_support && - color_traits.blit_support && - color_traits.attachment_support - ? color_traits.native - : color_traits.fallback; - const vk::Format depth_format = - depth_traits.transfer_support && depth_traits.attachment_support - ? depth_traits.native - : depth_traits.fallback; + const vk::Format color_format = color_traits.native; + const vk::Format depth_format = depth_traits.native; if (color_format == vk::Format::eUndefined && depth_format == vk::Format::eUndefined) { continue; diff --git a/src/video_core/renderer_vulkan/vk_texture_runtime.cpp b/src/video_core/renderer_vulkan/vk_texture_runtime.cpp index 46351f358..47951a9ae 100644 --- a/src/video_core/renderer_vulkan/vk_texture_runtime.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_runtime.cpp @@ -26,24 +26,6 @@ struct RecordParams { vk::Image dst_image; }; -[[nodiscard]] vk::ImageAspectFlags MakeAspect(VideoCore::SurfaceType type) { - switch (type) { - case VideoCore::SurfaceType::Color: - case VideoCore::SurfaceType::Texture: - case VideoCore::SurfaceType::Fill: - return vk::ImageAspectFlagBits::eColor; - case VideoCore::SurfaceType::Depth: - return vk::ImageAspectFlagBits::eDepth; - case VideoCore::SurfaceType::DepthStencil: - return vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil; - default: - LOG_CRITICAL(Render_Vulkan, "Invalid surface type {}", type); - UNREACHABLE(); - } - - return vk::ImageAspectFlagBits::eColor; -} - [[nodiscard]] vk::Filter MakeFilter(VideoCore::PixelFormat pixel_format) { switch (pixel_format) { case VideoCore::PixelFormat::D16: @@ -93,6 +75,17 @@ u32 UnpackDepthStencil(const StagingData& data, vk::Format dest) { } break; } + case vk::Format::eD32SfloatS8Uint: { + for (; stencil_offset < data.size; depth_offset += 4) { + std::byte* ptr = mapped.data() + depth_offset; + const u32 d24s8 = VideoCore::MakeInt(ptr); + const float d32 = (d24s8 >> 8) / 16777215.f; + mapped[stencil_offset] = static_cast(d24s8 & 0xFF); + std::memcpy(ptr, &d32, 4); + stencil_offset++; + } + break; + } default: LOG_ERROR(Render_Vulkan, "Unimplemtend convertion for depth format {}", vk::to_string(dest)); @@ -172,26 +165,18 @@ void TextureRuntime::Finish() { ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::PixelFormat format, VideoCore::TextureType type) { const FormatTraits traits = instance.GetTraits(format); - const vk::ImageAspectFlags aspect = MakeAspect(VideoCore::GetFormatType(format)); - - // Depth buffers are not supposed to support blit by the spec so don't require it. - const bool is_suitable = traits.transfer_support && traits.attachment_support && - (traits.blit_support || aspect & vk::ImageAspectFlagBits::eDepth); - const vk::Format vk_format = is_suitable ? traits.native : traits.fallback; - const vk::ImageUsageFlags vk_usage = is_suitable ? traits.usage : GetImageUsage(aspect); - - return Allocate(width, height, format, type, vk_format, vk_usage); + return Allocate(width, height, format, type, traits.native, traits.usage, traits.aspect); } MICROPROFILE_DEFINE(Vulkan_ImageAlloc, "Vulkan", "TextureRuntime Finish", MP_RGB(192, 52, 235)); ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::PixelFormat pixel_format, VideoCore::TextureType type, vk::Format format, - vk::ImageUsageFlags usage) { + vk::ImageUsageFlags usage, vk::ImageAspectFlags aspect) { MICROPROFILE_SCOPE(Vulkan_ImageAlloc); ImageAlloc alloc{}; alloc.format = format; - alloc.aspect = GetImageAspect(format); + alloc.aspect = aspect; // The internal format does not provide enough guarantee of texture uniqueness // especially when many pixel formats fallback to RGBA8 @@ -384,6 +369,8 @@ void TextureRuntime::FormatConvert(const Surface& surface, bool upload, std::spa return Pica::Texture::ConvertBGRToRGBA(source, dest); case VideoCore::PixelFormat::RGBA4: return Pica::Texture::ConvertRGBA4ToRGBA8(source, dest); + case VideoCore::PixelFormat::D24: + return Pica::Texture::ConvertD24ToD32(source, dest); default: break; } @@ -395,6 +382,8 @@ void TextureRuntime::FormatConvert(const Surface& surface, bool upload, std::spa return Pica::Texture::ConvertRGBA8ToRGBA4(source, dest); case VideoCore::PixelFormat::RGB8: return Pica::Texture::ConvertRGBAToBGR(source, dest); + case VideoCore::PixelFormat::D24: + return Pica::Texture::ConvertD32ToD24(source, dest); default: break; } @@ -850,10 +839,9 @@ const ReinterpreterList& TextureRuntime::GetPossibleReinterpretations( bool TextureRuntime::NeedsConvertion(VideoCore::PixelFormat format) const { const FormatTraits traits = instance.GetTraits(format); - const VideoCore::SurfaceType type = VideoCore::GetFormatType(format); - return type == VideoCore::SurfaceType::Color && - (format == VideoCore::PixelFormat::RGBA8 || !traits.blit_support || - !traits.attachment_support); + return traits.requires_conversion && + // DepthStencil formats are handled elsewhere due to de-interleaving. + traits.aspect != (vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil); } Surface::Surface(TextureRuntime& runtime) @@ -870,12 +858,12 @@ Surface::Surface(const VideoCore::SurfaceParams& params, TextureRuntime& runtime } Surface::Surface(const VideoCore::SurfaceParams& params, vk::Format format, - vk::ImageUsageFlags usage, TextureRuntime& runtime) + vk::ImageUsageFlags usage, vk::ImageAspectFlags aspect, TextureRuntime& runtime) : VideoCore::SurfaceBase{params}, runtime{runtime}, instance{runtime.GetInstance()}, scheduler{runtime.GetScheduler()} { if (format != vk::Format::eUndefined) { alloc = runtime.Allocate(GetScaledWidth(), GetScaledHeight(), pixel_format, texture_type, - format, usage); + format, usage, aspect); } } @@ -1214,7 +1202,7 @@ void Surface::DepthStencilDownload(const VideoCore::BufferTextureCopy& download, Surface r32_surface{r32_params, vk::Format::eR32Uint, vk::ImageUsageFlagBits::eTransferSrc | vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eStorage, - runtime}; + vk::ImageAspectFlagBits::eColor, runtime}; const VideoCore::TextureBlit blit = { .src_level = download.texture_level, diff --git a/src/video_core/renderer_vulkan/vk_texture_runtime.h b/src/video_core/renderer_vulkan/vk_texture_runtime.h index c416d3917..a3ba85d8d 100644 --- a/src/video_core/renderer_vulkan/vk_texture_runtime.h +++ b/src/video_core/renderer_vulkan/vk_texture_runtime.h @@ -106,7 +106,7 @@ public: /// Allocates a vulkan image [[nodiscard]] ImageAlloc Allocate(u32 width, u32 height, VideoCore::PixelFormat pixel_format, VideoCore::TextureType type, vk::Format format, - vk::ImageUsageFlags usage); + vk::ImageUsageFlags usage, vk::ImageAspectFlags aspect); /// Performs required format convertions on the staging data void FormatConvert(const Surface& surface, bool upload, std::span source, @@ -173,7 +173,7 @@ public: Surface(TextureRuntime& runtime); Surface(const VideoCore::SurfaceParams& params, TextureRuntime& runtime); Surface(const VideoCore::SurfaceParams& params, vk::Format format, vk::ImageUsageFlags usage, - TextureRuntime& runtime); + vk::ImageAspectFlags aspect, TextureRuntime& runtime); ~Surface() override; /// Uploads pixel data in staging to a rectangle region of the surface texture diff --git a/src/video_core/texture/texture_decode.cpp b/src/video_core/texture/texture_decode.cpp index 216516f43..b10a52c2a 100644 --- a/src/video_core/texture/texture_decode.cpp +++ b/src/video_core/texture/texture_decode.cpp @@ -300,6 +300,26 @@ void ConvertRGBA8ToRGB5A1(std::span source, std::span source, std::span dest) { + u32 j = 0; + for (std::size_t i = 0; i < dest.size(); i += 4) { + auto d32 = + Common::Color::DecodeD24(reinterpret_cast(source.data() + j)) / 16777215.f; + std::memcpy(dest.data() + i, &d32, sizeof(d32)); + j += 3; + } +} + +void ConvertD32ToD24(std::span source, std::span dest) { + u32 j = 0; + for (std::size_t i = 0; i < dest.size(); i += 3) { + float d32; + std::memcpy(&d32, source.data() + j, sizeof(d32)); + Common::Color::EncodeD24(d32 * 0xFFFFFF, reinterpret_cast(dest.data() + i)); + j += 4; + } +} + void ConvertD32S8ToD24S8(std::span source, std::span dest) { std::size_t depth_offset = 0; std::size_t stencil_offset = 4 * source.size() / 5; diff --git a/src/video_core/texture/texture_decode.h b/src/video_core/texture/texture_decode.h index bc27aaaf2..ef161110a 100644 --- a/src/video_core/texture/texture_decode.h +++ b/src/video_core/texture/texture_decode.h @@ -89,6 +89,10 @@ void ConvertRGB5A1ToRGBA8(std::span source, std::span source, std::span dest); +void ConvertD24ToD32(std::span source, std::span dest); + +void ConvertD32ToD24(std::span source, std::span dest); + void ConvertD32S8ToD24S8(std::span source, std::span dest); void InterleaveD24S8(std::span source, std::span dest);