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"
29 build_fmask_expand_compute_shader(struct radv_device
*device
, int samples
)
33 const struct glsl_type
*input_img_type
=
34 glsl_sampler_type(GLSL_SAMPLER_DIM_MS
, false, false,
36 const struct glsl_type
*output_img_type
=
37 glsl_sampler_type(GLSL_SAMPLER_DIM_MS
, false, false,
40 snprintf(name
, 64, "meta_fmask_expand_cs-%d", samples
);
42 nir_builder_init_simple_shader(&b
, NULL
, MESA_SHADER_COMPUTE
, NULL
);
43 b
.shader
->info
.name
= ralloc_strdup(b
.shader
, name
);
44 b
.shader
->info
.cs
.local_size
[0] = 16;
45 b
.shader
->info
.cs
.local_size
[1] = 16;
46 b
.shader
->info
.cs
.local_size
[2] = 1;
48 nir_variable
*input_img
= nir_variable_create(b
.shader
, nir_var_uniform
,
49 input_img_type
, "s_tex");
50 input_img
->data
.descriptor_set
= 0;
51 input_img
->data
.binding
= 0;
53 nir_variable
*output_img
= nir_variable_create(b
.shader
, nir_var_uniform
,
54 output_img_type
, "out_img");
55 output_img
->data
.descriptor_set
= 0;
56 output_img
->data
.binding
= 1;
58 nir_ssa_def
*invoc_id
= nir_load_local_invocation_id(&b
);
59 nir_ssa_def
*wg_id
= nir_load_work_group_id(&b
);
60 nir_ssa_def
*block_size
= nir_imm_ivec4(&b
,
61 b
.shader
->info
.cs
.local_size
[0],
62 b
.shader
->info
.cs
.local_size
[1],
63 b
.shader
->info
.cs
.local_size
[2], 0);
65 nir_ssa_def
*global_id
= nir_iadd(&b
, nir_imul(&b
, wg_id
, block_size
), invoc_id
);
67 nir_ssa_def
*input_img_deref
= &nir_build_deref_var(&b
, input_img
)->dest
.ssa
;
68 nir_ssa_def
*output_img_deref
= &nir_build_deref_var(&b
, output_img
)->dest
.ssa
;
70 nir_tex_instr
*tex_instr
[8];
71 for (uint32_t i
= 0; i
< samples
; i
++) {
72 tex_instr
[i
] = nir_tex_instr_create(b
.shader
, 3);
74 nir_tex_instr
*tex
= tex_instr
[i
];
75 tex
->sampler_dim
= GLSL_SAMPLER_DIM_MS
;
76 tex
->op
= nir_texop_txf_ms
;
77 tex
->src
[0].src_type
= nir_tex_src_coord
;
78 tex
->src
[0].src
= nir_src_for_ssa(nir_channels(&b
, global_id
, 0x3));
79 tex
->src
[1].src_type
= nir_tex_src_ms_index
;
80 tex
->src
[1].src
= nir_src_for_ssa(nir_imm_int(&b
, i
));
81 tex
->src
[2].src_type
= nir_tex_src_texture_deref
;
82 tex
->src
[2].src
= nir_src_for_ssa(input_img_deref
);
83 tex
->dest_type
= nir_type_float
;
84 tex
->is_array
= false;
85 tex
->coord_components
= 2;
87 nir_ssa_dest_init(&tex
->instr
, &tex
->dest
, 4, 32, "tex");
88 nir_builder_instr_insert(&b
, &tex
->instr
);
91 for (uint32_t i
= 0; i
< samples
; i
++) {
92 nir_ssa_def
*outval
= &tex_instr
[i
]->dest
.ssa
;
94 nir_intrinsic_instr
*store
=
95 nir_intrinsic_instr_create(b
.shader
,
96 nir_intrinsic_image_deref_store
);
97 store
->num_components
= 4;
98 store
->src
[0] = nir_src_for_ssa(output_img_deref
);
99 store
->src
[1] = nir_src_for_ssa(global_id
);
100 store
->src
[2] = nir_src_for_ssa(nir_imm_int(&b
, i
));
101 store
->src
[3] = nir_src_for_ssa(outval
);
102 nir_builder_instr_insert(&b
, &store
->instr
);
109 radv_expand_fmask_image_inplace(struct radv_cmd_buffer
*cmd_buffer
,
110 struct radv_image
*image
,
111 const VkImageSubresourceRange
*subresourceRange
)
113 struct radv_device
*device
= cmd_buffer
->device
;
114 struct radv_meta_saved_state saved_state
;
115 const uint32_t samples
= image
->info
.samples
;
116 const uint32_t samples_log2
= ffs(samples
) - 1;
118 radv_meta_save(&saved_state
, cmd_buffer
,
119 RADV_META_SAVE_COMPUTE_PIPELINE
|
120 RADV_META_SAVE_DESCRIPTORS
);
122 VkPipeline pipeline
= device
->meta_state
.fmask_expand
.pipeline
[samples_log2
];
124 radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer
),
125 VK_PIPELINE_BIND_POINT_COMPUTE
, pipeline
);
127 for (unsigned l
= 0; l
< subresourceRange
->layerCount
; l
++) {
128 struct radv_image_view iview
;
130 radv_image_view_init(&iview
, device
,
131 &(VkImageViewCreateInfo
) {
132 .sType
= VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO
,
133 .image
= radv_image_to_handle(image
),
134 .viewType
= radv_meta_get_view_type(image
),
135 .format
= image
->vk_format
,
136 .subresourceRange
= {
137 .aspectMask
= VK_IMAGE_ASPECT_COLOR_BIT
,
140 .baseArrayLayer
= subresourceRange
->baseArrayLayer
+ l
,
145 radv_meta_push_descriptor_set(cmd_buffer
,
146 VK_PIPELINE_BIND_POINT_COMPUTE
,
147 cmd_buffer
->device
->meta_state
.fmask_expand
.p_layout
,
149 2, /* descriptorWriteCount */
150 (VkWriteDescriptorSet
[]) {
152 .sType
= VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET
,
154 .dstArrayElement
= 0,
155 .descriptorCount
= 1,
156 .descriptorType
= VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
,
157 .pImageInfo
= (VkDescriptorImageInfo
[]) {
159 .sampler
= VK_NULL_HANDLE
,
160 .imageView
= radv_image_view_to_handle(&iview
),
161 .imageLayout
= VK_IMAGE_LAYOUT_GENERAL
166 .sType
= VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET
,
168 .dstArrayElement
= 0,
169 .descriptorCount
= 1,
170 .descriptorType
= VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
,
171 .pImageInfo
= (VkDescriptorImageInfo
[]) {
173 .sampler
= VK_NULL_HANDLE
,
174 .imageView
= radv_image_view_to_handle(&iview
),
175 .imageLayout
= VK_IMAGE_LAYOUT_GENERAL
181 radv_unaligned_dispatch(cmd_buffer
, image
->info
.width
, image
->info
.height
, 1);
184 radv_meta_restore(&saved_state
, cmd_buffer
);
186 cmd_buffer
->state
.flush_bits
|= RADV_CMD_FLAG_CS_PARTIAL_FLUSH
|
187 RADV_CMD_FLAG_INV_GLOBAL_L2
;
189 /* Re-initialize FMASK in fully expanded mode. */
190 radv_initialize_fmask(cmd_buffer
, image
);
193 void radv_device_finish_meta_fmask_expand_state(struct radv_device
*device
)
195 struct radv_meta_state
*state
= &device
->meta_state
;
197 for (uint32_t i
= 0; i
< MAX_SAMPLES_LOG2
; ++i
) {
198 radv_DestroyPipeline(radv_device_to_handle(device
),
199 state
->fmask_expand
.pipeline
[i
],
202 radv_DestroyPipelineLayout(radv_device_to_handle(device
),
203 state
->fmask_expand
.p_layout
,
206 radv_DestroyDescriptorSetLayout(radv_device_to_handle(device
),
207 state
->fmask_expand
.ds_layout
,
212 create_fmask_expand_pipeline(struct radv_device
*device
,
214 VkPipeline
*pipeline
)
216 struct radv_meta_state
*state
= &device
->meta_state
;
217 struct radv_shader_module cs
= { .nir
= NULL
};
220 cs
.nir
= build_fmask_expand_compute_shader(device
, samples
);
222 VkPipelineShaderStageCreateInfo pipeline_shader_stage
= {
223 .sType
= VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO
,
224 .stage
= VK_SHADER_STAGE_COMPUTE_BIT
,
225 .module
= radv_shader_module_to_handle(&cs
),
227 .pSpecializationInfo
= NULL
,
230 VkComputePipelineCreateInfo vk_pipeline_info
= {
231 .sType
= VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO
,
232 .stage
= pipeline_shader_stage
,
234 .layout
= state
->fmask_expand
.p_layout
,
237 result
= radv_CreateComputePipelines(radv_device_to_handle(device
),
238 radv_pipeline_cache_to_handle(&state
->cache
),
239 1, &vk_pipeline_info
, NULL
,
247 radv_device_init_meta_fmask_expand_state(struct radv_device
*device
)
249 struct radv_meta_state
*state
= &device
->meta_state
;
252 VkDescriptorSetLayoutCreateInfo ds_create_info
= {
253 .sType
= VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO
,
254 .flags
= VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR
,
256 .pBindings
= (VkDescriptorSetLayoutBinding
[]) {
259 .descriptorType
= VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
,
260 .descriptorCount
= 1,
261 .stageFlags
= VK_SHADER_STAGE_COMPUTE_BIT
,
262 .pImmutableSamplers
= NULL
266 .descriptorType
= VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
,
267 .descriptorCount
= 1,
268 .stageFlags
= VK_SHADER_STAGE_COMPUTE_BIT
,
269 .pImmutableSamplers
= NULL
274 result
= radv_CreateDescriptorSetLayout(radv_device_to_handle(device
),
275 &ds_create_info
, &state
->alloc
,
276 &state
->fmask_expand
.ds_layout
);
277 if (result
!= VK_SUCCESS
)
280 VkPipelineLayoutCreateInfo color_create_info
= {
281 .sType
= VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO
,
283 .pSetLayouts
= &state
->fmask_expand
.ds_layout
,
284 .pushConstantRangeCount
= 0,
285 .pPushConstantRanges
= NULL
,
288 result
= radv_CreatePipelineLayout(radv_device_to_handle(device
),
289 &color_create_info
, &state
->alloc
,
290 &state
->fmask_expand
.p_layout
);
291 if (result
!= VK_SUCCESS
)
294 for (uint32_t i
= 0; i
< MAX_SAMPLES_LOG2
; i
++) {
295 uint32_t samples
= 1 << i
;
296 result
= create_fmask_expand_pipeline(device
, samples
,
297 &state
->fmask_expand
.pipeline
[i
]);
298 if (result
!= VK_SUCCESS
)
304 radv_device_finish_meta_fmask_expand_state(device
);