blob: cee06d6e4c3418d9c725bac056a44feba604011a [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
54static XGL_RESULT pipeline_ia_state(struct intel_pipeline *pipeline,
55 const XGL_PIPELINE_IA_STATE_CREATE_INFO* ia_state)
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060056{
Courtney Goeltzenleuchter42509992014-08-21 17:33:46 -060057 pipeline->ia_state = *ia_state;
58
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060059 if (ia_state->provokingVertex == XGL_PROVOKING_VERTEX_FIRST) {
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -060060 pipeline->provoking_vertex_tri = 0;
61 pipeline->provoking_vertex_trifan = 1;
62 pipeline->provoking_vertex_line = 0;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060063 } else {
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -060064 pipeline->provoking_vertex_tri = 2;
65 pipeline->provoking_vertex_trifan = 2;
66 pipeline->provoking_vertex_line = 1;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060067 }
68
69 switch (ia_state->topology) {
70 case XGL_TOPOLOGY_POINT_LIST:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -060071 pipeline->prim_type = GEN6_3DPRIM_POINTLIST;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060072 break;
73 case XGL_TOPOLOGY_LINE_LIST:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -060074 pipeline->prim_type = GEN6_3DPRIM_LINELIST;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060075 break;
76 case XGL_TOPOLOGY_LINE_STRIP:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -060077 pipeline->prim_type = GEN6_3DPRIM_LINESTRIP;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060078 break;
79 case XGL_TOPOLOGY_TRIANGLE_LIST:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -060080 pipeline->prim_type = GEN6_3DPRIM_TRILIST;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060081 break;
82 case XGL_TOPOLOGY_TRIANGLE_STRIP:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -060083 pipeline->prim_type = GEN6_3DPRIM_TRISTRIP;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060084 break;
85 case XGL_TOPOLOGY_RECT_LIST:
86 /*
87 * TODO: Rect lists are special in XGL, do we need to do
88 * something special here?
89 * XGL Guide:
90 * The rectangle list is a special geometry primitive type
91 * that can be used for implementing post-processing techniques
92 * or efficient copy operations. There are some special limitations
93 * for rectangle primitives. They cannot be clipped, must
94 * be axis aligned and cannot have depth gradient.
95 * Failure to comply with these restrictions results in
96 * undefined rendering results.
97 */
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -060098 pipeline->prim_type = GEN6_3DPRIM_RECTLIST;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060099 break;
100 case XGL_TOPOLOGY_QUAD_LIST:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600101 pipeline->prim_type = GEN6_3DPRIM_QUADLIST;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600102 break;
103 case XGL_TOPOLOGY_QUAD_STRIP:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600104 pipeline->prim_type = GEN6_3DPRIM_QUADSTRIP;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600105 break;
106 case XGL_TOPOLOGY_LINE_LIST_ADJ:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600107 pipeline->prim_type = GEN6_3DPRIM_LINELIST_ADJ;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600108 break;
109 case XGL_TOPOLOGY_LINE_STRIP_ADJ:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600110 pipeline->prim_type = GEN6_3DPRIM_LINESTRIP_ADJ;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600111 break;
112 case XGL_TOPOLOGY_TRIANGLE_LIST_ADJ:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600113 pipeline->prim_type = GEN6_3DPRIM_TRILIST_ADJ;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600114 break;
115 case XGL_TOPOLOGY_TRIANGLE_STRIP_ADJ:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600116 pipeline->prim_type = GEN6_3DPRIM_TRISTRIP_ADJ;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600117 break;
118 case XGL_TOPOLOGY_PATCH:
119 // TODO: implement something here
120 break;
121 default:
122 return XGL_ERROR_BAD_PIPELINE_DATA;
123 }
124
125 if (ia_state->primitiveRestartEnable) {
126 pipeline->primitive_restart = true;
127 pipeline->primitive_restart_index = ia_state->primitiveRestartIndex;
128 } else {
129 pipeline->primitive_restart = false;
130 }
131
132 if (ia_state->disableVertexReuse) {
133 // TODO: What do we do to disable vertex reuse?
134 }
135
136 return XGL_SUCCESS;
137}
138
Chia-I Wu3efef432014-08-28 15:00:16 +0800139static XGL_RESULT pipeline_rs_state(struct intel_pipeline *pipeline,
140 const XGL_PIPELINE_RS_STATE_CREATE_INFO* rs_state)
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600141{
142 pipeline->depthClipEnable = rs_state->depthClipEnable;
143 pipeline->rasterizerDiscardEnable = rs_state->rasterizerDiscardEnable;
144 pipeline->pointSize = rs_state->pointSize;
145 return XGL_SUCCESS;
146}
147
Courtney Goeltzenleuchter42509992014-08-21 17:33:46 -0600148static void pipeline_destroy(struct intel_obj *obj)
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600149{
150 struct intel_pipeline *pipeline = intel_pipeline_from_obj(obj);
151
Courtney Goeltzenleuchterd85c1d62014-08-27 14:04:53 -0600152 if (pipeline->active_shaders & SHADER_VERTEX_FLAG) {
Chia-I Wu282d3bc2014-08-28 15:36:44 +0800153 icd_free(pipeline->intel_vs.pCode);
Courtney Goeltzenleuchterd85c1d62014-08-27 14:04:53 -0600154 }
155 if (pipeline->active_shaders & SHADER_GEOMETRY_FLAG) {
Chia-I Wu282d3bc2014-08-28 15:36:44 +0800156 icd_free(pipeline->gs.pCode);
Courtney Goeltzenleuchterd85c1d62014-08-27 14:04:53 -0600157 }
158 if (pipeline->active_shaders & SHADER_FRAGMENT_FLAG) {
Chia-I Wu282d3bc2014-08-28 15:36:44 +0800159 icd_free(pipeline->intel_fs.pCode);
Courtney Goeltzenleuchterd85c1d62014-08-27 14:04:53 -0600160 }
161 if (pipeline->active_shaders & SHADER_TESS_CONTROL_FLAG) {
Chia-I Wu282d3bc2014-08-28 15:36:44 +0800162 icd_free(pipeline->tess_control.pCode);
Courtney Goeltzenleuchterd85c1d62014-08-27 14:04:53 -0600163 }
164 if (pipeline->active_shaders & SHADER_TESS_EVAL_FLAG) {
Chia-I Wu282d3bc2014-08-28 15:36:44 +0800165 icd_free(pipeline->tess_eval.pCode);
Courtney Goeltzenleuchterd85c1d62014-08-27 14:04:53 -0600166 }
167
Chia-I Wued833872014-08-23 17:00:35 +0800168 if (pipeline->vs_rmap)
169 intel_rmap_destroy(pipeline->vs_rmap);
170 if (pipeline->fs_rmap)
171 intel_rmap_destroy(pipeline->fs_rmap);
172
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600173 intel_base_destroy(&pipeline->obj.base);
174}
175
Chia-I Wu3efef432014-08-28 15:00:16 +0800176static XGL_RESULT pipeline_shader(struct intel_pipeline *pipeline,
177 const XGL_PIPELINE_SHADER *info)
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600178{
Chia-I Wu3efef432014-08-28 15:00:16 +0800179 struct intel_shader *sh = intel_shader(info->shader);
180 void *kernel;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600181
Chia-I Wu3efef432014-08-28 15:00:16 +0800182 // TODO: process shader object and include in pipeline
183 // For now that processing is simply a copy so that the app
184 // can destroy the original shader object after pipeline creation.
185 kernel = icd_alloc(sh->ir->size, 0, XGL_SYSTEM_ALLOC_INTERNAL_SHADER);
186 if (!kernel)
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600187 return XGL_ERROR_OUT_OF_MEMORY;
Chia-I Wu3efef432014-08-28 15:00:16 +0800188
189 switch (info->stage) {
190 case XGL_SHADER_STAGE_VERTEX:
191 /*
192 * TODO: What should we do here?
193 * shader_state (XGL_PIPELINE_SHADER) contains links
194 * to application memory in the pLinkConstBufferInfo and
195 * it's pBufferData pointers. Do we need to bring all that
196 * into the driver or is it okay to rely on those references
197 * holding good data. In OpenGL we'd make a driver copy. Not
198 * as clear for XGL.
199 * For now, use the app pointers.
200 */
201 pipeline->vs = *info;
202 pipeline->intel_vs.pCode = kernel;
203 pipeline->intel_vs.codeSize = sh->ir->size;
204 pipeline->active_shaders |= SHADER_VERTEX_FLAG;
205 pipeline->vs_rmap = intel_rmap_create(pipeline->dev,
206 &info->descriptorSetMapping[0],
207 &info->dynamicMemoryViewMapping, 0);
208 if (!pipeline->vs_rmap) {
209 icd_free(kernel);
210 return XGL_ERROR_OUT_OF_MEMORY;
211 }
212 break;
213 case XGL_SHADER_STAGE_GEOMETRY:
214 pipeline->gs.pCode = kernel;
215 pipeline->gs.codeSize = sh->ir->size;
216 pipeline->active_shaders |= SHADER_GEOMETRY_FLAG;
217 break;
218 case XGL_SHADER_STAGE_FRAGMENT:
219 pipeline->fs = *info;
220 pipeline->intel_fs.pCode = kernel;
221 pipeline->intel_fs.codeSize = sh->ir->size;
222 pipeline->active_shaders |= SHADER_FRAGMENT_FLAG;
223 /* assuming one RT; need to parse the shader */
224 pipeline->fs_rmap = intel_rmap_create(pipeline->dev,
225 &info->descriptorSetMapping[0],
226 &info->dynamicMemoryViewMapping, 1);
227 if (!pipeline->fs_rmap) {
228 icd_free(kernel);
229 return XGL_ERROR_OUT_OF_MEMORY;
230 }
231 break;
232 case XGL_SHADER_STAGE_TESS_CONTROL:
233 pipeline->tess_control.pCode = kernel;
234 pipeline->tess_control.codeSize = sh->ir->size;
235 pipeline->active_shaders |= SHADER_TESS_CONTROL_FLAG;
236 break;
237 case XGL_SHADER_STAGE_TESS_EVALUATION:
238 pipeline->tess_eval.pCode = kernel;
239 pipeline->tess_eval.codeSize = sh->ir->size;
240 pipeline->active_shaders |= SHADER_TESS_EVAL_FLAG;
241 break;
242 case XGL_SHADER_STAGE_COMPUTE:
243 pipeline->compute.pCode = kernel;
244 pipeline->compute.codeSize = sh->ir->size;
245 pipeline->active_shaders |= SHADER_COMPUTE_FLAG;
246 break;
247 default:
248 assert(!"unknown shader stage");
249 break;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600250 }
251
Chia-I Wu3efef432014-08-28 15:00:16 +0800252 return XGL_SUCCESS;
253}
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600254
Chia-I Wu3efef432014-08-28 15:00:16 +0800255static XGL_RESULT builder_validate(const struct intel_pipeline_builder *builder,
256 const struct intel_pipeline *pipeline)
257{
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600258 /*
259 * Validate required elements
260 */
261 if (!(pipeline->active_shaders & SHADER_VERTEX_FLAG)) {
262 // TODO: Log debug message: Vertex Shader required.
Chia-I Wu3efef432014-08-28 15:00:16 +0800263 return XGL_ERROR_BAD_PIPELINE_DATA;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600264 }
265
266 /*
267 * Tessalation control and evaluation have to both have a shader defined or
268 * neither should have a shader defined.
269 */
270 if (((pipeline->active_shaders & SHADER_TESS_CONTROL_FLAG) == 0) !=
271 ((pipeline->active_shaders & SHADER_TESS_EVAL_FLAG) == 0) ) {
272 // TODO: Log debug message: Both Tess control and Tess eval are required to use tessalation
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 if ((pipeline->active_shaders & SHADER_COMPUTE_FLAG) &&
277 (pipeline->active_shaders & (SHADER_VERTEX_FLAG | SHADER_TESS_CONTROL_FLAG |
278 SHADER_TESS_EVAL_FLAG | SHADER_GEOMETRY_FLAG |
279 SHADER_FRAGMENT_FLAG))) {
280 // TODO: Log debug message: Can only specify compute shader when doing compute
Chia-I Wu3efef432014-08-28 15:00:16 +0800281 return XGL_ERROR_BAD_PIPELINE_DATA;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600282 }
283
284 /*
Courtney Goeltzenleuchter42509992014-08-21 17:33:46 -0600285 * XGL_TOPOLOGY_PATCH primitive topology is only valid for tessellation pipelines.
286 * Mismatching primitive topology and tessellation fails graphics pipeline creation.
287 */
288 if (pipeline->active_shaders & (SHADER_TESS_CONTROL_FLAG | SHADER_TESS_EVAL_FLAG) &&
289 (pipeline->ia_state.topology != XGL_TOPOLOGY_PATCH)) {
290 // TODO: Log debug message: Invalid topology used with tessalation shader.
Chia-I Wu3efef432014-08-28 15:00:16 +0800291 return XGL_ERROR_BAD_PIPELINE_DATA;
Courtney Goeltzenleuchter42509992014-08-21 17:33:46 -0600292 }
293
294 if ((pipeline->ia_state.topology == XGL_TOPOLOGY_PATCH) &&
295 (pipeline->active_shaders & ~(SHADER_TESS_CONTROL_FLAG | SHADER_TESS_EVAL_FLAG))) {
296 // TODO: Log debug message: Cannot use TOPOLOGY_PATCH on non-tessalation shader.
Chia-I Wu3efef432014-08-28 15:00:16 +0800297 return XGL_ERROR_BAD_PIPELINE_DATA;
Courtney Goeltzenleuchter42509992014-08-21 17:33:46 -0600298 }
299
Chia-I Wu3efef432014-08-28 15:00:16 +0800300 return XGL_SUCCESS;
301}
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600302
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800303static void builder_build_urb_alloc_gen6(struct intel_pipeline_builder *builder,
304 struct intel_pipeline *pipeline)
305{
306 const int urb_size = ((builder->gpu->gt == 2) ? 64 : 32) * 1024;
307 const struct intel_shader *vs = intel_shader(builder->vs.shader);
308 const struct intel_shader *gs = intel_shader(builder->gs.shader);
309 int vs_entry_size, gs_entry_size;
310 int vs_size, gs_size;
311
312 INTEL_GPU_ASSERT(builder->gpu, 6, 6);
313
314 vs_entry_size = ((vs->in_count >= vs->out_count) ?
315 vs->in_count : vs->out_count);
316 gs_entry_size = (gs) ? gs->out_count : 0;
317
318 /* in bytes */
319 vs_entry_size *= sizeof(float) * 4;
320 gs_entry_size *= sizeof(float) * 4;
321
322 if (gs) {
323 vs_size = urb_size / 2;
324 gs_size = vs_size;
325 } else {
326 vs_size = urb_size;
327 gs_size = 0;
328 }
329
330 /* 3DSTATE_URB */
331 {
332 const uint8_t cmd_len = 3;
333 const uint32_t dw0 = GEN6_RENDER_CMD(3D, 3DSTATE_URB) |
334 (cmd_len - 2);
335 int vs_alloc_size, gs_alloc_size;
336 int vs_entry_count, gs_entry_count;
337 uint32_t *dw;
338
339 /* in 1024-bit rows */
340 vs_alloc_size = (vs_entry_size + 128 - 1) / 128;
341 gs_alloc_size = (gs_entry_size + 128 - 1) / 128;
342
343 /* valid range is [1, 5] */
344 if (!vs_alloc_size)
345 vs_alloc_size = 1;
346 if (!gs_alloc_size)
347 gs_alloc_size = 1;
348 assert(vs_alloc_size <= 5 && gs_alloc_size <= 5);
349
350 /* valid range is [24, 256], multiples of 4 */
351 vs_entry_count = (vs_size / 128 / vs_alloc_size) & ~3;
352 if (vs_entry_count > 256)
353 vs_entry_count = 256;
354 assert(vs_entry_count >= 24);
355
356 /* valid range is [0, 256], multiples of 4 */
357 gs_entry_count = (gs_size / 128 / gs_alloc_size) & ~3;
358 if (gs_entry_count > 256)
359 gs_entry_count = 256;
360
361 STATIC_ASSERT(ARRAY_SIZE(pipeline->cmd_urb_alloc) >= cmd_len);
362 pipeline->cmd_urb_alloc_len = cmd_len;
363 dw = pipeline->cmd_urb_alloc;
364
365 dw[0] = dw0;
366 dw[1] = (vs_alloc_size - 1) << GEN6_URB_DW1_VS_ENTRY_SIZE__SHIFT |
367 vs_entry_count << GEN6_URB_DW1_VS_ENTRY_COUNT__SHIFT;
368 dw[2] = gs_entry_count << GEN6_URB_DW2_GS_ENTRY_COUNT__SHIFT |
369 (gs_alloc_size - 1) << GEN6_URB_DW2_GS_ENTRY_SIZE__SHIFT;
370 }
371}
372
373static void builder_build_urb_alloc_gen7(struct intel_pipeline_builder *builder,
374 struct intel_pipeline *pipeline)
375{
376 const int urb_size = ((builder->gpu->gt == 3) ? 512 :
377 (builder->gpu->gt == 2) ? 256 : 128) * 1024;
378 const struct intel_shader *vs = intel_shader(builder->vs.shader);
379 const struct intel_shader *gs = intel_shader(builder->gs.shader);
380 /* some space is reserved for PCBs */
381 int urb_offset = ((builder->gpu->gt == 3) ? 32 : 16) * 1024;
382 int vs_entry_size, gs_entry_size;
383 int vs_size, gs_size;
384
385 INTEL_GPU_ASSERT(builder->gpu, 7, 7.5);
386
387 vs_entry_size = ((vs->in_count >= vs->out_count) ?
388 vs->in_count : vs->out_count);
389 gs_entry_size = (gs) ? gs->out_count : 0;
390
391 /* in bytes */
392 vs_entry_size *= sizeof(float) * 4;
393 gs_entry_size *= sizeof(float) * 4;
394
395 if (gs) {
396 vs_size = (urb_size - urb_offset) / 2;
397 gs_size = vs_size;
398 } else {
399 vs_size = urb_size - urb_offset;
400 gs_size = 0;
401 }
402
403 /* 3DSTATE_URB_* */
404 {
405 const uint8_t cmd_len = 2;
406 int vs_alloc_size, gs_alloc_size;
407 int vs_entry_count, gs_entry_count;
408 uint32_t *dw;
409
410 /* in 512-bit rows */
411 vs_alloc_size = (vs_entry_size + 64 - 1) / 64;
412 gs_alloc_size = (gs_entry_size + 64 - 1) / 64;
413
414 if (!vs_alloc_size)
415 vs_alloc_size = 1;
416 if (!gs_alloc_size)
417 gs_alloc_size = 1;
418
419 /* avoid performance decrease due to banking */
420 if (vs_alloc_size == 5)
421 vs_alloc_size = 6;
422
423 /* in multiples of 8 */
424 vs_entry_count = (vs_size / 64 / vs_alloc_size) & ~7;
425 assert(vs_entry_count >= 32);
426
427 gs_entry_count = (gs_size / 64 / gs_alloc_size) & ~7;
428
429 if (intel_gpu_gen(builder->gpu) >= INTEL_GEN(7.5)) {
430 const int max_vs_entry_count =
431 (builder->gpu->gt >= 2) ? 1644 : 640;
432 const int max_gs_entry_count =
433 (builder->gpu->gt >= 2) ? 640 : 256;
434 if (vs_entry_count >= max_vs_entry_count)
435 vs_entry_count = max_vs_entry_count;
436 if (gs_entry_count >= max_gs_entry_count)
437 gs_entry_count = max_gs_entry_count;
438 } else {
439 const int max_vs_entry_count =
440 (builder->gpu->gt == 2) ? 704 : 512;
441 const int max_gs_entry_count =
442 (builder->gpu->gt == 2) ? 320 : 192;
443 if (vs_entry_count >= max_vs_entry_count)
444 vs_entry_count = max_vs_entry_count;
445 if (gs_entry_count >= max_gs_entry_count)
446 gs_entry_count = max_gs_entry_count;
447 }
448
449 STATIC_ASSERT(ARRAY_SIZE(pipeline->cmd_urb_alloc) >= cmd_len * 4);
450 pipeline->cmd_urb_alloc_len = cmd_len * 4;
451
452 dw = pipeline->cmd_urb_alloc;
453 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_URB_VS) | (cmd_len - 2);
454 dw[1] = (urb_offset / 8192) << GEN7_URB_ANY_DW1_OFFSET__SHIFT |
455 (vs_alloc_size - 1) << GEN7_URB_ANY_DW1_ENTRY_SIZE__SHIFT |
456 vs_entry_count;
457
458 dw += 2;
459 if (gs_size)
460 urb_offset += vs_size;
461 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_URB_GS) | (cmd_len - 2);
462 dw[1] = (urb_offset / 8192) << GEN7_URB_ANY_DW1_OFFSET__SHIFT |
463 (gs_alloc_size - 1) << GEN7_URB_ANY_DW1_ENTRY_SIZE__SHIFT |
464 gs_entry_count;
465
466 dw += 2;
467 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_URB_HS) | (cmd_len - 2);
468 dw[1] = (urb_offset / 8192) << GEN7_URB_ANY_DW1_OFFSET__SHIFT;
469
470 dw += 2;
471 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_URB_DS) | (cmd_len - 2);
472 dw[1] = (urb_offset / 8192) << GEN7_URB_ANY_DW1_OFFSET__SHIFT;
473 }
474}
475
476static XGL_RESULT builder_build_all(struct intel_pipeline_builder *builder,
477 struct intel_pipeline *pipeline)
Chia-I Wu3efef432014-08-28 15:00:16 +0800478{
479 XGL_RESULT ret;
480
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800481 if (intel_gpu_gen(builder->gpu) >= INTEL_GEN(7)) {
482 builder_build_urb_alloc_gen7(builder, pipeline);
483 } else {
484 builder_build_urb_alloc_gen6(builder, pipeline);
485 }
486
Chia-I Wu3efef432014-08-28 15:00:16 +0800487 ret = pipeline_ia_state(pipeline, &builder->ia);
488
489 if (ret == XGL_SUCCESS)
490 ret = pipeline_rs_state(pipeline, &builder->rs);
491
492 if (ret == XGL_SUCCESS && builder->vs.shader)
493 ret = pipeline_shader(pipeline, &builder->vs);
494 if (ret == XGL_SUCCESS && builder->tcs.shader)
495 ret = pipeline_shader(pipeline, &builder->tcs);
496 if (ret == XGL_SUCCESS && builder->tes.shader)
497 ret = pipeline_shader(pipeline, &builder->tes);
498 if (ret == XGL_SUCCESS && builder->gs.shader)
499 ret = pipeline_shader(pipeline, &builder->gs);
500 if (ret == XGL_SUCCESS && builder->fs.shader)
501 ret = pipeline_shader(pipeline, &builder->fs);
502
503 if (ret == XGL_SUCCESS) {
504 pipeline->db_format = builder->db.format;
505 pipeline->cb_state = builder->cb;
506 pipeline->tess_state = builder->tess;
507 }
508
509 return ret;
510}
511
512static XGL_RESULT builder_init(struct intel_pipeline_builder *builder,
513 const struct intel_gpu *gpu,
514 const struct intel_pipeline_builder_create_info *info)
515{
516 memset(builder, 0, sizeof(*builder));
517
518 builder->gpu = gpu;
519
520 while (info) {
521 const void *src = (const void *) info;
522 XGL_SIZE size;
523 void *dst;
524
525 switch (info->struct_type) {
526 case XGL_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO:
527 size = sizeof(builder->graphics);
528 dst = &builder->graphics;
529 break;
530 case XGL_STRUCTURE_TYPE_PIPELINE_IA_STATE_CREATE_INFO:
531 size = sizeof(builder->ia);
532 dst = &builder->ia;
533 break;
534 case XGL_STRUCTURE_TYPE_PIPELINE_DB_STATE_CREATE_INFO:
535 size = sizeof(builder->db);
536 dst = &builder->db;
537 break;
538 case XGL_STRUCTURE_TYPE_PIPELINE_CB_STATE_CREATE_INFO:
539 size = sizeof(builder->cb);
540 dst = &builder->cb;
541 break;
542 case XGL_STRUCTURE_TYPE_PIPELINE_RS_STATE_CREATE_INFO:
543 size = sizeof(builder->rs);
544 dst = &builder->rs;
545 break;
546 case XGL_STRUCTURE_TYPE_PIPELINE_TESS_STATE_CREATE_INFO:
547 size = sizeof(builder->tess);
548 dst = &builder->tess;
549 break;
550 case XGL_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO:
551 {
552 const XGL_PIPELINE_SHADER *shader = (const XGL_PIPELINE_SHADER *) (info + 1);
553
554 src = (const void *) shader;
555 size = sizeof(*shader);
556
557 switch (shader->stage) {
558 case XGL_SHADER_STAGE_VERTEX:
559 dst = &builder->vs;
560 break;
561 case XGL_SHADER_STAGE_TESS_CONTROL:
562 dst = &builder->tcs;
563 break;
564 case XGL_SHADER_STAGE_TESS_EVALUATION:
565 dst = &builder->tes;
566 break;
567 case XGL_SHADER_STAGE_GEOMETRY:
568 dst = &builder->gs;
569 break;
570 case XGL_SHADER_STAGE_FRAGMENT:
571 dst = &builder->fs;
572 break;
573 case XGL_SHADER_STAGE_COMPUTE:
574 dst = &builder->cs;
575 break;
576 default:
577 return XGL_ERROR_BAD_PIPELINE_DATA;
578 break;
579 }
580 }
581 break;
582 case XGL_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO:
583 size = sizeof(builder->compute);
584 dst = &builder->compute;
585 break;
586 default:
587 return XGL_ERROR_BAD_PIPELINE_DATA;
588 break;
589 }
590
591 memcpy(dst, src, size);
592
593 info = info->next;
594 }
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600595
596 return XGL_SUCCESS;
Chia-I Wu3efef432014-08-28 15:00:16 +0800597}
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600598
Chia-I Wu3efef432014-08-28 15:00:16 +0800599static XGL_RESULT graphics_pipeline_create(struct intel_dev *dev,
600 const XGL_GRAPHICS_PIPELINE_CREATE_INFO *info,
601 struct intel_pipeline **pipeline_ret)
602{
603 struct intel_pipeline_builder builder;
604 struct intel_pipeline *pipeline;
605 XGL_RESULT ret;
606
607 ret = builder_init(&builder, dev->gpu,
608 (const struct intel_pipeline_builder_create_info *) info);
609 if (ret != XGL_SUCCESS)
610 return ret;
611
612 pipeline = (struct intel_pipeline *)
613 intel_base_create(dev, sizeof(*pipeline), dev->base.dbg,
614 XGL_DBG_OBJECT_GRAPHICS_PIPELINE, info, 0);
615 if (!pipeline)
616 return XGL_ERROR_OUT_OF_MEMORY;
617
618 pipeline->dev = dev;
619 pipeline->obj.destroy = pipeline_destroy;
620 pipeline->total_size = 0;
621
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800622 ret = builder_build_all(&builder, pipeline);
Chia-I Wu3efef432014-08-28 15:00:16 +0800623 if (ret == XGL_SUCCESS)
624 ret = builder_validate(&builder, pipeline);
625 if (ret != XGL_SUCCESS) {
626 pipeline_destroy(&pipeline->obj);
627 return ret;
628 }
629
630 *pipeline_ret = pipeline;
631
632 return XGL_SUCCESS;
633}
634
635XGL_RESULT XGLAPI intelCreateGraphicsPipeline(
636 XGL_DEVICE device,
637 const XGL_GRAPHICS_PIPELINE_CREATE_INFO* pCreateInfo,
638 XGL_PIPELINE* pPipeline)
639{
640 struct intel_dev *dev = intel_dev(device);
641
642 return graphics_pipeline_create(dev, pCreateInfo,
643 (struct intel_pipeline **) pPipeline);
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600644}
645
646XGL_RESULT XGLAPI intelCreateComputePipeline(
647 XGL_DEVICE device,
648 const XGL_COMPUTE_PIPELINE_CREATE_INFO* pCreateInfo,
649 XGL_PIPELINE* pPipeline)
650{
651 return XGL_ERROR_UNAVAILABLE;
652}
653
654XGL_RESULT XGLAPI intelStorePipeline(
655 XGL_PIPELINE pipeline,
656 XGL_SIZE* pDataSize,
657 XGL_VOID* pData)
658{
659 return XGL_ERROR_UNAVAILABLE;
660}
661
662XGL_RESULT XGLAPI intelLoadPipeline(
663 XGL_DEVICE device,
664 XGL_SIZE dataSize,
665 const XGL_VOID* pData,
666 XGL_PIPELINE* pPipeline)
667{
668 return XGL_ERROR_UNAVAILABLE;
669}
670
671XGL_RESULT XGLAPI intelCreatePipelineDelta(
672 XGL_DEVICE device,
673 XGL_PIPELINE p1,
674 XGL_PIPELINE p2,
675 XGL_PIPELINE_DELTA* delta)
676{
677 return XGL_ERROR_UNAVAILABLE;
678}