101e04c3fSmrg/* 201e04c3fSmrg * Copyright © 2016 Intel Corporation 301e04c3fSmrg * 401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 501e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 601e04c3fSmrg * to deal in the Software without restriction, including without limitation 701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the 901e04c3fSmrg * Software is furnished to do so, subject to the following conditions: 1001e04c3fSmrg * 1101e04c3fSmrg * The above copyright notice and this permission notice (including the next 1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the 1301e04c3fSmrg * Software. 1401e04c3fSmrg * 1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 2101e04c3fSmrg * IN THE SOFTWARE. 2201e04c3fSmrg */ 2301e04c3fSmrg 2401e04c3fSmrg#include "anv_private.h" 2501e04c3fSmrg 2601e04c3fSmrgstatic bool 279f464c52Smayalookup_blorp_shader(struct blorp_batch *batch, 2801e04c3fSmrg const void *key, uint32_t key_size, 2901e04c3fSmrg uint32_t *kernel_out, void *prog_data_out) 3001e04c3fSmrg{ 319f464c52Smaya struct blorp_context *blorp = batch->blorp; 3201e04c3fSmrg struct anv_device *device = blorp->driver_ctx; 3301e04c3fSmrg 3401e04c3fSmrg /* The default cache must be a real cache */ 3501e04c3fSmrg assert(device->default_pipeline_cache.cache); 3601e04c3fSmrg 3701e04c3fSmrg struct anv_shader_bin *bin = 3801e04c3fSmrg anv_pipeline_cache_search(&device->default_pipeline_cache, key, key_size); 3901e04c3fSmrg if (!bin) 4001e04c3fSmrg return false; 4101e04c3fSmrg 4201e04c3fSmrg /* The cache already has a reference and it's not going anywhere so there 4301e04c3fSmrg * is no need to hold a second reference. 4401e04c3fSmrg */ 4501e04c3fSmrg anv_shader_bin_unref(device, bin); 4601e04c3fSmrg 4701e04c3fSmrg *kernel_out = bin->kernel.offset; 4801e04c3fSmrg *(const struct brw_stage_prog_data **)prog_data_out = bin->prog_data; 4901e04c3fSmrg 5001e04c3fSmrg return true; 5101e04c3fSmrg} 5201e04c3fSmrg 5301e04c3fSmrgstatic bool 547ec681f3Smrgupload_blorp_shader(struct blorp_batch *batch, uint32_t stage, 5501e04c3fSmrg const void *key, uint32_t key_size, 5601e04c3fSmrg const void *kernel, uint32_t kernel_size, 5701e04c3fSmrg const struct brw_stage_prog_data *prog_data, 5801e04c3fSmrg uint32_t prog_data_size, 5901e04c3fSmrg uint32_t *kernel_out, void *prog_data_out) 6001e04c3fSmrg{ 619f464c52Smaya struct blorp_context *blorp = batch->blorp; 6201e04c3fSmrg struct anv_device *device = blorp->driver_ctx; 6301e04c3fSmrg 6401e04c3fSmrg /* The blorp cache must be a real cache */ 6501e04c3fSmrg assert(device->default_pipeline_cache.cache); 6601e04c3fSmrg 6701e04c3fSmrg struct anv_pipeline_bind_map bind_map = { 6801e04c3fSmrg .surface_count = 0, 6901e04c3fSmrg .sampler_count = 0, 7001e04c3fSmrg }; 7101e04c3fSmrg 7201e04c3fSmrg struct anv_shader_bin *bin = 737ec681f3Smrg anv_pipeline_cache_upload_kernel(&device->default_pipeline_cache, stage, 7401e04c3fSmrg key, key_size, kernel, kernel_size, 759f464c52Smaya prog_data, prog_data_size, 767ec681f3Smrg NULL, 0, NULL, &bind_map); 7701e04c3fSmrg 7801e04c3fSmrg if (!bin) 7901e04c3fSmrg return false; 8001e04c3fSmrg 8101e04c3fSmrg /* The cache already has a reference and it's not going anywhere so there 8201e04c3fSmrg * is no need to hold a second reference. 8301e04c3fSmrg */ 8401e04c3fSmrg anv_shader_bin_unref(device, bin); 8501e04c3fSmrg 8601e04c3fSmrg *kernel_out = bin->kernel.offset; 8701e04c3fSmrg *(const struct brw_stage_prog_data **)prog_data_out = bin->prog_data; 8801e04c3fSmrg 8901e04c3fSmrg return true; 9001e04c3fSmrg} 9101e04c3fSmrg 9201e04c3fSmrgvoid 9301e04c3fSmrganv_device_init_blorp(struct anv_device *device) 9401e04c3fSmrg{ 9501e04c3fSmrg blorp_init(&device->blorp, device, &device->isl_dev); 967ec681f3Smrg device->blorp.compiler = device->physical->compiler; 9701e04c3fSmrg device->blorp.lookup_shader = lookup_blorp_shader; 9801e04c3fSmrg device->blorp.upload_shader = upload_blorp_shader; 997ec681f3Smrg switch (device->info.verx10) { 1007ec681f3Smrg case 70: 1017ec681f3Smrg device->blorp.exec = gfx7_blorp_exec; 1027ec681f3Smrg break; 1037ec681f3Smrg case 75: 1047ec681f3Smrg device->blorp.exec = gfx75_blorp_exec; 1057ec681f3Smrg break; 1067ec681f3Smrg case 80: 1077ec681f3Smrg device->blorp.exec = gfx8_blorp_exec; 10801e04c3fSmrg break; 1097ec681f3Smrg case 90: 1107ec681f3Smrg device->blorp.exec = gfx9_blorp_exec; 11101e04c3fSmrg break; 1127ec681f3Smrg case 110: 1137ec681f3Smrg device->blorp.exec = gfx11_blorp_exec; 11401e04c3fSmrg break; 1157ec681f3Smrg case 120: 1167ec681f3Smrg device->blorp.exec = gfx12_blorp_exec; 11701e04c3fSmrg break; 1187ec681f3Smrg case 125: 1197ec681f3Smrg device->blorp.exec = gfx125_blorp_exec; 12001e04c3fSmrg break; 12101e04c3fSmrg default: 12201e04c3fSmrg unreachable("Unknown hardware generation"); 12301e04c3fSmrg } 12401e04c3fSmrg} 12501e04c3fSmrg 12601e04c3fSmrgvoid 12701e04c3fSmrganv_device_finish_blorp(struct anv_device *device) 12801e04c3fSmrg{ 12901e04c3fSmrg blorp_finish(&device->blorp); 13001e04c3fSmrg} 13101e04c3fSmrg 1327ec681f3Smrgstatic void 1337ec681f3Smrganv_blorp_batch_init(struct anv_cmd_buffer *cmd_buffer, 1347ec681f3Smrg struct blorp_batch *batch, enum blorp_batch_flags flags) 1357ec681f3Smrg{ 1367ec681f3Smrg if (!(cmd_buffer->pool->queue_family->queueFlags & VK_QUEUE_GRAPHICS_BIT)) { 1377ec681f3Smrg assert(cmd_buffer->pool->queue_family->queueFlags & VK_QUEUE_COMPUTE_BIT); 1387ec681f3Smrg flags |= BLORP_BATCH_USE_COMPUTE; 1397ec681f3Smrg } 1407ec681f3Smrg 1417ec681f3Smrg blorp_batch_init(&cmd_buffer->device->blorp, batch, cmd_buffer, flags); 1427ec681f3Smrg} 1437ec681f3Smrg 1447ec681f3Smrgstatic void 1457ec681f3Smrganv_blorp_batch_finish(struct blorp_batch *batch) 1467ec681f3Smrg{ 1477ec681f3Smrg blorp_batch_finish(batch); 1487ec681f3Smrg} 1497ec681f3Smrg 15001e04c3fSmrgstatic void 15101e04c3fSmrgget_blorp_surf_for_anv_buffer(struct anv_device *device, 15201e04c3fSmrg struct anv_buffer *buffer, uint64_t offset, 15301e04c3fSmrg uint32_t width, uint32_t height, 15401e04c3fSmrg uint32_t row_pitch, enum isl_format format, 1557ec681f3Smrg bool is_dest, 15601e04c3fSmrg struct blorp_surf *blorp_surf, 15701e04c3fSmrg struct isl_surf *isl_surf) 15801e04c3fSmrg{ 15901e04c3fSmrg const struct isl_format_layout *fmtl = 16001e04c3fSmrg isl_format_get_layout(format); 16101e04c3fSmrg bool ok UNUSED; 16201e04c3fSmrg 16301e04c3fSmrg /* ASTC is the only format which doesn't support linear layouts. 16401e04c3fSmrg * Create an equivalently sized surface with ISL to get around this. 16501e04c3fSmrg */ 16601e04c3fSmrg if (fmtl->txc == ISL_TXC_ASTC) { 16701e04c3fSmrg /* Use an equivalently sized format */ 16801e04c3fSmrg format = ISL_FORMAT_R32G32B32A32_UINT; 16901e04c3fSmrg assert(fmtl->bpb == isl_format_get_layout(format)->bpb); 17001e04c3fSmrg 17101e04c3fSmrg /* Shrink the dimensions for the new format */ 17201e04c3fSmrg width = DIV_ROUND_UP(width, fmtl->bw); 17301e04c3fSmrg height = DIV_ROUND_UP(height, fmtl->bh); 17401e04c3fSmrg } 17501e04c3fSmrg 17601e04c3fSmrg *blorp_surf = (struct blorp_surf) { 17701e04c3fSmrg .surf = isl_surf, 17801e04c3fSmrg .addr = { 17901e04c3fSmrg .buffer = buffer->address.bo, 18001e04c3fSmrg .offset = buffer->address.offset + offset, 1817ec681f3Smrg .mocs = anv_mocs(device, buffer->address.bo, 1827ec681f3Smrg is_dest ? ISL_SURF_USAGE_RENDER_TARGET_BIT 1837ec681f3Smrg : ISL_SURF_USAGE_TEXTURE_BIT), 18401e04c3fSmrg }, 18501e04c3fSmrg }; 18601e04c3fSmrg 18701e04c3fSmrg ok = isl_surf_init(&device->isl_dev, isl_surf, 18801e04c3fSmrg .dim = ISL_SURF_DIM_2D, 18901e04c3fSmrg .format = format, 19001e04c3fSmrg .width = width, 19101e04c3fSmrg .height = height, 19201e04c3fSmrg .depth = 1, 19301e04c3fSmrg .levels = 1, 19401e04c3fSmrg .array_len = 1, 19501e04c3fSmrg .samples = 1, 19601e04c3fSmrg .row_pitch_B = row_pitch, 1977ec681f3Smrg .usage = is_dest ? ISL_SURF_USAGE_RENDER_TARGET_BIT 1987ec681f3Smrg : ISL_SURF_USAGE_TEXTURE_BIT, 19901e04c3fSmrg .tiling_flags = ISL_TILING_LINEAR_BIT); 20001e04c3fSmrg assert(ok); 20101e04c3fSmrg} 20201e04c3fSmrg 20301e04c3fSmrg/* Pick something high enough that it won't be used in core and low enough it 20401e04c3fSmrg * will never map to an extension. 20501e04c3fSmrg */ 20601e04c3fSmrg#define ANV_IMAGE_LAYOUT_EXPLICIT_AUX (VkImageLayout)10000000 20701e04c3fSmrg 20801e04c3fSmrgstatic struct blorp_address 20901e04c3fSmrganv_to_blorp_address(struct anv_address addr) 21001e04c3fSmrg{ 21101e04c3fSmrg return (struct blorp_address) { 21201e04c3fSmrg .buffer = addr.bo, 21301e04c3fSmrg .offset = addr.offset, 21401e04c3fSmrg }; 21501e04c3fSmrg} 21601e04c3fSmrg 21701e04c3fSmrgstatic void 21801e04c3fSmrgget_blorp_surf_for_anv_image(const struct anv_device *device, 21901e04c3fSmrg const struct anv_image *image, 22001e04c3fSmrg VkImageAspectFlags aspect, 2217ec681f3Smrg VkImageUsageFlags usage, 22201e04c3fSmrg VkImageLayout layout, 22301e04c3fSmrg enum isl_aux_usage aux_usage, 22401e04c3fSmrg struct blorp_surf *blorp_surf) 22501e04c3fSmrg{ 2267ec681f3Smrg const uint32_t plane = anv_image_aspect_to_plane(image, aspect); 22701e04c3fSmrg 2287ec681f3Smrg if (layout != ANV_IMAGE_LAYOUT_EXPLICIT_AUX) { 2297ec681f3Smrg assert(usage != 0); 2307ec681f3Smrg aux_usage = anv_layout_to_aux_usage(&device->info, image, 2317ec681f3Smrg aspect, usage, layout); 2327ec681f3Smrg } 2337ec681f3Smrg 2347ec681f3Smrg isl_surf_usage_flags_t mocs_usage = 2357ec681f3Smrg (usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) ? 2367ec681f3Smrg ISL_SURF_USAGE_RENDER_TARGET_BIT : ISL_SURF_USAGE_TEXTURE_BIT; 2377ec681f3Smrg 2387ec681f3Smrg const struct anv_surface *surface = &image->planes[plane].primary_surface; 2397ec681f3Smrg const struct anv_address address = 2407ec681f3Smrg anv_image_address(image, &surface->memory_range); 24101e04c3fSmrg 24201e04c3fSmrg *blorp_surf = (struct blorp_surf) { 24301e04c3fSmrg .surf = &surface->isl, 24401e04c3fSmrg .addr = { 2457ec681f3Smrg .buffer = address.bo, 2467ec681f3Smrg .offset = address.offset, 2477ec681f3Smrg .mocs = anv_mocs(device, address.bo, mocs_usage), 24801e04c3fSmrg }, 24901e04c3fSmrg }; 25001e04c3fSmrg 25101e04c3fSmrg if (aux_usage != ISL_AUX_USAGE_NONE) { 25201e04c3fSmrg const struct anv_surface *aux_surface = &image->planes[plane].aux_surface; 2537ec681f3Smrg const struct anv_address aux_address = 2547ec681f3Smrg anv_image_address(image, &aux_surface->memory_range); 2557ec681f3Smrg 25601e04c3fSmrg blorp_surf->aux_usage = aux_usage; 2577ec681f3Smrg blorp_surf->aux_surf = &aux_surface->isl; 2587ec681f3Smrg 2597ec681f3Smrg if (!anv_address_is_null(aux_address)) { 2607ec681f3Smrg blorp_surf->aux_addr = (struct blorp_address) { 2617ec681f3Smrg .buffer = aux_address.bo, 2627ec681f3Smrg .offset = aux_address.offset, 2637ec681f3Smrg .mocs = anv_mocs(device, aux_address.bo, 0), 2647ec681f3Smrg }; 2657ec681f3Smrg } 26601e04c3fSmrg 26701e04c3fSmrg /* If we're doing a partial resolve, then we need the indirect clear 26801e04c3fSmrg * color. If we are doing a fast clear and want to store/update the 26901e04c3fSmrg * clear color, we also pass the address to blorp, otherwise it will only 27001e04c3fSmrg * stomp the CCS to a particular value and won't care about format or 27101e04c3fSmrg * clear value 27201e04c3fSmrg */ 27301e04c3fSmrg if (aspect & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV) { 27401e04c3fSmrg const struct anv_address clear_color_addr = 27501e04c3fSmrg anv_image_get_clear_color_addr(device, image, aspect); 27601e04c3fSmrg blorp_surf->clear_color_addr = anv_to_blorp_address(clear_color_addr); 2777ec681f3Smrg } else if (aspect & VK_IMAGE_ASPECT_DEPTH_BIT) { 2787ec681f3Smrg const struct anv_address clear_color_addr = 2797ec681f3Smrg anv_image_get_clear_color_addr(device, image, aspect); 28001e04c3fSmrg blorp_surf->clear_color_addr = anv_to_blorp_address(clear_color_addr); 2817ec681f3Smrg blorp_surf->clear_color = (union isl_color_value) { 2827ec681f3Smrg .f32 = { ANV_HZ_FC_VAL }, 2837ec681f3Smrg }; 28401e04c3fSmrg } 28501e04c3fSmrg } 28601e04c3fSmrg} 28701e04c3fSmrg 2887ec681f3Smrgstatic bool 2897ec681f3Smrgget_blorp_surf_for_anv_shadow_image(const struct anv_device *device, 2907ec681f3Smrg const struct anv_image *image, 2917ec681f3Smrg VkImageAspectFlags aspect, 2927ec681f3Smrg struct blorp_surf *blorp_surf) 29301e04c3fSmrg{ 29401e04c3fSmrg 2957ec681f3Smrg const uint32_t plane = anv_image_aspect_to_plane(image, aspect); 2967ec681f3Smrg if (!anv_surface_is_valid(&image->planes[plane].shadow_surface)) 2977ec681f3Smrg return false; 29801e04c3fSmrg 2997ec681f3Smrg const struct anv_surface *surface = &image->planes[plane].shadow_surface; 3007ec681f3Smrg const struct anv_address address = 3017ec681f3Smrg anv_image_address(image, &surface->memory_range); 3027ec681f3Smrg 3037ec681f3Smrg *blorp_surf = (struct blorp_surf) { 3047ec681f3Smrg .surf = &surface->isl, 3057ec681f3Smrg .addr = { 3067ec681f3Smrg .buffer = address.bo, 3077ec681f3Smrg .offset = address.offset, 3087ec681f3Smrg .mocs = anv_mocs(device, address.bo, ISL_SURF_USAGE_RENDER_TARGET_BIT), 3097ec681f3Smrg }, 3107ec681f3Smrg }; 31101e04c3fSmrg 3127ec681f3Smrg return true; 3137ec681f3Smrg} 31401e04c3fSmrg 3157ec681f3Smrgstatic void 3167ec681f3Smrgcopy_image(struct anv_cmd_buffer *cmd_buffer, 3177ec681f3Smrg struct blorp_batch *batch, 3187ec681f3Smrg struct anv_image *src_image, 3197ec681f3Smrg VkImageLayout src_image_layout, 3207ec681f3Smrg struct anv_image *dst_image, 3217ec681f3Smrg VkImageLayout dst_image_layout, 3227ec681f3Smrg const VkImageCopy2KHR *region) 3237ec681f3Smrg{ 3247ec681f3Smrg VkOffset3D srcOffset = 3257ec681f3Smrg anv_sanitize_image_offset(src_image->vk.image_type, region->srcOffset); 3267ec681f3Smrg VkOffset3D dstOffset = 3277ec681f3Smrg anv_sanitize_image_offset(dst_image->vk.image_type, region->dstOffset); 3287ec681f3Smrg VkExtent3D extent = 3297ec681f3Smrg anv_sanitize_image_extent(src_image->vk.image_type, region->extent); 3307ec681f3Smrg 3317ec681f3Smrg const uint32_t dst_level = region->dstSubresource.mipLevel; 3327ec681f3Smrg unsigned dst_base_layer, layer_count; 3337ec681f3Smrg if (dst_image->vk.image_type == VK_IMAGE_TYPE_3D) { 3347ec681f3Smrg dst_base_layer = region->dstOffset.z; 3357ec681f3Smrg layer_count = region->extent.depth; 3367ec681f3Smrg } else { 3377ec681f3Smrg dst_base_layer = region->dstSubresource.baseArrayLayer; 3387ec681f3Smrg layer_count = vk_image_subresource_layer_count(&dst_image->vk, 3397ec681f3Smrg ®ion->dstSubresource); 3407ec681f3Smrg } 3417ec681f3Smrg 3427ec681f3Smrg const uint32_t src_level = region->srcSubresource.mipLevel; 3437ec681f3Smrg unsigned src_base_layer; 3447ec681f3Smrg if (src_image->vk.image_type == VK_IMAGE_TYPE_3D) { 3457ec681f3Smrg src_base_layer = region->srcOffset.z; 3467ec681f3Smrg } else { 3477ec681f3Smrg src_base_layer = region->srcSubresource.baseArrayLayer; 3487ec681f3Smrg assert(layer_count == 3497ec681f3Smrg vk_image_subresource_layer_count(&src_image->vk, 3507ec681f3Smrg ®ion->srcSubresource)); 3517ec681f3Smrg } 3527ec681f3Smrg 3537ec681f3Smrg VkImageAspectFlags src_mask = region->srcSubresource.aspectMask, 3547ec681f3Smrg dst_mask = region->dstSubresource.aspectMask; 3557ec681f3Smrg 3567ec681f3Smrg assert(anv_image_aspects_compatible(src_mask, dst_mask)); 3577ec681f3Smrg 3587ec681f3Smrg if (util_bitcount(src_mask) > 1) { 3597ec681f3Smrg anv_foreach_image_aspect_bit(aspect_bit, src_image, src_mask) { 36001e04c3fSmrg struct blorp_surf src_surf, dst_surf; 3617ec681f3Smrg get_blorp_surf_for_anv_image(cmd_buffer->device, 3627ec681f3Smrg src_image, 1UL << aspect_bit, 3637ec681f3Smrg VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 3647ec681f3Smrg src_image_layout, ISL_AUX_USAGE_NONE, 36501e04c3fSmrg &src_surf); 3667ec681f3Smrg get_blorp_surf_for_anv_image(cmd_buffer->device, 3677ec681f3Smrg dst_image, 1UL << aspect_bit, 3687ec681f3Smrg VK_IMAGE_USAGE_TRANSFER_DST_BIT, 3697ec681f3Smrg dst_image_layout, ISL_AUX_USAGE_NONE, 37001e04c3fSmrg &dst_surf); 3717ec681f3Smrg anv_cmd_buffer_mark_image_written(cmd_buffer, dst_image, 3727ec681f3Smrg 1UL << aspect_bit, 37301e04c3fSmrg dst_surf.aux_usage, dst_level, 37401e04c3fSmrg dst_base_layer, layer_count); 37501e04c3fSmrg 37601e04c3fSmrg for (unsigned i = 0; i < layer_count; i++) { 3777ec681f3Smrg blorp_copy(batch, &src_surf, src_level, src_base_layer + i, 37801e04c3fSmrg &dst_surf, dst_level, dst_base_layer + i, 37901e04c3fSmrg srcOffset.x, srcOffset.y, 38001e04c3fSmrg dstOffset.x, dstOffset.y, 38101e04c3fSmrg extent.width, extent.height); 38201e04c3fSmrg } 3837ec681f3Smrg 3847ec681f3Smrg struct blorp_surf dst_shadow_surf; 3857ec681f3Smrg if (get_blorp_surf_for_anv_shadow_image(cmd_buffer->device, 3867ec681f3Smrg dst_image, 3877ec681f3Smrg 1UL << aspect_bit, 3887ec681f3Smrg &dst_shadow_surf)) { 3897ec681f3Smrg for (unsigned i = 0; i < layer_count; i++) { 3907ec681f3Smrg blorp_copy(batch, &src_surf, src_level, src_base_layer + i, 3917ec681f3Smrg &dst_shadow_surf, dst_level, dst_base_layer + i, 3927ec681f3Smrg srcOffset.x, srcOffset.y, 3937ec681f3Smrg dstOffset.x, dstOffset.y, 3947ec681f3Smrg extent.width, extent.height); 3957ec681f3Smrg } 3967ec681f3Smrg } 3977ec681f3Smrg } 3987ec681f3Smrg } else { 3997ec681f3Smrg struct blorp_surf src_surf, dst_surf; 4007ec681f3Smrg get_blorp_surf_for_anv_image(cmd_buffer->device, src_image, src_mask, 4017ec681f3Smrg VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 4027ec681f3Smrg src_image_layout, ISL_AUX_USAGE_NONE, 4037ec681f3Smrg &src_surf); 4047ec681f3Smrg get_blorp_surf_for_anv_image(cmd_buffer->device, dst_image, dst_mask, 4057ec681f3Smrg VK_IMAGE_USAGE_TRANSFER_DST_BIT, 4067ec681f3Smrg dst_image_layout, ISL_AUX_USAGE_NONE, 4077ec681f3Smrg &dst_surf); 4087ec681f3Smrg anv_cmd_buffer_mark_image_written(cmd_buffer, dst_image, dst_mask, 4097ec681f3Smrg dst_surf.aux_usage, dst_level, 4107ec681f3Smrg dst_base_layer, layer_count); 4117ec681f3Smrg 4127ec681f3Smrg for (unsigned i = 0; i < layer_count; i++) { 4137ec681f3Smrg blorp_copy(batch, &src_surf, src_level, src_base_layer + i, 4147ec681f3Smrg &dst_surf, dst_level, dst_base_layer + i, 4157ec681f3Smrg srcOffset.x, srcOffset.y, 4167ec681f3Smrg dstOffset.x, dstOffset.y, 4177ec681f3Smrg extent.width, extent.height); 4187ec681f3Smrg } 4197ec681f3Smrg 4207ec681f3Smrg struct blorp_surf dst_shadow_surf; 4217ec681f3Smrg if (get_blorp_surf_for_anv_shadow_image(cmd_buffer->device, 4227ec681f3Smrg dst_image, dst_mask, 4237ec681f3Smrg &dst_shadow_surf)) { 4247ec681f3Smrg for (unsigned i = 0; i < layer_count; i++) { 4257ec681f3Smrg blorp_copy(batch, &src_surf, src_level, src_base_layer + i, 4267ec681f3Smrg &dst_shadow_surf, dst_level, dst_base_layer + i, 4277ec681f3Smrg srcOffset.x, srcOffset.y, 4287ec681f3Smrg dstOffset.x, dstOffset.y, 4297ec681f3Smrg extent.width, extent.height); 4307ec681f3Smrg } 43101e04c3fSmrg } 43201e04c3fSmrg } 4337ec681f3Smrg} 43401e04c3fSmrg 4357ec681f3Smrgvoid anv_CmdCopyImage2KHR( 4367ec681f3Smrg VkCommandBuffer commandBuffer, 4377ec681f3Smrg const VkCopyImageInfo2KHR* pCopyImageInfo) 4387ec681f3Smrg{ 4397ec681f3Smrg ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 4407ec681f3Smrg ANV_FROM_HANDLE(anv_image, src_image, pCopyImageInfo->srcImage); 4417ec681f3Smrg ANV_FROM_HANDLE(anv_image, dst_image, pCopyImageInfo->dstImage); 4427ec681f3Smrg 4437ec681f3Smrg struct blorp_batch batch; 4447ec681f3Smrg anv_blorp_batch_init(cmd_buffer, &batch, 0); 4457ec681f3Smrg 4467ec681f3Smrg for (unsigned r = 0; r < pCopyImageInfo->regionCount; r++) { 4477ec681f3Smrg copy_image(cmd_buffer, &batch, 4487ec681f3Smrg src_image, pCopyImageInfo->srcImageLayout, 4497ec681f3Smrg dst_image, pCopyImageInfo->dstImageLayout, 4507ec681f3Smrg &pCopyImageInfo->pRegions[r]); 4517ec681f3Smrg } 4527ec681f3Smrg 4537ec681f3Smrg anv_blorp_batch_finish(&batch); 4547ec681f3Smrg} 4557ec681f3Smrg 4567ec681f3Smrgstatic enum isl_format 4577ec681f3Smrgisl_format_for_size(unsigned size_B) 4587ec681f3Smrg{ 4597ec681f3Smrg /* Prefer 32-bit per component formats for CmdFillBuffer */ 4607ec681f3Smrg switch (size_B) { 4617ec681f3Smrg case 1: return ISL_FORMAT_R8_UINT; 4627ec681f3Smrg case 2: return ISL_FORMAT_R16_UINT; 4637ec681f3Smrg case 3: return ISL_FORMAT_R8G8B8_UINT; 4647ec681f3Smrg case 4: return ISL_FORMAT_R32_UINT; 4657ec681f3Smrg case 6: return ISL_FORMAT_R16G16B16_UINT; 4667ec681f3Smrg case 8: return ISL_FORMAT_R32G32_UINT; 4677ec681f3Smrg case 12: return ISL_FORMAT_R32G32B32_UINT; 4687ec681f3Smrg case 16: return ISL_FORMAT_R32G32B32A32_UINT; 4697ec681f3Smrg default: 4707ec681f3Smrg unreachable("Unknown format size"); 4717ec681f3Smrg } 47201e04c3fSmrg} 47301e04c3fSmrg 47401e04c3fSmrgstatic void 47501e04c3fSmrgcopy_buffer_to_image(struct anv_cmd_buffer *cmd_buffer, 4767ec681f3Smrg struct blorp_batch *batch, 47701e04c3fSmrg struct anv_buffer *anv_buffer, 47801e04c3fSmrg struct anv_image *anv_image, 47901e04c3fSmrg VkImageLayout image_layout, 4807ec681f3Smrg const VkBufferImageCopy2KHR* region, 48101e04c3fSmrg bool buffer_to_image) 48201e04c3fSmrg{ 48301e04c3fSmrg struct { 48401e04c3fSmrg struct blorp_surf surf; 48501e04c3fSmrg uint32_t level; 48601e04c3fSmrg VkOffset3D offset; 48701e04c3fSmrg } image, buffer, *src, *dst; 48801e04c3fSmrg 48901e04c3fSmrg buffer.level = 0; 49001e04c3fSmrg buffer.offset = (VkOffset3D) { 0, 0, 0 }; 49101e04c3fSmrg 49201e04c3fSmrg if (buffer_to_image) { 49301e04c3fSmrg src = &buffer; 49401e04c3fSmrg dst = ℑ 49501e04c3fSmrg } else { 49601e04c3fSmrg src = ℑ 49701e04c3fSmrg dst = &buffer; 49801e04c3fSmrg } 49901e04c3fSmrg 5007ec681f3Smrg const VkImageAspectFlags aspect = region->imageSubresource.aspectMask; 5017ec681f3Smrg 5027ec681f3Smrg get_blorp_surf_for_anv_image(cmd_buffer->device, anv_image, aspect, 5037ec681f3Smrg buffer_to_image ? 5047ec681f3Smrg VK_IMAGE_USAGE_TRANSFER_DST_BIT : 5057ec681f3Smrg VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 5067ec681f3Smrg image_layout, ISL_AUX_USAGE_NONE, 5077ec681f3Smrg &image.surf); 5087ec681f3Smrg image.offset = 5097ec681f3Smrg anv_sanitize_image_offset(anv_image->vk.image_type, region->imageOffset); 5107ec681f3Smrg image.level = region->imageSubresource.mipLevel; 5117ec681f3Smrg 5127ec681f3Smrg VkExtent3D extent = 5137ec681f3Smrg anv_sanitize_image_extent(anv_image->vk.image_type, region->imageExtent); 5147ec681f3Smrg if (anv_image->vk.image_type != VK_IMAGE_TYPE_3D) { 5157ec681f3Smrg image.offset.z = region->imageSubresource.baseArrayLayer; 5167ec681f3Smrg extent.depth = 5177ec681f3Smrg vk_image_subresource_layer_count(&anv_image->vk, 5187ec681f3Smrg ®ion->imageSubresource); 5197ec681f3Smrg } 52001e04c3fSmrg 5217ec681f3Smrg const enum isl_format linear_format = 5227ec681f3Smrg anv_get_isl_format(&cmd_buffer->device->info, anv_image->vk.format, 5237ec681f3Smrg aspect, VK_IMAGE_TILING_LINEAR); 5247ec681f3Smrg const struct isl_format_layout *linear_fmtl = 5257ec681f3Smrg isl_format_get_layout(linear_format); 52601e04c3fSmrg 5277ec681f3Smrg const uint32_t buffer_row_length = 5287ec681f3Smrg region->bufferRowLength ? 5297ec681f3Smrg region->bufferRowLength : extent.width; 53001e04c3fSmrg 5317ec681f3Smrg const uint32_t buffer_image_height = 5327ec681f3Smrg region->bufferImageHeight ? 5337ec681f3Smrg region->bufferImageHeight : extent.height; 53401e04c3fSmrg 5357ec681f3Smrg const uint32_t buffer_row_pitch = 5367ec681f3Smrg DIV_ROUND_UP(buffer_row_length, linear_fmtl->bw) * 5377ec681f3Smrg (linear_fmtl->bpb / 8); 53801e04c3fSmrg 5397ec681f3Smrg const uint32_t buffer_layer_stride = 5407ec681f3Smrg DIV_ROUND_UP(buffer_image_height, linear_fmtl->bh) * 5417ec681f3Smrg buffer_row_pitch; 54201e04c3fSmrg 5437ec681f3Smrg /* Some formats have additional restrictions which may cause ISL to 5447ec681f3Smrg * fail to create a surface for us. Some examples include: 5457ec681f3Smrg * 5467ec681f3Smrg * 1. ASTC formats are not allowed to be LINEAR and must be tiled 5477ec681f3Smrg * 2. YCbCr formats have to have 2-pixel aligned strides 5487ec681f3Smrg * 5497ec681f3Smrg * To avoid these issues, we always bind the buffer as if it's a 5507ec681f3Smrg * "normal" format like RGBA32_UINT. Since we're using blorp_copy, 5517ec681f3Smrg * the format doesn't matter as long as it has the right bpb. 5527ec681f3Smrg */ 5537ec681f3Smrg const VkExtent2D buffer_extent = { 5547ec681f3Smrg .width = DIV_ROUND_UP(extent.width, linear_fmtl->bw), 5557ec681f3Smrg .height = DIV_ROUND_UP(extent.height, linear_fmtl->bh), 5567ec681f3Smrg }; 5577ec681f3Smrg const enum isl_format buffer_format = 5587ec681f3Smrg isl_format_for_size(linear_fmtl->bpb / 8); 5597ec681f3Smrg 5607ec681f3Smrg struct isl_surf buffer_isl_surf; 5617ec681f3Smrg get_blorp_surf_for_anv_buffer(cmd_buffer->device, 5627ec681f3Smrg anv_buffer, region->bufferOffset, 5637ec681f3Smrg buffer_extent.width, buffer_extent.height, 5647ec681f3Smrg buffer_row_pitch, buffer_format, false, 5657ec681f3Smrg &buffer.surf, &buffer_isl_surf); 5667ec681f3Smrg 5677ec681f3Smrg bool dst_has_shadow = false; 5687ec681f3Smrg struct blorp_surf dst_shadow_surf; 5697ec681f3Smrg if (&image == dst) { 5707ec681f3Smrg /* In this case, the source is the buffer and, since blorp takes its 5717ec681f3Smrg * copy dimensions in terms of the source format, we have to use the 5727ec681f3Smrg * scaled down version for compressed textures because the source 5737ec681f3Smrg * format is an RGB format. 5747ec681f3Smrg */ 5757ec681f3Smrg extent.width = buffer_extent.width; 5767ec681f3Smrg extent.height = buffer_extent.height; 5777ec681f3Smrg 5787ec681f3Smrg anv_cmd_buffer_mark_image_written(cmd_buffer, anv_image, 5797ec681f3Smrg aspect, dst->surf.aux_usage, 5807ec681f3Smrg dst->level, 5817ec681f3Smrg dst->offset.z, extent.depth); 5827ec681f3Smrg 5837ec681f3Smrg dst_has_shadow = 5847ec681f3Smrg get_blorp_surf_for_anv_shadow_image(cmd_buffer->device, 5857ec681f3Smrg anv_image, aspect, 5867ec681f3Smrg &dst_shadow_surf); 5877ec681f3Smrg } 58801e04c3fSmrg 5897ec681f3Smrg for (unsigned z = 0; z < extent.depth; z++) { 5907ec681f3Smrg blorp_copy(batch, &src->surf, src->level, src->offset.z, 5917ec681f3Smrg &dst->surf, dst->level, dst->offset.z, 5927ec681f3Smrg src->offset.x, src->offset.y, dst->offset.x, dst->offset.y, 5937ec681f3Smrg extent.width, extent.height); 5947ec681f3Smrg 5957ec681f3Smrg if (dst_has_shadow) { 5967ec681f3Smrg blorp_copy(batch, &src->surf, src->level, src->offset.z, 5977ec681f3Smrg &dst_shadow_surf, dst->level, dst->offset.z, 5987ec681f3Smrg src->offset.x, src->offset.y, 5997ec681f3Smrg dst->offset.x, dst->offset.y, 60001e04c3fSmrg extent.width, extent.height); 60101e04c3fSmrg } 60201e04c3fSmrg 6037ec681f3Smrg image.offset.z++; 6047ec681f3Smrg buffer.surf.addr.offset += buffer_layer_stride; 6057ec681f3Smrg } 60601e04c3fSmrg} 60701e04c3fSmrg 6087ec681f3Smrgvoid anv_CmdCopyBufferToImage2KHR( 60901e04c3fSmrg VkCommandBuffer commandBuffer, 6107ec681f3Smrg const VkCopyBufferToImageInfo2KHR* pCopyBufferToImageInfo) 61101e04c3fSmrg{ 61201e04c3fSmrg ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 6137ec681f3Smrg ANV_FROM_HANDLE(anv_buffer, src_buffer, pCopyBufferToImageInfo->srcBuffer); 6147ec681f3Smrg ANV_FROM_HANDLE(anv_image, dst_image, pCopyBufferToImageInfo->dstImage); 61501e04c3fSmrg 6167ec681f3Smrg struct blorp_batch batch; 6177ec681f3Smrg anv_blorp_batch_init(cmd_buffer, &batch, 0); 6187ec681f3Smrg 6197ec681f3Smrg for (unsigned r = 0; r < pCopyBufferToImageInfo->regionCount; r++) { 6207ec681f3Smrg copy_buffer_to_image(cmd_buffer, &batch, src_buffer, dst_image, 6217ec681f3Smrg pCopyBufferToImageInfo->dstImageLayout, 6227ec681f3Smrg &pCopyBufferToImageInfo->pRegions[r], true); 6237ec681f3Smrg } 6247ec681f3Smrg 6257ec681f3Smrg anv_blorp_batch_finish(&batch); 62601e04c3fSmrg} 62701e04c3fSmrg 6287ec681f3Smrgvoid anv_CmdCopyImageToBuffer2KHR( 62901e04c3fSmrg VkCommandBuffer commandBuffer, 6307ec681f3Smrg const VkCopyImageToBufferInfo2KHR* pCopyImageToBufferInfo) 63101e04c3fSmrg{ 63201e04c3fSmrg ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 6337ec681f3Smrg ANV_FROM_HANDLE(anv_image, src_image, pCopyImageToBufferInfo->srcImage); 6347ec681f3Smrg ANV_FROM_HANDLE(anv_buffer, dst_buffer, pCopyImageToBufferInfo->dstBuffer); 6357ec681f3Smrg 6367ec681f3Smrg struct blorp_batch batch; 6377ec681f3Smrg anv_blorp_batch_init(cmd_buffer, &batch, 0); 6387ec681f3Smrg 6397ec681f3Smrg for (unsigned r = 0; r < pCopyImageToBufferInfo->regionCount; r++) { 6407ec681f3Smrg copy_buffer_to_image(cmd_buffer, &batch, dst_buffer, src_image, 6417ec681f3Smrg pCopyImageToBufferInfo->srcImageLayout, 6427ec681f3Smrg &pCopyImageToBufferInfo->pRegions[r], false); 6437ec681f3Smrg } 64401e04c3fSmrg 6457ec681f3Smrg anv_blorp_batch_finish(&batch); 6469f464c52Smaya 6479f464c52Smaya cmd_buffer->state.pending_pipe_bits |= ANV_PIPE_RENDER_TARGET_BUFFER_WRITES; 64801e04c3fSmrg} 64901e04c3fSmrg 65001e04c3fSmrgstatic bool 65101e04c3fSmrgflip_coords(unsigned *src0, unsigned *src1, unsigned *dst0, unsigned *dst1) 65201e04c3fSmrg{ 65301e04c3fSmrg bool flip = false; 65401e04c3fSmrg if (*src0 > *src1) { 65501e04c3fSmrg unsigned tmp = *src0; 65601e04c3fSmrg *src0 = *src1; 65701e04c3fSmrg *src1 = tmp; 65801e04c3fSmrg flip = !flip; 65901e04c3fSmrg } 66001e04c3fSmrg 66101e04c3fSmrg if (*dst0 > *dst1) { 66201e04c3fSmrg unsigned tmp = *dst0; 66301e04c3fSmrg *dst0 = *dst1; 66401e04c3fSmrg *dst1 = tmp; 66501e04c3fSmrg flip = !flip; 66601e04c3fSmrg } 66701e04c3fSmrg 66801e04c3fSmrg return flip; 66901e04c3fSmrg} 67001e04c3fSmrg 6717ec681f3Smrgstatic void 6727ec681f3Smrgblit_image(struct anv_cmd_buffer *cmd_buffer, 6737ec681f3Smrg struct blorp_batch *batch, 6747ec681f3Smrg struct anv_image *src_image, 6757ec681f3Smrg VkImageLayout src_image_layout, 6767ec681f3Smrg struct anv_image *dst_image, 6777ec681f3Smrg VkImageLayout dst_image_layout, 6787ec681f3Smrg const VkImageBlit2KHR *region, 6797ec681f3Smrg VkFilter filter) 68001e04c3fSmrg{ 6817ec681f3Smrg const VkImageSubresourceLayers *src_res = ®ion->srcSubresource; 6827ec681f3Smrg const VkImageSubresourceLayers *dst_res = ®ion->dstSubresource; 68301e04c3fSmrg 68401e04c3fSmrg struct blorp_surf src, dst; 68501e04c3fSmrg 68601e04c3fSmrg enum blorp_filter blorp_filter; 68701e04c3fSmrg switch (filter) { 68801e04c3fSmrg case VK_FILTER_NEAREST: 68901e04c3fSmrg blorp_filter = BLORP_FILTER_NEAREST; 69001e04c3fSmrg break; 69101e04c3fSmrg case VK_FILTER_LINEAR: 69201e04c3fSmrg blorp_filter = BLORP_FILTER_BILINEAR; 69301e04c3fSmrg break; 69401e04c3fSmrg default: 69501e04c3fSmrg unreachable("Invalid filter"); 69601e04c3fSmrg } 69701e04c3fSmrg 6987ec681f3Smrg assert(anv_image_aspects_compatible(src_res->aspectMask, 6997ec681f3Smrg dst_res->aspectMask)); 70001e04c3fSmrg 7017ec681f3Smrg anv_foreach_image_aspect_bit(aspect_bit, src_image, src_res->aspectMask) { 7027ec681f3Smrg get_blorp_surf_for_anv_image(cmd_buffer->device, 7037ec681f3Smrg src_image, 1U << aspect_bit, 7047ec681f3Smrg VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 7057ec681f3Smrg src_image_layout, ISL_AUX_USAGE_NONE, &src); 7067ec681f3Smrg get_blorp_surf_for_anv_image(cmd_buffer->device, 7077ec681f3Smrg dst_image, 1U << aspect_bit, 7087ec681f3Smrg VK_IMAGE_USAGE_TRANSFER_DST_BIT, 7097ec681f3Smrg dst_image_layout, ISL_AUX_USAGE_NONE, &dst); 71001e04c3fSmrg 7117ec681f3Smrg struct anv_format_plane src_format = 7127ec681f3Smrg anv_get_format_aspect(&cmd_buffer->device->info, src_image->vk.format, 7137ec681f3Smrg 1U << aspect_bit, src_image->vk.tiling); 7147ec681f3Smrg struct anv_format_plane dst_format = 7157ec681f3Smrg anv_get_format_aspect(&cmd_buffer->device->info, dst_image->vk.format, 7167ec681f3Smrg 1U << aspect_bit, dst_image->vk.tiling); 7177ec681f3Smrg 7187ec681f3Smrg unsigned dst_start, dst_end; 7197ec681f3Smrg if (dst_image->vk.image_type == VK_IMAGE_TYPE_3D) { 7207ec681f3Smrg assert(dst_res->baseArrayLayer == 0); 7217ec681f3Smrg dst_start = region->dstOffsets[0].z; 7227ec681f3Smrg dst_end = region->dstOffsets[1].z; 7237ec681f3Smrg } else { 7247ec681f3Smrg dst_start = dst_res->baseArrayLayer; 7257ec681f3Smrg dst_end = dst_start + 7267ec681f3Smrg vk_image_subresource_layer_count(&dst_image->vk, dst_res); 7277ec681f3Smrg } 72801e04c3fSmrg 7297ec681f3Smrg unsigned src_start, src_end; 7307ec681f3Smrg if (src_image->vk.image_type == VK_IMAGE_TYPE_3D) { 7317ec681f3Smrg assert(src_res->baseArrayLayer == 0); 7327ec681f3Smrg src_start = region->srcOffsets[0].z; 7337ec681f3Smrg src_end = region->srcOffsets[1].z; 7347ec681f3Smrg } else { 7357ec681f3Smrg src_start = src_res->baseArrayLayer; 7367ec681f3Smrg src_end = src_start + 7377ec681f3Smrg vk_image_subresource_layer_count(&src_image->vk, src_res); 7387ec681f3Smrg } 73901e04c3fSmrg 7407ec681f3Smrg bool flip_z = flip_coords(&src_start, &src_end, &dst_start, &dst_end); 7417ec681f3Smrg const unsigned num_layers = dst_end - dst_start; 7427ec681f3Smrg float src_z_step = (float)(src_end - src_start) / (float)num_layers; 74301e04c3fSmrg 7447ec681f3Smrg /* There is no interpolation to the pixel center during rendering, so 7457ec681f3Smrg * add the 0.5 offset ourselves here. */ 7467ec681f3Smrg float depth_center_offset = 0; 7477ec681f3Smrg if (src_image->vk.image_type == VK_IMAGE_TYPE_3D) 7487ec681f3Smrg depth_center_offset = 0.5 / num_layers * (src_end - src_start); 74901e04c3fSmrg 7507ec681f3Smrg if (flip_z) { 7517ec681f3Smrg src_start = src_end; 7527ec681f3Smrg src_z_step *= -1; 7537ec681f3Smrg depth_center_offset *= -1; 7547ec681f3Smrg } 75501e04c3fSmrg 7567ec681f3Smrg unsigned src_x0 = region->srcOffsets[0].x; 7577ec681f3Smrg unsigned src_x1 = region->srcOffsets[1].x; 7587ec681f3Smrg unsigned dst_x0 = region->dstOffsets[0].x; 7597ec681f3Smrg unsigned dst_x1 = region->dstOffsets[1].x; 7607ec681f3Smrg bool flip_x = flip_coords(&src_x0, &src_x1, &dst_x0, &dst_x1); 7617ec681f3Smrg 7627ec681f3Smrg unsigned src_y0 = region->srcOffsets[0].y; 7637ec681f3Smrg unsigned src_y1 = region->srcOffsets[1].y; 7647ec681f3Smrg unsigned dst_y0 = region->dstOffsets[0].y; 7657ec681f3Smrg unsigned dst_y1 = region->dstOffsets[1].y; 7667ec681f3Smrg bool flip_y = flip_coords(&src_y0, &src_y1, &dst_y0, &dst_y1); 7677ec681f3Smrg 7687ec681f3Smrg anv_cmd_buffer_mark_image_written(cmd_buffer, dst_image, 7697ec681f3Smrg 1U << aspect_bit, 7707ec681f3Smrg dst.aux_usage, 7717ec681f3Smrg dst_res->mipLevel, 7727ec681f3Smrg dst_start, num_layers); 7737ec681f3Smrg 7747ec681f3Smrg for (unsigned i = 0; i < num_layers; i++) { 7757ec681f3Smrg unsigned dst_z = dst_start + i; 7767ec681f3Smrg float src_z = src_start + i * src_z_step + depth_center_offset; 7777ec681f3Smrg 7787ec681f3Smrg blorp_blit(batch, &src, src_res->mipLevel, src_z, 7797ec681f3Smrg src_format.isl_format, src_format.swizzle, 7807ec681f3Smrg &dst, dst_res->mipLevel, dst_z, 7817ec681f3Smrg dst_format.isl_format, dst_format.swizzle, 7827ec681f3Smrg src_x0, src_y0, src_x1, src_y1, 7837ec681f3Smrg dst_x0, dst_y0, dst_x1, dst_y1, 7847ec681f3Smrg blorp_filter, flip_x, flip_y); 78501e04c3fSmrg } 78601e04c3fSmrg } 78701e04c3fSmrg} 78801e04c3fSmrg 7897ec681f3Smrgvoid anv_CmdBlitImage2KHR( 7907ec681f3Smrg VkCommandBuffer commandBuffer, 7917ec681f3Smrg const VkBlitImageInfo2KHR* pBlitImageInfo) 79201e04c3fSmrg{ 7937ec681f3Smrg ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 7947ec681f3Smrg ANV_FROM_HANDLE(anv_image, src_image, pBlitImageInfo->srcImage); 7957ec681f3Smrg ANV_FROM_HANDLE(anv_image, dst_image, pBlitImageInfo->dstImage); 7967ec681f3Smrg 7977ec681f3Smrg struct blorp_batch batch; 7987ec681f3Smrg anv_blorp_batch_init(cmd_buffer, &batch, 0); 7997ec681f3Smrg 8007ec681f3Smrg for (unsigned r = 0; r < pBlitImageInfo->regionCount; r++) { 8017ec681f3Smrg blit_image(cmd_buffer, &batch, 8027ec681f3Smrg src_image, pBlitImageInfo->srcImageLayout, 8037ec681f3Smrg dst_image, pBlitImageInfo->dstImageLayout, 8047ec681f3Smrg &pBlitImageInfo->pRegions[r], pBlitImageInfo->filter); 80501e04c3fSmrg } 8067ec681f3Smrg 8077ec681f3Smrg anv_blorp_batch_finish(&batch); 80801e04c3fSmrg} 80901e04c3fSmrg 81001e04c3fSmrg/** 81101e04c3fSmrg * Returns the greatest common divisor of a and b that is a power of two. 81201e04c3fSmrg */ 81301e04c3fSmrgstatic uint64_t 81401e04c3fSmrggcd_pow2_u64(uint64_t a, uint64_t b) 81501e04c3fSmrg{ 81601e04c3fSmrg assert(a > 0 || b > 0); 81701e04c3fSmrg 81801e04c3fSmrg unsigned a_log2 = ffsll(a) - 1; 81901e04c3fSmrg unsigned b_log2 = ffsll(b) - 1; 82001e04c3fSmrg 82101e04c3fSmrg /* If either a or b is 0, then a_log2 or b_log2 till be UINT_MAX in which 82201e04c3fSmrg * case, the MIN2() will take the other one. If both are 0 then we will 82301e04c3fSmrg * hit the assert above. 82401e04c3fSmrg */ 82501e04c3fSmrg return 1 << MIN2(a_log2, b_log2); 82601e04c3fSmrg} 82701e04c3fSmrg 82801e04c3fSmrg/* This is maximum possible width/height our HW can handle */ 82901e04c3fSmrg#define MAX_SURFACE_DIM (1ull << 14) 83001e04c3fSmrg 8317ec681f3Smrgstatic void 8327ec681f3Smrgcopy_buffer(struct anv_device *device, 8337ec681f3Smrg struct blorp_batch *batch, 8347ec681f3Smrg struct anv_buffer *src_buffer, 8357ec681f3Smrg struct anv_buffer *dst_buffer, 8367ec681f3Smrg const VkBufferCopy2KHR *region) 8377ec681f3Smrg{ 8387ec681f3Smrg struct blorp_address src = { 8397ec681f3Smrg .buffer = src_buffer->address.bo, 8407ec681f3Smrg .offset = src_buffer->address.offset + region->srcOffset, 8417ec681f3Smrg .mocs = anv_mocs(device, src_buffer->address.bo, 8427ec681f3Smrg ISL_SURF_USAGE_TEXTURE_BIT), 8437ec681f3Smrg }; 8447ec681f3Smrg struct blorp_address dst = { 8457ec681f3Smrg .buffer = dst_buffer->address.bo, 8467ec681f3Smrg .offset = dst_buffer->address.offset + region->dstOffset, 8477ec681f3Smrg .mocs = anv_mocs(device, dst_buffer->address.bo, 8487ec681f3Smrg ISL_SURF_USAGE_RENDER_TARGET_BIT), 8497ec681f3Smrg }; 8507ec681f3Smrg 8517ec681f3Smrg blorp_buffer_copy(batch, src, dst, region->size); 8527ec681f3Smrg} 8537ec681f3Smrg 8547ec681f3Smrgvoid anv_CmdCopyBuffer2KHR( 85501e04c3fSmrg VkCommandBuffer commandBuffer, 8567ec681f3Smrg const VkCopyBufferInfo2KHR* pCopyBufferInfo) 85701e04c3fSmrg{ 85801e04c3fSmrg ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 8597ec681f3Smrg ANV_FROM_HANDLE(anv_buffer, src_buffer, pCopyBufferInfo->srcBuffer); 8607ec681f3Smrg ANV_FROM_HANDLE(anv_buffer, dst_buffer, pCopyBufferInfo->dstBuffer); 86101e04c3fSmrg 86201e04c3fSmrg struct blorp_batch batch; 8637ec681f3Smrg anv_blorp_batch_init(cmd_buffer, &batch, 0); 86401e04c3fSmrg 8657ec681f3Smrg for (unsigned r = 0; r < pCopyBufferInfo->regionCount; r++) { 8667ec681f3Smrg copy_buffer(cmd_buffer->device, &batch, src_buffer, dst_buffer, 8677ec681f3Smrg &pCopyBufferInfo->pRegions[r]); 86801e04c3fSmrg } 86901e04c3fSmrg 8707ec681f3Smrg anv_blorp_batch_finish(&batch); 8719f464c52Smaya 8729f464c52Smaya cmd_buffer->state.pending_pipe_bits |= ANV_PIPE_RENDER_TARGET_BUFFER_WRITES; 87301e04c3fSmrg} 87401e04c3fSmrg 8757ec681f3Smrg 87601e04c3fSmrgvoid anv_CmdUpdateBuffer( 87701e04c3fSmrg VkCommandBuffer commandBuffer, 87801e04c3fSmrg VkBuffer dstBuffer, 87901e04c3fSmrg VkDeviceSize dstOffset, 88001e04c3fSmrg VkDeviceSize dataSize, 88101e04c3fSmrg const void* pData) 88201e04c3fSmrg{ 88301e04c3fSmrg ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 88401e04c3fSmrg ANV_FROM_HANDLE(anv_buffer, dst_buffer, dstBuffer); 88501e04c3fSmrg 88601e04c3fSmrg struct blorp_batch batch; 8877ec681f3Smrg anv_blorp_batch_init(cmd_buffer, &batch, 0); 88801e04c3fSmrg 88901e04c3fSmrg /* We can't quite grab a full block because the state stream needs a 89001e04c3fSmrg * little data at the top to build its linked list. 89101e04c3fSmrg */ 89201e04c3fSmrg const uint32_t max_update_size = 89301e04c3fSmrg cmd_buffer->device->dynamic_state_pool.block_size - 64; 89401e04c3fSmrg 89501e04c3fSmrg assert(max_update_size < MAX_SURFACE_DIM * 4); 89601e04c3fSmrg 89701e04c3fSmrg /* We're about to read data that was written from the CPU. Flush the 89801e04c3fSmrg * texture cache so we don't get anything stale. 89901e04c3fSmrg */ 9007ec681f3Smrg anv_add_pending_pipe_bits(cmd_buffer, 9017ec681f3Smrg ANV_PIPE_TEXTURE_CACHE_INVALIDATE_BIT, 9027ec681f3Smrg "before UpdateBuffer"); 90301e04c3fSmrg 90401e04c3fSmrg while (dataSize) { 90501e04c3fSmrg const uint32_t copy_size = MIN2(dataSize, max_update_size); 90601e04c3fSmrg 90701e04c3fSmrg struct anv_state tmp_data = 90801e04c3fSmrg anv_cmd_buffer_alloc_dynamic_state(cmd_buffer, copy_size, 64); 90901e04c3fSmrg 91001e04c3fSmrg memcpy(tmp_data.map, pData, copy_size); 91101e04c3fSmrg 91201e04c3fSmrg struct blorp_address src = { 9139f464c52Smaya .buffer = cmd_buffer->device->dynamic_state_pool.block_pool.bo, 91401e04c3fSmrg .offset = tmp_data.offset, 9157ec681f3Smrg .mocs = isl_mocs(&cmd_buffer->device->isl_dev, 9167ec681f3Smrg ISL_SURF_USAGE_TEXTURE_BIT, false) 91701e04c3fSmrg }; 91801e04c3fSmrg struct blorp_address dst = { 91901e04c3fSmrg .buffer = dst_buffer->address.bo, 92001e04c3fSmrg .offset = dst_buffer->address.offset + dstOffset, 9217ec681f3Smrg .mocs = anv_mocs(cmd_buffer->device, dst_buffer->address.bo, 9227ec681f3Smrg ISL_SURF_USAGE_RENDER_TARGET_BIT), 92301e04c3fSmrg }; 92401e04c3fSmrg 92501e04c3fSmrg blorp_buffer_copy(&batch, src, dst, copy_size); 92601e04c3fSmrg 92701e04c3fSmrg dataSize -= copy_size; 92801e04c3fSmrg dstOffset += copy_size; 92901e04c3fSmrg pData = (void *)pData + copy_size; 93001e04c3fSmrg } 93101e04c3fSmrg 9327ec681f3Smrg anv_blorp_batch_finish(&batch); 9339f464c52Smaya 9349f464c52Smaya cmd_buffer->state.pending_pipe_bits |= ANV_PIPE_RENDER_TARGET_BUFFER_WRITES; 93501e04c3fSmrg} 93601e04c3fSmrg 93701e04c3fSmrgvoid anv_CmdFillBuffer( 93801e04c3fSmrg VkCommandBuffer commandBuffer, 93901e04c3fSmrg VkBuffer dstBuffer, 94001e04c3fSmrg VkDeviceSize dstOffset, 94101e04c3fSmrg VkDeviceSize fillSize, 94201e04c3fSmrg uint32_t data) 94301e04c3fSmrg{ 94401e04c3fSmrg ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 94501e04c3fSmrg ANV_FROM_HANDLE(anv_buffer, dst_buffer, dstBuffer); 94601e04c3fSmrg struct blorp_surf surf; 94701e04c3fSmrg struct isl_surf isl_surf; 94801e04c3fSmrg 94901e04c3fSmrg struct blorp_batch batch; 9507ec681f3Smrg anv_blorp_batch_init(cmd_buffer, &batch, 0); 95101e04c3fSmrg 95201e04c3fSmrg fillSize = anv_buffer_get_range(dst_buffer, dstOffset, fillSize); 95301e04c3fSmrg 95401e04c3fSmrg /* From the Vulkan spec: 95501e04c3fSmrg * 95601e04c3fSmrg * "size is the number of bytes to fill, and must be either a multiple 95701e04c3fSmrg * of 4, or VK_WHOLE_SIZE to fill the range from offset to the end of 95801e04c3fSmrg * the buffer. If VK_WHOLE_SIZE is used and the remaining size of the 95901e04c3fSmrg * buffer is not a multiple of 4, then the nearest smaller multiple is 96001e04c3fSmrg * used." 96101e04c3fSmrg */ 96201e04c3fSmrg fillSize &= ~3ull; 96301e04c3fSmrg 96401e04c3fSmrg /* First, we compute the biggest format that can be used with the 96501e04c3fSmrg * given offsets and size. 96601e04c3fSmrg */ 96701e04c3fSmrg int bs = 16; 96801e04c3fSmrg bs = gcd_pow2_u64(bs, dstOffset); 96901e04c3fSmrg bs = gcd_pow2_u64(bs, fillSize); 97001e04c3fSmrg enum isl_format isl_format = isl_format_for_size(bs); 97101e04c3fSmrg 97201e04c3fSmrg union isl_color_value color = { 97301e04c3fSmrg .u32 = { data, data, data, data }, 97401e04c3fSmrg }; 97501e04c3fSmrg 97601e04c3fSmrg const uint64_t max_fill_size = MAX_SURFACE_DIM * MAX_SURFACE_DIM * bs; 97701e04c3fSmrg while (fillSize >= max_fill_size) { 97801e04c3fSmrg get_blorp_surf_for_anv_buffer(cmd_buffer->device, 97901e04c3fSmrg dst_buffer, dstOffset, 98001e04c3fSmrg MAX_SURFACE_DIM, MAX_SURFACE_DIM, 9817ec681f3Smrg MAX_SURFACE_DIM * bs, isl_format, true, 98201e04c3fSmrg &surf, &isl_surf); 98301e04c3fSmrg 98401e04c3fSmrg blorp_clear(&batch, &surf, isl_format, ISL_SWIZZLE_IDENTITY, 98501e04c3fSmrg 0, 0, 1, 0, 0, MAX_SURFACE_DIM, MAX_SURFACE_DIM, 9867ec681f3Smrg color, 0 /* color_write_disable */); 98701e04c3fSmrg fillSize -= max_fill_size; 98801e04c3fSmrg dstOffset += max_fill_size; 98901e04c3fSmrg } 99001e04c3fSmrg 99101e04c3fSmrg uint64_t height = fillSize / (MAX_SURFACE_DIM * bs); 99201e04c3fSmrg assert(height < MAX_SURFACE_DIM); 99301e04c3fSmrg if (height != 0) { 99401e04c3fSmrg const uint64_t rect_fill_size = height * MAX_SURFACE_DIM * bs; 99501e04c3fSmrg get_blorp_surf_for_anv_buffer(cmd_buffer->device, 99601e04c3fSmrg dst_buffer, dstOffset, 99701e04c3fSmrg MAX_SURFACE_DIM, height, 9987ec681f3Smrg MAX_SURFACE_DIM * bs, isl_format, true, 99901e04c3fSmrg &surf, &isl_surf); 100001e04c3fSmrg 100101e04c3fSmrg blorp_clear(&batch, &surf, isl_format, ISL_SWIZZLE_IDENTITY, 100201e04c3fSmrg 0, 0, 1, 0, 0, MAX_SURFACE_DIM, height, 10037ec681f3Smrg color, 0 /* color_write_disable */); 100401e04c3fSmrg fillSize -= rect_fill_size; 100501e04c3fSmrg dstOffset += rect_fill_size; 100601e04c3fSmrg } 100701e04c3fSmrg 100801e04c3fSmrg if (fillSize != 0) { 100901e04c3fSmrg const uint32_t width = fillSize / bs; 101001e04c3fSmrg get_blorp_surf_for_anv_buffer(cmd_buffer->device, 101101e04c3fSmrg dst_buffer, dstOffset, 101201e04c3fSmrg width, 1, 10137ec681f3Smrg width * bs, isl_format, true, 101401e04c3fSmrg &surf, &isl_surf); 101501e04c3fSmrg 101601e04c3fSmrg blorp_clear(&batch, &surf, isl_format, ISL_SWIZZLE_IDENTITY, 101701e04c3fSmrg 0, 0, 1, 0, 0, width, 1, 10187ec681f3Smrg color, 0 /* color_write_disable */); 101901e04c3fSmrg } 102001e04c3fSmrg 10217ec681f3Smrg anv_blorp_batch_finish(&batch); 10229f464c52Smaya 10239f464c52Smaya cmd_buffer->state.pending_pipe_bits |= ANV_PIPE_RENDER_TARGET_BUFFER_WRITES; 102401e04c3fSmrg} 102501e04c3fSmrg 102601e04c3fSmrgvoid anv_CmdClearColorImage( 102701e04c3fSmrg VkCommandBuffer commandBuffer, 102801e04c3fSmrg VkImage _image, 102901e04c3fSmrg VkImageLayout imageLayout, 103001e04c3fSmrg const VkClearColorValue* pColor, 103101e04c3fSmrg uint32_t rangeCount, 103201e04c3fSmrg const VkImageSubresourceRange* pRanges) 103301e04c3fSmrg{ 103401e04c3fSmrg ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 103501e04c3fSmrg ANV_FROM_HANDLE(anv_image, image, _image); 103601e04c3fSmrg 103701e04c3fSmrg struct blorp_batch batch; 10387ec681f3Smrg anv_blorp_batch_init(cmd_buffer, &batch, 0); 103901e04c3fSmrg 104001e04c3fSmrg for (unsigned r = 0; r < rangeCount; r++) { 104101e04c3fSmrg if (pRanges[r].aspectMask == 0) 104201e04c3fSmrg continue; 104301e04c3fSmrg 104401e04c3fSmrg assert(pRanges[r].aspectMask & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV); 104501e04c3fSmrg 104601e04c3fSmrg struct blorp_surf surf; 104701e04c3fSmrg get_blorp_surf_for_anv_image(cmd_buffer->device, 104801e04c3fSmrg image, pRanges[r].aspectMask, 10497ec681f3Smrg VK_IMAGE_USAGE_TRANSFER_DST_BIT, 105001e04c3fSmrg imageLayout, ISL_AUX_USAGE_NONE, &surf); 105101e04c3fSmrg 105201e04c3fSmrg struct anv_format_plane src_format = 10537ec681f3Smrg anv_get_format_aspect(&cmd_buffer->device->info, image->vk.format, 10547ec681f3Smrg VK_IMAGE_ASPECT_COLOR_BIT, image->vk.tiling); 105501e04c3fSmrg 105601e04c3fSmrg unsigned base_layer = pRanges[r].baseArrayLayer; 10577ec681f3Smrg uint32_t layer_count = 10587ec681f3Smrg vk_image_subresource_layer_count(&image->vk, &pRanges[r]); 10597ec681f3Smrg uint32_t level_count = 10607ec681f3Smrg vk_image_subresource_level_count(&image->vk, &pRanges[r]); 106101e04c3fSmrg 10627ec681f3Smrg for (uint32_t i = 0; i < level_count; i++) { 106301e04c3fSmrg const unsigned level = pRanges[r].baseMipLevel + i; 10647ec681f3Smrg const unsigned level_width = anv_minify(image->vk.extent.width, level); 10657ec681f3Smrg const unsigned level_height = anv_minify(image->vk.extent.height, level); 106601e04c3fSmrg 10677ec681f3Smrg if (image->vk.image_type == VK_IMAGE_TYPE_3D) { 106801e04c3fSmrg base_layer = 0; 10697ec681f3Smrg layer_count = anv_minify(image->vk.extent.depth, level); 107001e04c3fSmrg } 107101e04c3fSmrg 107201e04c3fSmrg anv_cmd_buffer_mark_image_written(cmd_buffer, image, 107301e04c3fSmrg pRanges[r].aspectMask, 107401e04c3fSmrg surf.aux_usage, level, 107501e04c3fSmrg base_layer, layer_count); 107601e04c3fSmrg 107701e04c3fSmrg blorp_clear(&batch, &surf, 107801e04c3fSmrg src_format.isl_format, src_format.swizzle, 107901e04c3fSmrg level, base_layer, layer_count, 108001e04c3fSmrg 0, 0, level_width, level_height, 10817ec681f3Smrg vk_to_isl_color(*pColor), 0 /* color_write_disable */); 108201e04c3fSmrg } 108301e04c3fSmrg } 108401e04c3fSmrg 10857ec681f3Smrg anv_blorp_batch_finish(&batch); 108601e04c3fSmrg} 108701e04c3fSmrg 108801e04c3fSmrgvoid anv_CmdClearDepthStencilImage( 108901e04c3fSmrg VkCommandBuffer commandBuffer, 109001e04c3fSmrg VkImage image_h, 109101e04c3fSmrg VkImageLayout imageLayout, 109201e04c3fSmrg const VkClearDepthStencilValue* pDepthStencil, 109301e04c3fSmrg uint32_t rangeCount, 109401e04c3fSmrg const VkImageSubresourceRange* pRanges) 109501e04c3fSmrg{ 109601e04c3fSmrg ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 109701e04c3fSmrg ANV_FROM_HANDLE(anv_image, image, image_h); 109801e04c3fSmrg 109901e04c3fSmrg struct blorp_batch batch; 11007ec681f3Smrg anv_blorp_batch_init(cmd_buffer, &batch, 0); 11017ec681f3Smrg assert((batch.flags & BLORP_BATCH_USE_COMPUTE) == 0); 110201e04c3fSmrg 11037ec681f3Smrg struct blorp_surf depth, stencil, stencil_shadow; 11047ec681f3Smrg if (image->vk.aspects & VK_IMAGE_ASPECT_DEPTH_BIT) { 110501e04c3fSmrg get_blorp_surf_for_anv_image(cmd_buffer->device, 110601e04c3fSmrg image, VK_IMAGE_ASPECT_DEPTH_BIT, 11077ec681f3Smrg VK_IMAGE_USAGE_TRANSFER_DST_BIT, 110801e04c3fSmrg imageLayout, ISL_AUX_USAGE_NONE, &depth); 110901e04c3fSmrg } else { 111001e04c3fSmrg memset(&depth, 0, sizeof(depth)); 111101e04c3fSmrg } 111201e04c3fSmrg 11137ec681f3Smrg bool has_stencil_shadow = false; 11147ec681f3Smrg if (image->vk.aspects & VK_IMAGE_ASPECT_STENCIL_BIT) { 111501e04c3fSmrg get_blorp_surf_for_anv_image(cmd_buffer->device, 111601e04c3fSmrg image, VK_IMAGE_ASPECT_STENCIL_BIT, 11177ec681f3Smrg VK_IMAGE_USAGE_TRANSFER_DST_BIT, 111801e04c3fSmrg imageLayout, ISL_AUX_USAGE_NONE, &stencil); 11197ec681f3Smrg 11207ec681f3Smrg has_stencil_shadow = 11217ec681f3Smrg get_blorp_surf_for_anv_shadow_image(cmd_buffer->device, image, 11227ec681f3Smrg VK_IMAGE_ASPECT_STENCIL_BIT, 11237ec681f3Smrg &stencil_shadow); 112401e04c3fSmrg } else { 112501e04c3fSmrg memset(&stencil, 0, sizeof(stencil)); 112601e04c3fSmrg } 112701e04c3fSmrg 112801e04c3fSmrg for (unsigned r = 0; r < rangeCount; r++) { 112901e04c3fSmrg if (pRanges[r].aspectMask == 0) 113001e04c3fSmrg continue; 113101e04c3fSmrg 113201e04c3fSmrg bool clear_depth = pRanges[r].aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT; 113301e04c3fSmrg bool clear_stencil = pRanges[r].aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT; 113401e04c3fSmrg 113501e04c3fSmrg unsigned base_layer = pRanges[r].baseArrayLayer; 11367ec681f3Smrg uint32_t layer_count = 11377ec681f3Smrg vk_image_subresource_layer_count(&image->vk, &pRanges[r]); 11387ec681f3Smrg uint32_t level_count = 11397ec681f3Smrg vk_image_subresource_level_count(&image->vk, &pRanges[r]); 114001e04c3fSmrg 11417ec681f3Smrg for (uint32_t i = 0; i < level_count; i++) { 114201e04c3fSmrg const unsigned level = pRanges[r].baseMipLevel + i; 11437ec681f3Smrg const unsigned level_width = anv_minify(image->vk.extent.width, level); 11447ec681f3Smrg const unsigned level_height = anv_minify(image->vk.extent.height, level); 114501e04c3fSmrg 11467ec681f3Smrg if (image->vk.image_type == VK_IMAGE_TYPE_3D) 11477ec681f3Smrg layer_count = anv_minify(image->vk.extent.depth, level); 114801e04c3fSmrg 114901e04c3fSmrg blorp_clear_depth_stencil(&batch, &depth, &stencil, 115001e04c3fSmrg level, base_layer, layer_count, 115101e04c3fSmrg 0, 0, level_width, level_height, 115201e04c3fSmrg clear_depth, pDepthStencil->depth, 115301e04c3fSmrg clear_stencil ? 0xff : 0, 115401e04c3fSmrg pDepthStencil->stencil); 11557ec681f3Smrg 11567ec681f3Smrg if (clear_stencil && has_stencil_shadow) { 11577ec681f3Smrg union isl_color_value stencil_color = { 11587ec681f3Smrg .u32 = { pDepthStencil->stencil, }, 11597ec681f3Smrg }; 11607ec681f3Smrg blorp_clear(&batch, &stencil_shadow, 11617ec681f3Smrg ISL_FORMAT_R8_UINT, ISL_SWIZZLE_IDENTITY, 11627ec681f3Smrg level, base_layer, layer_count, 11637ec681f3Smrg 0, 0, level_width, level_height, 11647ec681f3Smrg stencil_color, 0 /* color_write_disable */); 11657ec681f3Smrg } 116601e04c3fSmrg } 116701e04c3fSmrg } 116801e04c3fSmrg 11697ec681f3Smrg anv_blorp_batch_finish(&batch); 117001e04c3fSmrg} 117101e04c3fSmrg 117201e04c3fSmrgVkResult 117301e04c3fSmrganv_cmd_buffer_alloc_blorp_binding_table(struct anv_cmd_buffer *cmd_buffer, 117401e04c3fSmrg uint32_t num_entries, 117501e04c3fSmrg uint32_t *state_offset, 117601e04c3fSmrg struct anv_state *bt_state) 117701e04c3fSmrg{ 117801e04c3fSmrg *bt_state = anv_cmd_buffer_alloc_binding_table(cmd_buffer, num_entries, 117901e04c3fSmrg state_offset); 118001e04c3fSmrg if (bt_state->map == NULL) { 118101e04c3fSmrg /* We ran out of space. Grab a new binding table block. */ 118201e04c3fSmrg VkResult result = anv_cmd_buffer_new_binding_table_block(cmd_buffer); 118301e04c3fSmrg if (result != VK_SUCCESS) 118401e04c3fSmrg return result; 118501e04c3fSmrg 118601e04c3fSmrg /* Re-emit state base addresses so we get the new surface state base 118701e04c3fSmrg * address before we start emitting binding tables etc. 118801e04c3fSmrg */ 118901e04c3fSmrg anv_cmd_buffer_emit_state_base_address(cmd_buffer); 119001e04c3fSmrg 119101e04c3fSmrg *bt_state = anv_cmd_buffer_alloc_binding_table(cmd_buffer, num_entries, 119201e04c3fSmrg state_offset); 119301e04c3fSmrg assert(bt_state->map != NULL); 119401e04c3fSmrg } 119501e04c3fSmrg 119601e04c3fSmrg return VK_SUCCESS; 119701e04c3fSmrg} 119801e04c3fSmrg 119901e04c3fSmrgstatic VkResult 120001e04c3fSmrgbinding_table_for_surface_state(struct anv_cmd_buffer *cmd_buffer, 120101e04c3fSmrg struct anv_state surface_state, 120201e04c3fSmrg uint32_t *bt_offset) 120301e04c3fSmrg{ 120401e04c3fSmrg uint32_t state_offset; 120501e04c3fSmrg struct anv_state bt_state; 120601e04c3fSmrg 120701e04c3fSmrg VkResult result = 120801e04c3fSmrg anv_cmd_buffer_alloc_blorp_binding_table(cmd_buffer, 1, &state_offset, 120901e04c3fSmrg &bt_state); 121001e04c3fSmrg if (result != VK_SUCCESS) 121101e04c3fSmrg return result; 121201e04c3fSmrg 121301e04c3fSmrg uint32_t *bt_map = bt_state.map; 121401e04c3fSmrg bt_map[0] = surface_state.offset + state_offset; 121501e04c3fSmrg 121601e04c3fSmrg *bt_offset = bt_state.offset; 121701e04c3fSmrg return VK_SUCCESS; 121801e04c3fSmrg} 121901e04c3fSmrg 122001e04c3fSmrgstatic void 122101e04c3fSmrgclear_color_attachment(struct anv_cmd_buffer *cmd_buffer, 122201e04c3fSmrg struct blorp_batch *batch, 122301e04c3fSmrg const VkClearAttachment *attachment, 122401e04c3fSmrg uint32_t rectCount, const VkClearRect *pRects) 122501e04c3fSmrg{ 122601e04c3fSmrg const struct anv_subpass *subpass = cmd_buffer->state.subpass; 122701e04c3fSmrg const uint32_t color_att = attachment->colorAttachment; 12289f464c52Smaya assert(color_att < subpass->color_count); 122901e04c3fSmrg const uint32_t att_idx = subpass->color_attachments[color_att].attachment; 123001e04c3fSmrg 123101e04c3fSmrg if (att_idx == VK_ATTACHMENT_UNUSED) 123201e04c3fSmrg return; 123301e04c3fSmrg 123401e04c3fSmrg struct anv_render_pass_attachment *pass_att = 123501e04c3fSmrg &cmd_buffer->state.pass->attachments[att_idx]; 123601e04c3fSmrg struct anv_attachment_state *att_state = 123701e04c3fSmrg &cmd_buffer->state.attachments[att_idx]; 123801e04c3fSmrg 123901e04c3fSmrg uint32_t binding_table; 124001e04c3fSmrg VkResult result = 124101e04c3fSmrg binding_table_for_surface_state(cmd_buffer, att_state->color.state, 124201e04c3fSmrg &binding_table); 124301e04c3fSmrg if (result != VK_SUCCESS) 124401e04c3fSmrg return; 124501e04c3fSmrg 124601e04c3fSmrg union isl_color_value clear_color = 124701e04c3fSmrg vk_to_isl_color(attachment->clearValue.color); 124801e04c3fSmrg 124901e04c3fSmrg /* If multiview is enabled we ignore baseArrayLayer and layerCount */ 125001e04c3fSmrg if (subpass->view_mask) { 12517ec681f3Smrg u_foreach_bit(view_idx, subpass->view_mask) { 125201e04c3fSmrg for (uint32_t r = 0; r < rectCount; ++r) { 125301e04c3fSmrg const VkOffset2D offset = pRects[r].rect.offset; 125401e04c3fSmrg const VkExtent2D extent = pRects[r].rect.extent; 125501e04c3fSmrg blorp_clear_attachments(batch, binding_table, 125601e04c3fSmrg ISL_FORMAT_UNSUPPORTED, pass_att->samples, 125701e04c3fSmrg view_idx, 1, 125801e04c3fSmrg offset.x, offset.y, 125901e04c3fSmrg offset.x + extent.width, 126001e04c3fSmrg offset.y + extent.height, 126101e04c3fSmrg true, clear_color, false, 0.0f, 0, 0); 126201e04c3fSmrg } 126301e04c3fSmrg } 126401e04c3fSmrg return; 126501e04c3fSmrg } 126601e04c3fSmrg 126701e04c3fSmrg for (uint32_t r = 0; r < rectCount; ++r) { 126801e04c3fSmrg const VkOffset2D offset = pRects[r].rect.offset; 126901e04c3fSmrg const VkExtent2D extent = pRects[r].rect.extent; 127001e04c3fSmrg assert(pRects[r].layerCount != VK_REMAINING_ARRAY_LAYERS); 127101e04c3fSmrg blorp_clear_attachments(batch, binding_table, 127201e04c3fSmrg ISL_FORMAT_UNSUPPORTED, pass_att->samples, 127301e04c3fSmrg pRects[r].baseArrayLayer, 127401e04c3fSmrg pRects[r].layerCount, 127501e04c3fSmrg offset.x, offset.y, 127601e04c3fSmrg offset.x + extent.width, offset.y + extent.height, 127701e04c3fSmrg true, clear_color, false, 0.0f, 0, 0); 127801e04c3fSmrg } 127901e04c3fSmrg} 128001e04c3fSmrg 128101e04c3fSmrgstatic void 128201e04c3fSmrgclear_depth_stencil_attachment(struct anv_cmd_buffer *cmd_buffer, 128301e04c3fSmrg struct blorp_batch *batch, 128401e04c3fSmrg const VkClearAttachment *attachment, 128501e04c3fSmrg uint32_t rectCount, const VkClearRect *pRects) 128601e04c3fSmrg{ 128701e04c3fSmrg static const union isl_color_value color_value = { .u32 = { 0, } }; 128801e04c3fSmrg const struct anv_subpass *subpass = cmd_buffer->state.subpass; 12899f464c52Smaya if (!subpass->depth_stencil_attachment) 129001e04c3fSmrg return; 129101e04c3fSmrg 12929f464c52Smaya const uint32_t att_idx = subpass->depth_stencil_attachment->attachment; 12939f464c52Smaya assert(att_idx != VK_ATTACHMENT_UNUSED); 129401e04c3fSmrg struct anv_render_pass_attachment *pass_att = 129501e04c3fSmrg &cmd_buffer->state.pass->attachments[att_idx]; 129601e04c3fSmrg 129701e04c3fSmrg bool clear_depth = attachment->aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT; 129801e04c3fSmrg bool clear_stencil = attachment->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT; 129901e04c3fSmrg 130001e04c3fSmrg enum isl_format depth_format = ISL_FORMAT_UNSUPPORTED; 130101e04c3fSmrg if (clear_depth) { 130201e04c3fSmrg depth_format = anv_get_isl_format(&cmd_buffer->device->info, 130301e04c3fSmrg pass_att->format, 130401e04c3fSmrg VK_IMAGE_ASPECT_DEPTH_BIT, 130501e04c3fSmrg VK_IMAGE_TILING_OPTIMAL); 130601e04c3fSmrg } 130701e04c3fSmrg 130801e04c3fSmrg uint32_t binding_table; 130901e04c3fSmrg VkResult result = 131001e04c3fSmrg binding_table_for_surface_state(cmd_buffer, 131101e04c3fSmrg cmd_buffer->state.null_surface_state, 131201e04c3fSmrg &binding_table); 131301e04c3fSmrg if (result != VK_SUCCESS) 131401e04c3fSmrg return; 131501e04c3fSmrg 131601e04c3fSmrg /* If multiview is enabled we ignore baseArrayLayer and layerCount */ 131701e04c3fSmrg if (subpass->view_mask) { 13187ec681f3Smrg u_foreach_bit(view_idx, subpass->view_mask) { 131901e04c3fSmrg for (uint32_t r = 0; r < rectCount; ++r) { 132001e04c3fSmrg const VkOffset2D offset = pRects[r].rect.offset; 132101e04c3fSmrg const VkExtent2D extent = pRects[r].rect.extent; 132201e04c3fSmrg VkClearDepthStencilValue value = attachment->clearValue.depthStencil; 132301e04c3fSmrg blorp_clear_attachments(batch, binding_table, 132401e04c3fSmrg depth_format, pass_att->samples, 132501e04c3fSmrg view_idx, 1, 132601e04c3fSmrg offset.x, offset.y, 132701e04c3fSmrg offset.x + extent.width, 132801e04c3fSmrg offset.y + extent.height, 132901e04c3fSmrg false, color_value, 133001e04c3fSmrg clear_depth, value.depth, 133101e04c3fSmrg clear_stencil ? 0xff : 0, value.stencil); 133201e04c3fSmrg } 133301e04c3fSmrg } 133401e04c3fSmrg return; 133501e04c3fSmrg } 133601e04c3fSmrg 133701e04c3fSmrg for (uint32_t r = 0; r < rectCount; ++r) { 133801e04c3fSmrg const VkOffset2D offset = pRects[r].rect.offset; 133901e04c3fSmrg const VkExtent2D extent = pRects[r].rect.extent; 134001e04c3fSmrg VkClearDepthStencilValue value = attachment->clearValue.depthStencil; 134101e04c3fSmrg assert(pRects[r].layerCount != VK_REMAINING_ARRAY_LAYERS); 134201e04c3fSmrg blorp_clear_attachments(batch, binding_table, 134301e04c3fSmrg depth_format, pass_att->samples, 134401e04c3fSmrg pRects[r].baseArrayLayer, 134501e04c3fSmrg pRects[r].layerCount, 134601e04c3fSmrg offset.x, offset.y, 134701e04c3fSmrg offset.x + extent.width, offset.y + extent.height, 134801e04c3fSmrg false, color_value, 134901e04c3fSmrg clear_depth, value.depth, 135001e04c3fSmrg clear_stencil ? 0xff : 0, value.stencil); 135101e04c3fSmrg } 135201e04c3fSmrg} 135301e04c3fSmrg 135401e04c3fSmrgvoid anv_CmdClearAttachments( 135501e04c3fSmrg VkCommandBuffer commandBuffer, 135601e04c3fSmrg uint32_t attachmentCount, 135701e04c3fSmrg const VkClearAttachment* pAttachments, 135801e04c3fSmrg uint32_t rectCount, 135901e04c3fSmrg const VkClearRect* pRects) 136001e04c3fSmrg{ 136101e04c3fSmrg ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 136201e04c3fSmrg 136301e04c3fSmrg /* Because this gets called within a render pass, we tell blorp not to 136401e04c3fSmrg * trash our depth and stencil buffers. 136501e04c3fSmrg */ 136601e04c3fSmrg struct blorp_batch batch; 13679f464c52Smaya enum blorp_batch_flags flags = BLORP_BATCH_NO_EMIT_DEPTH_STENCIL; 13689f464c52Smaya if (cmd_buffer->state.conditional_render_enabled) { 13699f464c52Smaya anv_cmd_emit_conditional_render_predicate(cmd_buffer); 13709f464c52Smaya flags |= BLORP_BATCH_PREDICATE_ENABLE; 13719f464c52Smaya } 13727ec681f3Smrg anv_blorp_batch_init(cmd_buffer, &batch, flags); 137301e04c3fSmrg 137401e04c3fSmrg for (uint32_t a = 0; a < attachmentCount; ++a) { 137501e04c3fSmrg if (pAttachments[a].aspectMask & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV) { 137601e04c3fSmrg assert(pAttachments[a].aspectMask == VK_IMAGE_ASPECT_COLOR_BIT); 137701e04c3fSmrg clear_color_attachment(cmd_buffer, &batch, 137801e04c3fSmrg &pAttachments[a], 137901e04c3fSmrg rectCount, pRects); 138001e04c3fSmrg } else { 138101e04c3fSmrg clear_depth_stencil_attachment(cmd_buffer, &batch, 138201e04c3fSmrg &pAttachments[a], 138301e04c3fSmrg rectCount, pRects); 138401e04c3fSmrg } 138501e04c3fSmrg } 138601e04c3fSmrg 13877ec681f3Smrg anv_blorp_batch_finish(&batch); 138801e04c3fSmrg} 138901e04c3fSmrg 139001e04c3fSmrgenum subpass_stage { 139101e04c3fSmrg SUBPASS_STAGE_LOAD, 139201e04c3fSmrg SUBPASS_STAGE_DRAW, 139301e04c3fSmrg SUBPASS_STAGE_RESOLVE, 139401e04c3fSmrg}; 139501e04c3fSmrg 13969f464c52Smayavoid 13979f464c52Smayaanv_image_msaa_resolve(struct anv_cmd_buffer *cmd_buffer, 13989f464c52Smaya const struct anv_image *src_image, 13999f464c52Smaya enum isl_aux_usage src_aux_usage, 14009f464c52Smaya uint32_t src_level, uint32_t src_base_layer, 14019f464c52Smaya const struct anv_image *dst_image, 14029f464c52Smaya enum isl_aux_usage dst_aux_usage, 14039f464c52Smaya uint32_t dst_level, uint32_t dst_base_layer, 14049f464c52Smaya VkImageAspectFlagBits aspect, 14059f464c52Smaya uint32_t src_x, uint32_t src_y, 14069f464c52Smaya uint32_t dst_x, uint32_t dst_y, 14079f464c52Smaya uint32_t width, uint32_t height, 14089f464c52Smaya uint32_t layer_count, 14099f464c52Smaya enum blorp_filter filter) 141001e04c3fSmrg{ 14119f464c52Smaya struct blorp_batch batch; 14127ec681f3Smrg anv_blorp_batch_init(cmd_buffer, &batch, 0); 14137ec681f3Smrg assert((batch.flags & BLORP_BATCH_USE_COMPUTE) == 0); 141401e04c3fSmrg 14157ec681f3Smrg assert(src_image->vk.image_type == VK_IMAGE_TYPE_2D); 14167ec681f3Smrg assert(src_image->vk.samples > 1); 14177ec681f3Smrg assert(dst_image->vk.image_type == VK_IMAGE_TYPE_2D); 14187ec681f3Smrg assert(dst_image->vk.samples == 1); 141901e04c3fSmrg assert(src_image->n_planes == dst_image->n_planes); 14209f464c52Smaya 14219f464c52Smaya struct blorp_surf src_surf, dst_surf; 14229f464c52Smaya get_blorp_surf_for_anv_image(cmd_buffer->device, src_image, aspect, 14237ec681f3Smrg VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 14249f464c52Smaya ANV_IMAGE_LAYOUT_EXPLICIT_AUX, 14259f464c52Smaya src_aux_usage, &src_surf); 14269f464c52Smaya if (src_aux_usage == ISL_AUX_USAGE_MCS) { 14279f464c52Smaya src_surf.clear_color_addr = anv_to_blorp_address( 14289f464c52Smaya anv_image_get_clear_color_addr(cmd_buffer->device, src_image, 14299f464c52Smaya VK_IMAGE_ASPECT_COLOR_BIT)); 14309f464c52Smaya } 14319f464c52Smaya get_blorp_surf_for_anv_image(cmd_buffer->device, dst_image, aspect, 14327ec681f3Smrg VK_IMAGE_USAGE_TRANSFER_DST_BIT, 14339f464c52Smaya ANV_IMAGE_LAYOUT_EXPLICIT_AUX, 14349f464c52Smaya dst_aux_usage, &dst_surf); 14359f464c52Smaya anv_cmd_buffer_mark_image_written(cmd_buffer, dst_image, 14369f464c52Smaya aspect, dst_aux_usage, 14379f464c52Smaya dst_level, dst_base_layer, layer_count); 14389f464c52Smaya 14399f464c52Smaya if (filter == BLORP_FILTER_NONE) { 14409f464c52Smaya /* If no explicit filter is provided, then it's implied by the type of 14419f464c52Smaya * the source image. 14429f464c52Smaya */ 144301e04c3fSmrg if ((src_surf.surf->usage & ISL_SURF_USAGE_DEPTH_BIT) || 144401e04c3fSmrg (src_surf.surf->usage & ISL_SURF_USAGE_STENCIL_BIT) || 144501e04c3fSmrg isl_format_has_int_channel(src_surf.surf->format)) { 144601e04c3fSmrg filter = BLORP_FILTER_SAMPLE_0; 144701e04c3fSmrg } else { 144801e04c3fSmrg filter = BLORP_FILTER_AVERAGE; 144901e04c3fSmrg } 14509f464c52Smaya } 145101e04c3fSmrg 14529f464c52Smaya for (uint32_t l = 0; l < layer_count; l++) { 14539f464c52Smaya blorp_blit(&batch, 14549f464c52Smaya &src_surf, src_level, src_base_layer + l, 14559f464c52Smaya ISL_FORMAT_UNSUPPORTED, ISL_SWIZZLE_IDENTITY, 14569f464c52Smaya &dst_surf, dst_level, dst_base_layer + l, 14579f464c52Smaya ISL_FORMAT_UNSUPPORTED, ISL_SWIZZLE_IDENTITY, 14589f464c52Smaya src_x, src_y, src_x + width, src_y + height, 14599f464c52Smaya dst_x, dst_y, dst_x + width, dst_y + height, 14609f464c52Smaya filter, false, false); 146101e04c3fSmrg } 14629f464c52Smaya 14637ec681f3Smrg anv_blorp_batch_finish(&batch); 146401e04c3fSmrg} 146501e04c3fSmrg 14667ec681f3Smrgstatic void 14677ec681f3Smrgresolve_image(struct anv_cmd_buffer *cmd_buffer, 14687ec681f3Smrg struct anv_image *src_image, 14697ec681f3Smrg VkImageLayout src_image_layout, 14707ec681f3Smrg struct anv_image *dst_image, 14717ec681f3Smrg VkImageLayout dst_image_layout, 14727ec681f3Smrg const VkImageResolve2KHR *region) 147301e04c3fSmrg{ 14747ec681f3Smrg assert(region->srcSubresource.aspectMask == region->dstSubresource.aspectMask); 14757ec681f3Smrg assert(vk_image_subresource_layer_count(&src_image->vk, ®ion->srcSubresource) == 14767ec681f3Smrg vk_image_subresource_layer_count(&dst_image->vk, ®ion->dstSubresource)); 14777ec681f3Smrg 14787ec681f3Smrg const uint32_t layer_count = 14797ec681f3Smrg vk_image_subresource_layer_count(&dst_image->vk, ®ion->dstSubresource); 14807ec681f3Smrg 14817ec681f3Smrg anv_foreach_image_aspect_bit(aspect_bit, src_image, 14827ec681f3Smrg region->srcSubresource.aspectMask) { 14837ec681f3Smrg enum isl_aux_usage src_aux_usage = 14847ec681f3Smrg anv_layout_to_aux_usage(&cmd_buffer->device->info, src_image, 14857ec681f3Smrg (1 << aspect_bit), 14867ec681f3Smrg VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 14877ec681f3Smrg src_image_layout); 14887ec681f3Smrg enum isl_aux_usage dst_aux_usage = 14897ec681f3Smrg anv_layout_to_aux_usage(&cmd_buffer->device->info, dst_image, 14907ec681f3Smrg (1 << aspect_bit), 14917ec681f3Smrg VK_IMAGE_USAGE_TRANSFER_DST_BIT, 14927ec681f3Smrg dst_image_layout); 14937ec681f3Smrg 14947ec681f3Smrg anv_image_msaa_resolve(cmd_buffer, 14957ec681f3Smrg src_image, src_aux_usage, 14967ec681f3Smrg region->srcSubresource.mipLevel, 14977ec681f3Smrg region->srcSubresource.baseArrayLayer, 14987ec681f3Smrg dst_image, dst_aux_usage, 14997ec681f3Smrg region->dstSubresource.mipLevel, 15007ec681f3Smrg region->dstSubresource.baseArrayLayer, 15017ec681f3Smrg (1 << aspect_bit), 15027ec681f3Smrg region->srcOffset.x, 15037ec681f3Smrg region->srcOffset.y, 15047ec681f3Smrg region->dstOffset.x, 15057ec681f3Smrg region->dstOffset.y, 15067ec681f3Smrg region->extent.width, 15077ec681f3Smrg region->extent.height, 15087ec681f3Smrg layer_count, BLORP_FILTER_NONE); 150901e04c3fSmrg } 151001e04c3fSmrg} 151101e04c3fSmrg 15127ec681f3Smrgvoid anv_CmdResolveImage2KHR( 15137ec681f3Smrg VkCommandBuffer commandBuffer, 15147ec681f3Smrg const VkResolveImageInfo2KHR* pResolveImageInfo) 151501e04c3fSmrg{ 15167ec681f3Smrg ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 15177ec681f3Smrg ANV_FROM_HANDLE(anv_image, src_image, pResolveImageInfo->srcImage); 15187ec681f3Smrg ANV_FROM_HANDLE(anv_image, dst_image, pResolveImageInfo->dstImage); 15197ec681f3Smrg 15207ec681f3Smrg for (uint32_t r = 0; r < pResolveImageInfo->regionCount; r++) { 15217ec681f3Smrg resolve_image(cmd_buffer, 15227ec681f3Smrg src_image, pResolveImageInfo->srcImageLayout, 15237ec681f3Smrg dst_image, pResolveImageInfo->dstImageLayout, 15247ec681f3Smrg &pResolveImageInfo->pRegions[r]); 15257ec681f3Smrg } 152601e04c3fSmrg} 152701e04c3fSmrg 152801e04c3fSmrgvoid 152901e04c3fSmrganv_image_copy_to_shadow(struct anv_cmd_buffer *cmd_buffer, 153001e04c3fSmrg const struct anv_image *image, 15317ec681f3Smrg VkImageAspectFlagBits aspect, 153201e04c3fSmrg uint32_t base_level, uint32_t level_count, 153301e04c3fSmrg uint32_t base_layer, uint32_t layer_count) 153401e04c3fSmrg{ 153501e04c3fSmrg struct blorp_batch batch; 15367ec681f3Smrg anv_blorp_batch_init(cmd_buffer, &batch, 0); 153701e04c3fSmrg 15387ec681f3Smrg /* We don't know who touched the main surface last so flush a bunch of 15397ec681f3Smrg * caches to ensure we get good data. 15407ec681f3Smrg */ 15417ec681f3Smrg anv_add_pending_pipe_bits(cmd_buffer, 15427ec681f3Smrg ANV_PIPE_DEPTH_CACHE_FLUSH_BIT | 15437ec681f3Smrg ANV_PIPE_HDC_PIPELINE_FLUSH_BIT | 15447ec681f3Smrg ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | 15457ec681f3Smrg ANV_PIPE_TEXTURE_CACHE_INVALIDATE_BIT, 15467ec681f3Smrg "before copy_to_shadow"); 154701e04c3fSmrg 154801e04c3fSmrg struct blorp_surf surf; 154901e04c3fSmrg get_blorp_surf_for_anv_image(cmd_buffer->device, 15507ec681f3Smrg image, aspect, 15517ec681f3Smrg VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 155201e04c3fSmrg VK_IMAGE_LAYOUT_GENERAL, 155301e04c3fSmrg ISL_AUX_USAGE_NONE, &surf); 155401e04c3fSmrg assert(surf.aux_usage == ISL_AUX_USAGE_NONE); 155501e04c3fSmrg 15567ec681f3Smrg struct blorp_surf shadow_surf; 15577ec681f3Smrg get_blorp_surf_for_anv_shadow_image(cmd_buffer->device, 15587ec681f3Smrg image, aspect, &shadow_surf); 155901e04c3fSmrg 156001e04c3fSmrg for (uint32_t l = 0; l < level_count; l++) { 156101e04c3fSmrg const uint32_t level = base_level + l; 156201e04c3fSmrg 15637ec681f3Smrg const VkExtent3D extent = vk_image_mip_level_extent(&image->vk, level); 156401e04c3fSmrg 15657ec681f3Smrg if (image->vk.image_type == VK_IMAGE_TYPE_3D) 156601e04c3fSmrg layer_count = extent.depth; 156701e04c3fSmrg 156801e04c3fSmrg for (uint32_t a = 0; a < layer_count; a++) { 156901e04c3fSmrg const uint32_t layer = base_layer + a; 157001e04c3fSmrg 157101e04c3fSmrg blorp_copy(&batch, &surf, level, layer, 157201e04c3fSmrg &shadow_surf, level, layer, 157301e04c3fSmrg 0, 0, 0, 0, extent.width, extent.height); 157401e04c3fSmrg } 157501e04c3fSmrg } 157601e04c3fSmrg 15777ec681f3Smrg /* We just wrote to the buffer with the render cache. Flush it. */ 15787ec681f3Smrg anv_add_pending_pipe_bits(cmd_buffer, 15797ec681f3Smrg ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT, 15807ec681f3Smrg "after copy_to_shadow"); 15817ec681f3Smrg 15827ec681f3Smrg anv_blorp_batch_finish(&batch); 158301e04c3fSmrg} 158401e04c3fSmrg 158501e04c3fSmrgvoid 158601e04c3fSmrganv_image_clear_color(struct anv_cmd_buffer *cmd_buffer, 158701e04c3fSmrg const struct anv_image *image, 158801e04c3fSmrg VkImageAspectFlagBits aspect, 158901e04c3fSmrg enum isl_aux_usage aux_usage, 159001e04c3fSmrg enum isl_format format, struct isl_swizzle swizzle, 159101e04c3fSmrg uint32_t level, uint32_t base_layer, uint32_t layer_count, 159201e04c3fSmrg VkRect2D area, union isl_color_value clear_color) 159301e04c3fSmrg{ 15947ec681f3Smrg assert(image->vk.aspects == VK_IMAGE_ASPECT_COLOR_BIT); 159501e04c3fSmrg 159601e04c3fSmrg /* We don't support planar images with multisampling yet */ 159701e04c3fSmrg assert(image->n_planes == 1); 159801e04c3fSmrg 159901e04c3fSmrg struct blorp_batch batch; 16007ec681f3Smrg anv_blorp_batch_init(cmd_buffer, &batch, 0); 160101e04c3fSmrg 160201e04c3fSmrg struct blorp_surf surf; 160301e04c3fSmrg get_blorp_surf_for_anv_image(cmd_buffer->device, image, aspect, 16047ec681f3Smrg VK_IMAGE_USAGE_TRANSFER_DST_BIT, 160501e04c3fSmrg ANV_IMAGE_LAYOUT_EXPLICIT_AUX, 160601e04c3fSmrg aux_usage, &surf); 160701e04c3fSmrg anv_cmd_buffer_mark_image_written(cmd_buffer, image, aspect, aux_usage, 160801e04c3fSmrg level, base_layer, layer_count); 160901e04c3fSmrg 161001e04c3fSmrg blorp_clear(&batch, &surf, format, anv_swizzle_for_render(swizzle), 161101e04c3fSmrg level, base_layer, layer_count, 161201e04c3fSmrg area.offset.x, area.offset.y, 161301e04c3fSmrg area.offset.x + area.extent.width, 161401e04c3fSmrg area.offset.y + area.extent.height, 16157ec681f3Smrg clear_color, 0 /* color_write_disable */); 161601e04c3fSmrg 16177ec681f3Smrg anv_blorp_batch_finish(&batch); 161801e04c3fSmrg} 161901e04c3fSmrg 162001e04c3fSmrgvoid 162101e04c3fSmrganv_image_clear_depth_stencil(struct anv_cmd_buffer *cmd_buffer, 162201e04c3fSmrg const struct anv_image *image, 162301e04c3fSmrg VkImageAspectFlags aspects, 162401e04c3fSmrg enum isl_aux_usage depth_aux_usage, 162501e04c3fSmrg uint32_t level, 162601e04c3fSmrg uint32_t base_layer, uint32_t layer_count, 162701e04c3fSmrg VkRect2D area, 162801e04c3fSmrg float depth_value, uint8_t stencil_value) 162901e04c3fSmrg{ 16307ec681f3Smrg assert(image->vk.aspects & (VK_IMAGE_ASPECT_DEPTH_BIT | 16317ec681f3Smrg VK_IMAGE_ASPECT_STENCIL_BIT)); 163201e04c3fSmrg 163301e04c3fSmrg struct blorp_batch batch; 16347ec681f3Smrg anv_blorp_batch_init(cmd_buffer, &batch, 0); 16357ec681f3Smrg assert((batch.flags & BLORP_BATCH_USE_COMPUTE) == 0); 163601e04c3fSmrg 163701e04c3fSmrg struct blorp_surf depth = {}; 163801e04c3fSmrg if (aspects & VK_IMAGE_ASPECT_DEPTH_BIT) { 163901e04c3fSmrg get_blorp_surf_for_anv_image(cmd_buffer->device, 164001e04c3fSmrg image, VK_IMAGE_ASPECT_DEPTH_BIT, 16417ec681f3Smrg 0, ANV_IMAGE_LAYOUT_EXPLICIT_AUX, 164201e04c3fSmrg depth_aux_usage, &depth); 164301e04c3fSmrg } 164401e04c3fSmrg 164501e04c3fSmrg struct blorp_surf stencil = {}; 164601e04c3fSmrg if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) { 16477ec681f3Smrg const uint32_t plane = 16487ec681f3Smrg anv_image_aspect_to_plane(image, VK_IMAGE_ASPECT_STENCIL_BIT); 164901e04c3fSmrg get_blorp_surf_for_anv_image(cmd_buffer->device, 165001e04c3fSmrg image, VK_IMAGE_ASPECT_STENCIL_BIT, 16517ec681f3Smrg 0, ANV_IMAGE_LAYOUT_EXPLICIT_AUX, 16527ec681f3Smrg image->planes[plane].aux_usage, &stencil); 165301e04c3fSmrg } 165401e04c3fSmrg 16557ec681f3Smrg /* Blorp may choose to clear stencil using RGBA32_UINT for better 16567ec681f3Smrg * performance. If it does this, we need to flush it out of the depth 16577ec681f3Smrg * cache before rendering to it. 16587ec681f3Smrg */ 16597ec681f3Smrg anv_add_pending_pipe_bits(cmd_buffer, 16607ec681f3Smrg ANV_PIPE_DEPTH_CACHE_FLUSH_BIT | 16617ec681f3Smrg ANV_PIPE_END_OF_PIPE_SYNC_BIT, 16627ec681f3Smrg "before clear DS"); 16637ec681f3Smrg 166401e04c3fSmrg blorp_clear_depth_stencil(&batch, &depth, &stencil, 166501e04c3fSmrg level, base_layer, layer_count, 166601e04c3fSmrg area.offset.x, area.offset.y, 166701e04c3fSmrg area.offset.x + area.extent.width, 166801e04c3fSmrg area.offset.y + area.extent.height, 166901e04c3fSmrg aspects & VK_IMAGE_ASPECT_DEPTH_BIT, 167001e04c3fSmrg depth_value, 167101e04c3fSmrg (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) ? 0xff : 0, 167201e04c3fSmrg stencil_value); 167301e04c3fSmrg 16747ec681f3Smrg /* Blorp may choose to clear stencil using RGBA32_UINT for better 16757ec681f3Smrg * performance. If it does this, we need to flush it out of the render 16767ec681f3Smrg * cache before someone starts trying to do stencil on it. 16777ec681f3Smrg */ 16787ec681f3Smrg anv_add_pending_pipe_bits(cmd_buffer, 16797ec681f3Smrg ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | 16807ec681f3Smrg ANV_PIPE_END_OF_PIPE_SYNC_BIT, 16817ec681f3Smrg "after clear DS"); 16827ec681f3Smrg 16837ec681f3Smrg struct blorp_surf stencil_shadow; 16847ec681f3Smrg if ((aspects & VK_IMAGE_ASPECT_STENCIL_BIT) && 16857ec681f3Smrg get_blorp_surf_for_anv_shadow_image(cmd_buffer->device, image, 16867ec681f3Smrg VK_IMAGE_ASPECT_STENCIL_BIT, 16877ec681f3Smrg &stencil_shadow)) { 16887ec681f3Smrg union isl_color_value stencil_color = { 16897ec681f3Smrg .u32 = { stencil_value }, 16907ec681f3Smrg }; 16917ec681f3Smrg blorp_clear(&batch, &stencil_shadow, 16927ec681f3Smrg ISL_FORMAT_R8_UINT, ISL_SWIZZLE_IDENTITY, 16937ec681f3Smrg level, base_layer, layer_count, 16947ec681f3Smrg area.offset.x, area.offset.y, 16957ec681f3Smrg area.offset.x + area.extent.width, 16967ec681f3Smrg area.offset.y + area.extent.height, 16977ec681f3Smrg stencil_color, 0 /* color_write_disable */); 16987ec681f3Smrg } 16997ec681f3Smrg 17007ec681f3Smrg anv_blorp_batch_finish(&batch); 170101e04c3fSmrg} 170201e04c3fSmrg 170301e04c3fSmrgvoid 170401e04c3fSmrganv_image_hiz_op(struct anv_cmd_buffer *cmd_buffer, 170501e04c3fSmrg const struct anv_image *image, 170601e04c3fSmrg VkImageAspectFlagBits aspect, uint32_t level, 170701e04c3fSmrg uint32_t base_layer, uint32_t layer_count, 170801e04c3fSmrg enum isl_aux_op hiz_op) 170901e04c3fSmrg{ 171001e04c3fSmrg assert(aspect == VK_IMAGE_ASPECT_DEPTH_BIT); 171101e04c3fSmrg assert(base_layer + layer_count <= anv_image_aux_layers(image, aspect, level)); 17127ec681f3Smrg const uint32_t plane = anv_image_aspect_to_plane(image, aspect); 17137ec681f3Smrg assert(plane == 0); 171401e04c3fSmrg 171501e04c3fSmrg struct blorp_batch batch; 17167ec681f3Smrg anv_blorp_batch_init(cmd_buffer, &batch, 0); 17177ec681f3Smrg assert((batch.flags & BLORP_BATCH_USE_COMPUTE) == 0); 171801e04c3fSmrg 171901e04c3fSmrg struct blorp_surf surf; 172001e04c3fSmrg get_blorp_surf_for_anv_image(cmd_buffer->device, 172101e04c3fSmrg image, VK_IMAGE_ASPECT_DEPTH_BIT, 17227ec681f3Smrg 0, ANV_IMAGE_LAYOUT_EXPLICIT_AUX, 17237ec681f3Smrg image->planes[plane].aux_usage, &surf); 172401e04c3fSmrg 172501e04c3fSmrg blorp_hiz_op(&batch, &surf, level, base_layer, layer_count, hiz_op); 172601e04c3fSmrg 17277ec681f3Smrg anv_blorp_batch_finish(&batch); 172801e04c3fSmrg} 172901e04c3fSmrg 173001e04c3fSmrgvoid 173101e04c3fSmrganv_image_hiz_clear(struct anv_cmd_buffer *cmd_buffer, 173201e04c3fSmrg const struct anv_image *image, 173301e04c3fSmrg VkImageAspectFlags aspects, 173401e04c3fSmrg uint32_t level, 173501e04c3fSmrg uint32_t base_layer, uint32_t layer_count, 173601e04c3fSmrg VkRect2D area, uint8_t stencil_value) 173701e04c3fSmrg{ 17387ec681f3Smrg assert(image->vk.aspects & (VK_IMAGE_ASPECT_DEPTH_BIT | 17397ec681f3Smrg VK_IMAGE_ASPECT_STENCIL_BIT)); 174001e04c3fSmrg 174101e04c3fSmrg struct blorp_batch batch; 17427ec681f3Smrg anv_blorp_batch_init(cmd_buffer, &batch, 0); 17437ec681f3Smrg assert((batch.flags & BLORP_BATCH_USE_COMPUTE) == 0); 174401e04c3fSmrg 174501e04c3fSmrg struct blorp_surf depth = {}; 174601e04c3fSmrg if (aspects & VK_IMAGE_ASPECT_DEPTH_BIT) { 17477ec681f3Smrg const uint32_t plane = 17487ec681f3Smrg anv_image_aspect_to_plane(image, VK_IMAGE_ASPECT_DEPTH_BIT); 174901e04c3fSmrg assert(base_layer + layer_count <= 175001e04c3fSmrg anv_image_aux_layers(image, VK_IMAGE_ASPECT_DEPTH_BIT, level)); 175101e04c3fSmrg get_blorp_surf_for_anv_image(cmd_buffer->device, 175201e04c3fSmrg image, VK_IMAGE_ASPECT_DEPTH_BIT, 17537ec681f3Smrg 0, ANV_IMAGE_LAYOUT_EXPLICIT_AUX, 17547ec681f3Smrg image->planes[plane].aux_usage, &depth); 175501e04c3fSmrg } 175601e04c3fSmrg 175701e04c3fSmrg struct blorp_surf stencil = {}; 175801e04c3fSmrg if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) { 17597ec681f3Smrg const uint32_t plane = 17607ec681f3Smrg anv_image_aspect_to_plane(image, VK_IMAGE_ASPECT_STENCIL_BIT); 176101e04c3fSmrg get_blorp_surf_for_anv_image(cmd_buffer->device, 176201e04c3fSmrg image, VK_IMAGE_ASPECT_STENCIL_BIT, 17637ec681f3Smrg 0, ANV_IMAGE_LAYOUT_EXPLICIT_AUX, 17647ec681f3Smrg image->planes[plane].aux_usage, &stencil); 176501e04c3fSmrg } 176601e04c3fSmrg 176701e04c3fSmrg /* From the Sky Lake PRM Volume 7, "Depth Buffer Clear": 176801e04c3fSmrg * 176901e04c3fSmrg * "The following is required when performing a depth buffer clear with 177001e04c3fSmrg * using the WM_STATE or 3DSTATE_WM: 177101e04c3fSmrg * 177201e04c3fSmrg * * If other rendering operations have preceded this clear, a 177301e04c3fSmrg * PIPE_CONTROL with depth cache flush enabled, Depth Stall bit 177401e04c3fSmrg * enabled must be issued before the rectangle primitive used for 177501e04c3fSmrg * the depth buffer clear operation. 177601e04c3fSmrg * * [...]" 177701e04c3fSmrg * 177801e04c3fSmrg * Even though the PRM only says that this is required if using 3DSTATE_WM 177901e04c3fSmrg * and a 3DPRIMITIVE, the GPU appears to also need this to avoid occasional 178001e04c3fSmrg * hangs when doing a clear with WM_HZ_OP. 178101e04c3fSmrg */ 17827ec681f3Smrg anv_add_pending_pipe_bits(cmd_buffer, 17837ec681f3Smrg ANV_PIPE_DEPTH_CACHE_FLUSH_BIT | 17847ec681f3Smrg ANV_PIPE_DEPTH_STALL_BIT, 17857ec681f3Smrg "before clear hiz"); 17867ec681f3Smrg 17877ec681f3Smrg if ((aspects & VK_IMAGE_ASPECT_DEPTH_BIT) && 17887ec681f3Smrg depth.aux_usage == ISL_AUX_USAGE_HIZ_CCS_WT) { 17897ec681f3Smrg /* From Bspec 47010 (Depth Buffer Clear): 17907ec681f3Smrg * 17917ec681f3Smrg * Since the fast clear cycles to CCS are not cached in TileCache, 17927ec681f3Smrg * any previous depth buffer writes to overlapping pixels must be 17937ec681f3Smrg * flushed out of TileCache before a succeeding Depth Buffer Clear. 17947ec681f3Smrg * This restriction only applies to Depth Buffer with write-thru 17957ec681f3Smrg * enabled, since fast clears to CCS only occur for write-thru mode. 17967ec681f3Smrg * 17977ec681f3Smrg * There may have been a write to this depth buffer. Flush it from the 17987ec681f3Smrg * tile cache just in case. 17997ec681f3Smrg */ 18007ec681f3Smrg anv_add_pending_pipe_bits(cmd_buffer, 18017ec681f3Smrg ANV_PIPE_DEPTH_CACHE_FLUSH_BIT | 18027ec681f3Smrg ANV_PIPE_TILE_CACHE_FLUSH_BIT, 18037ec681f3Smrg "before clear hiz_ccs_wt"); 18047ec681f3Smrg } 180501e04c3fSmrg 180601e04c3fSmrg blorp_hiz_clear_depth_stencil(&batch, &depth, &stencil, 180701e04c3fSmrg level, base_layer, layer_count, 180801e04c3fSmrg area.offset.x, area.offset.y, 180901e04c3fSmrg area.offset.x + area.extent.width, 181001e04c3fSmrg area.offset.y + area.extent.height, 181101e04c3fSmrg aspects & VK_IMAGE_ASPECT_DEPTH_BIT, 181201e04c3fSmrg ANV_HZ_FC_VAL, 181301e04c3fSmrg aspects & VK_IMAGE_ASPECT_STENCIL_BIT, 181401e04c3fSmrg stencil_value); 181501e04c3fSmrg 18167ec681f3Smrg anv_blorp_batch_finish(&batch); 181701e04c3fSmrg 181801e04c3fSmrg /* From the SKL PRM, Depth Buffer Clear: 181901e04c3fSmrg * 182001e04c3fSmrg * "Depth Buffer Clear Workaround 182101e04c3fSmrg * 182201e04c3fSmrg * Depth buffer clear pass using any of the methods (WM_STATE, 182301e04c3fSmrg * 3DSTATE_WM or 3DSTATE_WM_HZ_OP) must be followed by a PIPE_CONTROL 182401e04c3fSmrg * command with DEPTH_STALL bit and Depth FLUSH bits “set” before 182501e04c3fSmrg * starting to render. DepthStall and DepthFlush are not needed between 182601e04c3fSmrg * consecutive depth clear passes nor is it required if the depth-clear 182701e04c3fSmrg * pass was done with “full_surf_clear” bit set in the 182801e04c3fSmrg * 3DSTATE_WM_HZ_OP." 182901e04c3fSmrg * 183001e04c3fSmrg * Even though the PRM provides a bunch of conditions under which this is 183101e04c3fSmrg * supposedly unnecessary, we choose to perform the flush unconditionally 183201e04c3fSmrg * just to be safe. 183301e04c3fSmrg */ 18347ec681f3Smrg anv_add_pending_pipe_bits(cmd_buffer, 18357ec681f3Smrg ANV_PIPE_DEPTH_CACHE_FLUSH_BIT | 18367ec681f3Smrg ANV_PIPE_DEPTH_STALL_BIT, 18377ec681f3Smrg "after clear hiz"); 183801e04c3fSmrg} 183901e04c3fSmrg 184001e04c3fSmrgvoid 184101e04c3fSmrganv_image_mcs_op(struct anv_cmd_buffer *cmd_buffer, 184201e04c3fSmrg const struct anv_image *image, 18437ec681f3Smrg enum isl_format format, struct isl_swizzle swizzle, 184401e04c3fSmrg VkImageAspectFlagBits aspect, 184501e04c3fSmrg uint32_t base_layer, uint32_t layer_count, 184601e04c3fSmrg enum isl_aux_op mcs_op, union isl_color_value *clear_value, 184701e04c3fSmrg bool predicate) 184801e04c3fSmrg{ 18497ec681f3Smrg assert(image->vk.aspects == VK_IMAGE_ASPECT_COLOR_BIT); 18507ec681f3Smrg assert(image->vk.samples > 1); 185101e04c3fSmrg assert(base_layer + layer_count <= anv_image_aux_layers(image, aspect, 0)); 185201e04c3fSmrg 185301e04c3fSmrg /* Multisampling with multi-planar formats is not supported */ 185401e04c3fSmrg assert(image->n_planes == 1); 185501e04c3fSmrg 185601e04c3fSmrg struct blorp_batch batch; 18577ec681f3Smrg anv_blorp_batch_init(cmd_buffer, &batch, 18587ec681f3Smrg BLORP_BATCH_PREDICATE_ENABLE * predicate + 18597ec681f3Smrg BLORP_BATCH_NO_UPDATE_CLEAR_COLOR * !clear_value); 18607ec681f3Smrg assert((batch.flags & BLORP_BATCH_USE_COMPUTE) == 0); 186101e04c3fSmrg 186201e04c3fSmrg struct blorp_surf surf; 186301e04c3fSmrg get_blorp_surf_for_anv_image(cmd_buffer->device, image, aspect, 18647ec681f3Smrg 0, ANV_IMAGE_LAYOUT_EXPLICIT_AUX, 186501e04c3fSmrg ISL_AUX_USAGE_MCS, &surf); 186601e04c3fSmrg 186701e04c3fSmrg /* Blorp will store the clear color for us if we provide the clear color 186801e04c3fSmrg * address and we are doing a fast clear. So we save the clear value into 18697ec681f3Smrg * the blorp surface. 187001e04c3fSmrg */ 18717ec681f3Smrg if (clear_value) 18727ec681f3Smrg surf.clear_color = *clear_value; 187301e04c3fSmrg 187401e04c3fSmrg /* From the Sky Lake PRM Vol. 7, "Render Target Fast Clear": 187501e04c3fSmrg * 187601e04c3fSmrg * "After Render target fast clear, pipe-control with color cache 187701e04c3fSmrg * write-flush must be issued before sending any DRAW commands on 187801e04c3fSmrg * that render target." 187901e04c3fSmrg * 188001e04c3fSmrg * This comment is a bit cryptic and doesn't really tell you what's going 188101e04c3fSmrg * or what's really needed. It appears that fast clear ops are not 188201e04c3fSmrg * properly synchronized with other drawing. This means that we cannot 188301e04c3fSmrg * have a fast clear operation in the pipe at the same time as other 188401e04c3fSmrg * regular drawing operations. We need to use a PIPE_CONTROL to ensure 188501e04c3fSmrg * that the contents of the previous draw hit the render target before we 188601e04c3fSmrg * resolve and then use a second PIPE_CONTROL after the resolve to ensure 188701e04c3fSmrg * that it is completed before any additional drawing occurs. 188801e04c3fSmrg */ 18897ec681f3Smrg anv_add_pending_pipe_bits(cmd_buffer, 18907ec681f3Smrg ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | 18917ec681f3Smrg ANV_PIPE_TILE_CACHE_FLUSH_BIT | 18927ec681f3Smrg ANV_PIPE_END_OF_PIPE_SYNC_BIT, 18937ec681f3Smrg "before fast clear mcs"); 189401e04c3fSmrg 189501e04c3fSmrg switch (mcs_op) { 189601e04c3fSmrg case ISL_AUX_OP_FAST_CLEAR: 18977ec681f3Smrg blorp_fast_clear(&batch, &surf, format, swizzle, 189801e04c3fSmrg 0, base_layer, layer_count, 18997ec681f3Smrg 0, 0, image->vk.extent.width, image->vk.extent.height); 190001e04c3fSmrg break; 190101e04c3fSmrg case ISL_AUX_OP_PARTIAL_RESOLVE: 190201e04c3fSmrg blorp_mcs_partial_resolve(&batch, &surf, format, 190301e04c3fSmrg base_layer, layer_count); 190401e04c3fSmrg break; 190501e04c3fSmrg case ISL_AUX_OP_FULL_RESOLVE: 190601e04c3fSmrg case ISL_AUX_OP_AMBIGUATE: 190701e04c3fSmrg default: 190801e04c3fSmrg unreachable("Unsupported MCS operation"); 190901e04c3fSmrg } 191001e04c3fSmrg 19117ec681f3Smrg anv_add_pending_pipe_bits(cmd_buffer, 19127ec681f3Smrg ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | 19137ec681f3Smrg ANV_PIPE_END_OF_PIPE_SYNC_BIT, 19147ec681f3Smrg "after fast clear mcs"); 191501e04c3fSmrg 19167ec681f3Smrg anv_blorp_batch_finish(&batch); 191701e04c3fSmrg} 191801e04c3fSmrg 191901e04c3fSmrgvoid 192001e04c3fSmrganv_image_ccs_op(struct anv_cmd_buffer *cmd_buffer, 192101e04c3fSmrg const struct anv_image *image, 19227ec681f3Smrg enum isl_format format, struct isl_swizzle swizzle, 192301e04c3fSmrg VkImageAspectFlagBits aspect, uint32_t level, 192401e04c3fSmrg uint32_t base_layer, uint32_t layer_count, 192501e04c3fSmrg enum isl_aux_op ccs_op, union isl_color_value *clear_value, 192601e04c3fSmrg bool predicate) 192701e04c3fSmrg{ 19287ec681f3Smrg assert(image->vk.aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV); 19297ec681f3Smrg assert(image->vk.samples == 1); 193001e04c3fSmrg assert(level < anv_image_aux_levels(image, aspect)); 193101e04c3fSmrg /* Multi-LOD YcBcR is not allowed */ 193201e04c3fSmrg assert(image->n_planes == 1 || level == 0); 193301e04c3fSmrg assert(base_layer + layer_count <= 193401e04c3fSmrg anv_image_aux_layers(image, aspect, level)); 193501e04c3fSmrg 19367ec681f3Smrg const uint32_t plane = anv_image_aspect_to_plane(image, aspect); 193701e04c3fSmrg 193801e04c3fSmrg struct blorp_batch batch; 19397ec681f3Smrg anv_blorp_batch_init(cmd_buffer, &batch, 19407ec681f3Smrg BLORP_BATCH_PREDICATE_ENABLE * predicate + 19417ec681f3Smrg BLORP_BATCH_NO_UPDATE_CLEAR_COLOR * !clear_value); 19427ec681f3Smrg assert((batch.flags & BLORP_BATCH_USE_COMPUTE) == 0); 194301e04c3fSmrg 194401e04c3fSmrg struct blorp_surf surf; 194501e04c3fSmrg get_blorp_surf_for_anv_image(cmd_buffer->device, image, aspect, 19467ec681f3Smrg 0, ANV_IMAGE_LAYOUT_EXPLICIT_AUX, 19477ec681f3Smrg image->planes[plane].aux_usage, 194801e04c3fSmrg &surf); 194901e04c3fSmrg 19507ec681f3Smrg uint32_t level_width = anv_minify(surf.surf->logical_level0_px.w, level); 19517ec681f3Smrg uint32_t level_height = anv_minify(surf.surf->logical_level0_px.h, level); 19527ec681f3Smrg 195301e04c3fSmrg /* Blorp will store the clear color for us if we provide the clear color 195401e04c3fSmrg * address and we are doing a fast clear. So we save the clear value into 19557ec681f3Smrg * the blorp surface. 195601e04c3fSmrg */ 19577ec681f3Smrg if (clear_value) 19587ec681f3Smrg surf.clear_color = *clear_value; 195901e04c3fSmrg 196001e04c3fSmrg /* From the Sky Lake PRM Vol. 7, "Render Target Fast Clear": 196101e04c3fSmrg * 196201e04c3fSmrg * "After Render target fast clear, pipe-control with color cache 196301e04c3fSmrg * write-flush must be issued before sending any DRAW commands on 196401e04c3fSmrg * that render target." 196501e04c3fSmrg * 196601e04c3fSmrg * This comment is a bit cryptic and doesn't really tell you what's going 196701e04c3fSmrg * or what's really needed. It appears that fast clear ops are not 196801e04c3fSmrg * properly synchronized with other drawing. This means that we cannot 196901e04c3fSmrg * have a fast clear operation in the pipe at the same time as other 197001e04c3fSmrg * regular drawing operations. We need to use a PIPE_CONTROL to ensure 197101e04c3fSmrg * that the contents of the previous draw hit the render target before we 197201e04c3fSmrg * resolve and then use a second PIPE_CONTROL after the resolve to ensure 197301e04c3fSmrg * that it is completed before any additional drawing occurs. 197401e04c3fSmrg */ 19757ec681f3Smrg anv_add_pending_pipe_bits(cmd_buffer, 19767ec681f3Smrg ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | 19777ec681f3Smrg ANV_PIPE_TILE_CACHE_FLUSH_BIT | 19787ec681f3Smrg ANV_PIPE_END_OF_PIPE_SYNC_BIT, 19797ec681f3Smrg "before fast clear ccs"); 198001e04c3fSmrg 198101e04c3fSmrg switch (ccs_op) { 198201e04c3fSmrg case ISL_AUX_OP_FAST_CLEAR: 19837ec681f3Smrg blorp_fast_clear(&batch, &surf, format, swizzle, 198401e04c3fSmrg level, base_layer, layer_count, 198501e04c3fSmrg 0, 0, level_width, level_height); 198601e04c3fSmrg break; 198701e04c3fSmrg case ISL_AUX_OP_FULL_RESOLVE: 198801e04c3fSmrg case ISL_AUX_OP_PARTIAL_RESOLVE: 198901e04c3fSmrg blorp_ccs_resolve(&batch, &surf, level, base_layer, layer_count, 199001e04c3fSmrg format, ccs_op); 199101e04c3fSmrg break; 199201e04c3fSmrg case ISL_AUX_OP_AMBIGUATE: 199301e04c3fSmrg for (uint32_t a = 0; a < layer_count; a++) { 199401e04c3fSmrg const uint32_t layer = base_layer + a; 199501e04c3fSmrg blorp_ccs_ambiguate(&batch, &surf, level, layer); 199601e04c3fSmrg } 199701e04c3fSmrg break; 199801e04c3fSmrg default: 199901e04c3fSmrg unreachable("Unsupported CCS operation"); 200001e04c3fSmrg } 200101e04c3fSmrg 20027ec681f3Smrg anv_add_pending_pipe_bits(cmd_buffer, 20037ec681f3Smrg ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | 20047ec681f3Smrg ANV_PIPE_END_OF_PIPE_SYNC_BIT, 20057ec681f3Smrg "after fast clear ccs"); 200601e04c3fSmrg 20077ec681f3Smrg anv_blorp_batch_finish(&batch); 200801e04c3fSmrg} 2009