Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/amd/vulkan/radv_meta_resolve.c
7204 views
1
/*
2
* Copyright © 2016 Intel Corporation
3
*
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the "Software"),
6
* to deal in the Software without restriction, including without limitation
7
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
* and/or sell copies of the Software, and to permit persons to whom the
9
* Software is furnished to do so, subject to the following conditions:
10
*
11
* The above copyright notice and this permission notice (including the next
12
* paragraph) shall be included in all copies or substantial portions of the
13
* Software.
14
*
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
* IN THE SOFTWARE.
22
*/
23
24
#include <assert.h>
25
#include <stdbool.h>
26
27
#include "nir/nir_builder.h"
28
#include "radv_meta.h"
29
#include "radv_private.h"
30
#include "sid.h"
31
#include "vk_format.h"
32
33
/* emit 0, 0, 0, 1 */
34
static nir_shader *
35
build_nir_fs(void)
36
{
37
const struct glsl_type *vec4 = glsl_vec4_type();
38
nir_variable *f_color; /* vec4, fragment output color */
39
40
nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT, NULL, "meta_resolve_fs");
41
42
f_color = nir_variable_create(b.shader, nir_var_shader_out, vec4, "f_color");
43
f_color->data.location = FRAG_RESULT_DATA0;
44
nir_store_var(&b, f_color, nir_imm_vec4(&b, 0.0, 0.0, 0.0, 1.0), 0xf);
45
46
return b.shader;
47
}
48
49
static VkResult
50
create_pass(struct radv_device *device, VkFormat vk_format, VkRenderPass *pass)
51
{
52
VkResult result;
53
VkDevice device_h = radv_device_to_handle(device);
54
const VkAllocationCallbacks *alloc = &device->meta_state.alloc;
55
VkAttachmentDescription2 attachments[2];
56
int i;
57
58
for (i = 0; i < 2; i++) {
59
attachments[i].sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2;
60
attachments[i].pNext = NULL;
61
attachments[i].format = vk_format;
62
attachments[i].samples = 1;
63
attachments[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
64
attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
65
}
66
attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
67
attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
68
attachments[1].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
69
attachments[1].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
70
71
result = radv_CreateRenderPass2(
72
device_h,
73
&(VkRenderPassCreateInfo2){
74
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,
75
.attachmentCount = 2,
76
.pAttachments = attachments,
77
.subpassCount = 1,
78
.pSubpasses =
79
&(VkSubpassDescription2){
80
.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,
81
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
82
.inputAttachmentCount = 0,
83
.colorAttachmentCount = 2,
84
.pColorAttachments =
85
(VkAttachmentReference2[]){
86
{
87
.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,
88
.attachment = 0,
89
.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
90
},
91
{
92
.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,
93
.attachment = 1,
94
.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
95
},
96
},
97
.pResolveAttachments = NULL,
98
.pDepthStencilAttachment =
99
&(VkAttachmentReference2){
100
.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,
101
.attachment = VK_ATTACHMENT_UNUSED,
102
},
103
.preserveAttachmentCount = 0,
104
.pPreserveAttachments = NULL,
105
},
106
.dependencyCount = 2,
107
.pDependencies =
108
(VkSubpassDependency2[]){{.sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2,
109
.srcSubpass = VK_SUBPASS_EXTERNAL,
110
.dstSubpass = 0,
111
.srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
112
.dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
113
.srcAccessMask = 0,
114
.dstAccessMask = 0,
115
.dependencyFlags = 0},
116
{.sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2,
117
.srcSubpass = 0,
118
.dstSubpass = VK_SUBPASS_EXTERNAL,
119
.srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
120
.dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
121
.srcAccessMask = 0,
122
.dstAccessMask = 0,
123
.dependencyFlags = 0}},
124
},
125
alloc, pass);
126
127
return result;
128
}
129
130
static VkResult
131
create_pipeline(struct radv_device *device, VkShaderModule vs_module_h, VkPipeline *pipeline,
132
VkRenderPass pass)
133
{
134
VkResult result;
135
VkDevice device_h = radv_device_to_handle(device);
136
137
nir_shader *fs_module = build_nir_fs();
138
if (!fs_module) {
139
/* XXX: Need more accurate error */
140
result = VK_ERROR_OUT_OF_HOST_MEMORY;
141
goto cleanup;
142
}
143
144
VkPipelineLayoutCreateInfo pl_create_info = {
145
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
146
.setLayoutCount = 0,
147
.pSetLayouts = NULL,
148
.pushConstantRangeCount = 0,
149
.pPushConstantRanges = NULL,
150
};
151
152
if (!device->meta_state.resolve.p_layout) {
153
result =
154
radv_CreatePipelineLayout(radv_device_to_handle(device), &pl_create_info,
155
&device->meta_state.alloc, &device->meta_state.resolve.p_layout);
156
if (result != VK_SUCCESS)
157
goto cleanup;
158
}
159
160
result = radv_graphics_pipeline_create(
161
device_h, radv_pipeline_cache_to_handle(&device->meta_state.cache),
162
&(VkGraphicsPipelineCreateInfo){
163
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
164
.stageCount = 2,
165
.pStages =
166
(VkPipelineShaderStageCreateInfo[]){
167
{
168
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
169
.stage = VK_SHADER_STAGE_VERTEX_BIT,
170
.module = vs_module_h,
171
.pName = "main",
172
},
173
{
174
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
175
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
176
.module = vk_shader_module_handle_from_nir(fs_module),
177
.pName = "main",
178
},
179
},
180
.pVertexInputState =
181
&(VkPipelineVertexInputStateCreateInfo){
182
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
183
.vertexBindingDescriptionCount = 0,
184
.vertexAttributeDescriptionCount = 0,
185
},
186
.pInputAssemblyState =
187
&(VkPipelineInputAssemblyStateCreateInfo){
188
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
189
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
190
.primitiveRestartEnable = false,
191
},
192
.pViewportState =
193
&(VkPipelineViewportStateCreateInfo){
194
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
195
.viewportCount = 1,
196
.scissorCount = 1,
197
},
198
.pRasterizationState =
199
&(VkPipelineRasterizationStateCreateInfo){
200
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
201
.depthClampEnable = false,
202
.rasterizerDiscardEnable = false,
203
.polygonMode = VK_POLYGON_MODE_FILL,
204
.cullMode = VK_CULL_MODE_NONE,
205
.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
206
},
207
.pMultisampleState =
208
&(VkPipelineMultisampleStateCreateInfo){
209
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
210
.rasterizationSamples = 1,
211
.sampleShadingEnable = false,
212
.pSampleMask = NULL,
213
.alphaToCoverageEnable = false,
214
.alphaToOneEnable = false,
215
},
216
.pColorBlendState =
217
&(VkPipelineColorBlendStateCreateInfo){
218
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
219
.logicOpEnable = false,
220
.attachmentCount = 2,
221
.pAttachments =
222
(VkPipelineColorBlendAttachmentState[]){
223
{
224
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
225
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
226
},
227
{
228
.colorWriteMask = 0,
229
230
}},
231
},
232
.pDynamicState =
233
&(VkPipelineDynamicStateCreateInfo){
234
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
235
.dynamicStateCount = 2,
236
.pDynamicStates =
237
(VkDynamicState[]){
238
VK_DYNAMIC_STATE_VIEWPORT,
239
VK_DYNAMIC_STATE_SCISSOR,
240
},
241
},
242
.layout = device->meta_state.resolve.p_layout,
243
.renderPass = pass,
244
.subpass = 0,
245
},
246
&(struct radv_graphics_pipeline_create_info){
247
.use_rectlist = true,
248
.custom_blend_mode = V_028808_CB_RESOLVE,
249
},
250
&device->meta_state.alloc, pipeline);
251
if (result != VK_SUCCESS)
252
goto cleanup;
253
254
goto cleanup;
255
256
cleanup:
257
ralloc_free(fs_module);
258
return result;
259
}
260
261
void
262
radv_device_finish_meta_resolve_state(struct radv_device *device)
263
{
264
struct radv_meta_state *state = &device->meta_state;
265
266
for (uint32_t j = 0; j < NUM_META_FS_KEYS; j++) {
267
radv_DestroyRenderPass(radv_device_to_handle(device), state->resolve.pass[j], &state->alloc);
268
radv_DestroyPipeline(radv_device_to_handle(device), state->resolve.pipeline[j],
269
&state->alloc);
270
}
271
radv_DestroyPipelineLayout(radv_device_to_handle(device), state->resolve.p_layout,
272
&state->alloc);
273
}
274
275
VkResult
276
radv_device_init_meta_resolve_state(struct radv_device *device, bool on_demand)
277
{
278
if (on_demand)
279
return VK_SUCCESS;
280
281
VkResult res = VK_SUCCESS;
282
struct radv_meta_state *state = &device->meta_state;
283
nir_shader *vs_module = radv_meta_build_nir_vs_generate_vertices();
284
if (!vs_module) {
285
/* XXX: Need more accurate error */
286
res = VK_ERROR_OUT_OF_HOST_MEMORY;
287
goto fail;
288
}
289
290
for (uint32_t i = 0; i < NUM_META_FS_KEYS; ++i) {
291
VkFormat format = radv_fs_key_format_exemplars[i];
292
unsigned fs_key = radv_format_meta_fs_key(device, format);
293
res = create_pass(device, format, &state->resolve.pass[fs_key]);
294
if (res != VK_SUCCESS)
295
goto fail;
296
297
VkShaderModule vs_module_h = vk_shader_module_handle_from_nir(vs_module);
298
res = create_pipeline(device, vs_module_h, &state->resolve.pipeline[fs_key],
299
state->resolve.pass[fs_key]);
300
if (res != VK_SUCCESS)
301
goto fail;
302
}
303
304
goto cleanup;
305
306
fail:
307
radv_device_finish_meta_resolve_state(device);
308
309
cleanup:
310
ralloc_free(vs_module);
311
312
return res;
313
}
314
315
static void
316
emit_resolve(struct radv_cmd_buffer *cmd_buffer, const struct radv_image *src_image,
317
const struct radv_image *dst_image, VkFormat vk_format, const VkOffset2D *dest_offset,
318
const VkExtent2D *resolve_extent)
319
{
320
struct radv_device *device = cmd_buffer->device;
321
VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
322
unsigned fs_key = radv_format_meta_fs_key(device, vk_format);
323
324
cmd_buffer->state.flush_bits |=
325
radv_src_access_flush(cmd_buffer, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, src_image) |
326
radv_dst_access_flush(cmd_buffer, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, src_image) |
327
radv_dst_access_flush(cmd_buffer, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, dst_image);
328
329
radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS,
330
device->meta_state.resolve.pipeline[fs_key]);
331
332
radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1,
333
&(VkViewport){.x = dest_offset->x,
334
.y = dest_offset->y,
335
.width = resolve_extent->width,
336
.height = resolve_extent->height,
337
.minDepth = 0.0f,
338
.maxDepth = 1.0f});
339
340
radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1,
341
&(VkRect2D){
342
.offset = *dest_offset,
343
.extent = *resolve_extent,
344
});
345
346
radv_CmdDraw(cmd_buffer_h, 3, 1, 0, 0);
347
cmd_buffer->state.flush_bits |=
348
radv_src_access_flush(cmd_buffer, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, dst_image);
349
}
350
351
enum radv_resolve_method {
352
RESOLVE_HW,
353
RESOLVE_COMPUTE,
354
RESOLVE_FRAGMENT,
355
};
356
357
static bool
358
image_hw_resolve_compat(const struct radv_device *device, struct radv_image *src_image,
359
struct radv_image *dst_image)
360
{
361
if (device->physical_device->rad_info.chip_class >= GFX9) {
362
return dst_image->planes[0].surface.u.gfx9.swizzle_mode ==
363
src_image->planes[0].surface.u.gfx9.swizzle_mode;
364
} else {
365
return dst_image->planes[0].surface.micro_tile_mode ==
366
src_image->planes[0].surface.micro_tile_mode;
367
}
368
}
369
370
static void
371
radv_pick_resolve_method_images(struct radv_device *device, struct radv_image *src_image,
372
VkFormat src_format, struct radv_image *dest_image,
373
unsigned dest_level, VkImageLayout dest_image_layout,
374
bool dest_render_loop, struct radv_cmd_buffer *cmd_buffer,
375
enum radv_resolve_method *method)
376
377
{
378
uint32_t queue_mask = radv_image_queue_family_mask(dest_image, cmd_buffer->queue_family_index,
379
cmd_buffer->queue_family_index);
380
381
if (vk_format_is_color(src_format)) {
382
/* Using the fragment resolve path is currently a hint to
383
* avoid decompressing DCC for partial resolves and
384
* re-initialize it after resolving using compute.
385
* TODO: Add support for layered and int to the fragment path.
386
*/
387
if (radv_layout_dcc_compressed(device, dest_image, dest_level, dest_image_layout,
388
dest_render_loop, queue_mask)) {
389
*method = RESOLVE_FRAGMENT;
390
} else if (!image_hw_resolve_compat(device, src_image, dest_image)) {
391
/* The micro tile mode only needs to match for the HW
392
* resolve path which is the default path for non-DCC
393
* resolves.
394
*/
395
*method = RESOLVE_COMPUTE;
396
}
397
398
if (src_format == VK_FORMAT_R16G16_UNORM || src_format == VK_FORMAT_R16G16_SNORM)
399
*method = RESOLVE_COMPUTE;
400
else if (vk_format_is_int(src_format))
401
*method = RESOLVE_COMPUTE;
402
else if (src_image->info.array_size > 1 || dest_image->info.array_size > 1)
403
*method = RESOLVE_COMPUTE;
404
} else {
405
if (src_image->info.array_size > 1 || dest_image->info.array_size > 1)
406
*method = RESOLVE_COMPUTE;
407
else
408
*method = RESOLVE_FRAGMENT;
409
}
410
}
411
412
static VkResult
413
build_resolve_pipeline(struct radv_device *device, unsigned fs_key)
414
{
415
VkResult result = VK_SUCCESS;
416
417
if (device->meta_state.resolve.pipeline[fs_key])
418
return result;
419
420
mtx_lock(&device->meta_state.mtx);
421
if (device->meta_state.resolve.pipeline[fs_key]) {
422
mtx_unlock(&device->meta_state.mtx);
423
return result;
424
}
425
426
nir_shader *vs_module = radv_meta_build_nir_vs_generate_vertices();
427
428
result = create_pass(device, radv_fs_key_format_exemplars[fs_key],
429
&device->meta_state.resolve.pass[fs_key]);
430
if (result != VK_SUCCESS)
431
goto fail;
432
433
VkShaderModule vs_module_h = vk_shader_module_handle_from_nir(vs_module);
434
result = create_pipeline(device, vs_module_h, &device->meta_state.resolve.pipeline[fs_key],
435
device->meta_state.resolve.pass[fs_key]);
436
437
fail:
438
ralloc_free(vs_module);
439
mtx_unlock(&device->meta_state.mtx);
440
return result;
441
}
442
443
static void
444
radv_meta_resolve_hardware_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image,
445
VkImageLayout src_image_layout, struct radv_image *dst_image,
446
VkImageLayout dst_image_layout, const VkImageResolve2KHR *region)
447
{
448
struct radv_device *device = cmd_buffer->device;
449
struct radv_meta_saved_state saved_state;
450
451
radv_meta_save(&saved_state, cmd_buffer, RADV_META_SAVE_GRAPHICS_PIPELINE);
452
453
assert(src_image->info.samples > 1);
454
if (src_image->info.samples <= 1) {
455
/* this causes GPU hangs if we get past here */
456
fprintf(stderr, "radv: Illegal resolve operation (src not multisampled), will hang GPU.");
457
return;
458
}
459
assert(dst_image->info.samples == 1);
460
461
if (src_image->info.array_size > 1)
462
radv_finishme("vkCmdResolveImage: multisample array images");
463
464
unsigned fs_key = radv_format_meta_fs_key(device, dst_image->vk_format);
465
466
/* From the Vulkan 1.0 spec:
467
*
468
* - The aspectMask member of srcSubresource and dstSubresource must
469
* only contain VK_IMAGE_ASPECT_COLOR_BIT
470
*
471
* - The layerCount member of srcSubresource and dstSubresource must
472
* match
473
*/
474
assert(region->srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
475
assert(region->dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
476
assert(region->srcSubresource.layerCount == region->dstSubresource.layerCount);
477
478
const uint32_t src_base_layer =
479
radv_meta_get_iview_layer(src_image, &region->srcSubresource, &region->srcOffset);
480
481
const uint32_t dst_base_layer =
482
radv_meta_get_iview_layer(dst_image, &region->dstSubresource, &region->dstOffset);
483
484
/**
485
* From Vulkan 1.0.6 spec: 18.6 Resolving Multisample Images
486
*
487
* extent is the size in texels of the source image to resolve in width,
488
* height and depth. 1D images use only x and width. 2D images use x, y,
489
* width and height. 3D images use x, y, z, width, height and depth.
490
*
491
* srcOffset and dstOffset select the initial x, y, and z offsets in
492
* texels of the sub-regions of the source and destination image data.
493
* extent is the size in texels of the source image to resolve in width,
494
* height and depth. 1D images use only x and width. 2D images use x, y,
495
* width and height. 3D images use x, y, z, width, height and depth.
496
*/
497
const struct VkExtent3D extent = radv_sanitize_image_extent(src_image->type, region->extent);
498
const struct VkOffset3D dstOffset =
499
radv_sanitize_image_offset(dst_image->type, region->dstOffset);
500
501
uint32_t queue_mask = radv_image_queue_family_mask(dst_image, cmd_buffer->queue_family_index,
502
cmd_buffer->queue_family_index);
503
504
if (radv_layout_dcc_compressed(cmd_buffer->device, dst_image, region->dstSubresource.mipLevel,
505
dst_image_layout, false, queue_mask)) {
506
VkImageSubresourceRange range = {
507
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
508
.baseMipLevel = region->dstSubresource.mipLevel,
509
.levelCount = 1,
510
.baseArrayLayer = dst_base_layer,
511
.layerCount = region->dstSubresource.layerCount,
512
};
513
514
cmd_buffer->state.flush_bits |= radv_init_dcc(cmd_buffer, dst_image, &range, 0xffffffff);
515
}
516
517
for (uint32_t layer = 0; layer < region->srcSubresource.layerCount; ++layer) {
518
519
VkResult ret = build_resolve_pipeline(device, fs_key);
520
if (ret != VK_SUCCESS) {
521
cmd_buffer->record_result = ret;
522
break;
523
}
524
525
struct radv_image_view src_iview;
526
radv_image_view_init(&src_iview, cmd_buffer->device,
527
&(VkImageViewCreateInfo){
528
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
529
.image = radv_image_to_handle(src_image),
530
.viewType = radv_meta_get_view_type(src_image),
531
.format = src_image->vk_format,
532
.subresourceRange =
533
{
534
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
535
.baseMipLevel = region->srcSubresource.mipLevel,
536
.levelCount = 1,
537
.baseArrayLayer = src_base_layer + layer,
538
.layerCount = 1,
539
},
540
},
541
NULL);
542
543
struct radv_image_view dst_iview;
544
radv_image_view_init(&dst_iview, cmd_buffer->device,
545
&(VkImageViewCreateInfo){
546
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
547
.image = radv_image_to_handle(dst_image),
548
.viewType = radv_meta_get_view_type(dst_image),
549
.format = dst_image->vk_format,
550
.subresourceRange =
551
{
552
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
553
.baseMipLevel = region->dstSubresource.mipLevel,
554
.levelCount = 1,
555
.baseArrayLayer = dst_base_layer + layer,
556
.layerCount = 1,
557
},
558
},
559
NULL);
560
561
VkFramebuffer fb_h;
562
radv_CreateFramebuffer(
563
radv_device_to_handle(device),
564
&(VkFramebufferCreateInfo){
565
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
566
.attachmentCount = 2,
567
.pAttachments =
568
(VkImageView[]){
569
radv_image_view_to_handle(&src_iview),
570
radv_image_view_to_handle(&dst_iview),
571
},
572
.width = radv_minify(dst_image->info.width, region->dstSubresource.mipLevel),
573
.height = radv_minify(dst_image->info.height, region->dstSubresource.mipLevel),
574
.layers = 1},
575
&cmd_buffer->pool->alloc, &fb_h);
576
577
radv_cmd_buffer_begin_render_pass(cmd_buffer,
578
&(VkRenderPassBeginInfo){
579
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
580
.renderPass = device->meta_state.resolve.pass[fs_key],
581
.framebuffer = fb_h,
582
.renderArea = {.offset =
583
{
584
dstOffset.x,
585
dstOffset.y,
586
},
587
.extent =
588
{
589
extent.width,
590
extent.height,
591
}},
592
.clearValueCount = 0,
593
.pClearValues = NULL,
594
},
595
NULL);
596
597
radv_cmd_buffer_set_subpass(cmd_buffer, &cmd_buffer->state.pass->subpasses[0]);
598
599
emit_resolve(cmd_buffer, src_image, dst_image, dst_iview.vk_format,
600
&(VkOffset2D){
601
.x = dstOffset.x,
602
.y = dstOffset.y,
603
},
604
&(VkExtent2D){
605
.width = extent.width,
606
.height = extent.height,
607
});
608
609
radv_cmd_buffer_end_render_pass(cmd_buffer);
610
611
radv_DestroyFramebuffer(radv_device_to_handle(device), fb_h, &cmd_buffer->pool->alloc);
612
}
613
614
radv_meta_restore(&saved_state, cmd_buffer);
615
}
616
617
static void
618
resolve_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image,
619
VkImageLayout src_image_layout, struct radv_image *dst_image,
620
VkImageLayout dst_image_layout, const VkImageResolve2KHR *region,
621
enum radv_resolve_method resolve_method)
622
{
623
switch (resolve_method) {
624
case RESOLVE_HW:
625
radv_meta_resolve_hardware_image(cmd_buffer, src_image, src_image_layout, dst_image,
626
dst_image_layout, region);
627
break;
628
case RESOLVE_FRAGMENT:
629
radv_meta_resolve_fragment_image(cmd_buffer, src_image, src_image_layout, dst_image,
630
dst_image_layout, region);
631
break;
632
case RESOLVE_COMPUTE:
633
radv_meta_resolve_compute_image(cmd_buffer, src_image, src_image->vk_format, src_image_layout,
634
dst_image, dst_image->vk_format, dst_image_layout, region);
635
break;
636
default:
637
assert(!"Invalid resolve method selected");
638
}
639
}
640
641
void
642
radv_CmdResolveImage2KHR(VkCommandBuffer commandBuffer,
643
const VkResolveImageInfo2KHR *pResolveImageInfo)
644
{
645
RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
646
RADV_FROM_HANDLE(radv_image, src_image, pResolveImageInfo->srcImage);
647
RADV_FROM_HANDLE(radv_image, dst_image, pResolveImageInfo->dstImage);
648
VkImageLayout src_image_layout = pResolveImageInfo->srcImageLayout;
649
VkImageLayout dst_image_layout = pResolveImageInfo->dstImageLayout;
650
enum radv_resolve_method resolve_method = RESOLVE_HW;
651
/* we can use the hw resolve only for single full resolves */
652
if (pResolveImageInfo->regionCount == 1) {
653
if (pResolveImageInfo->pRegions[0].srcOffset.x ||
654
pResolveImageInfo->pRegions[0].srcOffset.y || pResolveImageInfo->pRegions[0].srcOffset.z)
655
resolve_method = RESOLVE_COMPUTE;
656
if (pResolveImageInfo->pRegions[0].dstOffset.x ||
657
pResolveImageInfo->pRegions[0].dstOffset.y || pResolveImageInfo->pRegions[0].dstOffset.z)
658
resolve_method = RESOLVE_COMPUTE;
659
660
if (pResolveImageInfo->pRegions[0].extent.width != src_image->info.width ||
661
pResolveImageInfo->pRegions[0].extent.height != src_image->info.height ||
662
pResolveImageInfo->pRegions[0].extent.depth != src_image->info.depth)
663
resolve_method = RESOLVE_COMPUTE;
664
} else
665
resolve_method = RESOLVE_COMPUTE;
666
667
for (uint32_t r = 0; r < pResolveImageInfo->regionCount; r++) {
668
const VkImageResolve2KHR *region = &pResolveImageInfo->pRegions[r];
669
670
radv_pick_resolve_method_images(cmd_buffer->device, src_image, src_image->vk_format, dst_image,
671
region->dstSubresource.mipLevel, dst_image_layout, false,
672
cmd_buffer, &resolve_method);
673
674
resolve_image(cmd_buffer, src_image, src_image_layout, dst_image, dst_image_layout, region,
675
resolve_method);
676
}
677
}
678
679
static void
680
radv_cmd_buffer_resolve_subpass_hw(struct radv_cmd_buffer *cmd_buffer)
681
{
682
struct radv_framebuffer *fb = cmd_buffer->state.framebuffer;
683
const struct radv_subpass *subpass = cmd_buffer->state.subpass;
684
struct radv_meta_saved_state saved_state;
685
686
radv_meta_save(&saved_state, cmd_buffer, RADV_META_SAVE_GRAPHICS_PIPELINE);
687
688
for (uint32_t i = 0; i < subpass->color_count; ++i) {
689
struct radv_subpass_attachment src_att = subpass->color_attachments[i];
690
struct radv_subpass_attachment dest_att = subpass->resolve_attachments[i];
691
692
if (dest_att.attachment == VK_ATTACHMENT_UNUSED)
693
continue;
694
695
struct radv_image_view *src_iview = cmd_buffer->state.attachments[src_att.attachment].iview;
696
struct radv_image *src_img = src_iview->image;
697
698
struct radv_image_view *dest_iview = cmd_buffer->state.attachments[dest_att.attachment].iview;
699
struct radv_image *dst_img = dest_iview->image;
700
VkImageLayout dst_image_layout = cmd_buffer->state.attachments[dest_att.attachment].current_layout;
701
702
uint32_t queue_mask = radv_image_queue_family_mask(dst_img, cmd_buffer->queue_family_index,
703
cmd_buffer->queue_family_index);
704
705
if (radv_layout_dcc_compressed(cmd_buffer->device, dst_img, dest_iview->base_mip,
706
dst_image_layout, false, queue_mask)) {
707
VkImageSubresourceRange range = {
708
.aspectMask = dest_iview->aspect_mask,
709
.baseMipLevel = dest_iview->base_mip,
710
.levelCount = dest_iview->level_count,
711
.baseArrayLayer = dest_iview->base_layer,
712
.layerCount = dest_iview->layer_count,
713
};
714
715
cmd_buffer->state.flush_bits |= radv_init_dcc(cmd_buffer, dst_img, &range, 0xffffffff);
716
cmd_buffer->state.attachments[dest_att.attachment].current_layout =
717
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
718
}
719
720
struct radv_subpass resolve_subpass = {
721
.color_count = 2,
722
.color_attachments = (struct radv_subpass_attachment[]){src_att, dest_att},
723
.depth_stencil_attachment = NULL,
724
};
725
726
radv_cmd_buffer_set_subpass(cmd_buffer, &resolve_subpass);
727
728
VkResult ret = build_resolve_pipeline(
729
cmd_buffer->device, radv_format_meta_fs_key(cmd_buffer->device, dest_iview->vk_format));
730
if (ret != VK_SUCCESS) {
731
cmd_buffer->record_result = ret;
732
continue;
733
}
734
735
emit_resolve(cmd_buffer, src_img, dst_img, dest_iview->vk_format, &(VkOffset2D){0, 0},
736
&(VkExtent2D){fb->width, fb->height});
737
}
738
739
radv_cmd_buffer_set_subpass(cmd_buffer, subpass);
740
741
radv_meta_restore(&saved_state, cmd_buffer);
742
}
743
744
/**
745
* Emit any needed resolves for the current subpass.
746
*/
747
void
748
radv_cmd_buffer_resolve_subpass(struct radv_cmd_buffer *cmd_buffer)
749
{
750
const struct radv_subpass *subpass = cmd_buffer->state.subpass;
751
enum radv_resolve_method resolve_method = RESOLVE_HW;
752
753
if (!subpass->has_color_resolve && !subpass->ds_resolve_attachment)
754
return;
755
756
radv_describe_begin_render_pass_resolve(cmd_buffer);
757
758
if (subpass->ds_resolve_attachment) {
759
struct radv_subpass_attachment src_att = *subpass->depth_stencil_attachment;
760
struct radv_subpass_attachment dst_att = *subpass->ds_resolve_attachment;
761
struct radv_image_view *src_iview = cmd_buffer->state.attachments[src_att.attachment].iview;
762
struct radv_image_view *dst_iview = cmd_buffer->state.attachments[dst_att.attachment].iview;
763
764
/* Make sure to not clear the depth/stencil attachment after resolves. */
765
cmd_buffer->state.attachments[dst_att.attachment].pending_clear_aspects = 0;
766
767
radv_pick_resolve_method_images(cmd_buffer->device, src_iview->image, src_iview->vk_format,
768
dst_iview->image, dst_iview->base_mip, dst_att.layout,
769
dst_att.in_render_loop, cmd_buffer, &resolve_method);
770
771
if ((src_iview->aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) &&
772
subpass->depth_resolve_mode != VK_RESOLVE_MODE_NONE_KHR) {
773
if (resolve_method == RESOLVE_FRAGMENT) {
774
radv_depth_stencil_resolve_subpass_fs(cmd_buffer, VK_IMAGE_ASPECT_DEPTH_BIT,
775
subpass->depth_resolve_mode);
776
} else {
777
assert(resolve_method == RESOLVE_COMPUTE);
778
radv_depth_stencil_resolve_subpass_cs(cmd_buffer, VK_IMAGE_ASPECT_DEPTH_BIT,
779
subpass->depth_resolve_mode);
780
}
781
}
782
783
if ((src_iview->aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) &&
784
subpass->stencil_resolve_mode != VK_RESOLVE_MODE_NONE_KHR) {
785
if (resolve_method == RESOLVE_FRAGMENT) {
786
radv_depth_stencil_resolve_subpass_fs(cmd_buffer, VK_IMAGE_ASPECT_STENCIL_BIT,
787
subpass->stencil_resolve_mode);
788
} else {
789
assert(resolve_method == RESOLVE_COMPUTE);
790
radv_depth_stencil_resolve_subpass_cs(cmd_buffer, VK_IMAGE_ASPECT_STENCIL_BIT,
791
subpass->stencil_resolve_mode);
792
}
793
}
794
795
/* From the Vulkan spec 1.2.165:
796
*
797
* "VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT specifies
798
* write access to a color, resolve, or depth/stencil
799
* resolve attachment during a render pass or via
800
* certain subpass load and store operations."
801
*
802
* Yes, it's counterintuitive but it makes sense because ds
803
* resolve operations happen late at the end of the subpass.
804
*
805
* That said, RADV is wrong because it executes the subpass
806
* end barrier *before* any subpass resolves instead of after.
807
*
808
* TODO: Fix this properly by executing subpass end barriers
809
* after subpass resolves.
810
*/
811
cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_DB;
812
if (radv_image_has_htile(dst_iview->image))
813
cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_DB_META;
814
}
815
816
if (subpass->has_color_resolve) {
817
for (uint32_t i = 0; i < subpass->color_count; ++i) {
818
struct radv_subpass_attachment src_att = subpass->color_attachments[i];
819
struct radv_subpass_attachment dest_att = subpass->resolve_attachments[i];
820
821
if (dest_att.attachment == VK_ATTACHMENT_UNUSED)
822
continue;
823
824
/* Make sure to not clear color attachments after resolves. */
825
cmd_buffer->state.attachments[dest_att.attachment].pending_clear_aspects = 0;
826
827
struct radv_image_view *dst_iview =
828
cmd_buffer->state.attachments[dest_att.attachment].iview;
829
struct radv_image *dst_img = dst_iview->image;
830
struct radv_image_view *src_iview =
831
cmd_buffer->state.attachments[src_att.attachment].iview;
832
struct radv_image *src_img = src_iview->image;
833
834
radv_pick_resolve_method_images(cmd_buffer->device, src_img, src_iview->vk_format, dst_img,
835
dst_iview->base_mip, dest_att.layout,
836
dest_att.in_render_loop, cmd_buffer, &resolve_method);
837
838
if (resolve_method == RESOLVE_FRAGMENT) {
839
break;
840
}
841
}
842
843
switch (resolve_method) {
844
case RESOLVE_HW:
845
radv_cmd_buffer_resolve_subpass_hw(cmd_buffer);
846
break;
847
case RESOLVE_COMPUTE:
848
radv_cmd_buffer_resolve_subpass_cs(cmd_buffer);
849
break;
850
case RESOLVE_FRAGMENT:
851
radv_cmd_buffer_resolve_subpass_fs(cmd_buffer);
852
break;
853
default:
854
unreachable("Invalid resolve method");
855
}
856
}
857
858
radv_describe_end_render_pass_resolve(cmd_buffer);
859
}
860
861
/**
862
* Decompress CMask/FMask before resolving a multisampled source image inside a
863
* subpass.
864
*/
865
void
866
radv_decompress_resolve_subpass_src(struct radv_cmd_buffer *cmd_buffer)
867
{
868
const struct radv_subpass *subpass = cmd_buffer->state.subpass;
869
struct radv_framebuffer *fb = cmd_buffer->state.framebuffer;
870
uint32_t layer_count = fb->layers;
871
872
if (subpass->view_mask)
873
layer_count = util_last_bit(subpass->view_mask);
874
875
for (uint32_t i = 0; i < subpass->color_count; ++i) {
876
struct radv_subpass_attachment src_att = subpass->color_attachments[i];
877
struct radv_subpass_attachment dest_att = subpass->resolve_attachments[i];
878
879
if (dest_att.attachment == VK_ATTACHMENT_UNUSED)
880
continue;
881
882
struct radv_image_view *src_iview = cmd_buffer->state.attachments[src_att.attachment].iview;
883
struct radv_image *src_image = src_iview->image;
884
885
VkImageResolve2KHR region = {0};
886
region.sType = VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2_KHR;
887
region.srcSubresource.aspectMask = src_iview->aspect_mask;
888
region.srcSubresource.mipLevel = 0;
889
region.srcSubresource.baseArrayLayer = src_iview->base_layer;
890
region.srcSubresource.layerCount = layer_count;
891
892
radv_decompress_resolve_src(cmd_buffer, src_image, src_att.layout, &region);
893
}
894
}
895
896
static struct radv_sample_locations_state *
897
radv_get_resolve_sample_locations(struct radv_cmd_buffer *cmd_buffer)
898
{
899
struct radv_cmd_state *state = &cmd_buffer->state;
900
uint32_t subpass_id = radv_get_subpass_id(cmd_buffer);
901
902
for (uint32_t i = 0; i < state->num_subpass_sample_locs; i++) {
903
if (state->subpass_sample_locs[i].subpass_idx == subpass_id)
904
return &state->subpass_sample_locs[i].sample_location;
905
}
906
907
return NULL;
908
}
909
910
/**
911
* Decompress CMask/FMask before resolving a multisampled source image.
912
*/
913
void
914
radv_decompress_resolve_src(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image,
915
VkImageLayout src_image_layout, const VkImageResolve2KHR *region)
916
{
917
const uint32_t src_base_layer =
918
radv_meta_get_iview_layer(src_image, &region->srcSubresource, &region->srcOffset);
919
920
VkImageMemoryBarrier barrier = {0};
921
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
922
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
923
barrier.oldLayout = src_image_layout;
924
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
925
barrier.image = radv_image_to_handle(src_image);
926
barrier.subresourceRange = (VkImageSubresourceRange){
927
.aspectMask = region->srcSubresource.aspectMask,
928
.baseMipLevel = region->srcSubresource.mipLevel,
929
.levelCount = 1,
930
.baseArrayLayer = src_base_layer,
931
.layerCount = region->srcSubresource.layerCount,
932
};
933
934
if (src_image->flags & VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT) {
935
/* If the depth/stencil image uses different sample
936
* locations, we need them during HTILE decompressions.
937
*/
938
struct radv_sample_locations_state *sample_locs =
939
radv_get_resolve_sample_locations(cmd_buffer);
940
941
barrier.pNext = &(VkSampleLocationsInfoEXT){
942
.sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT,
943
.sampleLocationsPerPixel = sample_locs->per_pixel,
944
.sampleLocationGridSize = sample_locs->grid_size,
945
.sampleLocationsCount = sample_locs->count,
946
.pSampleLocations = sample_locs->locations,
947
};
948
}
949
950
radv_CmdPipelineBarrier(radv_cmd_buffer_to_handle(cmd_buffer), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
951
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, false, 0, NULL, 0, NULL, 1,
952
&barrier);
953
}
954
955