Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/amd/vulkan/radv_meta_decompress.c
7237 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 "radv_meta.h"
28
#include "radv_private.h"
29
#include "sid.h"
30
31
enum radv_depth_op {
32
DEPTH_DECOMPRESS,
33
DEPTH_RESUMMARIZE,
34
};
35
36
static VkResult
37
create_pass(struct radv_device *device, uint32_t samples, VkRenderPass *pass)
38
{
39
VkResult result;
40
VkDevice device_h = radv_device_to_handle(device);
41
const VkAllocationCallbacks *alloc = &device->meta_state.alloc;
42
VkAttachmentDescription2 attachment;
43
44
attachment.sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2;
45
attachment.pNext = NULL;
46
attachment.flags = 0;
47
attachment.format = VK_FORMAT_D32_SFLOAT_S8_UINT;
48
attachment.samples = samples;
49
attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
50
attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
51
attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
52
attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
53
attachment.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
54
attachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
55
56
result = radv_CreateRenderPass2(
57
device_h,
58
&(VkRenderPassCreateInfo2){
59
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,
60
.attachmentCount = 1,
61
.pAttachments = &attachment,
62
.subpassCount = 1,
63
.pSubpasses =
64
&(VkSubpassDescription2){
65
.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,
66
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
67
.inputAttachmentCount = 0,
68
.colorAttachmentCount = 0,
69
.pColorAttachments = NULL,
70
.pResolveAttachments = NULL,
71
.pDepthStencilAttachment =
72
&(VkAttachmentReference2){
73
.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,
74
.attachment = 0,
75
.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
76
},
77
.preserveAttachmentCount = 0,
78
.pPreserveAttachments = NULL,
79
},
80
.dependencyCount = 2,
81
.pDependencies =
82
(VkSubpassDependency2[]){{.sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2,
83
.srcSubpass = VK_SUBPASS_EXTERNAL,
84
.dstSubpass = 0,
85
.srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
86
.dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
87
.srcAccessMask = 0,
88
.dstAccessMask = 0,
89
.dependencyFlags = 0},
90
{.sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2,
91
.srcSubpass = 0,
92
.dstSubpass = VK_SUBPASS_EXTERNAL,
93
.srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
94
.dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
95
.srcAccessMask = 0,
96
.dstAccessMask = 0,
97
.dependencyFlags = 0}},
98
},
99
alloc, pass);
100
101
return result;
102
}
103
104
static VkResult
105
create_pipeline_layout(struct radv_device *device, VkPipelineLayout *layout)
106
{
107
VkPipelineLayoutCreateInfo pl_create_info = {
108
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
109
.setLayoutCount = 0,
110
.pSetLayouts = NULL,
111
.pushConstantRangeCount = 0,
112
.pPushConstantRanges = NULL,
113
};
114
115
return radv_CreatePipelineLayout(radv_device_to_handle(device), &pl_create_info,
116
&device->meta_state.alloc, layout);
117
}
118
119
static VkResult
120
create_pipeline(struct radv_device *device, uint32_t samples, VkRenderPass pass,
121
VkPipelineLayout layout, enum radv_depth_op op, VkPipeline *pipeline)
122
{
123
VkResult result;
124
VkDevice device_h = radv_device_to_handle(device);
125
126
mtx_lock(&device->meta_state.mtx);
127
if (*pipeline) {
128
mtx_unlock(&device->meta_state.mtx);
129
return VK_SUCCESS;
130
}
131
132
nir_shader *vs_module = radv_meta_build_nir_vs_generate_vertices();
133
nir_shader *fs_module = radv_meta_build_nir_fs_noop();
134
135
if (!vs_module || !fs_module) {
136
/* XXX: Need more accurate error */
137
result = VK_ERROR_OUT_OF_HOST_MEMORY;
138
goto cleanup;
139
}
140
141
const VkPipelineSampleLocationsStateCreateInfoEXT sample_locs_create_info = {
142
.sType = VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT,
143
.sampleLocationsEnable = false,
144
};
145
146
const VkGraphicsPipelineCreateInfo pipeline_create_info = {
147
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
148
.stageCount = 2,
149
.pStages =
150
(VkPipelineShaderStageCreateInfo[]){
151
{
152
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
153
.stage = VK_SHADER_STAGE_VERTEX_BIT,
154
.module = vk_shader_module_handle_from_nir(vs_module),
155
.pName = "main",
156
},
157
{
158
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
159
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
160
.module = vk_shader_module_handle_from_nir(fs_module),
161
.pName = "main",
162
},
163
},
164
.pVertexInputState =
165
&(VkPipelineVertexInputStateCreateInfo){
166
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
167
.vertexBindingDescriptionCount = 0,
168
.vertexAttributeDescriptionCount = 0,
169
},
170
.pInputAssemblyState =
171
&(VkPipelineInputAssemblyStateCreateInfo){
172
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
173
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
174
.primitiveRestartEnable = false,
175
},
176
.pViewportState =
177
&(VkPipelineViewportStateCreateInfo){
178
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
179
.viewportCount = 1,
180
.scissorCount = 1,
181
},
182
.pRasterizationState =
183
&(VkPipelineRasterizationStateCreateInfo){
184
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
185
.depthClampEnable = false,
186
.rasterizerDiscardEnable = false,
187
.polygonMode = VK_POLYGON_MODE_FILL,
188
.cullMode = VK_CULL_MODE_NONE,
189
.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
190
},
191
.pMultisampleState =
192
&(VkPipelineMultisampleStateCreateInfo){
193
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
194
.pNext = &sample_locs_create_info,
195
.rasterizationSamples = samples,
196
.sampleShadingEnable = false,
197
.pSampleMask = NULL,
198
.alphaToCoverageEnable = false,
199
.alphaToOneEnable = false,
200
},
201
.pColorBlendState =
202
&(VkPipelineColorBlendStateCreateInfo){
203
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
204
.logicOpEnable = false,
205
.attachmentCount = 0,
206
.pAttachments = NULL,
207
},
208
.pDepthStencilState =
209
&(VkPipelineDepthStencilStateCreateInfo){
210
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
211
.depthTestEnable = false,
212
.depthWriteEnable = false,
213
.depthBoundsTestEnable = false,
214
.stencilTestEnable = false,
215
},
216
.pDynamicState =
217
&(VkPipelineDynamicStateCreateInfo){
218
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
219
.dynamicStateCount = 3,
220
.pDynamicStates =
221
(VkDynamicState[]){
222
VK_DYNAMIC_STATE_VIEWPORT,
223
VK_DYNAMIC_STATE_SCISSOR,
224
VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT,
225
},
226
},
227
.layout = layout,
228
.renderPass = pass,
229
.subpass = 0,
230
};
231
232
struct radv_graphics_pipeline_create_info extra = {
233
.use_rectlist = true,
234
.depth_compress_disable = true,
235
.stencil_compress_disable = true,
236
.resummarize_enable = op == DEPTH_RESUMMARIZE,
237
};
238
239
result = radv_graphics_pipeline_create(
240
device_h, radv_pipeline_cache_to_handle(&device->meta_state.cache), &pipeline_create_info,
241
&extra, &device->meta_state.alloc, pipeline);
242
243
cleanup:
244
ralloc_free(fs_module);
245
ralloc_free(vs_module);
246
mtx_unlock(&device->meta_state.mtx);
247
return result;
248
}
249
250
void
251
radv_device_finish_meta_depth_decomp_state(struct radv_device *device)
252
{
253
struct radv_meta_state *state = &device->meta_state;
254
255
for (uint32_t i = 0; i < ARRAY_SIZE(state->depth_decomp); ++i) {
256
radv_DestroyRenderPass(radv_device_to_handle(device), state->depth_decomp[i].pass,
257
&state->alloc);
258
radv_DestroyPipelineLayout(radv_device_to_handle(device), state->depth_decomp[i].p_layout,
259
&state->alloc);
260
261
radv_DestroyPipeline(radv_device_to_handle(device),
262
state->depth_decomp[i].decompress_pipeline, &state->alloc);
263
radv_DestroyPipeline(radv_device_to_handle(device),
264
state->depth_decomp[i].resummarize_pipeline, &state->alloc);
265
}
266
}
267
268
VkResult
269
radv_device_init_meta_depth_decomp_state(struct radv_device *device, bool on_demand)
270
{
271
struct radv_meta_state *state = &device->meta_state;
272
VkResult res = VK_SUCCESS;
273
274
for (uint32_t i = 0; i < ARRAY_SIZE(state->depth_decomp); ++i) {
275
uint32_t samples = 1 << i;
276
277
res = create_pass(device, samples, &state->depth_decomp[i].pass);
278
if (res != VK_SUCCESS)
279
goto fail;
280
281
res = create_pipeline_layout(device, &state->depth_decomp[i].p_layout);
282
if (res != VK_SUCCESS)
283
goto fail;
284
285
if (on_demand)
286
continue;
287
288
res = create_pipeline(device, samples, state->depth_decomp[i].pass,
289
state->depth_decomp[i].p_layout, DEPTH_DECOMPRESS,
290
&state->depth_decomp[i].decompress_pipeline);
291
if (res != VK_SUCCESS)
292
goto fail;
293
294
res = create_pipeline(device, samples, state->depth_decomp[i].pass,
295
state->depth_decomp[i].p_layout, DEPTH_RESUMMARIZE,
296
&state->depth_decomp[i].resummarize_pipeline);
297
if (res != VK_SUCCESS)
298
goto fail;
299
}
300
301
return VK_SUCCESS;
302
303
fail:
304
radv_device_finish_meta_depth_decomp_state(device);
305
return res;
306
}
307
308
static VkPipeline *
309
radv_get_depth_pipeline(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
310
const VkImageSubresourceRange *subresourceRange, enum radv_depth_op op)
311
{
312
struct radv_meta_state *state = &cmd_buffer->device->meta_state;
313
uint32_t samples = image->info.samples;
314
uint32_t samples_log2 = ffs(samples) - 1;
315
VkPipeline *pipeline;
316
317
if (!state->depth_decomp[samples_log2].decompress_pipeline) {
318
VkResult ret;
319
320
ret = create_pipeline(cmd_buffer->device, samples, state->depth_decomp[samples_log2].pass,
321
state->depth_decomp[samples_log2].p_layout, DEPTH_DECOMPRESS,
322
&state->depth_decomp[samples_log2].decompress_pipeline);
323
if (ret != VK_SUCCESS) {
324
cmd_buffer->record_result = ret;
325
return NULL;
326
}
327
328
ret = create_pipeline(cmd_buffer->device, samples, state->depth_decomp[samples_log2].pass,
329
state->depth_decomp[samples_log2].p_layout, DEPTH_RESUMMARIZE,
330
&state->depth_decomp[samples_log2].resummarize_pipeline);
331
if (ret != VK_SUCCESS) {
332
cmd_buffer->record_result = ret;
333
return NULL;
334
}
335
}
336
337
switch (op) {
338
case DEPTH_DECOMPRESS:
339
pipeline = &state->depth_decomp[samples_log2].decompress_pipeline;
340
break;
341
case DEPTH_RESUMMARIZE:
342
pipeline = &state->depth_decomp[samples_log2].resummarize_pipeline;
343
break;
344
default:
345
unreachable("unknown operation");
346
}
347
348
return pipeline;
349
}
350
351
static void
352
radv_process_depth_image_layer(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
353
const VkImageSubresourceRange *range, int level, int layer)
354
{
355
struct radv_device *device = cmd_buffer->device;
356
struct radv_meta_state *state = &device->meta_state;
357
uint32_t samples_log2 = ffs(image->info.samples) - 1;
358
struct radv_image_view iview;
359
uint32_t width, height;
360
361
width = radv_minify(image->info.width, range->baseMipLevel + level);
362
height = radv_minify(image->info.height, range->baseMipLevel + level);
363
364
radv_image_view_init(&iview, device,
365
&(VkImageViewCreateInfo){
366
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
367
.image = radv_image_to_handle(image),
368
.viewType = radv_meta_get_view_type(image),
369
.format = image->vk_format,
370
.subresourceRange =
371
{
372
.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT,
373
.baseMipLevel = range->baseMipLevel + level,
374
.levelCount = 1,
375
.baseArrayLayer = range->baseArrayLayer + layer,
376
.layerCount = 1,
377
},
378
},
379
NULL);
380
381
VkFramebuffer fb_h;
382
radv_CreateFramebuffer(
383
radv_device_to_handle(device),
384
&(VkFramebufferCreateInfo){.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
385
.attachmentCount = 1,
386
.pAttachments = (VkImageView[]){radv_image_view_to_handle(&iview)},
387
.width = width,
388
.height = height,
389
.layers = 1},
390
&cmd_buffer->pool->alloc, &fb_h);
391
392
radv_cmd_buffer_begin_render_pass(cmd_buffer,
393
&(VkRenderPassBeginInfo){
394
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
395
.renderPass = state->depth_decomp[samples_log2].pass,
396
.framebuffer = fb_h,
397
.renderArea = {.offset =
398
{
399
0,
400
0,
401
},
402
.extent =
403
{
404
width,
405
height,
406
}},
407
.clearValueCount = 0,
408
.pClearValues = NULL,
409
},
410
NULL);
411
radv_cmd_buffer_set_subpass(cmd_buffer, &cmd_buffer->state.pass->subpasses[0]);
412
413
radv_CmdDraw(radv_cmd_buffer_to_handle(cmd_buffer), 3, 1, 0, 0);
414
radv_cmd_buffer_end_render_pass(cmd_buffer);
415
416
radv_DestroyFramebuffer(radv_device_to_handle(device), fb_h, &cmd_buffer->pool->alloc);
417
}
418
419
static void
420
radv_process_depth_stencil(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
421
const VkImageSubresourceRange *subresourceRange,
422
struct radv_sample_locations_state *sample_locs, enum radv_depth_op op)
423
{
424
struct radv_meta_saved_state saved_state;
425
VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
426
VkPipeline *pipeline;
427
428
radv_meta_save(
429
&saved_state, cmd_buffer,
430
RADV_META_SAVE_GRAPHICS_PIPELINE | RADV_META_SAVE_SAMPLE_LOCATIONS | RADV_META_SAVE_PASS);
431
432
pipeline = radv_get_depth_pipeline(cmd_buffer, image, subresourceRange, op);
433
434
radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer), VK_PIPELINE_BIND_POINT_GRAPHICS,
435
*pipeline);
436
437
if (sample_locs) {
438
assert(image->flags & VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT);
439
440
/* Set the sample locations specified during explicit or
441
* automatic layout transitions, otherwise the depth decompress
442
* pass uses the default HW locations.
443
*/
444
radv_CmdSetSampleLocationsEXT(cmd_buffer_h,
445
&(VkSampleLocationsInfoEXT){
446
.sampleLocationsPerPixel = sample_locs->per_pixel,
447
.sampleLocationGridSize = sample_locs->grid_size,
448
.sampleLocationsCount = sample_locs->count,
449
.pSampleLocations = sample_locs->locations,
450
});
451
}
452
453
for (uint32_t l = 0; l < radv_get_levelCount(image, subresourceRange); ++l) {
454
455
/* Do not decompress levels without HTILE. */
456
if (!radv_htile_enabled(image, subresourceRange->baseMipLevel + l))
457
continue;
458
459
uint32_t width = radv_minify(image->info.width, subresourceRange->baseMipLevel + l);
460
uint32_t height = radv_minify(image->info.height, subresourceRange->baseMipLevel + l);
461
462
radv_CmdSetViewport(cmd_buffer_h, 0, 1,
463
&(VkViewport){.x = 0,
464
.y = 0,
465
.width = width,
466
.height = height,
467
.minDepth = 0.0f,
468
.maxDepth = 1.0f});
469
470
radv_CmdSetScissor(cmd_buffer_h, 0, 1,
471
&(VkRect2D){
472
.offset = {0, 0},
473
.extent = {width, height},
474
});
475
476
for (uint32_t s = 0; s < radv_get_layerCount(image, subresourceRange); s++) {
477
radv_process_depth_image_layer(cmd_buffer, image, subresourceRange, l, s);
478
}
479
}
480
481
radv_meta_restore(&saved_state, cmd_buffer);
482
}
483
484
void
485
radv_decompress_depth_stencil(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
486
const VkImageSubresourceRange *subresourceRange,
487
struct radv_sample_locations_state *sample_locs)
488
{
489
struct radv_barrier_data barrier = {0};
490
491
barrier.layout_transitions.depth_stencil_expand = 1;
492
radv_describe_layout_transition(cmd_buffer, &barrier);
493
494
assert(cmd_buffer->queue_family_index == RADV_QUEUE_GENERAL);
495
radv_process_depth_stencil(cmd_buffer, image, subresourceRange, sample_locs, DEPTH_DECOMPRESS);
496
}
497
498
void
499
radv_resummarize_depth_stencil(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
500
const VkImageSubresourceRange *subresourceRange,
501
struct radv_sample_locations_state *sample_locs)
502
{
503
struct radv_barrier_data barrier = {0};
504
505
barrier.layout_transitions.depth_stencil_resummarize = 1;
506
radv_describe_layout_transition(cmd_buffer, &barrier);
507
508
assert(cmd_buffer->queue_family_index == RADV_QUEUE_GENERAL);
509
radv_process_depth_stencil(cmd_buffer, image, subresourceRange, sample_locs, DEPTH_RESUMMARIZE);
510
}
511
512