mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-09 04:38:03 +02:00
anv/blit2d: Add support for RGB destinations
This fixes 104 of the new image_clearing and copy_and_blit Vulkan CTS tests. Signed-off-by: Jason Ekstrand <jason@jlekstrand.net> Cc: "12.0" <mesa-stable@lists.freedesktop.org>
This commit is contained in:
parent
16ddda8452
commit
cf3cf2ecfc
1 changed files with 214 additions and 2 deletions
|
|
@ -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
|
static void
|
||||||
create_iview(struct anv_cmd_buffer *cmd_buffer,
|
create_iview(struct anv_cmd_buffer *cmd_buffer,
|
||||||
struct anv_meta_blit2d_surf *surf,
|
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,
|
||||||
|
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,
|
||||||
|
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,
|
||||||
|
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
|
void
|
||||||
anv_meta_blit2d(struct anv_cmd_buffer *cmd_buffer,
|
anv_meta_blit2d(struct anv_cmd_buffer *cmd_buffer,
|
||||||
struct anv_meta_blit2d_surf *src,
|
struct anv_meta_blit2d_surf *src,
|
||||||
|
|
@ -682,7 +832,8 @@ anv_meta_blit2d(struct anv_cmd_buffer *cmd_buffer,
|
||||||
num_rects, rects);
|
num_rects, rects);
|
||||||
return;
|
return;
|
||||||
} else if (dst->bs % 3 == 0) {
|
} 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;
|
return;
|
||||||
} else {
|
} else {
|
||||||
assert(util_is_power_of_two(dst->bs));
|
assert(util_is_power_of_two(dst->bs));
|
||||||
|
|
@ -908,6 +1059,61 @@ build_nir_copy_fragment_shader(struct anv_device *device,
|
||||||
return b.shader;
|
return b.shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* RGB copies have the same interface as normal copies */
|
||||||
|
#define rgb_vi_create_info normal_vi_create_info
|
||||||
|
|
||||||
|
static nir_shader *
|
||||||
|
build_nir_rgb_fragment_shader(struct anv_device *device,
|
||||||
|
texel_fetch_build_func txf_func)
|
||||||
|
{
|
||||||
|
const struct glsl_type *vec4 = glsl_vec4_type();
|
||||||
|
const struct glsl_type *vec3 = glsl_vector_type(GLSL_TYPE_FLOAT, 3);
|
||||||
|
nir_builder b;
|
||||||
|
|
||||||
|
nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_FRAGMENT, NULL);
|
||||||
|
b.shader->info.name = ralloc_strdup(b.shader, "meta_blit2d_fs");
|
||||||
|
|
||||||
|
nir_variable *tex_pos_in = nir_variable_create(b.shader, nir_var_shader_in,
|
||||||
|
vec3, "v_tex_pos");
|
||||||
|
tex_pos_in->data.location = VARYING_SLOT_VAR0;
|
||||||
|
|
||||||
|
nir_variable *color_out = nir_variable_create(b.shader, nir_var_shader_out,
|
||||||
|
vec4, "f_color");
|
||||||
|
color_out->data.location = FRAG_RESULT_DATA0;
|
||||||
|
|
||||||
|
/* We need gl_FragCoord so we know our position */
|
||||||
|
nir_variable *frag_coord_in = nir_variable_create(b.shader,
|
||||||
|
nir_var_shader_in,
|
||||||
|
vec4, "gl_FragCoord");
|
||||||
|
frag_coord_in->data.location = VARYING_SLOT_POS;
|
||||||
|
frag_coord_in->data.origin_upper_left = true;
|
||||||
|
|
||||||
|
nir_ssa_def *pos_int = nir_f2i(&b, nir_load_var(&b, tex_pos_in));
|
||||||
|
unsigned swiz[4] = { 0, 1 };
|
||||||
|
nir_ssa_def *tex_pos = nir_swizzle(&b, pos_int, swiz, 2, false);
|
||||||
|
nir_ssa_def *tex_pitch = nir_channel(&b, pos_int, 2);
|
||||||
|
|
||||||
|
nir_ssa_def *color = txf_func(&b, device, tex_pos, tex_pitch);
|
||||||
|
|
||||||
|
/* We figure out which component we are by the x component of FragCoord */
|
||||||
|
nir_ssa_def *frag_coord_int = nir_f2i(&b, nir_load_var(&b, frag_coord_in));
|
||||||
|
nir_ssa_def *comp = nir_umod(&b, nir_channel(&b, frag_coord_int, 0),
|
||||||
|
nir_imm_int(&b, 3));
|
||||||
|
|
||||||
|
/* 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, color, 0),
|
||||||
|
nir_bcsel(&b, nir_ieq(&b, comp, nir_imm_int(&b, 1)),
|
||||||
|
nir_channel(&b, color, 1),
|
||||||
|
nir_channel(&b, color, 2)));
|
||||||
|
|
||||||
|
nir_ssa_def *u = nir_ssa_undef(&b, 1, 32);
|
||||||
|
nir_store_var(&b, color_out, nir_vec4(&b, color_channel, u, u, u), 0x1);
|
||||||
|
|
||||||
|
return b.shader;
|
||||||
|
}
|
||||||
|
|
||||||
static const VkPipelineVertexInputStateCreateInfo w_tiled_vi_create_info = {
|
static const VkPipelineVertexInputStateCreateInfo w_tiled_vi_create_info = {
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||||
.vertexBindingDescriptionCount = 2,
|
.vertexBindingDescriptionCount = 2,
|
||||||
|
|
@ -1111,7 +1317,13 @@ blit2d_init_pipeline(struct anv_device *device,
|
||||||
vi_create_info = &w_tiled_vi_create_info;
|
vi_create_info = &w_tiled_vi_create_info;
|
||||||
break;
|
break;
|
||||||
case BLIT2D_DST_TYPE_RGB:
|
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_rgb_fragment_shader(device, src_func);
|
||||||
|
vi_create_info = &rgb_vi_create_info;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue