blob: 4f7d640a8fc11dc71b138d7abd2e88aefb931b4b [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
Chia-I Wu480d33b2014-08-29 10:26:14 +0800490 INTEL_GPU_ASSERT(builder->gpu, 7, 7.5);
Courtney Goeltzenleuchterb2867702014-08-28 17:44:05 -0600491
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
Courtney Goeltzenleuchterb2867702014-08-28 17:44:05 -0600567static void gen7_pipeline_gs(struct intel_pipeline_builder *builder,
568 struct intel_pipeline *pipeline)
569{
Courtney Goeltzenleuchterb2867702014-08-28 17:44:05 -0600570 // gen7_emit_3DSTATE_GS done by cmd_pipeline
Courtney Goeltzenleuchterb2867702014-08-28 17:44:05 -0600571}
572
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600573static void
574gen7_emit_3DSTATE_HS(struct intel_pipeline_builder *builder,
575 struct intel_pipeline *p)
576{
577 const uint8_t cmd_len = 7;
578 const uint32_t dw0 = GEN7_RENDER_CMD(3D, 3DSTATE_HS) | (cmd_len - 2);
579 uint32_t *dw;
580
Chia-I Wu480d33b2014-08-29 10:26:14 +0800581 INTEL_GPU_ASSERT(builder->gpu, 7, 7.5);
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600582
583 dw = pipeline_cmd_ptr(p, cmd_len);
584 dw[0] = dw0;
585 dw[1] = 0;
586 dw[2] = 0;
587 dw[3] = 0;
588 dw[4] = 0;
589 dw[5] = 0;
590 dw[6] = 0;
591}
592
593static void gen7_pipeline_hs(struct intel_pipeline_builder *builder,
594 struct intel_pipeline *pipeline)
595{
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600596 gen7_emit_3DSTATE_HS(builder, pipeline);
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600597}
598
599static void gen7_pipeline_te(struct intel_pipeline_builder *builder,
600 struct intel_pipeline *p)
601{
602 const uint8_t cmd_len = 4;
603 const uint32_t dw0 = GEN7_RENDER_CMD(3D, 3DSTATE_TE) | (cmd_len - 2);
604 uint32_t *dw;
605
Chia-I Wu480d33b2014-08-29 10:26:14 +0800606 INTEL_GPU_ASSERT(builder->gpu, 7, 7.5);
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600607
608 dw = pipeline_cmd_ptr(p, cmd_len);
609 dw[0] = dw0;
610 dw[1] = 0;
611 dw[2] = 0;
612 dw[3] = 0;
613}
614
615static void gen7_pipeline_ds(struct intel_pipeline_builder *builder,
616 struct intel_pipeline *p)
617{
618 const uint8_t cmd_len = 6;
619 const uint32_t dw0 = GEN7_RENDER_CMD(3D, 3DSTATE_DS) | (cmd_len - 2);
620 uint32_t *dw;
621
Chia-I Wu480d33b2014-08-29 10:26:14 +0800622 INTEL_GPU_ASSERT(builder->gpu, 7, 7.5);
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600623
624 dw = pipeline_cmd_ptr(p, cmd_len);
625 dw[0] = dw0;
626 dw[1] = 0;
627 dw[2] = 0;
628 dw[3] = 0;
629 dw[4] = 0;
630 dw[5] = 0;
631}
632
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800633static XGL_RESULT builder_build_all(struct intel_pipeline_builder *builder,
634 struct intel_pipeline *pipeline)
Chia-I Wu3efef432014-08-28 15:00:16 +0800635{
636 XGL_RESULT ret;
637
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800638 if (intel_gpu_gen(builder->gpu) >= INTEL_GEN(7)) {
Courtney Goeltzenleuchter68d9bef2014-08-28 17:35:03 -0600639 pipeline->pre_pso_wa_flags |= GEN6_WA_GEN7_VS_FLUSH;
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800640 builder_build_urb_alloc_gen7(builder, pipeline);
Courtney Goeltzenleuchter68d9bef2014-08-28 17:35:03 -0600641 builder_build_push_const_alloc_gen7(builder, pipeline);
642 gen7_pipeline_gs(builder, pipeline);
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600643 gen7_pipeline_hs(builder, pipeline);
644 gen7_pipeline_te(builder, pipeline);
645 gen7_pipeline_ds(builder, pipeline);
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800646 } else {
647 builder_build_urb_alloc_gen6(builder, pipeline);
648 }
649
Chia-I Wu3efef432014-08-28 15:00:16 +0800650 ret = pipeline_ia_state(pipeline, &builder->ia);
651
652 if (ret == XGL_SUCCESS)
653 ret = pipeline_rs_state(pipeline, &builder->rs);
654
655 if (ret == XGL_SUCCESS && builder->vs.shader)
656 ret = pipeline_shader(pipeline, &builder->vs);
657 if (ret == XGL_SUCCESS && builder->tcs.shader)
658 ret = pipeline_shader(pipeline, &builder->tcs);
659 if (ret == XGL_SUCCESS && builder->tes.shader)
660 ret = pipeline_shader(pipeline, &builder->tes);
661 if (ret == XGL_SUCCESS && builder->gs.shader)
662 ret = pipeline_shader(pipeline, &builder->gs);
663 if (ret == XGL_SUCCESS && builder->fs.shader)
664 ret = pipeline_shader(pipeline, &builder->fs);
665
666 if (ret == XGL_SUCCESS) {
667 pipeline->db_format = builder->db.format;
668 pipeline->cb_state = builder->cb;
669 pipeline->tess_state = builder->tess;
670 }
671
672 return ret;
673}
674
675static XGL_RESULT builder_init(struct intel_pipeline_builder *builder,
676 const struct intel_gpu *gpu,
677 const struct intel_pipeline_builder_create_info *info)
678{
679 memset(builder, 0, sizeof(*builder));
680
681 builder->gpu = gpu;
682
683 while (info) {
684 const void *src = (const void *) info;
685 XGL_SIZE size;
686 void *dst;
687
688 switch (info->struct_type) {
689 case XGL_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO:
690 size = sizeof(builder->graphics);
691 dst = &builder->graphics;
692 break;
693 case XGL_STRUCTURE_TYPE_PIPELINE_IA_STATE_CREATE_INFO:
694 size = sizeof(builder->ia);
695 dst = &builder->ia;
696 break;
697 case XGL_STRUCTURE_TYPE_PIPELINE_DB_STATE_CREATE_INFO:
698 size = sizeof(builder->db);
699 dst = &builder->db;
700 break;
701 case XGL_STRUCTURE_TYPE_PIPELINE_CB_STATE_CREATE_INFO:
702 size = sizeof(builder->cb);
703 dst = &builder->cb;
704 break;
705 case XGL_STRUCTURE_TYPE_PIPELINE_RS_STATE_CREATE_INFO:
706 size = sizeof(builder->rs);
707 dst = &builder->rs;
708 break;
709 case XGL_STRUCTURE_TYPE_PIPELINE_TESS_STATE_CREATE_INFO:
710 size = sizeof(builder->tess);
711 dst = &builder->tess;
712 break;
713 case XGL_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO:
714 {
715 const XGL_PIPELINE_SHADER *shader = (const XGL_PIPELINE_SHADER *) (info + 1);
716
717 src = (const void *) shader;
718 size = sizeof(*shader);
719
720 switch (shader->stage) {
721 case XGL_SHADER_STAGE_VERTEX:
722 dst = &builder->vs;
723 break;
724 case XGL_SHADER_STAGE_TESS_CONTROL:
725 dst = &builder->tcs;
726 break;
727 case XGL_SHADER_STAGE_TESS_EVALUATION:
728 dst = &builder->tes;
729 break;
730 case XGL_SHADER_STAGE_GEOMETRY:
731 dst = &builder->gs;
732 break;
733 case XGL_SHADER_STAGE_FRAGMENT:
734 dst = &builder->fs;
735 break;
736 case XGL_SHADER_STAGE_COMPUTE:
737 dst = &builder->cs;
738 break;
739 default:
740 return XGL_ERROR_BAD_PIPELINE_DATA;
741 break;
742 }
743 }
744 break;
745 case XGL_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO:
746 size = sizeof(builder->compute);
747 dst = &builder->compute;
748 break;
749 default:
750 return XGL_ERROR_BAD_PIPELINE_DATA;
751 break;
752 }
753
754 memcpy(dst, src, size);
755
756 info = info->next;
757 }
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600758
759 return XGL_SUCCESS;
Chia-I Wu3efef432014-08-28 15:00:16 +0800760}
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600761
Chia-I Wu3efef432014-08-28 15:00:16 +0800762static XGL_RESULT graphics_pipeline_create(struct intel_dev *dev,
763 const XGL_GRAPHICS_PIPELINE_CREATE_INFO *info,
764 struct intel_pipeline **pipeline_ret)
765{
766 struct intel_pipeline_builder builder;
767 struct intel_pipeline *pipeline;
768 XGL_RESULT ret;
769
770 ret = builder_init(&builder, dev->gpu,
771 (const struct intel_pipeline_builder_create_info *) info);
772 if (ret != XGL_SUCCESS)
773 return ret;
774
775 pipeline = (struct intel_pipeline *)
776 intel_base_create(dev, sizeof(*pipeline), dev->base.dbg,
777 XGL_DBG_OBJECT_GRAPHICS_PIPELINE, info, 0);
778 if (!pipeline)
779 return XGL_ERROR_OUT_OF_MEMORY;
780
781 pipeline->dev = dev;
782 pipeline->obj.destroy = pipeline_destroy;
Chia-I Wu3efef432014-08-28 15:00:16 +0800783
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800784 ret = builder_build_all(&builder, pipeline);
Chia-I Wu3efef432014-08-28 15:00:16 +0800785 if (ret == XGL_SUCCESS)
786 ret = builder_validate(&builder, pipeline);
787 if (ret != XGL_SUCCESS) {
788 pipeline_destroy(&pipeline->obj);
789 return ret;
790 }
791
792 *pipeline_ret = pipeline;
793
794 return XGL_SUCCESS;
795}
796
797XGL_RESULT XGLAPI intelCreateGraphicsPipeline(
798 XGL_DEVICE device,
799 const XGL_GRAPHICS_PIPELINE_CREATE_INFO* pCreateInfo,
800 XGL_PIPELINE* pPipeline)
801{
802 struct intel_dev *dev = intel_dev(device);
803
804 return graphics_pipeline_create(dev, pCreateInfo,
805 (struct intel_pipeline **) pPipeline);
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600806}
807
808XGL_RESULT XGLAPI intelCreateComputePipeline(
809 XGL_DEVICE device,
810 const XGL_COMPUTE_PIPELINE_CREATE_INFO* pCreateInfo,
811 XGL_PIPELINE* pPipeline)
812{
813 return XGL_ERROR_UNAVAILABLE;
814}
815
816XGL_RESULT XGLAPI intelStorePipeline(
817 XGL_PIPELINE pipeline,
818 XGL_SIZE* pDataSize,
819 XGL_VOID* pData)
820{
821 return XGL_ERROR_UNAVAILABLE;
822}
823
824XGL_RESULT XGLAPI intelLoadPipeline(
825 XGL_DEVICE device,
826 XGL_SIZE dataSize,
827 const XGL_VOID* pData,
828 XGL_PIPELINE* pPipeline)
829{
830 return XGL_ERROR_UNAVAILABLE;
831}
832
833XGL_RESULT XGLAPI intelCreatePipelineDelta(
834 XGL_DEVICE device,
835 XGL_PIPELINE p1,
836 XGL_PIPELINE p2,
837 XGL_PIPELINE_DELTA* delta)
838{
839 return XGL_ERROR_UNAVAILABLE;
840}