intel/compiler: Do image load/store lowering to NIR
[mesa.git] / src / intel / compiler / brw_fs_surface_builder.cpp
1 /*
2 * Copyright © 2013-2015 Intel Corporation
3 *
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:
10 *
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
13 * Software.
14 *
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
21 * IN THE SOFTWARE.
22 */
23
24 #include "isl/isl.h"
25 #include "brw_fs_surface_builder.h"
26 #include "brw_fs.h"
27
28 using namespace brw;
29
30 namespace brw {
31 namespace surface_access {
32 namespace {
33 /**
34 * Generate a logical send opcode for a surface message and return
35 * the result.
36 */
37 fs_reg
38 emit_send(const fs_builder &bld, enum opcode opcode,
39 const fs_reg &addr, const fs_reg &src, const fs_reg &surface,
40 unsigned dims, unsigned arg, unsigned rsize,
41 brw_predicate pred = BRW_PREDICATE_NONE)
42 {
43 /* Reduce the dynamically uniform surface index to a single
44 * scalar.
45 */
46 const fs_reg usurface = bld.emit_uniformize(surface);
47 const fs_reg srcs[] = {
48 addr, src, usurface, brw_imm_ud(dims), brw_imm_ud(arg)
49 };
50 const fs_reg dst = bld.vgrf(BRW_REGISTER_TYPE_UD, rsize);
51 fs_inst *inst = bld.emit(opcode, dst, srcs, ARRAY_SIZE(srcs));
52
53 inst->size_written = rsize * dst.component_size(inst->exec_size);
54 inst->predicate = pred;
55 return dst;
56 }
57 }
58
59 /**
60 * Emit an untyped surface read opcode. \p dims determines the number
61 * of components of the address and \p size the number of components of
62 * the returned value.
63 */
64 fs_reg
65 emit_untyped_read(const fs_builder &bld,
66 const fs_reg &surface, const fs_reg &addr,
67 unsigned dims, unsigned size,
68 brw_predicate pred)
69 {
70 return emit_send(bld, SHADER_OPCODE_UNTYPED_SURFACE_READ_LOGICAL,
71 addr, fs_reg(), surface, dims, size, size, pred);
72 }
73
74 /**
75 * Emit an untyped surface write opcode. \p dims determines the number
76 * of components of the address and \p size the number of components of
77 * the argument.
78 */
79 void
80 emit_untyped_write(const fs_builder &bld, const fs_reg &surface,
81 const fs_reg &addr, const fs_reg &src,
82 unsigned dims, unsigned size,
83 brw_predicate pred)
84 {
85 emit_send(bld, SHADER_OPCODE_UNTYPED_SURFACE_WRITE_LOGICAL,
86 addr, src, surface, dims, size, 0, pred);
87 }
88
89 /**
90 * Emit an untyped surface atomic opcode. \p dims determines the number
91 * of components of the address and \p rsize the number of components of
92 * the returned value (either zero or one).
93 */
94 fs_reg
95 emit_untyped_atomic(const fs_builder &bld,
96 const fs_reg &surface, const fs_reg &addr,
97 const fs_reg &src0, const fs_reg &src1,
98 unsigned dims, unsigned rsize, unsigned op,
99 brw_predicate pred)
100 {
101 /* FINISHME: Factor out this frequently recurring pattern into a
102 * helper function.
103 */
104 const unsigned n = (src0.file != BAD_FILE) + (src1.file != BAD_FILE);
105 const fs_reg srcs[] = { src0, src1 };
106 const fs_reg tmp = bld.vgrf(BRW_REGISTER_TYPE_UD, n);
107 bld.LOAD_PAYLOAD(tmp, srcs, n, 0);
108
109 return emit_send(bld, SHADER_OPCODE_UNTYPED_ATOMIC_LOGICAL,
110 addr, tmp, surface, dims, op, rsize, pred);
111 }
112
113 /**
114 * Emit an untyped surface atomic float opcode. \p dims determines the
115 * number of components of the address and \p rsize the number of
116 * components of the returned value (either zero or one).
117 */
118 fs_reg
119 emit_untyped_atomic_float(const fs_builder &bld,
120 const fs_reg &surface, const fs_reg &addr,
121 const fs_reg &src0, const fs_reg &src1,
122 unsigned dims, unsigned rsize, unsigned op,
123 brw_predicate pred)
124 {
125 /* FINISHME: Factor out this frequently recurring pattern into a
126 * helper function.
127 */
128 const unsigned n = (src0.file != BAD_FILE) + (src1.file != BAD_FILE);
129 const fs_reg srcs[] = { src0, src1 };
130 const fs_reg tmp = bld.vgrf(src0.type, n);
131 bld.LOAD_PAYLOAD(tmp, srcs, n, 0);
132
133 return emit_send(bld, SHADER_OPCODE_UNTYPED_ATOMIC_FLOAT_LOGICAL,
134 addr, tmp, surface, dims, op, rsize, pred);
135 }
136
137 /**
138 * Emit a typed surface read opcode. \p dims determines the number of
139 * components of the address and \p size the number of components of the
140 * returned value.
141 */
142 fs_reg
143 emit_typed_read(const fs_builder &bld, const fs_reg &surface,
144 const fs_reg &addr, unsigned dims, unsigned size)
145 {
146 return emit_send(bld, SHADER_OPCODE_TYPED_SURFACE_READ_LOGICAL,
147 addr, fs_reg(), surface, dims, size, size);
148 }
149
150 /**
151 * Emit a typed surface write opcode. \p dims determines the number of
152 * components of the address and \p size the number of components of the
153 * argument.
154 */
155 void
156 emit_typed_write(const fs_builder &bld, const fs_reg &surface,
157 const fs_reg &addr, const fs_reg &src,
158 unsigned dims, unsigned size)
159 {
160 emit_send(bld, SHADER_OPCODE_TYPED_SURFACE_WRITE_LOGICAL,
161 addr, src, surface, dims, size, 0);
162 }
163
164 /**
165 * Emit a typed surface atomic opcode. \p dims determines the number of
166 * components of the address and \p rsize the number of components of
167 * the returned value (either zero or one).
168 */
169 fs_reg
170 emit_typed_atomic(const fs_builder &bld, const fs_reg &surface,
171 const fs_reg &addr,
172 const fs_reg &src0, const fs_reg &src1,
173 unsigned dims, unsigned rsize, unsigned op,
174 brw_predicate pred)
175 {
176 /* FINISHME: Factor out this frequently recurring pattern into a
177 * helper function.
178 */
179 const unsigned n = (src0.file != BAD_FILE) + (src1.file != BAD_FILE);
180 const fs_reg srcs[] = { src0, src1 };
181 const fs_reg tmp = bld.vgrf(BRW_REGISTER_TYPE_UD, n);
182 bld.LOAD_PAYLOAD(tmp, srcs, n, 0);
183
184 return emit_send(bld, SHADER_OPCODE_TYPED_ATOMIC_LOGICAL,
185 addr, tmp, surface, dims, op, rsize);
186 }
187
188 fs_reg
189 emit_byte_scattered_read(const fs_builder &bld,
190 const fs_reg &surface, const fs_reg &addr,
191 unsigned dims, unsigned size,
192 unsigned bit_size, brw_predicate pred)
193 {
194 return emit_send(bld, SHADER_OPCODE_BYTE_SCATTERED_READ_LOGICAL,
195 addr, fs_reg(), surface, dims, bit_size, size, pred);
196 }
197
198 void
199 emit_byte_scattered_write(const fs_builder &bld, const fs_reg &surface,
200 const fs_reg &addr, const fs_reg &src,
201 unsigned dims,
202 unsigned bit_size, brw_predicate pred)
203 {
204 emit_send(bld, SHADER_OPCODE_BYTE_SCATTERED_WRITE_LOGICAL,
205 addr, src, surface, dims, bit_size, 0, pred);
206 }
207 }
208 }