+ nir_builder_instr_insert(b, &tex->instr);
+
+ 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)
+{
+ 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;
+
+ 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);
+ nir_store_var(&b, color_out, color, 0xf);
+
+ 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;