Browse Source

[TEST] Adjust mutable formats usage

temporary-branch
CamilleLaVey 4 days ago
parent
commit
328a2c1081
  1. 62
      src/video_core/renderer_vulkan/vk_texture_cache.cpp
  2. 1
      src/video_core/renderer_vulkan/vk_texture_cache.h

62
src/video_core/renderer_vulkan/vk_texture_cache.cpp

@ -8,6 +8,7 @@
#include <array> #include <array>
#include <optional> #include <optional>
#include <span> #include <span>
#include <utility>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <boost/container/small_vector.hpp> #include <boost/container/small_vector.hpp>
@ -163,6 +164,11 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT; flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
} }
const auto [samples_x, samples_y] = VideoCommon::SamplesLog2(info.num_samples); const auto [samples_x, samples_y] = VideoCommon::SamplesLog2(info.num_samples);
const VkSampleCountFlagBits samples = ConvertSampleCount(info.num_samples);
VkImageUsageFlags usage = ImageUsageFlags(format_info, info.format);
if (samples != VK_SAMPLE_COUNT_1_BIT && !device.IsStorageImageMultisampleSupported()) {
usage &= ~static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_STORAGE_BIT);
}
return VkImageCreateInfo{ return VkImageCreateInfo{
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
@ -176,9 +182,9 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
}, },
.mipLevels = static_cast<u32>(info.resources.levels), .mipLevels = static_cast<u32>(info.resources.levels),
.arrayLayers = static_cast<u32>(info.resources.layers), .arrayLayers = static_cast<u32>(info.resources.layers),
.samples = ConvertSampleCount(info.num_samples),
.samples = samples,
.tiling = VK_IMAGE_TILING_OPTIMAL, .tiling = VK_IMAGE_TILING_OPTIMAL,
.usage = ImageUsageFlags(format_info, info.format),
.usage = usage,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE, .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 0, .queueFamilyIndexCount = 0,
.pQueueFamilyIndices = nullptr, .pQueueFamilyIndices = nullptr,
@ -200,19 +206,27 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
.pViewFormats = view_formats.data(), .pViewFormats = view_formats.data(),
}; };
if (view_formats.size() > 1) { if (view_formats.size() > 1) {
image_ci.flags |=
VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT;
image_ci.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
const bool has_storage_compatible_view = const bool has_storage_compatible_view =
std::any_of(view_formats.begin(), view_formats.end(), [&device](VkFormat view_format) { std::any_of(view_formats.begin(), view_formats.end(), [&device](VkFormat view_format) {
return device.IsFormatSupported(view_format, VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT, return device.IsFormatSupported(view_format, VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT,
FormatType::Optimal); FormatType::Optimal);
}); });
// storageImageSampleCounts is only meaningful once shaderStorageImageMultisample is on;
// that feature is what the spec actually gates multisampled storage usage on.
const bool storage_allowed_for_samples = const bool storage_allowed_for_samples =
image_ci.samples == VK_SAMPLE_COUNT_1_BIT || image_ci.samples == VK_SAMPLE_COUNT_1_BIT ||
(device.GetStorageImageSampleCounts() &
static_cast<VkSampleCountFlags>(image_ci.samples)) != 0;
(device.IsStorageImageMultisampleSupported() &&
(device.GetStorageImageSampleCounts() &
static_cast<VkSampleCountFlags>(image_ci.samples)) != 0);
if (has_storage_compatible_view && storage_allowed_for_samples) { if (has_storage_compatible_view && storage_allowed_for_samples) {
// Requesting a usage the image's own format cannot support is the only thing here
// that needs extended usage; views narrow their own usage on creation.
if (!device.IsFormatSupported(image_ci.format, VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT,
FormatType::Optimal)) {
image_ci.flags |= VK_IMAGE_CREATE_EXTENDED_USAGE_BIT;
}
image_ci.usage |= VK_IMAGE_USAGE_STORAGE_BIT; image_ci.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
} }
@ -223,6 +237,25 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
return allocator.CreateImage(image_ci); return allocator.CreateImage(image_ci);
} }
[[nodiscard]] VkImageUsageFlags ViewUsageFlags(const Device& device, VkImageUsageFlags image_usage,
VkFormat view_format) {
static constexpr std::array<std::pair<VkImageUsageFlags, VkFormatFeatureFlags>, 4> CHECKS{{
{VK_IMAGE_USAGE_SAMPLED_BIT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT},
{VK_IMAGE_USAGE_STORAGE_BIT, VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT},
{VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT},
{VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT},
}};
VkImageUsageFlags usage = image_usage;
for (const auto& [usage_bit, feature] : CHECKS) {
if ((usage & usage_bit) != 0 &&
!device.IsFormatSupported(view_format, feature, FormatType::Optimal)) {
usage &= ~usage_bit;
}
}
return usage;
}
[[nodiscard]] vk::ImageView MakeStorageView(const vk::Device& device, u32 level, VkImage image, [[nodiscard]] vk::ImageView MakeStorageView(const vk::Device& device, u32 level, VkImage image,
VkFormat format) { VkFormat format) {
static constexpr VkImageViewUsageCreateInfo storage_image_view_usage_create_info{ static constexpr VkImageViewUsageCreateInfo storage_image_view_usage_create_info{
@ -2429,7 +2462,7 @@ bool Image::NeedsScaleHelper() const {
ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info, ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info,
ImageId image_id_, Image& image) ImageId image_id_, Image& image)
: VideoCommon::ImageViewBase{info, image.info, image_id_, image.gpu_addr}, : VideoCommon::ImageViewBase{info, image.info, image_id_, image.gpu_addr},
device{&runtime.device}, image_handle{image.Handle()},
device{&runtime.device}, image_handle{image.Handle()}, image_usage{image.UsageFlags()},
samples(ConvertSampleCount(image.info.num_samples)) { samples(ConvertSampleCount(image.info.num_samples)) {
using Shader::TextureType; using Shader::TextureType;
@ -2547,6 +2580,7 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageV
null_image = MakeImage(*device, runtime.memory_allocator, info, {}); null_image = MakeImage(*device, runtime.memory_allocator, info, {});
image_handle = *null_image; image_handle = *null_image;
image_usage = null_image.UsageFlags();
for (u32 i = 0; i < Shader::NUM_TEXTURE_TYPES; i++) { for (u32 i = 0; i < Shader::NUM_TEXTURE_TYPES; i++) {
image_views[i] = MakeView(VK_FORMAT_A8B8G8R8_UNORM_PACK32, VK_IMAGE_ASPECT_COLOR_BIT); image_views[i] = MakeView(VK_FORMAT_A8B8G8R8_UNORM_PACK32, VK_IMAGE_ASPECT_COLOR_BIT);
} }
@ -2633,9 +2667,21 @@ vk::ImageView ImageView::MakeView(VkFormat vk_format, VkImageAspectFlags aspect_
break; break;
} }
} }
// Only attach the narrowing struct when it actually drops something and still leaves a usage
// a view can be built around; otherwise keep inheriting the image's usage as before.
static constexpr VkImageUsageFlags VIEW_MEANINGFUL_USAGE =
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
const VkImageUsageFlags view_usage = ViewUsageFlags(*device, image_usage, vk_format);
const bool narrows = view_usage != image_usage && (view_usage & VIEW_MEANINGFUL_USAGE) != 0;
const VkImageViewUsageCreateInfo usage_ci{
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
.pNext = nullptr,
.usage = view_usage,
};
return device->GetLogical().CreateImageView({ return device->GetLogical().CreateImageView({
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.pNext = nullptr,
.pNext = narrows ? &usage_ci : nullptr,
.flags = 0, .flags = 0,
.image = image_handle, .image = image_handle,
.viewType = view_type, .viewType = view_type,

1
src/video_core/renderer_vulkan/vk_texture_cache.h

@ -509,6 +509,7 @@ private:
vk::ImageView color_view; vk::ImageView color_view;
vk::Image null_image; vk::Image null_image;
VkImage image_handle = VK_NULL_HANDLE; VkImage image_handle = VK_NULL_HANDLE;
VkImageUsageFlags image_usage = 0;
VkImageView render_target = VK_NULL_HANDLE; VkImageView render_target = VK_NULL_HANDLE;
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT; VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
u32 buffer_size = 0; u32 buffer_size = 0;

Loading…
Cancel
Save