2 * Copyright © 2019 Valve Corporation
3 * Copyright © 2018 Red Hat
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25 #include "radv_meta.h"
26 #include "radv_private.h"
27 #include "vk_format.h"
30 build_fmask_expand_compute_shader(struct radv_device
*device
, int samples
)
34 const struct glsl_type
*type
=
35 glsl_sampler_type(GLSL_SAMPLER_DIM_MS
, false, false,
37 const struct glsl_type
*img_type
=
38 glsl_image_type(GLSL_SAMPLER_DIM_MS
, false,
41 snprintf(name
, 64, "meta_fmask_expand_cs-%d", samples
);
43 nir_builder_init_simple_shader(&b
, NULL
, MESA_SHADER_COMPUTE
, NULL
);
44 b
.shader
->info
.name
= ralloc_strdup(b
.shader
, name
);
45 b
.shader
->info
.cs
.local_size
[0] = 16;
46 b
.shader
->info
.cs
.local_size
[1] = 16;
47 b
.shader
->info
.cs
.local_size
[2] = 1;
49 nir_variable
*input_img
= nir_variable_create(b
.shader
, nir_var_uniform
,
51 input_img
->data
.descriptor_set
= 0;
52 input_img
->data
.binding
= 0;
54 nir_variable
*output_img
= nir_variable_create(b
.shader
, nir_var_uniform
,
56 output_img
->data
.descriptor_set
= 0;
57 output_img
->data
.binding
= 0;
58 output_img
->data
.access
= ACCESS_NON_READABLE
;
60 nir_ssa_def
*invoc_id
= nir_load_local_invocation_id(&b
);
61 nir_ssa_def
*wg_id
= nir_load_work_group_id(&b
, 32);
62 nir_ssa_def
*block_size
= nir_imm_ivec4(&b
,
63 b
.shader
->info
.cs
.local_size
[0],
64 b
.shader
->info
.cs
.local_size
[1],
65 b
.shader
->info
.cs
.local_size
[2], 0);
67 nir_ssa_def
*global_id
= nir_iadd(&b
, nir_imul(&b
, wg_id
, block_size
), invoc_id
);
69 nir_ssa_def
*input_img_deref
= &nir_build_deref_var(&b
, input_img
)->dest
.ssa
;
70 nir_ssa_def
*output_img_deref
= &nir_build_deref_var(&b
, output_img
)->dest
.ssa
;
72 nir_tex_instr
*tex_instr
[8];
73 for (uint32_t i
= 0; i
< samples
; i
++) {
74 tex_instr
[i
] = nir_tex_instr_create(b
.shader
, 3);
76 nir_tex_instr
*tex
= tex_instr
[i
];
77 tex
->sampler_dim
= GLSL_SAMPLER_DIM_MS
;
78 tex
->op
= nir_texop_txf_ms
;
79 tex
->src
[0].src_type
= nir_tex_src_coord
;
80 tex
->src
[0].src
= nir_src_for_ssa(nir_channels(&b
, global_id
, 0x3));
81 tex
->src
[1].src_type
= nir_tex_src_ms_index
;
82 tex
->src
[1].src
= nir_src_for_ssa(nir_imm_int(&b
, i
));
83 tex
->src
[2].src_type
= nir_tex_src_texture_deref
;
84 tex
->src
[2].src
= nir_src_for_ssa(input_img_deref
);
85 tex
->dest_type
= nir_type_float
;
86 tex
->is_array
= false;
87 tex
->coord_components
= 2;
89 nir_ssa_dest_init(&tex
->instr
, &tex
->dest
, 4, 32, "tex");
90 nir_builder_instr_insert(&b
, &tex
->instr
);
93 for (uint32_t i
= 0; i
< samples
; i
++) {
94 nir_ssa_def
*outval
= &tex_instr
[i
]->dest
.ssa
;
96 nir_intrinsic_instr
*store
=
97 nir_intrinsic_instr_create(b
.shader
,
98 nir_intrinsic_image_deref_store
);
99 store
->num_components
= 4;
100 store
->src
[0] = nir_src_for_ssa(output_img_deref
);
101 store
->src
[1] = nir_src_for_ssa(global_id
);
102 store
->src
[2] = nir_src_for_ssa(nir_imm_int(&b
, i
));
103 store
->src
[3] = nir_src_for_ssa(outval
);
104 store
->src
[4] = nir_src_for_ssa(nir_imm_int(&b
, 0));
105 nir_builder_instr_insert(&b
, &store
->instr
);
112 radv_expand_fmask_image_inplace(struct radv_cmd_buffer
*cmd_buffer
,
113 struct radv_image
*image
,
114 const VkImageSubresourceRange
*subresourceRange
)
116 struct radv_device
*device
= cmd_buffer
->device
;
117 struct radv_meta_saved_state saved_state
;
118 const uint32_t samples
= image
->info
.samples
;
119 const uint32_t samples_log2
= ffs(samples
) - 1;
121 radv_meta_save(&saved_state
, cmd_buffer
,
122 RADV_META_SAVE_COMPUTE_PIPELINE
|
123 RADV_META_SAVE_DESCRIPTORS
);
125 VkPipeline pipeline
= device
->meta_state
.fmask_expand
.pipeline
[samples_log2
];
127 radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer
),
128 VK_PIPELINE_BIND_POINT_COMPUTE
, pipeline
);
130 for (unsigned l
= 0; l
< radv_get_layerCount(image
, subresourceRange
); l
++) {
131 struct radv_image_view iview
;
133 radv_image_view_init(&iview
, device
,
134 &(VkImageViewCreateInfo
) {
135 .sType
= VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO
,
136 .image
= radv_image_to_handle(image
),
137 .viewType
= radv_meta_get_view_type(image
),
138 .format
= vk_format_no_srgb(image
->vk_format
),
139 .subresourceRange
= {
140 .aspectMask
= VK_IMAGE_ASPECT_COLOR_BIT
,
143 .baseArrayLayer
= subresourceRange
->baseArrayLayer
+ l
,
148 radv_meta_push_descriptor_set(cmd_buffer
,
149 VK_PIPELINE_BIND_POINT_COMPUTE
,
150 cmd_buffer
->device
->meta_state
.fmask_expand
.p_layout
,
152 1, /* descriptorWriteCount */
153 (VkWriteDescriptorSet
[]) {
155 .sType
= VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET
,
157 .dstArrayElement
= 0,
158 .descriptorCount
= 1,
159 .descriptorType
= VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
,
160 .pImageInfo
= (VkDescriptorImageInfo
[]) {
162 .sampler
= VK_NULL_HANDLE
,
163 .imageView
= radv_image_view_to_handle(&iview
),
164 .imageLayout
= VK_IMAGE_LAYOUT_GENERAL
170 radv_unaligned_dispatch(cmd_buffer
, image
->info
.width
, image
->info
.height
, 1);
173 radv_meta_restore(&saved_state
, cmd_buffer
);
175 cmd_buffer
->state
.flush_bits
|= RADV_CMD_FLAG_CS_PARTIAL_FLUSH
|
176 RADV_CMD_FLAG_INV_L2
;
178 /* Re-initialize FMASK in fully expanded mode. */
179 radv_initialize_fmask(cmd_buffer
, image
, subresourceRange
);
182 void radv_device_finish_meta_fmask_expand_state(struct radv_device
*device
)
184 struct radv_meta_state
*state
= &device
->meta_state
;
186 for (uint32_t i
= 0; i
< MAX_SAMPLES_LOG2
; ++i
) {
187 radv_DestroyPipeline(radv_device_to_handle(device
),
188 state
->fmask_expand
.pipeline
[i
],
191 radv_DestroyPipelineLayout(radv_device_to_handle(device
),
192 state
->fmask_expand
.p_layout
,
195 radv_DestroyDescriptorSetLayout(radv_device_to_handle(device
),
196 state
->fmask_expand
.ds_layout
,
201 create_fmask_expand_pipeline(struct radv_device
*device
,
203 VkPipeline
*pipeline
)
205 struct radv_meta_state
*state
= &device
->meta_state
;
206 struct radv_shader_module cs
= { .nir
= NULL
};
209 cs
.nir
= build_fmask_expand_compute_shader(device
, samples
);
211 VkPipelineShaderStageCreateInfo pipeline_shader_stage
= {
212 .sType
= VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO
,
213 .stage
= VK_SHADER_STAGE_COMPUTE_BIT
,
214 .module
= radv_shader_module_to_handle(&cs
),
216 .pSpecializationInfo
= NULL
,
219 VkComputePipelineCreateInfo vk_pipeline_info
= {
220 .sType
= VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO
,
221 .stage
= pipeline_shader_stage
,
223 .layout
= state
->fmask_expand
.p_layout
,
226 result
= radv_CreateComputePipelines(radv_device_to_handle(device
),
227 radv_pipeline_cache_to_handle(&state
->cache
),
228 1, &vk_pipeline_info
, NULL
,
236 radv_device_init_meta_fmask_expand_state(struct radv_device
*device
)
238 struct radv_meta_state
*state
= &device
->meta_state
;
241 VkDescriptorSetLayoutCreateInfo ds_create_info
= {
242 .sType
= VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO
,
243 .flags
= VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR
,
245 .pBindings
= (VkDescriptorSetLayoutBinding
[]) {
248 .descriptorType
= VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
,
249 .descriptorCount
= 1,
250 .stageFlags
= VK_SHADER_STAGE_COMPUTE_BIT
,
251 .pImmutableSamplers
= NULL
256 result
= radv_CreateDescriptorSetLayout(radv_device_to_handle(device
),
257 &ds_create_info
, &state
->alloc
,
258 &state
->fmask_expand
.ds_layout
);
259 if (result
!= VK_SUCCESS
)
262 VkPipelineLayoutCreateInfo color_create_info
= {
263 .sType
= VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO
,
265 .pSetLayouts
= &state
->fmask_expand
.ds_layout
,
266 .pushConstantRangeCount
= 0,
267 .pPushConstantRanges
= NULL
,
270 result
= radv_CreatePipelineLayout(radv_device_to_handle(device
),
271 &color_create_info
, &state
->alloc
,
272 &state
->fmask_expand
.p_layout
);
273 if (result
!= VK_SUCCESS
)
276 for (uint32_t i
= 0; i
< MAX_SAMPLES_LOG2
; i
++) {
277 uint32_t samples
= 1 << i
;
278 result
= create_fmask_expand_pipeline(device
, samples
,
279 &state
->fmask_expand
.pipeline
[i
]);
280 if (result
!= VK_SUCCESS
)
286 radv_device_finish_meta_fmask_expand_state(device
);