1 /* 2 * Copyright 2011 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 "compiler/nir/nir.h" 25 #include "brw_context.h" 26 #include "brw_state.h" 27 #include "brw_defines.h" 28 #include "brw_util.h" 29 #include "main/macros.h" 30 #include "main/fbobject.h" 31 #include "intel_batchbuffer.h" 32 33 static void 34 upload_sbe(struct brw_context *brw) 35 { 36 struct gl_context *ctx = &brw->ctx; 37 /* BRW_NEW_FS_PROG_DATA */ 38 const struct brw_wm_prog_data *wm_prog_data = 39 brw_wm_prog_data(brw->wm.base.prog_data); 40 uint32_t num_outputs = wm_prog_data->num_varying_inputs; 41 uint16_t attr_overrides[VARYING_SLOT_MAX]; 42 uint32_t urb_entry_read_length; 43 uint32_t urb_entry_read_offset; 44 uint32_t point_sprite_enables; 45 int sbe_cmd_length; 46 47 uint32_t dw1 = 48 GEN7_SBE_SWIZZLE_ENABLE | 49 num_outputs << GEN7_SBE_NUM_OUTPUTS_SHIFT; 50 uint32_t dw4 = 0; 51 uint32_t dw5 = 0; 52 53 /* _NEW_BUFFERS */ 54 bool render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer); 55 56 /* _NEW_POINT 57 * 58 * Window coordinates in an FBO are inverted, which means point 59 * sprite origin must be inverted. 60 */ 61 if ((ctx->Point.SpriteOrigin == GL_LOWER_LEFT) != render_to_fbo) 62 dw1 |= GEN6_SF_POINT_SPRITE_LOWERLEFT; 63 else 64 dw1 |= GEN6_SF_POINT_SPRITE_UPPERLEFT; 65 66 /* _NEW_POINT | _NEW_LIGHT | _NEW_PROGRAM, 67 * BRW_NEW_FS_PROG_DATA | BRW_NEW_FRAGMENT_PROGRAM | 68 * BRW_NEW_GS_PROG_DATA | BRW_NEW_PRIMITIVE | BRW_NEW_TES_PROG_DATA | 69 * BRW_NEW_VUE_MAP_GEOM_OUT 70 */ 71 calculate_attr_overrides(brw, attr_overrides, 72 &point_sprite_enables, 73 &urb_entry_read_length, 74 &urb_entry_read_offset); 75 76 /* Typically, the URB entry read length and offset should be programmed in 77 * 3DSTATE_VS and 3DSTATE_GS; SBE inherits it from the last active stage 78 * which produces geometry. However, we don't know the proper value until 79 * we call calculate_attr_overrides(). 80 * 81 * To fit with our existing code, we override the inherited values and 82 * specify it here directly, as we did on previous generations. 83 */ 84 dw1 |= 85 urb_entry_read_length << GEN7_SBE_URB_ENTRY_READ_LENGTH_SHIFT | 86 urb_entry_read_offset << GEN8_SBE_URB_ENTRY_READ_OFFSET_SHIFT | 87 GEN8_SBE_FORCE_URB_ENTRY_READ_LENGTH | 88 GEN8_SBE_FORCE_URB_ENTRY_READ_OFFSET; 89 90 if (brw->gen == 8) { 91 sbe_cmd_length = 4; 92 } else { 93 sbe_cmd_length = 6; 94 95 /* prepare the active component dwords */ 96 int input_index = 0; 97 for (int attr = 0; attr < VARYING_SLOT_MAX; attr++) { 98 if (!(brw->fragment_program->info.inputs_read & 99 BITFIELD64_BIT(attr))) { 100 continue; 101 } 102 103 assert(input_index < 32); 104 105 if (input_index < 16) 106 dw4 |= (GEN9_SBE_ACTIVE_COMPONENT_XYZW << (input_index << 1)); 107 else 108 dw5 |= (GEN9_SBE_ACTIVE_COMPONENT_XYZW << ((input_index - 16) << 1)); 109 110 ++input_index; 111 } 112 } 113 BEGIN_BATCH(sbe_cmd_length); 114 OUT_BATCH(_3DSTATE_SBE << 16 | (sbe_cmd_length - 2)); 115 OUT_BATCH(dw1); 116 OUT_BATCH(point_sprite_enables); 117 OUT_BATCH(wm_prog_data->flat_inputs); 118 if (sbe_cmd_length >= 6) { 119 OUT_BATCH(dw4); 120 OUT_BATCH(dw5); 121 } 122 ADVANCE_BATCH(); 123 124 BEGIN_BATCH(11); 125 OUT_BATCH(_3DSTATE_SBE_SWIZ << 16 | (11 - 2)); 126 127 /* Output DWords 1 through 8: */ 128 for (int i = 0; i < 8; i++) { 129 OUT_BATCH(attr_overrides[i * 2] | attr_overrides[i * 2 + 1] << 16); 130 } 131 132 OUT_BATCH(0); /* wrapshortest enables 0-7 */ 133 OUT_BATCH(0); /* wrapshortest enables 8-15 */ 134 ADVANCE_BATCH(); 135 } 136 137 const struct brw_tracked_state gen8_sbe_state = { 138 .dirty = { 139 .mesa = _NEW_BUFFERS | 140 _NEW_LIGHT | 141 _NEW_POINT | 142 _NEW_POLYGON | 143 _NEW_PROGRAM, 144 .brw = BRW_NEW_BLORP | 145 BRW_NEW_CONTEXT | 146 BRW_NEW_FRAGMENT_PROGRAM | 147 BRW_NEW_FS_PROG_DATA | 148 BRW_NEW_GS_PROG_DATA | 149 BRW_NEW_TES_PROG_DATA | 150 BRW_NEW_VUE_MAP_GEOM_OUT, 151 }, 152 .emit = upload_sbe, 153 }; 154 155 static void 156 upload_sf(struct brw_context *brw) 157 { 158 struct gl_context *ctx = &brw->ctx; 159 uint32_t dw1 = 0, dw2 = 0, dw3 = 0; 160 float point_size; 161 162 dw1 = GEN6_SF_STATISTICS_ENABLE; 163 164 if (brw->sf.viewport_transform_enable) 165 dw1 |= GEN6_SF_VIEWPORT_TRANSFORM_ENABLE; 166 167 /* _NEW_LINE */ 168 uint32_t line_width_u3_7 = brw_get_line_width(brw); 169 if (brw->gen >= 9 || brw->is_cherryview) { 170 dw1 |= line_width_u3_7 << GEN9_SF_LINE_WIDTH_SHIFT; 171 } else { 172 dw2 |= line_width_u3_7 << GEN6_SF_LINE_WIDTH_SHIFT; 173 } 174 175 if (ctx->Line.SmoothFlag) { 176 dw2 |= GEN6_SF_LINE_END_CAP_WIDTH_1_0; 177 } 178 179 /* _NEW_POINT - Clamp to ARB_point_parameters user limits */ 180 point_size = CLAMP(ctx->Point.Size, ctx->Point.MinSize, ctx->Point.MaxSize); 181 182 /* Clamp to the hardware limits and convert to fixed point */ 183 dw3 |= U_FIXED(CLAMP(point_size, 0.125f, 255.875f), 3); 184 185 /* _NEW_PROGRAM | _NEW_POINT, BRW_NEW_VUE_MAP_GEOM_OUT */ 186 if (use_state_point_size(brw)) 187 dw3 |= GEN6_SF_USE_STATE_POINT_WIDTH; 188 189 /* _NEW_POINT | _NEW_MULTISAMPLE */ 190 if ((ctx->Point.SmoothFlag || _mesa_is_multisample_enabled(ctx)) && 191 !ctx->Point.PointSprite) { 192 dw3 |= GEN8_SF_SMOOTH_POINT_ENABLE; 193 } 194 195 dw3 |= GEN6_SF_LINE_AA_MODE_TRUE; 196 197 /* _NEW_LIGHT */ 198 if (ctx->Light.ProvokingVertex != GL_FIRST_VERTEX_CONVENTION) { 199 dw3 |= (2 << GEN6_SF_TRI_PROVOKE_SHIFT) | 200 (2 << GEN6_SF_TRIFAN_PROVOKE_SHIFT) | 201 (1 << GEN6_SF_LINE_PROVOKE_SHIFT); 202 } else { 203 dw3 |= (1 << GEN6_SF_TRIFAN_PROVOKE_SHIFT); 204 } 205 206 BEGIN_BATCH(4); 207 OUT_BATCH(_3DSTATE_SF << 16 | (4 - 2)); 208 OUT_BATCH(dw1); 209 OUT_BATCH(dw2); 210 OUT_BATCH(dw3); 211 ADVANCE_BATCH(); 212 } 213 214 const struct brw_tracked_state gen8_sf_state = { 215 .dirty = { 216 .mesa = _NEW_LIGHT | 217 _NEW_PROGRAM | 218 _NEW_LINE | 219 _NEW_MULTISAMPLE | 220 _NEW_POINT, 221 .brw = BRW_NEW_BLORP | 222 BRW_NEW_CONTEXT | 223 BRW_NEW_VUE_MAP_GEOM_OUT, 224 }, 225 .emit = upload_sf, 226 }; 227 228 static void 229 upload_raster(struct brw_context *brw) 230 { 231 struct gl_context *ctx = &brw->ctx; 232 uint32_t dw1 = 0; 233 234 /* _NEW_BUFFERS */ 235 bool render_to_fbo = _mesa_is_user_fbo(brw->ctx.DrawBuffer); 236 237 /* _NEW_POLYGON */ 238 if (ctx->Polygon._FrontBit == render_to_fbo) 239 dw1 |= GEN8_RASTER_FRONT_WINDING_CCW; 240 241 if (ctx->Polygon.CullFlag) { 242 switch (ctx->Polygon.CullFaceMode) { 243 case GL_FRONT: 244 dw1 |= GEN8_RASTER_CULL_FRONT; 245 break; 246 case GL_BACK: 247 dw1 |= GEN8_RASTER_CULL_BACK; 248 break; 249 case GL_FRONT_AND_BACK: 250 dw1 |= GEN8_RASTER_CULL_BOTH; 251 break; 252 default: 253 unreachable("not reached"); 254 } 255 } else { 256 dw1 |= GEN8_RASTER_CULL_NONE; 257 } 258 259 /* _NEW_POINT */ 260 if (ctx->Point.SmoothFlag) 261 dw1 |= GEN8_RASTER_SMOOTH_POINT_ENABLE; 262 263 if (_mesa_is_multisample_enabled(ctx)) 264 dw1 |= GEN8_RASTER_API_MULTISAMPLE_ENABLE; 265 266 if (ctx->Polygon.OffsetFill) 267 dw1 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_SOLID; 268 269 if (ctx->Polygon.OffsetLine) 270 dw1 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_WIREFRAME; 271 272 if (ctx->Polygon.OffsetPoint) 273 dw1 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_POINT; 274 275 switch (ctx->Polygon.FrontMode) { 276 case GL_FILL: 277 dw1 |= GEN6_SF_FRONT_SOLID; 278 break; 279 case GL_LINE: 280 dw1 |= GEN6_SF_FRONT_WIREFRAME; 281 break; 282 case GL_POINT: 283 dw1 |= GEN6_SF_FRONT_POINT; 284 break; 285 286 default: 287 unreachable("not reached"); 288 } 289 290 switch (ctx->Polygon.BackMode) { 291 case GL_FILL: 292 dw1 |= GEN6_SF_BACK_SOLID; 293 break; 294 case GL_LINE: 295 dw1 |= GEN6_SF_BACK_WIREFRAME; 296 break; 297 case GL_POINT: 298 dw1 |= GEN6_SF_BACK_POINT; 299 break; 300 default: 301 unreachable("not reached"); 302 } 303 304 /* _NEW_LINE */ 305 if (ctx->Line.SmoothFlag) 306 dw1 |= GEN8_RASTER_LINE_AA_ENABLE; 307 308 /* _NEW_SCISSOR */ 309 if (ctx->Scissor.EnableFlags) 310 dw1 |= GEN8_RASTER_SCISSOR_ENABLE; 311 312 /* _NEW_TRANSFORM */ 313 if (!ctx->Transform.DepthClamp) { 314 if (brw->gen >= 9) { 315 dw1 |= GEN9_RASTER_VIEWPORT_Z_NEAR_CLIP_TEST_ENABLE | 316 GEN9_RASTER_VIEWPORT_Z_FAR_CLIP_TEST_ENABLE; 317 } else { 318 dw1 |= GEN8_RASTER_VIEWPORT_Z_CLIP_TEST_ENABLE; 319 } 320 } 321 322 /* BRW_NEW_CONSERVATIVE_RASTERIZATION */ 323 if (ctx->IntelConservativeRasterization) { 324 if (brw->gen >= 9) 325 dw1 |= GEN9_RASTER_CONSERVATIVE_RASTERIZATION_ENABLE; 326 } 327 328 BEGIN_BATCH(5); 329 OUT_BATCH(_3DSTATE_RASTER << 16 | (5 - 2)); 330 OUT_BATCH(dw1); 331 OUT_BATCH_F(ctx->Polygon.OffsetUnits * 2); /* constant. copied from gen4 */ 332 OUT_BATCH_F(ctx->Polygon.OffsetFactor); /* scale */ 333 OUT_BATCH_F(ctx->Polygon.OffsetClamp); /* global depth offset clamp */ 334 ADVANCE_BATCH(); 335 } 336 337 const struct brw_tracked_state gen8_raster_state = { 338 .dirty = { 339 .mesa = _NEW_BUFFERS | 340 _NEW_LINE | 341 _NEW_MULTISAMPLE | 342 _NEW_POINT | 343 _NEW_POLYGON | 344 _NEW_SCISSOR | 345 _NEW_TRANSFORM, 346 .brw = BRW_NEW_BLORP | 347 BRW_NEW_CONTEXT | 348 BRW_NEW_CONSERVATIVE_RASTERIZATION, 349 }, 350 .emit = upload_raster, 351 }; 352