blob: 44c171a4288a2689575e211c896efc4bce6f625a [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
Courtney Goeltzenleuchterb2867702014-08-28 17:44:05 -0600561static void gen7_pipeline_gs(struct intel_pipeline_builder *builder,
562 struct intel_pipeline *pipeline)
563{
Courtney Goeltzenleuchterb2867702014-08-28 17:44:05 -0600564 // gen7_emit_3DSTATE_GS done by cmd_pipeline
Courtney Goeltzenleuchterb2867702014-08-28 17:44:05 -0600565}
566
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600567static void
568gen7_emit_3DSTATE_HS(struct intel_pipeline_builder *builder,
569 struct intel_pipeline *p)
570{
571 const uint8_t cmd_len = 7;
572 const uint32_t dw0 = GEN7_RENDER_CMD(3D, 3DSTATE_HS) | (cmd_len - 2);
573 uint32_t *dw;
574
Chia-I Wu480d33b2014-08-29 10:26:14 +0800575 INTEL_GPU_ASSERT(builder->gpu, 7, 7.5);
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600576
577 dw = pipeline_cmd_ptr(p, cmd_len);
578 dw[0] = dw0;
579 dw[1] = 0;
580 dw[2] = 0;
581 dw[3] = 0;
582 dw[4] = 0;
583 dw[5] = 0;
584 dw[6] = 0;
585}
586
587static void gen7_pipeline_hs(struct intel_pipeline_builder *builder,
588 struct intel_pipeline *pipeline)
589{
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600590 gen7_emit_3DSTATE_HS(builder, pipeline);
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600591}
592
593static void gen7_pipeline_te(struct intel_pipeline_builder *builder,
594 struct intel_pipeline *p)
595{
596 const uint8_t cmd_len = 4;
597 const uint32_t dw0 = GEN7_RENDER_CMD(3D, 3DSTATE_TE) | (cmd_len - 2);
598 uint32_t *dw;
599
Chia-I Wu480d33b2014-08-29 10:26:14 +0800600 INTEL_GPU_ASSERT(builder->gpu, 7, 7.5);
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600601
602 dw = pipeline_cmd_ptr(p, cmd_len);
603 dw[0] = dw0;
604 dw[1] = 0;
605 dw[2] = 0;
606 dw[3] = 0;
607}
608
609static void gen7_pipeline_ds(struct intel_pipeline_builder *builder,
610 struct intel_pipeline *p)
611{
612 const uint8_t cmd_len = 6;
613 const uint32_t dw0 = GEN7_RENDER_CMD(3D, 3DSTATE_DS) | (cmd_len - 2);
614 uint32_t *dw;
615
Chia-I Wu480d33b2014-08-29 10:26:14 +0800616 INTEL_GPU_ASSERT(builder->gpu, 7, 7.5);
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600617
618 dw = pipeline_cmd_ptr(p, cmd_len);
619 dw[0] = dw0;
620 dw[1] = 0;
621 dw[2] = 0;
622 dw[3] = 0;
623 dw[4] = 0;
624 dw[5] = 0;
625}
626
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800627static XGL_RESULT builder_build_all(struct intel_pipeline_builder *builder,
628 struct intel_pipeline *pipeline)
Chia-I Wu3efef432014-08-28 15:00:16 +0800629{
630 XGL_RESULT ret;
631
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800632 if (intel_gpu_gen(builder->gpu) >= INTEL_GEN(7)) {
633 builder_build_urb_alloc_gen7(builder, pipeline);
Courtney Goeltzenleuchter68d9bef2014-08-28 17:35:03 -0600634 builder_build_push_const_alloc_gen7(builder, pipeline);
635 gen7_pipeline_gs(builder, pipeline);
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600636 gen7_pipeline_hs(builder, pipeline);
637 gen7_pipeline_te(builder, pipeline);
638 gen7_pipeline_ds(builder, pipeline);
Chia-I Wu8370b402014-08-29 12:28:37 +0800639
640 pipeline->wa_flags = INTEL_CMD_WA_GEN6_PRE_DEPTH_STALL_WRITE |
641 INTEL_CMD_WA_GEN6_PRE_COMMAND_SCOREBOARD_STALL |
642 INTEL_CMD_WA_GEN7_PRE_VS_DEPTH_STALL_WRITE |
643 INTEL_CMD_WA_GEN7_POST_COMMAND_CS_STALL |
644 INTEL_CMD_WA_GEN7_POST_COMMAND_DEPTH_STALL;
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800645 } else {
646 builder_build_urb_alloc_gen6(builder, pipeline);
Chia-I Wu8370b402014-08-29 12:28:37 +0800647
648 pipeline->wa_flags = INTEL_CMD_WA_GEN6_PRE_DEPTH_STALL_WRITE |
649 INTEL_CMD_WA_GEN6_PRE_COMMAND_SCOREBOARD_STALL;
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800650 }
651
Chia-I Wu3efef432014-08-28 15:00:16 +0800652 ret = pipeline_ia_state(pipeline, &builder->ia);
653
654 if (ret == XGL_SUCCESS)
655 ret = pipeline_rs_state(pipeline, &builder->rs);
656
657 if (ret == XGL_SUCCESS && builder->vs.shader)
658 ret = pipeline_shader(pipeline, &builder->vs);
659 if (ret == XGL_SUCCESS && builder->tcs.shader)
660 ret = pipeline_shader(pipeline, &builder->tcs);
661 if (ret == XGL_SUCCESS && builder->tes.shader)
662 ret = pipeline_shader(pipeline, &builder->tes);
663 if (ret == XGL_SUCCESS && builder->gs.shader)
664 ret = pipeline_shader(pipeline, &builder->gs);
665 if (ret == XGL_SUCCESS && builder->fs.shader)
666 ret = pipeline_shader(pipeline, &builder->fs);
667
668 if (ret == XGL_SUCCESS) {
669 pipeline->db_format = builder->db.format;
670 pipeline->cb_state = builder->cb;
671 pipeline->tess_state = builder->tess;
672 }
673
674 return ret;
675}
676
677static XGL_RESULT builder_init(struct intel_pipeline_builder *builder,
678 const struct intel_gpu *gpu,
679 const struct intel_pipeline_builder_create_info *info)
680{
681 memset(builder, 0, sizeof(*builder));
682
683 builder->gpu = gpu;
684
685 while (info) {
686 const void *src = (const void *) info;
687 XGL_SIZE size;
688 void *dst;
689
690 switch (info->struct_type) {
691 case XGL_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO:
692 size = sizeof(builder->graphics);
693 dst = &builder->graphics;
694 break;
695 case XGL_STRUCTURE_TYPE_PIPELINE_IA_STATE_CREATE_INFO:
696 size = sizeof(builder->ia);
697 dst = &builder->ia;
698 break;
699 case XGL_STRUCTURE_TYPE_PIPELINE_DB_STATE_CREATE_INFO:
700 size = sizeof(builder->db);
701 dst = &builder->db;
702 break;
703 case XGL_STRUCTURE_TYPE_PIPELINE_CB_STATE_CREATE_INFO:
704 size = sizeof(builder->cb);
705 dst = &builder->cb;
706 break;
707 case XGL_STRUCTURE_TYPE_PIPELINE_RS_STATE_CREATE_INFO:
708 size = sizeof(builder->rs);
709 dst = &builder->rs;
710 break;
711 case XGL_STRUCTURE_TYPE_PIPELINE_TESS_STATE_CREATE_INFO:
712 size = sizeof(builder->tess);
713 dst = &builder->tess;
714 break;
715 case XGL_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO:
716 {
717 const XGL_PIPELINE_SHADER *shader = (const XGL_PIPELINE_SHADER *) (info + 1);
718
719 src = (const void *) shader;
720 size = sizeof(*shader);
721
722 switch (shader->stage) {
723 case XGL_SHADER_STAGE_VERTEX:
724 dst = &builder->vs;
725 break;
726 case XGL_SHADER_STAGE_TESS_CONTROL:
727 dst = &builder->tcs;
728 break;
729 case XGL_SHADER_STAGE_TESS_EVALUATION:
730 dst = &builder->tes;
731 break;
732 case XGL_SHADER_STAGE_GEOMETRY:
733 dst = &builder->gs;
734 break;
735 case XGL_SHADER_STAGE_FRAGMENT:
736 dst = &builder->fs;
737 break;
738 case XGL_SHADER_STAGE_COMPUTE:
739 dst = &builder->cs;
740 break;
741 default:
742 return XGL_ERROR_BAD_PIPELINE_DATA;
743 break;
744 }
745 }
746 break;
747 case XGL_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO:
748 size = sizeof(builder->compute);
749 dst = &builder->compute;
750 break;
751 default:
752 return XGL_ERROR_BAD_PIPELINE_DATA;
753 break;
754 }
755
756 memcpy(dst, src, size);
757
758 info = info->next;
759 }
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600760
761 return XGL_SUCCESS;
Chia-I Wu3efef432014-08-28 15:00:16 +0800762}
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600763
Chia-I Wu3efef432014-08-28 15:00:16 +0800764static XGL_RESULT graphics_pipeline_create(struct intel_dev *dev,
765 const XGL_GRAPHICS_PIPELINE_CREATE_INFO *info,
766 struct intel_pipeline **pipeline_ret)
767{
768 struct intel_pipeline_builder builder;
769 struct intel_pipeline *pipeline;
770 XGL_RESULT ret;
771
772 ret = builder_init(&builder, dev->gpu,
773 (const struct intel_pipeline_builder_create_info *) info);
774 if (ret != XGL_SUCCESS)
775 return ret;
776
777 pipeline = (struct intel_pipeline *)
778 intel_base_create(dev, sizeof(*pipeline), dev->base.dbg,
779 XGL_DBG_OBJECT_GRAPHICS_PIPELINE, info, 0);
780 if (!pipeline)
781 return XGL_ERROR_OUT_OF_MEMORY;
782
783 pipeline->dev = dev;
784 pipeline->obj.destroy = pipeline_destroy;
Chia-I Wu3efef432014-08-28 15:00:16 +0800785
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800786 ret = builder_build_all(&builder, pipeline);
Chia-I Wu3efef432014-08-28 15:00:16 +0800787 if (ret == XGL_SUCCESS)
788 ret = builder_validate(&builder, pipeline);
789 if (ret != XGL_SUCCESS) {
790 pipeline_destroy(&pipeline->obj);
791 return ret;
792 }
793
794 *pipeline_ret = pipeline;
795
796 return XGL_SUCCESS;
797}
798
799XGL_RESULT XGLAPI intelCreateGraphicsPipeline(
800 XGL_DEVICE device,
801 const XGL_GRAPHICS_PIPELINE_CREATE_INFO* pCreateInfo,
802 XGL_PIPELINE* pPipeline)
803{
804 struct intel_dev *dev = intel_dev(device);
805
806 return graphics_pipeline_create(dev, pCreateInfo,
807 (struct intel_pipeline **) pPipeline);
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600808}
809
810XGL_RESULT XGLAPI intelCreateComputePipeline(
811 XGL_DEVICE device,
812 const XGL_COMPUTE_PIPELINE_CREATE_INFO* pCreateInfo,
813 XGL_PIPELINE* pPipeline)
814{
815 return XGL_ERROR_UNAVAILABLE;
816}
817
818XGL_RESULT XGLAPI intelStorePipeline(
819 XGL_PIPELINE pipeline,
820 XGL_SIZE* pDataSize,
821 XGL_VOID* pData)
822{
823 return XGL_ERROR_UNAVAILABLE;
824}
825
826XGL_RESULT XGLAPI intelLoadPipeline(
827 XGL_DEVICE device,
828 XGL_SIZE dataSize,
829 const XGL_VOID* pData,
830 XGL_PIPELINE* pPipeline)
831{
832 return XGL_ERROR_UNAVAILABLE;
833}
834
835XGL_RESULT XGLAPI intelCreatePipelineDelta(
836 XGL_DEVICE device,
837 XGL_PIPELINE p1,
838 XGL_PIPELINE p2,
839 XGL_PIPELINE_DELTA* delta)
840{
841 return XGL_ERROR_UNAVAILABLE;
842}