• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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