v3dv: blit shader clean-ups
This avoids redundant per-layer operations that are the same across layers or that only need to do once. Namely: - The sampler for the blit source is the same for all layers. - The decision about whether we need to load TLB contents or not only needs to be done once. - Some command buffer state such as the pipeline, the viewport and the scissor is the same for all layers and should only be bound once. Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7651>
This commit is contained in:
parent
840ba2513a
commit
ba2e979b5c
|
@ -4802,6 +4802,7 @@ blit_shader(struct v3dv_cmd_buffer *cmd_buffer,
|
|||
bool dst_is_padded_image)
|
||||
{
|
||||
bool handled = true;
|
||||
VkResult result;
|
||||
|
||||
/* We don't support rendering to linear depth/stencil, this should have
|
||||
* been rewritten to a compatible color blit by the caller.
|
||||
|
@ -4959,7 +4960,6 @@ blit_shader(struct v3dv_cmd_buffer *cmd_buffer,
|
|||
0.0f
|
||||
};
|
||||
|
||||
|
||||
/* For blits from 3D images we also need to compute the slice coordinate to
|
||||
* sample from, which will change for each layer in the destination.
|
||||
* Compute the step we should increase for each iteration.
|
||||
|
@ -4981,17 +4981,64 @@ blit_shader(struct v3dv_cmd_buffer *cmd_buffer,
|
|||
struct v3dv_device *device = cmd_buffer->device;
|
||||
assert(device->meta.blit.dslayout);
|
||||
|
||||
/* Push command buffer state before starting meta operation */
|
||||
v3dv_cmd_buffer_meta_state_push(cmd_buffer, true);
|
||||
|
||||
/* Setup framebuffer */
|
||||
VkDevice _device = v3dv_device_to_handle(device);
|
||||
VkCommandBuffer _cmd_buffer = v3dv_cmd_buffer_to_handle(cmd_buffer);
|
||||
|
||||
VkResult result;
|
||||
/* Create sampler for blit source image */
|
||||
VkSamplerCreateInfo sampler_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
||||
.magFilter = filter,
|
||||
.minFilter = filter,
|
||||
.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||
.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||
.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||
.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST,
|
||||
};
|
||||
VkSampler sampler;
|
||||
result = v3dv_CreateSampler(_device, &sampler_info, &device->alloc,
|
||||
&sampler);
|
||||
if (result != VK_SUCCESS)
|
||||
goto fail;
|
||||
|
||||
v3dv_cmd_buffer_add_private_obj(
|
||||
cmd_buffer, (uintptr_t)sampler,
|
||||
(v3dv_cmd_buffer_private_obj_destroy_cb)v3dv_DestroySampler);
|
||||
|
||||
/* Push command buffer state before starting meta operation */
|
||||
v3dv_cmd_buffer_meta_state_push(cmd_buffer, true);
|
||||
|
||||
/* Push state that is common for all layers */
|
||||
v3dv_CmdBindPipeline(_cmd_buffer,
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
pipeline->pipeline);
|
||||
|
||||
const VkViewport viewport = {
|
||||
.x = dst_x,
|
||||
.y = dst_y,
|
||||
.width = dst_w,
|
||||
.height = dst_h,
|
||||
.minDepth = 0.0f,
|
||||
.maxDepth = 1.0f
|
||||
};
|
||||
v3dv_CmdSetViewport(_cmd_buffer, 0, 1, &viewport);
|
||||
|
||||
const VkRect2D scissor = {
|
||||
.offset = { dst_x, dst_y },
|
||||
.extent = { dst_w, dst_h }
|
||||
};
|
||||
v3dv_CmdSetScissor(_cmd_buffer, 0, 1, &scissor);
|
||||
|
||||
bool can_skip_tlb_load;
|
||||
const VkRect2D render_area = {
|
||||
.offset = { dst_x, dst_y },
|
||||
.extent = { dst_w, dst_h },
|
||||
};
|
||||
|
||||
/* Record per-layer commands */
|
||||
uint32_t dirty_dynamic_state = 0;
|
||||
VkImageAspectFlags aspects = region.dstSubresource.aspectMask;
|
||||
for (uint32_t i = 0; i < layer_count; i++) {
|
||||
/* Setup framebuffer */
|
||||
VkImageViewCreateInfo dst_image_view_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.image = v3dv_image_to_handle(dst),
|
||||
|
@ -5050,25 +5097,6 @@ blit_shader(struct v3dv_cmd_buffer *cmd_buffer,
|
|||
if (result != VK_SUCCESS)
|
||||
goto fail;
|
||||
|
||||
VkSamplerCreateInfo sampler_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
||||
.magFilter = filter,
|
||||
.minFilter = filter,
|
||||
.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||
.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||
.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||
.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST,
|
||||
};
|
||||
VkSampler sampler;
|
||||
result = v3dv_CreateSampler(_device, &sampler_info, &device->alloc,
|
||||
&sampler);
|
||||
if (result != VK_SUCCESS)
|
||||
goto fail;
|
||||
|
||||
v3dv_cmd_buffer_add_private_obj(
|
||||
cmd_buffer, (uintptr_t)sampler,
|
||||
(v3dv_cmd_buffer_private_obj_destroy_cb)v3dv_DestroySampler);
|
||||
|
||||
VkImageViewCreateInfo src_image_view_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.image = v3dv_image_to_handle(src),
|
||||
|
@ -5110,22 +5138,29 @@ blit_shader(struct v3dv_cmd_buffer *cmd_buffer,
|
|||
};
|
||||
v3dv_UpdateDescriptorSets(_device, 1, &write, 0, NULL);
|
||||
|
||||
v3dv_CmdBindDescriptorSets(_cmd_buffer,
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
device->meta.blit.playout,
|
||||
0, 1, &set,
|
||||
0, NULL);
|
||||
|
||||
/* If the region we are about to blit is tile-aligned, then we can
|
||||
* use the render pass version that won't pre-load the tile buffer
|
||||
* with the dst image contents before the blit. The exception is when we
|
||||
* don't have a full color mask, since in that case we need to preserve
|
||||
* the original value of some of the color components.
|
||||
*
|
||||
* Since all layers have the same area, we only need to compute this for
|
||||
* the first.
|
||||
*/
|
||||
const VkRect2D render_area = {
|
||||
.offset = { dst_x, dst_y },
|
||||
.extent = { dst_w, dst_h },
|
||||
};
|
||||
struct v3dv_render_pass *pipeline_pass =
|
||||
v3dv_render_pass_from_handle(pipeline->pass);
|
||||
bool can_skip_tlb_load =
|
||||
cmask == full_cmask &&
|
||||
v3dv_subpass_area_is_tile_aligned(&render_area, framebuffer,
|
||||
pipeline_pass, 0);
|
||||
if (i == 0) {
|
||||
struct v3dv_render_pass *pipeline_pass =
|
||||
v3dv_render_pass_from_handle(pipeline->pass);
|
||||
can_skip_tlb_load =
|
||||
cmask == full_cmask &&
|
||||
v3dv_subpass_area_is_tile_aligned(&render_area, framebuffer,
|
||||
pipeline_pass, 0);
|
||||
}
|
||||
|
||||
/* Record blit */
|
||||
VkRenderPassBeginInfo rp_info = {
|
||||
|
@ -5159,31 +5194,6 @@ blit_shader(struct v3dv_cmd_buffer *cmd_buffer,
|
|||
VK_SHADER_STAGE_VERTEX_BIT, 0, 20,
|
||||
&tex_coords);
|
||||
|
||||
v3dv_CmdBindPipeline(_cmd_buffer,
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
pipeline->pipeline);
|
||||
|
||||
v3dv_CmdBindDescriptorSets(_cmd_buffer,
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
device->meta.blit.playout,
|
||||
0, 1, &set,
|
||||
0, NULL);
|
||||
|
||||
const VkViewport viewport = {
|
||||
.x = dst_x,
|
||||
.y = dst_y,
|
||||
.width = dst_w,
|
||||
.height = dst_h,
|
||||
.minDepth = 0.0f,
|
||||
.maxDepth = 1.0f
|
||||
};
|
||||
v3dv_CmdSetViewport(_cmd_buffer, 0, 1, &viewport);
|
||||
const VkRect2D scissor = {
|
||||
.offset = { dst_x, dst_y },
|
||||
.extent = { dst_w, dst_h }
|
||||
};
|
||||
v3dv_CmdSetScissor(_cmd_buffer, 0, 1, &scissor);
|
||||
|
||||
v3dv_CmdDraw(_cmd_buffer, 4, 1, 0, 0);
|
||||
|
||||
v3dv_CmdEndRenderPass(_cmd_buffer);
|
||||
|
|
Loading…
Reference in New Issue