mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-21 03:16:54 +02:00
Support single-channel float storage writes
Support sampled views of storage texture arrays Support R8 UNORM storage writes
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -8846,6 +8846,18 @@ void CheckSampledColorViews() {
|
||||
SelectStorageColorView(VK_FORMAT_R16_UINT, VK_FORMAT_R16_UINT,
|
||||
DstSel(4, 0, 0, 0)) == VulkanImage::VIEW_STORAGE,
|
||||
"R16_UINT R000 storage did not select the identity storage view");
|
||||
Require("SampledColorViews", "storage R16 float R001 write mapping",
|
||||
SelectStorageColorView(VK_FORMAT_R16_SFLOAT, VK_FORMAT_R16_SFLOAT,
|
||||
DstSel(4, 0, 0, 1)) == VulkanImage::VIEW_STORAGE,
|
||||
"R16_SFLOAT R001 storage did not select the identity storage view");
|
||||
Require("SampledColorViews", "storage R32 float R001 write mapping",
|
||||
SelectStorageColorView(VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT,
|
||||
DstSel(4, 0, 0, 1)) == VulkanImage::VIEW_STORAGE,
|
||||
"R32_SFLOAT R001 storage did not select the identity storage view");
|
||||
Require("SampledColorViews", "storage R8 unorm R001 write mapping",
|
||||
SelectStorageColorView(VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM,
|
||||
DstSel(4, 0, 0, 1)) == VulkanImage::VIEW_STORAGE,
|
||||
"R8_UNORM R001 storage did not select the identity storage view");
|
||||
ShaderRecompiler::IR::ImageResource storage_resource{};
|
||||
storage_resource.kind = ShaderRecompiler::IR::ResourceKind::StorageImage;
|
||||
storage_resource.dimension = ShaderRecompiler::Decoder::ImageDimension::Dim2D;
|
||||
@@ -9062,6 +9074,21 @@ ShaderTextureResource BasicBgraStorageTextureDescriptor() {
|
||||
0x00000000u, 0x00700000u, 0x00000000u, 0x00000000u}};
|
||||
}
|
||||
|
||||
ShaderTextureResource Ppsa02527R16FloatStorageTextureDescriptor() {
|
||||
return {{0x00ce3500u, 0xc0d00000u, 0x010dc1dfu, 0x91b00204u,
|
||||
0x00000000u, 0x00700000u, 0x00000000u, 0x00000000u}};
|
||||
}
|
||||
|
||||
ShaderTextureResource Ppsa02527R32FloatStorageTextureDescriptor() {
|
||||
return {{0x00cea900u, 0xc1600000u, 0x0086c0efu, 0x91b00204u,
|
||||
0x00000000u, 0x00700000u, 0x00000000u, 0x00000000u}};
|
||||
}
|
||||
|
||||
ShaderTextureResource Ppsa02527R8UnormStorageTextureDescriptor() {
|
||||
return {{0x00c7d500u, 0xc0100000u, 0x0086c0efu, 0x91b00204u,
|
||||
0x00000000u, 0x00700000u, 0x00000000u, 0x00000000u}};
|
||||
}
|
||||
|
||||
ShaderTextureResource BasicYzwxStorageTextureDescriptor() {
|
||||
return {{0x00627801u, 0xc4d00000u, 0x0001c001u, 0x900009f5u,
|
||||
0x00000000u, 0x00700000u, 0x00000000u, 0x00000000u}};
|
||||
@@ -9121,6 +9148,14 @@ ShaderTextureResource BasicUintVolumeStorageTextureDescriptor() {
|
||||
resource = BasicBgraStorageTextureResource();
|
||||
descriptor = BasicBgraStorageTextureDescriptor();
|
||||
resource.read = true;
|
||||
} else if (std::strcmp(kind, "r16-float-read") == 0) {
|
||||
resource = BasicBgraStorageTextureResource();
|
||||
descriptor = Ppsa02527R16FloatStorageTextureDescriptor();
|
||||
resource.read = true;
|
||||
} else if (std::strcmp(kind, "r8-unorm-read") == 0) {
|
||||
resource = BasicBgraStorageTextureResource();
|
||||
descriptor = Ppsa02527R8UnormStorageTextureDescriptor();
|
||||
resource.read = true;
|
||||
} else if (std::strcmp(kind, "yzwx-read") == 0) {
|
||||
resource = BasicLinearStorageTextureResource();
|
||||
descriptor = BasicYzwxStorageTextureDescriptor();
|
||||
@@ -9203,6 +9238,42 @@ void CheckBasicStorageTextureDescriptor() {
|
||||
"PPSA02604 BGRA 2D storage descriptor fixture is malformed");
|
||||
ValidateStorageTexture(BasicBgraStorageTextureResource(), bgra, 0x870000);
|
||||
|
||||
const auto r16_float = Ppsa02527R16FloatStorageTextureDescriptor();
|
||||
Require("BasicStorageTexture", "PPSA02527 R16F descriptor",
|
||||
r16_float.Base40() == 0xce350000ull && r16_float.Width5() + 1u == 1920 &&
|
||||
r16_float.Height5() + 1u == 1080 && r16_float.Depth() + 1u == 1 &&
|
||||
r16_float.Format() ==
|
||||
Prospero::GpuEnumValue(Prospero::BufferFormat::k16Float) &&
|
||||
r16_float.TileMode() ==
|
||||
Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) &&
|
||||
r16_float.DstSelXYZW() == DstSel(4, 0, 0, 1),
|
||||
"PPSA02527 R16F 2D storage descriptor fixture is malformed");
|
||||
ValidateStorageTexture(BasicBgraStorageTextureResource(), r16_float, 0x480000);
|
||||
|
||||
const auto r32_float = Ppsa02527R32FloatStorageTextureDescriptor();
|
||||
Require("BasicStorageTexture", "PPSA02527 R32F descriptor",
|
||||
r32_float.Base40() == 0xcea90000ull && r32_float.Width5() + 1u == 960 &&
|
||||
r32_float.Height5() + 1u == 540 && r32_float.Depth() + 1u == 1 &&
|
||||
r32_float.Format() ==
|
||||
Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float) &&
|
||||
r32_float.TileMode() ==
|
||||
Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) &&
|
||||
r32_float.DstSelXYZW() == DstSel(4, 0, 0, 1),
|
||||
"PPSA02527 R32F 2D storage descriptor fixture is malformed");
|
||||
ValidateStorageTexture(BasicBgraStorageTextureResource(), r32_float, 0x280000);
|
||||
|
||||
const auto r8_unorm = Ppsa02527R8UnormStorageTextureDescriptor();
|
||||
Require("BasicStorageTexture", "PPSA02527 R8 UNORM descriptor",
|
||||
r8_unorm.Base40() == 0xc7d50000ull && r8_unorm.Width5() + 1u == 960 &&
|
||||
r8_unorm.Height5() + 1u == 540 && r8_unorm.Depth() + 1u == 1 &&
|
||||
r8_unorm.Format() ==
|
||||
Prospero::GpuEnumValue(Prospero::BufferFormat::k8UNorm) &&
|
||||
r8_unorm.TileMode() ==
|
||||
Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) &&
|
||||
r8_unorm.DstSelXYZW() == DstSel(4, 0, 0, 1),
|
||||
"PPSA02527 R8 UNORM 2D storage descriptor fixture is malformed");
|
||||
ValidateStorageTexture(BasicBgraStorageTextureResource(), r8_unorm, 0xc0000);
|
||||
|
||||
const auto yzwx = BasicYzwxStorageTextureDescriptor();
|
||||
Require("BasicStorageTexture", "YZWX descriptor",
|
||||
yzwx.Base40() == 0x62780100ull && yzwx.Width5() + 1u == 8 &&
|
||||
@@ -9269,7 +9340,8 @@ void CheckBasicStorageTextureDescriptor() {
|
||||
GetModuleFileNameA(nullptr, path, MAX_PATH) != 0,
|
||||
"GetModuleFileName failed");
|
||||
for (const char *kind : {"resource", "type", "tile", "mip", "swizzle",
|
||||
"linear-rgb1-read", "bgra-read", "yzwx-read", "yzwx-format",
|
||||
"linear-rgb1-read", "bgra-read", "r16-float-read", "r8-unorm-read",
|
||||
"yzwx-read", "yzwx-format",
|
||||
"array-base-view", "reserved", "metadata", "uint-format",
|
||||
"uint-resource-float-format", "depth-tile-read",
|
||||
"depth-tile-extent"}) {
|
||||
@@ -9830,6 +9902,24 @@ void CheckStorageTextureGpuOwnedRebindState() {
|
||||
}
|
||||
|
||||
void CheckStorageTextureSampledReuse() {
|
||||
const auto image_2d = Prospero::GpuEnumValue(Prospero::ImageType::kColor2D);
|
||||
const auto image_2d_array =
|
||||
Prospero::GpuEnumValue(Prospero::ImageType::kColor2DArray);
|
||||
const auto image_3d = Prospero::GpuEnumValue(Prospero::ImageType::kColor3D);
|
||||
Require("StorageTextureSampledReuse", "view shapes",
|
||||
SelectStorageSampledViewShape(image_2d, 1, 1) ==
|
||||
StorageSampledViewShape::Image2D &&
|
||||
SelectStorageSampledViewShape(image_2d_array, 16, 16) ==
|
||||
StorageSampledViewShape::Image2DArray &&
|
||||
SelectStorageSampledViewShape(image_3d, 16, 1) ==
|
||||
StorageSampledViewShape::Image3D &&
|
||||
SelectStorageSampledViewShape(image_2d, 16, 1) ==
|
||||
StorageSampledViewShape::Unsupported &&
|
||||
SelectStorageSampledViewShape(image_2d_array, 16, 1) ==
|
||||
StorageSampledViewShape::Unsupported &&
|
||||
SelectStorageSampledViewShape(image_3d, 16, 16) ==
|
||||
StorageSampledViewShape::Unsupported,
|
||||
"sampled storage view shape or backing-layer validation is incorrect");
|
||||
ImageInfo storage{};
|
||||
storage.address = 0x78650000;
|
||||
storage.size = 0x210000;
|
||||
|
||||
Reference in New Issue
Block a user