2525
2626namespace nvrhi ::vulkan
2727{
28+ extern vk::ImageAspectFlags guessImageAspectFlags (vk::Format format);
2829
2930 TrackedCommandBuffer::~TrackedCommandBuffer ()
3031 {
@@ -190,6 +191,34 @@ namespace nvrhi::vulkan
190191 std::vector<vk::SparseImageMemoryBind> sparseImageMemoryBinds;
191192 std::vector<vk::SparseMemoryBind> sparseMemoryBinds;
192193
194+ vk::ImageCreateInfo& imageInfo = texture->imageInfo ;
195+ vk::ImageAspectFlags textureAspectFlags = guessImageAspectFlags (imageInfo.format );
196+
197+ // Required for extent and offset since they must be multiples of the tile dimensions
198+ uint32_t tileWidth = 1 ;
199+ uint32_t tileHeight = 1 ;
200+ uint32_t tileDepth = 1 ;
201+
202+ // Mip tail info, required for resource offset
203+ vk::DeviceSize imageMipTailOffset = 0 ;
204+ vk::DeviceSize imageMipTailStride = 1 ;
205+
206+ std::vector<vk::SparseImageFormatProperties> formatProperties = m_Context.physicalDevice .getSparseImageFormatProperties (imageInfo.format , imageInfo.imageType , imageInfo.samples , imageInfo.usage , imageInfo.tiling );
207+ std::vector<vk::SparseImageMemoryRequirements> memoryRequirements = m_Context.device .getImageSparseMemoryRequirements (texture->image );
208+
209+ if (!formatProperties.empty ())
210+ {
211+ tileWidth = formatProperties[0 ].imageGranularity .width ;
212+ tileHeight = formatProperties[0 ].imageGranularity .height ;
213+ tileDepth = formatProperties[0 ].imageGranularity .depth ;
214+ }
215+
216+ if (!memoryRequirements.empty ())
217+ {
218+ imageMipTailOffset = memoryRequirements[0 ].imageMipTailOffset ;
219+ imageMipTailStride = memoryRequirements[0 ].imageMipTailStride ;
220+ }
221+
193222 for (size_t i = 0 ; i < numTileMappings; i++)
194223 {
195224 uint32_t numRegions = tileMappings[i].numTextureRegions ;
@@ -204,7 +233,7 @@ namespace nvrhi::vulkan
204233 if (tiledTextureRegion.tilesNum )
205234 {
206235 sparseMemoryBinds.push_back (vk::SparseMemoryBind ()
207- .setResourceOffset (0 )
236+ .setResourceOffset (imageMipTailOffset + tiledTextureCoordinate. arrayLevel * imageMipTailOffset )
208237 .setSize (tiledTextureRegion.tilesNum * texture->tileByteSize )
209238 .setMemory (deviceMemory)
210239 .setMemoryOffset (deviceMemory ? tileMappings[i].byteOffsets [j] : 0 ));
@@ -214,16 +243,17 @@ namespace nvrhi::vulkan
214243 vk::ImageSubresource subresource = {};
215244 subresource.arrayLayer = tiledTextureCoordinate.arrayLevel ;
216245 subresource.mipLevel = tiledTextureCoordinate.mipLevel ;
246+ subresource.aspectMask = textureAspectFlags; // Required for sparse binding
217247
218248 vk::Offset3D offset3D;
219- offset3D.x = tiledTextureCoordinate.x ;
220- offset3D.y = tiledTextureCoordinate.y ;
221- offset3D.z = tiledTextureCoordinate.z ;
249+ offset3D.x = tiledTextureCoordinate.x * tileWidth ;
250+ offset3D.y = tiledTextureCoordinate.y * tileHeight ;
251+ offset3D.z = tiledTextureCoordinate.z * tileHeight ;
222252
223253 vk::Extent3D extent3D;
224- extent3D.width = tiledTextureRegion.width ;
225- extent3D.height = tiledTextureRegion.height ;
226- extent3D.depth = tiledTextureRegion.depth ;
254+ extent3D.width = tiledTextureRegion.width * tileWidth ;
255+ extent3D.height = tiledTextureRegion.height * tileHeight ;
256+ extent3D.depth = tiledTextureRegion.depth * tileDepth ;
227257
228258 sparseImageMemoryBinds.push_back (vk::SparseImageMemoryBind ()
229259 .setSubresource (subresource)
0 commit comments