mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-22 20:06:54 +02:00
graphics: intersect texture views with resource mips
This commit is contained in:
@@ -405,10 +405,14 @@ static bool IsSupportedStorageTextureDescriptor(const ShaderRecompiler::IR::Imag
|
|||||||
const bool supported_swizzle =
|
const bool supported_swizzle =
|
||||||
IsValidImageSwizzle(swizzle) &&
|
IsValidImageSwizzle(swizzle) &&
|
||||||
(swizzle == DstSel(4, 5, 6, 7) || !resource.read || resource.atomic);
|
(swizzle == DstSel(4, 5, 6, 7) || !resource.read || resource.atomic);
|
||||||
|
const auto view_last_level =
|
||||||
|
resource.mip_mode == ShaderRecompiler::IR::ImageMipMode::DynamicStorage
|
||||||
|
? descriptor.LastLevel()
|
||||||
|
: std::min(descriptor.LastLevel(), descriptor.MaxMip());
|
||||||
return (is_1d || is_1d_array || is_2d || is_2d_array || is_3d) && supported_tile &&
|
return (is_1d || is_1d_array || is_2d || is_2d_array || is_3d) && supported_tile &&
|
||||||
descriptor.BaseLevel() <= descriptor.LastLevel() &&
|
descriptor.BaseLevel() <= view_last_level && view_last_level <= descriptor.MaxMip() &&
|
||||||
descriptor.LastLevel() <= descriptor.MaxMip() && descriptor.MinLod() == 0 &&
|
descriptor.MinLod() == 0 && supported_swizzle && descriptor.BCSwizzle() == 0 &&
|
||||||
supported_swizzle && descriptor.BCSwizzle() == 0 && !descriptor.MsaaDepth();
|
!descriptor.MsaaDepth();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsSupportedStorageTextureEncoding(const ShaderTextureResource& descriptor) {
|
static bool IsSupportedStorageTextureEncoding(const ShaderTextureResource& descriptor) {
|
||||||
@@ -629,11 +633,15 @@ RenderExecutor::ResolveTexture(const ShaderRecompiler::IR::ImageResource& reso
|
|||||||
const auto type = TextureType(descriptor);
|
const auto type = TextureType(descriptor);
|
||||||
const bool multisampled = IsMultisampledTexture(type);
|
const bool multisampled = IsMultisampledTexture(type);
|
||||||
const auto levels = multisampled ? 1u : static_cast<uint32_t>(descriptor.MaxMip()) + 1u;
|
const auto levels = multisampled ? 1u : static_cast<uint32_t>(descriptor.MaxMip()) + 1u;
|
||||||
const auto tile = descriptor.TileMode();
|
const bool dynamic_storage =
|
||||||
const bool depth_tile = tile == Prospero::TileMode::kDepth;
|
storage && resource.mip_mode == ShaderRecompiler::IR::ImageMipMode::DynamicStorage;
|
||||||
const bool msaa_tile = depth_tile || tile == Prospero::TileMode::kRenderTarget;
|
const auto view_last_level =
|
||||||
const bool msaa_array = type == Prospero::ImageType::kColor2DMsaaArray;
|
!multisampled && !dynamic_storage ? std::min(last_level, descriptor.MaxMip()) : last_level;
|
||||||
if ((!multisampled && (base_level > last_level || last_level >= levels)) ||
|
const auto tile = descriptor.TileMode();
|
||||||
|
const bool depth_tile = tile == Prospero::TileMode::kDepth;
|
||||||
|
const bool msaa_tile = depth_tile || tile == Prospero::TileMode::kRenderTarget;
|
||||||
|
const bool msaa_array = type == Prospero::ImageType::kColor2DMsaaArray;
|
||||||
|
if ((!multisampled && (base_level > view_last_level || view_last_level >= levels)) ||
|
||||||
(multisampled &&
|
(multisampled &&
|
||||||
(base_level != 0 || last_level == 0 || last_level > 3 ||
|
(base_level != 0 || last_level == 0 || last_level > 3 ||
|
||||||
descriptor.MaxMip() != last_level || !msaa_tile ||
|
descriptor.MaxMip() != last_level || !msaa_tile ||
|
||||||
@@ -652,7 +660,7 @@ RenderExecutor::ResolveTexture(const ShaderRecompiler::IR::ImageResource& reso
|
|||||||
}
|
}
|
||||||
const auto samples = multisampled ? 1u << last_level : 1u;
|
const auto samples = multisampled ? 1u << last_level : 1u;
|
||||||
const auto view_levels =
|
const auto view_levels =
|
||||||
multisampled ? 1u : static_cast<uint32_t>(last_level - base_level) + 1u;
|
multisampled ? 1u : static_cast<uint32_t>(view_last_level - base_level) + 1u;
|
||||||
const auto depth = static_cast<uint32_t>(descriptor.Depth()) + 1u;
|
const auto depth = static_cast<uint32_t>(descriptor.Depth()) + 1u;
|
||||||
const auto format = descriptor.Format();
|
const auto format = descriptor.Format();
|
||||||
const bool sampled_numeric_class =
|
const bool sampled_numeric_class =
|
||||||
|
|||||||
@@ -261,9 +261,10 @@ void RenderExecutor::DispatchDirect(uint64_t submit_id, RenderCommandBuffer& buf
|
|||||||
r.Base40(), static_cast<uint32_t>(r.Type()), static_cast<uint32_t>(r.Format()),
|
r.Base40(), static_cast<uint32_t>(r.Type()), static_cast<uint32_t>(r.Format()),
|
||||||
static_cast<uint32_t>(r.Width5()) + 1u, static_cast<uint32_t>(r.Height5()) + 1u,
|
static_cast<uint32_t>(r.Width5()) + 1u, static_cast<uint32_t>(r.Height5()) + 1u,
|
||||||
static_cast<uint32_t>(r.Depth()) + 1u,
|
static_cast<uint32_t>(r.Depth()) + 1u,
|
||||||
std::max<uint32_t>(static_cast<uint32_t>(r.LastLevel()),
|
r.Type() == Prospero::ImageType::kColor2DMsaa ||
|
||||||
static_cast<uint32_t>(r.MaxMip())) +
|
r.Type() == Prospero::ImageType::kColor2DMsaaArray
|
||||||
1u,
|
? 1u
|
||||||
|
: static_cast<uint32_t>(r.MaxMip()) + 1u,
|
||||||
static_cast<uint32_t>(r.TileMode()));
|
static_cast<uint32_t>(r.TileMode()));
|
||||||
}
|
}
|
||||||
for (uint32_t i = 0; i < program.info.samplers.size(); i++) {
|
for (uint32_t i = 0; i < program.info.samplers.size(); i++) {
|
||||||
|
|||||||
@@ -6561,43 +6561,75 @@ public:
|
|||||||
std::end(mipped_storage.fields),
|
std::end(mipped_storage.fields),
|
||||||
mipped_storage_descriptor.dwords.begin());
|
mipped_storage_descriptor.dwords.begin());
|
||||||
mipped_storage_descriptor.dword_count = 8;
|
mipped_storage_descriptor.dword_count = 8;
|
||||||
|
auto overwide_mipped_storage = mipped_storage;
|
||||||
|
overwide_mipped_storage.fields[3] =
|
||||||
|
(overwide_mipped_storage.fields[3] & ~(0xfu << 16u)) | (4u << 16u);
|
||||||
|
ShaderRecompiler::IR::DescriptorValue
|
||||||
|
overwide_mipped_storage_descriptor{};
|
||||||
|
std::copy(std::begin(overwide_mipped_storage.fields),
|
||||||
|
std::end(overwide_mipped_storage.fields),
|
||||||
|
overwide_mipped_storage_descriptor.dwords.begin());
|
||||||
|
overwide_mipped_storage_descriptor.dword_count = 8;
|
||||||
auto mipped_storage_resource = storage_resource;
|
auto mipped_storage_resource = storage_resource;
|
||||||
mipped_storage_resource.mip_mode =
|
mipped_storage_resource.mip_mode =
|
||||||
ShaderRecompiler::IR::ImageMipMode::DynamicStorage;
|
ShaderRecompiler::IR::ImageMipMode::DynamicStorage;
|
||||||
mipped_storage_resource.mip_count = 3;
|
mipped_storage_resource.mip_count = 3;
|
||||||
|
auto sampled_overwide_resource = storage_resource;
|
||||||
|
sampled_overwide_resource.kind =
|
||||||
|
ShaderRecompiler::IR::ResourceKind::ImageUint;
|
||||||
|
sampled_overwide_resource.read = true;
|
||||||
|
sampled_overwide_resource.written = false;
|
||||||
auto plain_mipped_storage_binding =
|
auto plain_mipped_storage_binding =
|
||||||
|
RenderExecutorTestAccess::ResolveTexture(executor, storage_resource,
|
||||||
|
mipped_storage_descriptor);
|
||||||
|
auto mipped_storage_binding = RenderExecutorTestAccess::ResolveTexture(
|
||||||
|
executor, mipped_storage_resource, mipped_storage_descriptor);
|
||||||
|
auto overwide_mipped_storage_binding =
|
||||||
RenderExecutorTestAccess::ResolveTexture(
|
RenderExecutorTestAccess::ResolveTexture(
|
||||||
executor, storage_resource, mipped_storage_descriptor);
|
executor, storage_resource, overwide_mipped_storage_descriptor);
|
||||||
auto mipped_storage_binding =
|
auto sampled_overwide_resolved = RenderExecutorTestAccess::ResolveTexture(
|
||||||
RenderExecutorTestAccess::ResolveTexture(
|
executor, sampled_overwide_resource,
|
||||||
executor, mipped_storage_resource, mipped_storage_descriptor);
|
overwide_mipped_storage_descriptor);
|
||||||
DescriptorCache::PreparedBindings mipped_prepared{};
|
DescriptorCache::PreparedBindings mipped_prepared{};
|
||||||
auto mipped_program =
|
auto mipped_program = std::make_shared<ShaderRecompiler::IR::Program>();
|
||||||
std::make_shared<ShaderRecompiler::IR::Program>();
|
|
||||||
mipped_program->info.images.push_back(storage_resource);
|
mipped_program->info.images.push_back(storage_resource);
|
||||||
mipped_program->info.images.push_back(mipped_storage_resource);
|
mipped_program->info.images.push_back(mipped_storage_resource);
|
||||||
|
mipped_program->info.images.push_back(storage_resource);
|
||||||
|
mipped_program->info.images.push_back(sampled_overwide_resource);
|
||||||
auto mipped_snapshot =
|
auto mipped_snapshot =
|
||||||
std::make_shared<ShaderRecompiler::IR::ResourceSnapshot>();
|
std::make_shared<ShaderRecompiler::IR::ResourceSnapshot>();
|
||||||
mipped_snapshot->images.assign(2, mipped_storage_descriptor);
|
mipped_snapshot->images = {mipped_storage_descriptor,
|
||||||
|
mipped_storage_descriptor,
|
||||||
|
overwide_mipped_storage_descriptor,
|
||||||
|
overwide_mipped_storage_descriptor};
|
||||||
mipped_prepared.program = std::move(mipped_program);
|
mipped_prepared.program = std::move(mipped_program);
|
||||||
mipped_prepared.snapshot = std::move(mipped_snapshot);
|
mipped_prepared.snapshot = std::move(mipped_snapshot);
|
||||||
mipped_prepared.resources.images.push_back(
|
mipped_prepared.resources.images.push_back(
|
||||||
std::move(plain_mipped_storage_binding));
|
std::move(plain_mipped_storage_binding));
|
||||||
mipped_prepared.resources.images.push_back(
|
mipped_prepared.resources.images.push_back(
|
||||||
std::move(mipped_storage_binding));
|
std::move(mipped_storage_binding));
|
||||||
|
mipped_prepared.resources.images.push_back(
|
||||||
|
std::move(overwide_mipped_storage_binding));
|
||||||
|
mipped_prepared.resources.images.push_back(
|
||||||
|
std::move(sampled_overwide_resolved));
|
||||||
executor.RebindImages(scheduler.Current(), mipped_prepared);
|
executor.RebindImages(scheduler.Current(), mipped_prepared);
|
||||||
auto &plain_mipped_binding = mipped_prepared.resources.images[0];
|
auto &plain_mipped_binding = mipped_prepared.resources.images[0];
|
||||||
auto &mipped_binding = mipped_prepared.resources.images[1];
|
auto &mipped_binding = mipped_prepared.resources.images[1];
|
||||||
|
auto &overwide_mipped_binding = mipped_prepared.resources.images[2];
|
||||||
|
auto &sampled_overwide_binding = mipped_prepared.resources.images[3];
|
||||||
plain_mipped_binding.layout = vk::ImageLayout::eGeneral;
|
plain_mipped_binding.layout = vk::ImageLayout::eGeneral;
|
||||||
mipped_binding.layout = vk::ImageLayout::eGeneral;
|
mipped_binding.layout = vk::ImageLayout::eGeneral;
|
||||||
|
overwide_mipped_binding.layout = vk::ImageLayout::eGeneral;
|
||||||
|
sampled_overwide_binding.layout = vk::ImageLayout::eGeneral;
|
||||||
auto plain_view_desc = plain_mipped_binding.desc;
|
auto plain_view_desc = plain_mipped_binding.desc;
|
||||||
plain_view_desc.view_info.level_count = 1;
|
plain_view_desc.view_info.level_count = 1;
|
||||||
Require(name, "dynamic storage mip views",
|
Require(name, "dynamic storage mip views",
|
||||||
plain_mipped_binding.desc.view_info.base_level == 1 &&
|
plain_mipped_binding.desc.view_info.base_level == 1 &&
|
||||||
plain_mipped_binding.desc.view_info.level_count == 3 &&
|
plain_mipped_binding.desc.view_info.level_count == 3 &&
|
||||||
plain_mipped_binding.mip_views.empty() &&
|
plain_mipped_binding.mip_views.empty() &&
|
||||||
plain_mipped_binding.image_view == texture_cache.FindTexture(
|
plain_mipped_binding.image_view ==
|
||||||
plain_mipped_binding.image_id, plain_view_desc) &&
|
texture_cache.FindTexture(plain_mipped_binding.image_id,
|
||||||
|
plain_view_desc) &&
|
||||||
mipped_binding.desc.info.resources.levels == 4 &&
|
mipped_binding.desc.info.resources.levels == 4 &&
|
||||||
mipped_binding.desc.view_info.base_level == 1 &&
|
mipped_binding.desc.view_info.base_level == 1 &&
|
||||||
mipped_binding.desc.view_info.level_count == 3 &&
|
mipped_binding.desc.view_info.level_count == 3 &&
|
||||||
@@ -6615,6 +6647,28 @@ public:
|
|||||||
.imageView == mipped_binding.mip_views[2],
|
.imageView == mipped_binding.mip_views[2],
|
||||||
"base-1 through last-3 storage view did not create three "
|
"base-1 through last-3 storage view did not create three "
|
||||||
"ordered one-level descriptors");
|
"ordered one-level descriptors");
|
||||||
|
Require(name, "over-wide fixed storage mip view",
|
||||||
|
overwide_mipped_storage.LastLevel() == 4 &&
|
||||||
|
overwide_mipped_storage.MaxMip() == 3 &&
|
||||||
|
overwide_mipped_binding.image_id ==
|
||||||
|
plain_mipped_binding.image_id &&
|
||||||
|
overwide_mipped_binding.desc.info.resources.levels == 4 &&
|
||||||
|
overwide_mipped_binding.desc.view_info.base_level == 1 &&
|
||||||
|
overwide_mipped_binding.desc.view_info.level_count == 3 &&
|
||||||
|
overwide_mipped_binding.mip_views.empty() &&
|
||||||
|
overwide_mipped_binding.image_view ==
|
||||||
|
plain_mipped_binding.image_view,
|
||||||
|
"fixed storage view was not intersected with its physical mip "
|
||||||
|
"range before Vulkan acquisition");
|
||||||
|
Require(name, "over-wide sampled mip view",
|
||||||
|
sampled_overwide_binding.image_id ==
|
||||||
|
plain_mipped_binding.image_id &&
|
||||||
|
sampled_overwide_binding.desc.info.resources.levels == 4 &&
|
||||||
|
sampled_overwide_binding.desc.view_info.base_level == 1 &&
|
||||||
|
sampled_overwide_binding.desc.view_info.level_count == 3 &&
|
||||||
|
sampled_overwide_binding.mip_views.empty() &&
|
||||||
|
sampled_overwide_binding.image_view != nullptr,
|
||||||
|
"sampled view was not intersected with its physical mip range");
|
||||||
auto srgb_storage = storage;
|
auto srgb_storage = storage;
|
||||||
constexpr auto srgb_format =
|
constexpr auto srgb_format =
|
||||||
static_cast<uint32_t>(Prospero::BufferFormat::k8_8_8_8Srgb);
|
static_cast<uint32_t>(Prospero::BufferFormat::k8_8_8_8Srgb);
|
||||||
@@ -18967,6 +19021,11 @@ ShaderTextureResource Ppsa01340MipRangeStorageTextureDescriptor() {
|
|||||||
0x00700030u, 0xb07b0000u, 0x0002ac3cu}};
|
0x00700030u, 0xb07b0000u, 0x0002ac3cu}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ShaderTextureResource Ppsa01340OverwideMipStorageTextureDescriptor() {
|
||||||
|
return {{0x0346c000u, 0xc4b00000u, 0x007fc07fu, 0x90990facu, 0x00000000u,
|
||||||
|
0x00700080u, 0x00000000u, 0x00000000u}};
|
||||||
|
}
|
||||||
|
|
||||||
ShaderRecompiler::IR::ImageResource Ppsa01530MaxMipStorageTextureResource() {
|
ShaderRecompiler::IR::ImageResource Ppsa01530MaxMipStorageTextureResource() {
|
||||||
auto resource = BasicBgraStorageTextureResource();
|
auto resource = BasicBgraStorageTextureResource();
|
||||||
resource.kind = ShaderRecompiler::IR::ResourceKind::StorageImageUint;
|
resource.kind = ShaderRecompiler::IR::ResourceKind::StorageImageUint;
|
||||||
@@ -19102,7 +19161,11 @@ ShaderTextureResource AtomicStorageTextureDescriptor() {
|
|||||||
descriptor.fields[3] =
|
descriptor.fields[3] =
|
||||||
(descriptor.fields[3] & ~(0x1fu << 20u)) |
|
(descriptor.fields[3] & ~(0x1fu << 20u)) |
|
||||||
(static_cast<uint32_t>(Prospero::TileMode::kStandard256B) << 20u);
|
(static_cast<uint32_t>(Prospero::TileMode::kStandard256B) << 20u);
|
||||||
} else if (std::strcmp(kind, "mip") == 0) {
|
} else if (std::strcmp(kind, "base-mip-out-of-resource") == 0) {
|
||||||
|
descriptor.fields[3] |= (1u << 12u) | (1u << 16u);
|
||||||
|
} else if (std::strcmp(kind, "dynamic-mip-out-of-resource") == 0) {
|
||||||
|
resource.mip_mode = ShaderRecompiler::IR::ImageMipMode::DynamicStorage;
|
||||||
|
resource.mip_count = 2;
|
||||||
descriptor.fields[3] |= 1u << 16u;
|
descriptor.fields[3] |= 1u << 16u;
|
||||||
} else if (std::strcmp(kind, "inverted-mip-range") == 0) {
|
} else if (std::strcmp(kind, "inverted-mip-range") == 0) {
|
||||||
descriptor.fields[3] |= 1u << 12u;
|
descriptor.fields[3] |= 1u << 12u;
|
||||||
@@ -19246,6 +19309,27 @@ void CheckBasicStorageTextureDescriptor() {
|
|||||||
ValidateStorageTexture(BasicBgraStorageTextureResource(), mip_range,
|
ValidateStorageTexture(BasicBgraStorageTextureResource(), mip_range,
|
||||||
0xa30000);
|
0xa30000);
|
||||||
|
|
||||||
|
const auto overwide_mip = Ppsa01340OverwideMipStorageTextureDescriptor();
|
||||||
|
Require(
|
||||||
|
"BasicStorageTexture", "PPSA01340 over-wide mip view",
|
||||||
|
overwide_mip.Base40() == 0x346c00000ull &&
|
||||||
|
overwide_mip.Width5() + 1u == 512 &&
|
||||||
|
overwide_mip.Height5() + 1u == 512 && overwide_mip.BaseLevel() == 0 &&
|
||||||
|
overwide_mip.LastLevel() == 9 && overwide_mip.MaxMip() == 8 &&
|
||||||
|
overwide_mip.Format() == Prospero::BufferFormat::k32_32_32_32UInt &&
|
||||||
|
overwide_mip.TileMode() == Prospero::TileMode::kStandard64KB,
|
||||||
|
"captured over-wide storage mip view is malformed");
|
||||||
|
TileSizeAlign overwide_size{};
|
||||||
|
TileGetTextureTotalSize(overwide_mip.Format(), overwide_mip.Width5() + 1u,
|
||||||
|
overwide_mip.Height5() + 1u, 1,
|
||||||
|
overwide_mip.MaxMip() + 1u, overwide_mip.TileMode(),
|
||||||
|
false, overwide_size);
|
||||||
|
Require("BasicStorageTexture", "PPSA01340 over-wide mip footprint",
|
||||||
|
overwide_size.size == 0x560000 && overwide_size.align == 0x10000,
|
||||||
|
"captured nine-level Standard64KB footprint changed");
|
||||||
|
ValidateStorageTexture(Ppsa01530MaxMipStorageTextureResource(), overwide_mip,
|
||||||
|
overwide_size.size);
|
||||||
|
|
||||||
const auto r16_float = Ppsa02527R16FloatStorageTextureDescriptor();
|
const auto r16_float = Ppsa02527R16FloatStorageTextureDescriptor();
|
||||||
Require("BasicStorageTexture", "PPSA02527 R16F descriptor",
|
Require("BasicStorageTexture", "PPSA02527 R16F descriptor",
|
||||||
r16_float.Base40() == 0xce350000ull &&
|
r16_float.Base40() == 0xce350000ull &&
|
||||||
@@ -19542,12 +19626,13 @@ void CheckBasicStorageTextureDescriptor() {
|
|||||||
GetModuleFileNameA(nullptr, path, MAX_PATH) != 0,
|
GetModuleFileNameA(nullptr, path, MAX_PATH) != 0,
|
||||||
"GetModuleFileName failed");
|
"GetModuleFileName failed");
|
||||||
for (const char *kind :
|
for (const char *kind :
|
||||||
{"resource", "type", "standard256b-volume", "mip",
|
{"resource", "type", "standard256b-volume",
|
||||||
"inverted-mip-range", "swizzle",
|
"base-mip-out-of-resource", "dynamic-mip-out-of-resource",
|
||||||
"linear-rgb1-read", "bgra-read", "r16-float-read", "r8-unorm-read",
|
"inverted-mip-range", "swizzle", "linear-rgb1-read", "bgra-read",
|
||||||
"yzwx-read", "reserved-swizzle", "array-base-out-of-range", "reserved",
|
"r16-float-read", "r8-unorm-read", "yzwx-read", "reserved-swizzle",
|
||||||
"uint-format", "uint-resource-float-format", "atomic-format",
|
"array-base-out-of-range", "reserved", "uint-format",
|
||||||
"depth-tile-read", "depth-tile-extent", "depth-tile-fmask"}) {
|
"uint-resource-float-format", "atomic-format", "depth-tile-read",
|
||||||
|
"depth-tile-extent", "depth-tile-fmask"}) {
|
||||||
std::string command = std::string("\"") + path +
|
std::string command = std::string("\"") + path +
|
||||||
"\" --storage-texture-descriptor-death " + kind;
|
"\" --storage-texture-descriptor-death " + kind;
|
||||||
std::vector<char> mutable_command(command.begin(), command.end());
|
std::vector<char> mutable_command(command.begin(), command.end());
|
||||||
|
|||||||
Reference in New Issue
Block a user