• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- mesa-c++  -*-
2  *
3  * Copyright (c) 2022 Collabora LTD
4  *
5  * Author: Gert Wollny <gert.wollny@collabora.com>
6  *
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:
13  *
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
16  * Software.
17  *
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.
25  */
26 
27 #include "sfn_shader_tess.h"
28 
29 #include "sfn_instr_export.h"
30 #include "sfn_shader_vs.h"
31 
32 #include <sstream>
33 
34 namespace r600 {
35 
36 using std::string;
37 
TCSShader(const r600_shader_key & key)38 TCSShader::TCSShader(const r600_shader_key& key):
39     Shader("TCS", key.tcs.first_atomic_counter),
40     m_tcs_prim_mode(key.tcs.prim_mode)
41 {
42 }
43 
44 bool
do_scan_instruction(nir_instr * instr)45 TCSShader::do_scan_instruction(nir_instr *instr)
46 {
47    if (instr->type != nir_instr_type_intrinsic)
48       return false;
49 
50    nir_intrinsic_instr *ii = nir_instr_as_intrinsic(instr);
51 
52    switch (ii->intrinsic) {
53    case nir_intrinsic_load_primitive_id:
54       m_sv_values.set(es_primitive_id);
55       break;
56    case nir_intrinsic_load_invocation_id:
57       m_sv_values.set(es_invocation_id);
58       break;
59    case nir_intrinsic_load_tcs_rel_patch_id_r600:
60       m_sv_values.set(es_rel_patch_id);
61       break;
62    case nir_intrinsic_load_tcs_tess_factor_base_r600:
63       m_sv_values.set(es_tess_factor_base);
64       break;
65    default:
66       return false;
67       ;
68    }
69    return true;
70 }
71 
72 int
do_allocate_reserved_registers()73 TCSShader::do_allocate_reserved_registers()
74 {
75    if (m_sv_values.test(es_primitive_id)) {
76       m_primitive_id = value_factory().allocate_pinned_register(0, 0);
77    }
78 
79    if (m_sv_values.test(es_invocation_id)) {
80       m_invocation_id = value_factory().allocate_pinned_register(0, 2);
81    }
82 
83    if (m_sv_values.test(es_rel_patch_id)) {
84       m_rel_patch_id = value_factory().allocate_pinned_register(0, 1);
85    }
86 
87    if (m_sv_values.test(es_tess_factor_base)) {
88       m_tess_factor_base = value_factory().allocate_pinned_register(0, 3);
89    }
90 
91    return value_factory().next_register_index();
92    ;
93 }
94 
95 bool
process_stage_intrinsic(nir_intrinsic_instr * instr)96 TCSShader::process_stage_intrinsic(nir_intrinsic_instr *instr)
97 {
98    switch (instr->intrinsic) {
99    case nir_intrinsic_load_tcs_rel_patch_id_r600:
100       return emit_simple_mov(instr->def, 0, m_rel_patch_id);
101    case nir_intrinsic_load_invocation_id:
102       return emit_simple_mov(instr->def, 0, m_invocation_id);
103    case nir_intrinsic_load_primitive_id:
104       return emit_simple_mov(instr->def, 0, m_primitive_id);
105    case nir_intrinsic_load_tcs_tess_factor_base_r600:
106       return emit_simple_mov(instr->def, 0, m_tess_factor_base);
107    case nir_intrinsic_store_tf_r600:
108       return store_tess_factor(instr);
109    default:
110       return false;
111    }
112 }
113 
114 bool
store_tess_factor(nir_intrinsic_instr * instr)115 TCSShader::store_tess_factor(nir_intrinsic_instr *instr)
116 {
117    auto value0 = value_factory().src_vec4(instr->src[0], pin_group, {0, 1, 7, 7});
118    emit_instruction(new WriteTFInstr(value0));
119    return true;
120 }
121 
122 void
do_get_shader_info(r600_shader * sh_info)123 TCSShader::do_get_shader_info(r600_shader *sh_info)
124 {
125    sh_info->processor_type = PIPE_SHADER_TESS_CTRL;
126    sh_info->tcs_prim_mode = m_tcs_prim_mode;
127 }
128 
129 bool
read_prop(std::istream & is)130 TCSShader::read_prop(std::istream& is)
131 {
132    string value;
133    is >> value;
134 
135    ASSERTED auto splitpos = value.find(':');
136    assert(splitpos != string::npos);
137 
138    std::istringstream ival(value);
139    string name;
140    string val;
141 
142    std::getline(ival, name, ':');
143 
144    if (name == "TCS_PRIM_MODE")
145       ival >> m_tcs_prim_mode;
146    else
147       return false;
148    return true;
149 }
150 
151 void
do_print_properties(std::ostream & os) const152 TCSShader::do_print_properties(std::ostream& os) const
153 {
154    os << "PROP TCS_PRIM_MODE:" << m_tcs_prim_mode << "\n";
155 }
156 
TESShader(const pipe_stream_output_info * so_info,const r600_shader * gs_shader,const r600_shader_key & key)157 TESShader::TESShader(const pipe_stream_output_info *so_info,
158                      const r600_shader *gs_shader,
159                      const r600_shader_key& key):
160     VertexStageShader("TES", key.tes.first_atomic_counter),
161     m_vs_as_gs_a(key.vs.as_gs_a),
162     m_tes_as_es(key.tes.as_es)
163 {
164    if (key.tes.as_es)
165       m_export_processor = new VertexExportForGS(this, gs_shader);
166    else
167       m_export_processor = new VertexExportForFs(this, so_info, key);
168 }
169 
170 bool
do_scan_instruction(nir_instr * instr)171 TESShader::do_scan_instruction(nir_instr *instr)
172 {
173    if (instr->type != nir_instr_type_intrinsic)
174       return false;
175 
176    auto intr = nir_instr_as_intrinsic(instr);
177 
178    switch (intr->intrinsic) {
179    case nir_intrinsic_load_tess_coord_xy:
180       m_sv_values.set(es_tess_coord);
181       break;
182    case nir_intrinsic_load_primitive_id:
183       m_sv_values.set(es_primitive_id);
184       break;
185    case nir_intrinsic_load_tcs_rel_patch_id_r600:
186       m_sv_values.set(es_rel_patch_id);
187       break;
188    case nir_intrinsic_store_output: {
189       int driver_location = nir_intrinsic_base(intr);
190       auto location = static_cast<gl_varying_slot>(nir_intrinsic_io_semantics(intr).location);
191       auto write_mask = nir_intrinsic_write_mask(intr);
192 
193       if (location == VARYING_SLOT_LAYER)
194          write_mask = 4;
195 
196       ShaderOutput output(driver_location, write_mask, location);
197 
198       add_output(output);
199       break;
200    }
201    default:
202       return false;
203    }
204    return true;
205 }
206 
207 int
do_allocate_reserved_registers()208 TESShader::do_allocate_reserved_registers()
209 {
210    if (m_sv_values.test(es_tess_coord)) {
211       m_tess_coord[0] = value_factory().allocate_pinned_register(0, 0);
212       m_tess_coord[1] = value_factory().allocate_pinned_register(0, 1);
213    }
214 
215    if (m_sv_values.test(es_rel_patch_id)) {
216       m_rel_patch_id = value_factory().allocate_pinned_register(0, 2);
217    }
218 
219    if (m_sv_values.test(es_primitive_id) || m_vs_as_gs_a) {
220       m_primitive_id = value_factory().allocate_pinned_register(0, 3);
221    }
222    return value_factory().next_register_index();
223 }
224 
225 bool
process_stage_intrinsic(nir_intrinsic_instr * intr)226 TESShader::process_stage_intrinsic(nir_intrinsic_instr *intr)
227 {
228    switch (intr->intrinsic) {
229    case nir_intrinsic_load_tess_coord_xy:
230       return emit_simple_mov(intr->def, 0, m_tess_coord[0], pin_none) &&
231              emit_simple_mov(intr->def, 1, m_tess_coord[1], pin_none);
232    case nir_intrinsic_load_primitive_id:
233       return emit_simple_mov(intr->def, 0, m_primitive_id);
234    case nir_intrinsic_load_tcs_rel_patch_id_r600:
235       return emit_simple_mov(intr->def, 0, m_rel_patch_id);
236    case nir_intrinsic_store_output:
237       return m_export_processor->store_output(*intr);
238    default:
239       return false;
240    }
241 }
242 
243 void
do_get_shader_info(r600_shader * sh_info)244 TESShader::do_get_shader_info(r600_shader *sh_info)
245 {
246    sh_info->processor_type = PIPE_SHADER_TESS_EVAL;
247    m_export_processor->get_shader_info(sh_info);
248 }
249 
250 void
do_finalize()251 TESShader::do_finalize()
252 {
253    m_export_processor->finalize();
254 }
255 
256 bool
read_prop(std::istream & is)257 TESShader::TESShader::read_prop(std::istream& is)
258 {
259    (void)is;
260    return true;
261 }
262 
263 void
do_print_properties(std::ostream & os) const264 TESShader::do_print_properties(std::ostream& os) const
265 {
266    (void)os;
267 }
268 
269 } // namespace r600
270