2016-10-07 09:16:09 +10:00
|
|
|
/*
|
|
|
|
* Copyright © 2016 Intel Corporation
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
* Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
|
* IN THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
2021-04-10 03:24:05 +02:00
|
|
|
#include "nir/nir_builder.h"
|
2016-10-07 09:16:09 +10:00
|
|
|
#include "radv_meta.h"
|
|
|
|
#include "radv_private.h"
|
|
|
|
#include "sid.h"
|
2021-04-10 03:24:05 +02:00
|
|
|
#include "vk_format.h"
|
2016-10-07 09:16:09 +10:00
|
|
|
|
2017-04-19 09:13:06 +10:00
|
|
|
/* emit 0, 0, 0, 1 */
|
2016-10-07 09:16:09 +10:00
|
|
|
static nir_shader *
|
2022-03-30 11:52:58 +01:00
|
|
|
build_nir_fs(struct radv_device *dev)
|
2016-10-07 09:16:09 +10:00
|
|
|
{
|
2021-04-10 03:24:05 +02:00
|
|
|
const struct glsl_type *vec4 = glsl_vec4_type();
|
|
|
|
nir_variable *f_color; /* vec4, fragment output color */
|
2016-10-07 09:16:09 +10:00
|
|
|
|
2022-03-30 11:52:58 +01:00
|
|
|
nir_builder b = radv_meta_init_shader(dev, MESA_SHADER_FRAGMENT, "meta_resolve_fs");
|
2016-10-07 09:16:09 +10:00
|
|
|
|
2021-04-10 03:24:05 +02:00
|
|
|
f_color = nir_variable_create(b.shader, nir_var_shader_out, vec4, "f_color");
|
|
|
|
f_color->data.location = FRAG_RESULT_DATA0;
|
|
|
|
nir_store_var(&b, f_color, nir_imm_vec4(&b, 0.0, 0.0, 0.0, 1.0), 0xf);
|
2016-10-07 09:16:09 +10:00
|
|
|
|
2021-04-10 03:24:05 +02:00
|
|
|
return b.shader;
|
2016-10-07 09:16:09 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
static VkResult
|
2022-03-17 09:51:07 +01:00
|
|
|
create_pipeline(struct radv_device *device, VkShaderModule vs_module_h, VkFormat format,
|
|
|
|
VkPipeline *pipeline)
|
2016-10-07 09:16:09 +10:00
|
|
|
{
|
2021-04-10 03:24:05 +02:00
|
|
|
VkResult result;
|
|
|
|
VkDevice device_h = radv_device_to_handle(device);
|
|
|
|
|
2022-03-30 11:52:58 +01:00
|
|
|
nir_shader *fs_module = build_nir_fs(device);
|
2021-04-10 03:24:05 +02:00
|
|
|
if (!fs_module) {
|
|
|
|
/* XXX: Need more accurate error */
|
|
|
|
result = VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
VkPipelineLayoutCreateInfo pl_create_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
|
|
|
.setLayoutCount = 0,
|
|
|
|
.pSetLayouts = NULL,
|
|
|
|
.pushConstantRangeCount = 0,
|
|
|
|
.pPushConstantRanges = NULL,
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!device->meta_state.resolve.p_layout) {
|
|
|
|
result =
|
|
|
|
radv_CreatePipelineLayout(radv_device_to_handle(device), &pl_create_info,
|
|
|
|
&device->meta_state.alloc, &device->meta_state.resolve.p_layout);
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2022-03-17 09:51:07 +01:00
|
|
|
VkFormat color_formats[2] = { format, format };
|
|
|
|
const VkPipelineRenderingCreateInfo rendering_create_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
|
|
|
|
.colorAttachmentCount = 2,
|
|
|
|
.pColorAttachmentFormats = color_formats,
|
|
|
|
};
|
|
|
|
|
2021-04-10 03:24:05 +02:00
|
|
|
result = radv_graphics_pipeline_create(
|
|
|
|
device_h, radv_pipeline_cache_to_handle(&device->meta_state.cache),
|
|
|
|
&(VkGraphicsPipelineCreateInfo){
|
|
|
|
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
2022-03-17 09:51:07 +01:00
|
|
|
.pNext = &rendering_create_info,
|
2021-04-10 03:24:05 +02:00
|
|
|
.stageCount = 2,
|
|
|
|
.pStages =
|
|
|
|
(VkPipelineShaderStageCreateInfo[]){
|
|
|
|
{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
|
|
|
.stage = VK_SHADER_STAGE_VERTEX_BIT,
|
|
|
|
.module = vs_module_h,
|
|
|
|
.pName = "main",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
|
|
|
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
|
|
|
|
.module = vk_shader_module_handle_from_nir(fs_module),
|
|
|
|
.pName = "main",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
.pVertexInputState =
|
|
|
|
&(VkPipelineVertexInputStateCreateInfo){
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
|
|
|
.vertexBindingDescriptionCount = 0,
|
|
|
|
.vertexAttributeDescriptionCount = 0,
|
|
|
|
},
|
|
|
|
.pInputAssemblyState =
|
|
|
|
&(VkPipelineInputAssemblyStateCreateInfo){
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
|
|
|
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
|
|
|
|
.primitiveRestartEnable = false,
|
|
|
|
},
|
|
|
|
.pViewportState =
|
|
|
|
&(VkPipelineViewportStateCreateInfo){
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
|
|
|
.viewportCount = 1,
|
|
|
|
.scissorCount = 1,
|
|
|
|
},
|
|
|
|
.pRasterizationState =
|
|
|
|
&(VkPipelineRasterizationStateCreateInfo){
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
|
|
|
.depthClampEnable = false,
|
|
|
|
.rasterizerDiscardEnable = false,
|
|
|
|
.polygonMode = VK_POLYGON_MODE_FILL,
|
|
|
|
.cullMode = VK_CULL_MODE_NONE,
|
|
|
|
.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
|
|
|
|
},
|
|
|
|
.pMultisampleState =
|
|
|
|
&(VkPipelineMultisampleStateCreateInfo){
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
|
|
|
.rasterizationSamples = 1,
|
|
|
|
.sampleShadingEnable = false,
|
|
|
|
.pSampleMask = NULL,
|
|
|
|
.alphaToCoverageEnable = false,
|
|
|
|
.alphaToOneEnable = false,
|
|
|
|
},
|
|
|
|
.pColorBlendState =
|
|
|
|
&(VkPipelineColorBlendStateCreateInfo){
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
|
|
|
|
.logicOpEnable = false,
|
|
|
|
.attachmentCount = 2,
|
|
|
|
.pAttachments =
|
|
|
|
(VkPipelineColorBlendAttachmentState[]){
|
|
|
|
{
|
|
|
|
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
|
|
|
|
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.colorWriteMask = 0,
|
|
|
|
|
|
|
|
}},
|
|
|
|
},
|
|
|
|
.pDynamicState =
|
|
|
|
&(VkPipelineDynamicStateCreateInfo){
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
|
|
|
.dynamicStateCount = 2,
|
|
|
|
.pDynamicStates =
|
|
|
|
(VkDynamicState[]){
|
|
|
|
VK_DYNAMIC_STATE_VIEWPORT,
|
|
|
|
VK_DYNAMIC_STATE_SCISSOR,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
.layout = device->meta_state.resolve.p_layout,
|
2022-03-17 09:51:07 +01:00
|
|
|
.renderPass = VK_NULL_HANDLE,
|
2021-04-10 03:24:05 +02:00
|
|
|
.subpass = 0,
|
|
|
|
},
|
|
|
|
&(struct radv_graphics_pipeline_create_info){
|
|
|
|
.use_rectlist = true,
|
|
|
|
.custom_blend_mode = V_028808_CB_RESOLVE,
|
|
|
|
},
|
|
|
|
&device->meta_state.alloc, pipeline);
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
goto cleanup;
|
2016-10-07 09:16:09 +10:00
|
|
|
|
|
|
|
cleanup:
|
2021-04-10 03:24:05 +02:00
|
|
|
ralloc_free(fs_module);
|
|
|
|
return result;
|
2016-10-07 09:16:09 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
radv_device_finish_meta_resolve_state(struct radv_device *device)
|
|
|
|
{
|
2021-04-10 03:24:05 +02:00
|
|
|
struct radv_meta_state *state = &device->meta_state;
|
|
|
|
|
|
|
|
for (uint32_t j = 0; j < NUM_META_FS_KEYS; j++) {
|
|
|
|
radv_DestroyPipeline(radv_device_to_handle(device), state->resolve.pipeline[j],
|
|
|
|
&state->alloc);
|
|
|
|
}
|
|
|
|
radv_DestroyPipelineLayout(radv_device_to_handle(device), state->resolve.p_layout,
|
|
|
|
&state->alloc);
|
2016-10-07 09:16:09 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
VkResult
|
2018-08-14 00:07:57 +02:00
|
|
|
radv_device_init_meta_resolve_state(struct radv_device *device, bool on_demand)
|
2016-10-07 09:16:09 +10:00
|
|
|
{
|
2021-04-10 03:24:05 +02:00
|
|
|
if (on_demand)
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
|
|
|
VkResult res = VK_SUCCESS;
|
|
|
|
struct radv_meta_state *state = &device->meta_state;
|
2022-03-30 11:52:58 +01:00
|
|
|
nir_shader *vs_module = radv_meta_build_nir_vs_generate_vertices(device);
|
2021-04-10 03:24:05 +02:00
|
|
|
if (!vs_module) {
|
|
|
|
/* XXX: Need more accurate error */
|
|
|
|
res = VK_ERROR_OUT_OF_HOST_MEMORY;
|
2022-07-20 14:49:38 +02:00
|
|
|
goto cleanup;
|
2021-04-10 03:24:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < NUM_META_FS_KEYS; ++i) {
|
|
|
|
VkFormat format = radv_fs_key_format_exemplars[i];
|
|
|
|
unsigned fs_key = radv_format_meta_fs_key(device, format);
|
|
|
|
|
|
|
|
VkShaderModule vs_module_h = vk_shader_module_handle_from_nir(vs_module);
|
2022-03-17 09:51:07 +01:00
|
|
|
res = create_pipeline(device, vs_module_h, format, &state->resolve.pipeline[fs_key]);
|
2021-04-10 03:24:05 +02:00
|
|
|
if (res != VK_SUCCESS)
|
2022-07-20 14:49:38 +02:00
|
|
|
goto cleanup;
|
2021-04-10 03:24:05 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 09:16:09 +10:00
|
|
|
cleanup:
|
2021-04-10 03:24:05 +02:00
|
|
|
ralloc_free(vs_module);
|
2016-10-07 09:16:09 +10:00
|
|
|
|
2021-04-10 03:24:05 +02:00
|
|
|
return res;
|
2016-10-07 09:16:09 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-04-10 03:24:05 +02:00
|
|
|
emit_resolve(struct radv_cmd_buffer *cmd_buffer, const struct radv_image *src_image,
|
|
|
|
const struct radv_image *dst_image, VkFormat vk_format, const VkOffset2D *dest_offset,
|
2016-10-07 09:16:09 +10:00
|
|
|
const VkExtent2D *resolve_extent)
|
|
|
|
{
|
2021-04-10 03:24:05 +02:00
|
|
|
struct radv_device *device = cmd_buffer->device;
|
|
|
|
VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
|
|
|
|
unsigned fs_key = radv_format_meta_fs_key(device, vk_format);
|
|
|
|
|
|
|
|
cmd_buffer->state.flush_bits |=
|
2022-03-30 10:28:56 +02:00
|
|
|
radv_src_access_flush(cmd_buffer, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, src_image) |
|
|
|
|
radv_dst_access_flush(cmd_buffer, VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT, src_image) |
|
|
|
|
radv_dst_access_flush(cmd_buffer, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, dst_image);
|
2021-04-10 03:24:05 +02:00
|
|
|
|
|
|
|
radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
|
|
|
device->meta_state.resolve.pipeline[fs_key]);
|
|
|
|
|
|
|
|
radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1,
|
|
|
|
&(VkViewport){.x = dest_offset->x,
|
|
|
|
.y = dest_offset->y,
|
|
|
|
.width = resolve_extent->width,
|
|
|
|
.height = resolve_extent->height,
|
|
|
|
.minDepth = 0.0f,
|
|
|
|
.maxDepth = 1.0f});
|
|
|
|
|
|
|
|
radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1,
|
|
|
|
&(VkRect2D){
|
|
|
|
.offset = *dest_offset,
|
|
|
|
.extent = *resolve_extent,
|
|
|
|
});
|
|
|
|
|
|
|
|
radv_CmdDraw(cmd_buffer_h, 3, 1, 0, 0);
|
|
|
|
cmd_buffer->state.flush_bits |=
|
2022-03-30 10:28:56 +02:00
|
|
|
radv_src_access_flush(cmd_buffer, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, dst_image);
|
2016-10-07 09:16:09 +10:00
|
|
|
}
|
|
|
|
|
2017-04-28 03:56:25 +01:00
|
|
|
enum radv_resolve_method {
|
2021-04-10 03:24:05 +02:00
|
|
|
RESOLVE_HW,
|
|
|
|
RESOLVE_COMPUTE,
|
|
|
|
RESOLVE_FRAGMENT,
|
2017-04-28 03:56:25 +01:00
|
|
|
};
|
|
|
|
|
2021-04-10 03:24:05 +02:00
|
|
|
static bool
|
|
|
|
image_hw_resolve_compat(const struct radv_device *device, struct radv_image *src_image,
|
|
|
|
struct radv_image *dst_image)
|
2021-01-23 02:36:29 +01:00
|
|
|
{
|
2022-05-12 02:50:17 -04:00
|
|
|
if (device->physical_device->rad_info.gfx_level >= GFX9) {
|
2021-04-02 14:00:57 -04:00
|
|
|
return dst_image->planes[0].surface.u.gfx9.swizzle_mode ==
|
|
|
|
src_image->planes[0].surface.u.gfx9.swizzle_mode;
|
2021-04-10 03:24:05 +02:00
|
|
|
} else {
|
|
|
|
return dst_image->planes[0].surface.micro_tile_mode ==
|
|
|
|
src_image->planes[0].surface.micro_tile_mode;
|
|
|
|
}
|
2021-01-23 02:36:29 +01:00
|
|
|
}
|
|
|
|
|
2021-04-10 03:24:05 +02:00
|
|
|
static void
|
|
|
|
radv_pick_resolve_method_images(struct radv_device *device, struct radv_image *src_image,
|
|
|
|
VkFormat src_format, struct radv_image *dest_image,
|
2021-05-06 12:20:37 +02:00
|
|
|
unsigned dest_level, VkImageLayout dest_image_layout,
|
|
|
|
bool dest_render_loop, struct radv_cmd_buffer *cmd_buffer,
|
2021-04-10 03:24:05 +02:00
|
|
|
enum radv_resolve_method *method)
|
2017-04-28 03:56:25 +01:00
|
|
|
|
|
|
|
{
|
radv: abstract queue family away from queue family index.
If we introduce another queue type (video decode) we can have a
disconnect between the RADV_QUEUE_ enum and the API queue_family_index.
currently the driver has
GENERAL, COMPUTE, TRANSFER which would end up at QFI 0, 1, <nothing>
since we don't create transfer.
Now if I add VDEC we get
GENERAL, COMPUTE, TRANSFER, VDEC at QFI 0, 1, <nothing>, 2
or if you do nocompute
GENERAL, COMPUTE, TRANSFER, VDEC at QFI 0, <nothing>, <nothing>, 1
This means we have to add a remapping table between the API qfi
and the internal qf.
This patches tries to do that, in theory right now it just adds
overhead, but I'd like to exercise these paths.
v2: add radv_queue_ring abstraction, and pass physical device in,
as it makes adding uvd later easier.
v3: rename, and drop one direction as unneeded now, drop queue_family_index
from cmd_buffers.
Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13687>
2021-11-05 16:03:24 +10:00
|
|
|
uint32_t queue_mask = radv_image_queue_family_mask(dest_image, cmd_buffer->qf,
|
|
|
|
cmd_buffer->qf);
|
2021-04-10 03:24:05 +02:00
|
|
|
|
|
|
|
if (vk_format_is_color(src_format)) {
|
|
|
|
/* Using the fragment resolve path is currently a hint to
|
|
|
|
* avoid decompressing DCC for partial resolves and
|
|
|
|
* re-initialize it after resolving using compute.
|
|
|
|
* TODO: Add support for layered and int to the fragment path.
|
|
|
|
*/
|
2021-05-06 12:20:37 +02:00
|
|
|
if (radv_layout_dcc_compressed(device, dest_image, dest_level, dest_image_layout,
|
|
|
|
dest_render_loop, queue_mask)) {
|
2021-04-10 03:24:05 +02:00
|
|
|
*method = RESOLVE_FRAGMENT;
|
|
|
|
} else if (!image_hw_resolve_compat(device, src_image, dest_image)) {
|
|
|
|
/* The micro tile mode only needs to match for the HW
|
|
|
|
* resolve path which is the default path for non-DCC
|
|
|
|
* resolves.
|
|
|
|
*/
|
|
|
|
*method = RESOLVE_COMPUTE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (src_format == VK_FORMAT_R16G16_UNORM || src_format == VK_FORMAT_R16G16_SNORM)
|
|
|
|
*method = RESOLVE_COMPUTE;
|
|
|
|
else if (vk_format_is_int(src_format))
|
|
|
|
*method = RESOLVE_COMPUTE;
|
|
|
|
else if (src_image->info.array_size > 1 || dest_image->info.array_size > 1)
|
|
|
|
*method = RESOLVE_COMPUTE;
|
|
|
|
} else {
|
|
|
|
if (src_image->info.array_size > 1 || dest_image->info.array_size > 1)
|
|
|
|
*method = RESOLVE_COMPUTE;
|
|
|
|
else
|
|
|
|
*method = RESOLVE_FRAGMENT;
|
|
|
|
}
|
2017-04-28 03:56:25 +01:00
|
|
|
}
|
|
|
|
|
2018-08-14 00:07:57 +02:00
|
|
|
static VkResult
|
2021-04-10 03:24:05 +02:00
|
|
|
build_resolve_pipeline(struct radv_device *device, unsigned fs_key)
|
2018-08-14 00:07:57 +02:00
|
|
|
{
|
2021-04-10 03:24:05 +02:00
|
|
|
VkResult result = VK_SUCCESS;
|
2018-08-14 00:07:57 +02:00
|
|
|
|
2021-04-10 03:24:05 +02:00
|
|
|
if (device->meta_state.resolve.pipeline[fs_key])
|
|
|
|
return result;
|
2018-08-14 00:07:57 +02:00
|
|
|
|
2021-04-10 03:24:05 +02:00
|
|
|
mtx_lock(&device->meta_state.mtx);
|
|
|
|
if (device->meta_state.resolve.pipeline[fs_key]) {
|
|
|
|
mtx_unlock(&device->meta_state.mtx);
|
|
|
|
return result;
|
|
|
|
}
|
2018-08-14 00:07:57 +02:00
|
|
|
|
2022-03-30 11:52:58 +01:00
|
|
|
nir_shader *vs_module = radv_meta_build_nir_vs_generate_vertices(device);
|
2018-08-14 00:07:57 +02:00
|
|
|
|
2021-04-10 03:24:05 +02:00
|
|
|
VkShaderModule vs_module_h = vk_shader_module_handle_from_nir(vs_module);
|
2022-03-17 09:51:07 +01:00
|
|
|
result = create_pipeline(device, vs_module_h, radv_fs_key_format_exemplars[fs_key],
|
|
|
|
&device->meta_state.resolve.pipeline[fs_key]);
|
2018-08-14 00:07:57 +02:00
|
|
|
|
2021-04-10 03:24:05 +02:00
|
|
|
ralloc_free(vs_module);
|
|
|
|
mtx_unlock(&device->meta_state.mtx);
|
|
|
|
return result;
|
2018-08-14 00:07:57 +02:00
|
|
|
}
|
|
|
|
|
2020-09-22 11:24:22 +02:00
|
|
|
static void
|
2021-04-10 03:24:05 +02:00
|
|
|
radv_meta_resolve_hardware_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image,
|
|
|
|
VkImageLayout src_image_layout, struct radv_image *dst_image,
|
2022-03-30 10:28:56 +02:00
|
|
|
VkImageLayout dst_image_layout, const VkImageResolve2 *region)
|
2020-09-22 11:24:22 +02:00
|
|
|
{
|
2021-04-10 03:24:05 +02:00
|
|
|
struct radv_device *device = cmd_buffer->device;
|
|
|
|
struct radv_meta_saved_state saved_state;
|
|
|
|
|
|
|
|
radv_meta_save(&saved_state, cmd_buffer, RADV_META_SAVE_GRAPHICS_PIPELINE);
|
|
|
|
|
|
|
|
assert(src_image->info.samples > 1);
|
|
|
|
assert(dst_image->info.samples == 1);
|
|
|
|
|
2022-03-25 14:58:39 -05:00
|
|
|
unsigned fs_key = radv_format_meta_fs_key(device, dst_image->vk.format);
|
2021-04-10 03:24:05 +02:00
|
|
|
|
|
|
|
/* From the Vulkan 1.0 spec:
|
|
|
|
*
|
|
|
|
* - The aspectMask member of srcSubresource and dstSubresource must
|
|
|
|
* only contain VK_IMAGE_ASPECT_COLOR_BIT
|
|
|
|
*
|
|
|
|
* - The layerCount member of srcSubresource and dstSubresource must
|
|
|
|
* match
|
|
|
|
*/
|
|
|
|
assert(region->srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
|
|
|
|
assert(region->dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
|
|
|
|
assert(region->srcSubresource.layerCount == region->dstSubresource.layerCount);
|
|
|
|
|
|
|
|
const uint32_t src_base_layer =
|
|
|
|
radv_meta_get_iview_layer(src_image, ®ion->srcSubresource, ®ion->srcOffset);
|
|
|
|
|
|
|
|
const uint32_t dst_base_layer =
|
|
|
|
radv_meta_get_iview_layer(dst_image, ®ion->dstSubresource, ®ion->dstOffset);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* From Vulkan 1.0.6 spec: 18.6 Resolving Multisample Images
|
|
|
|
*
|
|
|
|
* extent is the size in texels of the source image to resolve in width,
|
|
|
|
* height and depth. 1D images use only x and width. 2D images use x, y,
|
|
|
|
* width and height. 3D images use x, y, z, width, height and depth.
|
|
|
|
*
|
|
|
|
* srcOffset and dstOffset select the initial x, y, and z offsets in
|
|
|
|
* texels of the sub-regions of the source and destination image data.
|
|
|
|
* extent is the size in texels of the source image to resolve in width,
|
|
|
|
* height and depth. 1D images use only x and width. 2D images use x, y,
|
|
|
|
* width and height. 3D images use x, y, z, width, height and depth.
|
|
|
|
*/
|
2022-06-04 22:33:37 -05:00
|
|
|
const struct VkExtent3D extent = vk_image_sanitize_extent(&src_image->vk, region->extent);
|
|
|
|
const struct VkOffset3D dstOffset = vk_image_sanitize_offset(&dst_image->vk, region->dstOffset);
|
2021-04-10 03:24:05 +02:00
|
|
|
|
radv: abstract queue family away from queue family index.
If we introduce another queue type (video decode) we can have a
disconnect between the RADV_QUEUE_ enum and the API queue_family_index.
currently the driver has
GENERAL, COMPUTE, TRANSFER which would end up at QFI 0, 1, <nothing>
since we don't create transfer.
Now if I add VDEC we get
GENERAL, COMPUTE, TRANSFER, VDEC at QFI 0, 1, <nothing>, 2
or if you do nocompute
GENERAL, COMPUTE, TRANSFER, VDEC at QFI 0, <nothing>, <nothing>, 1
This means we have to add a remapping table between the API qfi
and the internal qf.
This patches tries to do that, in theory right now it just adds
overhead, but I'd like to exercise these paths.
v2: add radv_queue_ring abstraction, and pass physical device in,
as it makes adding uvd later easier.
v3: rename, and drop one direction as unneeded now, drop queue_family_index
from cmd_buffers.
Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13687>
2021-11-05 16:03:24 +10:00
|
|
|
uint32_t queue_mask = radv_image_queue_family_mask(dst_image, cmd_buffer->qf,
|
|
|
|
cmd_buffer->qf);
|
2021-05-06 14:30:19 +02:00
|
|
|
|
|
|
|
if (radv_layout_dcc_compressed(cmd_buffer->device, dst_image, region->dstSubresource.mipLevel,
|
|
|
|
dst_image_layout, false, queue_mask)) {
|
2021-04-10 03:24:05 +02:00
|
|
|
VkImageSubresourceRange range = {
|
|
|
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
.baseMipLevel = region->dstSubresource.mipLevel,
|
|
|
|
.levelCount = 1,
|
|
|
|
.baseArrayLayer = dst_base_layer,
|
|
|
|
.layerCount = region->dstSubresource.layerCount,
|
|
|
|
};
|
|
|
|
|
|
|
|
cmd_buffer->state.flush_bits |= radv_init_dcc(cmd_buffer, dst_image, &range, 0xffffffff);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (uint32_t layer = 0; layer < region->srcSubresource.layerCount; ++layer) {
|
|
|
|
|
|
|
|
VkResult ret = build_resolve_pipeline(device, fs_key);
|
|
|
|
if (ret != VK_SUCCESS) {
|
|
|
|
cmd_buffer->record_result = ret;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct radv_image_view src_iview;
|
|
|
|
radv_image_view_init(&src_iview, cmd_buffer->device,
|
|
|
|
&(VkImageViewCreateInfo){
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
|
|
|
.image = radv_image_to_handle(src_image),
|
|
|
|
.viewType = radv_meta_get_view_type(src_image),
|
2022-03-25 14:58:39 -05:00
|
|
|
.format = src_image->vk.format,
|
2021-04-10 03:24:05 +02:00
|
|
|
.subresourceRange =
|
|
|
|
{
|
|
|
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
.baseMipLevel = region->srcSubresource.mipLevel,
|
|
|
|
.levelCount = 1,
|
|
|
|
.baseArrayLayer = src_base_layer + layer,
|
|
|
|
.layerCount = 1,
|
|
|
|
},
|
|
|
|
},
|
2022-05-03 08:51:31 +02:00
|
|
|
0, NULL);
|
2021-04-10 03:24:05 +02:00
|
|
|
|
|
|
|
struct radv_image_view dst_iview;
|
|
|
|
radv_image_view_init(&dst_iview, cmd_buffer->device,
|
|
|
|
&(VkImageViewCreateInfo){
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
|
|
|
.image = radv_image_to_handle(dst_image),
|
|
|
|
.viewType = radv_meta_get_view_type(dst_image),
|
2022-03-25 14:58:39 -05:00
|
|
|
.format = dst_image->vk.format,
|
2021-04-10 03:24:05 +02:00
|
|
|
.subresourceRange =
|
|
|
|
{
|
|
|
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
.baseMipLevel = region->dstSubresource.mipLevel,
|
|
|
|
.levelCount = 1,
|
|
|
|
.baseArrayLayer = dst_base_layer + layer,
|
|
|
|
.layerCount = 1,
|
|
|
|
},
|
|
|
|
},
|
2022-05-03 08:51:31 +02:00
|
|
|
0, NULL);
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2022-03-17 09:51:07 +01:00
|
|
|
const VkRenderingAttachmentInfo color_atts[2] = {
|
|
|
|
{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
|
|
|
.imageView = radv_image_view_to_handle(&src_iview),
|
|
|
|
.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
|
|
|
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
|
|
|
|
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
|
|
|
.imageView = radv_image_view_to_handle(&dst_iview),
|
|
|
|
.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
|
|
|
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
|
|
|
|
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
const VkRenderingInfo rendering_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
|
|
|
|
.renderArea = {
|
|
|
|
.offset = { dstOffset.x, dstOffset.y },
|
|
|
|
.extent = { extent.width, extent.height },
|
|
|
|
},
|
|
|
|
.layerCount = 1,
|
|
|
|
.colorAttachmentCount = 2,
|
|
|
|
.pColorAttachments = color_atts,
|
|
|
|
};
|
|
|
|
|
|
|
|
radv_CmdBeginRendering(radv_cmd_buffer_to_handle(cmd_buffer), &rendering_info);
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2022-03-25 16:14:19 -05:00
|
|
|
emit_resolve(cmd_buffer, src_image, dst_image, dst_iview.vk.format,
|
2021-04-10 03:24:05 +02:00
|
|
|
&(VkOffset2D){
|
|
|
|
.x = dstOffset.x,
|
|
|
|
.y = dstOffset.y,
|
|
|
|
},
|
|
|
|
&(VkExtent2D){
|
|
|
|
.width = extent.width,
|
|
|
|
.height = extent.height,
|
|
|
|
});
|
|
|
|
|
2022-03-17 09:51:07 +01:00
|
|
|
radv_CmdEndRendering(radv_cmd_buffer_to_handle(cmd_buffer));
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2021-09-29 09:46:46 +02:00
|
|
|
radv_image_view_finish(&src_iview);
|
|
|
|
radv_image_view_finish(&dst_iview);
|
2021-04-10 03:24:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
radv_meta_restore(&saved_state, cmd_buffer);
|
2020-09-22 11:24:22 +02:00
|
|
|
}
|
|
|
|
|
2020-09-22 10:40:51 +02:00
|
|
|
static void
|
2021-04-10 03:24:05 +02:00
|
|
|
resolve_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image,
|
|
|
|
VkImageLayout src_image_layout, struct radv_image *dst_image,
|
2022-03-30 10:28:56 +02:00
|
|
|
VkImageLayout dst_image_layout, const VkImageResolve2 *region,
|
2021-04-10 03:24:05 +02:00
|
|
|
enum radv_resolve_method resolve_method)
|
2020-09-22 10:40:51 +02:00
|
|
|
{
|
2021-04-10 03:24:05 +02:00
|
|
|
switch (resolve_method) {
|
|
|
|
case RESOLVE_HW:
|
|
|
|
radv_meta_resolve_hardware_image(cmd_buffer, src_image, src_image_layout, dst_image,
|
|
|
|
dst_image_layout, region);
|
|
|
|
break;
|
|
|
|
case RESOLVE_FRAGMENT:
|
|
|
|
radv_meta_resolve_fragment_image(cmd_buffer, src_image, src_image_layout, dst_image,
|
|
|
|
dst_image_layout, region);
|
|
|
|
break;
|
|
|
|
case RESOLVE_COMPUTE:
|
2022-03-25 14:58:39 -05:00
|
|
|
radv_meta_resolve_compute_image(cmd_buffer, src_image, src_image->vk.format, src_image_layout,
|
|
|
|
dst_image, dst_image->vk.format, dst_image_layout, region);
|
2021-04-10 03:24:05 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert(!"Invalid resolve method selected");
|
|
|
|
}
|
2020-09-22 10:40:51 +02:00
|
|
|
}
|
|
|
|
|
2021-11-10 23:25:47 -08:00
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
2022-03-30 10:28:56 +02:00
|
|
|
radv_CmdResolveImage2(VkCommandBuffer commandBuffer,
|
|
|
|
const VkResolveImageInfo2 *pResolveImageInfo)
|
2020-09-22 10:40:51 +02:00
|
|
|
{
|
2021-04-10 03:24:05 +02:00
|
|
|
RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
|
|
|
|
RADV_FROM_HANDLE(radv_image, src_image, pResolveImageInfo->srcImage);
|
|
|
|
RADV_FROM_HANDLE(radv_image, dst_image, pResolveImageInfo->dstImage);
|
|
|
|
VkImageLayout src_image_layout = pResolveImageInfo->srcImageLayout;
|
|
|
|
VkImageLayout dst_image_layout = pResolveImageInfo->dstImageLayout;
|
2022-05-17 13:28:02 +02:00
|
|
|
const struct radv_physical_device *pdevice = cmd_buffer->device->physical_device;
|
|
|
|
enum radv_resolve_method resolve_method =
|
|
|
|
pdevice->rad_info.gfx_level >= GFX11 ? RESOLVE_FRAGMENT : RESOLVE_HW;
|
|
|
|
|
2021-04-10 03:24:05 +02:00
|
|
|
/* we can use the hw resolve only for single full resolves */
|
|
|
|
if (pResolveImageInfo->regionCount == 1) {
|
|
|
|
if (pResolveImageInfo->pRegions[0].srcOffset.x ||
|
|
|
|
pResolveImageInfo->pRegions[0].srcOffset.y || pResolveImageInfo->pRegions[0].srcOffset.z)
|
|
|
|
resolve_method = RESOLVE_COMPUTE;
|
|
|
|
if (pResolveImageInfo->pRegions[0].dstOffset.x ||
|
|
|
|
pResolveImageInfo->pRegions[0].dstOffset.y || pResolveImageInfo->pRegions[0].dstOffset.z)
|
|
|
|
resolve_method = RESOLVE_COMPUTE;
|
|
|
|
|
|
|
|
if (pResolveImageInfo->pRegions[0].extent.width != src_image->info.width ||
|
|
|
|
pResolveImageInfo->pRegions[0].extent.height != src_image->info.height ||
|
|
|
|
pResolveImageInfo->pRegions[0].extent.depth != src_image->info.depth)
|
|
|
|
resolve_method = RESOLVE_COMPUTE;
|
|
|
|
} else
|
|
|
|
resolve_method = RESOLVE_COMPUTE;
|
|
|
|
|
|
|
|
for (uint32_t r = 0; r < pResolveImageInfo->regionCount; r++) {
|
2022-03-30 10:28:56 +02:00
|
|
|
const VkImageResolve2 *region = &pResolveImageInfo->pRegions[r];
|
2021-05-06 12:20:37 +02:00
|
|
|
|
2022-03-25 14:58:39 -05:00
|
|
|
radv_pick_resolve_method_images(cmd_buffer->device, src_image, src_image->vk.format, dst_image,
|
2021-05-06 12:20:37 +02:00
|
|
|
region->dstSubresource.mipLevel, dst_image_layout, false,
|
|
|
|
cmd_buffer, &resolve_method);
|
|
|
|
|
|
|
|
resolve_image(cmd_buffer, src_image, src_image_layout, dst_image, dst_image_layout, region,
|
|
|
|
resolve_method);
|
2021-04-10 03:24:05 +02:00
|
|
|
}
|
2016-10-07 09:16:09 +10:00
|
|
|
}
|
|
|
|
|
2021-02-17 17:58:20 +01:00
|
|
|
static void
|
|
|
|
radv_cmd_buffer_resolve_subpass_hw(struct radv_cmd_buffer *cmd_buffer)
|
|
|
|
{
|
2022-03-28 15:54:12 +02:00
|
|
|
struct vk_framebuffer *fb = cmd_buffer->state.framebuffer;
|
2021-04-10 03:24:05 +02:00
|
|
|
const struct radv_subpass *subpass = cmd_buffer->state.subpass;
|
|
|
|
struct radv_meta_saved_state saved_state;
|
|
|
|
|
|
|
|
radv_meta_save(&saved_state, cmd_buffer, RADV_META_SAVE_GRAPHICS_PIPELINE);
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < subpass->color_count; ++i) {
|
|
|
|
struct radv_subpass_attachment src_att = subpass->color_attachments[i];
|
|
|
|
struct radv_subpass_attachment dest_att = subpass->resolve_attachments[i];
|
|
|
|
|
|
|
|
if (dest_att.attachment == VK_ATTACHMENT_UNUSED)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
struct radv_image_view *src_iview = cmd_buffer->state.attachments[src_att.attachment].iview;
|
|
|
|
struct radv_image *src_img = src_iview->image;
|
|
|
|
|
|
|
|
struct radv_image_view *dest_iview = cmd_buffer->state.attachments[dest_att.attachment].iview;
|
|
|
|
struct radv_image *dst_img = dest_iview->image;
|
2021-05-06 14:30:19 +02:00
|
|
|
VkImageLayout dst_image_layout = cmd_buffer->state.attachments[dest_att.attachment].current_layout;
|
|
|
|
|
radv: abstract queue family away from queue family index.
If we introduce another queue type (video decode) we can have a
disconnect between the RADV_QUEUE_ enum and the API queue_family_index.
currently the driver has
GENERAL, COMPUTE, TRANSFER which would end up at QFI 0, 1, <nothing>
since we don't create transfer.
Now if I add VDEC we get
GENERAL, COMPUTE, TRANSFER, VDEC at QFI 0, 1, <nothing>, 2
or if you do nocompute
GENERAL, COMPUTE, TRANSFER, VDEC at QFI 0, <nothing>, <nothing>, 1
This means we have to add a remapping table between the API qfi
and the internal qf.
This patches tries to do that, in theory right now it just adds
overhead, but I'd like to exercise these paths.
v2: add radv_queue_ring abstraction, and pass physical device in,
as it makes adding uvd later easier.
v3: rename, and drop one direction as unneeded now, drop queue_family_index
from cmd_buffers.
Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13687>
2021-11-05 16:03:24 +10:00
|
|
|
uint32_t queue_mask = radv_image_queue_family_mask(dst_img, cmd_buffer->qf,
|
|
|
|
cmd_buffer->qf);
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2022-03-25 16:14:19 -05:00
|
|
|
if (radv_layout_dcc_compressed(cmd_buffer->device, dst_img, dest_iview->vk.base_mip_level,
|
2021-05-06 14:30:19 +02:00
|
|
|
dst_image_layout, false, queue_mask)) {
|
2021-04-10 03:24:05 +02:00
|
|
|
VkImageSubresourceRange range = {
|
2022-03-25 16:14:19 -05:00
|
|
|
.aspectMask = dest_iview->vk.aspects,
|
|
|
|
.baseMipLevel = dest_iview->vk.base_mip_level,
|
|
|
|
.levelCount = dest_iview->vk.level_count,
|
|
|
|
.baseArrayLayer = dest_iview->vk.base_array_layer,
|
|
|
|
.layerCount = dest_iview->vk.layer_count,
|
2021-04-10 03:24:05 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
cmd_buffer->state.flush_bits |= radv_init_dcc(cmd_buffer, dst_img, &range, 0xffffffff);
|
|
|
|
cmd_buffer->state.attachments[dest_att.attachment].current_layout =
|
|
|
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct radv_subpass resolve_subpass = {
|
|
|
|
.color_count = 2,
|
|
|
|
.color_attachments = (struct radv_subpass_attachment[]){src_att, dest_att},
|
|
|
|
.depth_stencil_attachment = NULL,
|
|
|
|
};
|
|
|
|
|
|
|
|
radv_cmd_buffer_set_subpass(cmd_buffer, &resolve_subpass);
|
|
|
|
|
|
|
|
VkResult ret = build_resolve_pipeline(
|
2022-03-25 16:14:19 -05:00
|
|
|
cmd_buffer->device, radv_format_meta_fs_key(cmd_buffer->device, dest_iview->vk.format));
|
2021-04-10 03:24:05 +02:00
|
|
|
if (ret != VK_SUCCESS) {
|
|
|
|
cmd_buffer->record_result = ret;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-03-25 16:14:19 -05:00
|
|
|
emit_resolve(cmd_buffer, src_img, dst_img, dest_iview->vk.format, &(VkOffset2D){0, 0},
|
2021-04-10 03:24:05 +02:00
|
|
|
&(VkExtent2D){fb->width, fb->height});
|
|
|
|
|
2021-12-28 10:38:41 +01:00
|
|
|
radv_cmd_buffer_restore_subpass(cmd_buffer, subpass);
|
|
|
|
}
|
2021-04-10 03:24:05 +02:00
|
|
|
|
|
|
|
radv_meta_restore(&saved_state, cmd_buffer);
|
2021-02-17 17:58:20 +01:00
|
|
|
}
|
|
|
|
|
2016-10-07 09:16:09 +10:00
|
|
|
/**
|
|
|
|
* Emit any needed resolves for the current subpass.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
radv_cmd_buffer_resolve_subpass(struct radv_cmd_buffer *cmd_buffer)
|
|
|
|
{
|
2022-05-17 13:28:02 +02:00
|
|
|
const struct radv_physical_device *pdevice = cmd_buffer->device->physical_device;
|
2021-04-10 03:24:05 +02:00
|
|
|
const struct radv_subpass *subpass = cmd_buffer->state.subpass;
|
2022-05-17 13:28:02 +02:00
|
|
|
enum radv_resolve_method resolve_method =
|
|
|
|
pdevice->rad_info.gfx_level >= GFX11 ? RESOLVE_FRAGMENT : RESOLVE_HW;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
|
|
|
if (!subpass->has_color_resolve && !subpass->ds_resolve_attachment)
|
|
|
|
return;
|
|
|
|
|
|
|
|
radv_describe_begin_render_pass_resolve(cmd_buffer);
|
|
|
|
|
|
|
|
if (subpass->ds_resolve_attachment) {
|
|
|
|
struct radv_subpass_attachment src_att = *subpass->depth_stencil_attachment;
|
|
|
|
struct radv_subpass_attachment dst_att = *subpass->ds_resolve_attachment;
|
|
|
|
struct radv_image_view *src_iview = cmd_buffer->state.attachments[src_att.attachment].iview;
|
|
|
|
struct radv_image_view *dst_iview = cmd_buffer->state.attachments[dst_att.attachment].iview;
|
|
|
|
|
|
|
|
/* Make sure to not clear the depth/stencil attachment after resolves. */
|
|
|
|
cmd_buffer->state.attachments[dst_att.attachment].pending_clear_aspects = 0;
|
|
|
|
|
2022-03-25 16:14:19 -05:00
|
|
|
radv_pick_resolve_method_images(cmd_buffer->device, src_iview->image, src_iview->vk.format,
|
|
|
|
dst_iview->image, dst_iview->vk.base_mip_level, dst_att.layout,
|
2021-05-06 12:20:37 +02:00
|
|
|
dst_att.in_render_loop, cmd_buffer, &resolve_method);
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2022-03-25 16:14:19 -05:00
|
|
|
if ((src_iview->vk.aspects & VK_IMAGE_ASPECT_DEPTH_BIT) &&
|
2022-03-30 10:28:56 +02:00
|
|
|
subpass->depth_resolve_mode != VK_RESOLVE_MODE_NONE) {
|
2021-04-10 03:24:05 +02:00
|
|
|
if (resolve_method == RESOLVE_FRAGMENT) {
|
|
|
|
radv_depth_stencil_resolve_subpass_fs(cmd_buffer, VK_IMAGE_ASPECT_DEPTH_BIT,
|
|
|
|
subpass->depth_resolve_mode);
|
|
|
|
} else {
|
|
|
|
assert(resolve_method == RESOLVE_COMPUTE);
|
|
|
|
radv_depth_stencil_resolve_subpass_cs(cmd_buffer, VK_IMAGE_ASPECT_DEPTH_BIT,
|
|
|
|
subpass->depth_resolve_mode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-25 16:14:19 -05:00
|
|
|
if ((src_iview->vk.aspects & VK_IMAGE_ASPECT_STENCIL_BIT) &&
|
2022-03-30 10:28:56 +02:00
|
|
|
subpass->stencil_resolve_mode != VK_RESOLVE_MODE_NONE) {
|
2021-04-10 03:24:05 +02:00
|
|
|
if (resolve_method == RESOLVE_FRAGMENT) {
|
|
|
|
radv_depth_stencil_resolve_subpass_fs(cmd_buffer, VK_IMAGE_ASPECT_STENCIL_BIT,
|
|
|
|
subpass->stencil_resolve_mode);
|
|
|
|
} else {
|
|
|
|
assert(resolve_method == RESOLVE_COMPUTE);
|
|
|
|
radv_depth_stencil_resolve_subpass_cs(cmd_buffer, VK_IMAGE_ASPECT_STENCIL_BIT,
|
|
|
|
subpass->stencil_resolve_mode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* From the Vulkan spec 1.2.165:
|
|
|
|
*
|
2022-03-30 10:28:56 +02:00
|
|
|
* "VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT specifies
|
2021-04-10 03:24:05 +02:00
|
|
|
* write access to a color, resolve, or depth/stencil
|
|
|
|
* resolve attachment during a render pass or via
|
|
|
|
* certain subpass load and store operations."
|
|
|
|
*
|
|
|
|
* Yes, it's counterintuitive but it makes sense because ds
|
|
|
|
* resolve operations happen late at the end of the subpass.
|
|
|
|
*
|
|
|
|
* That said, RADV is wrong because it executes the subpass
|
|
|
|
* end barrier *before* any subpass resolves instead of after.
|
|
|
|
*
|
|
|
|
* TODO: Fix this properly by executing subpass end barriers
|
|
|
|
* after subpass resolves.
|
|
|
|
*/
|
|
|
|
cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_DB;
|
|
|
|
if (radv_image_has_htile(dst_iview->image))
|
|
|
|
cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_DB_META;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (subpass->has_color_resolve) {
|
|
|
|
for (uint32_t i = 0; i < subpass->color_count; ++i) {
|
|
|
|
struct radv_subpass_attachment src_att = subpass->color_attachments[i];
|
|
|
|
struct radv_subpass_attachment dest_att = subpass->resolve_attachments[i];
|
|
|
|
|
|
|
|
if (dest_att.attachment == VK_ATTACHMENT_UNUSED)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Make sure to not clear color attachments after resolves. */
|
|
|
|
cmd_buffer->state.attachments[dest_att.attachment].pending_clear_aspects = 0;
|
|
|
|
|
2021-05-06 12:20:37 +02:00
|
|
|
struct radv_image_view *dst_iview =
|
|
|
|
cmd_buffer->state.attachments[dest_att.attachment].iview;
|
|
|
|
struct radv_image *dst_img = dst_iview->image;
|
2021-04-10 03:24:05 +02:00
|
|
|
struct radv_image_view *src_iview =
|
|
|
|
cmd_buffer->state.attachments[src_att.attachment].iview;
|
|
|
|
struct radv_image *src_img = src_iview->image;
|
|
|
|
|
2022-03-25 16:14:19 -05:00
|
|
|
radv_pick_resolve_method_images(cmd_buffer->device, src_img, src_iview->vk.format, dst_img,
|
|
|
|
dst_iview->vk.base_mip_level, dest_att.layout,
|
2021-05-06 12:20:37 +02:00
|
|
|
dest_att.in_render_loop, cmd_buffer, &resolve_method);
|
2021-04-10 03:24:05 +02:00
|
|
|
|
|
|
|
if (resolve_method == RESOLVE_FRAGMENT) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (resolve_method) {
|
|
|
|
case RESOLVE_HW:
|
|
|
|
radv_cmd_buffer_resolve_subpass_hw(cmd_buffer);
|
|
|
|
break;
|
|
|
|
case RESOLVE_COMPUTE:
|
|
|
|
radv_cmd_buffer_resolve_subpass_cs(cmd_buffer);
|
|
|
|
break;
|
|
|
|
case RESOLVE_FRAGMENT:
|
|
|
|
radv_cmd_buffer_resolve_subpass_fs(cmd_buffer);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
unreachable("Invalid resolve method");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
radv_describe_end_render_pass_resolve(cmd_buffer);
|
2016-10-07 09:16:09 +10:00
|
|
|
}
|
2018-04-11 14:09:16 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Decompress CMask/FMask before resolving a multisampled source image inside a
|
|
|
|
* subpass.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
radv_decompress_resolve_subpass_src(struct radv_cmd_buffer *cmd_buffer)
|
|
|
|
{
|
2021-04-10 03:24:05 +02:00
|
|
|
const struct radv_subpass *subpass = cmd_buffer->state.subpass;
|
2022-03-28 15:54:12 +02:00
|
|
|
struct vk_framebuffer *fb = cmd_buffer->state.framebuffer;
|
2021-04-10 03:24:05 +02:00
|
|
|
uint32_t layer_count = fb->layers;
|
2019-06-10 17:45:32 +02:00
|
|
|
|
2021-04-10 03:24:05 +02:00
|
|
|
if (subpass->view_mask)
|
|
|
|
layer_count = util_last_bit(subpass->view_mask);
|
2018-04-11 14:09:16 +02:00
|
|
|
|
2021-04-10 03:24:05 +02:00
|
|
|
for (uint32_t i = 0; i < subpass->color_count; ++i) {
|
|
|
|
struct radv_subpass_attachment src_att = subpass->color_attachments[i];
|
|
|
|
struct radv_subpass_attachment dest_att = subpass->resolve_attachments[i];
|
2018-04-11 14:09:16 +02:00
|
|
|
|
2021-04-10 03:24:05 +02:00
|
|
|
if (dest_att.attachment == VK_ATTACHMENT_UNUSED)
|
|
|
|
continue;
|
2018-04-11 14:09:16 +02:00
|
|
|
|
2021-04-10 03:24:05 +02:00
|
|
|
struct radv_image_view *src_iview = cmd_buffer->state.attachments[src_att.attachment].iview;
|
|
|
|
struct radv_image *src_image = src_iview->image;
|
2018-04-11 14:09:16 +02:00
|
|
|
|
2022-03-30 10:28:56 +02:00
|
|
|
VkImageResolve2 region = {0};
|
|
|
|
region.sType = VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2;
|
2022-03-25 16:14:19 -05:00
|
|
|
region.srcSubresource.aspectMask = src_iview->vk.aspects;
|
2021-04-10 03:24:05 +02:00
|
|
|
region.srcSubresource.mipLevel = 0;
|
2022-03-25 16:14:19 -05:00
|
|
|
region.srcSubresource.baseArrayLayer = src_iview->vk.base_array_layer;
|
2021-04-10 03:24:05 +02:00
|
|
|
region.srcSubresource.layerCount = layer_count;
|
2018-04-11 14:09:16 +02:00
|
|
|
|
2021-04-10 03:24:05 +02:00
|
|
|
radv_decompress_resolve_src(cmd_buffer, src_image, src_att.layout, ®ion);
|
|
|
|
}
|
2018-04-11 14:09:16 +02:00
|
|
|
}
|
|
|
|
|
2019-06-12 11:39:58 +02:00
|
|
|
static struct radv_sample_locations_state *
|
|
|
|
radv_get_resolve_sample_locations(struct radv_cmd_buffer *cmd_buffer)
|
|
|
|
{
|
2021-04-10 03:24:05 +02:00
|
|
|
struct radv_cmd_state *state = &cmd_buffer->state;
|
|
|
|
uint32_t subpass_id = radv_get_subpass_id(cmd_buffer);
|
2019-06-12 11:39:58 +02:00
|
|
|
|
2021-04-10 03:24:05 +02:00
|
|
|
for (uint32_t i = 0; i < state->num_subpass_sample_locs; i++) {
|
|
|
|
if (state->subpass_sample_locs[i].subpass_idx == subpass_id)
|
|
|
|
return &state->subpass_sample_locs[i].sample_location;
|
|
|
|
}
|
2019-06-12 11:39:58 +02:00
|
|
|
|
2021-04-10 03:24:05 +02:00
|
|
|
return NULL;
|
2019-06-12 11:39:58 +02:00
|
|
|
}
|
|
|
|
|
2018-04-11 14:09:16 +02:00
|
|
|
/**
|
|
|
|
* Decompress CMask/FMask before resolving a multisampled source image.
|
|
|
|
*/
|
|
|
|
void
|
2021-04-10 03:24:05 +02:00
|
|
|
radv_decompress_resolve_src(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image,
|
2022-03-30 10:28:56 +02:00
|
|
|
VkImageLayout src_image_layout, const VkImageResolve2 *region)
|
2018-04-11 14:09:16 +02:00
|
|
|
{
|
2021-04-10 03:24:05 +02:00
|
|
|
const uint32_t src_base_layer =
|
|
|
|
radv_meta_get_iview_layer(src_image, ®ion->srcSubresource, ®ion->srcOffset);
|
|
|
|
|
2022-03-30 10:28:56 +02:00
|
|
|
VkImageMemoryBarrier2 barrier = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
|
|
|
|
.srcStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT,
|
|
|
|
.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
|
|
|
|
.dstStageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT,
|
|
|
|
.dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT,
|
2021-10-12 18:41:34 +02:00
|
|
|
.oldLayout = src_image_layout,
|
|
|
|
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
|
|
|
.image = radv_image_to_handle(src_image),
|
|
|
|
.subresourceRange = (VkImageSubresourceRange){
|
|
|
|
.aspectMask = region->srcSubresource.aspectMask,
|
|
|
|
.baseMipLevel = region->srcSubresource.mipLevel,
|
|
|
|
.levelCount = 1,
|
|
|
|
.baseArrayLayer = src_base_layer,
|
|
|
|
.layerCount = region->srcSubresource.layerCount,
|
|
|
|
}
|
2021-04-10 03:24:05 +02:00
|
|
|
};
|
|
|
|
|
2022-03-25 14:58:39 -05:00
|
|
|
if (src_image->vk.create_flags & VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT) {
|
2021-04-10 03:24:05 +02:00
|
|
|
/* If the depth/stencil image uses different sample
|
|
|
|
* locations, we need them during HTILE decompressions.
|
|
|
|
*/
|
|
|
|
struct radv_sample_locations_state *sample_locs =
|
|
|
|
radv_get_resolve_sample_locations(cmd_buffer);
|
|
|
|
|
|
|
|
barrier.pNext = &(VkSampleLocationsInfoEXT){
|
|
|
|
.sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT,
|
|
|
|
.sampleLocationsPerPixel = sample_locs->per_pixel,
|
|
|
|
.sampleLocationGridSize = sample_locs->grid_size,
|
|
|
|
.sampleLocationsCount = sample_locs->count,
|
|
|
|
.pSampleLocations = sample_locs->locations,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-03-30 10:28:56 +02:00
|
|
|
VkDependencyInfo dep_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
|
2021-10-12 18:41:34 +02:00
|
|
|
.imageMemoryBarrierCount = 1,
|
|
|
|
.pImageMemoryBarriers = &barrier,
|
|
|
|
};
|
|
|
|
|
2022-03-30 10:28:56 +02:00
|
|
|
radv_CmdPipelineBarrier2(radv_cmd_buffer_to_handle(cmd_buffer), &dep_info);
|
2018-04-11 14:09:16 +02:00
|
|
|
}
|