From 2c8058fb68a1e8cbc835272bd70c65eeac0779b9 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Tue, 11 Jul 2017 11:06:49 -0700 Subject: [PATCH] anv: Add a new anv_surface_state struct This struct represents a full surface state including the addresses of the referenced main and auxiliary surfaces (if any). This makes relocation setup substantially simpler and allows us to move 100% of the surface state setup logic into anv_image where it belongs. Before, we were manually fishing data out of surface states when emitting relocations so we knew how to offset aux address. It's best to keep all of the surface state emit logic together. This also gets us closer, at least cosmetically, to a world of no relocations where addresses are placed in surface states up-front. Reviewed-by: Lionel Landwerlin --- src/intel/vulkan/anv_blorp.c | 2 +- src/intel/vulkan/anv_image.c | 68 ++++++++++------- src/intel/vulkan/anv_private.h | 35 ++++++--- src/intel/vulkan/genX_cmd_buffer.c | 114 +++++++++++------------------ 4 files changed, 110 insertions(+), 109 deletions(-) diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c index 915643ffa3c..7f51bedb76f 100644 --- a/src/intel/vulkan/anv_blorp.c +++ b/src/intel/vulkan/anv_blorp.c @@ -915,7 +915,7 @@ clear_color_attachment(struct anv_cmd_buffer *cmd_buffer, uint32_t binding_table; VkResult result = - binding_table_for_surface_state(cmd_buffer, att_state->color_rt_state, + binding_table_for_surface_state(cmd_buffer, att_state->color.state, &binding_table); if (result != VK_SUCCESS) return; diff --git a/src/intel/vulkan/anv_image.c b/src/intel/vulkan/anv_image.c index f8cb243ad69..b69f76cac36 100644 --- a/src/intel/vulkan/anv_image.c +++ b/src/intel/vulkan/anv_image.c @@ -721,7 +721,7 @@ anv_image_fill_surface_state(struct anv_device *device, enum isl_aux_usage aux_usage, const union isl_color_value *clear_color, enum anv_image_view_state_flags flags, - struct anv_state *state, + struct anv_surface_state *state_inout, struct brw_image_param *image_param_out) { const struct anv_surface *surface = @@ -742,6 +742,10 @@ anv_image_fill_surface_state(struct anv_device *device, if (!clear_color) clear_color = &default_clear_color; + const uint64_t address = image->offset + surface->offset; + const uint64_t aux_address = (aux_usage == ISL_AUX_USAGE_NONE) ? 0 : + image->offset + image->aux_surface.offset; + if (view_usage == ISL_SURF_USAGE_STORAGE_BIT && !(flags & ANV_IMAGE_VIEW_STATE_STORAGE_WRITE_ONLY) && !isl_has_matching_typed_storage_image_format(&device->info, @@ -751,11 +755,14 @@ anv_image_fill_surface_state(struct anv_device *device, * the shader. */ assert(aux_usage == ISL_AUX_USAGE_NONE); - isl_buffer_fill_state(&device->isl_dev, state->map, + isl_buffer_fill_state(&device->isl_dev, state_inout->state.map, + .address = address, .size = surface->isl.size, .format = ISL_FORMAT_RAW, .stride = 1, .mocs = device->default_mocs); + state_inout->address = address, + state_inout->aux_address = 0; } else { if (view_usage == ISL_SURF_USAGE_STORAGE_BIT && !(flags & ANV_IMAGE_VIEW_STATE_STORAGE_WRITE_ONLY)) { @@ -768,16 +775,32 @@ anv_image_fill_surface_state(struct anv_device *device, view.format); } - isl_surf_fill_state(&device->isl_dev, state->map, + isl_surf_fill_state(&device->isl_dev, state_inout->state.map, .surf = &surface->isl, .view = &view, + .address = address, .clear_color = *clear_color, .aux_surf = &image->aux_surface.isl, .aux_usage = aux_usage, + .aux_address = aux_address, .mocs = device->default_mocs); + state_inout->address = address; + if (device->info.gen >= 8) { + state_inout->aux_address = aux_address; + } else { + /* On gen7 and prior, the bottom 12 bits of the MCS base address are + * used to store other information. This should be ok, however, + * because surface buffer addresses are always 4K page alinged. + */ + uint32_t *aux_addr_dw = state_inout->state.map + + device->isl_dev.ss.aux_addr_offset; + assert((aux_address & 0xfff) == 0); + assert(aux_address == (*aux_addr_dw & 0xfffff000)); + state_inout->aux_address = *aux_addr_dw; + } } - anv_state_flush(device, *state); + anv_state_flush(device, state_inout->state); if (image_param_out) { assert(view_usage == ISL_SURF_USAGE_STORAGE_BIT); @@ -830,12 +853,7 @@ anv_CreateImageView(VkDevice _device, break; } - const struct anv_surface *surface = - anv_image_get_surface_for_aspect_mask(image, range->aspectMask); - iview->image = image; - iview->bo = image->bo; - iview->offset = image->offset + surface->offset; iview->aspect_mask = pCreateInfo->subresourceRange.aspectMask; iview->vk_format = pCreateInfo->format; @@ -888,26 +906,26 @@ anv_CreateImageView(VkDevice _device, if (view_usage & VK_IMAGE_USAGE_SAMPLED_BIT || (view_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT && !(iview->aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT))) { - iview->optimal_sampler_surface_state = alloc_surface_state(device); - iview->general_sampler_surface_state = alloc_surface_state(device); + iview->optimal_sampler_surface_state.state = alloc_surface_state(device); + iview->general_sampler_surface_state.state = alloc_surface_state(device); - iview->general_sampler_aux_usage = + enum isl_aux_usage general_aux_usage = anv_layout_to_aux_usage(&device->info, image, iview->aspect_mask, VK_IMAGE_LAYOUT_GENERAL); - iview->optimal_sampler_aux_usage = + enum isl_aux_usage optimal_aux_usage = anv_layout_to_aux_usage(&device->info, image, iview->aspect_mask, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); anv_image_fill_surface_state(device, image, iview->aspect_mask, &iview->isl, ISL_SURF_USAGE_TEXTURE_BIT, - iview->optimal_sampler_aux_usage, NULL, + optimal_aux_usage, NULL, ANV_IMAGE_VIEW_STATE_TEXTURE_OPTIMAL, &iview->optimal_sampler_surface_state, NULL); anv_image_fill_surface_state(device, image, iview->aspect_mask, &iview->isl, ISL_SURF_USAGE_TEXTURE_BIT, - iview->general_sampler_aux_usage, NULL, + general_aux_usage, NULL, 0, &iview->general_sampler_surface_state, NULL); @@ -915,8 +933,8 @@ anv_CreateImageView(VkDevice _device, /* NOTE: This one needs to go last since it may stomp isl_view.format */ if (view_usage & VK_IMAGE_USAGE_STORAGE_BIT) { - iview->storage_surface_state = alloc_surface_state(device); - iview->writeonly_storage_surface_state = alloc_surface_state(device); + iview->storage_surface_state.state = alloc_surface_state(device); + iview->writeonly_storage_surface_state.state = alloc_surface_state(device); anv_image_fill_surface_state(device, image, iview->aspect_mask, &iview->isl, ISL_SURF_USAGE_STORAGE_BIT, @@ -948,24 +966,24 @@ anv_DestroyImageView(VkDevice _device, VkImageView _iview, if (!iview) return; - if (iview->optimal_sampler_surface_state.alloc_size > 0) { + if (iview->optimal_sampler_surface_state.state.alloc_size > 0) { anv_state_pool_free(&device->surface_state_pool, - iview->optimal_sampler_surface_state); + iview->optimal_sampler_surface_state.state); } - if (iview->general_sampler_surface_state.alloc_size > 0) { + if (iview->general_sampler_surface_state.state.alloc_size > 0) { anv_state_pool_free(&device->surface_state_pool, - iview->general_sampler_surface_state); + iview->general_sampler_surface_state.state); } - if (iview->storage_surface_state.alloc_size > 0) { + if (iview->storage_surface_state.state.alloc_size > 0) { anv_state_pool_free(&device->surface_state_pool, - iview->storage_surface_state); + iview->storage_surface_state.state); } - if (iview->writeonly_storage_surface_state.alloc_size > 0) { + if (iview->writeonly_storage_surface_state.state.alloc_size > 0) { anv_state_pool_free(&device->surface_state_pool, - iview->writeonly_storage_surface_state); + iview->writeonly_storage_surface_state.state); } vk_free2(&device->alloc, pAllocator, iview); diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index ee7672fc807..85843b204b2 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -1619,6 +1619,23 @@ void anv_dynamic_state_copy(struct anv_dynamic_state *dest, const struct anv_dynamic_state *src, uint32_t copy_mask); +struct anv_surface_state { + struct anv_state state; + /** Address of the surface referred to by this state + * + * This address is relative to the start of the BO. + */ + uint64_t address; + /* Address of the aux surface, if any + * + * This field is 0 if and only if no aux surface exists. + * + * This address is relative to the start of the BO. On gen7, the bottom 12 + * bits of this address include extra aux information. + */ + uint64_t aux_address; +}; + /** * Attachment state when recording a renderpass instance. * @@ -1627,8 +1644,8 @@ void anv_dynamic_state_copy(struct anv_dynamic_state *dest, struct anv_attachment_state { enum isl_aux_usage aux_usage; enum isl_aux_usage input_aux_usage; - struct anv_state color_rt_state; - struct anv_state input_att_state; + struct anv_surface_state color; + struct anv_surface_state input; VkImageLayout current_layout; VkImageAspectFlags pending_clear_aspects; @@ -2359,8 +2376,6 @@ anv_get_levelCount(const struct anv_image *image, struct anv_image_view { const struct anv_image *image; /**< VkImageViewCreateInfo::image */ - struct anv_bo *bo; - uint32_t offset; /**< Offset into bo. */ struct isl_view isl; @@ -2372,23 +2387,21 @@ struct anv_image_view { * RENDER_SURFACE_STATE when using image as a sampler surface with an image * layout of SHADER_READ_ONLY_OPTIMAL or DEPTH_STENCIL_READ_ONLY_OPTIMAL. */ - enum isl_aux_usage optimal_sampler_aux_usage; - struct anv_state optimal_sampler_surface_state; + struct anv_surface_state optimal_sampler_surface_state; /** * RENDER_SURFACE_STATE when using image as a sampler surface with an image * layout of GENERAL. */ - enum isl_aux_usage general_sampler_aux_usage; - struct anv_state general_sampler_surface_state; + struct anv_surface_state general_sampler_surface_state; /** * RENDER_SURFACE_STATE when using image as a storage image. Separate states * for write-only and readable, using the real format for write-only and the * lowered format for readable. */ - struct anv_state storage_surface_state; - struct anv_state writeonly_storage_surface_state; + struct anv_surface_state storage_surface_state; + struct anv_surface_state writeonly_storage_surface_state; struct brw_image_param storage_image_param; }; @@ -2406,7 +2419,7 @@ void anv_image_fill_surface_state(struct anv_device *device, enum isl_aux_usage aux_usage, const union isl_color_value *clear_color, enum anv_image_view_state_flags flags, - struct anv_state *state, + struct anv_surface_state *state_inout, struct brw_image_param *image_param_out); struct anv_image_create_info { diff --git a/src/intel/vulkan/genX_cmd_buffer.c b/src/intel/vulkan/genX_cmd_buffer.c index 188d9e71bca..7fb607f2189 100644 --- a/src/intel/vulkan/genX_cmd_buffer.c +++ b/src/intel/vulkan/genX_cmd_buffer.c @@ -179,34 +179,20 @@ add_surface_state_reloc(struct anv_cmd_buffer *cmd_buffer, } static void -add_image_relocs(struct anv_cmd_buffer * const cmd_buffer, - const struct anv_image * const image, - const VkImageAspectFlags aspect_mask, - const enum isl_aux_usage aux_usage, - const struct anv_state state) +add_image_relocs(struct anv_cmd_buffer *cmd_buffer, + const struct anv_image *image, + struct anv_surface_state state) { const struct isl_device *isl_dev = &cmd_buffer->device->isl_dev; - const uint32_t surf_offset = image->offset + - anv_image_get_surface_for_aspect_mask(image, aspect_mask)->offset; - add_surface_state_reloc(cmd_buffer, state, image->bo, surf_offset); - - if (aux_usage != ISL_AUX_USAGE_NONE) { - uint32_t aux_offset = image->offset + image->aux_surface.offset; - - /* On gen7 and prior, the bottom 12 bits of the MCS base address are - * used to store other information. This should be ok, however, because - * surface buffer addresses are always 4K page alinged. - */ - assert((aux_offset & 0xfff) == 0); - uint32_t *aux_addr_dw = state.map + isl_dev->ss.aux_addr_offset; - aux_offset += *aux_addr_dw & 0xfff; + add_surface_state_reloc(cmd_buffer, state.state, image->bo, state.address); + if (state.aux_address) { VkResult result = anv_reloc_list_add(&cmd_buffer->surface_relocs, &cmd_buffer->pool->alloc, - state.offset + isl_dev->ss.aux_addr_offset, - image->bo, aux_offset); + state.state.offset + isl_dev->ss.aux_addr_offset, + image->bo, state.aux_address); if (result != VK_SUCCESS) anv_batch_set_error(&cmd_buffer->batch, result); } @@ -774,8 +760,8 @@ transition_color_buffer(struct anv_cmd_buffer *cmd_buffer, /* Create a surface state with the right clear color and perform the * resolve. */ - struct anv_state surface_state = - anv_cmd_buffer_alloc_surface_state(cmd_buffer); + struct anv_surface_state surface_state; + surface_state.state = anv_cmd_buffer_alloc_surface_state(cmd_buffer); anv_image_fill_surface_state(cmd_buffer->device, image, VK_IMAGE_ASPECT_COLOR_BIT, &(struct isl_view) { @@ -789,14 +775,11 @@ transition_color_buffer(struct anv_cmd_buffer *cmd_buffer, ISL_SURF_USAGE_RENDER_TARGET_BIT, aux_usage, NULL, 0, &surface_state, NULL); - add_image_relocs(cmd_buffer, image, VK_IMAGE_ASPECT_COLOR_BIT, - image->aux_usage == ISL_AUX_USAGE_CCS_E ? - ISL_AUX_USAGE_CCS_E : ISL_AUX_USAGE_CCS_D, - surface_state); - anv_state_flush(cmd_buffer->device, surface_state); - genX(copy_fast_clear_dwords)(cmd_buffer, surface_state, image, level, - false /* copy to ss */); - anv_ccs_resolve(cmd_buffer, surface_state, image, level, layer_count, + add_image_relocs(cmd_buffer, image, surface_state); + genX(copy_fast_clear_dwords)(cmd_buffer, surface_state.state, image, + level, false /* copy to ss */); + anv_ccs_resolve(cmd_buffer, surface_state.state, image, + level, layer_count, image->aux_usage == ISL_AUX_USAGE_CCS_E ? BLORP_FAST_CLEAR_OP_RESOLVE_PARTIAL : BLORP_FAST_CLEAR_OP_RESOLVE_FULL); @@ -859,13 +842,13 @@ genX(cmd_buffer_setup_attachments)(struct anv_cmd_buffer *cmd_buffer, for (uint32_t i = 0; i < pass->attachment_count; ++i) { if (vk_format_is_color(pass->attachments[i].format)) { - state->attachments[i].color_rt_state = next_state; + state->attachments[i].color.state = next_state; next_state.offset += ss_stride; next_state.map += ss_stride; } if (need_input_attachment_state(&pass->attachments[i])) { - state->attachments[i].input_att_state = next_state; + state->attachments[i].input.state = next_state; next_state.offset += ss_stride; next_state.map += ss_stride; } @@ -926,12 +909,11 @@ genX(cmd_buffer_setup_attachments)(struct anv_cmd_buffer *cmd_buffer, state->attachments[i].aux_usage, &clear_color, 0, - &state->attachments[i].color_rt_state, + &state->attachments[i].color, NULL); - add_image_relocs(cmd_buffer, iview->image, iview->aspect_mask, - state->attachments[i].aux_usage, - state->attachments[i].color_rt_state); + add_image_relocs(cmd_buffer, iview->image, + state->attachments[i].color); } else { /* This field will be initialized after the first subpass * transition. @@ -950,12 +932,11 @@ genX(cmd_buffer_setup_attachments)(struct anv_cmd_buffer *cmd_buffer, state->attachments[i].input_aux_usage, &clear_color, 0, - &state->attachments[i].input_att_state, + &state->attachments[i].input, NULL); - add_image_relocs(cmd_buffer, iview->image, iview->aspect_mask, - state->attachments[i].input_aux_usage, - state->attachments[i].input_att_state); + add_image_relocs(cmd_buffer, iview->image, + state->attachments[i].input); } } } @@ -1553,7 +1534,7 @@ emit_binding_table(struct anv_cmd_buffer *cmd_buffer, if (att == VK_ATTACHMENT_UNUSED) { surface_state = cmd_buffer->state.null_surface_state; } else { - surface_state = cmd_buffer->state.attachments[att].color_rt_state; + surface_state = cmd_buffer->state.attachments[att].color.state; } } else { surface_state = cmd_buffer->state.null_surface_state; @@ -1575,18 +1556,13 @@ emit_binding_table(struct anv_cmd_buffer *cmd_buffer, case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: { - enum isl_aux_usage aux_usage; - if (desc->layout == VK_IMAGE_LAYOUT_GENERAL) { - surface_state = desc->image_view->general_sampler_surface_state; - aux_usage = desc->image_view->general_sampler_aux_usage; - } else { - surface_state = desc->image_view->optimal_sampler_surface_state; - aux_usage = desc->image_view->optimal_sampler_aux_usage; - } + struct anv_surface_state sstate = + (desc->layout == VK_IMAGE_LAYOUT_GENERAL) ? + desc->image_view->general_sampler_surface_state : + desc->image_view->optimal_sampler_surface_state; + surface_state = sstate.state; assert(surface_state.alloc_size); - add_image_relocs(cmd_buffer, desc->image_view->image, - desc->image_view->aspect_mask, - aux_usage, surface_state); + add_image_relocs(cmd_buffer, desc->image_view->image, sstate); break; } case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: @@ -1595,18 +1571,13 @@ emit_binding_table(struct anv_cmd_buffer *cmd_buffer, /* For depth and stencil input attachments, we treat it like any * old texture that a user may have bound. */ - enum isl_aux_usage aux_usage; - if (desc->layout == VK_IMAGE_LAYOUT_GENERAL) { - surface_state = desc->image_view->general_sampler_surface_state; - aux_usage = desc->image_view->general_sampler_aux_usage; - } else { - surface_state = desc->image_view->optimal_sampler_surface_state; - aux_usage = desc->image_view->optimal_sampler_aux_usage; - } + struct anv_surface_state sstate = + (desc->layout == VK_IMAGE_LAYOUT_GENERAL) ? + desc->image_view->general_sampler_surface_state : + desc->image_view->optimal_sampler_surface_state; + surface_state = sstate.state; assert(surface_state.alloc_size); - add_image_relocs(cmd_buffer, desc->image_view->image, - desc->image_view->aspect_mask, - aux_usage, surface_state); + add_image_relocs(cmd_buffer, desc->image_view->image, sstate); } else { /* For color input attachments, we create the surface state at * vkBeginRenderPass time so that we can include aux and clear @@ -1615,18 +1586,17 @@ emit_binding_table(struct anv_cmd_buffer *cmd_buffer, assert(binding->input_attachment_index < subpass->input_count); const unsigned subpass_att = binding->input_attachment_index; const unsigned att = subpass->input_attachments[subpass_att].attachment; - surface_state = cmd_buffer->state.attachments[att].input_att_state; + surface_state = cmd_buffer->state.attachments[att].input.state; } break; case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: { - surface_state = (binding->write_only) + struct anv_surface_state sstate = (binding->write_only) ? desc->image_view->writeonly_storage_surface_state : desc->image_view->storage_surface_state; + surface_state = sstate.state; assert(surface_state.alloc_size); - add_image_relocs(cmd_buffer, desc->image_view->image, - desc->image_view->aspect_mask, - desc->image_view->image->aux_usage, surface_state); + add_image_relocs(cmd_buffer, desc->image_view->image, sstate); struct brw_image_param *image_param = &cmd_buffer->state.push_constants[stage]->images[image++]; @@ -2951,7 +2921,7 @@ cmd_buffer_subpass_sync_fast_clear_values(struct anv_cmd_buffer *cmd_buffer) */ if (att_state->pending_clear_aspects && att_state->fast_clear) { /* Update the fast clear state entry. */ - genX(copy_fast_clear_dwords)(cmd_buffer, att_state->color_rt_state, + genX(copy_fast_clear_dwords)(cmd_buffer, att_state->color.state, iview->image, iview->isl.base_level, true /* copy from ss */); @@ -2975,13 +2945,13 @@ cmd_buffer_subpass_sync_fast_clear_values(struct anv_cmd_buffer *cmd_buffer) * * TODO: Do this only once per render pass instead of every subpass. */ - genX(copy_fast_clear_dwords)(cmd_buffer, att_state->color_rt_state, + genX(copy_fast_clear_dwords)(cmd_buffer, att_state->color.state, iview->image, iview->isl.base_level, false /* copy to ss */); if (need_input_attachment_state(rp_att) && att_state->input_aux_usage != ISL_AUX_USAGE_NONE) { - genX(copy_fast_clear_dwords)(cmd_buffer, att_state->input_att_state, + genX(copy_fast_clear_dwords)(cmd_buffer, att_state->input.state, iview->image, iview->isl.base_level, false /* copy to ss */); } -- 2.30.2