radv: silent a compiler warning in radv_CmdPushDescriptorSetKHR()
[mesa.git] / src / amd / vulkan / radv_meta_resolve_fs.c
index 499b3ae27af5031f7bb1470568a0ee68aa107950..d059760edf1034c3e9fd50ad32640c45c7937d81 100644 (file)
@@ -156,30 +156,23 @@ static const VkPipelineVertexInputStateCreateInfo normal_vi_create_info = {
        .vertexAttributeDescriptionCount = 0,
 };
 
-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,
-   VK_FORMAT_R16G16B16A16_SINT,
-   VK_FORMAT_R32_SFLOAT,
-   VK_FORMAT_R32G32_SFLOAT,
-   VK_FORMAT_R32G32B32A32_SFLOAT
-};
-
 static VkResult
 create_resolve_pipeline(struct radv_device *device,
                        int samples_log2,
                        VkFormat format)
 {
+       mtx_lock(&device->meta_state.mtx);
+
+       unsigned fs_key = radv_format_meta_fs_key(format);
+       VkPipeline *pipeline = &device->meta_state.resolve_fragment.rc[samples_log2].pipeline[fs_key];
+       if (*pipeline) {
+               mtx_unlock(&device->meta_state.mtx);
+               return VK_SUCCESS;
+       }
+
        VkResult result;
        bool is_integer = false;
        uint32_t samples = 1 << samples_log2;
-       unsigned fs_key = radv_format_meta_fs_key(format);
        const VkPipelineVertexInputStateCreateInfo *vi_create_info;
        vi_create_info = &normal_vi_create_info;
        if (vk_format_is_int(format))
@@ -195,9 +188,6 @@ create_resolve_pipeline(struct radv_device *device,
 
        assert(!*rp);
 
-       VkPipeline *pipeline = &device->meta_state.resolve_fragment.rc[samples_log2].pipeline[fs_key];
-       assert(!*pipeline);
-
        VkPipelineShaderStageCreateInfo pipeline_shader_stages[] = {
                {
                        .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
@@ -242,8 +232,8 @@ create_resolve_pipeline(struct radv_device *device,
                                                        .attachment = VK_ATTACHMENT_UNUSED,
                                                        .layout = VK_IMAGE_LAYOUT_GENERAL,
                                                },
-                                               .preserveAttachmentCount = 1,
-                                               .pPreserveAttachments = (uint32_t[]) { 0 },
+                                               .preserveAttachmentCount = 0,
+                                               .pPreserveAttachments = NULL,
                                        },
                                        .dependencyCount = 0,
                                }, &device->meta_state.alloc, rp + dst_layout);
@@ -322,11 +312,12 @@ create_resolve_pipeline(struct radv_device *device,
        ralloc_free(vs.nir);
        ralloc_free(fs.nir);
 
+       mtx_unlock(&device->meta_state.mtx);
        return result;
 }
 
 VkResult
-radv_device_init_meta_resolve_fragment_state(struct radv_device *device)
+radv_device_init_meta_resolve_fragment_state(struct radv_device *device, bool on_demand)
 {
        VkResult res;
 
@@ -334,9 +325,12 @@ radv_device_init_meta_resolve_fragment_state(struct radv_device *device)
        if (res != VK_SUCCESS)
                goto fail;
 
+       if (on_demand)
+               return VK_SUCCESS;
+
        for (uint32_t i = 0; i < MAX_SAMPLES_LOG2; ++i) {
-               for (unsigned j = 0; j < ARRAY_SIZE(pipeline_formats); ++j) {
-                       res = create_resolve_pipeline(device, i, pipeline_formats[j]);
+               for (unsigned j = 0; j < NUM_META_FS_KEYS; ++j) {
+                       res = create_resolve_pipeline(device, i, radv_fs_key_format_exemplars[j]);
                        if (res != VK_SUCCESS)
                                goto fail;
                }
@@ -373,6 +367,32 @@ radv_device_finish_meta_resolve_fragment_state(struct radv_device *device)
                                   &state->alloc);
 }
 
+static VkPipeline *
+radv_get_resolve_pipeline(struct radv_cmd_buffer *cmd_buffer,
+                         struct radv_image_view *src_iview,
+                         struct radv_image_view *dst_iview)
+{
+       struct radv_device *device = cmd_buffer->device;
+       unsigned fs_key = radv_format_meta_fs_key(dst_iview->vk_format);
+       const uint32_t samples = src_iview->image->info.samples;
+       const uint32_t samples_log2 = ffs(samples) - 1;
+       VkPipeline *pipeline;
+
+       pipeline = &device->meta_state.resolve_fragment.rc[samples_log2].pipeline[fs_key];
+       if (!*pipeline ) {
+               VkResult ret;
+
+               ret = create_resolve_pipeline(device, samples_log2,
+                                             radv_fs_key_format_exemplars[fs_key]);
+               if (ret != VK_SUCCESS) {
+                       cmd_buffer->record_result = ret;
+                       return NULL;
+               }
+       }
+
+       return pipeline;
+}
+
 static void
 emit_resolve(struct radv_cmd_buffer *cmd_buffer,
             struct radv_image_view *src_iview,
@@ -383,8 +403,8 @@ emit_resolve(struct radv_cmd_buffer *cmd_buffer,
 {
        struct radv_device *device = cmd_buffer->device;
        VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
-       const uint32_t samples = src_iview->image->info.samples;
-       const uint32_t samples_log2 = ffs(samples) - 1;
+       VkPipeline *pipeline;
+
        radv_meta_push_descriptor_set(cmd_buffer,
                                      VK_PIPELINE_BIND_POINT_GRAPHICS,
                                      cmd_buffer->device->meta_state.resolve_fragment.p_layout,
@@ -418,11 +438,10 @@ emit_resolve(struct radv_cmd_buffer *cmd_buffer,
                              VK_SHADER_STAGE_FRAGMENT_BIT, 0, 8,
                              push_constants);
 
-       unsigned fs_key = radv_format_meta_fs_key(dest_iview->vk_format);
-       VkPipeline pipeline_h = device->meta_state.resolve_fragment.rc[samples_log2].pipeline[fs_key];
+       pipeline = radv_get_resolve_pipeline(cmd_buffer, src_iview, dest_iview);
 
        radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS,
-                            pipeline_h);
+                            *pipeline);
 
        radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &(VkViewport) {
                .x = dest_offset->x,
@@ -458,9 +477,17 @@ void radv_meta_resolve_fragment_image(struct radv_cmd_buffer *cmd_buffer,
        unsigned dst_layout = radv_meta_dst_layout_from_layout(dest_image_layout);
        VkRenderPass rp;
 
-       radv_decompress_resolve_src(cmd_buffer, src_image,
+       radv_decompress_resolve_src(cmd_buffer, src_image, src_image_layout,
                                    region_count, regions);
 
+       if (!device->meta_state.resolve_fragment.rc[samples_log2].render_pass[fs_key][dst_layout]) {
+               VkResult ret = create_resolve_pipeline(device, samples_log2, radv_fs_key_format_exemplars[fs_key]);
+               if (ret != VK_SUCCESS) {
+                       cmd_buffer->record_result = ret;
+                       return;
+               }
+       }
+
        rp = device->meta_state.resolve_fragment.rc[samples_log2].render_pass[fs_key][dst_layout];
 
        radv_meta_save(&saved_state, cmd_buffer,
@@ -580,42 +607,27 @@ radv_cmd_buffer_resolve_subpass_fs(struct radv_cmd_buffer *cmd_buffer)
        struct radv_framebuffer *fb = cmd_buffer->state.framebuffer;
        const struct radv_subpass *subpass = cmd_buffer->state.subpass;
        struct radv_meta_saved_state saved_state;
+       struct radv_subpass_barrier barrier;
 
-       /* FINISHME(perf): Skip clears for resolve attachments.
-        *
-        * From the Vulkan 1.0 spec:
-        *
-        *    If the first use of an attachment in a render pass is as a resolve
-        *    attachment, then the loadOp is effectively ignored as the resolve is
-        *    guaranteed to overwrite all pixels in the render area.
-        */
+       /* Resolves happen before the end-of-subpass barriers get executed,
+        * so we have to make the attachment shader-readable */
+       barrier.src_stage_mask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+       barrier.src_access_mask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+       barrier.dst_access_mask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
+       radv_subpass_barrier(cmd_buffer, &barrier);
 
-       if (!subpass->has_resolve)
-               return;
+       radv_decompress_resolve_subpass_src(cmd_buffer);
 
        radv_meta_save(&saved_state, cmd_buffer,
                       RADV_META_SAVE_GRAPHICS_PIPELINE |
                       RADV_META_SAVE_CONSTANTS |
                       RADV_META_SAVE_DESCRIPTORS);
 
-       /* Resolves happen before the end-of-subpass barriers get executed,
-        * so we have to make the attachment shader-readable */
-       cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_PS_PARTIAL_FLUSH |
-                                       RADV_CMD_FLAG_FLUSH_AND_INV_CB |
-                                       RADV_CMD_FLAG_FLUSH_AND_INV_CB_META |
-                                       RADV_CMD_FLAG_FLUSH_AND_INV_DB |
-                                       RADV_CMD_FLAG_FLUSH_AND_INV_DB_META |
-                                       RADV_CMD_FLAG_INV_GLOBAL_L2 |
-                                       RADV_CMD_FLAG_INV_VMEM_L1;
-
-       radv_decompress_resolve_subpass_src(cmd_buffer);
-
        for (uint32_t i = 0; i < subpass->color_count; ++i) {
-               VkAttachmentReference src_att = subpass->color_attachments[i];
-               VkAttachmentReference dest_att = subpass->resolve_attachments[i];
+               struct radv_subpass_attachment src_att = subpass->color_attachments[i];
+               struct radv_subpass_attachment dest_att = subpass->resolve_attachments[i];
 
-               if (src_att.attachment == VK_ATTACHMENT_UNUSED ||
-                   dest_att.attachment == VK_ATTACHMENT_UNUSED)
+               if (dest_att.attachment == VK_ATTACHMENT_UNUSED)
                        continue;
 
                struct radv_image_view *dest_iview = cmd_buffer->state.framebuffer->attachments[dest_att.attachment].attachment;
@@ -623,11 +635,11 @@ radv_cmd_buffer_resolve_subpass_fs(struct radv_cmd_buffer *cmd_buffer)
 
                struct radv_subpass resolve_subpass = {
                        .color_count = 1,
-                       .color_attachments = (VkAttachmentReference[]) { dest_att },
-                       .depth_stencil_attachment = { .attachment = VK_ATTACHMENT_UNUSED },
+                       .color_attachments = (struct radv_subpass_attachment[]) { dest_att },
+                       .depth_stencil_attachment = NULL,
                };
 
-               radv_cmd_buffer_set_subpass(cmd_buffer, &resolve_subpass, false);
+               radv_cmd_buffer_set_subpass(cmd_buffer, &resolve_subpass);
 
                emit_resolve(cmd_buffer,
                             src_iview,
@@ -637,6 +649,7 @@ radv_cmd_buffer_resolve_subpass_fs(struct radv_cmd_buffer *cmd_buffer)
                             &(VkExtent2D) { fb->width, fb->height });
        }
 
-       cmd_buffer->state.subpass = subpass;
+       radv_cmd_buffer_set_subpass(cmd_buffer, subpass);
+
        radv_meta_restore(&saved_state, cmd_buffer);
 }