lavapipe: add support for VK_KHR_push_descriptor
authorDave Airlie <airlied@redhat.com>
Fri, 4 Dec 2020 00:24:46 +0000 (10:24 +1000)
committerMarge Bot <eric+marge@anholt.net>
Fri, 11 Dec 2020 21:53:41 +0000 (21:53 +0000)
Acked-by: Adam Jackson <ajax@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7912>

src/gallium/frontends/lavapipe/lvp_cmd_buffer.c
src/gallium/frontends/lavapipe/lvp_device.c
src/gallium/frontends/lavapipe/lvp_execute.c
src/gallium/frontends/lavapipe/lvp_extensions.py
src/gallium/frontends/lavapipe/lvp_private.h

index eff125472ede3f08a277dcf488378e9e05aad0d8..97e4cd20eafefe16a4aa7a3c39e418a637a38838 100644 (file)
@@ -1473,3 +1473,83 @@ void lvp_CmdDrawIndexedIndirectCount(
 
    cmd_buf_queue(cmd_buffer, cmd);
 }
+
+void lvp_CmdPushDescriptorSetKHR(
+   VkCommandBuffer                             commandBuffer,
+   VkPipelineBindPoint                         pipelineBindPoint,
+   VkPipelineLayout                            _layout,
+   uint32_t                                    set,
+   uint32_t                                    descriptorWriteCount,
+   const VkWriteDescriptorSet*                 pDescriptorWrites)
+{
+   LVP_FROM_HANDLE(lvp_cmd_buffer, cmd_buffer, commandBuffer);
+   LVP_FROM_HANDLE(lvp_pipeline_layout, layout, _layout);
+   struct lvp_cmd_buffer_entry *cmd;
+   int cmd_size = 0;
+
+   cmd_size += descriptorWriteCount * sizeof(struct lvp_write_descriptor);
+
+   int count_descriptors = 0;
+
+   for (unsigned i = 0; i < descriptorWriteCount; i++) {
+      count_descriptors += pDescriptorWrites[i].descriptorCount;
+   }
+   cmd_size += count_descriptors * sizeof(union lvp_descriptor_info);
+   cmd = cmd_buf_entry_alloc_size(cmd_buffer, cmd_size, LVP_CMD_PUSH_DESCRIPTOR_SET);
+   if (!cmd)
+      return;
+
+   cmd->u.push_descriptor_set.bind_point = pipelineBindPoint;
+   cmd->u.push_descriptor_set.layout = layout;
+   cmd->u.push_descriptor_set.set = set;
+   cmd->u.push_descriptor_set.descriptor_write_count = descriptorWriteCount;
+   cmd->u.push_descriptor_set.descriptors = (struct lvp_write_descriptor *)(cmd + 1);
+   cmd->u.push_descriptor_set.infos = (union lvp_descriptor_info *)(cmd->u.push_descriptor_set.descriptors + descriptorWriteCount);
+
+   unsigned descriptor_index = 0;
+
+   for (unsigned i = 0; i < descriptorWriteCount; i++) {
+      struct lvp_write_descriptor *desc = &cmd->u.push_descriptor_set.descriptors[i];
+
+      /* dstSet is ignored */
+      desc->dst_binding = pDescriptorWrites[i].dstBinding;
+      desc->dst_array_element = pDescriptorWrites[i].dstArrayElement;
+      desc->descriptor_count = pDescriptorWrites[i].descriptorCount;
+      desc->descriptor_type = pDescriptorWrites[i].descriptorType;
+
+      for (unsigned j = 0; j < desc->descriptor_count; j++) {
+         union lvp_descriptor_info *info = &cmd->u.push_descriptor_set.infos[descriptor_index + j];
+         switch (desc->descriptor_type) {
+         case VK_DESCRIPTOR_TYPE_SAMPLER:
+            info->sampler = lvp_sampler_from_handle(pDescriptorWrites[i].pImageInfo[j].sampler);
+            break;
+         case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+            info->sampler = lvp_sampler_from_handle(pDescriptorWrites[i].pImageInfo[j].sampler);
+            info->iview = lvp_image_view_from_handle(pDescriptorWrites[i].pImageInfo[j].imageView);
+            info->image_layout = pDescriptorWrites[i].pImageInfo[j].imageLayout;
+            break;
+         case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+         case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+         case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
+            info->iview = lvp_image_view_from_handle(pDescriptorWrites[i].pImageInfo[j].imageView);
+            info->image_layout = pDescriptorWrites[i].pImageInfo[j].imageLayout;
+            break;
+         case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+         case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
+            info->buffer_view = lvp_buffer_view_from_handle(pDescriptorWrites[i].pTexelBufferView[j]);
+            break;
+         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
+         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
+         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
+         default:
+            info->buffer = lvp_buffer_from_handle(pDescriptorWrites[i].pBufferInfo[j].buffer);
+            info->offset = pDescriptorWrites[i].pBufferInfo[j].offset;
+            info->range = pDescriptorWrites[i].pBufferInfo[j].range;
+            break;
+         }
+      }
+      descriptor_index += desc->descriptor_count;
+   }
+   cmd_buf_queue(cmd_buffer, cmd);
+}
index e47953f2feb4532114fae05028a8b061d65103f6..2f60b1e9f630133a48ffc9fccdc83b4ba3c59ad5 100644 (file)
@@ -554,6 +554,12 @@ void lvp_GetPhysicalDeviceProperties2(
    vk_foreach_struct(ext, pProperties->pNext) {
       switch (ext->sType) {
 
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: {
+         VkPhysicalDevicePushDescriptorPropertiesKHR *properties =
+            (VkPhysicalDevicePushDescriptorPropertiesKHR *) ext;
+         properties->maxPushDescriptors = MAX_PUSH_DESCRIPTORS;
+         break;
+      }
       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES: {
          VkPhysicalDeviceMaintenance3Properties *properties =
             (VkPhysicalDeviceMaintenance3Properties*)ext;
index 100642ffd2d7005ee7723a57abdf814f7d558705..e397cceb92bc35c28a49349b8423fb8fa3782cee 100644 (file)
@@ -752,7 +752,7 @@ static void fill_sampler_stage(struct rendering_state *state,
       return;
    ss_idx += array_idx;
    ss_idx += dyn_info->stage[stage].sampler_count;
-   fill_sampler(&state->ss[p_stage][ss_idx], descriptor->sampler);
+   fill_sampler(&state->ss[p_stage][ss_idx], binding->immutable_samplers ? binding->immutable_samplers[array_idx] : descriptor->sampler);
    if (state->num_sampler_states[p_stage] <= ss_idx)
       state->num_sampler_states[p_stage] = ss_idx + 1;
    state->ss_dirty[p_stage] = true;
@@ -2335,6 +2335,90 @@ static void handle_draw_indirect_count(struct lvp_cmd_buffer_entry *cmd,
    state->pctx->draw_vbo(state->pctx, &state->info, &state->indirect_info, &state->draw, 1);
 }
 
+static void handle_compute_push_descriptor_set(struct lvp_cmd_buffer_entry *cmd,
+                                               struct dyn_info *dyn_info,
+                                               struct rendering_state *state)
+{
+   struct lvp_cmd_push_descriptor_set *pds = &cmd->u.push_descriptor_set;
+   struct lvp_descriptor_set_layout *layout = pds->layout->set[pds->set].layout;
+
+   if (!(layout->shader_stages & VK_SHADER_STAGE_COMPUTE_BIT))
+      return;
+
+   unsigned info_idx = 0;
+   for (unsigned i = 0; i < pds->descriptor_write_count; i++) {
+      struct lvp_write_descriptor *desc = &pds->descriptors[i];
+      struct lvp_descriptor_set_binding_layout *binding = &layout->binding[desc->dst_binding];
+
+      if (!binding->valid)
+         continue;
+
+      for (unsigned j = 0; j < desc->descriptor_count; j++) {
+         union lvp_descriptor_info *info = &pds->infos[info_idx + j];
+
+         handle_descriptor(state, dyn_info, binding,
+                           MESA_SHADER_COMPUTE, PIPE_SHADER_COMPUTE,
+                           j, desc->descriptor_type,
+                           info);
+      }
+      info_idx += desc->descriptor_count;
+   }
+}
+
+static void handle_push_descriptor_set(struct lvp_cmd_buffer_entry *cmd,
+                                       struct rendering_state *state)
+{
+   struct lvp_cmd_push_descriptor_set *pds = &cmd->u.push_descriptor_set;
+   struct lvp_descriptor_set_layout *layout = pds->layout->set[pds->set].layout;
+   struct dyn_info dyn_info;
+
+   memset(&dyn_info.stage, 0, sizeof(dyn_info.stage));
+   dyn_info.dyn_index = 0;
+   if (pds->bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
+      handle_compute_push_descriptor_set(cmd, &dyn_info, state);
+   }
+
+   unsigned info_idx = 0;
+   for (unsigned i = 0; i < pds->descriptor_write_count; i++) {
+      struct lvp_write_descriptor *desc = &pds->descriptors[i];
+      struct lvp_descriptor_set_binding_layout *binding = &layout->binding[desc->dst_binding];
+
+      if (!binding->valid)
+         continue;
+
+      for (unsigned j = 0; j < desc->descriptor_count; j++) {
+         union lvp_descriptor_info *info = &pds->infos[info_idx + j];
+
+         if (layout->shader_stages & VK_SHADER_STAGE_VERTEX_BIT)
+            handle_descriptor(state, &dyn_info, binding,
+                              MESA_SHADER_VERTEX, PIPE_SHADER_VERTEX,
+                              j, desc->descriptor_type,
+                              info);
+         if (layout->shader_stages & VK_SHADER_STAGE_FRAGMENT_BIT)
+            handle_descriptor(state, &dyn_info, binding,
+                              MESA_SHADER_FRAGMENT, PIPE_SHADER_FRAGMENT,
+                              j, desc->descriptor_type,
+                              info);
+         if (layout->shader_stages & VK_SHADER_STAGE_GEOMETRY_BIT)
+            handle_descriptor(state, &dyn_info, binding,
+                              MESA_SHADER_GEOMETRY, PIPE_SHADER_GEOMETRY,
+                              j, desc->descriptor_type,
+                              info);
+         if (layout->shader_stages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
+            handle_descriptor(state, &dyn_info, binding,
+                              MESA_SHADER_TESS_CTRL, PIPE_SHADER_TESS_CTRL,
+                              j, desc->descriptor_type,
+                              info);
+         if (layout->shader_stages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
+            handle_descriptor(state, &dyn_info, binding,
+                              MESA_SHADER_TESS_EVAL, PIPE_SHADER_TESS_EVAL,
+                              j, desc->descriptor_type,
+                              info);
+      }
+      info_idx += desc->descriptor_count;
+   }
+}
+
 static void lvp_execute_cmd_buffer(struct lvp_cmd_buffer *cmd_buffer,
                                    struct rendering_state *state)
 {
@@ -2486,6 +2570,9 @@ static void lvp_execute_cmd_buffer(struct lvp_cmd_buffer *cmd_buffer,
          emit_state(state);
          handle_draw_indirect_count(cmd, state, true);
          break;
+      case LVP_CMD_PUSH_DESCRIPTOR_SET:
+         handle_push_descriptor_set(cmd, state);
+         break;
       }
    }
 }
index e790aee50de9b7d12f6a4108cb07bc745394ea13..c04fb0798604c8224fb6ec3134e39f72bb0b0094 100644 (file)
@@ -87,7 +87,7 @@ EXTENSIONS = [
     Extension('VK_KHR_maintenance2',                      1, False),
     Extension('VK_KHR_maintenance3',                      1, False),
     Extension('VK_KHR_pipeline_executable_properties',    1, False),
-    Extension('VK_KHR_push_descriptor',                   1, False),
+    Extension('VK_KHR_push_descriptor',                   1, True),
     Extension('VK_KHR_relaxed_block_layout',              1, True),
     Extension('VK_KHR_sampler_mirror_clamp_to_edge',      1, True),
     Extension('VK_KHR_sampler_ycbcr_conversion',          1, False),
index b21cfba425f0d34a82f029debdb81b84da9ef53b..03f4cfa454e2c74e2c8e1667732933274a61b0d0 100644 (file)
@@ -63,6 +63,7 @@ extern "C" {
 
 #define MAX_SETS         8
 #define MAX_PUSH_CONSTANTS_SIZE 128
+#define MAX_PUSH_DESCRIPTORS 32
 
 #define lvp_printflike(a, b) __attribute__((__format__(__printf__, a, b)))
 
@@ -646,6 +647,7 @@ enum lvp_cmds {
    LVP_CMD_EXECUTE_COMMANDS,
    LVP_CMD_DRAW_INDIRECT_COUNT,
    LVP_CMD_DRAW_INDEXED_INDIRECT_COUNT,
+   LVP_CMD_PUSH_DESCRIPTOR_SET,
 };
 
 struct lvp_cmd_bind_pipeline {
@@ -919,6 +921,22 @@ struct lvp_cmd_draw_indirect_count {
    uint32_t stride;
 };
 
+struct lvp_write_descriptor {
+   uint32_t dst_binding;
+   uint32_t dst_array_element;
+   uint32_t descriptor_count;
+   VkDescriptorType descriptor_type;
+};
+
+struct lvp_cmd_push_descriptor_set {
+   VkPipelineBindPoint bind_point;
+   struct lvp_pipeline_layout *layout;
+   uint32_t set;
+   uint32_t descriptor_write_count;
+   struct lvp_write_descriptor *descriptors;
+   union lvp_descriptor_info *infos;
+};
+
 struct lvp_cmd_buffer_entry {
    struct list_head cmd_link;
    uint32_t cmd_type;
@@ -960,6 +978,7 @@ struct lvp_cmd_buffer_entry {
       struct lvp_cmd_next_subpass next_subpass;
       struct lvp_cmd_execute_commands execute_commands;
       struct lvp_cmd_draw_indirect_count draw_indirect_count;
+      struct lvp_cmd_push_descriptor_set push_descriptor_set;
    } u;
 };