2 * Copyright © 2020 Mike Blumenkrantz
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:
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
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
24 * Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
28 #include "nir_builder.h"
31 * This pass splits gl_FragColor into gl_FragData[0-7] for drivers which handle
32 * the former but not the latter, e.g., zink.
36 If a fragment shader writes to "gl_FragColor", DrawBuffersIndexedEXT
37 specifies a set of draw buffers into which the color written to
38 "gl_FragColor" is written. If a fragment shader writes to
39 gl_FragData, DrawBuffersIndexedEXT specifies a set of draw buffers
40 into which each of the multiple output colors defined by these
41 variables are separately written. If a fragment shader writes to
42 neither gl_FragColor nor gl_FragData, the values of the fragment
43 colors following shader execution are undefined, and may differ
44 for each fragment color.
46 - EXT_multiview_draw_buffers
51 lower_fragcolor_instr(nir_intrinsic_instr
*instr
, nir_builder
*b
)
54 if (instr
->intrinsic
!= nir_intrinsic_store_deref
)
57 out
= nir_deref_instr_get_variable(nir_src_as_deref(instr
->src
[0]));
58 if (out
->data
.location
!= FRAG_RESULT_COLOR
|| out
->data
.mode
!= nir_var_shader_out
)
60 b
->cursor
= nir_after_instr(&instr
->instr
);
62 nir_ssa_def
*frag_color
= nir_load_var(b
, out
);
63 ralloc_free(out
->name
);
64 out
->name
= ralloc_strdup(out
, "gl_FragData[0]");
66 /* translate gl_FragColor -> gl_FragData since this is already handled */
67 out
->data
.location
= FRAG_RESULT_DATA0
;
68 nir_component_mask_t writemask
= nir_intrinsic_write_mask(instr
);
70 for (unsigned i
= 1; i
< 8; i
++) {
72 snprintf(name
, sizeof(name
), "gl_FragData[%u]", i
);
73 nir_variable
*out_color
= nir_variable_create(b
->shader
, nir_var_shader_out
,
76 out_color
->data
.location
= FRAG_RESULT_DATA0
+ i
;
77 out_color
->data
.driver_location
= i
;
78 out_color
->data
.index
= out
->data
.index
;
79 nir_store_var(b
, out_color
, frag_color
, writemask
);
85 nir_lower_fragcolor(nir_shader
*shader
)
87 bool progress
= false;
89 if (shader
->info
.stage
!= MESA_SHADER_FRAGMENT
)
92 nir_foreach_function(function
, shader
) {
95 nir_builder_init(&builder
, function
->impl
);
96 nir_foreach_block(block
, function
->impl
) {
97 nir_foreach_instr_safe(instr
, block
) {
98 if (instr
->type
== nir_instr_type_intrinsic
)
99 progress
|= lower_fragcolor_instr(nir_instr_as_intrinsic(instr
),
104 nir_metadata_preserve(function
->impl
, nir_metadata_block_index
| nir_metadata_dominance
);