Module: Mesa
Branch: main
Commit: 5a2efa98d96a4a642c7a6143c42503f93e87bc30
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=5a2efa98d96a4a642c7a6143c42503f93e87bc30

Author: Bas Nieuwenhuizen <[email protected]>
Date:   Sat Aug 20 20:16:30 2022 +0200

radv: Add binding code for 3d sparse images.

GFX7-8 code is kinda expected. For GFX9 and GFX10 the entire
mipchain is duplicated by "layer" even though smaller mips also
have less layers.

Reviewed-by: Samuel Pitoiset <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18165>

---

 src/amd/vulkan/radv_device.c | 45 +++++++++++++++++++++++++++-----------------
 1 file changed, 28 insertions(+), 17 deletions(-)

diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c
index 1a15610bdd2..e2a66da272e 100644
--- a/src/amd/vulkan/radv_device.c
+++ b/src/amd/vulkan/radv_device.c
@@ -4860,7 +4860,7 @@ radv_sparse_image_bind_memory(struct radv_device *device, 
const VkSparseImageMem
 
    for (uint32_t i = 0; i < bind->bindCount; ++i) {
       struct radv_device_memory *mem = NULL;
-      uint32_t offset, pitch;
+      uint32_t offset, pitch, depth_pitch;
       uint32_t mem_offset = bind->pBinds[i].memoryOffset;
       const uint32_t layer = bind->pBinds[i].subresource.arrayLayer;
       const uint32_t level = bind->pBinds[i].subresource.mipLevel;
@@ -4881,36 +4881,47 @@ radv_sparse_image_bind_memory(struct radv_device 
*device, const VkSparseImageMem
       if (device->physical_device->rad_info.gfx_level >= GFX9) {
          offset = surface->u.gfx9.surf_slice_size * layer + 
surface->u.gfx9.prt_level_offset[level];
          pitch = surface->u.gfx9.prt_level_pitch[level];
+         depth_pitch = surface->u.gfx9.surf_slice_size;
       } else {
-         offset = (uint64_t)surface->u.legacy.level[level].offset_256B * 256 +
-                  surface->u.legacy.level[level].slice_size_dw * 4 * layer;
+         depth_pitch = surface->u.legacy.level[level].slice_size_dw * 4;
+         offset = (uint64_t)surface->u.legacy.level[level].offset_256B * 256 + 
depth_pitch * layer;
          pitch = surface->u.legacy.level[level].nblk_x;
       }
 
-      offset += (bind_offset.y * pitch * bs) + (bind_offset.x * 
surface->prt_tile_height * bs);
+      offset += bind_offset.z * depth_pitch +
+                (bind_offset.y * pitch * surface->prt_tile_depth +
+                 bind_offset.x * surface->prt_tile_height * 
surface->prt_tile_depth) *
+                   bs;
 
       uint32_t aligned_extent_width = ALIGN(bind_extent.width, 
surface->prt_tile_width);
+      uint32_t aligned_extent_height = ALIGN(bind_extent.height, 
surface->prt_tile_height);
+      uint32_t aligned_extent_depth = ALIGN(bind_extent.depth, 
surface->prt_tile_depth);
 
-      bool whole_subres = bind_offset.x == 0 && aligned_extent_width == pitch;
+      bool whole_subres =
+         (bind_extent.height <= surface->prt_tile_height || 
aligned_extent_width == pitch) &&
+         (bind_extent.depth <= surface->prt_tile_depth ||
+          aligned_extent_width * aligned_extent_height * bs == depth_pitch);
 
       if (whole_subres) {
-         uint32_t aligned_extent_height = ALIGN(bind_extent.height, 
surface->prt_tile_height);
-
-         uint32_t size = aligned_extent_width * aligned_extent_height * bs;
+         uint32_t size = aligned_extent_width * aligned_extent_height * 
aligned_extent_depth * bs;
          result = device->ws->buffer_virtual_bind(device->ws, 
image->bindings[0].bo, offset, size,
                                                   mem ? mem->bo : NULL, 
mem_offset);
          if (result != VK_SUCCESS)
             return result;
       } else {
-         uint32_t img_increment = pitch * bs;
-         uint32_t mem_increment = aligned_extent_width * bs;
-         uint32_t size = mem_increment * surface->prt_tile_height;
-         for (unsigned y = 0; y < bind_extent.height; y += 
surface->prt_tile_height) {
-            result = device->ws->buffer_virtual_bind(device->ws,
-               image->bindings[0].bo, offset + img_increment * y, size, mem ? 
mem->bo : NULL,
-               mem_offset + mem_increment * y);
-            if (result != VK_SUCCESS)
-               return result;
+         uint32_t img_y_increment = pitch * bs * surface->prt_tile_depth;
+         uint32_t mem_y_increment = aligned_extent_width * bs * 
surface->prt_tile_depth;
+         uint32_t mem_z_increment = aligned_extent_width * 
aligned_extent_height * bs;
+         uint32_t size = mem_y_increment * surface->prt_tile_height;
+         for (unsigned z = 0; z < bind_extent.depth;
+              z += surface->prt_tile_depth, offset += depth_pitch * 
surface->prt_tile_depth) {
+            for (unsigned y = 0; y < bind_extent.height; y += 
surface->prt_tile_height) {
+               result = device->ws->buffer_virtual_bind(
+                  device->ws, image->bindings[0].bo, offset + img_y_increment 
* y, size,
+                  mem ? mem->bo : NULL, mem_offset + mem_y_increment * y + 
mem_z_increment * z);
+               if (result != VK_SUCCESS)
+                  return result;
+            }
          }
       }
    }

Reply via email to