diff --git a/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c b/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c index bf17b390c72..8e1f375e1f0 100644 --- a/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c +++ b/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c @@ -311,7 +311,9 @@ prepare_vs_driver_set(struct panvk_cmd_buffer *cmdbuf, emit_vs_attrib(cmdbuf, i, vb_offset, (struct mali_attribute_packed *)(&descs[i])); } else { - memset(&descs[i], 0, sizeof(descs[0])); + /* Write a NullDescriptor and rely on OOB behavior */ + pan_cast_and_pack(&descs[i], NULL_DESCRIPTOR, cfg) + ; } } @@ -326,15 +328,17 @@ prepare_vs_driver_set(struct panvk_cmd_buffer *cmdbuf, for (uint32_t i = 0; i < vb_count; i++) { const struct panvk_attrib_buf *vb = &cmdbuf->state.gfx.vb.bufs[i]; + const bool nulldesc = (vb->address == 0 && vb->size == 0); - pan_cast_and_pack(&descs[vb_offset + i], BUFFER, cfg) { - if (vi->bindings_valid & BITFIELD_BIT(i)) { + if ((vi->bindings_valid & BITFIELD_BIT(i)) && !nulldesc) { + pan_cast_and_pack(&descs[vb_offset + i], BUFFER, cfg) { cfg.address = vb->address; cfg.size = vb->size; - } else { - cfg.address = 0; - cfg.size = 0; } + } else { + /* Write a NullDescriptor and rely on OOB behavior */ + pan_cast_and_pack(&descs[vb_offset + i], NULL_DESCRIPTOR, cfg) + ; } } @@ -2634,7 +2638,7 @@ panvk_per_arch(CmdDrawIndexedIndirect)(VkCommandBuffer commandBuffer, VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); VK_FROM_HANDLE(panvk_buffer, buffer, _buffer); - if (drawCount == 0 || cmdbuf->state.gfx.ib.size == 0) + if (drawCount == 0) return; struct panvk_draw_info draw = { @@ -2687,7 +2691,7 @@ panvk_per_arch(CmdDrawIndexedIndirectCount)(VkCommandBuffer commandBuffer, VK_FROM_HANDLE(panvk_buffer, buffer, _buffer); VK_FROM_HANDLE(panvk_buffer, count_buffer, countBuffer); - if (maxDrawCount == 0 || cmdbuf->state.gfx.ib.size == 0) + if (maxDrawCount == 0) return; struct panvk_draw_info draw = { diff --git a/src/panfrost/vulkan/panvk_vX_cmd_draw.c b/src/panfrost/vulkan/panvk_vX_cmd_draw.c index 9d9eee0186f..1a21a32e31f 100644 --- a/src/panfrost/vulkan/panvk_vX_cmd_draw.c +++ b/src/panfrost/vulkan/panvk_vX_cmd_draw.c @@ -872,10 +872,15 @@ panvk_per_arch(CmdBindVertexBuffers2)(VkCommandBuffer commandBuffer, for (uint32_t i = 0; i < bindingCount; i++) { VK_FROM_HANDLE(panvk_buffer, buffer, pBuffers[i]); - cmdbuf->state.gfx.vb.bufs[firstBinding + i].address = - panvk_buffer_gpu_ptr(buffer, pOffsets[i]); - cmdbuf->state.gfx.vb.bufs[firstBinding + i].size = panvk_buffer_range( - buffer, pOffsets[i], pSizes ? pSizes[i] : VK_WHOLE_SIZE); + if (buffer) { + cmdbuf->state.gfx.vb.bufs[firstBinding + i].address = + panvk_buffer_gpu_ptr(buffer, pOffsets[i]); + cmdbuf->state.gfx.vb.bufs[firstBinding + i].size = panvk_buffer_range( + buffer, pOffsets[i], pSizes ? pSizes[i] : VK_WHOLE_SIZE); + } else { + cmdbuf->state.gfx.vb.bufs[firstBinding + i].address = 0; + cmdbuf->state.gfx.vb.bufs[firstBinding + i].size = 0; + } } cmdbuf->state.gfx.vb.count = @@ -899,15 +904,18 @@ panvk_per_arch(CmdBindIndexBuffer2)(VkCommandBuffer commandBuffer, cmdbuf->state.gfx.ib.host_addr = buf && buf->host_ptr ? buf->host_ptr + offset : NULL; #endif - cmdbuf->state.gfx.ib.index_size = vk_index_type_to_bytes(indexType); } else { cmdbuf->state.gfx.ib.size = 0; - cmdbuf->state.gfx.ib.dev_addr = 0; + /* In case of NullDescriptors, we need to set a non-NULL address and rely + * on out-of-bounds behavior against the zero size of the buffer. Note + * that this only works for v10+, as v9 does not have a way to specify the + * index buffer size. */ + cmdbuf->state.gfx.ib.dev_addr = PAN_ARCH >= 10 ? 0x1000 : 0; #if PAN_ARCH < 9 cmdbuf->state.gfx.ib.host_addr = 0; #endif - cmdbuf->state.gfx.ib.index_size = 0; } + cmdbuf->state.gfx.ib.index_size = vk_index_type_to_bytes(indexType); gfx_state_set_dirty(cmdbuf, IB); } diff --git a/src/panfrost/vulkan/panvk_vX_descriptor_set.c b/src/panfrost/vulkan/panvk_vX_descriptor_set.c index 14ecf639160..8a8590551cc 100644 --- a/src/panfrost/vulkan/panvk_vX_descriptor_set.c +++ b/src/panfrost/vulkan/panvk_vX_descriptor_set.c @@ -55,6 +55,20 @@ get_desc_slot_ptr(struct panvk_descriptor_set *set, uint32_t binding, memcpy(__dst, (desc), PANVK_DESCRIPTOR_SIZE); \ } while (0) +#if PAN_ARCH >= 9 +#define write_nulldesc(set, binding, elem, subdesc) \ + do { \ + struct mali_null_descriptor_packed null_desc; \ + pan_pack(&null_desc, NULL_DESCRIPTOR, cfg) \ + ; \ + write_desc(set, binding, elem, &null_desc, (subdesc)); \ + } while (0) +#else +#define write_nulldesc(set, binding, elem, subdesc) \ + do { \ + } while (0) +#endif + static void write_sampler_desc(struct panvk_descriptor_set *set, const VkDescriptorImageInfo *const pImageInfo, @@ -63,20 +77,25 @@ write_sampler_desc(struct panvk_descriptor_set *set, const struct panvk_descriptor_set_binding_layout *binding_layout = &set->layout->bindings[binding]; - if (binding_layout->immutable_samplers && !write_immutable) - return; - struct panvk_sampler *sampler; if (binding_layout->immutable_samplers) { + if (!write_immutable) + return; sampler = binding_layout->immutable_samplers[elem]; } else { - sampler = panvk_sampler_from_handle( - pImageInfo ? pImageInfo->sampler : VK_NULL_HANDLE); + if (!pImageInfo) + return; + sampler = panvk_sampler_from_handle(pImageInfo->sampler); } - if (!sampler) + if (!sampler) { + for (uint8_t plane = 0; plane < binding_layout->samplers_per_desc; + plane++) + write_nulldesc(set, binding, elem, + get_sampler_subdesc_info(binding_layout->type, plane)); return; + } for (uint8_t plane = 0; plane < sampler->desc_count; plane++) { write_desc(set, binding, elem, &sampler->descs[plane], @@ -89,26 +108,38 @@ write_image_view_desc(struct panvk_descriptor_set *set, const VkDescriptorImageInfo *const pImageInfo, uint32_t binding, uint32_t elem, VkDescriptorType type) { - if (pImageInfo && pImageInfo->imageView != VK_NULL_HANDLE) { - VK_FROM_HANDLE(panvk_image_view, view, pImageInfo->imageView); + if (!pImageInfo) + return; - uint8_t plane_count = vk_format_get_plane_count(view->vk.format); - for (uint8_t plane = 0; plane < plane_count; plane++) { - struct panvk_subdesc_info subdesc = get_tex_subdesc_info(type, plane); + const struct panvk_descriptor_set_binding_layout *binding_layout = + &set->layout->bindings[binding]; + + if (pImageInfo->imageView == VK_NULL_HANDLE) { + for (uint8_t plane = 0; plane < binding_layout->textures_per_desc; + plane++) + write_nulldesc(set, binding, elem, + get_sampler_subdesc_info(binding_layout->type, plane)); + return; + } + + VK_FROM_HANDLE(panvk_image_view, view, pImageInfo->imageView); + + uint8_t plane_count = vk_format_get_plane_count(view->vk.format); + for (uint8_t plane = 0; plane < plane_count; plane++) { + struct panvk_subdesc_info subdesc = get_tex_subdesc_info(type, plane); #if PAN_ARCH >= 9 - if (type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) - write_desc(set, binding, elem, &view->descs.storage_tex[plane], - subdesc); - else - write_desc(set, binding, elem, &view->descs.tex[plane], subdesc); + if (type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) + write_desc(set, binding, elem, &view->descs.storage_tex[plane], + subdesc); + else + write_desc(set, binding, elem, &view->descs.tex[plane], subdesc); #else - if (type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) - write_desc(set, binding, elem, &view->descs.img_attrib_buf, - NO_SUBDESC); - else - write_desc(set, binding, elem, &view->descs.tex[plane], subdesc); + if (type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) + write_desc(set, binding, elem, &view->descs.img_attrib_buf, + NO_SUBDESC); + else + write_desc(set, binding, elem, &view->descs.tex[plane], subdesc); #endif - } } } @@ -117,6 +148,11 @@ write_buffer_desc(struct panvk_descriptor_set *set, const VkDescriptorBufferInfo *const info, uint32_t binding, uint32_t elem, VkDescriptorType type) { + if (info->buffer == VK_NULL_HANDLE) { + write_nulldesc(set, binding, elem, NO_SUBDESC); + return; + } + VK_FROM_HANDLE(panvk_buffer, buffer, info->buffer); const uint64_t range = panvk_buffer_range(buffer, info->offset, info->range); assert(range <= UINT32_MAX); @@ -158,6 +194,11 @@ write_dynamic_buffer_desc(struct panvk_descriptor_set *set, const VkDescriptorBufferInfo *const info, uint32_t binding, uint32_t elem) { + if (info->buffer == VK_NULL_HANDLE) { + write_nulldesc(set, binding, elem, NO_SUBDESC); + return; + } + VK_FROM_HANDLE(panvk_buffer, buffer, info->buffer); const struct panvk_descriptor_set_binding_layout *binding_layout = &set->layout->bindings[binding]; @@ -177,19 +218,21 @@ write_buffer_view_desc(struct panvk_descriptor_set *set, const VkBufferView bufferView, uint32_t binding, uint32_t elem, VkDescriptorType type) { - if (bufferView != VK_NULL_HANDLE) { - VK_FROM_HANDLE(panvk_buffer_view, view, bufferView); + if (bufferView == VK_NULL_HANDLE) { + write_nulldesc(set, binding, elem, NO_SUBDESC); + return; + } + + VK_FROM_HANDLE(panvk_buffer_view, view, bufferView); #if PAN_ARCH < 9 - if (type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) - write_desc(set, binding, elem, &view->descs.img_attrib_buf, - NO_SUBDESC); - else - write_desc(set, binding, elem, &view->descs.tex, NO_SUBDESC); -#else + if (type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) + write_desc(set, binding, elem, &view->descs.img_attrib_buf, NO_SUBDESC); + else write_desc(set, binding, elem, &view->descs.tex, NO_SUBDESC); +#else + write_desc(set, binding, elem, &view->descs.tex, NO_SUBDESC); #endif - } } static void @@ -340,6 +383,14 @@ desc_set_write_immutable_samplers(struct panvk_descriptor_set *set, for (uint32_t j = 0; j < array_size; j++) { struct panvk_sampler *sampler = layout->bindings[b].immutable_samplers[j]; + if (!sampler) { + for (uint8_t plane = 0; + plane < layout->bindings[b].samplers_per_desc; plane++) + write_nulldesc( + set, b, j, + get_sampler_subdesc_info(layout->bindings[b].type, plane)); + continue; + } for (uint8_t plane = 0; plane < sampler->desc_count; plane++) { write_desc(set, b, j, &sampler->descs[plane],