blob: 41f2d923c81460e03a6f18bf767782bda1dc9544 [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
Chia-I Wu8370b402014-08-29 12:28:37 +080025#include "genhw/genhw.h"
26
27#include "cmd.h"
Courtney Goeltzenleuchter42509992014-08-21 17:33:46 -060028#include "shader.h"
Chia-I Wued833872014-08-23 17:00:35 +080029#include "pipeline_priv.h"
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060030
Chia-I Wu3efef432014-08-28 15:00:16 +080031struct intel_pipeline_builder {
32 const struct intel_gpu *gpu;
33
34 XGL_GRAPHICS_PIPELINE_CREATE_INFO graphics;
35 XGL_PIPELINE_IA_STATE_CREATE_INFO ia;
36 XGL_PIPELINE_DB_STATE_CREATE_INFO db;
37 XGL_PIPELINE_CB_STATE cb;
38 XGL_PIPELINE_RS_STATE_CREATE_INFO rs;
39 XGL_PIPELINE_TESS_STATE_CREATE_INFO tess;
40 XGL_PIPELINE_SHADER vs;
41 XGL_PIPELINE_SHADER tcs;
42 XGL_PIPELINE_SHADER tes;
43 XGL_PIPELINE_SHADER gs;
44 XGL_PIPELINE_SHADER fs;
45
46 XGL_COMPUTE_PIPELINE_CREATE_INFO compute;
47 XGL_PIPELINE_SHADER cs;
48};
49
50struct intel_pipeline_builder_create_info {
51 XGL_STRUCTURE_TYPE struct_type;
52 XGL_VOID *next;
53};
54
Courtney Goeltzenleuchter814cd292014-08-28 13:16:27 -060055static uint32_t *pipeline_cmd_ptr(struct intel_pipeline *pipeline, int cmd_len)
56{
57 uint32_t *ptr;
58
59 assert(pipeline->cmd_len + cmd_len < INTEL_PSO_CMD_ENTRIES);
60 ptr = &pipeline->cmds[pipeline->cmd_len];
61 pipeline->cmd_len += cmd_len;
62 return ptr;
63}
64
Chia-I Wu3efef432014-08-28 15:00:16 +080065static XGL_RESULT pipeline_ia_state(struct intel_pipeline *pipeline,
66 const XGL_PIPELINE_IA_STATE_CREATE_INFO* ia_state)
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060067{
Courtney Goeltzenleuchter42509992014-08-21 17:33:46 -060068 pipeline->ia_state = *ia_state;
69
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060070 if (ia_state->provokingVertex == XGL_PROVOKING_VERTEX_FIRST) {
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -060071 pipeline->provoking_vertex_tri = 0;
72 pipeline->provoking_vertex_trifan = 1;
73 pipeline->provoking_vertex_line = 0;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060074 } else {
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -060075 pipeline->provoking_vertex_tri = 2;
76 pipeline->provoking_vertex_trifan = 2;
77 pipeline->provoking_vertex_line = 1;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060078 }
79
80 switch (ia_state->topology) {
81 case XGL_TOPOLOGY_POINT_LIST:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -060082 pipeline->prim_type = GEN6_3DPRIM_POINTLIST;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060083 break;
84 case XGL_TOPOLOGY_LINE_LIST:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -060085 pipeline->prim_type = GEN6_3DPRIM_LINELIST;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060086 break;
87 case XGL_TOPOLOGY_LINE_STRIP:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -060088 pipeline->prim_type = GEN6_3DPRIM_LINESTRIP;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060089 break;
90 case XGL_TOPOLOGY_TRIANGLE_LIST:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -060091 pipeline->prim_type = GEN6_3DPRIM_TRILIST;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060092 break;
93 case XGL_TOPOLOGY_TRIANGLE_STRIP:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -060094 pipeline->prim_type = GEN6_3DPRIM_TRISTRIP;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060095 break;
96 case XGL_TOPOLOGY_RECT_LIST:
97 /*
98 * TODO: Rect lists are special in XGL, do we need to do
99 * something special here?
100 * XGL Guide:
101 * The rectangle list is a special geometry primitive type
102 * that can be used for implementing post-processing techniques
103 * or efficient copy operations. There are some special limitations
104 * for rectangle primitives. They cannot be clipped, must
105 * be axis aligned and cannot have depth gradient.
106 * Failure to comply with these restrictions results in
107 * undefined rendering results.
108 */
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600109 pipeline->prim_type = GEN6_3DPRIM_RECTLIST;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600110 break;
111 case XGL_TOPOLOGY_QUAD_LIST:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600112 pipeline->prim_type = GEN6_3DPRIM_QUADLIST;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600113 break;
114 case XGL_TOPOLOGY_QUAD_STRIP:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600115 pipeline->prim_type = GEN6_3DPRIM_QUADSTRIP;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600116 break;
117 case XGL_TOPOLOGY_LINE_LIST_ADJ:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600118 pipeline->prim_type = GEN6_3DPRIM_LINELIST_ADJ;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600119 break;
120 case XGL_TOPOLOGY_LINE_STRIP_ADJ:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600121 pipeline->prim_type = GEN6_3DPRIM_LINESTRIP_ADJ;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600122 break;
123 case XGL_TOPOLOGY_TRIANGLE_LIST_ADJ:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600124 pipeline->prim_type = GEN6_3DPRIM_TRILIST_ADJ;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600125 break;
126 case XGL_TOPOLOGY_TRIANGLE_STRIP_ADJ:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600127 pipeline->prim_type = GEN6_3DPRIM_TRISTRIP_ADJ;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600128 break;
129 case XGL_TOPOLOGY_PATCH:
130 // TODO: implement something here
131 break;
132 default:
133 return XGL_ERROR_BAD_PIPELINE_DATA;
134 }
135
136 if (ia_state->primitiveRestartEnable) {
137 pipeline->primitive_restart = true;
138 pipeline->primitive_restart_index = ia_state->primitiveRestartIndex;
139 } else {
140 pipeline->primitive_restart = false;
141 }
142
143 if (ia_state->disableVertexReuse) {
144 // TODO: What do we do to disable vertex reuse?
145 }
146
147 return XGL_SUCCESS;
148}
149
Chia-I Wu3efef432014-08-28 15:00:16 +0800150static XGL_RESULT pipeline_rs_state(struct intel_pipeline *pipeline,
151 const XGL_PIPELINE_RS_STATE_CREATE_INFO* rs_state)
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600152{
153 pipeline->depthClipEnable = rs_state->depthClipEnable;
154 pipeline->rasterizerDiscardEnable = rs_state->rasterizerDiscardEnable;
155 pipeline->pointSize = rs_state->pointSize;
156 return XGL_SUCCESS;
157}
158
Courtney Goeltzenleuchter42509992014-08-21 17:33:46 -0600159static void pipeline_destroy(struct intel_obj *obj)
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600160{
161 struct intel_pipeline *pipeline = intel_pipeline_from_obj(obj);
162
Courtney Goeltzenleuchterd85c1d62014-08-27 14:04:53 -0600163 if (pipeline->active_shaders & SHADER_VERTEX_FLAG) {
Chia-I Wu282d3bc2014-08-28 15:36:44 +0800164 icd_free(pipeline->intel_vs.pCode);
Courtney Goeltzenleuchterd85c1d62014-08-27 14:04:53 -0600165 }
166 if (pipeline->active_shaders & SHADER_GEOMETRY_FLAG) {
Chia-I Wu282d3bc2014-08-28 15:36:44 +0800167 icd_free(pipeline->gs.pCode);
Courtney Goeltzenleuchterd85c1d62014-08-27 14:04:53 -0600168 }
169 if (pipeline->active_shaders & SHADER_FRAGMENT_FLAG) {
Chia-I Wu282d3bc2014-08-28 15:36:44 +0800170 icd_free(pipeline->intel_fs.pCode);
Courtney Goeltzenleuchterd85c1d62014-08-27 14:04:53 -0600171 }
172 if (pipeline->active_shaders & SHADER_TESS_CONTROL_FLAG) {
Chia-I Wu282d3bc2014-08-28 15:36:44 +0800173 icd_free(pipeline->tess_control.pCode);
Courtney Goeltzenleuchterd85c1d62014-08-27 14:04:53 -0600174 }
175 if (pipeline->active_shaders & SHADER_TESS_EVAL_FLAG) {
Chia-I Wu282d3bc2014-08-28 15:36:44 +0800176 icd_free(pipeline->tess_eval.pCode);
Courtney Goeltzenleuchterd85c1d62014-08-27 14:04:53 -0600177 }
178
Chia-I Wued833872014-08-23 17:00:35 +0800179 if (pipeline->vs_rmap)
180 intel_rmap_destroy(pipeline->vs_rmap);
181 if (pipeline->fs_rmap)
182 intel_rmap_destroy(pipeline->fs_rmap);
183
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600184 intel_base_destroy(&pipeline->obj.base);
185}
186
Chia-I Wu3efef432014-08-28 15:00:16 +0800187static XGL_RESULT pipeline_shader(struct intel_pipeline *pipeline,
188 const XGL_PIPELINE_SHADER *info)
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600189{
Chia-I Wu3efef432014-08-28 15:00:16 +0800190 struct intel_shader *sh = intel_shader(info->shader);
191 void *kernel;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600192
Chia-I Wu3efef432014-08-28 15:00:16 +0800193 // TODO: process shader object and include in pipeline
194 // For now that processing is simply a copy so that the app
195 // can destroy the original shader object after pipeline creation.
196 kernel = icd_alloc(sh->ir->size, 0, XGL_SYSTEM_ALLOC_INTERNAL_SHADER);
197 if (!kernel)
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600198 return XGL_ERROR_OUT_OF_MEMORY;
Chia-I Wu3efef432014-08-28 15:00:16 +0800199
200 switch (info->stage) {
201 case XGL_SHADER_STAGE_VERTEX:
202 /*
203 * TODO: What should we do here?
204 * shader_state (XGL_PIPELINE_SHADER) contains links
205 * to application memory in the pLinkConstBufferInfo and
206 * it's pBufferData pointers. Do we need to bring all that
207 * into the driver or is it okay to rely on those references
208 * holding good data. In OpenGL we'd make a driver copy. Not
209 * as clear for XGL.
210 * For now, use the app pointers.
211 */
212 pipeline->vs = *info;
213 pipeline->intel_vs.pCode = kernel;
214 pipeline->intel_vs.codeSize = sh->ir->size;
215 pipeline->active_shaders |= SHADER_VERTEX_FLAG;
216 pipeline->vs_rmap = intel_rmap_create(pipeline->dev,
217 &info->descriptorSetMapping[0],
218 &info->dynamicMemoryViewMapping, 0);
219 if (!pipeline->vs_rmap) {
220 icd_free(kernel);
221 return XGL_ERROR_OUT_OF_MEMORY;
222 }
223 break;
224 case XGL_SHADER_STAGE_GEOMETRY:
225 pipeline->gs.pCode = kernel;
226 pipeline->gs.codeSize = sh->ir->size;
227 pipeline->active_shaders |= SHADER_GEOMETRY_FLAG;
228 break;
229 case XGL_SHADER_STAGE_FRAGMENT:
230 pipeline->fs = *info;
231 pipeline->intel_fs.pCode = kernel;
232 pipeline->intel_fs.codeSize = sh->ir->size;
233 pipeline->active_shaders |= SHADER_FRAGMENT_FLAG;
234 /* assuming one RT; need to parse the shader */
235 pipeline->fs_rmap = intel_rmap_create(pipeline->dev,
236 &info->descriptorSetMapping[0],
237 &info->dynamicMemoryViewMapping, 1);
238 if (!pipeline->fs_rmap) {
239 icd_free(kernel);
240 return XGL_ERROR_OUT_OF_MEMORY;
241 }
242 break;
243 case XGL_SHADER_STAGE_TESS_CONTROL:
244 pipeline->tess_control.pCode = kernel;
245 pipeline->tess_control.codeSize = sh->ir->size;
246 pipeline->active_shaders |= SHADER_TESS_CONTROL_FLAG;
247 break;
248 case XGL_SHADER_STAGE_TESS_EVALUATION:
249 pipeline->tess_eval.pCode = kernel;
250 pipeline->tess_eval.codeSize = sh->ir->size;
251 pipeline->active_shaders |= SHADER_TESS_EVAL_FLAG;
252 break;
253 case XGL_SHADER_STAGE_COMPUTE:
254 pipeline->compute.pCode = kernel;
255 pipeline->compute.codeSize = sh->ir->size;
256 pipeline->active_shaders |= SHADER_COMPUTE_FLAG;
257 break;
258 default:
259 assert(!"unknown shader stage");
260 break;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600261 }
262
Chia-I Wu3efef432014-08-28 15:00:16 +0800263 return XGL_SUCCESS;
264}
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600265
Chia-I Wu3efef432014-08-28 15:00:16 +0800266static XGL_RESULT builder_validate(const struct intel_pipeline_builder *builder,
267 const struct intel_pipeline *pipeline)
268{
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600269 /*
270 * Validate required elements
271 */
272 if (!(pipeline->active_shaders & SHADER_VERTEX_FLAG)) {
273 // TODO: Log debug message: Vertex Shader required.
Chia-I Wu3efef432014-08-28 15:00:16 +0800274 return XGL_ERROR_BAD_PIPELINE_DATA;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600275 }
276
277 /*
278 * Tessalation control and evaluation have to both have a shader defined or
279 * neither should have a shader defined.
280 */
281 if (((pipeline->active_shaders & SHADER_TESS_CONTROL_FLAG) == 0) !=
282 ((pipeline->active_shaders & SHADER_TESS_EVAL_FLAG) == 0) ) {
283 // TODO: Log debug message: Both Tess control and Tess eval are required to use tessalation
Chia-I Wu3efef432014-08-28 15:00:16 +0800284 return XGL_ERROR_BAD_PIPELINE_DATA;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600285 }
286
287 if ((pipeline->active_shaders & SHADER_COMPUTE_FLAG) &&
288 (pipeline->active_shaders & (SHADER_VERTEX_FLAG | SHADER_TESS_CONTROL_FLAG |
289 SHADER_TESS_EVAL_FLAG | SHADER_GEOMETRY_FLAG |
290 SHADER_FRAGMENT_FLAG))) {
291 // TODO: Log debug message: Can only specify compute shader when doing compute
Chia-I Wu3efef432014-08-28 15:00:16 +0800292 return XGL_ERROR_BAD_PIPELINE_DATA;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600293 }
294
295 /*
Courtney Goeltzenleuchter42509992014-08-21 17:33:46 -0600296 * XGL_TOPOLOGY_PATCH primitive topology is only valid for tessellation pipelines.
297 * Mismatching primitive topology and tessellation fails graphics pipeline creation.
298 */
299 if (pipeline->active_shaders & (SHADER_TESS_CONTROL_FLAG | SHADER_TESS_EVAL_FLAG) &&
300 (pipeline->ia_state.topology != XGL_TOPOLOGY_PATCH)) {
301 // TODO: Log debug message: Invalid topology used with tessalation shader.
Chia-I Wu3efef432014-08-28 15:00:16 +0800302 return XGL_ERROR_BAD_PIPELINE_DATA;
Courtney Goeltzenleuchter42509992014-08-21 17:33:46 -0600303 }
304
305 if ((pipeline->ia_state.topology == XGL_TOPOLOGY_PATCH) &&
306 (pipeline->active_shaders & ~(SHADER_TESS_CONTROL_FLAG | SHADER_TESS_EVAL_FLAG))) {
307 // TODO: Log debug message: Cannot use TOPOLOGY_PATCH on non-tessalation shader.
Chia-I Wu3efef432014-08-28 15:00:16 +0800308 return XGL_ERROR_BAD_PIPELINE_DATA;
Courtney Goeltzenleuchter42509992014-08-21 17:33:46 -0600309 }
310
Chia-I Wu3efef432014-08-28 15:00:16 +0800311 return XGL_SUCCESS;
312}
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600313
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800314static void builder_build_urb_alloc_gen6(struct intel_pipeline_builder *builder,
315 struct intel_pipeline *pipeline)
316{
317 const int urb_size = ((builder->gpu->gt == 2) ? 64 : 32) * 1024;
318 const struct intel_shader *vs = intel_shader(builder->vs.shader);
319 const struct intel_shader *gs = intel_shader(builder->gs.shader);
320 int vs_entry_size, gs_entry_size;
321 int vs_size, gs_size;
322
323 INTEL_GPU_ASSERT(builder->gpu, 6, 6);
324
325 vs_entry_size = ((vs->in_count >= vs->out_count) ?
326 vs->in_count : vs->out_count);
327 gs_entry_size = (gs) ? gs->out_count : 0;
328
329 /* in bytes */
330 vs_entry_size *= sizeof(float) * 4;
331 gs_entry_size *= sizeof(float) * 4;
332
333 if (gs) {
334 vs_size = urb_size / 2;
335 gs_size = vs_size;
336 } else {
337 vs_size = urb_size;
338 gs_size = 0;
339 }
340
341 /* 3DSTATE_URB */
342 {
343 const uint8_t cmd_len = 3;
344 const uint32_t dw0 = GEN6_RENDER_CMD(3D, 3DSTATE_URB) |
345 (cmd_len - 2);
346 int vs_alloc_size, gs_alloc_size;
347 int vs_entry_count, gs_entry_count;
348 uint32_t *dw;
349
350 /* in 1024-bit rows */
351 vs_alloc_size = (vs_entry_size + 128 - 1) / 128;
352 gs_alloc_size = (gs_entry_size + 128 - 1) / 128;
353
354 /* valid range is [1, 5] */
355 if (!vs_alloc_size)
356 vs_alloc_size = 1;
357 if (!gs_alloc_size)
358 gs_alloc_size = 1;
359 assert(vs_alloc_size <= 5 && gs_alloc_size <= 5);
360
361 /* valid range is [24, 256], multiples of 4 */
362 vs_entry_count = (vs_size / 128 / vs_alloc_size) & ~3;
363 if (vs_entry_count > 256)
364 vs_entry_count = 256;
365 assert(vs_entry_count >= 24);
366
367 /* valid range is [0, 256], multiples of 4 */
368 gs_entry_count = (gs_size / 128 / gs_alloc_size) & ~3;
369 if (gs_entry_count > 256)
370 gs_entry_count = 256;
371
Courtney Goeltzenleuchter814cd292014-08-28 13:16:27 -0600372 dw = pipeline_cmd_ptr(pipeline, cmd_len);
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800373
374 dw[0] = dw0;
375 dw[1] = (vs_alloc_size - 1) << GEN6_URB_DW1_VS_ENTRY_SIZE__SHIFT |
376 vs_entry_count << GEN6_URB_DW1_VS_ENTRY_COUNT__SHIFT;
377 dw[2] = gs_entry_count << GEN6_URB_DW2_GS_ENTRY_COUNT__SHIFT |
378 (gs_alloc_size - 1) << GEN6_URB_DW2_GS_ENTRY_SIZE__SHIFT;
379 }
380}
381
382static void builder_build_urb_alloc_gen7(struct intel_pipeline_builder *builder,
383 struct intel_pipeline *pipeline)
384{
385 const int urb_size = ((builder->gpu->gt == 3) ? 512 :
386 (builder->gpu->gt == 2) ? 256 : 128) * 1024;
387 const struct intel_shader *vs = intel_shader(builder->vs.shader);
388 const struct intel_shader *gs = intel_shader(builder->gs.shader);
389 /* some space is reserved for PCBs */
390 int urb_offset = ((builder->gpu->gt == 3) ? 32 : 16) * 1024;
391 int vs_entry_size, gs_entry_size;
392 int vs_size, gs_size;
393
394 INTEL_GPU_ASSERT(builder->gpu, 7, 7.5);
395
396 vs_entry_size = ((vs->in_count >= vs->out_count) ?
397 vs->in_count : vs->out_count);
398 gs_entry_size = (gs) ? gs->out_count : 0;
399
400 /* in bytes */
401 vs_entry_size *= sizeof(float) * 4;
402 gs_entry_size *= sizeof(float) * 4;
403
404 if (gs) {
405 vs_size = (urb_size - urb_offset) / 2;
406 gs_size = vs_size;
407 } else {
408 vs_size = urb_size - urb_offset;
409 gs_size = 0;
410 }
411
412 /* 3DSTATE_URB_* */
413 {
414 const uint8_t cmd_len = 2;
415 int vs_alloc_size, gs_alloc_size;
416 int vs_entry_count, gs_entry_count;
417 uint32_t *dw;
418
419 /* in 512-bit rows */
420 vs_alloc_size = (vs_entry_size + 64 - 1) / 64;
421 gs_alloc_size = (gs_entry_size + 64 - 1) / 64;
422
423 if (!vs_alloc_size)
424 vs_alloc_size = 1;
425 if (!gs_alloc_size)
426 gs_alloc_size = 1;
427
428 /* avoid performance decrease due to banking */
429 if (vs_alloc_size == 5)
430 vs_alloc_size = 6;
431
432 /* in multiples of 8 */
433 vs_entry_count = (vs_size / 64 / vs_alloc_size) & ~7;
434 assert(vs_entry_count >= 32);
435
436 gs_entry_count = (gs_size / 64 / gs_alloc_size) & ~7;
437
438 if (intel_gpu_gen(builder->gpu) >= INTEL_GEN(7.5)) {
439 const int max_vs_entry_count =
440 (builder->gpu->gt >= 2) ? 1644 : 640;
441 const int max_gs_entry_count =
442 (builder->gpu->gt >= 2) ? 640 : 256;
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 } else {
448 const int max_vs_entry_count =
449 (builder->gpu->gt == 2) ? 704 : 512;
450 const int max_gs_entry_count =
451 (builder->gpu->gt == 2) ? 320 : 192;
452 if (vs_entry_count >= max_vs_entry_count)
453 vs_entry_count = max_vs_entry_count;
454 if (gs_entry_count >= max_gs_entry_count)
455 gs_entry_count = max_gs_entry_count;
456 }
457
Courtney Goeltzenleuchter814cd292014-08-28 13:16:27 -0600458 dw = pipeline_cmd_ptr(pipeline, cmd_len*4);
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800459 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_URB_VS) | (cmd_len - 2);
460 dw[1] = (urb_offset / 8192) << GEN7_URB_ANY_DW1_OFFSET__SHIFT |
461 (vs_alloc_size - 1) << GEN7_URB_ANY_DW1_ENTRY_SIZE__SHIFT |
462 vs_entry_count;
463
464 dw += 2;
465 if (gs_size)
466 urb_offset += vs_size;
467 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_URB_GS) | (cmd_len - 2);
468 dw[1] = (urb_offset / 8192) << GEN7_URB_ANY_DW1_OFFSET__SHIFT |
469 (gs_alloc_size - 1) << GEN7_URB_ANY_DW1_ENTRY_SIZE__SHIFT |
470 gs_entry_count;
471
472 dw += 2;
473 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_URB_HS) | (cmd_len - 2);
474 dw[1] = (urb_offset / 8192) << GEN7_URB_ANY_DW1_OFFSET__SHIFT;
475
476 dw += 2;
477 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_URB_DS) | (cmd_len - 2);
478 dw[1] = (urb_offset / 8192) << GEN7_URB_ANY_DW1_OFFSET__SHIFT;
479 }
480}
481
Courtney Goeltzenleuchterb2867702014-08-28 17:44:05 -0600482static void builder_build_push_const_alloc_gen7(struct intel_pipeline_builder *builder,
483 struct intel_pipeline *p)
484{
485 const uint8_t cmd_len = 2;
486 uint32_t offset = 0;
487 uint32_t size = 8192;
488 uint32_t *dw;
489 int end;
490
Chia-I Wu480d33b2014-08-29 10:26:14 +0800491 INTEL_GPU_ASSERT(builder->gpu, 7, 7.5);
Courtney Goeltzenleuchterb2867702014-08-28 17:44:05 -0600492
493 /*
494 * From the Ivy Bridge PRM, volume 2 part 1, page 68:
495 *
496 * "(A table that says the maximum size of each constant buffer is
497 * 16KB")
498 *
499 * From the Ivy Bridge PRM, volume 2 part 1, page 115:
500 *
501 * "The sum of the Constant Buffer Offset and the Constant Buffer Size
502 * may not exceed the maximum value of the Constant Buffer Size."
503 *
504 * Thus, the valid range of buffer end is [0KB, 16KB].
505 */
506 end = (offset + size) / 1024;
507 if (end > 16) {
508 assert(!"invalid constant buffer end");
509 end = 16;
510 }
511
512 /* the valid range of buffer offset is [0KB, 15KB] */
513 offset = (offset + 1023) / 1024;
514 if (offset > 15) {
515 assert(!"invalid constant buffer offset");
516 offset = 15;
517 }
518
519 if (offset > end) {
520 assert(!size);
521 offset = end;
522 }
523
524 /* the valid range of buffer size is [0KB, 15KB] */
525 size = end - offset;
526 if (size > 15) {
527 assert(!"invalid constant buffer size");
528 size = 15;
529 }
530
531 dw = pipeline_cmd_ptr(p, cmd_len * 5);
532 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_PUSH_CONSTANT_ALLOC_VS) | (cmd_len - 2);
533 dw[1] = offset << GEN7_PCB_ALLOC_ANY_DW1_OFFSET__SHIFT |
534 size << GEN7_PCB_ALLOC_ANY_DW1_SIZE__SHIFT;
535
536 dw += 2;
537 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_PUSH_CONSTANT_ALLOC_PS) | (cmd_len - 2);
538 dw[1] = size << GEN7_PCB_ALLOC_ANY_DW1_OFFSET__SHIFT |
539 size << GEN7_PCB_ALLOC_ANY_DW1_SIZE__SHIFT;
540
541 dw += 2;
542 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_PUSH_CONSTANT_ALLOC_HS) | (cmd_len - 2);
543 dw[1] = 0 << GEN7_PCB_ALLOC_ANY_DW1_OFFSET__SHIFT |
544 0 << GEN7_PCB_ALLOC_ANY_DW1_SIZE__SHIFT;
545
546 dw += 2;
547 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_PUSH_CONSTANT_ALLOC_DS) | (cmd_len - 2);
548 dw[1] = 0 << GEN7_PCB_ALLOC_ANY_DW1_OFFSET__SHIFT |
549 0 << GEN7_PCB_ALLOC_ANY_DW1_SIZE__SHIFT;
550
551 dw += 2;
552 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_PUSH_CONSTANT_ALLOC_GS) | (cmd_len - 2);
553 dw[1] = 0 << GEN7_PCB_ALLOC_ANY_DW1_OFFSET__SHIFT |
554 0 << GEN7_PCB_ALLOC_ANY_DW1_SIZE__SHIFT;
Chia-I Wu8370b402014-08-29 12:28:37 +0800555
Courtney Goeltzenleuchterb2867702014-08-28 17:44:05 -0600556 // gen7_wa_pipe_control_cs_stall(p, true, true);
557 // looks equivalent to: gen6_wa_wm_multisample_flush - this does more
558 // than the documentation seems to imply
559}
560
Chia-I Wu4d9ad912014-08-29 14:20:36 +0800561static void builder_build_vertex_elements(struct intel_pipeline_builder *builder,
562 struct intel_pipeline *pipeline)
563{
564 const uint8_t cmd_len = 3;
565 const uint32_t dw0 = GEN6_RENDER_CMD(3D, 3DSTATE_VERTEX_ELEMENTS) |
566 (cmd_len - 2);
567 const struct intel_shader *vs = intel_shader(builder->vs.shader);
568 int comps[4] = { GEN6_VFCOMP_NOSTORE, GEN6_VFCOMP_NOSTORE,
569 GEN6_VFCOMP_NOSTORE, GEN6_VFCOMP_NOSTORE };
570 uint32_t *dw;
571
572 INTEL_GPU_ASSERT(builder->gpu, 6, 7.5);
573
574 if (!(vs->uses & (INTEL_SHADER_USE_VID | INTEL_SHADER_USE_IID)))
575 return;
576
577 dw = pipeline_cmd_ptr(pipeline, cmd_len);
578 dw[0] = dw0;
579 dw++;
580
581 comps[0] = (vs->uses & INTEL_SHADER_USE_VID) ?
582 GEN6_VFCOMP_STORE_VID : GEN6_VFCOMP_STORE_0;
583 if (vs->uses & INTEL_SHADER_USE_IID)
584 comps[1] = GEN6_VFCOMP_STORE_IID;
585
586 /* VERTEX_ELEMENT_STATE */
587 dw[0] = GEN6_VE_STATE_DW0_VALID;
588 dw[1] = comps[0] << GEN6_VE_STATE_DW1_COMP0__SHIFT |
589 comps[1] << GEN6_VE_STATE_DW1_COMP1__SHIFT |
590 comps[2] << GEN6_VE_STATE_DW1_COMP2__SHIFT |
591 comps[3] << GEN6_VE_STATE_DW1_COMP3__SHIFT;
592}
593
594
Courtney Goeltzenleuchterb2867702014-08-28 17:44:05 -0600595static void gen7_pipeline_gs(struct intel_pipeline_builder *builder,
596 struct intel_pipeline *pipeline)
597{
Courtney Goeltzenleuchterb2867702014-08-28 17:44:05 -0600598 // gen7_emit_3DSTATE_GS done by cmd_pipeline
Courtney Goeltzenleuchterb2867702014-08-28 17:44:05 -0600599}
600
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600601static void
602gen7_emit_3DSTATE_HS(struct intel_pipeline_builder *builder,
603 struct intel_pipeline *p)
604{
605 const uint8_t cmd_len = 7;
606 const uint32_t dw0 = GEN7_RENDER_CMD(3D, 3DSTATE_HS) | (cmd_len - 2);
607 uint32_t *dw;
608
Chia-I Wu480d33b2014-08-29 10:26:14 +0800609 INTEL_GPU_ASSERT(builder->gpu, 7, 7.5);
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600610
611 dw = pipeline_cmd_ptr(p, cmd_len);
612 dw[0] = dw0;
613 dw[1] = 0;
614 dw[2] = 0;
615 dw[3] = 0;
616 dw[4] = 0;
617 dw[5] = 0;
618 dw[6] = 0;
619}
620
621static void gen7_pipeline_hs(struct intel_pipeline_builder *builder,
622 struct intel_pipeline *pipeline)
623{
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600624 gen7_emit_3DSTATE_HS(builder, pipeline);
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600625}
626
627static void gen7_pipeline_te(struct intel_pipeline_builder *builder,
628 struct intel_pipeline *p)
629{
630 const uint8_t cmd_len = 4;
631 const uint32_t dw0 = GEN7_RENDER_CMD(3D, 3DSTATE_TE) | (cmd_len - 2);
632 uint32_t *dw;
633
Chia-I Wu480d33b2014-08-29 10:26:14 +0800634 INTEL_GPU_ASSERT(builder->gpu, 7, 7.5);
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600635
636 dw = pipeline_cmd_ptr(p, cmd_len);
637 dw[0] = dw0;
638 dw[1] = 0;
639 dw[2] = 0;
640 dw[3] = 0;
641}
642
643static void gen7_pipeline_ds(struct intel_pipeline_builder *builder,
644 struct intel_pipeline *p)
645{
646 const uint8_t cmd_len = 6;
647 const uint32_t dw0 = GEN7_RENDER_CMD(3D, 3DSTATE_DS) | (cmd_len - 2);
648 uint32_t *dw;
649
Chia-I Wu480d33b2014-08-29 10:26:14 +0800650 INTEL_GPU_ASSERT(builder->gpu, 7, 7.5);
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600651
652 dw = pipeline_cmd_ptr(p, cmd_len);
653 dw[0] = dw0;
654 dw[1] = 0;
655 dw[2] = 0;
656 dw[3] = 0;
657 dw[4] = 0;
658 dw[5] = 0;
659}
660
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800661static XGL_RESULT builder_build_all(struct intel_pipeline_builder *builder,
662 struct intel_pipeline *pipeline)
Chia-I Wu3efef432014-08-28 15:00:16 +0800663{
664 XGL_RESULT ret;
665
Chia-I Wu4d9ad912014-08-29 14:20:36 +0800666 builder_build_vertex_elements(builder, pipeline);
667
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800668 if (intel_gpu_gen(builder->gpu) >= INTEL_GEN(7)) {
669 builder_build_urb_alloc_gen7(builder, pipeline);
Courtney Goeltzenleuchter68d9bef2014-08-28 17:35:03 -0600670 builder_build_push_const_alloc_gen7(builder, pipeline);
671 gen7_pipeline_gs(builder, pipeline);
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600672 gen7_pipeline_hs(builder, pipeline);
673 gen7_pipeline_te(builder, pipeline);
674 gen7_pipeline_ds(builder, pipeline);
Chia-I Wu8370b402014-08-29 12:28:37 +0800675
676 pipeline->wa_flags = INTEL_CMD_WA_GEN6_PRE_DEPTH_STALL_WRITE |
677 INTEL_CMD_WA_GEN6_PRE_COMMAND_SCOREBOARD_STALL |
678 INTEL_CMD_WA_GEN7_PRE_VS_DEPTH_STALL_WRITE |
679 INTEL_CMD_WA_GEN7_POST_COMMAND_CS_STALL |
680 INTEL_CMD_WA_GEN7_POST_COMMAND_DEPTH_STALL;
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800681 } else {
682 builder_build_urb_alloc_gen6(builder, pipeline);
Chia-I Wu8370b402014-08-29 12:28:37 +0800683
684 pipeline->wa_flags = INTEL_CMD_WA_GEN6_PRE_DEPTH_STALL_WRITE |
685 INTEL_CMD_WA_GEN6_PRE_COMMAND_SCOREBOARD_STALL;
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800686 }
687
Chia-I Wu3efef432014-08-28 15:00:16 +0800688 ret = pipeline_ia_state(pipeline, &builder->ia);
689
690 if (ret == XGL_SUCCESS)
691 ret = pipeline_rs_state(pipeline, &builder->rs);
692
693 if (ret == XGL_SUCCESS && builder->vs.shader)
694 ret = pipeline_shader(pipeline, &builder->vs);
695 if (ret == XGL_SUCCESS && builder->tcs.shader)
696 ret = pipeline_shader(pipeline, &builder->tcs);
697 if (ret == XGL_SUCCESS && builder->tes.shader)
698 ret = pipeline_shader(pipeline, &builder->tes);
699 if (ret == XGL_SUCCESS && builder->gs.shader)
700 ret = pipeline_shader(pipeline, &builder->gs);
701 if (ret == XGL_SUCCESS && builder->fs.shader)
702 ret = pipeline_shader(pipeline, &builder->fs);
703
704 if (ret == XGL_SUCCESS) {
705 pipeline->db_format = builder->db.format;
706 pipeline->cb_state = builder->cb;
707 pipeline->tess_state = builder->tess;
708 }
709
710 return ret;
711}
712
713static XGL_RESULT builder_init(struct intel_pipeline_builder *builder,
714 const struct intel_gpu *gpu,
715 const struct intel_pipeline_builder_create_info *info)
716{
717 memset(builder, 0, sizeof(*builder));
718
719 builder->gpu = gpu;
720
721 while (info) {
722 const void *src = (const void *) info;
723 XGL_SIZE size;
724 void *dst;
725
726 switch (info->struct_type) {
727 case XGL_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO:
728 size = sizeof(builder->graphics);
729 dst = &builder->graphics;
730 break;
731 case XGL_STRUCTURE_TYPE_PIPELINE_IA_STATE_CREATE_INFO:
732 size = sizeof(builder->ia);
733 dst = &builder->ia;
734 break;
735 case XGL_STRUCTURE_TYPE_PIPELINE_DB_STATE_CREATE_INFO:
736 size = sizeof(builder->db);
737 dst = &builder->db;
738 break;
739 case XGL_STRUCTURE_TYPE_PIPELINE_CB_STATE_CREATE_INFO:
740 size = sizeof(builder->cb);
741 dst = &builder->cb;
742 break;
743 case XGL_STRUCTURE_TYPE_PIPELINE_RS_STATE_CREATE_INFO:
744 size = sizeof(builder->rs);
745 dst = &builder->rs;
746 break;
747 case XGL_STRUCTURE_TYPE_PIPELINE_TESS_STATE_CREATE_INFO:
748 size = sizeof(builder->tess);
749 dst = &builder->tess;
750 break;
751 case XGL_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO:
752 {
753 const XGL_PIPELINE_SHADER *shader = (const XGL_PIPELINE_SHADER *) (info + 1);
754
755 src = (const void *) shader;
756 size = sizeof(*shader);
757
758 switch (shader->stage) {
759 case XGL_SHADER_STAGE_VERTEX:
760 dst = &builder->vs;
761 break;
762 case XGL_SHADER_STAGE_TESS_CONTROL:
763 dst = &builder->tcs;
764 break;
765 case XGL_SHADER_STAGE_TESS_EVALUATION:
766 dst = &builder->tes;
767 break;
768 case XGL_SHADER_STAGE_GEOMETRY:
769 dst = &builder->gs;
770 break;
771 case XGL_SHADER_STAGE_FRAGMENT:
772 dst = &builder->fs;
773 break;
774 case XGL_SHADER_STAGE_COMPUTE:
775 dst = &builder->cs;
776 break;
777 default:
778 return XGL_ERROR_BAD_PIPELINE_DATA;
779 break;
780 }
781 }
782 break;
783 case XGL_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO:
784 size = sizeof(builder->compute);
785 dst = &builder->compute;
786 break;
787 default:
788 return XGL_ERROR_BAD_PIPELINE_DATA;
789 break;
790 }
791
792 memcpy(dst, src, size);
793
794 info = info->next;
795 }
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600796
797 return XGL_SUCCESS;
Chia-I Wu3efef432014-08-28 15:00:16 +0800798}
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600799
Chia-I Wu3efef432014-08-28 15:00:16 +0800800static XGL_RESULT graphics_pipeline_create(struct intel_dev *dev,
801 const XGL_GRAPHICS_PIPELINE_CREATE_INFO *info,
802 struct intel_pipeline **pipeline_ret)
803{
804 struct intel_pipeline_builder builder;
805 struct intel_pipeline *pipeline;
806 XGL_RESULT ret;
807
808 ret = builder_init(&builder, dev->gpu,
809 (const struct intel_pipeline_builder_create_info *) info);
810 if (ret != XGL_SUCCESS)
811 return ret;
812
813 pipeline = (struct intel_pipeline *)
814 intel_base_create(dev, sizeof(*pipeline), dev->base.dbg,
815 XGL_DBG_OBJECT_GRAPHICS_PIPELINE, info, 0);
816 if (!pipeline)
817 return XGL_ERROR_OUT_OF_MEMORY;
818
819 pipeline->dev = dev;
820 pipeline->obj.destroy = pipeline_destroy;
Chia-I Wu3efef432014-08-28 15:00:16 +0800821
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800822 ret = builder_build_all(&builder, pipeline);
Chia-I Wu3efef432014-08-28 15:00:16 +0800823 if (ret == XGL_SUCCESS)
824 ret = builder_validate(&builder, pipeline);
825 if (ret != XGL_SUCCESS) {
826 pipeline_destroy(&pipeline->obj);
827 return ret;
828 }
829
830 *pipeline_ret = pipeline;
831
832 return XGL_SUCCESS;
833}
834
835XGL_RESULT XGLAPI intelCreateGraphicsPipeline(
836 XGL_DEVICE device,
837 const XGL_GRAPHICS_PIPELINE_CREATE_INFO* pCreateInfo,
838 XGL_PIPELINE* pPipeline)
839{
840 struct intel_dev *dev = intel_dev(device);
841
842 return graphics_pipeline_create(dev, pCreateInfo,
843 (struct intel_pipeline **) pPipeline);
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600844}
845
846XGL_RESULT XGLAPI intelCreateComputePipeline(
847 XGL_DEVICE device,
848 const XGL_COMPUTE_PIPELINE_CREATE_INFO* pCreateInfo,
849 XGL_PIPELINE* pPipeline)
850{
851 return XGL_ERROR_UNAVAILABLE;
852}
853
854XGL_RESULT XGLAPI intelStorePipeline(
855 XGL_PIPELINE pipeline,
856 XGL_SIZE* pDataSize,
857 XGL_VOID* pData)
858{
859 return XGL_ERROR_UNAVAILABLE;
860}
861
862XGL_RESULT XGLAPI intelLoadPipeline(
863 XGL_DEVICE device,
864 XGL_SIZE dataSize,
865 const XGL_VOID* pData,
866 XGL_PIPELINE* pPipeline)
867{
868 return XGL_ERROR_UNAVAILABLE;
869}
870
871XGL_RESULT XGLAPI intelCreatePipelineDelta(
872 XGL_DEVICE device,
873 XGL_PIPELINE p1,
874 XGL_PIPELINE p2,
875 XGL_PIPELINE_DELTA* delta)
876{
877 return XGL_ERROR_UNAVAILABLE;
878}