summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/video_core/renderer_vulkan/maxwell_to_vk.cpp27
-rw-r--r--src/video_core/renderer_vulkan/maxwell_to_vk.h10
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp73
3 files changed, 72 insertions, 38 deletions
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
index ca7c2c579..b4473f194 100644
--- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
+++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
@@ -110,8 +110,8 @@ VkCompareOp DepthCompareFunction(Tegra::Texture::DepthCompareFunc depth_compare_
} // namespace Sampler
namespace {
-
-enum : u32 { Attachable = 1, Storage = 2 };
+constexpr u32 Attachable = 1 << 0;
+constexpr u32 Storage = 1 << 1;
struct FormatTuple {
VkFormat format; ///< Vulkan format
@@ -222,22 +222,27 @@ constexpr bool IsZetaFormat(PixelFormat pixel_format) {
} // Anonymous namespace
-FormatInfo SurfaceFormat(const Device& device, FormatType format_type, PixelFormat pixel_format) {
- ASSERT(static_cast<std::size_t>(pixel_format) < std::size(tex_format_tuples));
-
- auto tuple = tex_format_tuples[static_cast<std::size_t>(pixel_format)];
+FormatInfo SurfaceFormat(const Device& device, FormatType format_type, bool with_srgb,
+ PixelFormat pixel_format) {
+ ASSERT(static_cast<size_t>(pixel_format) < std::size(tex_format_tuples));
+ FormatTuple tuple = tex_format_tuples[static_cast<size_t>(pixel_format)];
if (tuple.format == VK_FORMAT_UNDEFINED) {
UNIMPLEMENTED_MSG("Unimplemented texture format with pixel format={}", pixel_format);
- return {VK_FORMAT_A8B8G8R8_UNORM_PACK32, true, true};
+ return FormatInfo{VK_FORMAT_A8B8G8R8_UNORM_PACK32, true, true};
}
// Use A8B8G8R8_UNORM on hardware that doesn't support ASTC natively
if (!device.IsOptimalAstcSupported() && VideoCore::Surface::IsPixelFormatASTC(pixel_format)) {
- const bool is_srgb = VideoCore::Surface::IsPixelFormatSRGB(pixel_format);
- tuple.format = is_srgb ? VK_FORMAT_A8B8G8R8_SRGB_PACK32 : VK_FORMAT_A8B8G8R8_UNORM_PACK32;
+ const bool is_srgb = with_srgb && VideoCore::Surface::IsPixelFormatSRGB(pixel_format);
+ if (is_srgb) {
+ tuple.format = VK_FORMAT_A8B8G8R8_SRGB_PACK32;
+ } else {
+ tuple.format = VK_FORMAT_A8B8G8R8_UNORM_PACK32;
+ tuple.usage |= Storage;
+ }
}
- const bool attachable = tuple.usage & Attachable;
- const bool storage = tuple.usage & Storage;
+ const bool attachable = (tuple.usage & Attachable) != 0;
+ const bool storage = (tuple.usage & Storage) != 0;
VkFormatFeatureFlags usage{};
switch (format_type) {
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.h b/src/video_core/renderer_vulkan/maxwell_to_vk.h
index 537969840..e59e6b6e2 100644
--- a/src/video_core/renderer_vulkan/maxwell_to_vk.h
+++ b/src/video_core/renderer_vulkan/maxwell_to_vk.h
@@ -35,7 +35,15 @@ struct FormatInfo {
bool storage;
};
-FormatInfo SurfaceFormat(const Device& device, FormatType format_type, PixelFormat pixel_format);
+/**
+ * Returns format properties supported in the host
+ * @param device Host device
+ * @param format_type Type of image the buffer will use
+ * @param with_srgb True when the format can be sRGB when converted to another format (ASTC)
+ * @param pixel_format Guest pixel format to describe
+ */
+[[nodiscard]] FormatInfo SurfaceFormat(const Device& device, FormatType format_type, bool with_srgb,
+ PixelFormat pixel_format);
VkShaderStageFlagBits ShaderStage(Tegra::Engines::ShaderType stage);
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index ab14922d7..aa7c5d7c6 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -95,20 +95,12 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
}
}
-[[nodiscard]] VkImageCreateInfo MakeImageCreateInfo(const Device& device, const ImageInfo& info) {
- const auto format_info = MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, info.format);
- VkImageCreateFlags flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
- if (info.type == ImageType::e2D && info.resources.layers >= 6 &&
- info.size.width == info.size.height) {
- flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
- }
- if (info.type == ImageType::e3D) {
- flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
- }
+[[nodiscard]] VkImageUsageFlags ImageUsageFlags(const MaxwellToVK::FormatInfo& info,
+ PixelFormat format) {
VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT;
- if (format_info.attachable) {
- switch (VideoCore::Surface::GetFormatType(info.format)) {
+ if (info.attachable) {
+ switch (VideoCore::Surface::GetFormatType(format)) {
case VideoCore::Surface::SurfaceType::ColorTexture:
usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
break;
@@ -120,9 +112,33 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
UNREACHABLE_MSG("Invalid surface type");
}
}
- if (format_info.storage) {
+ if (info.storage) {
usage |= VK_IMAGE_USAGE_STORAGE_BIT;
}
+ return usage;
+}
+
+/// Returns the preferred format for a VkImage
+[[nodiscard]] PixelFormat StorageFormat(PixelFormat format) {
+ switch (format) {
+ case PixelFormat::A8B8G8R8_SRGB:
+ return PixelFormat::A8B8G8R8_UNORM;
+ default:
+ return format;
+ }
+}
+
+[[nodiscard]] VkImageCreateInfo MakeImageCreateInfo(const Device& device, const ImageInfo& info) {
+ const PixelFormat format = StorageFormat(info.format);
+ const auto format_info = MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, false, format);
+ VkImageCreateFlags flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
+ if (info.type == ImageType::e2D && info.resources.layers >= 6 &&
+ info.size.width == info.size.height) {
+ flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
+ }
+ if (info.type == ImageType::e3D) {
+ flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
+ }
const auto [samples_x, samples_y] = VideoCommon::SamplesLog2(info.num_samples);
return VkImageCreateInfo{
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
@@ -130,17 +146,16 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
.flags = flags,
.imageType = ConvertImageType(info.type),
.format = format_info.format,
- .extent =
- {
- .width = info.size.width >> samples_x,
- .height = info.size.height >> samples_y,
- .depth = info.size.depth,
- },
+ .extent{
+ .width = info.size.width >> samples_x,
+ .height = info.size.height >> samples_y,
+ .depth = info.size.depth,
+ },
.mipLevels = static_cast<u32>(info.resources.levels),
.arrayLayers = static_cast<u32>(info.resources.layers),
.samples = ConvertSampleCount(info.num_samples),
.tiling = VK_IMAGE_TILING_OPTIMAL,
- .usage = usage,
+ .usage = ImageUsageFlags(format_info, format),
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 0,
.pQueueFamilyIndices = nullptr,
@@ -209,10 +224,11 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
[[nodiscard]] VkAttachmentDescription AttachmentDescription(const Device& device,
const ImageView* image_view) {
- const auto pixel_format = image_view->format;
+ using MaxwellToVK::SurfaceFormat;
+ const PixelFormat pixel_format = image_view->format;
return VkAttachmentDescription{
.flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT,
- .format = MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, pixel_format).format,
+ .format = SurfaceFormat(device, FormatType::Optimal, true, pixel_format).format,
.samples = image_view->Samples(),
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
@@ -868,11 +884,16 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
std::ranges::transform(swizzle, swizzle.begin(), ConvertGreenRed);
}
}
- const VkFormat vk_format =
- MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, format).format;
+ const auto format_info = MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, true, format);
+ const VkFormat vk_format = format_info.format;
+ const VkImageViewUsageCreateInfo image_view_usage{
+ .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
+ .pNext = nullptr,
+ .usage = ImageUsageFlags(format_info, format),
+ };
const VkImageViewCreateInfo create_info{
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
- .pNext = nullptr,
+ .pNext = &image_view_usage,
.flags = 0,
.image = image.Handle(),
.viewType = VkImageViewType{},
@@ -962,7 +983,7 @@ vk::ImageView ImageView::MakeDepthStencilView(VkImageAspectFlags aspect_mask) {
.flags = 0,
.image = image_handle,
.viewType = ImageViewType(type),
- .format = MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, format).format,
+ .format = MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, true, format).format,
.components{
.r = VK_COMPONENT_SWIZZLE_IDENTITY,
.g = VK_COMPONENT_SWIZZLE_IDENTITY,