X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fintel%2Fvulkan%2Fanv_meta_blit2d.c;h=06e104329527e77b80bb78d08482a11fc060f045;hb=fef08af99c7e83f100a5ae25f2798131c278d841;hp=cf2dc66597d5cd185cfd320d2fc5ebc5b0625b15;hpb=b37502b9832f02626b0caca22500b46ebbbe8007;p=mesa.git diff --git a/src/intel/vulkan/anv_meta_blit2d.c b/src/intel/vulkan/anv_meta_blit2d.c index cf2dc66597d..06e10432952 100644 --- a/src/intel/vulkan/anv_meta_blit2d.c +++ b/src/intel/vulkan/anv_meta_blit2d.c @@ -95,29 +95,20 @@ vk_format_for_size(int bs) static void create_iview(struct anv_cmd_buffer *cmd_buffer, struct anv_meta_blit2d_surf *surf, - struct anv_meta_blit2d_rect *rect, + uint64_t offset, VkImageUsageFlags usage, + uint32_t width, + uint32_t height, VkImage *img, struct anv_image_view *iview) { - struct isl_tile_info tile_info; - isl_tiling_get_info(&cmd_buffer->device->isl_dev, - surf->tiling, surf->bs, &tile_info); - const unsigned tile_width_px = tile_info.width > surf->bs ? - tile_info.width / surf->bs : 1; - uint32_t *rect_y = (usage == VK_IMAGE_USAGE_SAMPLED_BIT) ? - &rect->src_y : &rect->dst_y; - uint32_t *rect_x = (usage == VK_IMAGE_USAGE_SAMPLED_BIT) ? - &rect->src_x : &rect->dst_x; - - /* Define the shared state among all created image views */ const VkImageCreateInfo image_info = { .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .imageType = VK_IMAGE_TYPE_2D, .format = vk_format_for_size(surf->bs), .extent = { - .width = rect->width + (*rect_x) % tile_width_px, - .height = rect->height + (*rect_y) % tile_info.height, + .width = width, + .height = height, .depth = 1, }, .mipLevels = 1, @@ -140,19 +131,7 @@ create_iview(struct anv_cmd_buffer *cmd_buffer, * creating a dummy memory object etc. so there's really no point. */ anv_image_from_handle(*img)->bo = surf->bo; - anv_image_from_handle(*img)->offset = surf->base_offset; - - /* Create a VkImageView that starts at the tile aligned offset closest - * to the provided x/y offset into the surface. - */ - struct isl_surf *isl_surf = &anv_image_from_handle(*img)->color_surface.isl; - - uint32_t img_o = 0; - isl_tiling_get_intratile_offset_el(&cmd_buffer->device->isl_dev, - isl_surf->tiling, surf->bs, - isl_surf->row_pitch, - *rect_x * surf->bs, *rect_y, - &img_o, rect_x, rect_y); + anv_image_from_handle(*img)->offset = surf->base_offset + offset; anv_image_view_init(iview, cmd_buffer->device, &(VkImageViewCreateInfo) { @@ -167,12 +146,16 @@ create_iview(struct anv_cmd_buffer *cmd_buffer, .baseArrayLayer = 0, .layerCount = 1 }, - }, cmd_buffer, img_o, usage); + }, cmd_buffer, usage); } struct blit2d_src_temps { VkImage image; struct anv_image_view iview; + + struct anv_buffer buffer; + struct anv_buffer_view bview; + VkDescriptorPool desc_pool; VkDescriptorSet set; }; @@ -187,56 +170,137 @@ blit2d_bind_src(struct anv_cmd_buffer *cmd_buffer, struct anv_device *device = cmd_buffer->device; VkDevice vk_device = anv_device_to_handle(cmd_buffer->device); - create_iview(cmd_buffer, src, rect, VK_IMAGE_USAGE_SAMPLED_BIT, - &tmp->image, &tmp->iview); - - anv_CreateDescriptorPool(vk_device, - &(const VkDescriptorPoolCreateInfo) { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - .pNext = NULL, - .flags = 0, - .maxSets = 1, - .poolSizeCount = 1, - .pPoolSizes = (VkDescriptorPoolSize[]) { + if (src_type == BLIT2D_SRC_TYPE_NORMAL) { + uint32_t offset = 0; + isl_tiling_get_intratile_offset_el(&cmd_buffer->device->isl_dev, + src->tiling, src->bs, src->pitch, + rect->src_x, rect->src_y, + &offset, &rect->src_x, &rect->src_y); + + create_iview(cmd_buffer, src, offset, VK_IMAGE_USAGE_SAMPLED_BIT, + rect->src_x + rect->width, rect->src_y + rect->height, + &tmp->image, &tmp->iview); + + anv_CreateDescriptorPool(vk_device, + &(const VkDescriptorPoolCreateInfo) { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + .pNext = NULL, + .flags = 0, + .maxSets = 1, + .poolSizeCount = 1, + .pPoolSizes = (VkDescriptorPoolSize[]) { + { + .type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + .descriptorCount = 1 + }, + } + }, &cmd_buffer->pool->alloc, &tmp->desc_pool); + + anv_AllocateDescriptorSets(vk_device, + &(VkDescriptorSetAllocateInfo) { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, + .descriptorPool = tmp->desc_pool, + .descriptorSetCount = 1, + .pSetLayouts = &device->meta_state.blit2d.img_ds_layout + }, &tmp->set); + + anv_UpdateDescriptorSets(vk_device, + 1, /* writeCount */ + (VkWriteDescriptorSet[]) { { - .type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, - .descriptorCount = 1 - }, - } - }, &cmd_buffer->pool->alloc, &tmp->desc_pool); - - anv_AllocateDescriptorSets(vk_device, - &(VkDescriptorSetAllocateInfo) { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, - .descriptorPool = tmp->desc_pool, - .descriptorSetCount = 1, - .pSetLayouts = &device->meta_state.blit2d.img_ds_layout - }, &tmp->set); - - anv_UpdateDescriptorSets(vk_device, - 1, /* writeCount */ - (VkWriteDescriptorSet[]) { - { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = tmp->set, - .dstBinding = 0, - .dstArrayElement = 0, - .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, - .pImageInfo = (VkDescriptorImageInfo[]) { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = tmp->set, + .dstBinding = 0, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + .pImageInfo = (VkDescriptorImageInfo[]) { + { + .sampler = NULL, + .imageView = anv_image_view_to_handle(&tmp->iview), + .imageLayout = VK_IMAGE_LAYOUT_GENERAL, + }, + } + } + }, 0, NULL); + + anv_CmdBindDescriptorSets(anv_cmd_buffer_to_handle(cmd_buffer), + VK_PIPELINE_BIND_POINT_GRAPHICS, + device->meta_state.blit2d.img_p_layout, 0, 1, + &tmp->set, 0, NULL); + } else { + assert(src_type == BLIT2D_SRC_TYPE_W_DETILE); + assert(src->tiling == ISL_TILING_W); + assert(src->bs == 1); + + uint32_t tile_offset = 0; + isl_tiling_get_intratile_offset_el(&cmd_buffer->device->isl_dev, + ISL_TILING_W, 1, src->pitch, + rect->src_x, rect->src_y, + &tile_offset, + &rect->src_x, &rect->src_y); + + tmp->buffer = (struct anv_buffer) { + .device = device, + .size = align_u32(rect->src_y + rect->height, 64) * src->pitch, + .usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, + .bo = src->bo, + .offset = src->base_offset + tile_offset, + }; + + anv_buffer_view_init(&tmp->bview, device, + &(VkBufferViewCreateInfo) { + .sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, + .buffer = anv_buffer_to_handle(&tmp->buffer), + .format = VK_FORMAT_R8_UINT, + .offset = 0, + .range = VK_WHOLE_SIZE, + }, cmd_buffer); + + anv_CreateDescriptorPool(vk_device, + &(const VkDescriptorPoolCreateInfo) { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + .pNext = NULL, + .flags = 0, + .maxSets = 1, + .poolSizeCount = 1, + .pPoolSizes = (VkDescriptorPoolSize[]) { { - .sampler = NULL, - .imageView = anv_image_view_to_handle(&tmp->iview), - .imageLayout = VK_IMAGE_LAYOUT_GENERAL, + .type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + .descriptorCount = 1 }, } - } - }, 0, NULL); + }, &cmd_buffer->pool->alloc, &tmp->desc_pool); + + anv_AllocateDescriptorSets(vk_device, + &(VkDescriptorSetAllocateInfo) { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, + .descriptorPool = tmp->desc_pool, + .descriptorSetCount = 1, + .pSetLayouts = &device->meta_state.blit2d.buf_ds_layout + }, &tmp->set); + + anv_UpdateDescriptorSets(vk_device, + 1, /* writeCount */ + (VkWriteDescriptorSet[]) { + { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = tmp->set, + .dstBinding = 0, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + .pTexelBufferView = (VkBufferView[]) { + anv_buffer_view_to_handle(&tmp->bview), + }, + } + }, 0, NULL); - anv_CmdBindDescriptorSets(anv_cmd_buffer_to_handle(cmd_buffer), - VK_PIPELINE_BIND_POINT_GRAPHICS, - device->meta_state.blit2d.img_p_layout, 0, 1, - &tmp->set, 0, NULL); + anv_CmdBindDescriptorSets(anv_cmd_buffer_to_handle(cmd_buffer), + VK_PIPELINE_BIND_POINT_GRAPHICS, + device->meta_state.blit2d.buf_p_layout, 0, 1, + &tmp->set, 0, NULL); + } } static void @@ -246,8 +310,49 @@ blit2d_unbind_src(struct anv_cmd_buffer *cmd_buffer, { anv_DestroyDescriptorPool(anv_device_to_handle(cmd_buffer->device), tmp->desc_pool, &cmd_buffer->pool->alloc); - anv_DestroyImage(anv_device_to_handle(cmd_buffer->device), - tmp->image, &cmd_buffer->pool->alloc); + if (src_type == BLIT2D_SRC_TYPE_NORMAL) { + anv_DestroyImage(anv_device_to_handle(cmd_buffer->device), + tmp->image, &cmd_buffer->pool->alloc); + } +} + +struct blit2d_dst_temps { + VkImage image; + struct anv_image_view iview; + VkFramebuffer fb; +}; + +static void +blit2d_bind_dst(struct anv_cmd_buffer *cmd_buffer, + struct anv_meta_blit2d_surf *dst, + uint64_t offset, + uint32_t width, + uint32_t height, + struct blit2d_dst_temps *tmp) +{ + create_iview(cmd_buffer, dst, offset, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + width, height, &tmp->image, &tmp->iview); + + anv_CreateFramebuffer(anv_device_to_handle(cmd_buffer->device), + &(VkFramebufferCreateInfo) { + .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, + .attachmentCount = 1, + .pAttachments = (VkImageView[]) { + anv_image_view_to_handle(&tmp->iview), + }, + .width = width, + .height = height, + .layers = 1 + }, &cmd_buffer->pool->alloc, &tmp->fb); +} + +static void +blit2d_unbind_dst(struct anv_cmd_buffer *cmd_buffer, + struct blit2d_dst_temps *tmp) +{ + VkDevice vk_device = anv_device_to_handle(cmd_buffer->device); + anv_DestroyFramebuffer(vk_device, tmp->fb, &cmd_buffer->pool->alloc); + anv_DestroyImage(vk_device, tmp->image, &cmd_buffer->pool->alloc); } void @@ -261,8 +366,7 @@ void anv_meta_begin_blit2d(struct anv_cmd_buffer *cmd_buffer, struct anv_meta_saved_state *save) { - anv_meta_save(save, cmd_buffer, - (1 << VK_DYNAMIC_STATE_VIEWPORT)); + anv_meta_save(save, cmd_buffer, 0); } static void @@ -288,16 +392,21 @@ anv_meta_blit2d_normal_dst(struct anv_cmd_buffer *cmd_buffer, struct anv_meta_blit2d_rect *rects) { struct anv_device *device = cmd_buffer->device; - VkDevice vk_device = anv_device_to_handle(cmd_buffer->device); - VkImageUsageFlags dst_usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 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); - VkImage dst_img; - struct anv_image_view dst_iview; - create_iview(cmd_buffer, dst, &rects[r], dst_usage, &dst_img, &dst_iview); + uint32_t offset = 0; + isl_tiling_get_intratile_offset_el(&cmd_buffer->device->isl_dev, + dst->tiling, dst->bs, dst->pitch, + rects[r].dst_x, rects[r].dst_y, + &offset, + &rects[r].dst_x, &rects[r].dst_y); + + struct blit2d_dst_temps dst_temps; + blit2d_bind_dst(cmd_buffer, dst, offset, rects[r].dst_x + rects[r].width, + rects[r].dst_y + rects[r].height, &dst_temps); struct blit_vb_data { float pos[2]; @@ -347,7 +456,8 @@ anv_meta_blit2d_normal_dst(struct anv_cmd_buffer *cmd_buffer, }, }; - anv_state_clflush(vb_state); + if (!device->info.has_llc) + anv_state_clflush(vb_state); struct anv_buffer vertex_buffer = { .device = device, @@ -366,24 +476,11 @@ anv_meta_blit2d_normal_dst(struct anv_cmd_buffer *cmd_buffer, sizeof(struct anv_vue_header), }); - VkFramebuffer fb; - anv_CreateFramebuffer(vk_device, - &(VkFramebufferCreateInfo) { - .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, - .attachmentCount = 1, - .pAttachments = (VkImageView[]) { - anv_image_view_to_handle(&dst_iview), - }, - .width = dst_iview.extent.width, - .height = dst_iview.extent.height, - .layers = 1 - }, &cmd_buffer->pool->alloc, &fb); - 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 = fb, + .framebuffer = dst_temps.fb, .renderArea = { .offset = { rects[r].dst_x, rects[r].dst_y, }, .extent = { rects[r].width, rects[r].height }, @@ -394,15 +491,149 @@ anv_meta_blit2d_normal_dst(struct anv_cmd_buffer *cmd_buffer, bind_pipeline(cmd_buffer, src_type, BLIT2D_DST_TYPE_NORMAL); - anv_CmdSetViewport(anv_cmd_buffer_to_handle(cmd_buffer), 0, 1, - &(VkViewport) { - .x = 0.0f, - .y = 0.0f, - .width = dst_iview.extent.width, - .height = dst_iview.extent.height, - .minDepth = 0.0f, - .maxDepth = 1.0f, - }); + 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); + } +} + +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, + }, + }; + + 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, + (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); @@ -412,8 +643,7 @@ anv_meta_blit2d_normal_dst(struct anv_cmd_buffer *cmd_buffer, * descriptor sets, etc. has been used. We are free to delete it. */ blit2d_unbind_src(cmd_buffer, src_type, &src_temps); - anv_DestroyFramebuffer(vk_device, fb, &cmd_buffer->pool->alloc); - anv_DestroyImage(vk_device, dst_img, &cmd_buffer->pool->alloc); + blit2d_unbind_dst(cmd_buffer, &dst_temps); } } @@ -432,8 +662,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"); @@ -471,6 +701,15 @@ build_nir_vertex_shader(void) tex_pos_out->data.interpolation = INTERP_QUALIFIER_SMOOTH; nir_copy_var(&b, tex_pos_out, tex_pos_in); + nir_variable *other_in = nir_variable_create(b.shader, nir_var_shader_in, + vec4, "a_other"); + other_in->data.location = VERT_ATTRIB_GENERIC2; + nir_variable *other_out = nir_variable_create(b.shader, nir_var_shader_out, + vec4, "v_other"); + other_out->data.location = VARYING_SLOT_VAR1; + other_out->data.interpolation = INTERP_QUALIFIER_FLAT; + nir_copy_var(&b, other_out, other_in); + return b.shader; } @@ -478,6 +717,80 @@ typedef nir_ssa_def* (*texel_fetch_build_func)(struct nir_builder *, struct anv_device *, nir_ssa_def *, nir_ssa_def *); +static nir_ssa_def * +nir_copy_bits(struct nir_builder *b, nir_ssa_def *dst, unsigned dst_offset, + nir_ssa_def *src, unsigned src_offset, unsigned num_bits) +{ + unsigned src_mask = (~1u >> (32 - num_bits)) << src_offset; + nir_ssa_def *masked = nir_iand(b, src, nir_imm_int(b, src_mask)); + + nir_ssa_def *shifted; + if (dst_offset > src_offset) { + shifted = nir_ishl(b, masked, nir_imm_int(b, dst_offset - src_offset)); + } else if (dst_offset < src_offset) { + shifted = nir_ushr(b, masked, nir_imm_int(b, src_offset - dst_offset)); + } else { + assert(dst_offset == src_offset); + shifted = masked; + } + + return nir_ior(b, dst, shifted); +} + +static nir_ssa_def * +build_nir_w_tiled_fetch(struct nir_builder *b, struct anv_device *device, + nir_ssa_def *tex_pos, nir_ssa_def *tex_pitch) +{ + nir_ssa_def *x = nir_channel(b, tex_pos, 0); + nir_ssa_def *y = nir_channel(b, tex_pos, 1); + + /* First, compute the block-aligned offset */ + nir_ssa_def *x_major = nir_ushr(b, x, nir_imm_int(b, 6)); + nir_ssa_def *y_major = nir_ushr(b, y, nir_imm_int(b, 6)); + nir_ssa_def *offset = + nir_iadd(b, nir_imul(b, y_major, + nir_imul(b, tex_pitch, nir_imm_int(b, 64))), + nir_imul(b, x_major, nir_imm_int(b, 4096))); + + /* Compute the bottom 12 bits of the offset */ + offset = nir_copy_bits(b, offset, 0, x, 0, 1); + offset = nir_copy_bits(b, offset, 1, y, 0, 1); + offset = nir_copy_bits(b, offset, 2, x, 1, 1); + offset = nir_copy_bits(b, offset, 3, y, 1, 1); + offset = nir_copy_bits(b, offset, 4, x, 2, 1); + offset = nir_copy_bits(b, offset, 5, y, 2, 4); + offset = nir_copy_bits(b, offset, 9, x, 3, 3); + + if (device->isl_dev.has_bit6_swizzling) { + offset = nir_ixor(b, offset, + nir_ushr(b, nir_iand(b, offset, nir_imm_int(b, 0x0200)), + nir_imm_int(b, 3))); + } + + const struct glsl_type *sampler_type = + glsl_sampler_type(GLSL_SAMPLER_DIM_BUF, 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, 1); + tex->sampler_dim = GLSL_SAMPLER_DIM_BUF; + tex->op = nir_texop_txf; + tex->src[0].src_type = nir_tex_src_coord; + tex->src[0].src = nir_src_for_ssa(offset); + tex->dest_type = nir_type_float; /* TODO */ + tex->is_array = false; + tex->coord_components = 1; + 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); + + return &tex->dest.ssa; +} + 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) @@ -508,6 +821,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) @@ -538,6 +892,134 @@ 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); + + nir_ssa_def *tex_off = nir_channels(&b, nir_load_var(&b, tex_off_in), 0x3); + 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) { @@ -595,17 +1077,23 @@ blit2d_init_pipeline(struct anv_device *device, src_func = build_nir_texel_fetch; break; case BLIT2D_SRC_TYPE_W_DETILE: - /* Not yet supported */ + src_func = build_nir_w_tiled_fetch; + break; default: - return VK_SUCCESS; + 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: @@ -621,47 +1109,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, @@ -682,7 +1129,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, @@ -741,8 +1188,6 @@ blit2d_init_pipeline(struct anv_device *device, const struct anv_graphics_pipeline_create_info anv_pipeline_info = { .color_attachment_count = -1, .use_repclear = false, - .disable_viewport = true, - .disable_scissor = true, .disable_vs = true, .use_rectlist = true };