blob: 57828772f37ed7debb38379c84bc82911c389ead [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
481static XGL_RESULT builder_build_all(struct intel_pipeline_builder *builder,
482 struct intel_pipeline *pipeline)
Chia-I Wu3efef432014-08-28 15:00:16 +0800483{
484 XGL_RESULT ret;
485
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800486 if (intel_gpu_gen(builder->gpu) >= INTEL_GEN(7)) {
Courtney Goeltzenleuchter68d9bef2014-08-28 17:35:03 -0600487 pipeline->pre_pso_wa_flags |= GEN6_WA_GEN7_VS_FLUSH;
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800488 builder_build_urb_alloc_gen7(builder, pipeline);
Courtney Goeltzenleuchter68d9bef2014-08-28 17:35:03 -0600489 builder_build_push_const_alloc_gen7(builder, pipeline);
490 gen7_pipeline_gs(builder, pipeline);
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800491 } else {
492 builder_build_urb_alloc_gen6(builder, pipeline);
493 }
494
Chia-I Wu3efef432014-08-28 15:00:16 +0800495 ret = pipeline_ia_state(pipeline, &builder->ia);
496
497 if (ret == XGL_SUCCESS)
498 ret = pipeline_rs_state(pipeline, &builder->rs);
499
500 if (ret == XGL_SUCCESS && builder->vs.shader)
501 ret = pipeline_shader(pipeline, &builder->vs);
502 if (ret == XGL_SUCCESS && builder->tcs.shader)
503 ret = pipeline_shader(pipeline, &builder->tcs);
504 if (ret == XGL_SUCCESS && builder->tes.shader)
505 ret = pipeline_shader(pipeline, &builder->tes);
506 if (ret == XGL_SUCCESS && builder->gs.shader)
507 ret = pipeline_shader(pipeline, &builder->gs);
508 if (ret == XGL_SUCCESS && builder->fs.shader)
509 ret = pipeline_shader(pipeline, &builder->fs);
510
511 if (ret == XGL_SUCCESS) {
512 pipeline->db_format = builder->db.format;
513 pipeline->cb_state = builder->cb;
514 pipeline->tess_state = builder->tess;
515 }
516
517 return ret;
518}
519
520static XGL_RESULT builder_init(struct intel_pipeline_builder *builder,
521 const struct intel_gpu *gpu,
522 const struct intel_pipeline_builder_create_info *info)
523{
524 memset(builder, 0, sizeof(*builder));
525
526 builder->gpu = gpu;
527
528 while (info) {
529 const void *src = (const void *) info;
530 XGL_SIZE size;
531 void *dst;
532
533 switch (info->struct_type) {
534 case XGL_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO:
535 size = sizeof(builder->graphics);
536 dst = &builder->graphics;
537 break;
538 case XGL_STRUCTURE_TYPE_PIPELINE_IA_STATE_CREATE_INFO:
539 size = sizeof(builder->ia);
540 dst = &builder->ia;
541 break;
542 case XGL_STRUCTURE_TYPE_PIPELINE_DB_STATE_CREATE_INFO:
543 size = sizeof(builder->db);
544 dst = &builder->db;
545 break;
546 case XGL_STRUCTURE_TYPE_PIPELINE_CB_STATE_CREATE_INFO:
547 size = sizeof(builder->cb);
548 dst = &builder->cb;
549 break;
550 case XGL_STRUCTURE_TYPE_PIPELINE_RS_STATE_CREATE_INFO:
551 size = sizeof(builder->rs);
552 dst = &builder->rs;
553 break;
554 case XGL_STRUCTURE_TYPE_PIPELINE_TESS_STATE_CREATE_INFO:
555 size = sizeof(builder->tess);
556 dst = &builder->tess;
557 break;
558 case XGL_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO:
559 {
560 const XGL_PIPELINE_SHADER *shader = (const XGL_PIPELINE_SHADER *) (info + 1);
561
562 src = (const void *) shader;
563 size = sizeof(*shader);
564
565 switch (shader->stage) {
566 case XGL_SHADER_STAGE_VERTEX:
567 dst = &builder->vs;
568 break;
569 case XGL_SHADER_STAGE_TESS_CONTROL:
570 dst = &builder->tcs;
571 break;
572 case XGL_SHADER_STAGE_TESS_EVALUATION:
573 dst = &builder->tes;
574 break;
575 case XGL_SHADER_STAGE_GEOMETRY:
576 dst = &builder->gs;
577 break;
578 case XGL_SHADER_STAGE_FRAGMENT:
579 dst = &builder->fs;
580 break;
581 case XGL_SHADER_STAGE_COMPUTE:
582 dst = &builder->cs;
583 break;
584 default:
585 return XGL_ERROR_BAD_PIPELINE_DATA;
586 break;
587 }
588 }
589 break;
590 case XGL_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO:
591 size = sizeof(builder->compute);
592 dst = &builder->compute;
593 break;
594 default:
595 return XGL_ERROR_BAD_PIPELINE_DATA;
596 break;
597 }
598
599 memcpy(dst, src, size);
600
601 info = info->next;
602 }
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600603
604 return XGL_SUCCESS;
Chia-I Wu3efef432014-08-28 15:00:16 +0800605}
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600606
Chia-I Wu3efef432014-08-28 15:00:16 +0800607static XGL_RESULT graphics_pipeline_create(struct intel_dev *dev,
608 const XGL_GRAPHICS_PIPELINE_CREATE_INFO *info,
609 struct intel_pipeline **pipeline_ret)
610{
611 struct intel_pipeline_builder builder;
612 struct intel_pipeline *pipeline;
613 XGL_RESULT ret;
614
615 ret = builder_init(&builder, dev->gpu,
616 (const struct intel_pipeline_builder_create_info *) info);
617 if (ret != XGL_SUCCESS)
618 return ret;
619
620 pipeline = (struct intel_pipeline *)
621 intel_base_create(dev, sizeof(*pipeline), dev->base.dbg,
622 XGL_DBG_OBJECT_GRAPHICS_PIPELINE, info, 0);
623 if (!pipeline)
624 return XGL_ERROR_OUT_OF_MEMORY;
625
626 pipeline->dev = dev;
627 pipeline->obj.destroy = pipeline_destroy;
Chia-I Wu3efef432014-08-28 15:00:16 +0800628
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800629 ret = builder_build_all(&builder, pipeline);
Chia-I Wu3efef432014-08-28 15:00:16 +0800630 if (ret == XGL_SUCCESS)
631 ret = builder_validate(&builder, pipeline);
632 if (ret != XGL_SUCCESS) {
633 pipeline_destroy(&pipeline->obj);
634 return ret;
635 }
636
637 *pipeline_ret = pipeline;
638
639 return XGL_SUCCESS;
640}
641
642XGL_RESULT XGLAPI intelCreateGraphicsPipeline(
643 XGL_DEVICE device,
644 const XGL_GRAPHICS_PIPELINE_CREATE_INFO* pCreateInfo,
645 XGL_PIPELINE* pPipeline)
646{
647 struct intel_dev *dev = intel_dev(device);
648
649 return graphics_pipeline_create(dev, pCreateInfo,
650 (struct intel_pipeline **) pPipeline);
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600651}
652
653XGL_RESULT XGLAPI intelCreateComputePipeline(
654 XGL_DEVICE device,
655 const XGL_COMPUTE_PIPELINE_CREATE_INFO* pCreateInfo,
656 XGL_PIPELINE* pPipeline)
657{
658 return XGL_ERROR_UNAVAILABLE;
659}
660
661XGL_RESULT XGLAPI intelStorePipeline(
662 XGL_PIPELINE pipeline,
663 XGL_SIZE* pDataSize,
664 XGL_VOID* pData)
665{
666 return XGL_ERROR_UNAVAILABLE;
667}
668
669XGL_RESULT XGLAPI intelLoadPipeline(
670 XGL_DEVICE device,
671 XGL_SIZE dataSize,
672 const XGL_VOID* pData,
673 XGL_PIPELINE* pPipeline)
674{
675 return XGL_ERROR_UNAVAILABLE;
676}
677
678XGL_RESULT XGLAPI intelCreatePipelineDelta(
679 XGL_DEVICE device,
680 XGL_PIPELINE p1,
681 XGL_PIPELINE p2,
682 XGL_PIPELINE_DELTA* delta)
683{
684 return XGL_ERROR_UNAVAILABLE;
685}