From 83c7e1f1db77c57802c72e0dff114f7a0daca5b5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 13 May 2015 14:43:08 -0700 Subject: [PATCH] vk: Add support for sampler descriptors --- src/vulkan/compiler.cpp | 4 +- src/vulkan/device.c | 124 ++++++++++++++++++++++++++++++---------- src/vulkan/pipeline.c | 66 ++++++++++++++++----- src/vulkan/private.h | 9 ++- 4 files changed, 153 insertions(+), 50 deletions(-) diff --git a/src/vulkan/compiler.cpp b/src/vulkan/compiler.cpp index f8be0f070a8..f81008b8f72 100644 --- a/src/vulkan/compiler.cpp +++ b/src/vulkan/compiler.cpp @@ -70,8 +70,8 @@ set_binding_table_layout(struct brw_stage_prog_data *prog_data, else bias = 0; - count = pipeline->layout->stage[stage].count; - entries = pipeline->layout->stage[stage].entries; + count = pipeline->layout->stage[stage].surface_count; + entries = pipeline->layout->stage[stage].surface_entries; prog_data->map_entries = (uint32_t *) malloc(count * sizeof(prog_data->map_entries[0])); diff --git a/src/vulkan/device.c b/src/vulkan/device.c index 7da2322137f..d5eab4866d4 100644 --- a/src/vulkan/device.c +++ b/src/vulkan/device.c @@ -1415,8 +1415,8 @@ VkResult VKAPI vkCreateDescriptorSetLayout( { struct anv_device *device = (struct anv_device *) _device; struct anv_descriptor_set_layout *set_layout; - uint32_t count, k; - size_t size, total; + uint32_t count, k, num_entries; + size_t size, sampler_total, surface_total; assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO); @@ -1432,7 +1432,8 @@ VkResult VKAPI vkCreateDescriptorSetLayout( return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); k = 0; - total = 0; + sampler_total = 0; + surface_total = 0; for (uint32_t i = 0; i < pCreateInfo->count; i++) { for (uint32_t j = 0; j < pCreateInfo->pBinding[i].count; j++) { set_layout->bindings[k].mask = pCreateInfo->pBinding[i].stageFlags; @@ -1440,11 +1441,36 @@ VkResult VKAPI vkCreateDescriptorSetLayout( k++; } - total += pCreateInfo->pBinding[i].count * + num_entries = pCreateInfo->pBinding[i].count * __builtin_popcount(pCreateInfo->pBinding[i].stageFlags); + + switch (pCreateInfo->pBinding[i].descriptorType) { + case VK_DESCRIPTOR_TYPE_SAMPLER: + sampler_total += num_entries; + break; + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + sampler_total += num_entries; + surface_total += num_entries; + break; + + 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: + surface_total += num_entries; + break; + + default: + unreachable("invalid descriptor type"); + } } - set_layout->total = total; + set_layout->sampler_total = sampler_total; + set_layout->surface_total = surface_total; set_layout->count = count; *pSetLayout = (VkDescriptorSetLayout) set_layout; @@ -2136,36 +2162,25 @@ void VKAPI vkCmdBindVertexBuffers( static void flush_descriptor_sets(struct anv_cmd_buffer *cmd_buffer) { - static const uint32_t opcodes[] = { - [VK_SHADER_STAGE_VERTEX] = 38, - [VK_SHADER_STAGE_TESS_CONTROL] = 39, - [VK_SHADER_STAGE_TESS_EVALUATION] = 40, - [VK_SHADER_STAGE_GEOMETRY] = 41, - [VK_SHADER_STAGE_FRAGMENT] = 42, - [VK_SHADER_STAGE_COMPUTE] = 0, - }; - struct anv_pipeline_layout *layout = cmd_buffer->pipeline->layout; struct anv_framebuffer *framebuffer = cmd_buffer->framebuffer; for (uint32_t s = 0; s < VK_NUM_SHADER_STAGE; s++) { uint32_t bias = s == VK_SHADER_STAGE_FRAGMENT ? MAX_RTS : 0; - uint32_t count, *table; + uint32_t binding_table_length, *table; struct anv_state table_state; if (layout) - count = layout->stage[s].count + bias; + binding_table_length = layout->stage[s].surface_count + bias; else if (s == VK_SHADER_STAGE_FRAGMENT) - count = framebuffer->color_attachment_count; + binding_table_length = framebuffer->color_attachment_count; else - count = 0; + binding_table_length = 0; - if (count == 0) - continue; - - table_state = anv_state_stream_alloc(&cmd_buffer->surface_state_stream, - count * 4, 32); + if (binding_table_length > 0) + table_state = anv_state_stream_alloc(&cmd_buffer->surface_state_stream, + binding_table_length * 4, 32); table = table_state.map; if (s == VK_SHADER_STAGE_FRAGMENT) { @@ -2182,8 +2197,8 @@ flush_descriptor_sets(struct anv_cmd_buffer *cmd_buffer) } if (layout) { - for (uint32_t i = 0; i < layout->stage[s].count; i++) { - struct anv_pipeline_layout_entry *e = &layout->stage[s].entries[i]; + for (uint32_t i = 0; i < layout->stage[s].surface_count; i++) { + struct anv_pipeline_layout_entry *e = &layout->stage[s].surface_entries[i]; struct anv_descriptor *d = &cmd_buffer->descriptor_sets[e->set]->descriptors[e->index]; struct anv_image_view *image_view; @@ -2227,15 +2242,62 @@ flush_descriptor_sets(struct anv_cmd_buffer *cmd_buffer) } } - /* FIXME: Samplers */ - /* The binding table pointer commands all have the same structure, only * the opcode differs. */ - anv_batch_emit(&cmd_buffer->batch, - GEN8_3DSTATE_BINDING_TABLE_POINTERS_VS, - ._3DCommandSubOpcode = opcodes[s], - .PointertoVSBindingTable = table_state.offset); + static const uint32_t binding_table_opcodes[] = { + [VK_SHADER_STAGE_VERTEX] = 38, + [VK_SHADER_STAGE_TESS_CONTROL] = 39, + [VK_SHADER_STAGE_TESS_EVALUATION] = 40, + [VK_SHADER_STAGE_GEOMETRY] = 41, + [VK_SHADER_STAGE_FRAGMENT] = 42, + [VK_SHADER_STAGE_COMPUTE] = 0, + }; + + if (binding_table_length > 0) + anv_batch_emit(&cmd_buffer->batch, + GEN8_3DSTATE_BINDING_TABLE_POINTERS_VS, + ._3DCommandSubOpcode = binding_table_opcodes[s], + .PointertoVSBindingTable = table_state.offset); + + + if (layout && layout->stage[s].sampler_count > 0) { + struct anv_state sampler_state; + + sampler_state = anv_state_stream_alloc(&cmd_buffer->dynamic_state_stream, + layout->stage[s].sampler_count * 16, 32); + for (uint32_t i = 0; i < layout->stage[s].sampler_count; i++) { + struct anv_pipeline_layout_entry *e = &layout->stage[s].sampler_entries[i]; + struct anv_sampler *sampler; + + switch (e->type) { + case VK_DESCRIPTOR_TYPE_SAMPLER: + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + sampler = + cmd_buffer->descriptor_sets[e->set]->descriptors[e->index].sampler; + break; + default: + unreachable("non-sampler descriptor in sampler entries"); + break; + } + + memcpy(sampler_state.map + i * 16, sampler->state, sizeof(sampler->state)); + } + + static const uint32_t sampler_state_opcodes[] = { + [VK_SHADER_STAGE_VERTEX] = 43, + [VK_SHADER_STAGE_TESS_CONTROL] = 44, /* HS */ + [VK_SHADER_STAGE_TESS_EVALUATION] = 45, /* DS */ + [VK_SHADER_STAGE_GEOMETRY] = 46, + [VK_SHADER_STAGE_FRAGMENT] = 47, + [VK_SHADER_STAGE_COMPUTE] = 0, + }; + + anv_batch_emit(&cmd_buffer->batch, + GEN8_3DSTATE_SAMPLER_STATE_POINTERS_VS, + ._3DCommandSubOpcode = sampler_state_opcodes[s], + .PointertoVSSamplerState = sampler_state.offset); + } } } diff --git a/src/vulkan/pipeline.c b/src/vulkan/pipeline.c index ce1fa303d7c..a260c3cd24a 100644 --- a/src/vulkan/pipeline.c +++ b/src/vulkan/pipeline.c @@ -560,43 +560,81 @@ VkResult VKAPI vkCreatePipelineLayout( { struct anv_device *device = (struct anv_device *) _device; struct anv_pipeline_layout *layout; - struct anv_pipeline_layout_entry *entry; - uint32_t total; + struct anv_pipeline_layout_entry *sampler_entry, *surface_entry; + uint32_t sampler_total, surface_total; size_t size; assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO); - total = 0; + sampler_total = 0; + surface_total = 0; for (uint32_t i = 0; i < pCreateInfo->descriptorSetCount; i++) { struct anv_descriptor_set_layout *set_layout = (struct anv_descriptor_set_layout *) pCreateInfo->pSetLayouts[i]; - for (uint32_t j = 0; j < set_layout->count; j++) - total += set_layout->total; + for (uint32_t j = 0; j < set_layout->count; j++) { + sampler_total += set_layout->sampler_total; + surface_total += set_layout->surface_total; + } } - size = sizeof(*layout) + total * sizeof(layout->entries[0]); + size = sizeof(*layout) + + (sampler_total + surface_total) * 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); - entry = layout->entries; + sampler_entry = layout->entries; + surface_entry = layout->entries + sampler_total; for (uint32_t s = 0; s < VK_NUM_SHADER_STAGE; s++) { - layout->stage[s].entries = entry; + layout->stage[s].sampler_entries = sampler_entry; + layout->stage[s].surface_entries = surface_entry; for (uint32_t i = 0; i < pCreateInfo->descriptorSetCount; i++) { struct anv_descriptor_set_layout *set_layout = (struct anv_descriptor_set_layout *) pCreateInfo->pSetLayouts[i]; - for (uint32_t j = 0; j < set_layout->count; j++) + for (uint32_t j = 0; j < set_layout->count; j++) { if (set_layout->bindings[j].mask & (1 << s)) { - entry->type = set_layout->bindings[j].type; - entry->set = i; - entry->index = j; - entry++; + switch (set_layout->bindings[j].type) { + case VK_DESCRIPTOR_TYPE_SAMPLER: + sampler_entry->type = set_layout->bindings[j].type; + sampler_entry->set = i; + sampler_entry->index = j; + sampler_entry++; + break; + + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + sampler_entry->type = set_layout->bindings[j].type; + sampler_entry->set = i; + sampler_entry->index = j; + sampler_entry++; + /* fall through */ + + 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: + surface_entry->type = set_layout->bindings[j].type; + surface_entry->set = i; + surface_entry->index = j; + surface_entry++; + break; + + default: + break; + } } + } } - layout->stage[s].count = entry - layout->stage[s].entries; + layout->stage[s].sampler_count = + sampler_entry - layout->stage[s].sampler_entries; + layout->stage[s].surface_count = + surface_entry - layout->stage[s].surface_entries; } *pPipelineLayout = (VkPipelineLayout) layout; diff --git a/src/vulkan/private.h b/src/vulkan/private.h index dbb29acbf20..09535a73b64 100644 --- a/src/vulkan/private.h +++ b/src/vulkan/private.h @@ -446,7 +446,8 @@ struct anv_dynamic_cb_state { }; struct anv_descriptor_set_layout { - uint32_t total; /* total number of entries in all stages */ + uint32_t sampler_total; /* total number of samplers in all stages */ + uint32_t surface_total; /* total number of surfaces in all stages */ uint32_t count; struct { VkDescriptorType type; @@ -476,8 +477,10 @@ struct anv_pipeline_layout_entry { struct anv_pipeline_layout { struct { - uint32_t count; - struct anv_pipeline_layout_entry *entries; + uint32_t sampler_count; + struct anv_pipeline_layout_entry *sampler_entries; + uint32_t surface_count; + struct anv_pipeline_layout_entry *surface_entries; } stage[VK_NUM_SHADER_STAGE]; struct anv_pipeline_layout_entry entries[0]; -- 2.30.2