radv/meta: remove CB_RESOLVE

CB_RESOLVE isn't very fast and we already have two different paths,
it's been removed in hw since GFX11. PAL and RadeonSI removed support
for it too.

Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39957>
This commit is contained in:
Samuel Pitoiset 2026-02-13 07:37:15 +01:00 committed by Marge Bot
parent 9c05ca4366
commit 1746837a71
5 changed files with 11 additions and 390 deletions

View file

@ -84,7 +84,6 @@ enum radv_meta_object_key_type {
RADV_META_OBJECT_KEY_FMASK_COPY,
RADV_META_OBJECT_KEY_FMASK_EXPAND,
RADV_META_OBJECT_KEY_FMASK_DECOMPRESS,
RADV_META_OBJECT_KEY_RESOLVE_HW,
RADV_META_OBJECT_KEY_RESOLVE_CS,
RADV_META_OBJECT_KEY_RESOLVE_GFX,
RADV_META_OBJECT_KEY_DGC,

View file

@ -13,181 +13,11 @@
#include "radv_meta.h"
#include "vk_format.h"
struct radv_resolve_key {
enum radv_meta_object_key_type type;
VkFormat format;
};
static VkResult
get_pipeline(struct radv_device *device, VkFormat format, VkPipeline *pipeline_out, VkPipelineLayout *layout_out)
{
struct radv_resolve_key key;
VkResult result;
result = radv_meta_get_noop_pipeline_layout(device, layout_out);
if (result != VK_SUCCESS)
return result;
memset(&key, 0, sizeof(key));
key.type = RADV_META_OBJECT_KEY_RESOLVE_HW;
key.format = format;
VkPipeline pipeline_from_cache = vk_meta_lookup_pipeline(&device->meta_state.device, &key, sizeof(key));
if (pipeline_from_cache != VK_NULL_HANDLE) {
*pipeline_out = pipeline_from_cache;
return VK_SUCCESS;
}
nir_shader *vs_module = radv_meta_nir_build_vs_generate_vertices(device);
nir_shader *fs_module = radv_meta_nir_build_resolve_hw(device);
const VkGraphicsPipelineCreateInfoRADV radv_info = {
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO_RADV,
.custom_blend_mode = V_028808_CB_RESOLVE,
};
const VkGraphicsPipelineCreateInfo pipeline_create_info = {
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = &radv_info,
.stageCount = 2,
.pStages =
(VkPipelineShaderStageCreateInfo[]){
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_VERTEX_BIT,
.module = vk_shader_module_handle_from_nir(vs_module),
.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_META_RECT_LIST_MESA,
.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 = *layout_out,
};
struct vk_meta_rendering_info render = {
.color_attachment_count = 2,
.color_attachment_formats = {format, format},
};
result = vk_meta_create_graphics_pipeline(&device->vk, &device->meta_state.device, &pipeline_create_info, &render,
&key, sizeof(key), pipeline_out);
ralloc_free(vs_module);
ralloc_free(fs_module);
return result;
}
static void
emit_resolve(struct radv_cmd_buffer *cmd_buffer, const struct radv_image *src_image, const struct radv_image *dst_image,
VkFormat vk_format)
{
struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
VkPipelineLayout layout;
VkPipeline pipeline;
VkResult result;
result = get_pipeline(device, vk_format, &pipeline, &layout);
if (result != VK_SUCCESS) {
vk_command_buffer_set_error(&cmd_buffer->vk, result);
return;
}
cmd_buffer->state.flush_bits |= radv_src_access_flush(cmd_buffer, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, 0, src_image, NULL) |
radv_dst_access_flush(cmd_buffer, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT, 0, src_image, NULL);
radv_meta_bind_graphics_pipeline(cmd_buffer, pipeline);
radv_CmdDraw(cmd_buffer_h, 3, 1, 0, 0);
cmd_buffer->state.flush_bits |= radv_src_access_flush(cmd_buffer, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, 0, dst_image, NULL);
}
enum radv_resolve_method {
RESOLVE_HW,
RESOLVE_COMPUTE,
RESOLVE_FRAGMENT,
};
static bool
image_hw_resolve_compat(const struct radv_device *device, struct radv_image *src_image, struct radv_image *dst_image)
{
const struct radv_physical_device *pdev = radv_device_physical(device);
if (pdev->info.gfx_level >= GFX9) {
return dst_image->planes[0].surface.u.gfx9.swizzle_mode == src_image->planes[0].surface.u.gfx9.swizzle_mode;
} else {
return dst_image->planes[0].surface.micro_tile_mode == src_image->planes[0].surface.micro_tile_mode;
}
}
static void
radv_pick_resolve_method_images(struct radv_device *device, struct radv_image *src_image, VkFormat src_format,
struct radv_image *dst_image, unsigned dst_level, VkImageLayout dst_image_layout,
@ -204,12 +34,6 @@ radv_pick_resolve_method_images(struct radv_device *device, struct radv_image *s
*/
if (radv_layout_dcc_compressed(device, dst_image, dst_level, dst_image_layout, queue_mask)) {
*method = RESOLVE_FRAGMENT;
} else if (!image_hw_resolve_compat(device, src_image, dst_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)
@ -227,154 +51,6 @@ radv_pick_resolve_method_images(struct radv_device *device, struct radv_image *s
}
}
static void
radv_meta_resolve_hardware_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image, VkFormat src_format,
VkImageLayout src_image_layout, struct radv_image *dst_image, VkFormat dst_format,
VkImageLayout dst_image_layout, const VkImageResolve2 *region)
{
struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
assert(src_image->vk.samples > 1);
assert(dst_image->vk.samples == 1);
/* From the Vulkan 1.0 spec:
*
* - The aspectMask member of srcSubresource and dstSubresource must
* only contain VK_IMAGE_ASPECT_COLOR_BIT
*/
assert(region->srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
assert(region->dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
/* Multi-layer resolves are handled by compute */
assert(vk_image_subresource_layer_count(&src_image->vk, &region->srcSubresource) == 1 &&
vk_image_subresource_layer_count(&dst_image->vk, &region->dstSubresource) == 1);
/**
* 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.
*/
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);
uint32_t queue_mask = radv_image_queue_family_mask(dst_image, cmd_buffer->qf, cmd_buffer->qf);
if (radv_layout_dcc_compressed(device, dst_image, region->dstSubresource.mipLevel, dst_image_layout, queue_mask)) {
VkImageSubresourceRange range = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = region->dstSubresource.mipLevel,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
};
cmd_buffer->state.flush_bits |= radv_init_dcc(cmd_buffer, dst_image, &range, DCC_UNCOMPRESSED);
}
VkRect2D resolve_area = {
.offset = {dstOffset.x, dstOffset.y},
.extent = {extent.width, extent.height},
};
radv_meta_set_viewport_and_scissor(cmd_buffer, resolve_area.offset.x, resolve_area.offset.y,
resolve_area.extent.width, resolve_area.extent.height);
const VkImageViewUsageCreateInfo src_iview_usage_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
};
struct radv_image_view src_iview;
radv_image_view_init(&src_iview, device,
&(VkImageViewCreateInfo){
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.pNext = &src_iview_usage_info,
.flags = VK_IMAGE_VIEW_CREATE_DRIVER_INTERNAL_BIT_MESA,
.image = radv_image_to_handle(src_image),
.viewType = VK_IMAGE_VIEW_TYPE_2D,
.format = src_format,
.subresourceRange =
{
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
},
},
NULL);
const VkImageViewUsageCreateInfo dst_iview_usage_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
};
struct radv_image_view dst_iview;
radv_image_view_init(&dst_iview, device,
&(VkImageViewCreateInfo){
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.pNext = &dst_iview_usage_info,
.flags = VK_IMAGE_VIEW_CREATE_DRIVER_INTERNAL_BIT_MESA,
.image = radv_image_to_handle(dst_image),
.viewType = radv_meta_get_view_type(dst_image),
.format = dst_format,
.subresourceRange =
{
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = region->dstSubresource.mipLevel,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
},
},
NULL);
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,
.flags = VK_RENDERING_LOCAL_READ_CONCURRENT_ACCESS_CONTROL_BIT_KHR,
.renderArea = resolve_area,
.layerCount = 1,
.colorAttachmentCount = 2,
.pColorAttachments = color_atts,
};
radv_CmdBeginRendering(radv_cmd_buffer_to_handle(cmd_buffer), &rendering_info);
emit_resolve(cmd_buffer, src_image, dst_image, dst_format);
const VkRenderingEndInfoKHR end_info = {
.sType = VK_STRUCTURE_TYPE_RENDERING_END_INFO_KHR,
};
radv_CmdEndRendering2KHR(radv_cmd_buffer_to_handle(cmd_buffer), &end_info);
radv_image_view_finish(&src_iview);
radv_image_view_finish(&dst_iview);
}
/**
* Decompress CMask/FMask before resolving a multisampled source image.
*/
@ -470,21 +146,13 @@ resolve_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image,
const VkResolveModeFlagBits resolve_mode =
vk_format_is_int(src_format) ? VK_RESOLVE_MODE_SAMPLE_ZERO_BIT : VK_RESOLVE_MODE_AVERAGE_BIT;
switch (resolve_method) {
case RESOLVE_HW:
radv_meta_resolve_hardware_image(cmd_buffer, src_image, src_format, src_image_layout, dst_image, dst_format,
dst_image_layout, region);
break;
case RESOLVE_FRAGMENT:
if (resolve_method == RESOLVE_FRAGMENT) {
radv_gfx_resolve_image(cmd_buffer, src_image, src_format, src_image_layout, dst_image, dst_format,
dst_image_layout, resolve_mode, region);
break;
case RESOLVE_COMPUTE:
} else {
assert(resolve_method == RESOLVE_COMPUTE);
radv_compute_resolve_image(cmd_buffer, src_image, src_format, src_image_layout, dst_image, dst_format,
dst_image_layout, resolve_mode, region);
break;
default:
assert(!"Invalid resolve method selected");
}
}
}
@ -507,22 +175,6 @@ radv_CmdResolveImage2(VkCommandBuffer commandBuffer, const VkResolveImageInfo2 *
radv_meta_begin(cmd_buffer);
/* 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->vk.extent.width ||
pResolveImageInfo->pRegions[0].extent.height != src_image->vk.extent.height ||
pResolveImageInfo->pRegions[0].extent.depth != src_image->vk.extent.depth)
resolve_method = RESOLVE_COMPUTE;
} else
resolve_method = RESOLVE_COMPUTE;
for (uint32_t r = 0; r < pResolveImageInfo->regionCount; r++) {
const VkImageResolve2 *region = &pResolveImageInfo->pRegions[r];
@ -741,27 +393,15 @@ radv_cmd_buffer_resolve_rendering(struct radv_cmd_buffer *cmd_buffer, const VkRe
dst_format = vk_format_no_srgb(dst_format);
}
switch (resolve_method) {
case RESOLVE_HW:
radv_meta_resolve_hardware_image(cmd_buffer, src_iview->image, src_format, src_layout, dst_iview->image,
dst_format, dst_layout, &region);
break;
case RESOLVE_COMPUTE:
radv_decompress_resolve_src(cmd_buffer, src_iview->image, src_layout, &region, NULL);
radv_compute_resolve_image(cmd_buffer, src_iview->image, src_format, src_layout, dst_iview->image,
dst_format, dst_layout, att->resolveMode, &region);
used_compute = true;
break;
case RESOLVE_FRAGMENT: {
radv_decompress_resolve_src(cmd_buffer, src_iview->image, src_layout, &region, NULL);
radv_decompress_resolve_src(cmd_buffer, src_iview->image, src_layout, &region, NULL);
if (resolve_method == RESOLVE_FRAGMENT) {
radv_gfx_resolve_image(cmd_buffer, src_iview->image, src_format, src_layout, dst_iview->image, dst_format,
dst_layout, att->resolveMode, &region);
break;
}
default:
UNREACHABLE("Invalid resolve method");
} else {
assert(resolve_method == RESOLVE_COMPUTE);
radv_compute_resolve_image(cmd_buffer, src_iview->image, src_format, src_layout, dst_iview->image,
dst_format, dst_layout, att->resolveMode, &region);
}
}
}

View file

@ -1355,21 +1355,6 @@ radv_meta_nir_build_resolve_fs(struct radv_device *dev, bool use_fmask, int samp
return b.shader;
}
nir_shader *
radv_meta_nir_build_resolve_hw(struct radv_device *dev)
{
const struct glsl_type *vec4 = glsl_vec4_type();
nir_variable *f_color;
nir_builder b = radv_meta_nir_init_shader(dev, MESA_SHADER_FRAGMENT, "meta_resolve_hw");
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);
return b.shader;
}
nir_shader *
radv_meta_nir_build_clear_hiz_compute_shader(struct radv_device *dev, int samples)
{

View file

@ -103,8 +103,6 @@ nir_shader *radv_meta_nir_build_resolve_cs(struct radv_device *dev, bool use_fma
nir_shader *radv_meta_nir_build_resolve_fs(struct radv_device *dev, bool use_fmask, int samples, bool is_integer,
VkImageAspectFlags aspects, VkResolveModeFlagBits resolve_mode);
nir_shader *radv_meta_nir_build_resolve_hw(struct radv_device *dev);
nir_shader *radv_meta_nir_build_clear_hiz_compute_shader(struct radv_device *dev, int samples);
nir_shader *radv_meta_nir_build_copy_memory_indirect_preprocess_cs(struct radv_device *dev);

View file

@ -12200,9 +12200,8 @@ radv_emit_cb_render_state(struct radv_cmd_buffer *cmd_buffer)
}
if (pdev->info.has_rbplus) {
/* RB+ doesn't work with dual source blending, logic op and CB_RESOLVE. */
cb_color_control |= S_028808_DISABLE_DUAL_QUAD(mrt0_is_dual_src || d->vk.cb.logic_op_enable ||
cmd_buffer->state.custom_blend_mode == V_028808_CB_RESOLVE);
/* RB+ doesn't work with dual source blending and logic op. */
cb_color_control |= S_028808_DISABLE_DUAL_QUAD(mrt0_is_dual_src || d->vk.cb.logic_op_enable);
if (mrt0_is_dual_src) {
for (unsigned i = 0; i < MAX_RTS; i++) {