From 6221593ff81a19129eee53a1cbded0d009425a38 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Mon, 14 Sep 2015 11:45:35 -0700 Subject: [PATCH] vk/meta: Partially implement vkCmdCopy*, vkCmdBlit* for 3D images Partially implement the below functions for 3D images: vkCmdCopyBufferToImage vkCmdCopyImageToBuffer vkCmdCopyImage vkCmdBlitImage Not all features work, and there is much for performance improvement. Beware that vkCmdCopyImage and vkCmdBlitImage are untested. Crucible proves that vkCmdCopyBufferToImage and vkCmdCopyImageToBuffer works, though. Supported: - copy regions with z offset Unsupported: - copy regions with extent.depth > 1 Crucible test results on master@d452d2b are: pass: func.miptree.r8g8b8a8-unorm.*.view-3d.* pass: func.miptree.d32-sfloat.*.view-3d.* fail: func.miptree.s8-uint.*.view-3d.* --- src/vulkan/anv_meta.c | 304 +++++++++++++++++++++++++++++---------- src/vulkan/anv_private.h | 7 +- src/vulkan/gen8_state.c | 2 +- 3 files changed, 235 insertions(+), 78 deletions(-) diff --git a/src/vulkan/anv_meta.c b/src/vulkan/anv_meta.c index 607054b92ab..aa48b978427 100644 --- a/src/vulkan/anv_meta.c +++ b/src/vulkan/anv_meta.c @@ -385,6 +385,43 @@ anv_cmd_buffer_clear_attachments(struct anv_cmd_buffer *cmd_buffer, anv_cmd_buffer_restore(cmd_buffer, &saved_state); } +static VkImageViewType +meta_blit_get_src_image_view_type(const struct anv_image *src_image) +{ + switch (src_image->type) { + case VK_IMAGE_TYPE_1D: + return VK_IMAGE_VIEW_TYPE_1D; + case VK_IMAGE_TYPE_2D: + return VK_IMAGE_VIEW_TYPE_2D; + case VK_IMAGE_TYPE_3D: + return VK_IMAGE_VIEW_TYPE_3D; + default: + assert(!"bad VkImageType"); + return 0; + } +} + +static uint32_t +meta_blit_get_dest_view_base_array_slice(const struct anv_image *dest_image, + const VkImageSubresource *dest_subresource, + const VkOffset3D *dest_offset) +{ + switch (dest_image->type) { + case VK_IMAGE_TYPE_1D: + case VK_IMAGE_TYPE_2D: + return dest_subresource->arraySlice; + case VK_IMAGE_TYPE_3D: + /* HACK: Vulkan does not allow attaching a 3D image to a framebuffer, + * but meta does it anyway. When doing so, we translate the + * destination's z offset into an array offset. + */ + return dest_offset->z; + default: + assert(!"bad VkImageType"); + return 0; + } +} + static void anv_device_init_meta_blit_state(struct anv_device *device) { @@ -404,7 +441,7 @@ anv_device_init_meta_blit_state(struct anv_device *device) } ); - VkShaderModule fsm = GLSL_VK_SHADER_MODULE(device, FRAGMENT, + VkShaderModule fsm_2d = GLSL_VK_SHADER_MODULE(device, FRAGMENT, out vec4 f_color; in vec4 v_tex_coord; layout(set = 0, binding = 0) uniform sampler2D u_tex; @@ -414,6 +451,16 @@ anv_device_init_meta_blit_state(struct anv_device *device) } ); + VkShaderModule fsm_3d = GLSL_VK_SHADER_MODULE(device, FRAGMENT, + out vec4 f_color; + in vec4 v_tex_coord; + layout(set = 0, binding = 0) uniform sampler3D u_tex; + void main() + { + f_color = texture(u_tex, v_tex_coord.xyz); + } + ); + VkShader vs; anv_CreateShader(anv_device_to_handle(device), &(VkShaderCreateInfo) { @@ -422,13 +469,21 @@ anv_device_init_meta_blit_state(struct anv_device *device) .pName = "main", }, &vs); - VkShader fs; + VkShader fs_2d; anv_CreateShader(anv_device_to_handle(device), &(VkShaderCreateInfo) { .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO, - .module = fsm, + .module = fsm_2d, .pName = "main", - }, &fs); + }, &fs_2d); + + VkShader fs_3d; + anv_CreateShader(anv_device_to_handle(device), + &(VkShaderCreateInfo) { + .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO, + .module = fsm_3d, + .pName = "main", + }, &fs_3d); VkPipelineVertexInputStateCreateInfo vi_create_info = { .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, @@ -441,7 +496,7 @@ anv_device_init_meta_blit_state(struct anv_device *device) }, { .binding = 1, - .strideInBytes = 16, + .strideInBytes = 5 * sizeof(float), .stepRate = VK_VERTEX_INPUT_STEP_RATE_VERTEX }, }, @@ -465,7 +520,7 @@ anv_device_init_meta_blit_state(struct anv_device *device) /* Texture Coordinate */ .location = 2, .binding = 1, - .format = VK_FORMAT_R32G32_SFLOAT, + .format = VK_FORMAT_R32G32B32_SFLOAT, .offsetInBytes = 8 } } @@ -494,61 +549,74 @@ anv_device_init_meta_blit_state(struct anv_device *device) }, &device->meta_state.blit.pipeline_layout); - anv_graphics_pipeline_create(anv_device_to_handle(device), - &(VkGraphicsPipelineCreateInfo) { - .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .stageCount = 2, - .pStages = (VkPipelineShaderStageCreateInfo[]) { - { - .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - .stage = VK_SHADER_STAGE_VERTEX, - .shader = vs, - .pSpecializationInfo = NULL - }, { - .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - .stage = VK_SHADER_STAGE_FRAGMENT, - .shader = fs, - .pSpecializationInfo = NULL - }, - }, - .pVertexInputState = &vi_create_info, - .pInputAssemblyState = &(VkPipelineInputAssemblyStateCreateInfo) { - .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, - .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, - .primitiveRestartEnable = false, - }, - .pRasterState = &(VkPipelineRasterStateCreateInfo) { - .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTER_STATE_CREATE_INFO, - .depthClipEnable = true, - .rasterizerDiscardEnable = false, - .fillMode = VK_FILL_MODE_SOLID, - .cullMode = VK_CULL_MODE_NONE, - .frontFace = VK_FRONT_FACE_CCW - }, - .pColorBlendState = &(VkPipelineColorBlendStateCreateInfo) { - .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, - .attachmentCount = 1, - .pAttachments = (VkPipelineColorBlendAttachmentState []) { - { .channelWriteMask = VK_CHANNEL_A_BIT | - VK_CHANNEL_R_BIT | VK_CHANNEL_G_BIT | VK_CHANNEL_B_BIT }, - } - }, - .flags = 0, - .layout = device->meta_state.blit.pipeline_layout, + VkPipelineShaderStageCreateInfo pipeline_shader_stages[] = { + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .stage = VK_SHADER_STAGE_VERTEX, + .shader = vs, + .pSpecializationInfo = NULL + }, { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .stage = VK_SHADER_STAGE_FRAGMENT, + .shader = {0}, /* TEMPLATE VALUE! FILL ME IN! */ + .pSpecializationInfo = NULL }, - &(struct anv_graphics_pipeline_create_info) { - .use_repclear = false, - .disable_viewport = true, - .disable_scissor = true, - .disable_vs = true, - .use_rectlist = true + }; + + const VkGraphicsPipelineCreateInfo vk_pipeline_info = { + .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, + .stageCount = ARRAY_SIZE(pipeline_shader_stages), + .pStages = pipeline_shader_stages, + .pVertexInputState = &vi_create_info, + .pInputAssemblyState = &(VkPipelineInputAssemblyStateCreateInfo) { + .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, + .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, + .primitiveRestartEnable = false, }, - &device->meta_state.blit.pipeline); + .pRasterState = &(VkPipelineRasterStateCreateInfo) { + .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTER_STATE_CREATE_INFO, + .depthClipEnable = true, + .rasterizerDiscardEnable = false, + .fillMode = VK_FILL_MODE_SOLID, + .cullMode = VK_CULL_MODE_NONE, + .frontFace = VK_FRONT_FACE_CCW + }, + .pColorBlendState = &(VkPipelineColorBlendStateCreateInfo) { + .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, + .attachmentCount = 1, + .pAttachments = (VkPipelineColorBlendAttachmentState []) { + { .channelWriteMask = VK_CHANNEL_A_BIT | + VK_CHANNEL_R_BIT | VK_CHANNEL_G_BIT | VK_CHANNEL_B_BIT }, + } + }, + .flags = 0, + .layout = device->meta_state.blit.pipeline_layout, + }; + + const struct anv_graphics_pipeline_create_info anv_pipeline_info = { + .use_repclear = false, + .disable_viewport = true, + .disable_scissor = true, + .disable_vs = true, + .use_rectlist = true + }; + + pipeline_shader_stages[1].shader = fs_2d; + anv_graphics_pipeline_create(anv_device_to_handle(device), + &vk_pipeline_info, &anv_pipeline_info, + &device->meta_state.blit.pipeline_2d_src); + + pipeline_shader_stages[1].shader = fs_3d; + anv_graphics_pipeline_create(anv_device_to_handle(device), + &vk_pipeline_info, &anv_pipeline_info, + &device->meta_state.blit.pipeline_3d_src); anv_DestroyShaderModule(anv_device_to_handle(device), vsm); anv_DestroyShader(anv_device_to_handle(device), vs); - anv_DestroyShaderModule(anv_device_to_handle(device), fsm); - anv_DestroyShader(anv_device_to_handle(device), fs); + anv_DestroyShaderModule(anv_device_to_handle(device), fsm_2d); + anv_DestroyShader(anv_device_to_handle(device), fs_2d); + anv_DestroyShaderModule(anv_device_to_handle(device), fsm_3d); + anv_DestroyShader(anv_device_to_handle(device), fs_3d); } static void @@ -559,11 +627,6 @@ meta_prepare_blit(struct anv_cmd_buffer *cmd_buffer, anv_cmd_buffer_save(cmd_buffer, saved_state); - if (cmd_buffer->state.pipeline != anv_pipeline_from_handle(device->meta_state.blit.pipeline)) - anv_CmdBindPipeline(anv_cmd_buffer_to_handle(cmd_buffer), - VK_PIPELINE_BIND_POINT_GRAPHICS, - device->meta_state.blit.pipeline); - /* We don't need anything here, only set if not already set. */ if (cmd_buffer->state.rs_state == NULL) anv_CmdBindDynamicRasterState(anv_cmd_buffer_to_handle(cmd_buffer), @@ -585,9 +648,11 @@ struct blit_region { static void meta_emit_blit(struct anv_cmd_buffer *cmd_buffer, + struct anv_image *src_image, struct anv_image_view *src_view, VkOffset3D src_offset, VkExtent3D src_extent, + struct anv_image *dest_image, struct anv_color_attachment_view *dest_view, VkOffset3D dest_offset, VkExtent3D dest_extent) @@ -597,7 +662,7 @@ meta_emit_blit(struct anv_cmd_buffer *cmd_buffer, struct blit_vb_data { float pos[2]; - float tex_coord[2]; + float tex_coord[3]; } *vb_data; unsigned vb_size = sizeof(struct vue_header) + 3 * sizeof(*vb_data); @@ -615,6 +680,7 @@ meta_emit_blit(struct anv_cmd_buffer *cmd_buffer, .tex_coord = { (float)(src_offset.x + src_extent.width) / (float)src_view->extent.width, (float)(src_offset.y + src_extent.height) / (float)src_view->extent.height, + (float)(src_offset.z + src_extent.depth) / (float)src_view->extent.depth, }, }; @@ -626,6 +692,7 @@ meta_emit_blit(struct anv_cmd_buffer *cmd_buffer, .tex_coord = { (float)src_offset.x / (float)src_view->extent.width, (float)(src_offset.y + src_extent.height) / (float)src_view->extent.height, + (float)(src_offset.z + src_extent.depth) / (float)src_view->extent.depth, }, }; @@ -637,6 +704,7 @@ meta_emit_blit(struct anv_cmd_buffer *cmd_buffer, .tex_coord = { (float)src_offset.x / (float)src_view->extent.width, (float)src_offset.y / (float)src_view->extent.height, + (float)src_offset.z / (float)src_view->extent.depth, }, }; @@ -747,6 +815,28 @@ meta_emit_blit(struct anv_cmd_buffer *cmd_buffer, .pAttachmentClearValues = NULL, }, VK_RENDER_PASS_CONTENTS_INLINE); + VkPipeline pipeline; + + switch (src_image->type) { + case VK_IMAGE_TYPE_1D: + anv_finishme("VK_IMAGE_TYPE_1D"); + pipeline = device->meta_state.blit.pipeline_2d_src; + break; + case VK_IMAGE_TYPE_2D: + pipeline = device->meta_state.blit.pipeline_2d_src; + break; + case VK_IMAGE_TYPE_3D: + pipeline = device->meta_state.blit.pipeline_3d_src; + break; + default: + unreachable(!"bad VkImageType"); + } + + if (cmd_buffer->state.pipeline != anv_pipeline_from_handle(pipeline)) { + anv_CmdBindPipeline(anv_cmd_buffer_to_handle(cmd_buffer), + VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + } + anv_CmdBindDynamicViewportState(anv_cmd_buffer_to_handle(cmd_buffer), anv_framebuffer_from_handle(fb)->vp_state); @@ -864,9 +954,11 @@ do_buffer_copy(struct anv_cmd_buffer *cmd_buffer, cmd_buffer); meta_emit_blit(cmd_buffer, + anv_image_from_handle(src_image), &src_view, (VkOffset3D) { 0, 0, 0 }, (VkExtent3D) { width, height, 1 }, + anv_image_from_handle(dest_image), &dest_view, (VkOffset3D) { 0, 0, 0 }, (VkExtent3D) { width, height, 1 }); @@ -966,6 +1058,9 @@ void anv_CmdCopyImage( ANV_FROM_HANDLE(anv_image, src_image, srcImage); ANV_FROM_HANDLE(anv_image, dest_image, destImage); + const VkImageViewType src_view_type = + meta_blit_get_src_image_view_type(src_image); + struct anv_saved_state saved_state; meta_prepare_blit(cmd_buffer, &saved_state); @@ -976,7 +1071,7 @@ void anv_CmdCopyImage( &(VkImageViewCreateInfo) { .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .image = srcImage, - .viewType = VK_IMAGE_VIEW_TYPE_2D, + .viewType = src_view_type, .format = src_image->format->vk_format, .channels = { VK_CHANNEL_SWIZZLE_R, @@ -994,6 +1089,20 @@ void anv_CmdCopyImage( }, cmd_buffer); + const VkOffset3D dest_offset = { + .x = pRegions[r].destOffset.x, + .y = pRegions[r].destOffset.y, + .z = 0, + }; + + const uint32_t dest_array_slice = + meta_blit_get_dest_view_base_array_slice(dest_image, + &pRegions[r].destSubresource, + &pRegions[r].destOffset); + + if (pRegions[r].extent.depth > 1) + anv_finishme("FINISHME: copy multiple depth layers"); + struct anv_color_attachment_view dest_view; anv_color_attachment_view_init(&dest_view, cmd_buffer->device, &(VkAttachmentViewCreateInfo) { @@ -1001,17 +1110,17 @@ void anv_CmdCopyImage( .image = destImage, .format = dest_image->format->vk_format, .mipLevel = pRegions[r].destSubresource.mipLevel, - .baseArraySlice = pRegions[r].destSubresource.arraySlice, + .baseArraySlice = dest_array_slice, .arraySize = 1, }, cmd_buffer); meta_emit_blit(cmd_buffer, - &src_view, + src_image, &src_view, pRegions[r].srcOffset, pRegions[r].extent, - &dest_view, - pRegions[r].destOffset, + dest_image, &dest_view, + dest_offset, pRegions[r].extent); } @@ -1033,6 +1142,9 @@ void anv_CmdBlitImage( ANV_FROM_HANDLE(anv_image, src_image, srcImage); ANV_FROM_HANDLE(anv_image, dest_image, destImage); + const VkImageViewType src_view_type = + meta_blit_get_src_image_view_type(src_image); + struct anv_saved_state saved_state; anv_finishme("respect VkTexFilter"); @@ -1045,7 +1157,7 @@ void anv_CmdBlitImage( &(VkImageViewCreateInfo) { .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .image = srcImage, - .viewType = VK_IMAGE_VIEW_TYPE_2D, + .viewType = src_view_type, .format = src_image->format->vk_format, .channels = { VK_CHANNEL_SWIZZLE_R, @@ -1063,6 +1175,20 @@ void anv_CmdBlitImage( }, cmd_buffer); + const VkOffset3D dest_offset = { + .x = pRegions[r].destOffset.x, + .y = pRegions[r].destOffset.y, + .z = 0, + }; + + const uint32_t dest_array_slice = + meta_blit_get_dest_view_base_array_slice(dest_image, + &pRegions[r].destSubresource, + &pRegions[r].destOffset); + + if (pRegions[r].destExtent.depth > 1) + anv_finishme("FINISHME: copy multiple depth layers"); + struct anv_color_attachment_view dest_view; anv_color_attachment_view_init(&dest_view, cmd_buffer->device, &(VkAttachmentViewCreateInfo) { @@ -1070,17 +1196,17 @@ void anv_CmdBlitImage( .image = destImage, .format = dest_image->format->vk_format, .mipLevel = pRegions[r].destSubresource.mipLevel, - .baseArraySlice = pRegions[r].destSubresource.arraySlice, + .baseArraySlice = dest_array_slice, .arraySize = 1, }, cmd_buffer); meta_emit_blit(cmd_buffer, - &src_view, + src_image, &src_view, pRegions[r].srcOffset, pRegions[r].srcExtent, - &dest_view, - pRegions[r].destOffset, + dest_image, &dest_view, + dest_offset, pRegions[r].destExtent); } @@ -1181,6 +1307,20 @@ void anv_CmdCopyBufferToImage( }, cmd_buffer); + const VkOffset3D dest_offset = { + .x = pRegions[r].imageOffset.x, + .y = pRegions[r].imageOffset.y, + .z = 0, + }; + + const uint32_t dest_array_slice = + meta_blit_get_dest_view_base_array_slice(dest_image, + &pRegions[r].imageSubresource, + &pRegions[r].imageOffset); + + if (pRegions[r].imageExtent.depth > 1) + anv_finishme("FINISHME: copy multiple depth layers"); + struct anv_color_attachment_view dest_view; anv_color_attachment_view_init(&dest_view, cmd_buffer->device, &(VkAttachmentViewCreateInfo) { @@ -1188,17 +1328,19 @@ void anv_CmdCopyBufferToImage( .image = anv_image_to_handle(dest_image), .format = proxy_format, .mipLevel = pRegions[r].imageSubresource.mipLevel, - .baseArraySlice = pRegions[r].imageSubresource.arraySlice, + .baseArraySlice = dest_array_slice, .arraySize = 1, }, cmd_buffer); meta_emit_blit(cmd_buffer, + anv_image_from_handle(srcImage), &src_view, (VkOffset3D) { 0, 0, 0 }, pRegions[r].imageExtent, + dest_image, &dest_view, - pRegions[r].imageOffset, + dest_offset, pRegions[r].imageExtent); anv_DestroyImage(vk_device, srcImage); @@ -1220,15 +1362,21 @@ void anv_CmdCopyImageToBuffer( VkDevice vk_device = anv_device_to_handle(cmd_buffer->device); struct anv_saved_state saved_state; + const VkImageViewType src_view_type = + meta_blit_get_src_image_view_type(src_image); + meta_prepare_blit(cmd_buffer, &saved_state); for (unsigned r = 0; r < regionCount; r++) { + if (pRegions[r].imageExtent.depth > 1) + anv_finishme("FINISHME: copy multiple depth layers"); + struct anv_image_view src_view; anv_image_view_init(&src_view, cmd_buffer->device, &(VkImageViewCreateInfo) { .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .image = srcImage, - .viewType = VK_IMAGE_VIEW_TYPE_2D, + .viewType = src_view_type, .format = src_image->format->vk_format, .channels = { VK_CHANNEL_SWIZZLE_R, @@ -1268,9 +1416,11 @@ void anv_CmdCopyImageToBuffer( cmd_buffer); meta_emit_blit(cmd_buffer, + anv_image_from_handle(srcImage), &src_view, pRegions[r].imageOffset, pRegions[r].imageExtent, + anv_image_from_handle(destImage), &dest_view, (VkOffset3D) { 0, 0, 0 }, pRegions[r].imageExtent); @@ -1501,7 +1651,9 @@ anv_device_finish_meta(struct anv_device *device) /* Blit */ anv_DestroyPipeline(anv_device_to_handle(device), - device->meta_state.blit.pipeline); + device->meta_state.blit.pipeline_2d_src); + anv_DestroyPipeline(anv_device_to_handle(device), + device->meta_state.blit.pipeline_3d_src); anv_DestroyPipelineLayout(anv_device_to_handle(device), device->meta_state.blit.pipeline_layout); anv_DestroyDescriptorSetLayout(anv_device_to_handle(device), diff --git a/src/vulkan/anv_private.h b/src/vulkan/anv_private.h index b290d60cc08..9115393ad4b 100644 --- a/src/vulkan/anv_private.h +++ b/src/vulkan/anv_private.h @@ -356,7 +356,12 @@ struct anv_meta_state { } clear; struct { - VkPipeline pipeline; + /** Pipeline that blits from a 2D image. */ + VkPipeline pipeline_2d_src; + + /** Pipeline that blits from a 3D image. */ + VkPipeline pipeline_3d_src; + VkPipelineLayout pipeline_layout; VkDescriptorSetLayout ds_layout; } blit; diff --git a/src/vulkan/gen8_state.c b/src/vulkan/gen8_state.c index 26509f1d817..4c9161c0c9c 100644 --- a/src/vulkan/gen8_state.c +++ b/src/vulkan/gen8_state.c @@ -363,7 +363,7 @@ gen8_color_attachment_view_init(struct anv_color_attachment_view *aview, } struct GEN8_RENDER_SURFACE_STATE surface_state = { - .SurfaceType = SURFTYPE_2D, + .SurfaceType = image->type, .SurfaceArray = image->array_size > 1, .SurfaceFormat = format_info->surface_format, .SurfaceVerticalAlignment = anv_valign[surface->v_align], -- 2.30.2