diff --git a/src/gallium/frontends/lavapipe/lvp_cmd_buffer.c b/src/gallium/frontends/lavapipe/lvp_cmd_buffer.c index eff125472ed..97e4cd20eaf 100644 --- a/src/gallium/frontends/lavapipe/lvp_cmd_buffer.c +++ b/src/gallium/frontends/lavapipe/lvp_cmd_buffer.c @@ -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); +} diff --git a/src/gallium/frontends/lavapipe/lvp_device.c b/src/gallium/frontends/lavapipe/lvp_device.c index e47953f2feb..2f60b1e9f63 100644 --- a/src/gallium/frontends/lavapipe/lvp_device.c +++ b/src/gallium/frontends/lavapipe/lvp_device.c @@ -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; diff --git a/src/gallium/frontends/lavapipe/lvp_execute.c b/src/gallium/frontends/lavapipe/lvp_execute.c index 100642ffd2d..e397cceb92b 100644 --- a/src/gallium/frontends/lavapipe/lvp_execute.c +++ b/src/gallium/frontends/lavapipe/lvp_execute.c @@ -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; } } } diff --git a/src/gallium/frontends/lavapipe/lvp_extensions.py b/src/gallium/frontends/lavapipe/lvp_extensions.py index e790aee50de..c04fb079860 100644 --- a/src/gallium/frontends/lavapipe/lvp_extensions.py +++ b/src/gallium/frontends/lavapipe/lvp_extensions.py @@ -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), diff --git a/src/gallium/frontends/lavapipe/lvp_private.h b/src/gallium/frontends/lavapipe/lvp_private.h index b21cfba425f..03f4cfa454e 100644 --- a/src/gallium/frontends/lavapipe/lvp_private.h +++ b/src/gallium/frontends/lavapipe/lvp_private.h @@ -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; };