diff --git a/core/libs/prx/libSceAgcDriver/tests/ShaderDeviceProfile.cpp b/core/libs/prx/libSceAgcDriver/tests/ShaderDeviceProfile.cpp index d928bf05c..7f3366c56 100644 --- a/core/libs/prx/libSceAgcDriver/tests/ShaderDeviceProfile.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/ShaderDeviceProfile.cpp @@ -144,10 +144,15 @@ void CheckHeaps() { Reject([&] { allocate(image, 1u, RuntimeAbi::SamplerHeapCapacity + 1u); }, "metadata capacity"); image.resourceClass = ImageResourceClass::Storage; image.mipMode = ImageMipMode::DynamicStorage; - image.mipCount = RuntimeAbi::StorageHeapCapacity; + image.mipCount = RuntimeAbi::StorageMipSlots; const auto storage = allocate(image, 1u); Require(BindingAllocator{}.FindBinding(storage.layout, DescriptorBindingForImage(image)).resources.size() == image.mipCount, "storage heap did not reserve each mip"); - Reject([&] { allocate(image, 2u); }, "heap capacity exceeded"); + const auto shared = allocate(image, 2u); + Require(BindingAllocator{}.FindBinding(shared.layout, DescriptorBindingForImage(image)).resources.size() == 2u * image.mipCount, "a storage heap did not hold two dynamic-mip images"); + const auto capacity = RuntimeAbi::StorageHeapCapacity / image.mipCount; + const auto filled = allocate(image, capacity); + Require(BindingAllocator{}.FindBinding(filled.layout, DescriptorBindingForImage(image)).resources.size() == RuntimeAbi::StorageHeapCapacity, "a full storage heap was not allocated"); + Reject([&] { allocate(image, capacity + 1u); }, "heap capacity exceeded"); Reject([&] { allocate(image, 0u, RuntimeAbi::SamplerHeapCapacity / 2u + 1u); }, "sampler pairs"); const std::array dimensions{RdnaImageDimension::Dim1D, RdnaImageDimension::Dim1DArray, RdnaImageDimension::Dim2D, RdnaImageDimension::Dim2DArray, RdnaImageDimension::Dim3D, RdnaImageDimension::Dim2DMsaa, RdnaImageDimension::Dim2DMsaaArray}; std::set classes; diff --git a/core/shader/recompiler/Optimization/src/BindingAllocator.cpp b/core/shader/recompiler/Optimization/src/BindingAllocator.cpp index 518ac228e..185c7ea89 100644 --- a/core/shader/recompiler/Optimization/src/BindingAllocator.cpp +++ b/core/shader/recompiler/Optimization/src/BindingAllocator.cpp @@ -114,7 +114,7 @@ BindingAllocationResult BindingAllocator::Allocate(IrProgram& program, const Bin std::array, ImageBindingCount> imageGroups; const auto place = [&](std::uint32_t i) { const bool dynamic = info.images[i].mipMode == ImageMipMode::DynamicStorage; - const std::uint32_t count = dynamic ? RuntimeAbi::StorageHeapCapacity : 1u; + const std::uint32_t count = dynamic ? RuntimeAbi::StorageMipSlots : 1u; std::array placed{}; for (const auto& mode : ResourceMaterializer::RuntimeImageModes(info.images[i])) { const auto group = ImageBindingIndex(DescriptorBindingForImage(mode)); diff --git a/core/shader/recompiler/Optimization/src/DescriptorBindingBuilder.cpp b/core/shader/recompiler/Optimization/src/DescriptorBindingBuilder.cpp index 5a7a24e54..0c06248de 100644 --- a/core/shader/recompiler/Optimization/src/DescriptorBindingBuilder.cpp +++ b/core/shader/recompiler/Optimization/src/DescriptorBindingBuilder.cpp @@ -312,7 +312,7 @@ DescriptorBindingPlan DescriptorBindingBuilder::Prepare(const IrBindingLayout& l const auto word = snapshot.images.at(index).dwords[3]; const auto first = (word >> 12u) & 0xfu; const auto last = (word >> 16u) & 0xfu; - if (last < first || last - first >= RuntimeAbi::StorageHeapCapacity) fail("invalid dynamic storage mip range"); + if (last < first || last - first >= RuntimeAbi::StorageMipSlots) fail("invalid dynamic storage mip range"); plan.specialization.push_back({PipelineSpecialization::MipCountBase + index, last - first + 1u}); } for (std::uint32_t resource = 0; resource < info.images.size(); ++resource) { diff --git a/core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp b/core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp index 8bd10eac8..8f4edf617 100644 --- a/core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp +++ b/core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp @@ -619,7 +619,7 @@ std::vector ResourceMaterializer::RuntimeImageModes(const ImageRe mode.depthBits = depth; mode.depthUnorm16 = unorm16; mode.cube = false; - mode.mipCount = mode.mipMode == ImageMipMode::DynamicStorage ? RuntimeAbi::StorageHeapCapacity : 1u; + mode.mipCount = mode.mipMode == ImageMipMode::DynamicStorage ? RuntimeAbi::StorageMipSlots : 1u; mode.shaderSwizzle = ShaderImageIdentitySwizzle; if (conversion == IrBufferFormat::Format11_11_10UNorm || conversion == IrBufferFormat::Format10_11_11Float) mode.shaderSwizzle = 0x2acu; modes.push_back(mode); @@ -746,7 +746,7 @@ std::uint32_t ResourceMaterializer::RuntimeImageMode(const ImageResource& image, if (!exact) throw std::runtime_error(storage ? "runtime packed image bits are not reproducible through the view" : "runtime packed image bits are not recoverable from the view"); } } - if (decoded.mipCount > (image.mipMode == ImageMipMode::DynamicStorage ? RuntimeAbi::StorageHeapCapacity : 1u)) throw std::runtime_error("runtime storage image mip capacity exceeded"); + if (decoded.mipCount > (image.mipMode == ImageMipMode::DynamicStorage ? RuntimeAbi::StorageMipSlots : 1u)) throw std::runtime_error("runtime storage image mip capacity exceeded"); if ((descriptorImageSwizzle(descriptor) & 06666u) == 0u && !decoded.fmask && !decoded.depthBits && decoded.conversionFormat == IrBufferFormat::Invalid && !decoded.srgbDecode) { for (std::uint32_t index = 0u; index < modes.size(); ++index) { if (modes[index].constantSwizzle && modes[index].numericClass == decoded.numericClass) return index; @@ -795,7 +795,7 @@ void ResourceMaterializer::ApplyStaticInterface(IrProgram& program, bool nativeS image.srgbDecodeFormats = resources.srgbDecodeFormats; if (image.indirectRoot != ImageResource::NoIndirectImage) throw std::runtime_error("static image interface was already expanded"); image.numericClass = image.atomic ? IrTextureNumericClass::Uint : IrTextureNumericClass::Float; - image.mipCount = image.mipMode == ImageMipMode::DynamicStorage ? RuntimeAbi::StorageHeapCapacity : 1u; + image.mipCount = image.mipMode == ImageMipMode::DynamicStorage ? RuntimeAbi::StorageMipSlots : 1u; if (resources.descriptorSources.at(image.source).indirectImage.has_value()) { if (images.size() + slots - 1u > ShaderInfo::MaxImages) throw std::runtime_error("static bindless image capacity exceeded"); image.indirectRoot = index; diff --git a/core/shader/recompiler/RuntimeAbi.hpp b/core/shader/recompiler/RuntimeAbi.hpp index 6f6f84d93..43f7bb37c 100644 --- a/core/shader/recompiler/RuntimeAbi.hpp +++ b/core/shader/recompiler/RuntimeAbi.hpp @@ -35,7 +35,8 @@ inline constexpr std::uint32_t UserDataCapacity = 128u; inline constexpr std::uint32_t BufferCapacity = 128u; inline constexpr std::uint32_t ImageCapacity = 256u; inline constexpr std::uint32_t SampledHeapCapacity = 16u; -inline constexpr std::uint32_t StorageHeapCapacity = 4u; +inline constexpr std::uint32_t StorageMipSlots = 4u; +inline constexpr std::uint32_t StorageHeapCapacity = 16u; inline constexpr std::uint32_t SamplerHeapCapacity = 32u; struct ResourceMetadata {