const uint32_t *pDynamicOffsets)
{
TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
+ TU_FROM_HANDLE(tu_pipeline_layout, layout, _layout);
+ unsigned dyn_idx = 0;
struct tu_descriptor_state *descriptors_state =
tu_get_descriptors_state(cmd_buffer, pipelineBindPoint);
descriptors_state->sets[idx] = set;
descriptors_state->valid |= (1u << idx);
+
+ for(unsigned j = 0; j < set->layout->dynamic_offset_count; ++j, ++dyn_idx) {
+ unsigned idx = j + layout->set[i + firstSet].dynamic_offset_start;
+ assert(dyn_idx < dynamicOffsetCount);
+
+ descriptors_state->dynamic_buffers[idx] =
+ set->dynamic_descriptors[j].va + pDynamicOffsets[dyn_idx];
+ }
}
cmd_buffer->state.dirty |= TU_CMD_DIRTY_DESCRIPTOR_SETS;
struct tu_cs_entry ib;
};
+static struct tu_sampler*
+sampler_ptr(struct tu_descriptor_state *descriptors_state,
+ const struct tu_descriptor_map *map, unsigned i)
+{
+ assert(descriptors_state->valid & (1 << map->set[i]));
+
+ struct tu_descriptor_set *set = descriptors_state->sets[map->set[i]];
+ assert(map->binding[i] < set->layout->binding_count);
+
+ const struct tu_descriptor_set_binding_layout *layout =
+ &set->layout->binding[map->binding[i]];
+
+ switch (layout->type) {
+ case VK_DESCRIPTOR_TYPE_SAMPLER:
+ return (struct tu_sampler*) &set->mapped_ptr[layout->offset / 4];
+ case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+ return (struct tu_sampler*) &set->mapped_ptr[layout->offset / 4 + A6XX_TEX_CONST_DWORDS];
+ default:
+ unreachable("unimplemented descriptor type");
+ break;
+ }
+}
+
static uint32_t*
-map_get(struct tu_descriptor_state *descriptors_state,
- const struct tu_descriptor_map *map, unsigned i)
+texture_ptr(struct tu_descriptor_state *descriptors_state,
+ const struct tu_descriptor_map *map, unsigned i)
{
assert(descriptors_state->valid & (1 << map->set[i]));
struct tu_descriptor_set *set = descriptors_state->sets[map->set[i]];
+ assert(map->binding[i] < set->layout->binding_count);
+ const struct tu_descriptor_set_binding_layout *layout =
+ &set->layout->binding[map->binding[i]];
+
+ switch (layout->type) {
+ case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+ case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+ return &set->mapped_ptr[layout->offset / 4];
+ case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+ case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
+ return &set->mapped_ptr[layout->offset / 4];
+ default:
+ unreachable("unimplemented descriptor type");
+ break;
+ }
+}
+
+static uint64_t
+buffer_ptr(struct tu_descriptor_state *descriptors_state,
+ const struct tu_descriptor_map *map,
+ unsigned i)
+{
+ assert(descriptors_state->valid & (1 << map->set[i]));
+
+ struct tu_descriptor_set *set = descriptors_state->sets[map->set[i]];
assert(map->binding[i] < set->layout->binding_count);
- return &set->mapped_ptr[set->layout->binding[map->binding[i]].offset / 4];
+ const struct tu_descriptor_set_binding_layout *layout =
+ &set->layout->binding[map->binding[i]];
+
+ switch (layout->type) {
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
+ return descriptors_state->dynamic_buffers[layout->dynamic_offset_offset];
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
+ return (uint64_t) set->mapped_ptr[layout->offset / 4 + 1] << 32 |
+ set->mapped_ptr[layout->offset / 4];
+ default:
+ unreachable("unimplemented descriptor type");
+ break;
+ }
}
static inline uint32_t
for (uint32_t i = 0; i < ARRAY_SIZE(state->range); i++) {
if (state->range[i].start < state->range[i].end) {
- uint32_t *ptr = map_get(descriptors_state, &link->ubo_map, i - 1);
-
uint32_t size = state->range[i].end - state->range[i].start;
uint32_t offset = state->range[i].start;
continue;
}
+ uint64_t va = buffer_ptr(descriptors_state, &link->ubo_map, i - 1);
+
tu_cs_emit_pkt7(cs, tu6_stage2opcode(type), 3);
tu_cs_emit(cs, CP_LOAD_STATE6_0_DST_OFF(state->range[i].offset / 16) |
CP_LOAD_STATE6_0_STATE_TYPE(ST6_CONSTANTS) |
CP_LOAD_STATE6_0_STATE_SRC(SS6_INDIRECT) |
CP_LOAD_STATE6_0_STATE_BLOCK(tu6_stage2shadersb(type)) |
CP_LOAD_STATE6_0_NUM_UNIT(size / 16));
- tu_cs_emit_qw(cs, ((uint64_t) ptr[1] << 32 | ptr[0]) + offset);
+ tu_cs_emit_qw(cs, va + offset);
}
}
}
const struct tu_program_descriptor_linkage *link =
&pipeline->program.link[type];
- uint32_t anum = align(link->ubo_map.num, 2);
+ uint32_t num = MIN2(link->ubo_map.num, link->const_state.num_ubos);
+ uint32_t anum = align(num, 2);
uint32_t i;
- if (!link->ubo_map.num)
+ if (!num)
return;
tu_cs_emit_pkt7(cs, tu6_stage2opcode(type), 3 + (2 * anum));
- tu_cs_emit(cs, CP_LOAD_STATE6_0_DST_OFF(link->offset_ubo) |
+ tu_cs_emit(cs, CP_LOAD_STATE6_0_DST_OFF(link->const_state.offsets.ubo) |
CP_LOAD_STATE6_0_STATE_TYPE(ST6_CONSTANTS) |
CP_LOAD_STATE6_0_STATE_SRC(SS6_DIRECT) |
CP_LOAD_STATE6_0_STATE_BLOCK(tu6_stage2shadersb(type)) |
tu_cs_emit(cs, CP_LOAD_STATE6_1_EXT_SRC_ADDR(0));
tu_cs_emit(cs, CP_LOAD_STATE6_2_EXT_SRC_ADDR_HI(0));
- for (i = 0; i < link->ubo_map.num; i++) {
- uint32_t *ptr = map_get(descriptors_state, &link->ubo_map, i);
- tu_cs_emit(cs, ptr[0]);
- tu_cs_emit(cs, ptr[1]);
- }
+ for (i = 0; i < num; i++)
+ tu_cs_emit_qw(cs, buffer_ptr(descriptors_state, &link->ubo_map, i));
for (; i < anum; i++) {
tu_cs_emit(cs, 0xffffffff);
tu_cs_begin_sub_stream(device, draw_state, size, &cs);
for (unsigned i = 0; i < link->texture_map.num; i++) {
- uint32_t *ptr = map_get(descriptors_state, &link->texture_map, i);
+ uint32_t *ptr = texture_ptr(descriptors_state, &link->texture_map, i);
for (unsigned j = 0; j < A6XX_TEX_CONST_DWORDS; j++)
tu_cs_emit(&cs, ptr[j]);
}
for (unsigned i = 0; i < link->sampler_map.num; i++) {
- uint32_t *ptr = map_get(descriptors_state, &link->sampler_map, i);
- struct tu_sampler *sampler = (void*) &ptr[A6XX_TEX_CONST_DWORDS];
+ struct tu_sampler *sampler = sampler_ptr(descriptors_state, &link->sampler_map, i);
for (unsigned j = 0; j < A6XX_TEX_SAMP_DWORDS; j++)
tu_cs_emit(&cs, sampler->state[j]);
descriptor_size(enum VkDescriptorType type)
{
switch (type) {
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
+ return 0;
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
- /* UBO pointer */
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
+ case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+ case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
+ /* 64bit pointer */
return 8;
+ case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+ case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+ case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
+ return A6XX_TEX_CONST_DWORDS*4;
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
/* texture const + tu_sampler struct (includes border color) */
return A6XX_TEX_CONST_DWORDS*4 + sizeof(struct tu_sampler);
+ case VK_DESCRIPTOR_TYPE_SAMPLER:
+ return sizeof(struct tu_sampler);
default:
unreachable("unknown descriptor type\n");
return 0;
DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT);
uint32_t max_binding = 0;
- for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++)
+ uint32_t immutable_sampler_count = 0;
+ for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) {
max_binding = MAX2(max_binding, pCreateInfo->pBindings[j].binding);
+ if ((pCreateInfo->pBindings[j].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
+ pCreateInfo->pBindings[j].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) &&
+ pCreateInfo->pBindings[j].pImmutableSamplers) {
+ immutable_sampler_count += pCreateInfo->pBindings[j].descriptorCount;
+ }
+ }
- uint32_t size =
- sizeof(struct tu_descriptor_set_layout) +
+ uint32_t samplers_offset = sizeof(struct tu_descriptor_set_layout) +
(max_binding + 1) * sizeof(set_layout->binding[0]);
+ uint32_t size = samplers_offset + immutable_sampler_count * sizeof(struct tu_sampler);
set_layout = vk_alloc2(&device->alloc, pAllocator, size, 8,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
set_layout->flags = pCreateInfo->flags;
/* We just allocate all the samplers at the end of the struct */
- uint32_t *samplers = (uint32_t *) &set_layout->binding[max_binding + 1];
- (void) samplers; /* TODO: Use me */
+ struct tu_sampler *samplers = (void*) &set_layout->binding[max_binding + 1];
VkDescriptorSetLayoutBinding *bindings = create_sorted_bindings(
pCreateInfo->pBindings, pCreateInfo->bindingCount);
for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) {
const VkDescriptorSetLayoutBinding *binding = bindings + j;
uint32_t b = binding->binding;
- uint32_t alignment = 8;
+ uint32_t alignment = 4;
unsigned binding_buffer_count = 1;
+ switch (binding->descriptorType) {
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
+ assert(!(pCreateInfo->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR));
+ set_layout->binding[b].dynamic_offset_count = 1;
+ break;
+ default:
+ break;
+ }
+
set_layout->size = align(set_layout->size, alignment);
set_layout->binding[b].type = binding->descriptorType;
set_layout->binding[b].array_size = binding->descriptorCount;
set_layout->has_variable_descriptors = true;
}
+ if ((binding->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
+ binding->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) &&
+ binding->pImmutableSamplers) {
+ set_layout->binding[b].immutable_samplers_offset = samplers_offset;
+ set_layout->has_immutable_samplers = true;
+
+ for (uint32_t i = 0; i < binding->descriptorCount; i++)
+ samplers[i] = *tu_sampler_from_handle(binding->pImmutableSamplers[i]);
+
+ samplers += binding->descriptorCount;
+ samplers_offset += sizeof(struct tu_sampler) * binding->descriptorCount;
+ }
+
set_layout->size +=
binding->descriptorCount * set_layout->binding[b].size;
buffer_count += binding->descriptorCount * binding_buffer_count;
if (pCreateInfo->pPoolSizes[i].type != VK_DESCRIPTOR_TYPE_SAMPLER)
bo_count += pCreateInfo->pPoolSizes[i].descriptorCount;
+ switch(pCreateInfo->pPoolSizes[i].type) {
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
+ range_count += pCreateInfo->pPoolSizes[i].descriptorCount;
+ default:
+ break;
+ }
+
bo_size += descriptor_size(pCreateInfo->pPoolSizes[i].type) *
pCreateInfo->pPoolSizes[i].descriptorCount;
}
return VK_SUCCESS;
}
+static void write_texel_buffer_descriptor(struct tu_device *device,
+ struct tu_cmd_buffer *cmd_buffer,
+ unsigned *dst,
+ struct tu_bo **buffer_list,
+ const VkBufferView _buffer_view)
+{
+ TU_FROM_HANDLE(tu_buffer_view, buffer_view, _buffer_view);
+
+ tu_finishme("texel buffer descriptor");
+}
+
static void write_buffer_descriptor(struct tu_device *device,
struct tu_cmd_buffer *cmd_buffer,
unsigned *dst,
*buffer_list = buffer->bo;
}
+static void write_dynamic_buffer_descriptor(struct tu_device *device,
+ struct tu_descriptor_range *range,
+ struct tu_bo **buffer_list,
+ const VkDescriptorBufferInfo *buffer_info)
+{
+ TU_FROM_HANDLE(tu_buffer, buffer, buffer_info->buffer);
+ uint64_t va = buffer->bo->iova;
+ unsigned size = buffer_info->range;
+
+ if (buffer_info->range == VK_WHOLE_SIZE)
+ size = buffer->size - buffer_info->offset;
+
+ va += buffer_info->offset + buffer->bo_offset;
+ range->va = va;
+ range->size = size;
+
+ *buffer_list = buffer->bo;
+}
+
static void
write_image_descriptor(struct tu_device *device,
struct tu_cmd_buffer *cmd_buffer,
- unsigned size, unsigned *dst,
+ unsigned *dst,
struct tu_bo **buffer_list,
VkDescriptorType descriptor_type,
const VkDescriptorImageInfo *image_info)
{
TU_FROM_HANDLE(tu_sampler, sampler, image_info->sampler);
- write_image_descriptor(device, cmd_buffer, sampler_offset, dst, buffer_list,
+ write_image_descriptor(device, cmd_buffer, dst, buffer_list,
descriptor_type, image_info);
/* copy over sampler state */
if (has_sampler) {
}
}
+static void
+write_sampler_descriptor(struct tu_device *device,
+ unsigned *dst,
+ const VkDescriptorImageInfo *image_info)
+{
+ TU_FROM_HANDLE(tu_sampler, sampler, image_info->sampler);
+
+ memcpy(dst, sampler, sizeof(*sampler));
+}
+
void
tu_update_descriptor_sets(struct tu_device *device,
struct tu_cmd_buffer *cmd_buffer,
uint32_t *ptr = set->mapped_ptr;
struct tu_bo **buffer_list = set->descriptors;
+ const struct tu_sampler *samplers = tu_immutable_samplers(set->layout, binding_layout);
+
ptr += binding_layout->offset / 4;
ptr += binding_layout->size * writeset->dstArrayElement / 4;
buffer_list += writeset->dstArrayElement;
for (j = 0; j < writeset->descriptorCount; ++j) {
switch(writeset->descriptorType) {
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
+ unsigned idx = writeset->dstArrayElement + j;
+ idx += binding_layout->dynamic_offset_offset;
+ assert(!(set->layout->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR));
+ write_dynamic_buffer_descriptor(device, set->dynamic_descriptors + idx,
+ buffer_list, writeset->pBufferInfo + j);
+ break;
+ }
+
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
write_buffer_descriptor(device, cmd_buffer, ptr, buffer_list,
writeset->pBufferInfo + j);
break;
+ case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+ case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
+ write_texel_buffer_descriptor(device, cmd_buffer, ptr, buffer_list,
+ writeset->pTexelBufferView[j]);
+ break;
+ case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+ case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+ case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
+ write_image_descriptor(device, cmd_buffer, ptr, buffer_list,
+ writeset->descriptorType,
+ writeset->pImageInfo + j);
+ break;
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
write_combined_image_sampler_descriptor(device, cmd_buffer,
A6XX_TEX_CONST_DWORDS*4,
writeset->descriptorType,
writeset->pImageInfo + j,
!binding_layout->immutable_samplers_offset);
+ if (binding_layout->immutable_samplers_offset) {
+ const unsigned idx = writeset->dstArrayElement + j;
+ memcpy((char*)ptr + A6XX_TEX_CONST_DWORDS*4, &samplers[idx],
+ sizeof(struct tu_sampler));
+ }
+ break;
+ case VK_DESCRIPTOR_TYPE_SAMPLER:
+ write_sampler_descriptor(device, ptr, writeset->pImageInfo + j);
break;
default:
unreachable("unimplemented descriptor type");
unsigned char sha1[20];
};
-static inline const uint32_t *
+static inline const struct tu_sampler*
tu_immutable_samplers(const struct tu_descriptor_set_layout *set,
const struct tu_descriptor_set_binding_layout *binding)
{
- return (const uint32_t *) ((const char *) set +
+ return (struct tu_sampler *) ((const char *) set +
binding->immutable_samplers_offset);
}
#endif /* TU_DESCRIPTOR_SET_H */
struct ir3_shader *shader = builder->shaders[i]->variants[0].shader;
link->ubo_state = shader->ubo_state;
+ link->const_state = shader->const_state;
link->constlen = builder->shaders[i]->variants[0].constlen;
- link->offset_ubo = shader->const_state.offsets.ubo;
- link->num_ubo = shader->const_state.num_ubos;
link->texture_map = builder->shaders[i]->texture_map;
link->sampler_map = builder->shaders[i]->sampler_map;
link->ubo_map = builder->shaders[i]->ubo_map;
+ link->ssbo_map = builder->shaders[i]->ssbo_map;
+ link->image_mapping = builder->shaders[i]->variants[0].image_mapping;
}
}
uint32_t valid;
struct tu_push_descriptor_set push_set;
bool push_dirty;
- uint32_t dynamic_buffers[4 * MAX_DYNAMIC_BUFFERS];
+ uint64_t dynamic_buffers[MAX_DYNAMIC_BUFFERS];
};
struct tu_tile
tu_get_descriptors_state(struct tu_cmd_buffer *cmd_buffer,
VkPipelineBindPoint bind_point)
{
- assert(bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS);
return &cmd_buffer->descriptors[bind_point];
}
struct tu_descriptor_map
{
+ /* TODO: avoid fixed size array/justify the size */
unsigned num;
- int set[32];
- int binding[32];
+ int set[64];
+ int binding[64];
};
struct tu_shader
struct tu_descriptor_map texture_map;
struct tu_descriptor_map sampler_map;
struct tu_descriptor_map ubo_map;
+ struct tu_descriptor_map ssbo_map;
/* This may be true for vertex shaders. When true, variants[1] is the
* binning variant and binning_binary is non-NULL.
struct tu_program_descriptor_linkage
{
struct ir3_ubo_analysis_state ubo_state;
+ struct ir3_const_state const_state;
uint32_t constlen;
- uint32_t offset_ubo; /* ubo pointers const offset */
- uint32_t num_ubo; /* number of ubo pointers */
-
struct tu_descriptor_map texture_map;
struct tu_descriptor_map sampler_map;
struct tu_descriptor_map ubo_map;
+ struct tu_descriptor_map ssbo_map;
+ struct ir3_ibo_mapping image_mapping;
};
struct tu_pipeline
return false;
nir_const_value *const_val = nir_src_as_const_value(instr->src[0]);
- if (!const_val || const_val->u32 != 0) {
+ if (!const_val || const_val->u32 != 0)
tu_finishme("non-zero vulkan_resource_index array index");
- return false;
- }
- if (nir_intrinsic_desc_type(instr) != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) {
- tu_finishme("non-ubo vulkan_resource_index");
- return false;
- }
- unsigned index = map_add(&shader->ubo_map,
- nir_intrinsic_desc_set(instr),
- nir_intrinsic_binding(instr));
+ unsigned set = nir_intrinsic_desc_set(instr);
+ unsigned binding = nir_intrinsic_binding(instr);
+ unsigned index = 0;
+
+ switch (nir_intrinsic_desc_type(instr)) {
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
+ /* skip index 0 which is used for push constants */
+ index = map_add(&shader->ubo_map, set, binding) + 1;
+ break;
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
+ index = map_add(&shader->ssbo_map, set, binding);
+ break;
+ default:
+ tu_finishme("unsupported desc_type for vulkan_resource_index");
+ break;
+ }
- b->cursor = nir_before_instr(&instr->instr);
- /* skip index 0 because ir3 treats it differently */
nir_ssa_def_rewrite_uses(&instr->dest.ssa,
- nir_src_for_ssa(nir_imm_int(b, index + 1)));
+ nir_src_for_ssa(nir_imm_int(b, index)));
nir_instr_remove(&instr->instr);
return true;