Support single-channel float storage writes

Support sampled views of storage texture arrays

Support R8 UNORM storage writes
This commit is contained in:
nmzik
2026-07-17 02:24:22 +02:00
parent feb678c23e
commit 013e9a4485
4 changed files with 133 additions and 16 deletions
@@ -187,6 +187,7 @@ enum class RenderTargetOverlap : uint8_t {
};
enum class SampledOverlap : uint8_t { None, ReadOnlyAlias, Unsupported };
enum class StorageSampledOverlap : uint8_t { None, ExactImage, Unsupported };
enum class StorageSampledViewShape : uint8_t { Image2D, Image2DArray, Image3D, Unsupported };
enum class StorageImageOverlap : uint8_t { None, RetireSampled, PageNeighbor, Unsupported };
enum class HostWriteOverlap : uint8_t { None, InvalidateImage, Unsupported };
enum class BufferImageBinding : uint8_t { Texture, VideoOut, RenderTarget, Unsupported };
@@ -199,6 +200,22 @@ enum class BufferImageWrite : uint8_t {
};
enum class MetaImageOverlap : uint8_t { RetainSampled, RetireTarget, Unsupported };
[[nodiscard]] inline constexpr StorageSampledViewShape
SelectStorageSampledViewShape(uint32_t type, uint32_t depth, uint32_t backing_layers) noexcept {
switch (static_cast<Prospero::ImageType>(type)) {
case Prospero::ImageType::kColor2D:
return depth == 1 && backing_layers == 1 ? StorageSampledViewShape::Image2D
: StorageSampledViewShape::Unsupported;
case Prospero::ImageType::kColor2DArray:
return depth != 0 && depth == backing_layers ? StorageSampledViewShape::Image2DArray
: StorageSampledViewShape::Unsupported;
case Prospero::ImageType::kColor3D:
return depth != 0 && backing_layers == 1 ? StorageSampledViewShape::Image3D
: StorageSampledViewShape::Unsupported;
default: return StorageSampledViewShape::Unsupported;
}
}
[[nodiscard]] inline constexpr bool IsSupportedRenderTargetElementSize(uint32_t size) noexcept {
switch (size) {
case 1:
+14 -8
View File
@@ -9,11 +9,14 @@
namespace Libs::Graphics {
[[nodiscard]] inline bool IsSupportedStorageSwizzle(uint32_t format, uint32_t swizzle) noexcept {
const bool single_channel_uint = format == Prospero::GpuEnumValue(Prospero::BufferFormat::k8UInt) ||
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16UInt) ||
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt);
const bool single_channel = format == Prospero::GpuEnumValue(Prospero::BufferFormat::k8UNorm) ||
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k8UInt) ||
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16UInt) ||
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt) ||
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16Float) ||
format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float);
return swizzle == DstSel(4, 5, 6, 7) ||
(single_channel_uint &&
(single_channel &&
(swizzle == DstSel(4, 0, 0, 0) || swizzle == DstSel(4, 0, 0, 1))) ||
(format == Prospero::GpuEnumValue(Prospero::BufferFormat::k8_8_8_8UNorm) &&
(swizzle == DstSel(4, 5, 6, 1) || swizzle == DstSel(6, 5, 4, 7))) ||
@@ -114,12 +117,15 @@ IsSupportedSampledDepthResource(const ShaderRecompiler::IR::ImageResource& resou
[[nodiscard]] inline int SelectStorageColorView(VkFormat image_format, VkFormat view_format,
uint32_t swizzle) noexcept {
const bool single_channel_uint = view_format == VK_FORMAT_R8_UINT ||
view_format == VK_FORMAT_R16_UINT ||
view_format == VK_FORMAT_R32_UINT;
const bool single_channel = view_format == VK_FORMAT_R8_UNORM ||
view_format == VK_FORMAT_R8_UINT ||
view_format == VK_FORMAT_R16_UINT ||
view_format == VK_FORMAT_R32_UINT ||
view_format == VK_FORMAT_R16_SFLOAT ||
view_format == VK_FORMAT_R32_SFLOAT;
const bool swizzle_ok =
swizzle == DstSel(4, 5, 6, 7) ||
(single_channel_uint && (swizzle == DstSel(4, 0, 0, 0) || swizzle == DstSel(4, 0, 0, 1))) ||
(single_channel && (swizzle == DstSel(4, 0, 0, 0) || swizzle == DstSel(4, 0, 0, 1))) ||
(view_format == VK_FORMAT_R8G8B8A8_UNORM &&
(swizzle == DstSel(4, 5, 6, 1) || swizzle == DstSel(6, 5, 4, 7))) ||
(view_format == VK_FORMAT_R32G32B32A32_SFLOAT && swizzle == DstSel(5, 6, 7, 4));
@@ -1557,11 +1557,10 @@ VkImageView TextureCache::GetRenderTargetStorageView(GraphicContext* c
VkImageView TextureCache::GetStorageTextureSampledView(GraphicContext* ctx,
StorageTextureVulkanImage* image,
const ImageInfo& info) {
const bool image_2d =
info.type == Prospero::GpuEnumValue(Prospero::ImageType::kColor2D) && info.depth == 1;
const bool image_3d =
info.type == Prospero::GpuEnumValue(Prospero::ImageType::kColor3D) && info.depth != 0;
if (ctx == nullptr || image == nullptr || image->image == nullptr || (!image_2d && !image_3d) ||
const auto shape = SelectStorageSampledViewShape(
info.type, info.depth, image != nullptr ? image->layers : 0);
if (ctx == nullptr || image == nullptr || image->image == nullptr ||
shape == StorageSampledViewShape::Unsupported ||
info.base_array != 0 || info.levels != image->mip_levels ||
info.base_level >= info.levels || info.view_levels == 0 ||
info.base_level + info.view_levels > info.levels) {
@@ -1593,14 +1592,19 @@ VkImageView TextureCache::GetStorageTextureSampledView(GraphicContext*
create.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
create.pNext = &usage;
create.image = image->image;
create.viewType = image_3d ? VK_IMAGE_VIEW_TYPE_3D : VK_IMAGE_VIEW_TYPE_2D;
create.viewType = shape == StorageSampledViewShape::Image3D
? VK_IMAGE_VIEW_TYPE_3D
: shape == StorageSampledViewShape::Image2DArray
? VK_IMAGE_VIEW_TYPE_2D_ARRAY
: VK_IMAGE_VIEW_TYPE_2D;
create.format = view_format;
create.components = TextureGetComponentMapping(info.swizzle);
create.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
create.subresourceRange.baseMipLevel = info.base_level;
create.subresourceRange.levelCount = info.view_levels;
create.subresourceRange.baseArrayLayer = 0;
create.subresourceRange.layerCount = 1;
create.subresourceRange.layerCount =
shape == StorageSampledViewShape::Image2DArray ? info.depth : 1;
VkImageView view = nullptr;
const auto result = vkCreateImageView(ctx->device, &create, nullptr, &view);
if (result != VK_SUCCESS || view == nullptr) {