From fad418ff47894a1d579b28346d605d1d57de9b74 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Kristian=20H=C3=B8gsberg=20Kristensen?= Date: Wed, 27 May 2015 14:05:50 -0700 Subject: [PATCH] vk: Implement dynamic buffer offsets We do this by creating a surface state on the fly that incorporates the dynamic offset. This patch also refactor the descriptor set layout constructor a bit to be less clever with switch statement fall through. Instead of duplicating the subtle code to update the sampler and surface slot map, we just use two switch statements. --- src/vulkan/device.c | 151 ++++++++++++++++++++++++++----------------- src/vulkan/private.h | 12 +++- 2 files changed, 101 insertions(+), 62 deletions(-) diff --git a/src/vulkan/device.c b/src/vulkan/device.c index ed2b8d14b7f..3f3319bb50a 100644 --- a/src/vulkan/device.c +++ b/src/vulkan/device.c @@ -1565,37 +1565,21 @@ VkResult anv_CreateBuffer( // Buffer view functions -VkResult anv_CreateBufferView( - VkDevice _device, - const VkBufferViewCreateInfo* pCreateInfo, - VkBufferView* pView) +static void +fill_buffer_surface_state(void *state, VkFormat format, + uint32_t offset, uint32_t range) { - struct anv_device *device = (struct anv_device *) _device; - struct anv_buffer *buffer = (struct anv_buffer *) pCreateInfo->buffer; - struct anv_surface_view *view; - const struct anv_format *format; - - assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO); - - view = anv_device_alloc(device, sizeof(*view), 8, - VK_SYSTEM_ALLOC_TYPE_API_OBJECT); - if (view == NULL) - return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); - - view->bo = buffer->bo; - view->offset = buffer->offset + pCreateInfo->offset; - view->surface_state = - anv_state_pool_alloc(&device->surface_state_pool, 64, 64); - view->format = pCreateInfo->format; + const struct anv_format *info; - format = anv_format_for_vk_format(pCreateInfo->format); + info = anv_format_for_vk_format(format); /* This assumes RGBA float format. */ uint32_t stride = 4; - uint32_t num_elements = pCreateInfo->range / stride; + uint32_t num_elements = range / stride; + struct GEN8_RENDER_SURFACE_STATE surface_state = { .SurfaceType = SURFTYPE_BUFFER, .SurfaceArray = false, - .SurfaceFormat = format->format, + .SurfaceFormat = info->format, .SurfaceVerticalAlignment = VALIGN4, .SurfaceHorizontalAlignment = HALIGN4, .TileMode = LINEAR, @@ -1627,10 +1611,37 @@ VkResult anv_CreateBufferView( .ShaderChannelSelectAlpha = SCS_ALPHA, .ResourceMinLOD = 0, /* FIXME: We assume that the image must be bound at this time. */ - .SurfaceBaseAddress = { NULL, view->offset }, + .SurfaceBaseAddress = { NULL, offset }, }; - GEN8_RENDER_SURFACE_STATE_pack(NULL, view->surface_state.map, &surface_state); + GEN8_RENDER_SURFACE_STATE_pack(NULL, state, &surface_state); +} + +VkResult anv_CreateBufferView( + VkDevice _device, + const VkBufferViewCreateInfo* pCreateInfo, + VkBufferView* pView) +{ + struct anv_device *device = (struct anv_device *) _device; + struct anv_buffer *buffer = (struct anv_buffer *) pCreateInfo->buffer; + struct anv_surface_view *view; + + assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO); + + view = anv_device_alloc(device, sizeof(*view), 8, + VK_SYSTEM_ALLOC_TYPE_API_OBJECT); + if (view == NULL) + return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + + view->bo = buffer->bo; + view->offset = buffer->offset + pCreateInfo->offset; + view->surface_state = + anv_state_pool_alloc(&device->surface_state_pool, 64, 64); + view->format = pCreateInfo->format; + view->range = pCreateInfo->range; + + fill_buffer_surface_state(view->surface_state.map, + pCreateInfo->format, view->offset, pCreateInfo->range); *pView = (VkImageView) view; @@ -1748,16 +1759,16 @@ VkResult anv_CreateDescriptorSetLayout( 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].count; break; + default: + break; + } + switch (pCreateInfo->pBinding[i].descriptorType) { case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: - for_each_bit(s, pCreateInfo->pBinding[i].stageFlags) - sampler_count[s] += pCreateInfo->pBinding[i].count; - - /* fall through */ - case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: @@ -1773,18 +1784,16 @@ VkResult anv_CreateDescriptorSetLayout( break; } - count += pCreateInfo->pBinding[i].count; - } - - for (uint32_t i = 0; i < pCreateInfo->count; i++) { switch (pCreateInfo->pBinding[i].descriptorType) { case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: - num_dynamic_buffers++; + num_dynamic_buffers += pCreateInfo->pBinding[i].count; break; default: break; } + + count += pCreateInfo->pBinding[i].count; } uint32_t sampler_total = 0; @@ -1795,7 +1804,7 @@ VkResult anv_CreateDescriptorSetLayout( } size_t size = sizeof(*set_layout) + - (sampler_total + surface_total) * sizeof(uint32_t); + (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) @@ -1804,9 +1813,9 @@ VkResult anv_CreateDescriptorSetLayout( set_layout->num_dynamic_buffers = num_dynamic_buffers; set_layout->count = count; - uint32_t *p = set_layout->entries; - uint32_t *sampler[VK_NUM_SHADER_STAGE]; - uint32_t *surface[VK_NUM_SHADER_STAGE]; + struct anv_descriptor_slot *p = set_layout->entries; + struct anv_descriptor_slot *sampler[VK_NUM_SHADER_STAGE]; + struct anv_descriptor_slot *surface[VK_NUM_SHADER_STAGE]; for (uint32_t s = 0; s < VK_NUM_SHADER_STAGE; s++) { set_layout->stage[s].surface_count = surface_count[s]; set_layout->stage[s].surface_start = surface[s] = p; @@ -1817,21 +1826,34 @@ VkResult anv_CreateDescriptorSetLayout( } uint32_t descriptor = 0; + bool dynamic; for (uint32_t i = 0; i < pCreateInfo->count; i++) { switch (pCreateInfo->pBinding[i].descriptorType) { case VK_DESCRIPTOR_TYPE_SAMPLER: - for_each_bit(s, pCreateInfo->pBinding[i].stageFlags) - for (uint32_t j = 0; j < pCreateInfo->pBinding[i].count; j++) - *(sampler[s])++ = descriptor + j; - break; - case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: for_each_bit(s, pCreateInfo->pBinding[i].stageFlags) - for (uint32_t j = 0; j < pCreateInfo->pBinding[i].count; j++) - *(sampler[s])++ = descriptor + j; + for (uint32_t j = 0; j < pCreateInfo->pBinding[i].count; j++) { + sampler[s]->index = descriptor + j; + sampler[s]->dynamic = false; + sampler[s]++; + } + break; + default: + break; + } - /* fallthrough */ + switch (pCreateInfo->pBinding[i].descriptorType) { + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + dynamic = true; + break; + default: + dynamic = false; + 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: @@ -1842,11 +1864,13 @@ VkResult anv_CreateDescriptorSetLayout( case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: for_each_bit(s, pCreateInfo->pBinding[i].stageFlags) for (uint32_t j = 0; j < pCreateInfo->pBinding[i].count; j++) { - *(surface[s])++ = descriptor + j; + surface[s]->index = descriptor + j; + surface[s]->dynamic = dynamic; + surface[s]++; } break; default: - unreachable(""); + break; } descriptor += pCreateInfo->pBinding[i].count; } @@ -2731,41 +2755,52 @@ void anv_CmdBindDescriptorSets( struct anv_pipeline_layout *layout = cmd_buffer->pipeline->layout; struct anv_bindings *bindings = cmd_buffer->bindings; - uint32_t offset = 0; + uint32_t dynamic_slot = 0; for (uint32_t i = 0; i < setCount; i++) { struct anv_descriptor_set *set = (struct anv_descriptor_set *) pDescriptorSets[i]; struct anv_descriptor_set_layout *set_layout = layout->set[firstSet + i].layout; for (uint32_t s = 0; s < VK_NUM_SHADER_STAGE; s++) { - uint32_t *surface_to_desc = set_layout->stage[s].surface_start; - uint32_t *sampler_to_desc = set_layout->stage[s].sampler_start; + struct anv_descriptor_slot *surface_slots = set_layout->stage[s].surface_start; + struct anv_descriptor_slot *sampler_slots = set_layout->stage[s].sampler_start; uint32_t bias = s == VK_SHADER_STAGE_FRAGMENT ? MAX_RTS : 0; uint32_t start; start = bias + layout->set[firstSet + i].surface_start[s]; for (uint32_t b = 0; b < set_layout->stage[s].surface_count; b++) { - struct anv_surface_view *view = set->descriptors[surface_to_desc[b]].view; + struct anv_surface_view *view = set->descriptors[surface_slots[b].index].view; if (!view) continue; struct anv_state state = anv_cmd_buffer_alloc_surface_state(cmd_buffer, 64, 64); - memcpy(state.map, view->surface_state.map, 64); + + uint32_t offset; + if (surface_slots[b].dynamic) { + offset = view->offset + pDynamicOffsets[dynamic_slot]; + fill_buffer_surface_state(state.map, view->format, offset, + view->range - pDynamicOffsets[dynamic_slot]); + dynamic_slot++; + } else { + offset = view->offset; + memcpy(state.map, view->surface_state.map, 64); + } /* The address goes in dwords 8 and 9 of the SURFACE_STATE */ *(uint64_t *)(state.map + 8 * 4) = anv_reloc_list_add(&cmd_buffer->surface_relocs, cmd_buffer->device, state.offset + 8 * 4, - view->bo, view->offset); + view->bo, offset); bindings->descriptors[s].surfaces[start + b] = state.offset; } start = layout->set[firstSet + i].sampler_start[s]; for (uint32_t b = 0; b < set_layout->stage[s].sampler_count; b++) { - struct anv_sampler *sampler = set->descriptors[sampler_to_desc[b]].sampler; + + struct anv_sampler *sampler = set->descriptors[sampler_slots[b].index].sampler; if (!sampler) continue; @@ -2773,8 +2808,6 @@ void anv_CmdBindDescriptorSets( sampler->state, sizeof(sampler->state)); } } - - offset += layout->set[firstSet + i].layout->num_dynamic_buffers; } cmd_buffer->dirty |= ANV_CMD_BUFFER_DESCRIPTOR_SET_DIRTY; diff --git a/src/vulkan/private.h b/src/vulkan/private.h index 96b72596a1f..38b908aa6b3 100644 --- a/src/vulkan/private.h +++ b/src/vulkan/private.h @@ -541,17 +541,22 @@ struct anv_query_pool { struct anv_bo bo; }; +struct anv_descriptor_slot { + bool dynamic; + uint8_t index; +} entries[0]; + struct anv_descriptor_set_layout { struct { uint32_t surface_count; - uint32_t *surface_start; + struct anv_descriptor_slot *surface_start; uint32_t sampler_count; - uint32_t *sampler_start; + struct anv_descriptor_slot *sampler_start; } stage[VK_NUM_SHADER_STAGE]; uint32_t count; uint32_t num_dynamic_buffers; - uint32_t entries[0]; + struct anv_descriptor_slot entries[0]; }; struct anv_descriptor { @@ -754,6 +759,7 @@ struct anv_surface_view { struct anv_state surface_state; struct anv_bo * bo; uint32_t offset; + uint32_t range; VkExtent3D extent; VkFormat format; }; -- 2.30.2