This fixes 104 of the new image_clearing and copy_and_blit Vulkan CTS tests.
Signed-off-by: Jason Ekstrand <ja...@jlekstrand.net> Cc: "12.0" <mesa-sta...@lists.freedesktop.org> --- src/intel/vulkan/anv_meta_blit2d.c | 210 ++++++++++++++++++++++++++++++++++++- 1 file changed, 208 insertions(+), 2 deletions(-) diff --git a/src/intel/vulkan/anv_meta_blit2d.c b/src/intel/vulkan/anv_meta_blit2d.c index 30bc6ed..cb3548b 100644 --- a/src/intel/vulkan/anv_meta_blit2d.c +++ b/src/intel/vulkan/anv_meta_blit2d.c @@ -92,6 +92,21 @@ vk_format_for_size(int bs) } } +/* This function returns the format corresponding to a single component of the + * RGB format for the given size returned by vk_format_for_size(). + */ +static VkFormat +vk_single_component_format_for_rgb_size(int bs) +{ + switch (bs) { + case 3: return VK_FORMAT_R8_UNORM; + case 6: return VK_FORMAT_R16_UNORM; + case 12: return VK_FORMAT_R32_UINT; + default: + unreachable("Invalid format block size"); + } +} + static void create_iview(struct anv_cmd_buffer *cmd_buffer, struct anv_meta_blit2d_surf *surf, @@ -663,6 +678,141 @@ anv_meta_blit2d_w_tiled_dst(struct anv_cmd_buffer *cmd_buffer, } } +static void +anv_meta_blit2d_rgb_dst(struct anv_cmd_buffer *cmd_buffer, + struct anv_meta_blit2d_surf *src, + enum blit2d_src_type src_type, + struct anv_meta_blit2d_surf *dst, + unsigned num_rects, + struct anv_meta_blit2d_rect *rects) +{ + struct anv_device *device = cmd_buffer->device; + + for (unsigned r = 0; r < num_rects; ++r) { + struct blit2d_src_temps src_temps; + blit2d_bind_src(cmd_buffer, src, src_type, &rects[r], &src_temps); + + assert(dst->bs % 3 == 0); + assert(dst->tiling == ISL_TILING_LINEAR); + + uint32_t offset; + isl_tiling_get_intratile_offset_el(&cmd_buffer->device->isl_dev, + dst->tiling, 1, dst->pitch, + rects[r].dst_x, rects[r].dst_y, + &offset, + &rects[r].dst_x, &rects[r].dst_y); + + /* A red surface three times as wide as the actual RGB destination */ + struct anv_meta_blit2d_surf dst_R = { + .bo = dst->bo, + .tiling = dst->tiling, + .base_offset = dst->base_offset, + .bs = dst->bs / 3, + .pitch = dst->pitch, + }; + + struct blit2d_dst_temps dst_temps; + blit2d_bind_dst(cmd_buffer, &dst_R, offset, + (rects[r].dst_x + rects[r].width) * 3, + rects[r].dst_y + rects[r].height, + vk_single_component_format_for_rgb_size(dst->bs), + &dst_temps); + + struct blit_vb_data { + float pos[2]; + float tex_coord[3]; + } *vb_data; + + unsigned vb_size = sizeof(struct anv_vue_header) + 3 * sizeof(*vb_data); + + struct anv_state vb_state = + anv_cmd_buffer_alloc_dynamic_state(cmd_buffer, vb_size, 16); + memset(vb_state.map, 0, sizeof(struct anv_vue_header)); + vb_data = vb_state.map + sizeof(struct anv_vue_header); + + vb_data[0] = (struct blit_vb_data) { + .pos = { + (rects[r].dst_x + rects[r].width) * 3, + rects[r].dst_y + rects[r].height, + }, + .tex_coord = { + (rects[r].src_x + rects[r].width) * 3, + rects[r].src_y + rects[r].height, + src->pitch, + }, + }; + + vb_data[1] = (struct blit_vb_data) { + .pos = { + rects[r].dst_x * 3, + rects[r].dst_y + rects[r].height, + }, + .tex_coord = { + rects[r].src_x * 3, + rects[r].src_y + rects[r].height, + src->pitch, + }, + }; + + vb_data[2] = (struct blit_vb_data) { + .pos = { + rects[r].dst_x * 3, + rects[r].dst_y, + }, + .tex_coord = { + rects[r].src_x * 3, + rects[r].src_y, + src->pitch, + }, + }; + + if (!device->info.has_llc) + anv_state_clflush(vb_state); + + struct anv_buffer vertex_buffer = { + .device = device, + .size = vb_size, + .bo = &device->dynamic_state_block_pool.bo, + .offset = vb_state.offset, + }; + + anv_CmdBindVertexBuffers(anv_cmd_buffer_to_handle(cmd_buffer), 0, 2, + (VkBuffer[]) { + anv_buffer_to_handle(&vertex_buffer), + anv_buffer_to_handle(&vertex_buffer) + }, + (VkDeviceSize[]) { + 0, + sizeof(struct anv_vue_header), + }); + + ANV_CALL(CmdBeginRenderPass)(anv_cmd_buffer_to_handle(cmd_buffer), + &(VkRenderPassBeginInfo) { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + .renderPass = device->meta_state.blit2d.render_pass, + .framebuffer = dst_temps.fb, + .renderArea = { + .offset = { rects[r].dst_x, rects[r].dst_y, }, + .extent = { rects[r].width, rects[r].height }, + }, + .clearValueCount = 0, + .pClearValues = NULL, + }, VK_SUBPASS_CONTENTS_INLINE); + + bind_pipeline(cmd_buffer, src_type, BLIT2D_DST_TYPE_RGB); + + ANV_CALL(CmdDraw)(anv_cmd_buffer_to_handle(cmd_buffer), 3, 1, 0, 0); + + ANV_CALL(CmdEndRenderPass)(anv_cmd_buffer_to_handle(cmd_buffer)); + + /* At the point where we emit the draw call, all data from the + * descriptor sets, etc. has been used. We are free to delete it. + */ + blit2d_unbind_src(cmd_buffer, src_type, &src_temps); + blit2d_unbind_dst(cmd_buffer, &dst_temps); + } +} + void anv_meta_blit2d(struct anv_cmd_buffer *cmd_buffer, struct anv_meta_blit2d_surf *src, @@ -682,7 +832,8 @@ anv_meta_blit2d(struct anv_cmd_buffer *cmd_buffer, num_rects, rects); return; } else if (dst->bs % 3 == 0) { - anv_finishme("Blitting to RGB destinations not yet supported"); + anv_meta_blit2d_rgb_dst(cmd_buffer, src, src_type, dst, + num_rects, rects); return; } else { assert(util_is_power_of_two(dst->bs)); @@ -808,6 +959,54 @@ build_nir_w_tiled_fetch(struct nir_builder *b, struct anv_device *device, } static nir_ssa_def * +build_nir_rgb_component_fetch(struct nir_builder *b, struct anv_device *device, + nir_ssa_def *tex_pos, nir_ssa_def *tex_pitch) +{ + /* Figure out which of the three RGB components we want */ + nir_ssa_def *comp = nir_umod(b, nir_channel(b, tex_pos, 0), + nir_imm_int(b, 3)); + /* Divide the x component of the position by 3 */ + tex_pos = nir_vec2(b, nir_udiv(b, nir_channel(b, tex_pos, 0), + nir_imm_int(b, 3)), + nir_channel(b, tex_pos, 1)); + + const struct glsl_type *sampler_type = + glsl_sampler_type(GLSL_SAMPLER_DIM_2D, false, false, GLSL_TYPE_FLOAT); + nir_variable *sampler = nir_variable_create(b->shader, nir_var_uniform, + sampler_type, "s_tex"); + sampler->data.descriptor_set = 0; + sampler->data.binding = 0; + + nir_tex_instr *tex = nir_tex_instr_create(b->shader, 2); + tex->sampler_dim = GLSL_SAMPLER_DIM_2D; + tex->op = nir_texop_txf; + tex->src[0].src_type = nir_tex_src_coord; + tex->src[0].src = nir_src_for_ssa(tex_pos); + tex->src[1].src_type = nir_tex_src_lod; + tex->src[1].src = nir_src_for_ssa(nir_imm_int(b, 0)); + tex->dest_type = nir_type_float; /* TODO */ + tex->is_array = false; + tex->coord_components = 2; + tex->texture = nir_deref_var_create(tex, sampler); + tex->sampler = NULL; + + nir_ssa_dest_init(&tex->instr, &tex->dest, 4, 32, "tex"); + nir_builder_instr_insert(b, &tex->instr); + + /* Select the given channel from the texelFetch result */ + nir_ssa_def *color_channel = + nir_bcsel(b, nir_ieq(b, comp, nir_imm_int(b, 0)), + nir_channel(b, &tex->dest.ssa, 0), + nir_bcsel(b, nir_ieq(b, comp, nir_imm_int(b, 1)), + nir_channel(b, &tex->dest.ssa, 1), + nir_channel(b, &tex->dest.ssa, 2))); + + /* The final color write needs 4 components */ + nir_ssa_def *undef = nir_ssa_undef(b, 1, 32); + return nir_vec4(b, color_channel, undef, undef, undef); +} + +static nir_ssa_def * build_nir_texel_fetch(struct nir_builder *b, struct anv_device *device, nir_ssa_def *tex_pos, nir_ssa_def *tex_pitch) { @@ -1111,7 +1310,14 @@ blit2d_init_pipeline(struct anv_device *device, vi_create_info = &w_tiled_vi_create_info; break; case BLIT2D_DST_TYPE_RGB: - /* Not yet supported */ + /* RGB destinations and W-detiling don't mix */ + if (src_type != BLIT2D_SRC_TYPE_NORMAL) + return VK_SUCCESS; + + fs.nir = build_nir_copy_fragment_shader(device, + build_nir_rgb_component_fetch); + vi_create_info = &normal_vi_create_info; + break; default: return VK_SUCCESS; } -- 2.5.0.400.gff86faf _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev