diff --git a/CMakeLists.txt b/CMakeLists.txt index 0bd38f642..4fc910427 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -453,6 +453,8 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp src/video_core/renderer_vulkan/vk_swapchain.h src/video_core/texture_cache/image.cpp src/video_core/texture_cache/image.h + src/video_core/texture_cache/image_info.cpp + src/video_core/texture_cache/image_info.h src/video_core/texture_cache/image_view.cpp src/video_core/texture_cache/image_view.h src/video_core/texture_cache/sampler.cpp diff --git a/src/video_core/texture_cache/image.cpp b/src/video_core/texture_cache/image.cpp index 5192bd65e..f4ba2088c 100644 --- a/src/video_core/texture_cache/image.cpp +++ b/src/video_core/texture_cache/image.cpp @@ -2,7 +2,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/assert.h" -#include "common/config.h" #include "video_core/renderer_vulkan/liverpool_to_vk.h" #include "video_core/renderer_vulkan/vk_instance.h" #include "video_core/renderer_vulkan/vk_scheduler.h" @@ -14,25 +13,8 @@ namespace VideoCore { using namespace Vulkan; -using VideoOutFormat = Libraries::VideoOut::PixelFormat; using Libraries::VideoOut::TilingMode; -static vk::Format ConvertPixelFormat(const VideoOutFormat format) { - switch (format) { - case VideoOutFormat::A8R8G8B8Srgb: - return vk::Format::eB8G8R8A8Srgb; - case VideoOutFormat::A8B8G8R8Srgb: - return vk::Format::eR8G8B8A8Srgb; - case VideoOutFormat::A2R10G10B10: - case VideoOutFormat::A2R10G10B10Srgb: - return vk::Format::eA2R10G10B10UnormPack32; - default: - break; - } - UNREACHABLE_MSG("Unknown format={}", static_cast(format)); - return {}; -} - bool ImageInfo::IsBlockCoded() const { switch (pixel_format) { case vk::Format::eBc1RgbaSrgbBlock: @@ -101,93 +83,6 @@ static vk::ImageUsageFlags ImageUsageFlags(const ImageInfo& info) { return usage; } -static vk::ImageType ConvertImageType(AmdGpu::ImageType type) noexcept { - switch (type) { - case AmdGpu::ImageType::Color1D: - case AmdGpu::ImageType::Color1DArray: - return vk::ImageType::e1D; - case AmdGpu::ImageType::Color2D: - case AmdGpu::ImageType::Cube: - case AmdGpu::ImageType::Color2DArray: - return vk::ImageType::e2D; - case AmdGpu::ImageType::Color3D: - return vk::ImageType::e3D; - default: - UNREACHABLE(); - } -} - -ImageInfo::ImageInfo(const Libraries::VideoOut::BufferAttributeGroup& group) noexcept { - const auto& attrib = group.attrib; - is_tiled = attrib.tiling_mode == TilingMode::Tile; - tiling_mode = - is_tiled ? AmdGpu::TilingMode::Display_MacroTiled : AmdGpu::TilingMode::Display_Linear; - pixel_format = ConvertPixelFormat(attrib.pixel_format); - type = vk::ImageType::e2D; - size.width = attrib.width; - size.height = attrib.height; - pitch = attrib.tiling_mode == TilingMode::Linear ? size.width : (size.width + 127) & (~127); - const bool is_32bpp = attrib.pixel_format != VideoOutFormat::A16R16G16B16Float; - ASSERT(is_32bpp); - if (!is_tiled) { - guest_size_bytes = pitch * size.height * 4; - return; - } - if (Config::isNeoMode()) { - guest_size_bytes = pitch * ((size.height + 127) & (~127)) * 4; - } else { - guest_size_bytes = pitch * ((size.height + 63) & (~63)) * 4; - } - usage.vo_buffer = true; -} - -ImageInfo::ImageInfo(const AmdGpu::Liverpool::ColorBuffer& buffer, - const AmdGpu::Liverpool::CbDbExtent& hint /*= {}*/) noexcept { - is_tiled = buffer.IsTiled(); - tiling_mode = buffer.GetTilingMode(); - pixel_format = LiverpoolToVK::SurfaceFormat(buffer.info.format, buffer.NumFormat()); - num_samples = 1 << buffer.attrib.num_fragments_log2; - type = vk::ImageType::e2D; - size.width = hint.Valid() ? hint.width : buffer.Pitch(); - size.height = hint.Valid() ? hint.height : buffer.Height(); - size.depth = 1; - pitch = size.width; - guest_size_bytes = buffer.GetColorSliceSize(); - meta_info.cmask_addr = buffer.info.fast_clear ? buffer.CmaskAddress() : 0; - meta_info.fmask_addr = buffer.info.compression ? buffer.FmaskAddress() : 0; - usage.render_target = true; -} - -ImageInfo::ImageInfo(const AmdGpu::Liverpool::DepthBuffer& buffer, VAddr htile_address, - const AmdGpu::Liverpool::CbDbExtent& hint) noexcept { - is_tiled = false; - pixel_format = LiverpoolToVK::DepthFormat(buffer.z_info.format, buffer.stencil_info.format); - type = vk::ImageType::e2D; - num_samples = 1 << buffer.z_info.num_samples; // spec doesn't say it is a log2 - size.width = hint.Valid() ? hint.width : buffer.Pitch(); - size.height = hint.Valid() ? hint.height : buffer.Height(); - size.depth = 1; - pitch = size.width; - guest_size_bytes = buffer.GetDepthSliceSize(); - meta_info.htile_addr = buffer.z_info.tile_surface_en ? htile_address : 0; - usage.depth_target = true; -} - -ImageInfo::ImageInfo(const AmdGpu::Image& image) noexcept { - is_tiled = image.IsTiled(); - tiling_mode = image.GetTilingMode(); - pixel_format = LiverpoolToVK::SurfaceFormat(image.GetDataFmt(), image.GetNumberFmt()); - type = ConvertImageType(image.GetType()); - size.width = image.width + 1; - size.height = image.height + 1; - size.depth = 1; - pitch = image.Pitch(); - resources.levels = image.NumLevels(); - resources.layers = image.NumLayers(); - guest_size_bytes = image.GetSize(); - usage.texture = true; -} - UniqueImage::UniqueImage(vk::Device device_, VmaAllocator allocator_) : device{device_}, allocator{allocator_} {} diff --git a/src/video_core/texture_cache/image.h b/src/video_core/texture_cache/image.h index e91f1b589..fceeddf99 100644 --- a/src/video_core/texture_cache/image.h +++ b/src/video_core/texture_cache/image.h @@ -9,6 +9,7 @@ #include "video_core/amdgpu/liverpool.h" #include "video_core/amdgpu/resource.h" #include "video_core/renderer_vulkan/vk_common.h" +#include "video_core/texture_cache/image_info.h" #include "video_core/texture_cache/image_view.h" #include "video_core/texture_cache/types.h" @@ -34,47 +35,6 @@ enum ImageFlagBits : u32 { }; DECLARE_ENUM_FLAG_OPERATORS(ImageFlagBits) -struct ImageInfo { - ImageInfo() = default; - explicit ImageInfo(const Libraries::VideoOut::BufferAttributeGroup& group) noexcept; - explicit ImageInfo(const AmdGpu::Liverpool::ColorBuffer& buffer, - const AmdGpu::Liverpool::CbDbExtent& hint = {}) noexcept; - explicit ImageInfo(const AmdGpu::Liverpool::DepthBuffer& buffer, VAddr htile_address, - const AmdGpu::Liverpool::CbDbExtent& hint = {}) noexcept; - explicit ImageInfo(const AmdGpu::Image& image) noexcept; - - bool IsTiled() const { - return tiling_mode != AmdGpu::TilingMode::Display_Linear; - } - bool IsBlockCoded() const; - bool IsPacked() const; - bool IsDepthStencil() const; - - struct { - VAddr cmask_addr; - VAddr fmask_addr; - VAddr htile_addr; - } meta_info{}; - - struct { - u32 texture : 1; - u32 storage : 1; - u32 render_target : 1; - u32 depth_target : 1; - u32 vo_buffer : 1; - } usage{}; // Usage data tracked during image lifetime - - bool is_tiled = false; - vk::Format pixel_format = vk::Format::eUndefined; - vk::ImageType type = vk::ImageType::e1D; - SubresourceExtent resources; - Extent3D size{1, 1, 1}; - u32 num_samples = 1; - u32 pitch = 0; - u32 guest_size_bytes = 0; - AmdGpu::TilingMode tiling_mode{AmdGpu::TilingMode::Display_Linear}; -}; - struct UniqueImage { explicit UniqueImage(vk::Device device, VmaAllocator allocator); ~UniqueImage(); diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp new file mode 100644 index 000000000..12df14c01 --- /dev/null +++ b/src/video_core/texture_cache/image_info.cpp @@ -0,0 +1,118 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/assert.h" +#include "common/config.h" +#include "video_core/renderer_vulkan/liverpool_to_vk.h" +#include "video_core/texture_cache/image_info.h" + +namespace VideoCore { + +using namespace Vulkan; +using Libraries::VideoOut::TilingMode; +using VideoOutFormat = Libraries::VideoOut::PixelFormat; + +static vk::Format ConvertPixelFormat(const VideoOutFormat format) { + switch (format) { + case VideoOutFormat::A8R8G8B8Srgb: + return vk::Format::eB8G8R8A8Srgb; + case VideoOutFormat::A8B8G8R8Srgb: + return vk::Format::eR8G8B8A8Srgb; + case VideoOutFormat::A2R10G10B10: + case VideoOutFormat::A2R10G10B10Srgb: + return vk::Format::eA2R10G10B10UnormPack32; + default: + break; + } + UNREACHABLE_MSG("Unknown format={}", static_cast(format)); + return {}; +} + +static vk::ImageType ConvertImageType(AmdGpu::ImageType type) noexcept { + switch (type) { + case AmdGpu::ImageType::Color1D: + case AmdGpu::ImageType::Color1DArray: + return vk::ImageType::e1D; + case AmdGpu::ImageType::Color2D: + case AmdGpu::ImageType::Cube: + case AmdGpu::ImageType::Color2DArray: + return vk::ImageType::e2D; + case AmdGpu::ImageType::Color3D: + return vk::ImageType::e3D; + default: + UNREACHABLE(); + } +} + +ImageInfo::ImageInfo(const Libraries::VideoOut::BufferAttributeGroup& group) noexcept { + const auto& attrib = group.attrib; + is_tiled = attrib.tiling_mode == TilingMode::Tile; + tiling_mode = + is_tiled ? AmdGpu::TilingMode::Display_MacroTiled : AmdGpu::TilingMode::Display_Linear; + pixel_format = ConvertPixelFormat(attrib.pixel_format); + type = vk::ImageType::e2D; + size.width = attrib.width; + size.height = attrib.height; + pitch = attrib.tiling_mode == TilingMode::Linear ? size.width : (size.width + 127) & (~127); + const bool is_32bpp = attrib.pixel_format != VideoOutFormat::A16R16G16B16Float; + ASSERT(is_32bpp); + if (!is_tiled) { + guest_size_bytes = pitch * size.height * 4; + return; + } + if (Config::isNeoMode()) { + guest_size_bytes = pitch * ((size.height + 127) & (~127)) * 4; + } else { + guest_size_bytes = pitch * ((size.height + 63) & (~63)) * 4; + } + usage.vo_buffer = true; +} + +ImageInfo::ImageInfo(const AmdGpu::Liverpool::ColorBuffer& buffer, + const AmdGpu::Liverpool::CbDbExtent& hint /*= {}*/) noexcept { + is_tiled = buffer.IsTiled(); + tiling_mode = buffer.GetTilingMode(); + pixel_format = LiverpoolToVK::SurfaceFormat(buffer.info.format, buffer.NumFormat()); + num_samples = 1 << buffer.attrib.num_fragments_log2; + type = vk::ImageType::e2D; + size.width = hint.Valid() ? hint.width : buffer.Pitch(); + size.height = hint.Valid() ? hint.height : buffer.Height(); + size.depth = 1; + pitch = size.width; + guest_size_bytes = buffer.GetColorSliceSize(); + meta_info.cmask_addr = buffer.info.fast_clear ? buffer.CmaskAddress() : 0; + meta_info.fmask_addr = buffer.info.compression ? buffer.FmaskAddress() : 0; + usage.render_target = true; +} + +ImageInfo::ImageInfo(const AmdGpu::Liverpool::DepthBuffer& buffer, VAddr htile_address, + const AmdGpu::Liverpool::CbDbExtent& hint) noexcept { + is_tiled = false; + pixel_format = LiverpoolToVK::DepthFormat(buffer.z_info.format, buffer.stencil_info.format); + type = vk::ImageType::e2D; + num_samples = 1 << buffer.z_info.num_samples; // spec doesn't say it is a log2 + size.width = hint.Valid() ? hint.width : buffer.Pitch(); + size.height = hint.Valid() ? hint.height : buffer.Height(); + size.depth = 1; + pitch = size.width; + guest_size_bytes = buffer.GetDepthSliceSize(); + meta_info.htile_addr = buffer.z_info.tile_surface_en ? htile_address : 0; + usage.depth_target = true; +} + +ImageInfo::ImageInfo(const AmdGpu::Image& image) noexcept { + is_tiled = image.IsTiled(); + tiling_mode = image.GetTilingMode(); + pixel_format = LiverpoolToVK::SurfaceFormat(image.GetDataFmt(), image.GetNumberFmt()); + type = ConvertImageType(image.GetType()); + size.width = image.width + 1; + size.height = image.height + 1; + size.depth = 1; + pitch = image.Pitch(); + resources.levels = image.NumLevels(); + resources.layers = image.NumLayers(); + guest_size_bytes = image.GetSize(); + usage.texture = true; +} + +} // namespace VideoCore diff --git a/src/video_core/texture_cache/image_info.h b/src/video_core/texture_cache/image_info.h new file mode 100644 index 000000000..a473896c1 --- /dev/null +++ b/src/video_core/texture_cache/image_info.h @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/enum.h" +#include "common/types.h" +#include "core/libraries/videoout/buffer.h" +#include "video_core/amdgpu/liverpool.h" +#include "video_core/texture_cache/types.h" + +namespace VideoCore { + +struct ImageInfo { + ImageInfo() = default; + explicit ImageInfo(const Libraries::VideoOut::BufferAttributeGroup& group) noexcept; + explicit ImageInfo(const AmdGpu::Liverpool::ColorBuffer& buffer, + const AmdGpu::Liverpool::CbDbExtent& hint = {}) noexcept; + explicit ImageInfo(const AmdGpu::Liverpool::DepthBuffer& buffer, VAddr htile_address, + const AmdGpu::Liverpool::CbDbExtent& hint = {}) noexcept; + explicit ImageInfo(const AmdGpu::Image& image) noexcept; + + bool IsTiled() const { + return tiling_mode != AmdGpu::TilingMode::Display_Linear; + } + bool IsBlockCoded() const; + bool IsPacked() const; + bool IsDepthStencil() const; + + struct { + VAddr cmask_addr; + VAddr fmask_addr; + VAddr htile_addr; + } meta_info{}; + + struct { + u32 texture : 1; + u32 storage : 1; + u32 render_target : 1; + u32 depth_target : 1; + u32 stencil : 1; + u32 vo_buffer : 1; + } usage{}; // Usage data tracked during image lifetime + + bool is_tiled = false; + vk::Format pixel_format = vk::Format::eUndefined; + vk::ImageType type = vk::ImageType::e1D; + SubresourceExtent resources; + Extent3D size{1, 1, 1}; + u32 num_samples = 1; + u32 pitch = 0; + u32 guest_size_bytes = 0; + AmdGpu::TilingMode tiling_mode{AmdGpu::TilingMode::Display_Linear}; +}; + +} // namespace VideoCore