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
38static inline void
39gen6_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
54static inline void
55gen6_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
78static inline void
79gen6_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
194static inline void
195ilo_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 */
220static inline void
221gen6_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
267static inline void
268gen8_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