f5200405f7ad60ab71dafd35151615da0dd4cded
[mesa.git] / src / gallium / drivers / r600 / sfn / sfn_emitssboinstruction.cpp
1 #include "sfn_emitssboinstruction.h"
2
3 #include "sfn_instruction_fetch.h"
4 #include "sfn_instruction_gds.h"
5 #include "sfn_instruction_misc.h"
6 #include "sfn_instruction_tex.h"
7 #include "../r600_pipe.h"
8 #include "../r600_asm.h"
9
10 namespace r600 {
11
12 #define R600_SHADER_BUFFER_INFO_SEL (512 + R600_BUFFER_INFO_OFFSET / 16)
13
14 EmitSSBOInstruction::EmitSSBOInstruction(ShaderFromNirProcessor& processor):
15 EmitInstruction(processor),
16 m_require_rat_return_address(false),
17 m_ssbo_image_offset(0)
18 {
19 }
20
21 void EmitSSBOInstruction::set_ssbo_offset(int offset)
22 {
23 m_ssbo_image_offset = offset;
24 }
25
26
27 void EmitSSBOInstruction::set_require_rat_return_address()
28 {
29 m_require_rat_return_address = true;
30 }
31
32 bool
33 EmitSSBOInstruction::load_rat_return_address()
34 {
35 if (m_require_rat_return_address) {
36 m_rat_return_address = get_temp_vec4();
37 emit_instruction(new AluInstruction(op1_mbcnt_32lo_accum_prev_int, m_rat_return_address.reg_i(0), literal(-1), {alu_write}));
38 emit_instruction(new AluInstruction(op1_mbcnt_32hi_int, m_rat_return_address.reg_i(1), literal(-1), {alu_write}));
39 emit_instruction(new AluInstruction(op3_muladd_uint24, m_rat_return_address.reg_i(2), PValue(new InlineConstValue(ALU_SRC_SE_ID, 0)),
40 literal(256), PValue(new InlineConstValue(ALU_SRC_HW_WAVE_ID, 0)), {alu_write, alu_last_instr}));
41 emit_instruction(new AluInstruction(op3_muladd_uint24, m_rat_return_address.reg_i(1),
42 m_rat_return_address.reg_i(2), literal(0x40), m_rat_return_address.reg_i(0),
43 {alu_write, alu_last_instr}));
44 m_require_rat_return_address = false;
45 }
46 return true;
47 }
48
49
50 bool EmitSSBOInstruction::do_emit(nir_instr* instr)
51 {
52 const nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
53 switch (intr->intrinsic) {
54 case nir_intrinsic_atomic_counter_add:
55 case nir_intrinsic_atomic_counter_and:
56 case nir_intrinsic_atomic_counter_exchange:
57 case nir_intrinsic_atomic_counter_max:
58 case nir_intrinsic_atomic_counter_min:
59 case nir_intrinsic_atomic_counter_or:
60 case nir_intrinsic_atomic_counter_xor:
61 case nir_intrinsic_atomic_counter_comp_swap:
62 return emit_atomic(intr);
63 case nir_intrinsic_atomic_counter_read:
64 case nir_intrinsic_atomic_counter_post_dec:
65 return emit_unary_atomic(intr);
66 case nir_intrinsic_atomic_counter_inc:
67 return emit_atomic_inc(intr);
68 case nir_intrinsic_atomic_counter_pre_dec:
69 return emit_atomic_pre_dec(intr);
70 case nir_intrinsic_load_ssbo:
71 return emit_load_ssbo(intr);
72 case nir_intrinsic_store_ssbo:
73 return emit_store_ssbo(intr);
74 case nir_intrinsic_ssbo_atomic_add:
75 case nir_intrinsic_ssbo_atomic_comp_swap:
76 case nir_intrinsic_ssbo_atomic_or:
77 case nir_intrinsic_ssbo_atomic_xor:
78 case nir_intrinsic_ssbo_atomic_imax:
79 case nir_intrinsic_ssbo_atomic_imin:
80 case nir_intrinsic_ssbo_atomic_umax:
81 case nir_intrinsic_ssbo_atomic_umin:
82 case nir_intrinsic_ssbo_atomic_and:
83 case nir_intrinsic_ssbo_atomic_exchange:
84 return emit_ssbo_atomic_op(intr);
85 case nir_intrinsic_image_store:
86 return emit_image_store(intr);
87 case nir_intrinsic_image_load:
88 case nir_intrinsic_image_atomic_add:
89 case nir_intrinsic_image_atomic_and:
90 case nir_intrinsic_image_atomic_or:
91 case nir_intrinsic_image_atomic_xor:
92 case nir_intrinsic_image_atomic_exchange:
93 case nir_intrinsic_image_atomic_comp_swap:
94 case nir_intrinsic_image_atomic_umin:
95 case nir_intrinsic_image_atomic_umax:
96 case nir_intrinsic_image_atomic_imin:
97 case nir_intrinsic_image_atomic_imax:
98 return emit_image_load(intr);
99 case nir_intrinsic_image_size:
100 return emit_image_size(intr);
101 case nir_intrinsic_get_buffer_size:
102 return emit_buffer_size(intr);
103 default:
104 return false;
105 }
106 }
107
108 bool EmitSSBOInstruction::emit_atomic(const nir_intrinsic_instr* instr)
109 {
110 ESDOp op = get_opcode(instr->intrinsic);
111
112 if (DS_OP_INVALID == op)
113 return false;
114
115 GPRVector dest = make_dest(instr);
116
117 int base = remap_atomic_base(nir_intrinsic_base(instr));
118
119 PValue uav_id = from_nir(instr->src[0], 0);
120
121 PValue value = from_nir_with_fetch_constant(instr->src[1], 0);
122
123 GDSInstr *ir = nullptr;
124 if (instr->intrinsic == nir_intrinsic_atomic_counter_comp_swap) {
125 PValue value2 = from_nir_with_fetch_constant(instr->src[2], 0);
126 ir = new GDSInstr(op, dest, value, value2, uav_id, base);
127 } else {
128 ir = new GDSInstr(op, dest, value, uav_id, base);
129 }
130
131 emit_instruction(ir);
132 return true;
133 }
134
135 bool EmitSSBOInstruction::emit_unary_atomic(const nir_intrinsic_instr* instr)
136 {
137 ESDOp op = get_opcode(instr->intrinsic);
138
139 if (DS_OP_INVALID == op)
140 return false;
141
142 GPRVector dest = make_dest(instr);
143
144 PValue uav_id = from_nir(instr->src[0], 0);
145
146 auto ir = new GDSInstr(op, dest, uav_id, remap_atomic_base(nir_intrinsic_base(instr)));
147
148 emit_instruction(ir);
149 return true;
150 }
151
152 ESDOp EmitSSBOInstruction::get_opcode(const nir_intrinsic_op opcode)
153 {
154 switch (opcode) {
155 case nir_intrinsic_atomic_counter_add:
156 return DS_OP_ADD_RET;
157 case nir_intrinsic_atomic_counter_and:
158 return DS_OP_AND_RET;
159 case nir_intrinsic_atomic_counter_exchange:
160 return DS_OP_XCHG_RET;
161 case nir_intrinsic_atomic_counter_inc:
162 return DS_OP_INC_RET;
163 case nir_intrinsic_atomic_counter_max:
164 return DS_OP_MAX_UINT_RET;
165 case nir_intrinsic_atomic_counter_min:
166 return DS_OP_MIN_UINT_RET;
167 case nir_intrinsic_atomic_counter_or:
168 return DS_OP_OR_RET;
169 case nir_intrinsic_atomic_counter_read:
170 return DS_OP_READ_RET;
171 case nir_intrinsic_atomic_counter_xor:
172 return DS_OP_XOR_RET;
173 case nir_intrinsic_atomic_counter_post_dec:
174 return DS_OP_DEC_RET;
175 case nir_intrinsic_atomic_counter_comp_swap:
176 return DS_OP_CMP_XCHG_RET;
177 case nir_intrinsic_atomic_counter_pre_dec:
178 default:
179 return DS_OP_INVALID;
180 }
181 }
182
183 RatInstruction::ERatOp
184 EmitSSBOInstruction::get_rat_opcode(const nir_intrinsic_op opcode, pipe_format format) const
185 {
186 switch (opcode) {
187 case nir_intrinsic_ssbo_atomic_add:
188 case nir_intrinsic_image_atomic_add:
189 return RatInstruction::ADD_RTN;
190 case nir_intrinsic_ssbo_atomic_and:
191 case nir_intrinsic_image_atomic_and:
192 return RatInstruction::AND_RTN;
193 case nir_intrinsic_ssbo_atomic_exchange:
194 case nir_intrinsic_image_atomic_exchange:
195 return RatInstruction::XCHG_RTN;
196 case nir_intrinsic_ssbo_atomic_or:
197 case nir_intrinsic_image_atomic_or:
198 return RatInstruction::OR_RTN;
199 case nir_intrinsic_ssbo_atomic_imin:
200 case nir_intrinsic_image_atomic_imin:
201 return RatInstruction::MIN_INT_RTN;
202 case nir_intrinsic_ssbo_atomic_imax:
203 case nir_intrinsic_image_atomic_imax:
204 return RatInstruction::MAX_INT_RTN;
205 case nir_intrinsic_ssbo_atomic_umin:
206 case nir_intrinsic_image_atomic_umin:
207 return RatInstruction::MIN_UINT_RTN;
208 case nir_intrinsic_ssbo_atomic_umax:
209 case nir_intrinsic_image_atomic_umax:
210 return RatInstruction::MAX_UINT_RTN;
211 case nir_intrinsic_ssbo_atomic_xor:
212 case nir_intrinsic_image_atomic_xor:
213 return RatInstruction::XOR_RTN;
214 case nir_intrinsic_ssbo_atomic_comp_swap:
215 case nir_intrinsic_image_atomic_comp_swap:
216 if (util_format_is_float(format))
217 return RatInstruction::CMPXCHG_FLT_RTN;
218 else
219 return RatInstruction::CMPXCHG_INT_RTN;
220 case nir_intrinsic_image_load:
221 return RatInstruction::NOP_RTN;
222 default:
223 unreachable("Unsupported RAT instruction");
224 }
225 }
226
227
228 bool EmitSSBOInstruction::emit_atomic_add(const nir_intrinsic_instr* instr)
229 {
230 GPRVector dest = make_dest(instr);
231
232 PValue value = from_nir_with_fetch_constant(instr->src[1], 0);
233
234 PValue uav_id = from_nir(instr->src[0], 0);
235
236 auto ir = new GDSInstr(DS_OP_ADD_RET, dest, value, uav_id,
237 remap_atomic_base(nir_intrinsic_base(instr)));
238
239 emit_instruction(ir);
240 return true;
241 }
242
243 bool EmitSSBOInstruction::load_atomic_inc_limits()
244 {
245 m_atomic_update = get_temp_register();
246 emit_instruction(new AluInstruction(op1_mov, m_atomic_update, literal(1),
247 {alu_write, alu_last_instr}));
248 return true;
249 }
250
251 bool EmitSSBOInstruction::emit_atomic_inc(const nir_intrinsic_instr* instr)
252 {
253 PValue uav_id = from_nir(instr->src[0], 0);
254 GPRVector dest = make_dest(instr);
255 auto ir = new GDSInstr(DS_OP_ADD_RET, dest, m_atomic_update, uav_id,
256 remap_atomic_base(nir_intrinsic_base(instr)));
257 emit_instruction(ir);
258 return true;
259 }
260
261 bool EmitSSBOInstruction::emit_atomic_pre_dec(const nir_intrinsic_instr *instr)
262 {
263 GPRVector dest = make_dest(instr);
264
265 PValue uav_id = from_nir(instr->src[0], 0);
266
267 auto ir = new GDSInstr(DS_OP_SUB_RET, dest, m_atomic_update, uav_id,
268 remap_atomic_base(nir_intrinsic_base(instr)));
269 emit_instruction(ir);
270
271 emit_instruction(new AluInstruction(op2_sub_int, dest.x(), dest.x(), literal(1), last_write));
272
273 return true;
274 }
275
276 bool EmitSSBOInstruction::emit_load_ssbo(const nir_intrinsic_instr* instr)
277 {
278 GPRVector dest = make_dest(instr);
279
280 /** src0 not used, should be some offset */
281 auto addr = from_nir(instr->src[1], 0);
282 PValue addr_temp = create_register_from_nir_src(instr->src[1], 1);
283
284 /** Should be lowered in nir */
285 emit_instruction(new AluInstruction(op2_lshr_int, addr_temp, {addr, PValue(new LiteralValue(2))},
286 {alu_write, alu_last_instr}));
287
288 const EVTXDataFormat formats[4] = {
289 fmt_32,
290 fmt_32_32,
291 fmt_32_32_32,
292 fmt_32_32_32_32
293 };
294
295 const std::array<int,4> dest_swt[4] = {
296 {0,7,7,7},
297 {0,1,7,7},
298 {0,1,2,7},
299 {0,1,2,3}
300 };
301
302 /* TODO fix resource index */
303 auto ir = new FetchInstruction(dest, addr_temp,
304 R600_IMAGE_REAL_RESOURCE_OFFSET, from_nir(instr->src[0], 0),
305 formats[nir_dest_num_components(instr->dest) - 1], vtx_nf_int);
306 ir->set_dest_swizzle(dest_swt[nir_dest_num_components(instr->dest) - 1]);
307 ir->set_flag(vtx_use_tc);
308
309 emit_instruction(ir);
310 return true;
311 }
312
313 bool EmitSSBOInstruction::emit_store_ssbo(const nir_intrinsic_instr* instr)
314 {
315
316 GPRVector::Swizzle swz = {7,7,7,7};
317 for (unsigned i = 0; i < nir_src_num_components(instr->src[0]); ++i)
318 swz[i] = i;
319
320 auto orig_addr = from_nir(instr->src[2], 0);
321
322 int temp1 = allocate_temp_register();
323 GPRVector addr_vec(temp1, {0,1,2,7});
324
325 auto temp2 = get_temp_vec4();
326
327 auto rat_id = from_nir(instr->src[1], 0);
328
329 emit_instruction(new AluInstruction(op2_lshr_int, addr_vec.reg_i(0), orig_addr,
330 PValue(new LiteralValue(2)), write));
331 emit_instruction(new AluInstruction(op1_mov, addr_vec.reg_i(1), Value::zero, write));
332 emit_instruction(new AluInstruction(op1_mov, addr_vec.reg_i(2), Value::zero, last_write));
333
334
335 //#define WRITE_AS_VECTOR
336 #ifdef WRITE_AS_VECTOR
337 std::unique_ptr<GPRVector> value(vec_from_nir_with_fetch_constant(instr->src[0],
338 (1 << instr->src[0].ssa->num_components) - 1, swz));
339
340 /* TODO fix resource index */
341 int nelements = instr->src[0].ssa->num_components - 1;
342 if (nelements == 2)
343 nelements = 3;
344 auto ir = new RatInstruction(cf_mem_rat, RatInstruction::STORE_TYPED,
345 *value, addr_vec, 0, rat_id, 11,
346 (1 << instr->src[0].ssa->num_components) - 1,
347 0, false);
348 emit_instruction(ir);
349 #else
350
351 auto values = vec_from_nir_with_fetch_constant(instr->src[0],
352 (1 << nir_src_num_components(instr->src[0])) - 1, {0,1,2,3}, true);
353
354 emit_instruction(new RatInstruction(cf_mem_rat, RatInstruction::STORE_TYPED,
355 values, addr_vec, m_ssbo_image_offset, rat_id, 1,
356 1, 0, false));
357
358 for (unsigned i = 1; i < nir_src_num_components(instr->src[0]); ++i) {
359 emit_instruction(new AluInstruction(op1_mov, temp2.reg_i(0), from_nir(instr->src[0], i), write));
360 emit_instruction(new AluInstruction(op2_add_int, addr_vec.reg_i(0),
361 {addr_vec.reg_i(0), Value::one_i}, last_write));
362 emit_instruction(new RatInstruction(cf_mem_rat, RatInstruction::STORE_TYPED,
363 temp2, addr_vec, 0, rat_id, 1,
364 1, 0, false));
365 }
366 #endif
367 return true;
368 }
369
370 bool
371 EmitSSBOInstruction::emit_image_store(const nir_intrinsic_instr *intrin)
372 {
373 int imageid = 0;
374 PValue image_offset;
375
376 if (nir_src_is_const(intrin->src[0]))
377 imageid = nir_src_as_int(intrin->src[0]);
378 else
379 image_offset = from_nir(intrin->src[0], 0);
380
381 auto coord = vec_from_nir_with_fetch_constant(intrin->src[1], 0xf, {0,1,2,3});
382 auto undef = from_nir(intrin->src[2], 0);
383 auto value = vec_from_nir_with_fetch_constant(intrin->src[3], 0xf, {0,1,2,3});
384 auto unknown = from_nir(intrin->src[4], 0);
385
386 if (nir_intrinsic_image_dim(intrin) == GLSL_SAMPLER_DIM_1D &&
387 nir_intrinsic_image_array(intrin)) {
388 emit_instruction(new AluInstruction(op1_mov, coord.reg_i(2), coord.reg_i(1), {alu_write}));
389 emit_instruction(new AluInstruction(op1_mov, coord.reg_i(1), coord.reg_i(2), {alu_last_instr, alu_write}));
390 }
391
392 auto store = new RatInstruction(cf_mem_rat, RatInstruction::STORE_TYPED, value, coord, imageid,
393 image_offset, 1, 0xf, 0, false);
394 emit_instruction(store);
395 return true;
396 }
397
398 bool
399 EmitSSBOInstruction::emit_ssbo_atomic_op(const nir_intrinsic_instr *intrin)
400 {
401 int imageid = 0;
402 PValue image_offset;
403
404 if (nir_src_is_const(intrin->src[0]))
405 imageid = nir_src_as_int(intrin->src[0]);
406 else
407 image_offset = from_nir(intrin->src[0], 0);
408
409 auto opcode = EmitSSBOInstruction::get_rat_opcode(intrin->intrinsic, PIPE_FORMAT_R32_UINT);
410
411
412 auto coord_orig = from_nir(intrin->src[1], 0, 0);
413 auto coord = get_temp_register(0);
414
415 emit_instruction(new AluInstruction(op2_lshr_int, coord, coord_orig, literal(2), last_write));
416
417 if (intrin->intrinsic == nir_intrinsic_ssbo_atomic_comp_swap) {
418 emit_instruction(new AluInstruction(op1_mov, m_rat_return_address.reg_i(0),
419 from_nir(intrin->src[3], 0), {alu_write}));
420 // TODO: cayman wants channel 2 here
421 emit_instruction(new AluInstruction(op1_mov, m_rat_return_address.reg_i(3),
422 from_nir(intrin->src[2], 0), {alu_last_instr, alu_write}));
423 } else {
424 emit_instruction(new AluInstruction(op1_mov, m_rat_return_address.reg_i(0),
425 from_nir(intrin->src[2], 0), {alu_write}));
426 emit_instruction(new AluInstruction(op1_mov, m_rat_return_address.reg_i(2), Value::zero, last_write));
427 }
428
429
430 GPRVector out_vec({coord, coord, coord, coord});
431
432 auto atomic = new RatInstruction(cf_mem_rat, opcode, m_rat_return_address, out_vec, imageid + m_ssbo_image_offset,
433 image_offset, 1, 0xf, 0, true);
434 emit_instruction(atomic);
435 emit_instruction(new WaitAck(0));
436
437 GPRVector dest = vec_from_nir(intrin->dest, intrin->dest.ssa.num_components);
438 auto fetch = new FetchInstruction(vc_fetch,
439 no_index_offset,
440 fmt_32,
441 vtx_nf_int,
442 vtx_es_none,
443 m_rat_return_address.reg_i(1),
444 dest,
445 0,
446 false,
447 0xf,
448 R600_IMAGE_IMMED_RESOURCE_OFFSET + imageid,
449 0,
450 bim_none,
451 false,
452 false,
453 0,
454 0,
455 0,
456 image_offset,
457 {0,7,7,7});
458 fetch->set_flag(vtx_srf_mode);
459 fetch->set_flag(vtx_use_tc);
460 emit_instruction(fetch);
461 return true;
462
463 }
464
465 bool
466 EmitSSBOInstruction::emit_image_load(const nir_intrinsic_instr *intrin)
467 {
468 int imageid = 0;
469 PValue image_offset;
470
471 if (nir_src_is_const(intrin->src[0]))
472 imageid = nir_src_as_int(intrin->src[0]);
473 else
474 image_offset = from_nir(intrin->src[0], 0);
475
476 auto rat_op = get_rat_opcode(intrin->intrinsic, nir_intrinsic_format(intrin));
477
478 GPRVector::Swizzle swz = {0,1,2,3};
479 auto coord = vec_from_nir_with_fetch_constant(intrin->src[1], 0xf, swz);
480
481 if (nir_intrinsic_image_dim(intrin) == GLSL_SAMPLER_DIM_1D &&
482 nir_intrinsic_image_array(intrin)) {
483 emit_instruction(new AluInstruction(op1_mov, coord.reg_i(2), coord.reg_i(1), {alu_write}));
484 emit_instruction(new AluInstruction(op1_mov, coord.reg_i(1), coord.reg_i(2), {alu_last_instr, alu_write}));
485 }
486
487 if (intrin->intrinsic != nir_intrinsic_image_load) {
488 if (intrin->intrinsic == nir_intrinsic_image_atomic_comp_swap) {
489 emit_instruction(new AluInstruction(op1_mov, m_rat_return_address.reg_i(0),
490 from_nir(intrin->src[4], 0), {alu_write}));
491 emit_instruction(new AluInstruction(op1_mov, m_rat_return_address.reg_i(3),
492 from_nir(intrin->src[3], 0), {alu_last_instr, alu_write}));
493 } else {
494 emit_instruction(new AluInstruction(op1_mov, m_rat_return_address.reg_i(0),
495 from_nir(intrin->src[3], 0), {alu_last_instr, alu_write}));
496 }
497 }
498
499 auto store = new RatInstruction(cf_mem_rat, rat_op, m_rat_return_address, coord, imageid,
500 image_offset, 1, 0xf, 0, true);
501 emit_instruction(store);
502 return fetch_return_value(intrin);
503 }
504
505 bool EmitSSBOInstruction::fetch_return_value(const nir_intrinsic_instr *intrin)
506 {
507 emit_instruction(new WaitAck(0));
508
509 pipe_format format = nir_intrinsic_format(intrin);
510 unsigned fmt = fmt_32;
511 unsigned num_format = 0;
512 unsigned format_comp = 0;
513 unsigned endian = 0;
514
515 int imageid = 0;
516 PValue image_offset;
517
518 if (nir_src_is_const(intrin->src[0]))
519 imageid = nir_src_as_int(intrin->src[0]);
520 else
521 image_offset = from_nir(intrin->src[0], 0);
522
523 r600_vertex_data_type(format, &fmt, &num_format, &format_comp, &endian);
524
525 GPRVector dest = vec_from_nir(intrin->dest, nir_dest_num_components(intrin->dest));
526
527 auto fetch = new FetchInstruction(vc_fetch,
528 no_index_offset,
529 (EVTXDataFormat)fmt,
530 (EVFetchNumFormat)num_format,
531 (EVFetchEndianSwap)endian,
532 m_rat_return_address.reg_i(1),
533 dest,
534 0,
535 false,
536 0xf,
537 R600_IMAGE_IMMED_RESOURCE_OFFSET + imageid,
538 0,
539 bim_none,
540 false,
541 false,
542 0,
543 0,
544 0,
545 image_offset, {0,1,2,3});
546 fetch->set_flag(vtx_srf_mode);
547 fetch->set_flag(vtx_use_tc);
548 if (format_comp)
549 fetch->set_flag(vtx_format_comp_signed);
550
551 emit_instruction(fetch);
552 return true;
553 }
554
555 bool EmitSSBOInstruction::emit_image_size(const nir_intrinsic_instr *intrin)
556 {
557 GPRVector dest = vec_from_nir(intrin->dest, nir_dest_num_components(intrin->dest));
558 GPRVector src{0,{4,4,4,4}};
559
560 auto const_offset = nir_src_as_const_value(intrin->src[0]);
561 auto dyn_offset = PValue();
562 int res_id = R600_IMAGE_REAL_RESOURCE_OFFSET;
563 if (const_offset)
564 res_id += const_offset[0].u32;
565 else
566 dyn_offset = from_nir(intrin->src[0], 0);
567
568 if (nir_intrinsic_image_dim(intrin) == GLSL_SAMPLER_DIM_BUF) {
569 emit_instruction(new FetchInstruction(dest, PValue(new GPRValue(0, 7)),
570 res_id,
571 bim_none));
572 return true;
573 } else {
574 emit_instruction(new TexInstruction(TexInstruction::get_resinfo, dest, src,
575 0/* ?? */,
576 res_id, dyn_offset));
577 if (nir_intrinsic_image_dim(intrin) == GLSL_SAMPLER_DIM_CUBE &&
578 nir_intrinsic_image_array(intrin) && nir_dest_num_components(intrin->dest) > 2) {
579 /* Need to load the layers from a const buffer */
580
581 unsigned lookup_resid = const_offset[0].u32;
582 emit_instruction(new AluInstruction(op1_mov, dest.reg_i(2),
583 PValue(new UniformValue(lookup_resid/4 + R600_SHADER_BUFFER_INFO_SEL, lookup_resid % 4,
584 R600_BUFFER_INFO_CONST_BUFFER)),
585 EmitInstruction::last_write));
586 }
587 }
588 return true;
589 }
590
591 bool EmitSSBOInstruction::emit_buffer_size(const nir_intrinsic_instr *intr)
592 {
593 std::array<PValue,4> dst_elms;
594
595
596 for (uint16_t i = 0; i < 4; ++i) {
597 dst_elms[i] = from_nir(intr->dest, (i < intr->dest.ssa.num_components) ? i : 7);
598 }
599
600 GPRVector dst(dst_elms);
601 GPRVector src(0,{4,4,4,4});
602
603 auto const_offset = nir_src_as_const_value(intr->src[0]);
604 auto dyn_offset = PValue();
605 int res_id = R600_IMAGE_REAL_RESOURCE_OFFSET;
606 if (const_offset)
607 res_id += const_offset[0].u32;
608 else
609 assert(0 && "dynamic buffer offset not supported in buffer_size");
610
611 emit_instruction(new FetchInstruction(dst, PValue(new GPRValue(0, 7)),
612 res_id, bim_none));
613
614 return true;
615 }
616
617 GPRVector EmitSSBOInstruction::make_dest(const nir_intrinsic_instr* ir)
618 {
619 GPRVector::Values v;
620 int i;
621 for (i = 0; i < 4; ++i)
622 v[i] = from_nir(ir->dest, i);
623 return GPRVector(v);
624 }
625
626 }