renderer_vulkan: Centralize pixel format trait management. (#18)
* renderer_vulkan: Centralize pixel format trait management. * renderer_vulkan: Add D24 <-> D32 conversion support.
This commit is contained in:
@ -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
|
||||
|
@ -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<u32>(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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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)} {
|
||||
|
@ -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;
|
||||
|
@ -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<u32>(ptr);
|
||||
const float d32 = (d24s8 >> 8) / 16777215.f;
|
||||
mapped[stencil_offset] = static_cast<std::byte>(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<Surface>{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,
|
||||
|
@ -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<std::byte> 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
|
||||
|
@ -300,6 +300,26 @@ void ConvertRGBA8ToRGB5A1(std::span<const std::byte> source, std::span<std::byte
|
||||
}
|
||||
}
|
||||
|
||||
void ConvertD24ToD32(std::span<const std::byte> source, std::span<std::byte> dest) {
|
||||
u32 j = 0;
|
||||
for (std::size_t i = 0; i < dest.size(); i += 4) {
|
||||
auto d32 =
|
||||
Common::Color::DecodeD24(reinterpret_cast<const u8*>(source.data() + j)) / 16777215.f;
|
||||
std::memcpy(dest.data() + i, &d32, sizeof(d32));
|
||||
j += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void ConvertD32ToD24(std::span<const std::byte> source, std::span<std::byte> 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<u8*>(dest.data() + i));
|
||||
j += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void ConvertD32S8ToD24S8(std::span<const std::byte> source, std::span<std::byte> dest) {
|
||||
std::size_t depth_offset = 0;
|
||||
std::size_t stencil_offset = 4 * source.size() / 5;
|
||||
|
@ -89,6 +89,10 @@ void ConvertRGB5A1ToRGBA8(std::span<const std::byte> source, std::span<std::byte
|
||||
|
||||
void ConvertRGBA8ToRGB5A1(std::span<const std::byte> source, std::span<std::byte> dest);
|
||||
|
||||
void ConvertD24ToD32(std::span<const std::byte> source, std::span<std::byte> dest);
|
||||
|
||||
void ConvertD32ToD24(std::span<const std::byte> source, std::span<std::byte> dest);
|
||||
|
||||
void ConvertD32S8ToD24S8(std::span<const std::byte> source, std::span<std::byte> dest);
|
||||
|
||||
void InterleaveD24S8(std::span<const std::byte> source, std::span<std::byte> dest);
|
||||
|
Reference in New Issue
Block a user