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 (at) 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 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 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 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 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 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 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