[Mesa-dev] [PATCH 2/2] anv/blit2d: Add support for RGB destinations
Jason Ekstrand
jason at jlekstrand.net
Tue Aug 2 17:00:30 UTC 2016
This fixes 104 of the new image_clearing and copy_and_blit Vulkan CTS
tests.
Signed-off-by: Jason Ekstrand <jason at jlekstrand.net>
Cc: "12.0" <mesa-stable at 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
More information about the mesa-dev
mailing list