3 * Copyright (c) 2018 Collabora LTD
5 * Author: Gert Wollny <gert.wollny@collabora.com>
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * on the rights to use, copy, modify, merge, publish, distribute, sub
11 * license, and/or sell copies of the Software, and to permit persons to whom
12 * the Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
27 #include "sfn_shaderio.h"
28 #include "sfn_debug.h"
29 #include "tgsi/tgsi_from_mesa.h"
36 using std::priority_queue
;
45 ShaderInput::ShaderInput(tgsi_semantic name
):
48 m_uses_interpolate_at_centroid(false)
52 ShaderInput::~ShaderInput()
56 void ShaderInput::set_lds_pos(UNUSED
int lds_pos
)
60 int ShaderInput::ij_index() const
65 bool ShaderInput::interpolate() const
70 int ShaderInput::lds_pos() const
75 bool ShaderInput::is_varying() const
80 void ShaderInput::set_uses_interpolate_at_centroid()
82 m_uses_interpolate_at_centroid
= true;
85 void ShaderInput::set_ioinfo(r600_shader_io
& io
, int translated_ij_index
) const
89 io
.ij_index
= translated_ij_index
;
90 io
.lds_pos
= lds_pos();
91 io
.uses_interpolate_at_centroid
= m_uses_interpolate_at_centroid
;
93 set_specific_ioinfo(io
);
96 void ShaderInput::set_specific_ioinfo(UNUSED r600_shader_io
& io
) const
100 ShaderInputSystemValue::ShaderInputSystemValue(tgsi_semantic name
, int gpr
):
106 void ShaderInputSystemValue::set_specific_ioinfo(r600_shader_io
& io
) const
112 ShaderInputVarying::ShaderInputVarying(tgsi_semantic _name
, int sid
, nir_variable
*input
):
114 m_driver_location(input
->data
.driver_location
),
115 m_location_frac(input
->data
.location_frac
),
118 m_mask((1 << input
->type
->components()) - 1)
120 sfn_log
<< SfnLog::io
<< __func__
123 << " op: " << input
->data
.interpolation
;
127 enum glsl_base_type base_type
=
128 glsl_get_base_type(glsl_without_array(input
->type
));
130 switch (input
->data
.interpolation
) {
131 case INTERP_MODE_NONE
:
132 if (glsl_base_type_is_integer(base_type
)) {
133 m_interpolate
= TGSI_INTERPOLATE_CONSTANT
;
137 if (name() == TGSI_SEMANTIC_COLOR
) {
138 m_interpolate
= TGSI_INTERPOLATE_COLOR
;
144 case INTERP_MODE_SMOOTH
:
145 assert(!glsl_base_type_is_integer(base_type
));
147 m_interpolate
= TGSI_INTERPOLATE_PERSPECTIVE
;
151 case INTERP_MODE_NOPERSPECTIVE
:
152 assert(!glsl_base_type_is_integer(base_type
));
154 m_interpolate
= TGSI_INTERPOLATE_LINEAR
;
158 case INTERP_MODE_FLAT
:
159 m_interpolate
= TGSI_INTERPOLATE_CONSTANT
;
163 if (input
->data
.sample
) {
164 m_interpolate_loc
= TGSI_INTERPOLATE_LOC_SAMPLE
;
165 } else if (input
->data
.centroid
) {
166 m_interpolate_loc
= TGSI_INTERPOLATE_LOC_CENTROID
;
169 m_interpolate_loc
= TGSI_INTERPOLATE_LOC_CENTER
;
172 sfn_log
<< SfnLog::io
173 << " -> IP:" << m_interpolate
174 << " IJ:" << m_ij_index
178 bool ShaderInputVarying::is_varying() const
183 void ShaderInputVarying::update_mask(int additional_comps
)
185 m_mask
|= additional_comps
;
188 void ShaderInputVarying::evaluate_spi_sid()
191 case TGSI_SEMANTIC_POSITION
:
192 case TGSI_SEMANTIC_PSIZE
:
193 case TGSI_SEMANTIC_EDGEFLAG
:
194 case TGSI_SEMANTIC_FACE
:
195 case TGSI_SEMANTIC_SAMPLEMASK
:
196 assert(0 && "System value used as varying");
198 case TGSI_SEMANTIC_GENERIC
:
199 m_spi_sid
= m_sid
+ 1;
202 /* For non-generic params - pack name and sid into 8 bits */
203 m_spi_sid
= (0x80 | (name() << 3) | m_sid
) + 1;
207 ShaderInputVarying::ShaderInputVarying(tgsi_semantic name
,
208 const ShaderInputVarying
& orig
, size_t location
):
210 m_driver_location(location
),
211 m_location_frac(orig
.location_frac()),
214 m_spi_sid(orig
.m_spi_sid
),
215 m_interpolate(orig
.m_interpolate
),
216 m_interpolate_loc(orig
.m_interpolate_loc
),
217 m_ij_index(orig
.m_ij_index
),
223 bool ShaderInputVarying::interpolate() const
225 return m_interpolate
> 0;
228 int ShaderInputVarying::ij_index() const
233 void ShaderInputVarying::set_lds_pos(int lds_pos
)
238 int ShaderInputVarying::lds_pos() const
243 void ShaderInputVarying::set_specific_ioinfo(r600_shader_io
& io
) const
245 io
.interpolate
= m_interpolate
;
246 io
.interpolate_location
= m_interpolate_loc
;
248 io
.spi_sid
= m_spi_sid
;
249 set_color_ioinfo(io
);
252 void ShaderInputVarying::set_color_ioinfo(UNUSED r600_shader_io
& io
) const
254 sfn_log
<< SfnLog::io
<< __func__
<< " Don't set color_ioinfo\n";
257 ShaderInputColor::ShaderInputColor(tgsi_semantic name
, int sid
, nir_variable
*input
):
258 ShaderInputVarying(name
, sid
, input
),
259 m_back_color_input_idx(0)
261 sfn_log
<< SfnLog::io
<< __func__
<< "name << " << name
<< " sid << " << sid
<< "\n";
264 void ShaderInputColor::set_back_color(unsigned back_color_input_idx
)
266 sfn_log
<< SfnLog::io
<< "Set back color index " << back_color_input_idx
<< "\n";
267 m_back_color_input_idx
= back_color_input_idx
;
270 void ShaderInputColor::set_color_ioinfo(r600_shader_io
& io
) const
272 sfn_log
<< SfnLog::io
<< __func__
<< " set color_ioinfo " << m_back_color_input_idx
<< "\n";
273 io
.back_color_input
= m_back_color_input_idx
;
276 size_t ShaderIO::add_input(ShaderInput
*input
)
278 m_inputs
.push_back(PShaderInput(input
));
279 return m_inputs
.size() - 1;
282 PShaderInput
ShaderIO::find_varying(tgsi_semantic name
, int sid
, int frac
)
284 for (auto& a
: m_inputs
) {
285 if (a
->name() == name
) {
286 assert(a
->is_varying());
287 auto& v
= static_cast<ShaderInputVarying
&>(*a
);
288 if (v
.sid() == sid
&& (v
.location_frac() == frac
))
295 struct VaryingShaderIOLess
{
296 bool operator () (PShaderInput lhs
, PShaderInput rhs
) const
298 const ShaderInputVarying
& l
= static_cast<ShaderInputVarying
&>(*lhs
);
299 const ShaderInputVarying
& r
= static_cast<ShaderInputVarying
&>(*rhs
);
300 return l
.location() > r
.location();
304 void ShaderIO::sort_varying_inputs()
306 priority_queue
<PShaderInput
, vector
<PShaderInput
>, VaryingShaderIOLess
> q
;
310 for (auto i
= 0u; i
< m_inputs
.size(); ++i
) {
311 if (m_inputs
[i
]->is_varying()) {
317 auto next_index
= idx
.begin();
321 m_inputs
[*next_index
++] = si
;
325 void ShaderIO::update_lds_pos()
328 m_ldspos
.resize(m_inputs
.size());
329 for (auto& i
: m_inputs
) {
330 if (!i
->is_varying())
333 auto& v
= static_cast<ShaderInputVarying
&>(*i
);
334 /* There are shaders that miss an input ...*/
335 if (m_ldspos
.size() <= static_cast<unsigned>(v
.location()))
336 m_ldspos
.resize(v
.location() + 1);
339 std::fill(m_ldspos
.begin(), m_ldspos
.end(), -1);
340 for (auto& i
: m_inputs
) {
341 if (!i
->is_varying())
344 auto& v
= static_cast<ShaderInputVarying
&>(*i
);
345 if (m_ldspos
[v
.location()] < 0) {
347 m_ldspos
[v
.location()] = m_lds_pos
;
349 v
.set_lds_pos(m_lds_pos
);
354 std::vector
<PShaderInput
> &ShaderIO::inputs()
359 ShaderInput
& ShaderIO::input(size_t k
)
361 assert(k
< m_inputs
.size());
365 ShaderInput
& ShaderIO::input(size_t driver_loc
, int frac
)
367 for (auto& i
: m_inputs
) {
368 if (!i
->is_varying())
371 auto& v
= static_cast<ShaderInputVarying
&>(*i
);
372 if (v
.location() == driver_loc
&& v
.location_frac() == frac
)
375 return input(driver_loc
);
378 void ShaderIO::set_two_sided()