mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-09 21:20:14 +01:00
anv/blit2d: Add support for W-tiled destinations
Reviewed-by: Nanley Chery <nanley.g.chery@intel.com> Reviewed-by: Chad Versace <chad.versace@intel.com>
This commit is contained in:
parent
0a6842c1bd
commit
e3312644cb
1 changed files with 322 additions and 44 deletions
|
|
@ -514,6 +514,149 @@ anv_meta_blit2d_normal_dst(struct anv_cmd_buffer *cmd_buffer,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
anv_meta_blit2d_w_tiled_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 == 1);
|
||||
uint32_t offset;
|
||||
isl_tiling_get_intratile_offset_el(&cmd_buffer->device->isl_dev,
|
||||
ISL_TILING_W, 1, dst->pitch,
|
||||
rects[r].dst_x, rects[r].dst_y,
|
||||
&offset,
|
||||
&rects[r].dst_x, &rects[r].dst_y);
|
||||
|
||||
/* The original coordinates were in terms of an actual W-tiled offset
|
||||
* but we are binding this image as Y-tiled. We need to adjust our
|
||||
* rectangle accordingly.
|
||||
*/
|
||||
uint32_t xmin_Y, xmax_Y, ymin_Y, ymax_Y;
|
||||
xmin_Y = (rects[r].dst_x / 8) * 16;
|
||||
xmax_Y = DIV_ROUND_UP(rects[r].dst_x + rects[r].width, 8) * 16;
|
||||
ymin_Y = (rects[r].dst_y / 4) * 2;
|
||||
ymax_Y = DIV_ROUND_UP(rects[r].dst_y + rects[r].height, 4) * 2;
|
||||
|
||||
struct anv_meta_blit2d_surf dst_Y = {
|
||||
.bo = dst->bo,
|
||||
.tiling = ISL_TILING_Y0,
|
||||
.base_offset = dst->base_offset,
|
||||
.bs = 1,
|
||||
.pitch = dst->pitch * 2,
|
||||
};
|
||||
|
||||
struct blit2d_dst_temps dst_temps;
|
||||
blit2d_bind_dst(cmd_buffer, &dst_Y, offset, xmax_Y, ymax_Y, &dst_temps);
|
||||
|
||||
struct blit_vb_header {
|
||||
struct anv_vue_header vue;
|
||||
int32_t tex_offset[2];
|
||||
uint32_t tex_pitch;
|
||||
uint32_t bounds[4];
|
||||
} *vb_header;
|
||||
|
||||
struct blit_vb_data {
|
||||
float pos[2];
|
||||
} *vb_data;
|
||||
|
||||
unsigned vb_size = sizeof(*vb_header) + 3 * sizeof(*vb_data);
|
||||
|
||||
struct anv_state vb_state =
|
||||
anv_cmd_buffer_alloc_dynamic_state(cmd_buffer, vb_size, 16);
|
||||
vb_header = vb_state.map;
|
||||
|
||||
*vb_header = (struct blit_vb_header) {
|
||||
.tex_offset = {
|
||||
rects[r].src_x - rects[r].dst_x,
|
||||
rects[r].src_y - rects[r].dst_y,
|
||||
},
|
||||
.tex_pitch = src->pitch,
|
||||
.bounds = {
|
||||
rects[r].dst_x,
|
||||
rects[r].dst_y,
|
||||
rects[r].dst_x + rects[r].width,
|
||||
rects[r].dst_y + rects[r].height,
|
||||
},
|
||||
};
|
||||
|
||||
vb_data = (void *)(vb_header + 1);
|
||||
|
||||
vb_data[0] = (struct blit_vb_data) {
|
||||
.pos = {
|
||||
xmax_Y,
|
||||
ymax_Y,
|
||||
},
|
||||
};
|
||||
|
||||
vb_data[1] = (struct blit_vb_data) {
|
||||
.pos = {
|
||||
xmin_Y,
|
||||
ymax_Y,
|
||||
},
|
||||
};
|
||||
|
||||
vb_data[2] = (struct blit_vb_data) {
|
||||
.pos = {
|
||||
xmin_Y,
|
||||
ymin_Y,
|
||||
},
|
||||
};
|
||||
|
||||
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,
|
||||
(void *)vb_data - vb_state.map,
|
||||
});
|
||||
|
||||
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 = { xmin_Y, ymin_Y, },
|
||||
.extent = { xmax_Y - xmin_Y, ymax_Y - ymin_Y },
|
||||
},
|
||||
.clearValueCount = 0,
|
||||
.pClearValues = NULL,
|
||||
}, VK_SUBPASS_CONTENTS_INLINE);
|
||||
|
||||
bind_pipeline(cmd_buffer, src_type, BLIT2D_DST_TYPE_W_TILE);
|
||||
|
||||
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,
|
||||
|
|
@ -529,8 +672,8 @@ anv_meta_blit2d(struct anv_cmd_buffer *cmd_buffer,
|
|||
}
|
||||
|
||||
if (dst->tiling == ISL_TILING_W) {
|
||||
assert(dst->bs == 1);
|
||||
anv_finishme("Blitting to w-tiled destinations not yet supported");
|
||||
anv_meta_blit2d_w_tiled_dst(cmd_buffer, src, src_type, dst,
|
||||
num_rects, rects);
|
||||
return;
|
||||
} else if (dst->bs % 3 == 0) {
|
||||
anv_finishme("Blitting to RGB destinations not yet supported");
|
||||
|
|
@ -688,6 +831,47 @@ build_nir_texel_fetch(struct nir_builder *b, struct anv_device *device,
|
|||
return &tex->dest.ssa;
|
||||
}
|
||||
|
||||
static const VkPipelineVertexInputStateCreateInfo normal_vi_create_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||
.vertexBindingDescriptionCount = 2,
|
||||
.pVertexBindingDescriptions = (VkVertexInputBindingDescription[]) {
|
||||
{
|
||||
.binding = 0,
|
||||
.stride = 0,
|
||||
.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE
|
||||
},
|
||||
{
|
||||
.binding = 1,
|
||||
.stride = 5 * sizeof(float),
|
||||
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX
|
||||
},
|
||||
},
|
||||
.vertexAttributeDescriptionCount = 3,
|
||||
.pVertexAttributeDescriptions = (VkVertexInputAttributeDescription[]) {
|
||||
{
|
||||
/* VUE Header */
|
||||
.location = 0,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32A32_UINT,
|
||||
.offset = 0
|
||||
},
|
||||
{
|
||||
/* Position */
|
||||
.location = 1,
|
||||
.binding = 1,
|
||||
.format = VK_FORMAT_R32G32_SFLOAT,
|
||||
.offset = 0
|
||||
},
|
||||
{
|
||||
/* Texture Coordinate */
|
||||
.location = 2,
|
||||
.binding = 1,
|
||||
.format = VK_FORMAT_R32G32B32_SFLOAT,
|
||||
.offset = 8
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static nir_shader *
|
||||
build_nir_copy_fragment_shader(struct anv_device *device,
|
||||
texel_fetch_build_func txf_func)
|
||||
|
|
@ -718,6 +902,136 @@ build_nir_copy_fragment_shader(struct anv_device *device,
|
|||
return b.shader;
|
||||
}
|
||||
|
||||
static const VkPipelineVertexInputStateCreateInfo w_tiled_vi_create_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||
.vertexBindingDescriptionCount = 2,
|
||||
.pVertexBindingDescriptions = (VkVertexInputBindingDescription[]) {
|
||||
{
|
||||
.binding = 0,
|
||||
.stride = 0,
|
||||
.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE
|
||||
},
|
||||
{
|
||||
.binding = 1,
|
||||
.stride = 2 * sizeof(float),
|
||||
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX
|
||||
},
|
||||
},
|
||||
.vertexAttributeDescriptionCount = 4,
|
||||
.pVertexAttributeDescriptions = (VkVertexInputAttributeDescription[]) {
|
||||
{
|
||||
/* VUE Header */
|
||||
.location = 0,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32A32_UINT,
|
||||
.offset = 0
|
||||
},
|
||||
{
|
||||
/* Position */
|
||||
.location = 1,
|
||||
.binding = 1,
|
||||
.format = VK_FORMAT_R32G32_SFLOAT,
|
||||
.offset = 0
|
||||
},
|
||||
{
|
||||
/* Texture Offset */
|
||||
.location = 2,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32_UINT,
|
||||
.offset = 16
|
||||
},
|
||||
{
|
||||
/* Destination bounds */
|
||||
.location = 3,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32A32_UINT,
|
||||
.offset = 28
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static nir_shader *
|
||||
build_nir_w_tiled_fragment_shader(struct anv_device *device,
|
||||
texel_fetch_build_func txf_func)
|
||||
{
|
||||
const struct glsl_type *vec4 = glsl_vec4_type();
|
||||
const struct glsl_type *ivec3 = glsl_vector_type(GLSL_TYPE_INT, 3);
|
||||
const struct glsl_type *uvec4 = glsl_vector_type(GLSL_TYPE_UINT, 4);
|
||||
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");
|
||||
|
||||
/* We need gl_FragCoord so we know our Y-tiled 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;
|
||||
|
||||
/* In location 0 we have an ivec3 that has the offset from dest to
|
||||
* source in the first two components and the stride in the third.
|
||||
*/
|
||||
nir_variable *tex_off_in = nir_variable_create(b.shader, nir_var_shader_in,
|
||||
ivec3, "v_tex_off");
|
||||
tex_off_in->data.location = VARYING_SLOT_VAR0;
|
||||
tex_off_in->data.interpolation = INTERP_QUALIFIER_FLAT;
|
||||
|
||||
/* In location 1 we have a uvec4 that gives us the bounds of the
|
||||
* destination. We need to discard if we get outside this boundary.
|
||||
*/
|
||||
nir_variable *bounds_in = nir_variable_create(b.shader, nir_var_shader_in,
|
||||
uvec4, "v_bounds");
|
||||
bounds_in->data.location = VARYING_SLOT_VAR1;
|
||||
bounds_in->data.interpolation = INTERP_QUALIFIER_FLAT;
|
||||
|
||||
nir_variable *color_out = nir_variable_create(b.shader, nir_var_shader_out,
|
||||
vec4, "f_color");
|
||||
color_out->data.location = FRAG_RESULT_DATA0;
|
||||
|
||||
nir_ssa_def *frag_coord_int = nir_f2i(&b, nir_load_var(&b, frag_coord_in));
|
||||
nir_ssa_def *x_Y = nir_channel(&b, frag_coord_int, 0);
|
||||
nir_ssa_def *y_Y = nir_channel(&b, frag_coord_int, 1);
|
||||
|
||||
/* Compute the W-tiled position from the Y-tiled position */
|
||||
nir_ssa_def *x_W = nir_iand(&b, x_Y, nir_imm_int(&b, 0xffffff80));
|
||||
x_W = nir_ushr(&b, x_W, nir_imm_int(&b, 1));
|
||||
x_W = nir_copy_bits(&b, x_W, 0, x_Y, 0, 1);
|
||||
x_W = nir_copy_bits(&b, x_W, 1, x_Y, 2, 1);
|
||||
x_W = nir_copy_bits(&b, x_W, 2, y_Y, 0, 1);
|
||||
x_W = nir_copy_bits(&b, x_W, 3, x_Y, 4, 3);
|
||||
|
||||
nir_ssa_def *y_W = nir_iand(&b, y_Y, nir_imm_int(&b, 0xffffffe0));
|
||||
y_W = nir_ishl(&b, y_W, nir_imm_int(&b, 1));
|
||||
y_W = nir_copy_bits(&b, y_W, 0, x_Y, 1, 1);
|
||||
y_W = nir_copy_bits(&b, y_W, 1, x_Y, 3, 1);
|
||||
y_W = nir_copy_bits(&b, y_W, 2, y_Y, 1, 4);
|
||||
|
||||
/* Figure out if we are out-of-bounds and discard */
|
||||
nir_ssa_def *bounds = nir_load_var(&b, bounds_in);
|
||||
nir_ssa_def *oob =
|
||||
nir_ior(&b, nir_ult(&b, x_W, nir_channel(&b, bounds, 0)),
|
||||
nir_ior(&b, nir_ult(&b, y_W, nir_channel(&b, bounds, 1)),
|
||||
nir_ior(&b, nir_uge(&b, x_W, nir_channel(&b, bounds, 2)),
|
||||
nir_uge(&b, y_W, nir_channel(&b, bounds, 3)))));
|
||||
|
||||
nir_intrinsic_instr *discard =
|
||||
nir_intrinsic_instr_create(b.shader, nir_intrinsic_discard_if);
|
||||
discard->src[0] = nir_src_for_ssa(oob);
|
||||
nir_builder_instr_insert(&b, &discard->instr);
|
||||
|
||||
unsigned swiz[4] = { 0, 1, 0, 0 };
|
||||
nir_ssa_def *tex_off =
|
||||
nir_swizzle(&b, nir_load_var(&b, tex_off_in), swiz, 2, false);
|
||||
nir_ssa_def *tex_pos = nir_iadd(&b, nir_vec2(&b, x_W, y_W), tex_off);
|
||||
nir_ssa_def *tex_pitch = nir_channel(&b, nir_load_var(&b, tex_off_in), 2);
|
||||
|
||||
nir_ssa_def *color = txf_func(&b, device, tex_pos, tex_pitch);
|
||||
nir_store_var(&b, color_out, color, 0xf);
|
||||
|
||||
return b.shader;
|
||||
}
|
||||
|
||||
void
|
||||
anv_device_finish_meta_blit2d_state(struct anv_device *device)
|
||||
{
|
||||
|
|
@ -781,12 +1095,17 @@ blit2d_init_pipeline(struct anv_device *device,
|
|||
unreachable("Invalid blit2d source type");
|
||||
}
|
||||
|
||||
const VkPipelineVertexInputStateCreateInfo *vi_create_info;
|
||||
struct anv_shader_module fs = { .nir = NULL };
|
||||
switch (dst_type) {
|
||||
case BLIT2D_DST_TYPE_NORMAL:
|
||||
fs.nir = build_nir_copy_fragment_shader(device, src_func);
|
||||
vi_create_info = &normal_vi_create_info;
|
||||
break;
|
||||
case BLIT2D_DST_TYPE_W_TILE:
|
||||
fs.nir = build_nir_w_tiled_fragment_shader(device, src_func);
|
||||
vi_create_info = &w_tiled_vi_create_info;
|
||||
break;
|
||||
case BLIT2D_DST_TYPE_RGB:
|
||||
/* Not yet supported */
|
||||
default:
|
||||
|
|
@ -802,47 +1121,6 @@ blit2d_init_pipeline(struct anv_device *device,
|
|||
.nir = build_nir_vertex_shader(),
|
||||
};
|
||||
|
||||
VkPipelineVertexInputStateCreateInfo vi_create_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||
.vertexBindingDescriptionCount = 2,
|
||||
.pVertexBindingDescriptions = (VkVertexInputBindingDescription[]) {
|
||||
{
|
||||
.binding = 0,
|
||||
.stride = 0,
|
||||
.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE
|
||||
},
|
||||
{
|
||||
.binding = 1,
|
||||
.stride = 5 * sizeof(float),
|
||||
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX
|
||||
},
|
||||
},
|
||||
.vertexAttributeDescriptionCount = 3,
|
||||
.pVertexAttributeDescriptions = (VkVertexInputAttributeDescription[]) {
|
||||
{
|
||||
/* VUE Header */
|
||||
.location = 0,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32A32_UINT,
|
||||
.offset = 0
|
||||
},
|
||||
{
|
||||
/* Position */
|
||||
.location = 1,
|
||||
.binding = 1,
|
||||
.format = VK_FORMAT_R32G32_SFLOAT,
|
||||
.offset = 0
|
||||
},
|
||||
{
|
||||
/* Texture Coordinate */
|
||||
.location = 2,
|
||||
.binding = 1,
|
||||
.format = VK_FORMAT_R32G32B32_SFLOAT,
|
||||
.offset = 8
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
VkPipelineShaderStageCreateInfo pipeline_shader_stages[] = {
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||
|
|
@ -863,7 +1141,7 @@ blit2d_init_pipeline(struct anv_device *device,
|
|||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||
.stageCount = ARRAY_SIZE(pipeline_shader_stages),
|
||||
.pStages = pipeline_shader_stages,
|
||||
.pVertexInputState = &vi_create_info,
|
||||
.pVertexInputState = vi_create_info,
|
||||
.pInputAssemblyState = &(VkPipelineInputAssemblyStateCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
||||
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue