anv: Completely rework descriptor set layouts

This patch reworks a bunch of stuff in the way we do descriptor set
layouts.  Our previous approach had a couple of problems.  First, it was
based on a misunderstanding of arrays in descriptor sets.  Second, it
didn't properly handle descriptor sets where some bindings were missing
stages.  The new apporach should be correct and also makes some operations,
particularly those on the hot-path, a bit easier.

We use the descriptor set layout for four things:

 1) To determine the map from bindings to the actual flattened descriptor
    set in vkUpdateDescriptorSets().

 2) To determine the descriptor <-> binding table entry mapping to use in
    anv_cmd_buffer_flush_descriptor_sets().

 3) To determine the mappings of dynamic indices.

 4) To determine the (set, binding, array index) -> binding table entry
    mapping inside of shaders.

The new approach is directly taylored towards these operations.
This commit is contained in:
Jason Ekstrand 2015-10-14 15:18:49 -07:00
parent 7965fe7da6
commit b37c38c1ca
6 changed files with 219 additions and 212 deletions

View file

@ -483,7 +483,7 @@ void anv_CmdBindDescriptorSets(
cmd_buffer->state.descriptors_dirty |= set_layout->shader_stages;
}
if (set_layout->num_dynamic_buffers > 0) {
if (set_layout->dynamic_offset_count > 0) {
VkShaderStage s;
for_each_bit(s, set_layout->shader_stages) {
anv_cmd_buffer_ensure_push_constant_field(cmd_buffer, s,
@ -492,13 +492,13 @@ void anv_CmdBindDescriptorSets(
cmd_buffer->state.push_constants[s]->dynamic_offsets +
layout->set[firstSet + i].dynamic_offset_start;
memcpy(offsets, pDynamicOffsets + dynamic_slot,
set_layout->num_dynamic_buffers * sizeof(*pDynamicOffsets));
typed_memcpy(offsets, pDynamicOffsets + dynamic_slot,
set_layout->dynamic_offset_count);
}
cmd_buffer->state.push_constants_dirty |= set_layout->shader_stages;
dynamic_slot += set_layout->num_dynamic_buffers;
dynamic_slot += set_layout->dynamic_offset_count;
}
}
}
@ -594,41 +594,35 @@ anv_cmd_buffer_emit_binding_table(struct anv_cmd_buffer *cmd_buffer,
if (layout == NULL)
return VK_SUCCESS;
for (uint32_t set = 0; set < layout->num_sets; set++) {
struct anv_descriptor_set_binding *d = &cmd_buffer->state.descriptors[set];
struct anv_descriptor_set_layout *set_layout = layout->set[set].layout;
struct anv_descriptor_slot *surface_slots =
set_layout->stage[stage].surface_start;
for (uint32_t s = 0; s < layout->stage[stage].surface_count; s++) {
struct anv_pipeline_binding *binding =
&layout->stage[stage].surface_to_descriptor[s];
struct anv_descriptor_set *set =
cmd_buffer->state.descriptors[binding->set].set;
struct anv_descriptor *desc = &set->descriptors[binding->offset];
uint32_t start = bias + layout->set[set].stage[stage].surface_start;
const struct anv_state *surface_state;
struct anv_bo *bo;
uint32_t bo_offset;
for (uint32_t b = 0; b < set_layout->stage[stage].surface_count; b++) {
struct anv_descriptor *desc =
&d->set->descriptors[surface_slots[b].index];
const struct anv_state *surface_state;
struct anv_bo *bo;
uint32_t bo_offset;
switch (desc->type) {
case ANV_DESCRIPTOR_TYPE_EMPTY:
case ANV_DESCRIPTOR_TYPE_SAMPLER:
continue;
case ANV_DESCRIPTOR_TYPE_BUFFER_VIEW:
surface_state = &desc->buffer_view->surface_state;
bo = desc->buffer_view->bo;
bo_offset = desc->buffer_view->offset;
break;
case ANV_DESCRIPTOR_TYPE_IMAGE_VIEW:
surface_state = &desc->image_view->nonrt_surface_state;
bo = desc->image_view->bo;
bo_offset = desc->image_view->offset;
break;
}
bt_map[start + b] = surface_state->offset + state_offset;
add_surface_state_reloc(cmd_buffer, *surface_state, bo, bo_offset);
switch (desc->type) {
case ANV_DESCRIPTOR_TYPE_EMPTY:
case ANV_DESCRIPTOR_TYPE_SAMPLER:
continue;
case ANV_DESCRIPTOR_TYPE_BUFFER_VIEW:
surface_state = &desc->buffer_view->surface_state;
bo = desc->buffer_view->bo;
bo_offset = desc->buffer_view->offset;
break;
case ANV_DESCRIPTOR_TYPE_IMAGE_VIEW:
surface_state = &desc->image_view->nonrt_surface_state;
bo = desc->image_view->bo;
bo_offset = desc->image_view->offset;
break;
}
bt_map[bias + s] = surface_state->offset + state_offset;
add_surface_state_reloc(cmd_buffer, *surface_state, bo, bo_offset);
}
return VK_SUCCESS;
@ -656,26 +650,20 @@ anv_cmd_buffer_emit_samplers(struct anv_cmd_buffer *cmd_buffer,
if (state->map == NULL)
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
for (uint32_t set = 0; set < layout->num_sets; set++) {
struct anv_descriptor_set_binding *d = &cmd_buffer->state.descriptors[set];
struct anv_descriptor_set_layout *set_layout = layout->set[set].layout;
struct anv_descriptor_slot *sampler_slots =
set_layout->stage[stage].sampler_start;
for (uint32_t s = 0; s < layout->stage[stage].sampler_count; s++) {
struct anv_pipeline_binding *binding =
&layout->stage[stage].sampler_to_descriptor[s];
struct anv_descriptor_set *set =
cmd_buffer->state.descriptors[binding->set].set;
struct anv_descriptor *desc = &set->descriptors[binding->offset];
uint32_t start = layout->set[set].stage[stage].sampler_start;
if (desc->type != ANV_DESCRIPTOR_TYPE_SAMPLER)
continue;
for (uint32_t b = 0; b < set_layout->stage[stage].sampler_count; b++) {
struct anv_descriptor *desc =
&d->set->descriptors[sampler_slots[b].index];
struct anv_sampler *sampler = desc->sampler;
if (desc->type != ANV_DESCRIPTOR_TYPE_SAMPLER)
continue;
struct anv_sampler *sampler = desc->sampler;
memcpy(state->map + (start + b) * 16,
sampler->state, sizeof(sampler->state));
}
memcpy(state->map + (s * 16),
sampler->state, sizeof(sampler->state));
}
return VK_SUCCESS;

View file

@ -92,13 +92,20 @@ set_binding_table_layout(struct brw_stage_prog_data *prog_data,
k = bias;
map = prog_data->map_entries;
for (uint32_t i = 0; i < layout->num_sets; i++) {
prog_data->bind_map[i].index = map;
for (uint32_t j = 0; j < layout->set[i].layout->stage[stage].surface_count; j++)
*map++ = k++;
for (uint32_t set = 0; set < layout->num_sets; set++) {
prog_data->bind_map[set].index = map;
unsigned index_count = 0;
for (uint32_t b = 0; b < layout->set[set].layout->binding_count; b++) {
if (layout->set[set].layout->binding[b].stage[stage].surface_index < 0)
continue;
prog_data->bind_map[i].index_count =
layout->set[i].layout->stage[stage].surface_count;
unsigned array_size = layout->set[set].layout->binding[b].array_size;
for (uint32_t i = 0; i < array_size; i++)
*map++ = k++;
index_count += array_size;
}
prog_data->bind_map[set].index_count = index_count;
}
return VK_SUCCESS;

View file

@ -1440,117 +1440,48 @@ VkResult anv_CreateDescriptorSetLayout(
{
ANV_FROM_HANDLE(anv_device, device, _device);
struct anv_descriptor_set_layout *set_layout;
uint32_t s;
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO);
uint32_t sampler_count[VK_SHADER_STAGE_NUM] = { 0, };
uint32_t surface_count[VK_SHADER_STAGE_NUM] = { 0, };
uint32_t num_dynamic_buffers = 0;
uint32_t count = 0;
VkShaderStageFlags stages = 0;
uint32_t s;
size_t size = sizeof(struct anv_descriptor_set_layout) +
pCreateInfo->count * sizeof(set_layout->binding[0]);
for (uint32_t i = 0; i < pCreateInfo->count; i++) {
switch (pCreateInfo->pBinding[i].descriptorType) {
case VK_DESCRIPTOR_TYPE_SAMPLER:
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
for_each_bit(s, pCreateInfo->pBinding[i].stageFlags)
sampler_count[s] += pCreateInfo->pBinding[i].arraySize;
break;
default:
break;
}
switch (pCreateInfo->pBinding[i].descriptorType) {
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
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:
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
for_each_bit(s, pCreateInfo->pBinding[i].stageFlags)
surface_count[s] += pCreateInfo->pBinding[i].arraySize;
break;
default:
break;
}
switch (pCreateInfo->pBinding[i].descriptorType) {
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
num_dynamic_buffers += pCreateInfo->pBinding[i].arraySize;
break;
default:
break;
}
stages |= pCreateInfo->pBinding[i].stageFlags;
count += pCreateInfo->pBinding[i].arraySize;
}
uint32_t sampler_total = 0;
uint32_t surface_total = 0;
for (uint32_t s = 0; s < VK_SHADER_STAGE_NUM; s++) {
sampler_total += sampler_count[s];
surface_total += surface_count[s];
}
size_t size = sizeof(*set_layout) +
(sampler_total + surface_total) * sizeof(set_layout->entries[0]);
set_layout = anv_device_alloc(device, size, 8,
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
if (!set_layout)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
set_layout->num_dynamic_buffers = num_dynamic_buffers;
set_layout->count = count;
set_layout->shader_stages = stages;
set_layout->binding_count = pCreateInfo->count;
set_layout->shader_stages = 0;
set_layout->size = 0;
struct anv_descriptor_slot *p = set_layout->entries;
struct anv_descriptor_slot *sampler[VK_SHADER_STAGE_NUM];
struct anv_descriptor_slot *surface[VK_SHADER_STAGE_NUM];
for (uint32_t s = 0; s < VK_SHADER_STAGE_NUM; s++) {
set_layout->stage[s].surface_count = surface_count[s];
set_layout->stage[s].surface_start = surface[s] = p;
p += surface_count[s];
set_layout->stage[s].sampler_count = sampler_count[s];
set_layout->stage[s].sampler_start = sampler[s] = p;
p += sampler_count[s];
}
/* Initialize all binding_layout entries to -1 */
memset(set_layout->binding, -1,
pCreateInfo->count * sizeof(set_layout->binding[0]));
uint32_t descriptor = 0;
int8_t dynamic_slot = 0;
bool is_dynamic;
for (uint32_t i = 0; i < pCreateInfo->count; i++) {
switch (pCreateInfo->pBinding[i].descriptorType) {
uint32_t sampler_count[VK_SHADER_STAGE_NUM] = { 0, };
uint32_t surface_count[VK_SHADER_STAGE_NUM] = { 0, };
uint32_t dynamic_offset_count = 0;
for (uint32_t b = 0; b < pCreateInfo->count; b++) {
uint32_t array_size = MAX2(1, pCreateInfo->pBinding[b].arraySize);
set_layout->binding[b].array_size = array_size;
set_layout->size += array_size;
switch (pCreateInfo->pBinding[b].descriptorType) {
case VK_DESCRIPTOR_TYPE_SAMPLER:
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
for_each_bit(s, pCreateInfo->pBinding[i].stageFlags)
for (uint32_t j = 0; j < pCreateInfo->pBinding[i].arraySize; j++) {
sampler[s]->index = descriptor + j;
sampler[s]->dynamic_slot = -1;
sampler[s]++;
}
for_each_bit(s, pCreateInfo->pBinding[b].stageFlags) {
set_layout->binding[b].stage[s].sampler_index = sampler_count[s];
sampler_count[s] += array_size;
}
break;
default:
break;
}
switch (pCreateInfo->pBinding[i].descriptorType) {
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
is_dynamic = true;
break;
default:
is_dynamic = false;
break;
}
switch (pCreateInfo->pBinding[i].descriptorType) {
switch (pCreateInfo->pBinding[b].descriptorType) {
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
@ -1561,26 +1492,30 @@ VkResult anv_CreateDescriptorSetLayout(
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
for_each_bit(s, pCreateInfo->pBinding[i].stageFlags)
for (uint32_t j = 0; j < pCreateInfo->pBinding[i].arraySize; j++) {
surface[s]->index = descriptor + j;
if (is_dynamic)
surface[s]->dynamic_slot = dynamic_slot + j;
else
surface[s]->dynamic_slot = -1;
surface[s]++;
}
for_each_bit(s, pCreateInfo->pBinding[b].stageFlags) {
set_layout->binding[b].stage[s].surface_index = surface_count[s];
surface_count[s] += array_size;
}
break;
default:
break;
}
if (is_dynamic)
dynamic_slot += pCreateInfo->pBinding[i].arraySize;
switch (pCreateInfo->pBinding[b].descriptorType) {
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
set_layout->binding[b].dynamic_offset_index = dynamic_offset_count;
dynamic_offset_count += array_size;
break;
default:
break;
}
descriptor += pCreateInfo->pBinding[i].arraySize;
set_layout->shader_stages |= pCreateInfo->pBinding[b].stageFlags;
}
set_layout->dynamic_offset_count = dynamic_offset_count;
*pSetLayout = anv_descriptor_set_layout_to_handle(set_layout);
return VK_SUCCESS;
@ -1627,7 +1562,7 @@ anv_descriptor_set_create(struct anv_device *device,
struct anv_descriptor_set **out_set)
{
struct anv_descriptor_set *set;
size_t size = sizeof(*set) + layout->count * sizeof(set->descriptors[0]);
size_t size = sizeof(*set) + layout->size * sizeof(set->descriptors[0]);
set = anv_device_alloc(device, size, 8, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
if (!set)

View file

@ -39,7 +39,6 @@ apply_dynamic_offsets_block(nir_block *block, void *void_state)
{
struct apply_dynamic_offsets_state *state = void_state;
struct anv_descriptor_set_layout *set_layout;
const struct anv_descriptor_slot *slot;
nir_foreach_instr_safe(block, instr) {
if (instr->type != nir_instr_type_intrinsic)
@ -69,19 +68,18 @@ apply_dynamic_offsets_block(nir_block *block, void *void_state)
}
set_layout = state->layout->set[set].layout;
slot = &set_layout->stage[state->stage].surface_start[binding];
if (slot->dynamic_slot < 0)
if (set_layout->binding[binding].dynamic_offset_index < 0)
continue;
uint32_t dynamic_index = state->layout->set[set].dynamic_offset_start +
slot->dynamic_slot;
uint32_t index = state->layout->set[set].dynamic_offset_start +
set_layout->binding[binding].dynamic_offset_index;
state->builder.cursor = nir_before_instr(&intrin->instr);
nir_intrinsic_instr *offset_load =
nir_intrinsic_instr_create(state->shader, nir_intrinsic_load_uniform);
offset_load->num_components = 1;
offset_load->const_index[0] = state->indices_start + dynamic_index;
offset_load->const_index[0] = state->indices_start + index;
offset_load->const_index[1] = 0;
nir_ssa_dest_init(&offset_load->instr, &offset_load->dest, 1, NULL);
nir_builder_instr_insert(&state->builder, &offset_load->instr);

View file

@ -458,48 +458,101 @@ VkResult anv_CreatePipelineLayout(
VkPipelineLayout* pPipelineLayout)
{
ANV_FROM_HANDLE(anv_device, device, _device);
struct anv_pipeline_layout *layout;
struct anv_pipeline_layout l, *layout;
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO);
layout = anv_device_alloc(device, sizeof(*layout), 8,
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
l.num_sets = pCreateInfo->descriptorSetCount;
unsigned dynamic_offset_count = 0;
memset(l.stage, 0, sizeof(l.stage));
for (uint32_t set = 0; set < pCreateInfo->descriptorSetCount; set++) {
ANV_FROM_HANDLE(anv_descriptor_set_layout, set_layout,
pCreateInfo->pSetLayouts[set]);
l.set[set].layout = set_layout;
l.set[set].dynamic_offset_start = dynamic_offset_count;
for (uint32_t b = 0; b < set_layout->binding_count; b++) {
if (set_layout->binding[b].dynamic_offset_index >= 0)
dynamic_offset_count += set_layout->binding[b].array_size;
}
for (VkShaderStage s = 0; s < VK_SHADER_STAGE_NUM; s++) {
l.set[set].stage[s].surface_start = l.stage[s].surface_count;
l.set[set].stage[s].sampler_start = l.stage[s].sampler_count;
for (uint32_t b = 0; b < set_layout->binding_count; b++) {
unsigned array_size = set_layout->binding[b].array_size;
if (set_layout->binding[b].stage[s].surface_index >= 0) {
l.stage[s].surface_count += array_size;
if (set_layout->binding[b].dynamic_offset_index >= 0)
l.stage[s].has_dynamic_offsets = true;
}
if (set_layout->binding[b].stage[s].sampler_index >= 0)
l.stage[s].sampler_count += array_size;
}
}
}
unsigned num_bindings = 0;
for (VkShaderStage s = 0; s < VK_SHADER_STAGE_NUM; s++)
num_bindings += l.stage[s].surface_count + l.stage[s].sampler_count;
size_t size = sizeof(*layout) + num_bindings * sizeof(layout->entries[0]);
layout = anv_device_alloc(device, size, 8, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
if (layout == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
layout->num_sets = pCreateInfo->descriptorSetCount;
/* Now we can actually build our surface and sampler maps */
struct anv_pipeline_binding *entry = layout->entries;
for (VkShaderStage s = 0; s < VK_SHADER_STAGE_NUM; s++) {
l.stage[s].surface_to_descriptor = entry;
entry += l.stage[s].surface_count;
l.stage[s].sampler_to_descriptor = entry;
entry += l.stage[s].sampler_count;
uint32_t surface_start[VK_SHADER_STAGE_NUM] = { 0, };
uint32_t sampler_start[VK_SHADER_STAGE_NUM] = { 0, };
int surface = 0;
int sampler = 0;
for (uint32_t set = 0; set < pCreateInfo->descriptorSetCount; set++) {
struct anv_descriptor_set_layout *set_layout = l.set[set].layout;
for (uint32_t s = 0; s < VK_SHADER_STAGE_NUM; s++) {
layout->stage[s].has_dynamic_offsets = false;
layout->stage[s].surface_count = 0;
layout->stage[s].sampler_count = 0;
}
unsigned set_offset = 0;
for (uint32_t b = 0; b < set_layout->binding_count; b++) {
unsigned array_size = set_layout->binding[b].array_size;
uint32_t num_dynamic_offsets = 0;
for (uint32_t i = 0; i < pCreateInfo->descriptorSetCount; i++) {
ANV_FROM_HANDLE(anv_descriptor_set_layout, set_layout,
pCreateInfo->pSetLayouts[i]);
if (set_layout->binding[b].stage[s].surface_index >= 0) {
assert(surface == l.set[set].stage[s].surface_start +
set_layout->binding[b].stage[s].surface_index);
for (unsigned i = 0; i < array_size; i++) {
l.stage[s].surface_to_descriptor[surface + i].set = set;
l.stage[s].surface_to_descriptor[surface + i].offset = set_offset + i;
}
surface += array_size;
}
layout->set[i].layout = set_layout;
layout->set[i].dynamic_offset_start = num_dynamic_offsets;
num_dynamic_offsets += set_layout->num_dynamic_buffers;
for (uint32_t s = 0; s < VK_SHADER_STAGE_NUM; s++) {
if (set_layout->num_dynamic_buffers > 0)
layout->stage[s].has_dynamic_offsets = true;
if (set_layout->binding[b].stage[s].sampler_index >= 0) {
assert(sampler == l.set[set].stage[s].sampler_start +
set_layout->binding[b].stage[s].sampler_index);
for (unsigned i = 0; i < array_size; i++) {
l.stage[s].sampler_to_descriptor[sampler + i].set = set;
l.stage[s].sampler_to_descriptor[sampler + i].offset = set_offset + i;
}
sampler += array_size;
}
layout->set[i].stage[s].surface_start = surface_start[s];
surface_start[s] += set_layout->stage[s].surface_count;
layout->set[i].stage[s].sampler_start = sampler_start[s];
sampler_start[s] += set_layout->stage[s].sampler_count;
layout->stage[s].surface_count += set_layout->stage[s].surface_count;
layout->stage[s].sampler_count += set_layout->stage[s].sampler_count;
set_offset += array_size;
}
}
}
/* Finally, we're done setting it up, copy into the allocated version */
*layout = l;
*pPipelineLayout = anv_pipeline_layout_to_handle(layout);
return VK_SUCCESS;

View file

@ -660,23 +660,37 @@ struct anv_device_memory {
void * map;
};
struct anv_descriptor_slot {
int8_t dynamic_slot;
uint8_t index;
struct anv_descriptor_set_binding_layout {
/* Number of array elements in this binding */
uint16_t array_size;
/* Index into the dynamic state array for a dynamic buffer */
int16_t dynamic_offset_index;
struct {
/* Index into the binding table for the associated surface */
int16_t surface_index;
/* Index into the sampler table for the associated sampler */
int16_t sampler_index;
} stage[VK_SHADER_STAGE_NUM];
};
struct anv_descriptor_set_layout {
struct {
uint32_t surface_count;
struct anv_descriptor_slot *surface_start;
uint32_t sampler_count;
struct anv_descriptor_slot *sampler_start;
} stage[VK_SHADER_STAGE_NUM];
/* Number of bindings in this descriptor set */
uint16_t binding_count;
uint32_t count;
uint32_t num_dynamic_buffers;
VkShaderStageFlags shader_stages;
struct anv_descriptor_slot entries[0];
/* Total size of the descriptor set with room for all array entries */
uint16_t size;
/* Shader stages affected by this descriptor set */
uint16_t shader_stages;
/* Number of dynamic offsets used by this descriptor set */
uint16_t dynamic_offset_count;
/* Don't use this directly */
struct anv_descriptor_set_binding_layout binding[0];
};
enum anv_descriptor_type {
@ -718,6 +732,14 @@ anv_descriptor_set_destroy(struct anv_device *device,
#define MAX_DYNAMIC_BUFFERS 16
#define MAX_IMAGES 8
struct anv_pipeline_binding {
/* The descriptor set this surface corresponds to */
uint16_t set;
/* Offset into the descriptor set */
uint16_t offset;
};
struct anv_pipeline_layout {
struct {
struct anv_descriptor_set_layout *layout;
@ -733,8 +755,12 @@ struct anv_pipeline_layout {
struct {
bool has_dynamic_offsets;
uint32_t surface_count;
struct anv_pipeline_binding *surface_to_descriptor;
uint32_t sampler_count;
struct anv_pipeline_binding *sampler_to_descriptor;
} stage[VK_SHADER_STAGE_NUM];
struct anv_pipeline_binding entries[0];
};
struct anv_buffer {