1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2014 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
26 */
27
28 #ifndef ILO_BUILDER_RENDER_H
29 #define ILO_BUILDER_RENDER_H
30
31 #include "genhw/genhw.h"
32 #include "intel_winsys.h"
33
34 #include "ilo_core.h"
35 #include "ilo_dev.h"
36 #include "ilo_builder.h"
37
38 static inline void
gen6_STATE_SIP(struct ilo_builder * builder,uint32_t sip)39 gen6_STATE_SIP(struct ilo_builder *builder, uint32_t sip)
40 {
41 const uint8_t cmd_len = (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) ? 3 : 2;
42 uint32_t *dw;
43
44 ILO_DEV_ASSERT(builder->dev, 6, 8);
45
46 ilo_builder_batch_pointer(builder, cmd_len, &dw);
47
48 dw[0] = GEN6_RENDER_CMD(COMMON, STATE_SIP) | (cmd_len - 2);
49 dw[1] = sip;
50 if (ilo_dev_gen(builder->dev) >= ILO_GEN(8))
51 dw[2] = 0;
52 }
53
54 static inline void
gen6_PIPELINE_SELECT(struct ilo_builder * builder,int pipeline)55 gen6_PIPELINE_SELECT(struct ilo_builder *builder, int pipeline)
56 {
57 const uint8_t cmd_len = 1;
58 const uint32_t dw0 = GEN6_RENDER_CMD(SINGLE_DW, PIPELINE_SELECT) |
59 pipeline;
60
61 ILO_DEV_ASSERT(builder->dev, 6, 8);
62
63 switch (pipeline) {
64 case GEN6_PIPELINE_SELECT_DW0_SELECT_3D:
65 case GEN6_PIPELINE_SELECT_DW0_SELECT_MEDIA:
66 break;
67 case GEN7_PIPELINE_SELECT_DW0_SELECT_GPGPU:
68 assert(ilo_dev_gen(builder->dev) >= ILO_GEN(7));
69 break;
70 default:
71 assert(!"unknown pipeline");
72 break;
73 }
74
75 ilo_builder_batch_write(builder, cmd_len, &dw0);
76 }
77
78 static inline void
gen6_PIPE_CONTROL(struct ilo_builder * builder,uint32_t dw1,struct intel_bo * bo,uint32_t bo_offset,uint64_t imm)79 gen6_PIPE_CONTROL(struct ilo_builder *builder, uint32_t dw1,
80 struct intel_bo *bo, uint32_t bo_offset,
81 uint64_t imm)
82 {
83 const uint8_t cmd_len = (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) ? 6 : 5;
84 uint32_t reloc_flags = INTEL_RELOC_WRITE;
85 uint32_t *dw;
86 unsigned pos;
87
88 ILO_DEV_ASSERT(builder->dev, 6, 8);
89
90 if (dw1 & GEN6_PIPE_CONTROL_CS_STALL) {
91 /*
92 * From the Sandy Bridge PRM, volume 2 part 1, page 73:
93 *
94 * "1 of the following must also be set (when CS stall is set):
95 *
96 * * Depth Cache Flush Enable ([0] of DW1)
97 * * Stall at Pixel Scoreboard ([1] of DW1)
98 * * Depth Stall ([13] of DW1)
99 * * Post-Sync Operation ([13] of DW1)
100 * * Render Target Cache Flush Enable ([12] of DW1)
101 * * Notify Enable ([8] of DW1)"
102 *
103 * From the Ivy Bridge PRM, volume 2 part 1, page 61:
104 *
105 * "One of the following must also be set (when CS stall is set):
106 *
107 * * Render Target Cache Flush Enable ([12] of DW1)
108 * * Depth Cache Flush Enable ([0] of DW1)
109 * * Stall at Pixel Scoreboard ([1] of DW1)
110 * * Depth Stall ([13] of DW1)
111 * * Post-Sync Operation ([13] of DW1)"
112 */
113 uint32_t bit_test = GEN6_PIPE_CONTROL_RENDER_CACHE_FLUSH |
114 GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH |
115 GEN6_PIPE_CONTROL_PIXEL_SCOREBOARD_STALL |
116 GEN6_PIPE_CONTROL_DEPTH_STALL;
117
118 /* post-sync op */
119 bit_test |= GEN6_PIPE_CONTROL_WRITE_IMM |
120 GEN6_PIPE_CONTROL_WRITE_PS_DEPTH_COUNT |
121 GEN6_PIPE_CONTROL_WRITE_TIMESTAMP;
122
123 if (ilo_dev_gen(builder->dev) == ILO_GEN(6))
124 bit_test |= GEN6_PIPE_CONTROL_NOTIFY_ENABLE;
125
126 assert(dw1 & bit_test);
127 }
128
129 if (dw1 & GEN6_PIPE_CONTROL_DEPTH_STALL) {
130 /*
131 * From the Sandy Bridge PRM, volume 2 part 1, page 73:
132 *
133 * "Following bits must be clear (when Depth Stall is set):
134 *
135 * * Render Target Cache Flush Enable ([12] of DW1)
136 * * Depth Cache Flush Enable ([0] of DW1)"
137 */
138 assert(!(dw1 & (GEN6_PIPE_CONTROL_RENDER_CACHE_FLUSH |
139 GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH)));
140 }
141
142 switch (dw1 & GEN6_PIPE_CONTROL_WRITE__MASK) {
143 case GEN6_PIPE_CONTROL_WRITE_PS_DEPTH_COUNT:
144 case GEN6_PIPE_CONTROL_WRITE_TIMESTAMP:
145 assert(!imm);
146 break;
147 default:
148 break;
149 }
150
151 assert(bo_offset % 8 == 0);
152
153 pos = ilo_builder_batch_pointer(builder, cmd_len, &dw);
154
155 dw[0] = GEN6_RENDER_CMD(3D, PIPE_CONTROL) | (cmd_len - 2);
156 dw[1] = dw1;
157
158 if (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) {
159 dw[4] = (uint32_t) imm;
160 dw[5] = (uint32_t) (imm >> 32);
161
162 if (bo) {
163 ilo_builder_batch_reloc64(builder, pos + 2,
164 bo, bo_offset, reloc_flags);
165 } else {
166 dw[2] = 0;
167 dw[3] = 0;
168 }
169
170 } else {
171 dw[3] = (uint32_t) imm;
172 dw[4] = (uint32_t) (imm >> 32);
173
174 if (bo) {
175 /*
176 * From the Sandy Bridge PRM, volume 1 part 3, page 19:
177 *
178 * "[DevSNB] PPGTT memory writes by MI_* (such as
179 * MI_STORE_DATA_IMM) and PIPE_CONTROL are not supported."
180 */
181 if (ilo_dev_gen(builder->dev) == ILO_GEN(6)) {
182 bo_offset |= GEN6_PIPE_CONTROL_DW2_USE_GGTT;
183 reloc_flags |= INTEL_RELOC_GGTT;
184 }
185
186 ilo_builder_batch_reloc(builder, pos + 2,
187 bo, bo_offset, reloc_flags);
188 } else {
189 dw[2] = 0;
190 }
191 }
192 }
193
194 static inline void
ilo_builder_batch_patch_sba(struct ilo_builder * builder)195 ilo_builder_batch_patch_sba(struct ilo_builder *builder)
196 {
197 const struct ilo_builder_writer *inst =
198 &builder->writers[ILO_BUILDER_WRITER_INSTRUCTION];
199
200 if (!builder->sba_instruction_pos)
201 return;
202
203 if (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) {
204 ilo_builder_batch_reloc64(builder, builder->sba_instruction_pos,
205 inst->bo,
206 builder->mocs << GEN8_SBA_MOCS__SHIFT | GEN6_SBA_ADDR_MODIFIED,
207 0);
208 } else {
209 ilo_builder_batch_reloc(builder, builder->sba_instruction_pos, inst->bo,
210 builder->mocs << GEN6_SBA_MOCS__SHIFT | GEN6_SBA_ADDR_MODIFIED,
211 0);
212 }
213 }
214
215 /**
216 * Add a STATE_BASE_ADDRESS to the batch buffer. The relocation entry for the
217 * instruction buffer is not added until ilo_builder_end() or next
218 * gen6_state_base_address().
219 */
220 static inline void
gen6_state_base_address(struct ilo_builder * builder,bool init_all)221 gen6_state_base_address(struct ilo_builder *builder, bool init_all)
222 {
223 const uint8_t cmd_len = 10;
224 const struct ilo_builder_writer *bat =
225 &builder->writers[ILO_BUILDER_WRITER_BATCH];
226 uint32_t *dw;
227 unsigned pos;
228
229 ILO_DEV_ASSERT(builder->dev, 6, 7.5);
230
231 pos = ilo_builder_batch_pointer(builder, cmd_len, &dw);
232
233 dw[0] = GEN6_RENDER_CMD(COMMON, STATE_BASE_ADDRESS) | (cmd_len - 2);
234 dw[1] = builder->mocs << GEN6_SBA_MOCS__SHIFT |
235 builder->mocs << GEN6_SBA_DW1_GENERAL_STATELESS_MOCS__SHIFT |
236 init_all;
237
238 ilo_builder_batch_reloc(builder, pos + 2, bat->bo,
239 builder->mocs << GEN6_SBA_MOCS__SHIFT | GEN6_SBA_ADDR_MODIFIED,
240 0);
241 ilo_builder_batch_reloc(builder, pos + 3, bat->bo,
242 builder->mocs << GEN6_SBA_MOCS__SHIFT | GEN6_SBA_ADDR_MODIFIED,
243 0);
244
245 dw[4] = builder->mocs << GEN6_SBA_MOCS__SHIFT | init_all;
246
247 /*
248 * Since the instruction writer has WRITER_FLAG_APPEND set, it is tempting
249 * not to set Instruction Base Address. The problem is that we do not know
250 * if the bo has been or will be moved by the kernel. We need a relocation
251 * entry because of that.
252 *
253 * And since we also set WRITER_FLAG_GROW, we have to wait until
254 * ilo_builder_end(), when the final bo is known, to add the relocation
255 * entry.
256 */
257 ilo_builder_batch_patch_sba(builder);
258 builder->sba_instruction_pos = pos + 5;
259
260 /* skip range checks */
261 dw[6] = init_all;
262 dw[7] = 0xfffff000 + init_all;
263 dw[8] = 0xfffff000 + init_all;
264 dw[9] = init_all;
265 }
266
267 static inline void
gen8_state_base_address(struct ilo_builder * builder,bool init_all)268 gen8_state_base_address(struct ilo_builder *builder, bool init_all)
269 {
270 const uint8_t cmd_len = 16;
271 const struct ilo_builder_writer *bat =
272 &builder->writers[ILO_BUILDER_WRITER_BATCH];
273 uint32_t *dw;
274 unsigned pos;
275
276 ILO_DEV_ASSERT(builder->dev, 8, 8);
277
278 pos = ilo_builder_batch_pointer(builder, cmd_len, &dw);
279
280 dw[0] = GEN6_RENDER_CMD(COMMON, STATE_BASE_ADDRESS) | (cmd_len - 2);
281 dw[1] = builder->mocs << GEN8_SBA_MOCS__SHIFT | init_all;
282 dw[2] = 0;
283 dw[3] = builder->mocs << GEN8_SBA_DW3_STATELESS_MOCS__SHIFT;
284 ilo_builder_batch_reloc64(builder, pos + 4, bat->bo,
285 builder->mocs << GEN8_SBA_MOCS__SHIFT | GEN6_SBA_ADDR_MODIFIED,
286 0);
287 ilo_builder_batch_reloc64(builder, pos + 6, bat->bo,
288 builder->mocs << GEN8_SBA_MOCS__SHIFT | GEN6_SBA_ADDR_MODIFIED,
289 0);
290 dw[8] = builder->mocs << GEN8_SBA_MOCS__SHIFT | init_all;
291 dw[9] = 0;
292
293 ilo_builder_batch_patch_sba(builder);
294 builder->sba_instruction_pos = pos + 10;
295
296 /* skip range checks */
297 dw[12] = 0xfffff000 + init_all;
298 dw[13] = 0xfffff000 + init_all;
299 dw[14] = 0xfffff000 + init_all;
300 dw[15] = 0xfffff000 + init_all;
301 }
302
303 #endif /* ILO_BUILDER_RENDER_H */
304