blob: 22071b60c61a8eb143a5bf44eb1c5c50894a2467 [file] [log] [blame]
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -06001/*
2 * XGL
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
Courtney Goeltzenleuchter42509992014-08-21 17:33:46 -060025#include "shader.h"
Chia-I Wued833872014-08-23 17:00:35 +080026#include "pipeline_priv.h"
Courtney Goeltzenleuchterd85c1d62014-08-27 14:04:53 -060027#include "genhw/genhw.h"
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -060028#include "genhw/gen_render_3d.xml.h"
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060029
Chia-I Wu3efef432014-08-28 15:00:16 +080030struct intel_pipeline_builder {
31 const struct intel_gpu *gpu;
32
33 XGL_GRAPHICS_PIPELINE_CREATE_INFO graphics;
34 XGL_PIPELINE_IA_STATE_CREATE_INFO ia;
35 XGL_PIPELINE_DB_STATE_CREATE_INFO db;
36 XGL_PIPELINE_CB_STATE cb;
37 XGL_PIPELINE_RS_STATE_CREATE_INFO rs;
38 XGL_PIPELINE_TESS_STATE_CREATE_INFO tess;
39 XGL_PIPELINE_SHADER vs;
40 XGL_PIPELINE_SHADER tcs;
41 XGL_PIPELINE_SHADER tes;
42 XGL_PIPELINE_SHADER gs;
43 XGL_PIPELINE_SHADER fs;
44
45 XGL_COMPUTE_PIPELINE_CREATE_INFO compute;
46 XGL_PIPELINE_SHADER cs;
47};
48
49struct intel_pipeline_builder_create_info {
50 XGL_STRUCTURE_TYPE struct_type;
51 XGL_VOID *next;
52};
53
Courtney Goeltzenleuchter814cd292014-08-28 13:16:27 -060054static uint32_t *pipeline_cmd_ptr(struct intel_pipeline *pipeline, int cmd_len)
55{
56 uint32_t *ptr;
57
58 assert(pipeline->cmd_len + cmd_len < INTEL_PSO_CMD_ENTRIES);
59 ptr = &pipeline->cmds[pipeline->cmd_len];
60 pipeline->cmd_len += cmd_len;
61 return ptr;
62}
63
Chia-I Wu3efef432014-08-28 15:00:16 +080064static XGL_RESULT pipeline_ia_state(struct intel_pipeline *pipeline,
65 const XGL_PIPELINE_IA_STATE_CREATE_INFO* ia_state)
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060066{
Courtney Goeltzenleuchter42509992014-08-21 17:33:46 -060067 pipeline->ia_state = *ia_state;
68
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060069 if (ia_state->provokingVertex == XGL_PROVOKING_VERTEX_FIRST) {
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -060070 pipeline->provoking_vertex_tri = 0;
71 pipeline->provoking_vertex_trifan = 1;
72 pipeline->provoking_vertex_line = 0;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060073 } else {
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -060074 pipeline->provoking_vertex_tri = 2;
75 pipeline->provoking_vertex_trifan = 2;
76 pipeline->provoking_vertex_line = 1;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060077 }
78
79 switch (ia_state->topology) {
80 case XGL_TOPOLOGY_POINT_LIST:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -060081 pipeline->prim_type = GEN6_3DPRIM_POINTLIST;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060082 break;
83 case XGL_TOPOLOGY_LINE_LIST:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -060084 pipeline->prim_type = GEN6_3DPRIM_LINELIST;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060085 break;
86 case XGL_TOPOLOGY_LINE_STRIP:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -060087 pipeline->prim_type = GEN6_3DPRIM_LINESTRIP;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060088 break;
89 case XGL_TOPOLOGY_TRIANGLE_LIST:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -060090 pipeline->prim_type = GEN6_3DPRIM_TRILIST;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060091 break;
92 case XGL_TOPOLOGY_TRIANGLE_STRIP:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -060093 pipeline->prim_type = GEN6_3DPRIM_TRISTRIP;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060094 break;
95 case XGL_TOPOLOGY_RECT_LIST:
96 /*
97 * TODO: Rect lists are special in XGL, do we need to do
98 * something special here?
99 * XGL Guide:
100 * The rectangle list is a special geometry primitive type
101 * that can be used for implementing post-processing techniques
102 * or efficient copy operations. There are some special limitations
103 * for rectangle primitives. They cannot be clipped, must
104 * be axis aligned and cannot have depth gradient.
105 * Failure to comply with these restrictions results in
106 * undefined rendering results.
107 */
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600108 pipeline->prim_type = GEN6_3DPRIM_RECTLIST;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600109 break;
110 case XGL_TOPOLOGY_QUAD_LIST:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600111 pipeline->prim_type = GEN6_3DPRIM_QUADLIST;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600112 break;
113 case XGL_TOPOLOGY_QUAD_STRIP:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600114 pipeline->prim_type = GEN6_3DPRIM_QUADSTRIP;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600115 break;
116 case XGL_TOPOLOGY_LINE_LIST_ADJ:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600117 pipeline->prim_type = GEN6_3DPRIM_LINELIST_ADJ;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600118 break;
119 case XGL_TOPOLOGY_LINE_STRIP_ADJ:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600120 pipeline->prim_type = GEN6_3DPRIM_LINESTRIP_ADJ;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600121 break;
122 case XGL_TOPOLOGY_TRIANGLE_LIST_ADJ:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600123 pipeline->prim_type = GEN6_3DPRIM_TRILIST_ADJ;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600124 break;
125 case XGL_TOPOLOGY_TRIANGLE_STRIP_ADJ:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600126 pipeline->prim_type = GEN6_3DPRIM_TRISTRIP_ADJ;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600127 break;
128 case XGL_TOPOLOGY_PATCH:
129 // TODO: implement something here
130 break;
131 default:
132 return XGL_ERROR_BAD_PIPELINE_DATA;
133 }
134
135 if (ia_state->primitiveRestartEnable) {
136 pipeline->primitive_restart = true;
137 pipeline->primitive_restart_index = ia_state->primitiveRestartIndex;
138 } else {
139 pipeline->primitive_restart = false;
140 }
141
142 if (ia_state->disableVertexReuse) {
143 // TODO: What do we do to disable vertex reuse?
144 }
145
146 return XGL_SUCCESS;
147}
148
Chia-I Wu3efef432014-08-28 15:00:16 +0800149static XGL_RESULT pipeline_rs_state(struct intel_pipeline *pipeline,
150 const XGL_PIPELINE_RS_STATE_CREATE_INFO* rs_state)
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600151{
152 pipeline->depthClipEnable = rs_state->depthClipEnable;
153 pipeline->rasterizerDiscardEnable = rs_state->rasterizerDiscardEnable;
154 pipeline->pointSize = rs_state->pointSize;
155 return XGL_SUCCESS;
156}
157
Courtney Goeltzenleuchter42509992014-08-21 17:33:46 -0600158static void pipeline_destroy(struct intel_obj *obj)
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600159{
160 struct intel_pipeline *pipeline = intel_pipeline_from_obj(obj);
161
Courtney Goeltzenleuchterd85c1d62014-08-27 14:04:53 -0600162 if (pipeline->active_shaders & SHADER_VERTEX_FLAG) {
Chia-I Wu282d3bc2014-08-28 15:36:44 +0800163 icd_free(pipeline->intel_vs.pCode);
Courtney Goeltzenleuchterd85c1d62014-08-27 14:04:53 -0600164 }
165 if (pipeline->active_shaders & SHADER_GEOMETRY_FLAG) {
Chia-I Wu282d3bc2014-08-28 15:36:44 +0800166 icd_free(pipeline->gs.pCode);
Courtney Goeltzenleuchterd85c1d62014-08-27 14:04:53 -0600167 }
168 if (pipeline->active_shaders & SHADER_FRAGMENT_FLAG) {
Chia-I Wu282d3bc2014-08-28 15:36:44 +0800169 icd_free(pipeline->intel_fs.pCode);
Courtney Goeltzenleuchterd85c1d62014-08-27 14:04:53 -0600170 }
171 if (pipeline->active_shaders & SHADER_TESS_CONTROL_FLAG) {
Chia-I Wu282d3bc2014-08-28 15:36:44 +0800172 icd_free(pipeline->tess_control.pCode);
Courtney Goeltzenleuchterd85c1d62014-08-27 14:04:53 -0600173 }
174 if (pipeline->active_shaders & SHADER_TESS_EVAL_FLAG) {
Chia-I Wu282d3bc2014-08-28 15:36:44 +0800175 icd_free(pipeline->tess_eval.pCode);
Courtney Goeltzenleuchterd85c1d62014-08-27 14:04:53 -0600176 }
177
Chia-I Wued833872014-08-23 17:00:35 +0800178 if (pipeline->vs_rmap)
179 intel_rmap_destroy(pipeline->vs_rmap);
180 if (pipeline->fs_rmap)
181 intel_rmap_destroy(pipeline->fs_rmap);
182
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600183 intel_base_destroy(&pipeline->obj.base);
184}
185
Chia-I Wu3efef432014-08-28 15:00:16 +0800186static XGL_RESULT pipeline_shader(struct intel_pipeline *pipeline,
187 const XGL_PIPELINE_SHADER *info)
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600188{
Chia-I Wu3efef432014-08-28 15:00:16 +0800189 struct intel_shader *sh = intel_shader(info->shader);
190 void *kernel;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600191
Chia-I Wu3efef432014-08-28 15:00:16 +0800192 // TODO: process shader object and include in pipeline
193 // For now that processing is simply a copy so that the app
194 // can destroy the original shader object after pipeline creation.
195 kernel = icd_alloc(sh->ir->size, 0, XGL_SYSTEM_ALLOC_INTERNAL_SHADER);
196 if (!kernel)
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600197 return XGL_ERROR_OUT_OF_MEMORY;
Chia-I Wu3efef432014-08-28 15:00:16 +0800198
199 switch (info->stage) {
200 case XGL_SHADER_STAGE_VERTEX:
201 /*
202 * TODO: What should we do here?
203 * shader_state (XGL_PIPELINE_SHADER) contains links
204 * to application memory in the pLinkConstBufferInfo and
205 * it's pBufferData pointers. Do we need to bring all that
206 * into the driver or is it okay to rely on those references
207 * holding good data. In OpenGL we'd make a driver copy. Not
208 * as clear for XGL.
209 * For now, use the app pointers.
210 */
211 pipeline->vs = *info;
212 pipeline->intel_vs.pCode = kernel;
213 pipeline->intel_vs.codeSize = sh->ir->size;
214 pipeline->active_shaders |= SHADER_VERTEX_FLAG;
215 pipeline->vs_rmap = intel_rmap_create(pipeline->dev,
216 &info->descriptorSetMapping[0],
217 &info->dynamicMemoryViewMapping, 0);
218 if (!pipeline->vs_rmap) {
219 icd_free(kernel);
220 return XGL_ERROR_OUT_OF_MEMORY;
221 }
222 break;
223 case XGL_SHADER_STAGE_GEOMETRY:
224 pipeline->gs.pCode = kernel;
225 pipeline->gs.codeSize = sh->ir->size;
226 pipeline->active_shaders |= SHADER_GEOMETRY_FLAG;
227 break;
228 case XGL_SHADER_STAGE_FRAGMENT:
229 pipeline->fs = *info;
230 pipeline->intel_fs.pCode = kernel;
231 pipeline->intel_fs.codeSize = sh->ir->size;
232 pipeline->active_shaders |= SHADER_FRAGMENT_FLAG;
233 /* assuming one RT; need to parse the shader */
234 pipeline->fs_rmap = intel_rmap_create(pipeline->dev,
235 &info->descriptorSetMapping[0],
236 &info->dynamicMemoryViewMapping, 1);
237 if (!pipeline->fs_rmap) {
238 icd_free(kernel);
239 return XGL_ERROR_OUT_OF_MEMORY;
240 }
241 break;
242 case XGL_SHADER_STAGE_TESS_CONTROL:
243 pipeline->tess_control.pCode = kernel;
244 pipeline->tess_control.codeSize = sh->ir->size;
245 pipeline->active_shaders |= SHADER_TESS_CONTROL_FLAG;
246 break;
247 case XGL_SHADER_STAGE_TESS_EVALUATION:
248 pipeline->tess_eval.pCode = kernel;
249 pipeline->tess_eval.codeSize = sh->ir->size;
250 pipeline->active_shaders |= SHADER_TESS_EVAL_FLAG;
251 break;
252 case XGL_SHADER_STAGE_COMPUTE:
253 pipeline->compute.pCode = kernel;
254 pipeline->compute.codeSize = sh->ir->size;
255 pipeline->active_shaders |= SHADER_COMPUTE_FLAG;
256 break;
257 default:
258 assert(!"unknown shader stage");
259 break;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600260 }
261
Chia-I Wu3efef432014-08-28 15:00:16 +0800262 return XGL_SUCCESS;
263}
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600264
Chia-I Wu3efef432014-08-28 15:00:16 +0800265static XGL_RESULT builder_validate(const struct intel_pipeline_builder *builder,
266 const struct intel_pipeline *pipeline)
267{
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600268 /*
269 * Validate required elements
270 */
271 if (!(pipeline->active_shaders & SHADER_VERTEX_FLAG)) {
272 // TODO: Log debug message: Vertex Shader required.
Chia-I Wu3efef432014-08-28 15:00:16 +0800273 return XGL_ERROR_BAD_PIPELINE_DATA;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600274 }
275
276 /*
277 * Tessalation control and evaluation have to both have a shader defined or
278 * neither should have a shader defined.
279 */
280 if (((pipeline->active_shaders & SHADER_TESS_CONTROL_FLAG) == 0) !=
281 ((pipeline->active_shaders & SHADER_TESS_EVAL_FLAG) == 0) ) {
282 // TODO: Log debug message: Both Tess control and Tess eval are required to use tessalation
Chia-I Wu3efef432014-08-28 15:00:16 +0800283 return XGL_ERROR_BAD_PIPELINE_DATA;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600284 }
285
286 if ((pipeline->active_shaders & SHADER_COMPUTE_FLAG) &&
287 (pipeline->active_shaders & (SHADER_VERTEX_FLAG | SHADER_TESS_CONTROL_FLAG |
288 SHADER_TESS_EVAL_FLAG | SHADER_GEOMETRY_FLAG |
289 SHADER_FRAGMENT_FLAG))) {
290 // TODO: Log debug message: Can only specify compute shader when doing compute
Chia-I Wu3efef432014-08-28 15:00:16 +0800291 return XGL_ERROR_BAD_PIPELINE_DATA;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600292 }
293
294 /*
Courtney Goeltzenleuchter42509992014-08-21 17:33:46 -0600295 * XGL_TOPOLOGY_PATCH primitive topology is only valid for tessellation pipelines.
296 * Mismatching primitive topology and tessellation fails graphics pipeline creation.
297 */
298 if (pipeline->active_shaders & (SHADER_TESS_CONTROL_FLAG | SHADER_TESS_EVAL_FLAG) &&
299 (pipeline->ia_state.topology != XGL_TOPOLOGY_PATCH)) {
300 // TODO: Log debug message: Invalid topology used with tessalation shader.
Chia-I Wu3efef432014-08-28 15:00:16 +0800301 return XGL_ERROR_BAD_PIPELINE_DATA;
Courtney Goeltzenleuchter42509992014-08-21 17:33:46 -0600302 }
303
304 if ((pipeline->ia_state.topology == XGL_TOPOLOGY_PATCH) &&
305 (pipeline->active_shaders & ~(SHADER_TESS_CONTROL_FLAG | SHADER_TESS_EVAL_FLAG))) {
306 // TODO: Log debug message: Cannot use TOPOLOGY_PATCH on non-tessalation shader.
Chia-I Wu3efef432014-08-28 15:00:16 +0800307 return XGL_ERROR_BAD_PIPELINE_DATA;
Courtney Goeltzenleuchter42509992014-08-21 17:33:46 -0600308 }
309
Chia-I Wu3efef432014-08-28 15:00:16 +0800310 return XGL_SUCCESS;
311}
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600312
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800313static void builder_build_urb_alloc_gen6(struct intel_pipeline_builder *builder,
314 struct intel_pipeline *pipeline)
315{
316 const int urb_size = ((builder->gpu->gt == 2) ? 64 : 32) * 1024;
317 const struct intel_shader *vs = intel_shader(builder->vs.shader);
318 const struct intel_shader *gs = intel_shader(builder->gs.shader);
319 int vs_entry_size, gs_entry_size;
320 int vs_size, gs_size;
321
322 INTEL_GPU_ASSERT(builder->gpu, 6, 6);
323
324 vs_entry_size = ((vs->in_count >= vs->out_count) ?
325 vs->in_count : vs->out_count);
326 gs_entry_size = (gs) ? gs->out_count : 0;
327
328 /* in bytes */
329 vs_entry_size *= sizeof(float) * 4;
330 gs_entry_size *= sizeof(float) * 4;
331
332 if (gs) {
333 vs_size = urb_size / 2;
334 gs_size = vs_size;
335 } else {
336 vs_size = urb_size;
337 gs_size = 0;
338 }
339
340 /* 3DSTATE_URB */
341 {
342 const uint8_t cmd_len = 3;
343 const uint32_t dw0 = GEN6_RENDER_CMD(3D, 3DSTATE_URB) |
344 (cmd_len - 2);
345 int vs_alloc_size, gs_alloc_size;
346 int vs_entry_count, gs_entry_count;
347 uint32_t *dw;
348
349 /* in 1024-bit rows */
350 vs_alloc_size = (vs_entry_size + 128 - 1) / 128;
351 gs_alloc_size = (gs_entry_size + 128 - 1) / 128;
352
353 /* valid range is [1, 5] */
354 if (!vs_alloc_size)
355 vs_alloc_size = 1;
356 if (!gs_alloc_size)
357 gs_alloc_size = 1;
358 assert(vs_alloc_size <= 5 && gs_alloc_size <= 5);
359
360 /* valid range is [24, 256], multiples of 4 */
361 vs_entry_count = (vs_size / 128 / vs_alloc_size) & ~3;
362 if (vs_entry_count > 256)
363 vs_entry_count = 256;
364 assert(vs_entry_count >= 24);
365
366 /* valid range is [0, 256], multiples of 4 */
367 gs_entry_count = (gs_size / 128 / gs_alloc_size) & ~3;
368 if (gs_entry_count > 256)
369 gs_entry_count = 256;
370
Courtney Goeltzenleuchter814cd292014-08-28 13:16:27 -0600371 dw = pipeline_cmd_ptr(pipeline, cmd_len);
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800372
373 dw[0] = dw0;
374 dw[1] = (vs_alloc_size - 1) << GEN6_URB_DW1_VS_ENTRY_SIZE__SHIFT |
375 vs_entry_count << GEN6_URB_DW1_VS_ENTRY_COUNT__SHIFT;
376 dw[2] = gs_entry_count << GEN6_URB_DW2_GS_ENTRY_COUNT__SHIFT |
377 (gs_alloc_size - 1) << GEN6_URB_DW2_GS_ENTRY_SIZE__SHIFT;
378 }
379}
380
381static void builder_build_urb_alloc_gen7(struct intel_pipeline_builder *builder,
382 struct intel_pipeline *pipeline)
383{
384 const int urb_size = ((builder->gpu->gt == 3) ? 512 :
385 (builder->gpu->gt == 2) ? 256 : 128) * 1024;
386 const struct intel_shader *vs = intel_shader(builder->vs.shader);
387 const struct intel_shader *gs = intel_shader(builder->gs.shader);
388 /* some space is reserved for PCBs */
389 int urb_offset = ((builder->gpu->gt == 3) ? 32 : 16) * 1024;
390 int vs_entry_size, gs_entry_size;
391 int vs_size, gs_size;
392
393 INTEL_GPU_ASSERT(builder->gpu, 7, 7.5);
394
395 vs_entry_size = ((vs->in_count >= vs->out_count) ?
396 vs->in_count : vs->out_count);
397 gs_entry_size = (gs) ? gs->out_count : 0;
398
399 /* in bytes */
400 vs_entry_size *= sizeof(float) * 4;
401 gs_entry_size *= sizeof(float) * 4;
402
403 if (gs) {
404 vs_size = (urb_size - urb_offset) / 2;
405 gs_size = vs_size;
406 } else {
407 vs_size = urb_size - urb_offset;
408 gs_size = 0;
409 }
410
411 /* 3DSTATE_URB_* */
412 {
413 const uint8_t cmd_len = 2;
414 int vs_alloc_size, gs_alloc_size;
415 int vs_entry_count, gs_entry_count;
416 uint32_t *dw;
417
418 /* in 512-bit rows */
419 vs_alloc_size = (vs_entry_size + 64 - 1) / 64;
420 gs_alloc_size = (gs_entry_size + 64 - 1) / 64;
421
422 if (!vs_alloc_size)
423 vs_alloc_size = 1;
424 if (!gs_alloc_size)
425 gs_alloc_size = 1;
426
427 /* avoid performance decrease due to banking */
428 if (vs_alloc_size == 5)
429 vs_alloc_size = 6;
430
431 /* in multiples of 8 */
432 vs_entry_count = (vs_size / 64 / vs_alloc_size) & ~7;
433 assert(vs_entry_count >= 32);
434
435 gs_entry_count = (gs_size / 64 / gs_alloc_size) & ~7;
436
437 if (intel_gpu_gen(builder->gpu) >= INTEL_GEN(7.5)) {
438 const int max_vs_entry_count =
439 (builder->gpu->gt >= 2) ? 1644 : 640;
440 const int max_gs_entry_count =
441 (builder->gpu->gt >= 2) ? 640 : 256;
442 if (vs_entry_count >= max_vs_entry_count)
443 vs_entry_count = max_vs_entry_count;
444 if (gs_entry_count >= max_gs_entry_count)
445 gs_entry_count = max_gs_entry_count;
446 } else {
447 const int max_vs_entry_count =
448 (builder->gpu->gt == 2) ? 704 : 512;
449 const int max_gs_entry_count =
450 (builder->gpu->gt == 2) ? 320 : 192;
451 if (vs_entry_count >= max_vs_entry_count)
452 vs_entry_count = max_vs_entry_count;
453 if (gs_entry_count >= max_gs_entry_count)
454 gs_entry_count = max_gs_entry_count;
455 }
456
Courtney Goeltzenleuchter814cd292014-08-28 13:16:27 -0600457 dw = pipeline_cmd_ptr(pipeline, cmd_len*4);
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800458 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_URB_VS) | (cmd_len - 2);
459 dw[1] = (urb_offset / 8192) << GEN7_URB_ANY_DW1_OFFSET__SHIFT |
460 (vs_alloc_size - 1) << GEN7_URB_ANY_DW1_ENTRY_SIZE__SHIFT |
461 vs_entry_count;
462
463 dw += 2;
464 if (gs_size)
465 urb_offset += vs_size;
466 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_URB_GS) | (cmd_len - 2);
467 dw[1] = (urb_offset / 8192) << GEN7_URB_ANY_DW1_OFFSET__SHIFT |
468 (gs_alloc_size - 1) << GEN7_URB_ANY_DW1_ENTRY_SIZE__SHIFT |
469 gs_entry_count;
470
471 dw += 2;
472 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_URB_HS) | (cmd_len - 2);
473 dw[1] = (urb_offset / 8192) << GEN7_URB_ANY_DW1_OFFSET__SHIFT;
474
475 dw += 2;
476 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_URB_DS) | (cmd_len - 2);
477 dw[1] = (urb_offset / 8192) << GEN7_URB_ANY_DW1_OFFSET__SHIFT;
478 }
479}
480
Courtney Goeltzenleuchterb2867702014-08-28 17:44:05 -0600481static void builder_build_push_const_alloc_gen7(struct intel_pipeline_builder *builder,
482 struct intel_pipeline *p)
483{
484 const uint8_t cmd_len = 2;
485 uint32_t offset = 0;
486 uint32_t size = 8192;
487 uint32_t *dw;
488 int end;
489
490 INTEL_GPU_ASSERT(builder->gpu, 7, 7);
491
492 /*
493 * From the Ivy Bridge PRM, volume 2 part 1, page 68:
494 *
495 * "(A table that says the maximum size of each constant buffer is
496 * 16KB")
497 *
498 * From the Ivy Bridge PRM, volume 2 part 1, page 115:
499 *
500 * "The sum of the Constant Buffer Offset and the Constant Buffer Size
501 * may not exceed the maximum value of the Constant Buffer Size."
502 *
503 * Thus, the valid range of buffer end is [0KB, 16KB].
504 */
505 end = (offset + size) / 1024;
506 if (end > 16) {
507 assert(!"invalid constant buffer end");
508 end = 16;
509 }
510
511 /* the valid range of buffer offset is [0KB, 15KB] */
512 offset = (offset + 1023) / 1024;
513 if (offset > 15) {
514 assert(!"invalid constant buffer offset");
515 offset = 15;
516 }
517
518 if (offset > end) {
519 assert(!size);
520 offset = end;
521 }
522
523 /* the valid range of buffer size is [0KB, 15KB] */
524 size = end - offset;
525 if (size > 15) {
526 assert(!"invalid constant buffer size");
527 size = 15;
528 }
529
530 dw = pipeline_cmd_ptr(p, cmd_len * 5);
531 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_PUSH_CONSTANT_ALLOC_VS) | (cmd_len - 2);
532 dw[1] = offset << GEN7_PCB_ALLOC_ANY_DW1_OFFSET__SHIFT |
533 size << GEN7_PCB_ALLOC_ANY_DW1_SIZE__SHIFT;
534
535 dw += 2;
536 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_PUSH_CONSTANT_ALLOC_PS) | (cmd_len - 2);
537 dw[1] = size << GEN7_PCB_ALLOC_ANY_DW1_OFFSET__SHIFT |
538 size << GEN7_PCB_ALLOC_ANY_DW1_SIZE__SHIFT;
539
540 dw += 2;
541 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_PUSH_CONSTANT_ALLOC_HS) | (cmd_len - 2);
542 dw[1] = 0 << GEN7_PCB_ALLOC_ANY_DW1_OFFSET__SHIFT |
543 0 << GEN7_PCB_ALLOC_ANY_DW1_SIZE__SHIFT;
544
545 dw += 2;
546 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_PUSH_CONSTANT_ALLOC_DS) | (cmd_len - 2);
547 dw[1] = 0 << GEN7_PCB_ALLOC_ANY_DW1_OFFSET__SHIFT |
548 0 << GEN7_PCB_ALLOC_ANY_DW1_SIZE__SHIFT;
549
550 dw += 2;
551 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_PUSH_CONSTANT_ALLOC_GS) | (cmd_len - 2);
552 dw[1] = 0 << GEN7_PCB_ALLOC_ANY_DW1_OFFSET__SHIFT |
553 0 << GEN7_PCB_ALLOC_ANY_DW1_SIZE__SHIFT;
554 /*
555 * From the Ivy Bridge PRM, volume 2 part 1, page 292:
556 *
557 * "A PIPE_CONTOL command with the CS Stall bit set must be programmed
558 * in the ring after this instruction
559 * (3DSTATE_PUSH_CONSTANT_ALLOC_PS)."
560 */
561 p->post_pso_wa_flags |= GEN7_WA_MULTISAMPLE_FLUSH;
562 // gen7_wa_pipe_control_cs_stall(p, true, true);
563 // looks equivalent to: gen6_wa_wm_multisample_flush - this does more
564 // than the documentation seems to imply
565}
566
567static void
568gen7_emit_3dstate_constant(struct intel_pipeline_builder *builder,
569 struct intel_pipeline *pipeline,
570 int subop,
571 const uint32_t *bufs, const int *sizes,
572 int num_bufs)
573{
574 const uint8_t cmd_len = 7;
575 const uint32_t cmd = GEN6_RENDER_TYPE_RENDER |
576 GEN6_RENDER_SUBTYPE_3D |
577 subop |
578 (cmd_len - 2);
579 uint32_t *dw = pipeline_cmd_ptr(pipeline, cmd_len);
580 int total_read_length, i;
581
582 INTEL_GPU_ASSERT(builder->gpu, 7, 7);
583
584 /* VS, HS, DS, GS, and PS variants */
585 assert(subop >= GEN6_RENDER_OPCODE_3DSTATE_CONSTANT_VS &&
586 subop <= GEN7_RENDER_OPCODE_3DSTATE_CONSTANT_DS &&
587 subop != GEN6_RENDER_OPCODE_3DSTATE_SAMPLE_MASK);
588
589 assert(num_bufs <= 4);
590
591 dw[0] = cmd;
592 dw++;
593 dw[0] = 0;
594 dw[1] = 0;
595
596 total_read_length = 0;
597 for (i = 0; i < 4; i++) {
598 int read_len;
599
600 /*
601 * From the Ivy Bridge PRM, volume 2 part 1, page 112:
602 *
603 * "Constant buffers must be enabled in order from Constant Buffer 0
604 * to Constant Buffer 3 within this command. For example, it is
605 * not allowed to enable Constant Buffer 1 by programming a
606 * non-zero value in the VS Constant Buffer 1 Read Length without a
607 * non-zero value in VS Constant Buffer 0 Read Length."
608 */
609 if (i >= num_bufs || !sizes[i]) {
610 for (; i < 4; i++) {
611 assert(i >= num_bufs || !sizes[i]);
612 dw[2 + i] = 0;
613 }
614 break;
615 }
616
617 /* read lengths are in 256-bit units */
618 read_len = (sizes[i] + 31) / 32;
619 /* the lower 5 bits are used for memory object control state */
620 assert(bufs[i] % 32 == 0);
621
622 dw[i / 2] |= read_len << ((i % 2) ? 16 : 0);
623 dw[2 + i] = bufs[i];
624
625 total_read_length += read_len;
626 }
627
628 /*
629 * From the Ivy Bridge PRM, volume 2 part 1, page 113:
630 *
631 * "The sum of all four read length fields must be less than or equal
632 * to the size of 64"
633 */
634 assert(total_read_length <= 64);
635}
636
637static void
638gen7_emit_3dstate_pointer(struct intel_pipeline_builder *builder,
639 struct intel_pipeline *p,
640 int subop, uint32_t pointer)
641{
642 const uint8_t cmd_len = 2;
643 const uint32_t dw0 = GEN6_RENDER_TYPE_RENDER |
644 GEN6_RENDER_SUBTYPE_3D |
645 subop |
646 (cmd_len - 2);
647 uint32_t *dw;
648
649 INTEL_GPU_ASSERT(builder->gpu, 7, 7);
650
651 dw = pipeline_cmd_ptr(p, cmd_len);
652 dw[0] = dw0;
653 dw[1] = pointer;
654}
655
656static void gen7_pipeline_gs(struct intel_pipeline_builder *builder,
657 struct intel_pipeline *pipeline)
658{
659 /* 3DSTATE_CONSTANT_GS and 3DSTATE_GS */
660 gen7_emit_3dstate_constant(builder, pipeline,
661 GEN6_RENDER_OPCODE_3DSTATE_CONSTANT_GS,
662 0, 0, 0);
663 // gen7_emit_3DSTATE_GS done by cmd_pipeline
664
665 /* 3DSTATE_BINDING_TABLE_POINTERS_GS */
666 // TODO: Do we want to track dirty state within a command buffer?
667 gen7_emit_3dstate_pointer(builder, pipeline,
668 GEN7_RENDER_OPCODE_3DSTATE_BINDING_TABLE_POINTERS_GS,
669 pipeline->gs_state.BINDING_TABLE_STATE);
670}
671
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600672static void
673gen7_emit_3DSTATE_HS(struct intel_pipeline_builder *builder,
674 struct intel_pipeline *p)
675{
676 const uint8_t cmd_len = 7;
677 const uint32_t dw0 = GEN7_RENDER_CMD(3D, 3DSTATE_HS) | (cmd_len - 2);
678 uint32_t *dw;
679
680 INTEL_GPU_ASSERT(builder->gpu, 7, 7);
681
682 dw = pipeline_cmd_ptr(p, cmd_len);
683 dw[0] = dw0;
684 dw[1] = 0;
685 dw[2] = 0;
686 dw[3] = 0;
687 dw[4] = 0;
688 dw[5] = 0;
689 dw[6] = 0;
690}
691
692static void gen7_pipeline_hs(struct intel_pipeline_builder *builder,
693 struct intel_pipeline *pipeline)
694{
695 /* 3DSTATE_CONSTANT_HS and 3DSTATE_HS */
696 gen7_emit_3dstate_constant(builder, pipeline,
697 GEN7_RENDER_OPCODE_3DSTATE_CONSTANT_HS,
698 0, 0, 0);
699 gen7_emit_3DSTATE_HS(builder, pipeline);
700
701 /* 3DSTATE_BINDING_TABLE_POINTERS_HS */
702 // TODO: Do we want to track dirty state within a command buffer?
703 gen7_emit_3dstate_pointer(builder, pipeline,
704 GEN7_RENDER_OPCODE_3DSTATE_BINDING_TABLE_POINTERS_HS,
705 0);
706}
707
708static void gen7_pipeline_te(struct intel_pipeline_builder *builder,
709 struct intel_pipeline *p)
710{
711 const uint8_t cmd_len = 4;
712 const uint32_t dw0 = GEN7_RENDER_CMD(3D, 3DSTATE_TE) | (cmd_len - 2);
713 uint32_t *dw;
714
715 INTEL_GPU_ASSERT(builder->gpu, 7, 7);
716
717 dw = pipeline_cmd_ptr(p, cmd_len);
718 dw[0] = dw0;
719 dw[1] = 0;
720 dw[2] = 0;
721 dw[3] = 0;
722}
723
724static void gen7_pipeline_ds(struct intel_pipeline_builder *builder,
725 struct intel_pipeline *p)
726{
727 const uint8_t cmd_len = 6;
728 const uint32_t dw0 = GEN7_RENDER_CMD(3D, 3DSTATE_DS) | (cmd_len - 2);
729 uint32_t *dw;
730
731 INTEL_GPU_ASSERT(builder->gpu, 7, 7);
732
733 dw = pipeline_cmd_ptr(p, cmd_len);
734 dw[0] = dw0;
735 dw[1] = 0;
736 dw[2] = 0;
737 dw[3] = 0;
738 dw[4] = 0;
739 dw[5] = 0;
740}
741
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800742static XGL_RESULT builder_build_all(struct intel_pipeline_builder *builder,
743 struct intel_pipeline *pipeline)
Chia-I Wu3efef432014-08-28 15:00:16 +0800744{
745 XGL_RESULT ret;
746
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800747 if (intel_gpu_gen(builder->gpu) >= INTEL_GEN(7)) {
Courtney Goeltzenleuchter68d9bef2014-08-28 17:35:03 -0600748 pipeline->pre_pso_wa_flags |= GEN6_WA_GEN7_VS_FLUSH;
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800749 builder_build_urb_alloc_gen7(builder, pipeline);
Courtney Goeltzenleuchter68d9bef2014-08-28 17:35:03 -0600750 builder_build_push_const_alloc_gen7(builder, pipeline);
751 gen7_pipeline_gs(builder, pipeline);
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600752 gen7_pipeline_hs(builder, pipeline);
753 gen7_pipeline_te(builder, pipeline);
754 gen7_pipeline_ds(builder, pipeline);
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800755 } else {
756 builder_build_urb_alloc_gen6(builder, pipeline);
757 }
758
Chia-I Wu3efef432014-08-28 15:00:16 +0800759 ret = pipeline_ia_state(pipeline, &builder->ia);
760
761 if (ret == XGL_SUCCESS)
762 ret = pipeline_rs_state(pipeline, &builder->rs);
763
764 if (ret == XGL_SUCCESS && builder->vs.shader)
765 ret = pipeline_shader(pipeline, &builder->vs);
766 if (ret == XGL_SUCCESS && builder->tcs.shader)
767 ret = pipeline_shader(pipeline, &builder->tcs);
768 if (ret == XGL_SUCCESS && builder->tes.shader)
769 ret = pipeline_shader(pipeline, &builder->tes);
770 if (ret == XGL_SUCCESS && builder->gs.shader)
771 ret = pipeline_shader(pipeline, &builder->gs);
772 if (ret == XGL_SUCCESS && builder->fs.shader)
773 ret = pipeline_shader(pipeline, &builder->fs);
774
775 if (ret == XGL_SUCCESS) {
776 pipeline->db_format = builder->db.format;
777 pipeline->cb_state = builder->cb;
778 pipeline->tess_state = builder->tess;
779 }
780
781 return ret;
782}
783
784static XGL_RESULT builder_init(struct intel_pipeline_builder *builder,
785 const struct intel_gpu *gpu,
786 const struct intel_pipeline_builder_create_info *info)
787{
788 memset(builder, 0, sizeof(*builder));
789
790 builder->gpu = gpu;
791
792 while (info) {
793 const void *src = (const void *) info;
794 XGL_SIZE size;
795 void *dst;
796
797 switch (info->struct_type) {
798 case XGL_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO:
799 size = sizeof(builder->graphics);
800 dst = &builder->graphics;
801 break;
802 case XGL_STRUCTURE_TYPE_PIPELINE_IA_STATE_CREATE_INFO:
803 size = sizeof(builder->ia);
804 dst = &builder->ia;
805 break;
806 case XGL_STRUCTURE_TYPE_PIPELINE_DB_STATE_CREATE_INFO:
807 size = sizeof(builder->db);
808 dst = &builder->db;
809 break;
810 case XGL_STRUCTURE_TYPE_PIPELINE_CB_STATE_CREATE_INFO:
811 size = sizeof(builder->cb);
812 dst = &builder->cb;
813 break;
814 case XGL_STRUCTURE_TYPE_PIPELINE_RS_STATE_CREATE_INFO:
815 size = sizeof(builder->rs);
816 dst = &builder->rs;
817 break;
818 case XGL_STRUCTURE_TYPE_PIPELINE_TESS_STATE_CREATE_INFO:
819 size = sizeof(builder->tess);
820 dst = &builder->tess;
821 break;
822 case XGL_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO:
823 {
824 const XGL_PIPELINE_SHADER *shader = (const XGL_PIPELINE_SHADER *) (info + 1);
825
826 src = (const void *) shader;
827 size = sizeof(*shader);
828
829 switch (shader->stage) {
830 case XGL_SHADER_STAGE_VERTEX:
831 dst = &builder->vs;
832 break;
833 case XGL_SHADER_STAGE_TESS_CONTROL:
834 dst = &builder->tcs;
835 break;
836 case XGL_SHADER_STAGE_TESS_EVALUATION:
837 dst = &builder->tes;
838 break;
839 case XGL_SHADER_STAGE_GEOMETRY:
840 dst = &builder->gs;
841 break;
842 case XGL_SHADER_STAGE_FRAGMENT:
843 dst = &builder->fs;
844 break;
845 case XGL_SHADER_STAGE_COMPUTE:
846 dst = &builder->cs;
847 break;
848 default:
849 return XGL_ERROR_BAD_PIPELINE_DATA;
850 break;
851 }
852 }
853 break;
854 case XGL_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO:
855 size = sizeof(builder->compute);
856 dst = &builder->compute;
857 break;
858 default:
859 return XGL_ERROR_BAD_PIPELINE_DATA;
860 break;
861 }
862
863 memcpy(dst, src, size);
864
865 info = info->next;
866 }
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600867
868 return XGL_SUCCESS;
Chia-I Wu3efef432014-08-28 15:00:16 +0800869}
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600870
Chia-I Wu3efef432014-08-28 15:00:16 +0800871static XGL_RESULT graphics_pipeline_create(struct intel_dev *dev,
872 const XGL_GRAPHICS_PIPELINE_CREATE_INFO *info,
873 struct intel_pipeline **pipeline_ret)
874{
875 struct intel_pipeline_builder builder;
876 struct intel_pipeline *pipeline;
877 XGL_RESULT ret;
878
879 ret = builder_init(&builder, dev->gpu,
880 (const struct intel_pipeline_builder_create_info *) info);
881 if (ret != XGL_SUCCESS)
882 return ret;
883
884 pipeline = (struct intel_pipeline *)
885 intel_base_create(dev, sizeof(*pipeline), dev->base.dbg,
886 XGL_DBG_OBJECT_GRAPHICS_PIPELINE, info, 0);
887 if (!pipeline)
888 return XGL_ERROR_OUT_OF_MEMORY;
889
890 pipeline->dev = dev;
891 pipeline->obj.destroy = pipeline_destroy;
Chia-I Wu3efef432014-08-28 15:00:16 +0800892
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800893 ret = builder_build_all(&builder, pipeline);
Chia-I Wu3efef432014-08-28 15:00:16 +0800894 if (ret == XGL_SUCCESS)
895 ret = builder_validate(&builder, pipeline);
896 if (ret != XGL_SUCCESS) {
897 pipeline_destroy(&pipeline->obj);
898 return ret;
899 }
900
901 *pipeline_ret = pipeline;
902
903 return XGL_SUCCESS;
904}
905
906XGL_RESULT XGLAPI intelCreateGraphicsPipeline(
907 XGL_DEVICE device,
908 const XGL_GRAPHICS_PIPELINE_CREATE_INFO* pCreateInfo,
909 XGL_PIPELINE* pPipeline)
910{
911 struct intel_dev *dev = intel_dev(device);
912
913 return graphics_pipeline_create(dev, pCreateInfo,
914 (struct intel_pipeline **) pPipeline);
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600915}
916
917XGL_RESULT XGLAPI intelCreateComputePipeline(
918 XGL_DEVICE device,
919 const XGL_COMPUTE_PIPELINE_CREATE_INFO* pCreateInfo,
920 XGL_PIPELINE* pPipeline)
921{
922 return XGL_ERROR_UNAVAILABLE;
923}
924
925XGL_RESULT XGLAPI intelStorePipeline(
926 XGL_PIPELINE pipeline,
927 XGL_SIZE* pDataSize,
928 XGL_VOID* pData)
929{
930 return XGL_ERROR_UNAVAILABLE;
931}
932
933XGL_RESULT XGLAPI intelLoadPipeline(
934 XGL_DEVICE device,
935 XGL_SIZE dataSize,
936 const XGL_VOID* pData,
937 XGL_PIPELINE* pPipeline)
938{
939 return XGL_ERROR_UNAVAILABLE;
940}
941
942XGL_RESULT XGLAPI intelCreatePipelineDelta(
943 XGL_DEVICE device,
944 XGL_PIPELINE p1,
945 XGL_PIPELINE p2,
946 XGL_PIPELINE_DELTA* delta)
947{
948 return XGL_ERROR_UNAVAILABLE;
949}