X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Famd%2Fvulkan%2Fradv_meta_clear.c;h=b42ecedfc9809d15ad5ffb14986e203987e9a2ee;hb=258ebe79a0c2133e362035b76f3cf3243880926f;hp=1c1b8c6b1e343035e2cf403a6e750325e250ebf5;hpb=f4e499ec79147f4172f3669ae9dafd941aaeeb65;p=mesa.git diff --git a/src/amd/vulkan/radv_meta_clear.c b/src/amd/vulkan/radv_meta_clear.c index 1c1b8c6b1e3..b42ecedfc98 100644 --- a/src/amd/vulkan/radv_meta_clear.c +++ b/src/amd/vulkan/radv_meta_clear.c @@ -21,23 +21,13 @@ * IN THE SOFTWARE. */ +#include "radv_debug.h" #include "radv_meta.h" #include "radv_private.h" #include "nir/nir_builder.h" #include "util/format_rgb9e5.h" #include "vk_format.h" -/** Vertex attributes for color clears. */ -struct color_clear_vattrs { - float position[2]; - VkClearColorValue color; -}; - -/** Vertex attributes for depthstencil clears. */ -struct depthstencil_clear_vattrs { - float position[2]; - float depth_clear; -}; enum { DEPTH_CLEAR_SLOW, @@ -62,41 +52,40 @@ build_color_shaders(struct nir_shader **out_vs, const struct glsl_type *position_type = glsl_vec4_type(); const struct glsl_type *color_type = glsl_vec4_type(); - nir_variable *vs_in_pos = - nir_variable_create(vs_b.shader, nir_var_shader_in, position_type, - "a_position"); - vs_in_pos->data.location = VERT_ATTRIB_GENERIC0; - nir_variable *vs_out_pos = nir_variable_create(vs_b.shader, nir_var_shader_out, position_type, "gl_Position"); vs_out_pos->data.location = VARYING_SLOT_POS; - nir_variable *vs_in_color = - nir_variable_create(vs_b.shader, nir_var_shader_in, color_type, - "a_color"); - vs_in_color->data.location = VERT_ATTRIB_GENERIC1; - - nir_variable *vs_out_color = - nir_variable_create(vs_b.shader, nir_var_shader_out, color_type, - "v_color"); - vs_out_color->data.location = VARYING_SLOT_VAR0; - vs_out_color->data.interpolation = INTERP_MODE_FLAT; - - nir_variable *fs_in_color = - nir_variable_create(fs_b.shader, nir_var_shader_in, color_type, - "v_color"); - fs_in_color->data.location = vs_out_color->data.location; - fs_in_color->data.interpolation = vs_out_color->data.interpolation; + nir_intrinsic_instr *in_color_load = nir_intrinsic_instr_create(fs_b.shader, nir_intrinsic_load_push_constant); + nir_intrinsic_set_base(in_color_load, 0); + nir_intrinsic_set_range(in_color_load, 16); + in_color_load->src[0] = nir_src_for_ssa(nir_imm_int(&fs_b, 0)); + in_color_load->num_components = 4; + nir_ssa_dest_init(&in_color_load->instr, &in_color_load->dest, 4, 32, "clear color"); + nir_builder_instr_insert(&fs_b, &in_color_load->instr); nir_variable *fs_out_color = nir_variable_create(fs_b.shader, nir_var_shader_out, color_type, "f_color"); fs_out_color->data.location = FRAG_RESULT_DATA0 + frag_output; - nir_copy_var(&vs_b, vs_out_pos, vs_in_pos); - nir_copy_var(&vs_b, vs_out_color, vs_in_color); - nir_copy_var(&fs_b, fs_out_color, fs_in_color); + nir_store_var(&fs_b, fs_out_color, &in_color_load->dest.ssa, 0xf); + + nir_ssa_def *outvec = radv_meta_gen_rect_vertices(&vs_b); + nir_store_var(&vs_b, vs_out_pos, outvec, 0xf); + + const struct glsl_type *layer_type = glsl_int_type(); + nir_variable *vs_out_layer = + nir_variable_create(vs_b.shader, nir_var_shader_out, layer_type, + "v_layer"); + vs_out_layer->data.location = VARYING_SLOT_LAYER; + vs_out_layer->data.interpolation = INTERP_MODE_FLAT; + nir_ssa_def *inst_id = nir_load_system_value(&vs_b, nir_intrinsic_load_instance_id, 0); + nir_ssa_def *base_instance = nir_load_system_value(&vs_b, nir_intrinsic_load_base_instance, 0); + + nir_ssa_def *layer_id = nir_iadd(&vs_b, inst_id, base_instance); + nir_store_var(&vs_b, vs_out_layer, layer_id, 0x1); *out_vs = vs_b.shader; *out_fs = fs_b.shader; @@ -111,9 +100,10 @@ create_pipeline(struct radv_device *device, const VkPipelineVertexInputStateCreateInfo *vi_state, const VkPipelineDepthStencilStateCreateInfo *ds_state, const VkPipelineColorBlendStateCreateInfo *cb_state, + const VkPipelineLayout layout, const struct radv_graphics_pipeline_create_info *extra, const VkAllocationCallbacks *alloc, - struct radv_pipeline **pipeline) + VkPipeline *pipeline) { VkDevice device_h = radv_device_to_handle(device); VkResult result; @@ -121,7 +111,6 @@ create_pipeline(struct radv_device *device, struct radv_shader_module vs_m = { .nir = vs_nir }; struct radv_shader_module fs_m = { .nir = fs_nir }; - VkPipeline pipeline_h = VK_NULL_HANDLE; result = radv_graphics_pipeline_create(device_h, radv_pipeline_cache_to_handle(&device->meta_state.cache), &(VkGraphicsPipelineCreateInfo) { @@ -149,8 +138,8 @@ create_pipeline(struct radv_device *device, }, .pViewportState = &(VkPipelineViewportStateCreateInfo) { .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, - .viewportCount = 0, - .scissorCount = 0, + .viewportCount = 1, + .scissorCount = 1, }, .pRasterizationState = &(VkPipelineRasterizationStateCreateInfo) { .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, @@ -177,9 +166,11 @@ create_pipeline(struct radv_device *device, * we need only restore dynamic state was vkCmdSet. */ .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, - .dynamicStateCount = 6, + .dynamicStateCount = 8, .pDynamicStates = (VkDynamicState[]) { /* Everything except stencil write mask */ + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR, VK_DYNAMIC_STATE_LINE_WIDTH, VK_DYNAMIC_STATE_DEPTH_BIAS, VK_DYNAMIC_STATE_BLEND_CONSTANTS, @@ -188,29 +179,66 @@ create_pipeline(struct radv_device *device, VK_DYNAMIC_STATE_STENCIL_REFERENCE, }, }, - .flags = 0, - .renderPass = radv_render_pass_to_handle(render_pass), - .subpass = 0, - }, + .layout = layout, + .flags = 0, + .renderPass = radv_render_pass_to_handle(render_pass), + .subpass = 0, + }, extra, alloc, - &pipeline_h); + pipeline); ralloc_free(vs_nir); ralloc_free(fs_nir); - *pipeline = radv_pipeline_from_handle(pipeline_h); - return result; } +static VkResult +create_color_renderpass(struct radv_device *device, + VkFormat vk_format, + uint32_t samples, + VkRenderPass *pass) +{ + return radv_CreateRenderPass(radv_device_to_handle(device), + &(VkRenderPassCreateInfo) { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, + .attachmentCount = 1, + .pAttachments = &(VkAttachmentDescription) { + .format = vk_format, + .samples = samples, + .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .initialLayout = VK_IMAGE_LAYOUT_GENERAL, + .finalLayout = VK_IMAGE_LAYOUT_GENERAL, + }, + .subpassCount = 1, + .pSubpasses = &(VkSubpassDescription) { + .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, + .inputAttachmentCount = 0, + .colorAttachmentCount = 1, + .pColorAttachments = &(VkAttachmentReference) { + .attachment = 0, + .layout = VK_IMAGE_LAYOUT_GENERAL, + }, + .pResolveAttachments = NULL, + .pDepthStencilAttachment = &(VkAttachmentReference) { + .attachment = VK_ATTACHMENT_UNUSED, + .layout = VK_IMAGE_LAYOUT_GENERAL, + }, + .preserveAttachmentCount = 1, + .pPreserveAttachments = (uint32_t[]) { 0 }, + }, + .dependencyCount = 0, + }, &device->meta_state.alloc, pass); +} + static VkResult create_color_pipeline(struct radv_device *device, - VkFormat vk_format, uint32_t samples, uint32_t frag_output, - struct radv_pipeline **pipeline, - VkRenderPass *pass) + VkPipeline *pipeline, + VkRenderPass pass) { struct nir_shader *vs_nir; struct nir_shader *fs_nir; @@ -219,31 +247,8 @@ create_color_pipeline(struct radv_device *device, const VkPipelineVertexInputStateCreateInfo vi_state = { .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - .vertexBindingDescriptionCount = 1, - .pVertexBindingDescriptions = (VkVertexInputBindingDescription[]) { - { - .binding = 0, - .stride = sizeof(struct color_clear_vattrs), - .inputRate = VK_VERTEX_INPUT_RATE_VERTEX - }, - }, - .vertexAttributeDescriptionCount = 2, - .pVertexAttributeDescriptions = (VkVertexInputAttributeDescription[]) { - { - /* Position */ - .location = 0, - .binding = 0, - .format = VK_FORMAT_R32G32_SFLOAT, - .offset = offsetof(struct color_clear_vattrs, position), - }, - { - /* Color */ - .location = 1, - .binding = 0, - .format = VK_FORMAT_R32G32B32A32_SFLOAT, - .offset = offsetof(struct color_clear_vattrs, color), - }, - }, + .vertexBindingDescriptionCount = 0, + .vertexAttributeDescriptionCount = 0, }; const VkPipelineDepthStencilStateCreateInfo ds_state = { @@ -270,69 +275,18 @@ create_color_pipeline(struct radv_device *device, .pAttachments = blend_attachment_state }; - result = radv_CreateRenderPass(radv_device_to_handle(device), - &(VkRenderPassCreateInfo) { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - .attachmentCount = 1, - .pAttachments = &(VkAttachmentDescription) { - .format = vk_format, - .samples = samples, - .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, - .storeOp = VK_ATTACHMENT_STORE_OP_STORE, - .initialLayout = VK_IMAGE_LAYOUT_GENERAL, - .finalLayout = VK_IMAGE_LAYOUT_GENERAL, - }, - .subpassCount = 1, - .pSubpasses = &(VkSubpassDescription) { - .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, - .inputAttachmentCount = 0, - .colorAttachmentCount = 1, - .pColorAttachments = &(VkAttachmentReference) { - .attachment = 0, - .layout = VK_IMAGE_LAYOUT_GENERAL, - }, - .pResolveAttachments = NULL, - .pDepthStencilAttachment = &(VkAttachmentReference) { - .attachment = VK_ATTACHMENT_UNUSED, - .layout = VK_IMAGE_LAYOUT_GENERAL, - }, - .preserveAttachmentCount = 1, - .pPreserveAttachments = (uint32_t[]) { 0 }, - }, - .dependencyCount = 0, - }, &device->meta_state.alloc, pass); - if (result != VK_SUCCESS) - return result; struct radv_graphics_pipeline_create_info extra = { .use_rectlist = true, }; - result = create_pipeline(device, radv_render_pass_from_handle(*pass), + result = create_pipeline(device, radv_render_pass_from_handle(pass), samples, vs_nir, fs_nir, &vi_state, &ds_state, &cb_state, + device->meta_state.clear_color_p_layout, &extra, &device->meta_state.alloc, pipeline); return result; } -static void -destroy_pipeline(struct radv_device *device, struct radv_pipeline *pipeline) -{ - if (!pipeline) - return; - - RADV_CALL(DestroyPipeline)(radv_device_to_handle(device), - radv_pipeline_to_handle(pipeline), - &device->meta_state.alloc); - -} - -static void -destroy_render_pass(struct radv_device *device, VkRenderPass renderpass) -{ - RADV_CALL(DestroyRenderPass)(radv_device_to_handle(device), renderpass, - &device->meta_state.alloc); -} - void radv_device_finish_meta_clear_state(struct radv_device *device) { @@ -340,26 +294,42 @@ radv_device_finish_meta_clear_state(struct radv_device *device) for (uint32_t i = 0; i < ARRAY_SIZE(state->clear); ++i) { for (uint32_t j = 0; j < ARRAY_SIZE(state->clear[i].color_pipelines); ++j) { - destroy_pipeline(device, state->clear[i].color_pipelines[j]); - destroy_render_pass(device, state->clear[i].render_pass[j]); + radv_DestroyPipeline(radv_device_to_handle(device), + state->clear[i].color_pipelines[j], + &state->alloc); + radv_DestroyRenderPass(radv_device_to_handle(device), + state->clear[i].render_pass[j], + &state->alloc); } for (uint32_t j = 0; j < NUM_DEPTH_CLEAR_PIPELINES; j++) { - destroy_pipeline(device, state->clear[i].depth_only_pipeline[j]); - destroy_render_pass(device, state->clear[i].depth_only_rp[j]); - destroy_pipeline(device, state->clear[i].stencil_only_pipeline[j]); - destroy_render_pass(device, state->clear[i].stencil_only_rp[j]); - destroy_pipeline(device, state->clear[i].depthstencil_pipeline[j]); - destroy_render_pass(device, state->clear[i].depthstencil_rp[j]); + radv_DestroyPipeline(radv_device_to_handle(device), + state->clear[i].depth_only_pipeline[j], + &state->alloc); + radv_DestroyPipeline(radv_device_to_handle(device), + state->clear[i].stencil_only_pipeline[j], + &state->alloc); + radv_DestroyPipeline(radv_device_to_handle(device), + state->clear[i].depthstencil_pipeline[j], + &state->alloc); } + radv_DestroyRenderPass(radv_device_to_handle(device), + state->clear[i].depthstencil_rp, + &state->alloc); } - + radv_DestroyPipelineLayout(radv_device_to_handle(device), + state->clear_color_p_layout, + &state->alloc); + radv_DestroyPipelineLayout(radv_device_to_handle(device), + state->clear_depth_p_layout, + &state->alloc); } static void emit_color_clear(struct radv_cmd_buffer *cmd_buffer, const VkClearAttachment *clear_att, - const VkClearRect *clear_rect) + const VkClearRect *clear_rect, + uint32_t view_mask) { struct radv_device *device = cmd_buffer->device; const struct radv_subpass *subpass = cmd_buffer->state.subpass; @@ -367,22 +337,19 @@ emit_color_clear(struct radv_cmd_buffer *cmd_buffer, const uint32_t subpass_att = clear_att->colorAttachment; const uint32_t pass_att = subpass->color_attachments[subpass_att].attachment; const struct radv_image_view *iview = fb->attachments[pass_att].attachment; - const uint32_t samples = iview->image->samples; + const uint32_t samples = iview->image->info.samples; const uint32_t samples_log2 = ffs(samples) - 1; unsigned fs_key = radv_format_meta_fs_key(iview->vk_format); - struct radv_pipeline *pipeline; VkClearColorValue clear_value = clear_att->clearValue.color; VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer); - VkPipeline pipeline_h; - uint32_t offset; + VkPipeline pipeline; if (fs_key == -1) { radv_finishme("color clears incomplete"); return; } - pipeline = device->meta_state.clear[samples_log2].color_pipelines[fs_key]; - pipeline_h = radv_pipeline_to_handle(pipeline); + pipeline = device->meta_state.clear[samples_log2].color_pipelines[fs_key]; if (!pipeline) { radv_finishme("color clears incomplete"); return; @@ -392,29 +359,10 @@ emit_color_clear(struct radv_cmd_buffer *cmd_buffer, assert(clear_att->aspectMask == VK_IMAGE_ASPECT_COLOR_BIT); assert(clear_att->colorAttachment < subpass->color_count); - const struct color_clear_vattrs vertex_data[3] = { - { - .position = { - clear_rect->rect.offset.x, - clear_rect->rect.offset.y, - }, - .color = clear_value, - }, - { - .position = { - clear_rect->rect.offset.x, - clear_rect->rect.offset.y + clear_rect->rect.extent.height, - }, - .color = clear_value, - }, - { - .position = { - clear_rect->rect.offset.x + clear_rect->rect.extent.width, - clear_rect->rect.offset.y, - }, - .color = clear_value, - }, - }; + radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer), + device->meta_state.clear_color_p_layout, + VK_SHADER_STAGE_FRAGMENT_BIT, 0, 16, + &clear_value); struct radv_subpass clear_subpass = { .color_count = 1, @@ -426,26 +374,28 @@ emit_color_clear(struct radv_cmd_buffer *cmd_buffer, radv_cmd_buffer_set_subpass(cmd_buffer, &clear_subpass, false); - radv_cmd_buffer_upload_data(cmd_buffer, sizeof(vertex_data), 16, vertex_data, &offset); - struct radv_buffer vertex_buffer = { - .device = device, - .size = sizeof(vertex_data), - .bo = cmd_buffer->upload.upload_bo, - .offset = offset, - }; + radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS, + pipeline); + radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &(VkViewport) { + .x = clear_rect->rect.offset.x, + .y = clear_rect->rect.offset.y, + .width = clear_rect->rect.extent.width, + .height = clear_rect->rect.extent.height, + .minDepth = 0.0f, + .maxDepth = 1.0f + }); - RADV_CALL(CmdBindVertexBuffers)(cmd_buffer_h, 0, 1, - (VkBuffer[]) { radv_buffer_to_handle(&vertex_buffer) }, - (VkDeviceSize[]) { 0 }); + radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &clear_rect->rect); - if (cmd_buffer->state.pipeline != pipeline) { - RADV_CALL(CmdBindPipeline)(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS, - pipeline_h); + if (view_mask) { + unsigned i; + for_each_bit(i, view_mask) + radv_CmdDraw(cmd_buffer_h, 3, 1, 0, i); + } else { + radv_CmdDraw(cmd_buffer_h, 3, clear_rect->layerCount, 0, clear_rect->baseArrayLayer); } - RADV_CALL(CmdDraw)(cmd_buffer_h, 3, 1, 0, 0); - radv_cmd_buffer_set_subpass(cmd_buffer, subpass, false); } @@ -460,31 +410,82 @@ build_depthstencil_shader(struct nir_shader **out_vs, struct nir_shader **out_fs vs_b.shader->info.name = ralloc_strdup(vs_b.shader, "meta_clear_depthstencil_vs"); fs_b.shader->info.name = ralloc_strdup(fs_b.shader, "meta_clear_depthstencil_fs"); - const struct glsl_type *position_type = glsl_vec4_type(); - - nir_variable *vs_in_pos = - nir_variable_create(vs_b.shader, nir_var_shader_in, position_type, - "a_position"); - vs_in_pos->data.location = VERT_ATTRIB_GENERIC0; + const struct glsl_type *position_out_type = glsl_vec4_type(); nir_variable *vs_out_pos = - nir_variable_create(vs_b.shader, nir_var_shader_out, position_type, + nir_variable_create(vs_b.shader, nir_var_shader_out, position_out_type, "gl_Position"); vs_out_pos->data.location = VARYING_SLOT_POS; - nir_copy_var(&vs_b, vs_out_pos, vs_in_pos); + nir_intrinsic_instr *in_color_load = nir_intrinsic_instr_create(vs_b.shader, nir_intrinsic_load_push_constant); + nir_intrinsic_set_base(in_color_load, 0); + nir_intrinsic_set_range(in_color_load, 4); + in_color_load->src[0] = nir_src_for_ssa(nir_imm_int(&vs_b, 0)); + in_color_load->num_components = 1; + nir_ssa_dest_init(&in_color_load->instr, &in_color_load->dest, 1, 32, "depth value"); + nir_builder_instr_insert(&vs_b, &in_color_load->instr); + + nir_ssa_def *outvec = radv_meta_gen_rect_vertices_comp2(&vs_b, &in_color_load->dest.ssa); + nir_store_var(&vs_b, vs_out_pos, outvec, 0xf); + + const struct glsl_type *layer_type = glsl_int_type(); + nir_variable *vs_out_layer = + nir_variable_create(vs_b.shader, nir_var_shader_out, layer_type, + "v_layer"); + vs_out_layer->data.location = VARYING_SLOT_LAYER; + vs_out_layer->data.interpolation = INTERP_MODE_FLAT; + nir_ssa_def *inst_id = nir_load_system_value(&vs_b, nir_intrinsic_load_instance_id, 0); + nir_ssa_def *base_instance = nir_load_system_value(&vs_b, nir_intrinsic_load_base_instance, 0); + + nir_ssa_def *layer_id = nir_iadd(&vs_b, inst_id, base_instance); + nir_store_var(&vs_b, vs_out_layer, layer_id, 0x1); *out_vs = vs_b.shader; *out_fs = fs_b.shader; } +static VkResult +create_depthstencil_renderpass(struct radv_device *device, + uint32_t samples, + VkRenderPass *render_pass) +{ + return radv_CreateRenderPass(radv_device_to_handle(device), + &(VkRenderPassCreateInfo) { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, + .attachmentCount = 1, + .pAttachments = &(VkAttachmentDescription) { + .format = VK_FORMAT_D32_SFLOAT_S8_UINT, + .samples = samples, + .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .initialLayout = VK_IMAGE_LAYOUT_GENERAL, + .finalLayout = VK_IMAGE_LAYOUT_GENERAL, + }, + .subpassCount = 1, + .pSubpasses = &(VkSubpassDescription) { + .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, + .inputAttachmentCount = 0, + .colorAttachmentCount = 0, + .pColorAttachments = NULL, + .pResolveAttachments = NULL, + .pDepthStencilAttachment = &(VkAttachmentReference) { + .attachment = 0, + .layout = VK_IMAGE_LAYOUT_GENERAL, + }, + .preserveAttachmentCount = 1, + .pPreserveAttachments = (uint32_t[]) { 0 }, + }, + .dependencyCount = 0, + }, &device->meta_state.alloc, render_pass); +} + static VkResult create_depthstencil_pipeline(struct radv_device *device, VkImageAspectFlags aspects, uint32_t samples, int index, - struct radv_pipeline **pipeline, - VkRenderPass *render_pass) + VkPipeline *pipeline, + VkRenderPass render_pass) { struct nir_shader *vs_nir, *fs_nir; VkResult result; @@ -492,24 +493,8 @@ create_depthstencil_pipeline(struct radv_device *device, const VkPipelineVertexInputStateCreateInfo vi_state = { .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - .vertexBindingDescriptionCount = 1, - .pVertexBindingDescriptions = (VkVertexInputBindingDescription[]) { - { - .binding = 0, - .stride = sizeof(struct depthstencil_clear_vattrs), - .inputRate = VK_VERTEX_INPUT_RATE_VERTEX - }, - }, - .vertexAttributeDescriptionCount = 1, - .pVertexAttributeDescriptions = (VkVertexInputAttributeDescription[]) { - { - /* Position */ - .location = 0, - .binding = 0, - .format = VK_FORMAT_R32G32B32_SFLOAT, - .offset = offsetof(struct depthstencil_clear_vattrs, position), - }, - }, + .vertexBindingDescriptionCount = 0, + .vertexAttributeDescriptionCount = 0, }; const VkPipelineDepthStencilStateCreateInfo ds_state = { @@ -535,36 +520,6 @@ create_depthstencil_pipeline(struct radv_device *device, .pAttachments = NULL, }; - result = radv_CreateRenderPass(radv_device_to_handle(device), - &(VkRenderPassCreateInfo) { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - .attachmentCount = 1, - .pAttachments = &(VkAttachmentDescription) { - .format = VK_FORMAT_UNDEFINED, - .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, - .storeOp = VK_ATTACHMENT_STORE_OP_STORE, - .initialLayout = VK_IMAGE_LAYOUT_GENERAL, - .finalLayout = VK_IMAGE_LAYOUT_GENERAL, - }, - .subpassCount = 1, - .pSubpasses = &(VkSubpassDescription) { - .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, - .inputAttachmentCount = 0, - .colorAttachmentCount = 0, - .pColorAttachments = NULL, - .pResolveAttachments = NULL, - .pDepthStencilAttachment = &(VkAttachmentReference) { - .attachment = 0, - .layout = VK_IMAGE_LAYOUT_GENERAL, - }, - .preserveAttachmentCount = 1, - .pPreserveAttachments = (uint32_t[]) { 0 }, - }, - .dependencyCount = 0, - }, &device->meta_state.alloc, render_pass); - if (result != VK_SUCCESS) - return result; - struct radv_graphics_pipeline_create_info extra = { .use_rectlist = true, }; @@ -577,31 +532,44 @@ create_depthstencil_pipeline(struct radv_device *device, extra.db_stencil_clear = index == DEPTH_CLEAR_SLOW ? false : true; extra.db_stencil_disable_expclear = index == DEPTH_CLEAR_FAST_NO_EXPCLEAR ? true : false; } - result = create_pipeline(device, radv_render_pass_from_handle(*render_pass), + result = create_pipeline(device, radv_render_pass_from_handle(render_pass), samples, vs_nir, fs_nir, &vi_state, &ds_state, &cb_state, + device->meta_state.clear_depth_p_layout, &extra, &device->meta_state.alloc, pipeline); return result; } -static bool depth_view_can_fast_clear(const struct radv_image_view *iview, +static bool depth_view_can_fast_clear(struct radv_cmd_buffer *cmd_buffer, + const struct radv_image_view *iview, + VkImageAspectFlags aspects, VkImageLayout layout, - const VkClearRect *clear_rect) + const VkClearRect *clear_rect, + VkClearDepthStencilValue clear_value) { + uint32_t queue_mask = radv_image_queue_family_mask(iview->image, + cmd_buffer->queue_family_index, + cmd_buffer->queue_family_index); if (clear_rect->rect.offset.x || clear_rect->rect.offset.y || clear_rect->rect.extent.width != iview->extent.width || clear_rect->rect.extent.height != iview->extent.height) return false; - if (iview->image->htile.size && + if (iview->image->tc_compatible_htile && + (((aspects & VK_IMAGE_ASPECT_DEPTH_BIT) && clear_value.depth != 0.0 && + clear_value.depth != 1.0) || + ((aspects & VK_IMAGE_ASPECT_STENCIL_BIT) && clear_value.stencil != 0))) + return false; + if (iview->image->surface.htile_size && iview->base_mip == 0 && iview->base_layer == 0 && - radv_layout_can_expclear(iview->image, layout) && - memcmp(&iview->extent, &iview->image->extent, sizeof(iview->extent)) == 0) + radv_layout_is_htile_compressed(iview->image, layout, queue_mask) && + !radv_image_extent_compare(iview->image, &iview->extent)) return true; return false; } -static struct radv_pipeline * -pick_depthstencil_pipeline(struct radv_meta_state *meta_state, +static VkPipeline +pick_depthstencil_pipeline(struct radv_cmd_buffer *cmd_buffer, + struct radv_meta_state *meta_state, const struct radv_image_view *iview, int samples_log2, VkImageAspectFlags aspects, @@ -609,7 +577,7 @@ pick_depthstencil_pipeline(struct radv_meta_state *meta_state, const VkClearRect *clear_rect, VkClearDepthStencilValue clear_value) { - bool fast = depth_view_can_fast_clear(iview, layout, clear_rect); + bool fast = depth_view_can_fast_clear(cmd_buffer, iview, aspects, layout, clear_rect, clear_value); int index = DEPTH_CLEAR_SLOW; if (fast) { @@ -642,81 +610,144 @@ emit_depthstencil_clear(struct radv_cmd_buffer *cmd_buffer, VkClearDepthStencilValue clear_value = clear_att->clearValue.depthStencil; VkImageAspectFlags aspects = clear_att->aspectMask; const struct radv_image_view *iview = fb->attachments[pass_att].attachment; - const uint32_t samples = iview->image->samples; + const uint32_t samples = iview->image->info.samples; const uint32_t samples_log2 = ffs(samples) - 1; VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer); - uint32_t offset; - assert(aspects == VK_IMAGE_ASPECT_DEPTH_BIT || - aspects == VK_IMAGE_ASPECT_STENCIL_BIT || - aspects == (VK_IMAGE_ASPECT_DEPTH_BIT | - VK_IMAGE_ASPECT_STENCIL_BIT)); assert(pass_att != VK_ATTACHMENT_UNUSED); - const struct depthstencil_clear_vattrs vertex_data[3] = { - { - .position = { - clear_rect->rect.offset.x, - clear_rect->rect.offset.y, - }, - .depth_clear = clear_value.depth, - }, - { - .position = { - clear_rect->rect.offset.x, - clear_rect->rect.offset.y + clear_rect->rect.extent.height, - }, - .depth_clear = clear_value.depth, - }, - { - .position = { - clear_rect->rect.offset.x + clear_rect->rect.extent.width, - clear_rect->rect.offset.y, - }, - .depth_clear = clear_value.depth, - }, - }; + if (!(aspects & VK_IMAGE_ASPECT_DEPTH_BIT)) + clear_value.depth = 1.0f; - radv_cmd_buffer_upload_data(cmd_buffer, sizeof(vertex_data), 16, vertex_data, &offset); - struct radv_buffer vertex_buffer = { - .device = device, - .size = sizeof(vertex_data), - .bo = cmd_buffer->upload.upload_bo, - .offset = offset, - }; + radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer), + device->meta_state.clear_depth_p_layout, + VK_SHADER_STAGE_VERTEX_BIT, 0, 4, + &clear_value.depth); if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) { - RADV_CALL(CmdSetStencilReference)(cmd_buffer_h, VK_STENCIL_FACE_FRONT_BIT, + radv_CmdSetStencilReference(cmd_buffer_h, VK_STENCIL_FACE_FRONT_BIT, clear_value.stencil); } - RADV_CALL(CmdBindVertexBuffers)(cmd_buffer_h, 0, 1, - (VkBuffer[]) { radv_buffer_to_handle(&vertex_buffer) }, - (VkDeviceSize[]) { 0 }); - - struct radv_pipeline *pipeline = pick_depthstencil_pipeline(meta_state, - iview, - samples_log2, - aspects, - subpass->depth_stencil_attachment.layout, - clear_rect, - clear_value); - if (cmd_buffer->state.pipeline != pipeline) { - RADV_CALL(CmdBindPipeline)(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS, - radv_pipeline_to_handle(pipeline)); - } - - if (depth_view_can_fast_clear(iview, subpass->depth_stencil_attachment.layout, clear_rect)) + VkPipeline pipeline = pick_depthstencil_pipeline(cmd_buffer, + meta_state, + iview, + samples_log2, + aspects, + subpass->depth_stencil_attachment.layout, + clear_rect, + clear_value); + + radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS, + pipeline); + + if (depth_view_can_fast_clear(cmd_buffer, iview, aspects, + subpass->depth_stencil_attachment.layout, + clear_rect, clear_value)) radv_set_depth_clear_regs(cmd_buffer, iview->image, clear_value, aspects); - RADV_CALL(CmdDraw)(cmd_buffer_h, 3, 1, 0, 0); + radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &(VkViewport) { + .x = clear_rect->rect.offset.x, + .y = clear_rect->rect.offset.y, + .width = clear_rect->rect.extent.width, + .height = clear_rect->rect.extent.height, + .minDepth = 0.0f, + .maxDepth = 1.0f + }); + + radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &clear_rect->rect); + + radv_CmdDraw(cmd_buffer_h, 3, clear_rect->layerCount, 0, clear_rect->baseArrayLayer); } +static bool +emit_fast_htile_clear(struct radv_cmd_buffer *cmd_buffer, + const VkClearAttachment *clear_att, + const VkClearRect *clear_rect, + enum radv_cmd_flush_bits *pre_flush, + enum radv_cmd_flush_bits *post_flush) +{ + const struct radv_subpass *subpass = cmd_buffer->state.subpass; + const uint32_t pass_att = subpass->depth_stencil_attachment.attachment; + VkImageLayout image_layout = subpass->depth_stencil_attachment.layout; + const struct radv_framebuffer *fb = cmd_buffer->state.framebuffer; + const struct radv_image_view *iview = fb->attachments[pass_att].attachment; + VkClearDepthStencilValue clear_value = clear_att->clearValue.depthStencil; + VkImageAspectFlags aspects = clear_att->aspectMask; + uint32_t clear_word, flush_bits; + + if (!iview->image->surface.htile_size) + return false; + + if (cmd_buffer->device->instance->debug_flags & RADV_DEBUG_NO_FAST_CLEARS) + return false; + + if (!radv_layout_is_htile_compressed(iview->image, image_layout, radv_image_queue_family_mask(iview->image, cmd_buffer->queue_family_index, cmd_buffer->queue_family_index))) + goto fail; + + /* don't fast clear 3D */ + if (iview->image->type == VK_IMAGE_TYPE_3D) + goto fail; + + /* all layers are bound */ + if (iview->base_layer > 0) + goto fail; + if (iview->image->info.array_size != iview->layer_count) + goto fail; + + if (!radv_image_extent_compare(iview->image, &iview->extent)) + goto fail; + + if (clear_rect->rect.offset.x || clear_rect->rect.offset.y || + clear_rect->rect.extent.width != iview->image->info.width || + clear_rect->rect.extent.height != iview->image->info.height) + goto fail; + + if (clear_rect->baseArrayLayer != 0) + goto fail; + if (clear_rect->layerCount != iview->image->info.array_size) + goto fail; + + if ((clear_value.depth != 0.0 && clear_value.depth != 1.0) || !(aspects & VK_IMAGE_ASPECT_DEPTH_BIT)) + goto fail; + + if (vk_format_aspects(iview->image->vk_format) & VK_IMAGE_ASPECT_STENCIL_BIT) { + if (clear_value.stencil != 0 || !(aspects & VK_IMAGE_ASPECT_STENCIL_BIT)) + goto fail; + clear_word = clear_value.depth ? 0xfffc0000 : 0; + } else + clear_word = clear_value.depth ? 0xfffffff0 : 0; + + if (pre_flush) { + cmd_buffer->state.flush_bits |= (RADV_CMD_FLAG_FLUSH_AND_INV_DB | + RADV_CMD_FLAG_FLUSH_AND_INV_DB_META) & ~ *pre_flush; + *pre_flush |= cmd_buffer->state.flush_bits; + } else + cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_DB | + RADV_CMD_FLAG_FLUSH_AND_INV_DB_META; + + flush_bits = radv_fill_buffer(cmd_buffer, iview->image->bo, + iview->image->offset + iview->image->htile_offset, + iview->image->surface.htile_size, clear_word); + + radv_set_depth_clear_regs(cmd_buffer, iview->image, clear_value, aspects); + if (post_flush) { + *post_flush |= flush_bits; + } else { + cmd_buffer->state.flush_bits |= flush_bits; + } + + return true; +fail: + return false; +} static VkFormat pipeline_formats[] = { VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_UINT, VK_FORMAT_R8G8B8A8_SINT, + VK_FORMAT_A2R10G10B10_UINT_PACK32, + VK_FORMAT_A2R10G10B10_SINT_PACK32, VK_FORMAT_R16G16B16A16_UNORM, VK_FORMAT_R16G16B16A16_SNORM, VK_FORMAT_R16G16B16A16_UINT, @@ -732,7 +763,33 @@ radv_device_init_meta_clear_state(struct radv_device *device) VkResult res; struct radv_meta_state *state = &device->meta_state; - memset(&device->meta_state.clear, 0, sizeof(device->meta_state.clear)); + VkPipelineLayoutCreateInfo pl_color_create_info = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .setLayoutCount = 0, + .pushConstantRangeCount = 1, + .pPushConstantRanges = &(VkPushConstantRange){VK_SHADER_STAGE_FRAGMENT_BIT, 0, 16}, + }; + + res = radv_CreatePipelineLayout(radv_device_to_handle(device), + &pl_color_create_info, + &device->meta_state.alloc, + &device->meta_state.clear_color_p_layout); + if (res != VK_SUCCESS) + goto fail; + + VkPipelineLayoutCreateInfo pl_depth_create_info = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .setLayoutCount = 0, + .pushConstantRangeCount = 1, + .pPushConstantRanges = &(VkPushConstantRange){VK_SHADER_STAGE_VERTEX_BIT, 0, 4}, + }; + + res = radv_CreatePipelineLayout(radv_device_to_handle(device), + &pl_depth_create_info, + &device->meta_state.alloc, + &device->meta_state.clear_depth_p_layout); + if (res != VK_SUCCESS) + goto fail; for (uint32_t i = 0; i < ARRAY_SIZE(state->clear); ++i) { uint32_t samples = 1 << i; @@ -740,20 +797,32 @@ radv_device_init_meta_clear_state(struct radv_device *device) VkFormat format = pipeline_formats[j]; unsigned fs_key = radv_format_meta_fs_key(format); assert(!state->clear[i].color_pipelines[fs_key]); - res = create_color_pipeline(device, format, samples, 0, &state->clear[i].color_pipelines[fs_key], - &state->clear[i].render_pass[fs_key]); + + res = create_color_renderpass(device, format, samples, + &state->clear[i].render_pass[fs_key]); + if (res != VK_SUCCESS) + goto fail; + + res = create_color_pipeline(device, samples, 0, &state->clear[i].color_pipelines[fs_key], + state->clear[i].render_pass[fs_key]); if (res != VK_SUCCESS) goto fail; } + res = create_depthstencil_renderpass(device, + samples, + &state->clear[i].depthstencil_rp); + if (res != VK_SUCCESS) + goto fail; + for (uint32_t j = 0; j < NUM_DEPTH_CLEAR_PIPELINES; j++) { res = create_depthstencil_pipeline(device, VK_IMAGE_ASPECT_DEPTH_BIT, samples, j, &state->clear[i].depth_only_pipeline[j], - &state->clear[i].depth_only_rp[j]); + state->clear[i].depthstencil_rp); if (res != VK_SUCCESS) goto fail; @@ -762,7 +831,7 @@ radv_device_init_meta_clear_state(struct radv_device *device) samples, j, &state->clear[i].stencil_only_pipeline[j], - &state->clear[i].stencil_only_rp[j]); + state->clear[i].depthstencil_rp); if (res != VK_SUCCESS) goto fail; @@ -772,7 +841,7 @@ radv_device_init_meta_clear_state(struct radv_device *device) samples, j, &state->clear[i].depthstencil_pipeline[j], - &state->clear[i].depthstencil_rp[j]); + state->clear[i].depthstencil_rp); if (res != VK_SUCCESS) goto fail; } @@ -784,10 +853,90 @@ fail: return res; } +static void vi_get_fast_clear_parameters(VkFormat format, + const VkClearColorValue *clear_value, + uint32_t* reset_value, + bool *can_avoid_fast_clear_elim) +{ + bool values[4] = {}; + int extra_channel; + bool main_value = false; + bool extra_value = false; + int i; + *can_avoid_fast_clear_elim = false; + + *reset_value = 0x20202020U; + + const struct vk_format_description *desc = vk_format_description(format); + if (format == VK_FORMAT_B10G11R11_UFLOAT_PACK32 || + format == VK_FORMAT_R5G6B5_UNORM_PACK16 || + format == VK_FORMAT_B5G6R5_UNORM_PACK16) + extra_channel = -1; + else if (desc->layout == VK_FORMAT_LAYOUT_PLAIN) { + if (radv_translate_colorswap(format, false) <= 1) + extra_channel = desc->nr_channels - 1; + else + extra_channel = 0; + } else + return; + + for (i = 0; i < 4; i++) { + int index = desc->swizzle[i] - VK_SWIZZLE_X; + if (desc->swizzle[i] < VK_SWIZZLE_X || + desc->swizzle[i] > VK_SWIZZLE_W) + continue; + + if (desc->channel[i].pure_integer && + desc->channel[i].type == VK_FORMAT_TYPE_SIGNED) { + /* Use the maximum value for clamping the clear color. */ + int max = u_bit_consecutive(0, desc->channel[i].size - 1); + + values[i] = clear_value->int32[i] != 0; + if (clear_value->int32[i] != 0 && MIN2(clear_value->int32[i], max) != max) + return; + } else if (desc->channel[i].pure_integer && + desc->channel[i].type == VK_FORMAT_TYPE_UNSIGNED) { + /* Use the maximum value for clamping the clear color. */ + unsigned max = u_bit_consecutive(0, desc->channel[i].size); + + values[i] = clear_value->uint32[i] != 0U; + if (clear_value->uint32[i] != 0U && MIN2(clear_value->uint32[i], max) != max) + return; + } else { + values[i] = clear_value->float32[i] != 0.0F; + if (clear_value->float32[i] != 0.0F && clear_value->float32[i] != 1.0F) + return; + } + + if (index == extra_channel) + extra_value = values[i]; + else + main_value = values[i]; + } + + for (int i = 0; i < 4; ++i) + if (values[i] != main_value && + desc->swizzle[i] - VK_SWIZZLE_X != extra_channel && + desc->swizzle[i] >= VK_SWIZZLE_X && + desc->swizzle[i] <= VK_SWIZZLE_W) + return; + + *can_avoid_fast_clear_elim = true; + if (main_value) + *reset_value |= 0x80808080U; + + if (extra_value) + *reset_value |= 0x40404040U; + return; +} + static bool emit_fast_color_clear(struct radv_cmd_buffer *cmd_buffer, const VkClearAttachment *clear_att, - const VkClearRect *clear_rect) + const VkClearRect *clear_rect, + enum radv_cmd_flush_bits *pre_flush, + enum radv_cmd_flush_bits *post_flush, + uint32_t view_mask) { const struct radv_subpass *subpass = cmd_buffer->state.subpass; const uint32_t subpass_att = clear_att->colorAttachment; @@ -796,18 +945,16 @@ emit_fast_color_clear(struct radv_cmd_buffer *cmd_buffer, const struct radv_framebuffer *fb = cmd_buffer->state.framebuffer; const struct radv_image_view *iview = fb->attachments[pass_att].attachment; VkClearColorValue clear_value = clear_att->clearValue.color; - uint32_t clear_color[2]; + uint32_t clear_color[2], flush_bits; bool ret; if (!iview->image->cmask.size && !iview->image->surface.dcc_size) return false; - if (!cmd_buffer->device->allow_fast_clears) + if (cmd_buffer->device->instance->debug_flags & RADV_DEBUG_NO_FAST_CLEARS) return false; - if (!radv_layout_has_cmask(iview->image, image_layout)) - goto fail; - if (vk_format_get_blocksizebits(iview->image->vk_format) > 64) + if (!radv_layout_can_fast_clear(iview->image, image_layout, radv_image_queue_family_mask(iview->image, cmd_buffer->queue_family_index, cmd_buffer->queue_family_index))) goto fail; /* don't fast clear 3D */ @@ -817,26 +964,33 @@ emit_fast_color_clear(struct radv_cmd_buffer *cmd_buffer, /* all layers are bound */ if (iview->base_layer > 0) goto fail; - if (iview->image->array_size != iview->layer_count) + if (iview->image->info.array_size != iview->layer_count) goto fail; - if (iview->image->levels > 1) + if (iview->image->info.levels > 1) goto fail; - if (iview->image->surface.level[0].mode < RADEON_SURF_MODE_1D) + if (iview->image->surface.is_linear) goto fail; - - if (memcmp(&iview->extent, &iview->image->extent, sizeof(iview->extent))) + if (!radv_image_extent_compare(iview->image, &iview->extent)) goto fail; if (clear_rect->rect.offset.x || clear_rect->rect.offset.y || - clear_rect->rect.extent.width != iview->image->extent.width || - clear_rect->rect.extent.height != iview->image->extent.height) + clear_rect->rect.extent.width != iview->image->info.width || + clear_rect->rect.extent.height != iview->image->info.height) goto fail; - if (clear_rect->baseArrayLayer != 0) + if (view_mask && (iview->image->info.array_size >= 32 || + (1u << iview->image->info.array_size) - 1u != view_mask)) + goto fail; + if (!view_mask && clear_rect->baseArrayLayer != 0) goto fail; - if (clear_rect->layerCount != iview->image->array_size) + if (!view_mask && clear_rect->layerCount != iview->image->info.array_size) + goto fail; + + /* RB+ doesn't work with CMASK fast clear on Stoney. */ + if (!iview->image->surface.dcc_size && + cmd_buffer->device->physical_device->rad_info.family == CHIP_STONEY) goto fail; /* DCC */ @@ -845,22 +999,37 @@ emit_fast_color_clear(struct radv_cmd_buffer *cmd_buffer, if (ret == false) goto fail; - cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_CB | - RADV_CMD_FLAG_FLUSH_AND_INV_CB_META; - si_emit_cache_flush(cmd_buffer); + if (pre_flush) { + cmd_buffer->state.flush_bits |= (RADV_CMD_FLAG_FLUSH_AND_INV_CB | + RADV_CMD_FLAG_FLUSH_AND_INV_CB_META) & ~ *pre_flush; + *pre_flush |= cmd_buffer->state.flush_bits; + } else + cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_CB | + RADV_CMD_FLAG_FLUSH_AND_INV_CB_META; /* clear cmask buffer */ if (iview->image->surface.dcc_size) { - radv_fill_buffer(cmd_buffer, iview->image->bo, - iview->image->offset + iview->image->dcc_offset, - iview->image->surface.dcc_size, 0x20202020); + uint32_t reset_value; + bool can_avoid_fast_clear_elim; + vi_get_fast_clear_parameters(iview->image->vk_format, + &clear_value, &reset_value, + &can_avoid_fast_clear_elim); + + flush_bits = radv_fill_buffer(cmd_buffer, iview->image->bo, + iview->image->offset + iview->image->dcc_offset, + iview->image->surface.dcc_size, reset_value); + radv_set_dcc_need_cmask_elim_pred(cmd_buffer, iview->image, + !can_avoid_fast_clear_elim); + } else { + flush_bits = radv_fill_buffer(cmd_buffer, iview->image->bo, + iview->image->offset + iview->image->cmask.offset, + iview->image->cmask.size, 0); + } + + if (post_flush) { + *post_flush |= flush_bits; } else { - radv_fill_buffer(cmd_buffer, iview->image->bo, - iview->image->offset + iview->image->cmask.offset, - iview->image->cmask.size, 0); + cmd_buffer->state.flush_bits |= flush_bits; } - cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_CS_PARTIAL_FLUSH | - RADV_CMD_FLAG_INV_VMEM_L1 | - RADV_CMD_FLAG_INV_GLOBAL_L2; radv_set_color_clear_regs(cmd_buffer, iview->image, subpass_att, clear_color); @@ -875,41 +1044,74 @@ fail: static void emit_clear(struct radv_cmd_buffer *cmd_buffer, const VkClearAttachment *clear_att, - const VkClearRect *clear_rect) + const VkClearRect *clear_rect, + enum radv_cmd_flush_bits *pre_flush, + enum radv_cmd_flush_bits *post_flush, + uint32_t view_mask) { if (clear_att->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) { - - if (!emit_fast_color_clear(cmd_buffer, clear_att, clear_rect)) - emit_color_clear(cmd_buffer, clear_att, clear_rect); + if (!emit_fast_color_clear(cmd_buffer, clear_att, clear_rect, + pre_flush, post_flush, view_mask)) + emit_color_clear(cmd_buffer, clear_att, clear_rect, view_mask); } else { assert(clear_att->aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)); - emit_depthstencil_clear(cmd_buffer, clear_att, clear_rect); + if (!emit_fast_htile_clear(cmd_buffer, clear_att, clear_rect, + pre_flush, post_flush)) + emit_depthstencil_clear(cmd_buffer, clear_att, clear_rect); } } +static inline bool +radv_attachment_needs_clear(struct radv_cmd_state *cmd_state, uint32_t a) +{ + uint32_t view_mask = cmd_state->subpass->view_mask; + return (a != VK_ATTACHMENT_UNUSED && + cmd_state->attachments[a].pending_clear_aspects && + (!view_mask || (view_mask & ~cmd_state->attachments[a].cleared_views))); +} + static bool -subpass_needs_clear(const struct radv_cmd_buffer *cmd_buffer) +radv_subpass_needs_clear(struct radv_cmd_buffer *cmd_buffer) { - const struct radv_cmd_state *cmd_state = &cmd_buffer->state; - uint32_t ds; + struct radv_cmd_state *cmd_state = &cmd_buffer->state; + uint32_t a; if (!cmd_state->subpass) return false; - ds = cmd_state->subpass->depth_stencil_attachment.attachment; + for (uint32_t i = 0; i < cmd_state->subpass->color_count; ++i) { - uint32_t a = cmd_state->subpass->color_attachments[i].attachment; - if (cmd_state->attachments[a].pending_clear_aspects) { + a = cmd_state->subpass->color_attachments[i].attachment; + if (radv_attachment_needs_clear(cmd_state, a)) return true; - } } - if (ds != VK_ATTACHMENT_UNUSED && - cmd_state->attachments[ds].pending_clear_aspects) { - return true; - } + a = cmd_state->subpass->depth_stencil_attachment.attachment; + return radv_attachment_needs_clear(cmd_state, a); +} - return false; +static void +radv_subpass_clear_attachment(struct radv_cmd_buffer *cmd_buffer, + struct radv_attachment_state *attachment, + const VkClearAttachment *clear_att, + enum radv_cmd_flush_bits *pre_flush, + enum radv_cmd_flush_bits *post_flush) +{ + struct radv_cmd_state *cmd_state = &cmd_buffer->state; + uint32_t view_mask = cmd_state->subpass->view_mask; + + VkClearRect clear_rect = { + .rect = cmd_state->render_area, + .baseArrayLayer = 0, + .layerCount = cmd_state->framebuffer->layers, + }; + + emit_clear(cmd_buffer, clear_att, &clear_rect, pre_flush, post_flush, + view_mask & ~attachment->cleared_views); + if (view_mask) + attachment->cleared_views |= view_mask; + else + attachment->pending_clear_aspects = 0; } /** @@ -922,25 +1124,20 @@ radv_cmd_buffer_clear_subpass(struct radv_cmd_buffer *cmd_buffer) { struct radv_cmd_state *cmd_state = &cmd_buffer->state; struct radv_meta_saved_state saved_state; + enum radv_cmd_flush_bits pre_flush = 0; + enum radv_cmd_flush_bits post_flush = 0; - if (!subpass_needs_clear(cmd_buffer)) + if (!radv_subpass_needs_clear(cmd_buffer)) return; - radv_meta_save_graphics_reset_vport_scissor(&saved_state, cmd_buffer); - - if (cmd_state->framebuffer->layers > 1) - radv_finishme("clearing multi-layer framebuffer"); - - VkClearRect clear_rect = { - .rect = cmd_state->render_area, - .baseArrayLayer = 0, - .layerCount = 1, /* FINISHME: clear multi-layer framebuffer */ - }; + radv_meta_save(&saved_state, cmd_buffer, + RADV_META_SAVE_GRAPHICS_PIPELINE | + RADV_META_SAVE_CONSTANTS); for (uint32_t i = 0; i < cmd_state->subpass->color_count; ++i) { uint32_t a = cmd_state->subpass->color_attachments[i].attachment; - if (!cmd_state->attachments[a].pending_clear_aspects) + if (!radv_attachment_needs_clear(cmd_state, a)) continue; assert(cmd_state->attachments[a].pending_clear_aspects == @@ -952,38 +1149,166 @@ radv_cmd_buffer_clear_subpass(struct radv_cmd_buffer *cmd_buffer) .clearValue = cmd_state->attachments[a].clear_value, }; - emit_clear(cmd_buffer, &clear_att, &clear_rect); - cmd_state->attachments[a].pending_clear_aspects = 0; + radv_subpass_clear_attachment(cmd_buffer, + &cmd_state->attachments[a], + &clear_att, &pre_flush, + &post_flush); } uint32_t ds = cmd_state->subpass->depth_stencil_attachment.attachment; + if (radv_attachment_needs_clear(cmd_state, ds)) { + VkClearAttachment clear_att = { + .aspectMask = cmd_state->attachments[ds].pending_clear_aspects, + .clearValue = cmd_state->attachments[ds].clear_value, + }; - if (ds != VK_ATTACHMENT_UNUSED) { + radv_subpass_clear_attachment(cmd_buffer, + &cmd_state->attachments[ds], + &clear_att, &pre_flush, + &post_flush); + } - if (cmd_state->attachments[ds].pending_clear_aspects) { + radv_meta_restore(&saved_state, cmd_buffer); + cmd_buffer->state.flush_bits |= post_flush; +} - VkClearAttachment clear_att = { - .aspectMask = cmd_state->attachments[ds].pending_clear_aspects, - .clearValue = cmd_state->attachments[ds].clear_value, - }; +static void +radv_clear_image_layer(struct radv_cmd_buffer *cmd_buffer, + struct radv_image *image, + VkImageLayout image_layout, + const VkImageSubresourceRange *range, + VkFormat format, int level, int layer, + const VkClearValue *clear_val) +{ + VkDevice device_h = radv_device_to_handle(cmd_buffer->device); + struct radv_image_view iview; + uint32_t width = radv_minify(image->info.width, range->baseMipLevel + level); + uint32_t height = radv_minify(image->info.height, range->baseMipLevel + level); + + radv_image_view_init(&iview, cmd_buffer->device, + &(VkImageViewCreateInfo) { + .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + .image = radv_image_to_handle(image), + .viewType = radv_meta_get_view_type(image), + .format = format, + .subresourceRange = { + .aspectMask = range->aspectMask, + .baseMipLevel = range->baseMipLevel + level, + .levelCount = 1, + .baseArrayLayer = range->baseArrayLayer + layer, + .layerCount = 1 + }, + }); + + VkFramebuffer fb; + radv_CreateFramebuffer(device_h, + &(VkFramebufferCreateInfo) { + .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, + .attachmentCount = 1, + .pAttachments = (VkImageView[]) { + radv_image_view_to_handle(&iview), + }, + .width = width, + .height = height, + .layers = 1 + }, + &cmd_buffer->pool->alloc, + &fb); + + VkAttachmentDescription att_desc = { + .format = iview.vk_format, + .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD, + .stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE, + .initialLayout = image_layout, + .finalLayout = image_layout, + }; - emit_clear(cmd_buffer, &clear_att, &clear_rect); - cmd_state->attachments[ds].pending_clear_aspects = 0; - } + VkSubpassDescription subpass_desc = { + .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, + .inputAttachmentCount = 0, + .colorAttachmentCount = 0, + .pColorAttachments = NULL, + .pResolveAttachments = NULL, + .pDepthStencilAttachment = NULL, + .preserveAttachmentCount = 0, + .pPreserveAttachments = NULL, + }; + + const VkAttachmentReference att_ref = { + .attachment = 0, + .layout = image_layout, + }; + + if (range->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) { + subpass_desc.colorAttachmentCount = 1; + subpass_desc.pColorAttachments = &att_ref; + } else { + subpass_desc.pDepthStencilAttachment = &att_ref; } - radv_meta_restore(&saved_state, cmd_buffer); -} + VkRenderPass pass; + radv_CreateRenderPass(device_h, + &(VkRenderPassCreateInfo) { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, + .attachmentCount = 1, + .pAttachments = &att_desc, + .subpassCount = 1, + .pSubpasses = &subpass_desc, + }, + &cmd_buffer->pool->alloc, + &pass); + + radv_CmdBeginRenderPass(radv_cmd_buffer_to_handle(cmd_buffer), + &(VkRenderPassBeginInfo) { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + .renderArea = { + .offset = { 0, 0, }, + .extent = { + .width = width, + .height = height, + }, + }, + .renderPass = pass, + .framebuffer = fb, + .clearValueCount = 0, + .pClearValues = NULL, + }, + VK_SUBPASS_CONTENTS_INLINE); + + VkClearAttachment clear_att = { + .aspectMask = range->aspectMask, + .colorAttachment = 0, + .clearValue = *clear_val, + }; + + VkClearRect clear_rect = { + .rect = { + .offset = { 0, 0 }, + .extent = { width, height }, + }, + .baseArrayLayer = range->baseArrayLayer, + .layerCount = 1, /* FINISHME: clear multi-layer framebuffer */ + }; + + emit_clear(cmd_buffer, &clear_att, &clear_rect, NULL, NULL, 0); + radv_CmdEndRenderPass(radv_cmd_buffer_to_handle(cmd_buffer)); + radv_DestroyRenderPass(device_h, pass, + &cmd_buffer->pool->alloc); + radv_DestroyFramebuffer(device_h, fb, + &cmd_buffer->pool->alloc); +} static void radv_cmd_clear_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image, VkImageLayout image_layout, const VkClearValue *clear_value, uint32_t range_count, - const VkImageSubresourceRange *ranges) + const VkImageSubresourceRange *ranges, + bool cs) { - VkDevice device_h = radv_device_to_handle(cmd_buffer->device); VkFormat format = image->vk_format; VkClearValue internal_clear_value = *clear_value; @@ -994,129 +1319,35 @@ radv_cmd_clear_image(struct radv_cmd_buffer *cmd_buffer, internal_clear_value.color.uint32[0] = value; } + if (format == VK_FORMAT_R4G4_UNORM_PACK8) { + uint8_t r, g; + format = VK_FORMAT_R8_UINT; + r = float_to_ubyte(clear_value->color.float32[0]) >> 4; + g = float_to_ubyte(clear_value->color.float32[1]) >> 4; + internal_clear_value.color.uint32[0] = (r << 4) | (g & 0xf); + } + for (uint32_t r = 0; r < range_count; r++) { const VkImageSubresourceRange *range = &ranges[r]; for (uint32_t l = 0; l < radv_get_levelCount(image, range); ++l) { const uint32_t layer_count = image->type == VK_IMAGE_TYPE_3D ? - radv_minify(image->extent.depth, l) : + radv_minify(image->info.depth, range->baseMipLevel + l) : radv_get_layerCount(image, range); for (uint32_t s = 0; s < layer_count; ++s) { - struct radv_image_view iview; - radv_image_view_init(&iview, cmd_buffer->device, - &(VkImageViewCreateInfo) { - .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - .image = radv_image_to_handle(image), - .viewType = radv_meta_get_view_type(image), - .format = format, - .subresourceRange = { - .aspectMask = range->aspectMask, - .baseMipLevel = range->baseMipLevel + l, - .levelCount = 1, - .baseArrayLayer = range->baseArrayLayer + s, - .layerCount = 1 - }, - }, - cmd_buffer, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); - - VkFramebuffer fb; - radv_CreateFramebuffer(device_h, - &(VkFramebufferCreateInfo) { - .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, - .attachmentCount = 1, - .pAttachments = (VkImageView[]) { - radv_image_view_to_handle(&iview), - }, - .width = iview.extent.width, - .height = iview.extent.height, - .layers = 1 - }, - &cmd_buffer->pool->alloc, - &fb); - - VkAttachmentDescription att_desc = { - .format = iview.vk_format, - .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, - .storeOp = VK_ATTACHMENT_STORE_OP_STORE, - .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD, - .stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE, - .initialLayout = image_layout, - .finalLayout = image_layout, - }; - - VkSubpassDescription subpass_desc = { - .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, - .inputAttachmentCount = 0, - .colorAttachmentCount = 0, - .pColorAttachments = NULL, - .pResolveAttachments = NULL, - .pDepthStencilAttachment = NULL, - .preserveAttachmentCount = 0, - .pPreserveAttachments = NULL, - }; - - const VkAttachmentReference att_ref = { - .attachment = 0, - .layout = image_layout, - }; - - if (range->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) { - subpass_desc.colorAttachmentCount = 1; - subpass_desc.pColorAttachments = &att_ref; + + if (cs) { + struct radv_meta_blit2d_surf surf; + surf.format = format; + surf.image = image; + surf.level = range->baseMipLevel + l; + surf.layer = range->baseArrayLayer + s; + surf.aspect_mask = range->aspectMask; + radv_meta_clear_image_cs(cmd_buffer, &surf, + &internal_clear_value.color); } else { - subpass_desc.pDepthStencilAttachment = &att_ref; + radv_clear_image_layer(cmd_buffer, image, image_layout, + range, format, l, s, &internal_clear_value); } - - VkRenderPass pass; - radv_CreateRenderPass(device_h, - &(VkRenderPassCreateInfo) { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - .attachmentCount = 1, - .pAttachments = &att_desc, - .subpassCount = 1, - .pSubpasses = &subpass_desc, - }, - &cmd_buffer->pool->alloc, - &pass); - - RADV_CALL(CmdBeginRenderPass)(radv_cmd_buffer_to_handle(cmd_buffer), - &(VkRenderPassBeginInfo) { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .renderArea = { - .offset = { 0, 0, }, - .extent = { - .width = iview.extent.width, - .height = iview.extent.height, - }, - }, - .renderPass = pass, - .framebuffer = fb, - .clearValueCount = 0, - .pClearValues = NULL, - }, - VK_SUBPASS_CONTENTS_INLINE); - - VkClearAttachment clear_att = { - .aspectMask = range->aspectMask, - .colorAttachment = 0, - .clearValue = internal_clear_value, - }; - - VkClearRect clear_rect = { - .rect = { - .offset = { 0, 0 }, - .extent = { iview.extent.width, iview.extent.height }, - }, - .baseArrayLayer = range->baseArrayLayer, - .layerCount = 1, /* FINISHME: clear multi-layer framebuffer */ - }; - - emit_clear(cmd_buffer, &clear_att, &clear_rect); - - RADV_CALL(CmdEndRenderPass)(radv_cmd_buffer_to_handle(cmd_buffer)); - RADV_CALL(DestroyRenderPass)(device_h, pass, - &cmd_buffer->pool->alloc); - RADV_CALL(DestroyFramebuffer)(device_h, fb, - &cmd_buffer->pool->alloc); } } } @@ -1133,12 +1364,22 @@ void radv_CmdClearColorImage( RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer); RADV_FROM_HANDLE(radv_image, image, image_h); struct radv_meta_saved_state saved_state; + bool cs = cmd_buffer->queue_family_index == RADV_QUEUE_COMPUTE; - radv_meta_save_graphics_reset_vport_scissor(&saved_state, cmd_buffer); + if (cs) { + radv_meta_save(&saved_state, cmd_buffer, + RADV_META_SAVE_COMPUTE_PIPELINE | + RADV_META_SAVE_CONSTANTS | + RADV_META_SAVE_DESCRIPTORS); + } else { + radv_meta_save(&saved_state, cmd_buffer, + RADV_META_SAVE_GRAPHICS_PIPELINE | + RADV_META_SAVE_CONSTANTS); + } radv_cmd_clear_image(cmd_buffer, image, imageLayout, (const VkClearValue *) pColor, - rangeCount, pRanges); + rangeCount, pRanges, cs); radv_meta_restore(&saved_state, cmd_buffer); } @@ -1155,11 +1396,13 @@ void radv_CmdClearDepthStencilImage( RADV_FROM_HANDLE(radv_image, image, image_h); struct radv_meta_saved_state saved_state; - radv_meta_save_graphics_reset_vport_scissor(&saved_state, cmd_buffer); + radv_meta_save(&saved_state, cmd_buffer, + RADV_META_SAVE_GRAPHICS_PIPELINE | + RADV_META_SAVE_CONSTANTS); radv_cmd_clear_image(cmd_buffer, image, imageLayout, (const VkClearValue *) pDepthStencil, - rangeCount, pRanges); + rangeCount, pRanges, false); radv_meta_restore(&saved_state, cmd_buffer); } @@ -1173,20 +1416,26 @@ void radv_CmdClearAttachments( { RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer); struct radv_meta_saved_state saved_state; + enum radv_cmd_flush_bits pre_flush = 0; + enum radv_cmd_flush_bits post_flush = 0; if (!cmd_buffer->state.subpass) return; - radv_meta_save_graphics_reset_vport_scissor(&saved_state, cmd_buffer); + radv_meta_save(&saved_state, cmd_buffer, + RADV_META_SAVE_GRAPHICS_PIPELINE | + RADV_META_SAVE_CONSTANTS); /* FINISHME: We can do better than this dumb loop. It thrashes too much * state. */ for (uint32_t a = 0; a < attachmentCount; ++a) { for (uint32_t r = 0; r < rectCount; ++r) { - emit_clear(cmd_buffer, &pAttachments[a], &pRects[r]); + emit_clear(cmd_buffer, &pAttachments[a], &pRects[r], &pre_flush, &post_flush, + cmd_buffer->state.subpass->view_mask); } } radv_meta_restore(&saved_state, cmd_buffer); + cmd_buffer->state.flush_bits |= post_flush; }