r600/sfn: use the per shader atomic base
[mesa.git] / src / gallium / drivers / r600 / sfn / sfn_shader_vertex.cpp
1 /* -*- mesa-c++ -*-
2 *
3 * Copyright (c) 2018 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
28 #include "pipe/p_defines.h"
29 #include "tgsi/tgsi_from_mesa.h"
30 #include "sfn_shader_vertex.h"
31 #include "sfn_instruction_lds.h"
32
33 #include <queue>
34
35
36 namespace r600 {
37
38 using std::priority_queue;
39
40 VertexShaderFromNir::VertexShaderFromNir(r600_pipe_shader *sh,
41 r600_pipe_shader_selector& sel,
42 const r600_shader_key& key,
43 struct r600_shader* gs_shader,
44 enum chip_class chip_class):
45 VertexStage(PIPE_SHADER_VERTEX, sel, sh->shader,
46 sh->scratch_space_needed, chip_class, key.vs.first_atomic_counter),
47 m_num_clip_dist(0),
48 m_last_param_export(nullptr),
49 m_last_pos_export(nullptr),
50 m_pipe_shader(sh),
51 m_enabled_stream_buffers_mask(0),
52 m_so_info(&sel.so),
53 m_vertex_id(),
54 m_key(key)
55 {
56 // reg 0 is used in the fetch shader
57 increment_reserved_registers();
58
59 sh_info().atomic_base = key.vs.first_atomic_counter;
60 sh_info().vs_as_gs_a = m_key.vs.as_gs_a;
61
62 if (key.vs.as_es) {
63 sh->shader.vs_as_es = true;
64 m_export_processor.reset(new VertexStageExportForGS(*this, gs_shader));
65 } else if (key.vs.as_ls) {
66 sh->shader.vs_as_ls = true;
67 sfn_log << SfnLog::trans << "Start VS for GS\n";
68 m_export_processor.reset(new VertexStageExportForES(*this));
69 } else {
70 m_export_processor.reset(new VertexStageExportForFS(*this, &sel.so, sh, key));
71 }
72 }
73
74 bool VertexShaderFromNir::do_process_inputs(nir_variable *input)
75 {
76 ++sh_info().ninput;
77
78 if (input->data.location < VERT_ATTRIB_MAX) {
79 increment_reserved_registers();
80 return true;
81 }
82 fprintf(stderr, "r600-NIR-VS: Unimplemented process_inputs for %d\n", input->data.location);
83 return false;
84 }
85
86 bool VertexShaderFromNir::do_allocate_reserved_registers()
87 {
88 /* Since the vertex ID is nearly always used, we add it here as an input so
89 * that the registers used for vertex attributes don't get clobbered by the
90 * register merge step */
91 auto R0x = new GPRValue(0,0);
92 R0x->set_as_input();
93 m_vertex_id.reset(R0x);
94 inject_register(0, 0, m_vertex_id, false);
95
96 if (m_key.vs.as_gs_a || m_sv_values.test(es_primitive_id)) {
97 auto R0z = new GPRValue(0,2);
98 R0x->set_as_input();
99 m_primitive_id.reset(R0z);
100 inject_register(0, 2, m_primitive_id, false);
101 }
102
103 if (m_sv_values.test(es_instanceid)) {
104 auto R0w = new GPRValue(0,3);
105 R0w->set_as_input();
106 m_instance_id.reset(R0w);
107 inject_register(0, 3, m_instance_id, false);
108 }
109
110
111 if (m_sv_values.test(es_rel_patch_id)) {
112 auto R0y = new GPRValue(0,1);
113 R0y->set_as_input();
114 m_rel_vertex_id.reset(R0y);
115 inject_register(0, 1, m_rel_vertex_id, false);
116 }
117
118 return true;
119 }
120
121 void VertexShaderFromNir::emit_shader_start()
122 {
123 m_export_processor->setup_paramn_map();
124 }
125
126 bool VertexShaderFromNir::scan_sysvalue_access(nir_instr *instr)
127 {
128 switch (instr->type) {
129 case nir_instr_type_intrinsic: {
130 nir_intrinsic_instr *ii = nir_instr_as_intrinsic(instr);
131 switch (ii->intrinsic) {
132 case nir_intrinsic_load_vertex_id:
133 m_sv_values.set(es_vertexid);
134 break;
135 case nir_intrinsic_load_instance_id:
136 m_sv_values.set(es_instanceid);
137 break;
138 case nir_intrinsic_load_tcs_rel_patch_id_r600:
139 m_sv_values.set(es_rel_patch_id);
140 break;
141 default:
142 ;
143 }
144 }
145 default:
146 ;
147 }
148 return true;
149 }
150
151 bool VertexShaderFromNir::emit_intrinsic_instruction_override(nir_intrinsic_instr* instr)
152 {
153 switch (instr->intrinsic) {
154 case nir_intrinsic_load_vertex_id:
155 return load_preloaded_value(instr->dest, 0, m_vertex_id);
156 case nir_intrinsic_load_tcs_rel_patch_id_r600:
157 return load_preloaded_value(instr->dest, 0, m_rel_vertex_id);
158 case nir_intrinsic_load_instance_id:
159 return load_preloaded_value(instr->dest, 0, m_instance_id);
160 case nir_intrinsic_store_local_shared_r600:
161 return emit_store_local_shared(instr);
162 default:
163 return false;
164 }
165 }
166
167 bool VertexShaderFromNir::emit_store_local_shared(nir_intrinsic_instr* instr)
168 {
169 unsigned write_mask = nir_intrinsic_write_mask(instr);
170
171 auto address = from_nir(instr->src[1], 0);
172 int swizzle_base = (write_mask & 0x3) ? 0 : 2;
173 write_mask |= write_mask >> 2;
174
175 auto value = from_nir(instr->src[0], swizzle_base);
176 if (!(write_mask & 2)) {
177 emit_instruction(new LDSWriteInstruction(address, 1, value));
178 } else {
179 auto value1 = from_nir(instr->src[0], swizzle_base + 1);
180 emit_instruction(new LDSWriteInstruction(address, 1, value, value1));
181 }
182
183 return true;
184 }
185
186 bool VertexShaderFromNir::do_process_outputs(nir_variable *output)
187 {
188 return m_export_processor->do_process_outputs(output);
189 }
190
191 bool VertexShaderFromNir::do_emit_load_deref(const nir_variable *in_var, nir_intrinsic_instr* instr)
192 {
193 if (in_var->data.location < VERT_ATTRIB_MAX) {
194 for (int i = 0; i < instr->num_components ; ++i) {
195 auto s = new GPRValue(in_var->data.driver_location + 1, i);
196 s->set_as_input();
197 auto src = PValue(s);
198 inject_register(in_var->data.driver_location + 1, i, src, false);
199
200 if (i == 0)
201 set_input(in_var->data.driver_location, src);
202
203 load_preloaded_value(instr->dest, i, src, i == instr->num_components - 1);
204 }
205 return true;
206 }
207 fprintf(stderr, "r600-NIR: Unimplemented load_deref for %d\n", in_var->data.location);
208 return false;
209 }
210
211 void VertexShaderFromNir::do_finalize()
212 {
213 m_export_processor->finalize_exports();
214 }
215
216 bool VertexShaderFromNir::do_emit_store_deref(const nir_variable *out_var, nir_intrinsic_instr* instr)
217 {
218 return m_export_processor->store_deref(out_var, instr);
219 }
220
221 }