blob: f4cd5a21420f0345c55514927da2e3a152d9ce35 [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.
Chia-I Wu44e42362014-09-02 08:32:09 +080023 *
24 * Authors:
25 * Courtney Goeltzenleuchter <courtney@lunarg.com>
26 * Chia-I Wu <olv@lunarg.com>
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060027 */
28
Chia-I Wu8370b402014-08-29 12:28:37 +080029#include "genhw/genhw.h"
Chia-I Wu3f239832014-12-11 22:57:18 +080030#include "compiler/pipeline/pipeline_compiler_interface.h"
Chia-I Wu8370b402014-08-29 12:28:37 +080031#include "cmd.h"
Chia-I Wu1d125092014-10-08 08:49:38 +080032#include "format.h"
Courtney Goeltzenleuchter42509992014-08-21 17:33:46 -060033#include "shader.h"
Chia-I Wu3f239832014-12-11 22:57:18 +080034#include "pipeline.h"
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -060035
Tony Barbourfa6cac72015-01-16 14:27:35 -070036static int translate_blend_func(XGL_BLEND_FUNC func)
37{
38 switch (func) {
39 case XGL_BLEND_FUNC_ADD: return GEN6_BLENDFUNCTION_ADD;
40 case XGL_BLEND_FUNC_SUBTRACT: return GEN6_BLENDFUNCTION_SUBTRACT;
41 case XGL_BLEND_FUNC_REVERSE_SUBTRACT: return GEN6_BLENDFUNCTION_REVERSE_SUBTRACT;
42 case XGL_BLEND_FUNC_MIN: return GEN6_BLENDFUNCTION_MIN;
43 case XGL_BLEND_FUNC_MAX: return GEN6_BLENDFUNCTION_MAX;
44 default:
45 assert(!"unknown blend func");
46 return GEN6_BLENDFUNCTION_ADD;
47 };
48}
49
50static int translate_blend(XGL_BLEND blend)
51{
52 switch (blend) {
53 case XGL_BLEND_ZERO: return GEN6_BLENDFACTOR_ZERO;
54 case XGL_BLEND_ONE: return GEN6_BLENDFACTOR_ONE;
55 case XGL_BLEND_SRC_COLOR: return GEN6_BLENDFACTOR_SRC_COLOR;
56 case XGL_BLEND_ONE_MINUS_SRC_COLOR: return GEN6_BLENDFACTOR_INV_SRC_COLOR;
57 case XGL_BLEND_DEST_COLOR: return GEN6_BLENDFACTOR_DST_COLOR;
58 case XGL_BLEND_ONE_MINUS_DEST_COLOR: return GEN6_BLENDFACTOR_INV_DST_COLOR;
59 case XGL_BLEND_SRC_ALPHA: return GEN6_BLENDFACTOR_SRC_ALPHA;
60 case XGL_BLEND_ONE_MINUS_SRC_ALPHA: return GEN6_BLENDFACTOR_INV_SRC_ALPHA;
61 case XGL_BLEND_DEST_ALPHA: return GEN6_BLENDFACTOR_DST_ALPHA;
62 case XGL_BLEND_ONE_MINUS_DEST_ALPHA: return GEN6_BLENDFACTOR_INV_DST_ALPHA;
63 case XGL_BLEND_CONSTANT_COLOR: return GEN6_BLENDFACTOR_CONST_COLOR;
64 case XGL_BLEND_ONE_MINUS_CONSTANT_COLOR: return GEN6_BLENDFACTOR_INV_CONST_COLOR;
65 case XGL_BLEND_CONSTANT_ALPHA: return GEN6_BLENDFACTOR_CONST_ALPHA;
66 case XGL_BLEND_ONE_MINUS_CONSTANT_ALPHA: return GEN6_BLENDFACTOR_INV_CONST_ALPHA;
67 case XGL_BLEND_SRC_ALPHA_SATURATE: return GEN6_BLENDFACTOR_SRC_ALPHA_SATURATE;
68 case XGL_BLEND_SRC1_COLOR: return GEN6_BLENDFACTOR_SRC1_COLOR;
69 case XGL_BLEND_ONE_MINUS_SRC1_COLOR: return GEN6_BLENDFACTOR_INV_SRC1_COLOR;
70 case XGL_BLEND_SRC1_ALPHA: return GEN6_BLENDFACTOR_SRC1_ALPHA;
71 case XGL_BLEND_ONE_MINUS_SRC1_ALPHA: return GEN6_BLENDFACTOR_INV_SRC1_ALPHA;
72 default:
73 assert(!"unknown blend factor");
74 return GEN6_BLENDFACTOR_ONE;
75 };
76}
77
78static int translate_compare_func(XGL_COMPARE_FUNC func)
79{
80 switch (func) {
81 case XGL_COMPARE_NEVER: return GEN6_COMPAREFUNCTION_NEVER;
82 case XGL_COMPARE_LESS: return GEN6_COMPAREFUNCTION_LESS;
83 case XGL_COMPARE_EQUAL: return GEN6_COMPAREFUNCTION_EQUAL;
84 case XGL_COMPARE_LESS_EQUAL: return GEN6_COMPAREFUNCTION_LEQUAL;
85 case XGL_COMPARE_GREATER: return GEN6_COMPAREFUNCTION_GREATER;
86 case XGL_COMPARE_NOT_EQUAL: return GEN6_COMPAREFUNCTION_NOTEQUAL;
87 case XGL_COMPARE_GREATER_EQUAL: return GEN6_COMPAREFUNCTION_GEQUAL;
88 case XGL_COMPARE_ALWAYS: return GEN6_COMPAREFUNCTION_ALWAYS;
89 default:
90 assert(!"unknown compare_func");
91 return GEN6_COMPAREFUNCTION_NEVER;
92 }
93}
94
95static int translate_stencil_op(XGL_STENCIL_OP op)
96{
97 switch (op) {
98 case XGL_STENCIL_OP_KEEP: return GEN6_STENCILOP_KEEP;
99 case XGL_STENCIL_OP_ZERO: return GEN6_STENCILOP_ZERO;
100 case XGL_STENCIL_OP_REPLACE: return GEN6_STENCILOP_REPLACE;
101 case XGL_STENCIL_OP_INC_CLAMP: return GEN6_STENCILOP_INCRSAT;
102 case XGL_STENCIL_OP_DEC_CLAMP: return GEN6_STENCILOP_DECRSAT;
103 case XGL_STENCIL_OP_INVERT: return GEN6_STENCILOP_INVERT;
104 case XGL_STENCIL_OP_INC_WRAP: return GEN6_STENCILOP_INCR;
105 case XGL_STENCIL_OP_DEC_WRAP: return GEN6_STENCILOP_DECR;
106 default:
107 assert(!"unknown stencil op");
108 return GEN6_STENCILOP_KEEP;
109 }
110}
111
Chia-I Wu3f239832014-12-11 22:57:18 +0800112struct intel_pipeline_create_info {
113 XGL_GRAPHICS_PIPELINE_CREATE_INFO graphics;
114 XGL_PIPELINE_VERTEX_INPUT_CREATE_INFO vi;
115 XGL_PIPELINE_IA_STATE_CREATE_INFO ia;
Tony Barbourfa6cac72015-01-16 14:27:35 -0700116 XGL_PIPELINE_DS_STATE_CREATE_INFO db;
117 XGL_PIPELINE_CB_STATE_CREATE_INFO cb;
Chia-I Wu3f239832014-12-11 22:57:18 +0800118 XGL_PIPELINE_RS_STATE_CREATE_INFO rs;
119 XGL_PIPELINE_TESS_STATE_CREATE_INFO tess;
Tony Barbourfa6cac72015-01-16 14:27:35 -0700120 XGL_PIPELINE_MS_STATE_CREATE_INFO ms;
121 XGL_PIPELINE_VP_STATE_CREATE_INFO vp;
Chia-I Wu3f239832014-12-11 22:57:18 +0800122 XGL_PIPELINE_SHADER vs;
123 XGL_PIPELINE_SHADER tcs;
124 XGL_PIPELINE_SHADER tes;
125 XGL_PIPELINE_SHADER gs;
126 XGL_PIPELINE_SHADER fs;
127
128 XGL_COMPUTE_PIPELINE_CREATE_INFO compute;
129};
130struct intel_pipeline_shader *intel_pipeline_shader_create_meta(struct intel_dev *dev,
131 enum intel_dev_meta_shader id)
132{
133 struct intel_pipeline_shader *sh;
134 XGL_RESULT ret;
135
136 sh = icd_alloc(sizeof(*sh), 0, XGL_SYSTEM_ALLOC_INTERNAL);
137 if (!sh)
138 return NULL;
139 memset(sh, 0, sizeof(*sh));
140
141 ret = intel_pipeline_shader_compile_meta(sh, dev->gpu, id);
142 if (ret != XGL_SUCCESS) {
143 icd_free(sh);
144 return NULL;
145 }
146
147 switch (id) {
148 case INTEL_DEV_META_VS_FILL_MEM:
149 case INTEL_DEV_META_VS_COPY_MEM:
150 case INTEL_DEV_META_VS_COPY_MEM_UNALIGNED:
151 sh->max_threads = intel_gpu_get_max_threads(dev->gpu,
152 XGL_SHADER_STAGE_VERTEX);
153 break;
154 default:
155 sh->max_threads = intel_gpu_get_max_threads(dev->gpu,
156 XGL_SHADER_STAGE_FRAGMENT);
157 break;
158 }
159
160 return sh;
161}
162
163void intel_pipeline_shader_destroy(struct intel_pipeline_shader *sh)
164{
165 intel_pipeline_shader_cleanup(sh);
166 icd_free(sh);
167}
168
169static XGL_RESULT pipeline_build_shader(struct intel_pipeline *pipeline,
170 struct intel_pipeline_shader *sh,
171 const XGL_PIPELINE_SHADER *sh_info)
172{
173 XGL_RESULT ret;
174
175 ret = intel_pipeline_shader_compile(sh, pipeline->dev->gpu, sh_info);
176 if (ret != XGL_SUCCESS)
177 return ret;
178
179 sh->max_threads =
180 intel_gpu_get_max_threads(pipeline->dev->gpu, sh_info->stage);
181
182 /* 1KB aligned */
183 sh->scratch_offset = u_align(pipeline->scratch_size, 1024);
184 pipeline->scratch_size = sh->scratch_offset +
185 sh->per_thread_scratch_size * sh->max_threads;
186
187 pipeline->active_shaders |= 1 << sh_info->stage;
188
189 return XGL_SUCCESS;
190}
191
192static XGL_RESULT pipeline_build_shaders(struct intel_pipeline *pipeline,
193 const struct intel_pipeline_create_info *info)
194{
195 XGL_RESULT ret = XGL_SUCCESS;
196
197 if (ret == XGL_SUCCESS && info->vs.shader)
198 ret = pipeline_build_shader(pipeline, &pipeline->vs, &info->vs);
199 if (ret == XGL_SUCCESS && info->tcs.shader)
200 ret = pipeline_build_shader(pipeline, &pipeline->tcs, &info->tcs);
201 if (ret == XGL_SUCCESS && info->tes.shader)
202 ret = pipeline_build_shader(pipeline, &pipeline->tes, &info->tes);
203 if (ret == XGL_SUCCESS && info->gs.shader)
204 ret = pipeline_build_shader(pipeline, &pipeline->gs, &info->gs);
205 if (ret == XGL_SUCCESS && info->fs.shader)
206 ret = pipeline_build_shader(pipeline, &pipeline->fs, &info->fs);
207
208 if (ret == XGL_SUCCESS && info->compute.cs.shader)
209 ret = pipeline_build_shader(pipeline, &pipeline->cs, &info->compute.cs);
210
211 return ret;
212}
Courtney Goeltzenleuchter814cd292014-08-28 13:16:27 -0600213static uint32_t *pipeline_cmd_ptr(struct intel_pipeline *pipeline, int cmd_len)
214{
215 uint32_t *ptr;
216
217 assert(pipeline->cmd_len + cmd_len < INTEL_PSO_CMD_ENTRIES);
218 ptr = &pipeline->cmds[pipeline->cmd_len];
219 pipeline->cmd_len += cmd_len;
220 return ptr;
221}
222
Chia-I Wube0a3d92014-09-02 13:20:59 +0800223static XGL_RESULT pipeline_build_ia(struct intel_pipeline *pipeline,
224 const struct intel_pipeline_create_info* info)
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600225{
Chia-I Wube0a3d92014-09-02 13:20:59 +0800226 pipeline->topology = info->ia.topology;
227 pipeline->disable_vs_cache = info->ia.disableVertexReuse;
Courtney Goeltzenleuchter42509992014-08-21 17:33:46 -0600228
Chia-I Wube0a3d92014-09-02 13:20:59 +0800229 switch (info->ia.topology) {
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600230 case XGL_TOPOLOGY_POINT_LIST:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600231 pipeline->prim_type = GEN6_3DPRIM_POINTLIST;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600232 break;
233 case XGL_TOPOLOGY_LINE_LIST:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600234 pipeline->prim_type = GEN6_3DPRIM_LINELIST;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600235 break;
236 case XGL_TOPOLOGY_LINE_STRIP:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600237 pipeline->prim_type = GEN6_3DPRIM_LINESTRIP;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600238 break;
239 case XGL_TOPOLOGY_TRIANGLE_LIST:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600240 pipeline->prim_type = GEN6_3DPRIM_TRILIST;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600241 break;
242 case XGL_TOPOLOGY_TRIANGLE_STRIP:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600243 pipeline->prim_type = GEN6_3DPRIM_TRISTRIP;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600244 break;
245 case XGL_TOPOLOGY_RECT_LIST:
246 /*
247 * TODO: Rect lists are special in XGL, do we need to do
248 * something special here?
249 * XGL Guide:
250 * The rectangle list is a special geometry primitive type
251 * that can be used for implementing post-processing techniques
252 * or efficient copy operations. There are some special limitations
253 * for rectangle primitives. They cannot be clipped, must
254 * be axis aligned and cannot have depth gradient.
255 * Failure to comply with these restrictions results in
256 * undefined rendering results.
257 */
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600258 pipeline->prim_type = GEN6_3DPRIM_RECTLIST;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600259 break;
260 case XGL_TOPOLOGY_QUAD_LIST:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600261 pipeline->prim_type = GEN6_3DPRIM_QUADLIST;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600262 break;
263 case XGL_TOPOLOGY_QUAD_STRIP:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600264 pipeline->prim_type = GEN6_3DPRIM_QUADSTRIP;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600265 break;
266 case XGL_TOPOLOGY_LINE_LIST_ADJ:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600267 pipeline->prim_type = GEN6_3DPRIM_LINELIST_ADJ;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600268 break;
269 case XGL_TOPOLOGY_LINE_STRIP_ADJ:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600270 pipeline->prim_type = GEN6_3DPRIM_LINESTRIP_ADJ;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600271 break;
272 case XGL_TOPOLOGY_TRIANGLE_LIST_ADJ:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600273 pipeline->prim_type = GEN6_3DPRIM_TRILIST_ADJ;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600274 break;
275 case XGL_TOPOLOGY_TRIANGLE_STRIP_ADJ:
Courtney Goeltzenleuchter8a3de592014-08-22 09:09:46 -0600276 pipeline->prim_type = GEN6_3DPRIM_TRISTRIP_ADJ;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600277 break;
278 case XGL_TOPOLOGY_PATCH:
Chia-I Wube0a3d92014-09-02 13:20:59 +0800279 if (!info->tess.patchControlPoints ||
280 info->tess.patchControlPoints > 32)
281 return XGL_ERROR_BAD_PIPELINE_DATA;
282 pipeline->prim_type = GEN7_3DPRIM_PATCHLIST_1 +
283 info->tess.patchControlPoints - 1;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600284 break;
285 default:
286 return XGL_ERROR_BAD_PIPELINE_DATA;
287 }
288
Chia-I Wube0a3d92014-09-02 13:20:59 +0800289 if (info->ia.primitiveRestartEnable) {
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600290 pipeline->primitive_restart = true;
Chia-I Wube0a3d92014-09-02 13:20:59 +0800291 pipeline->primitive_restart_index = info->ia.primitiveRestartIndex;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600292 } else {
293 pipeline->primitive_restart = false;
294 }
295
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600296 return XGL_SUCCESS;
297}
298
Chia-I Wu3efef432014-08-28 15:00:16 +0800299static XGL_RESULT pipeline_rs_state(struct intel_pipeline *pipeline,
300 const XGL_PIPELINE_RS_STATE_CREATE_INFO* rs_state)
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600301{
302 pipeline->depthClipEnable = rs_state->depthClipEnable;
303 pipeline->rasterizerDiscardEnable = rs_state->rasterizerDiscardEnable;
Tony Barbourfa6cac72015-01-16 14:27:35 -0700304
305 if (rs_state->provokingVertex == XGL_PROVOKING_VERTEX_FIRST) {
306 pipeline->provoking_vertex_tri = 0;
307 pipeline->provoking_vertex_trifan = 1;
308 pipeline->provoking_vertex_line = 0;
309 } else {
310 pipeline->provoking_vertex_tri = 2;
311 pipeline->provoking_vertex_trifan = 2;
312 pipeline->provoking_vertex_line = 1;
313 }
314
315 switch (rs_state->fillMode) {
316 case XGL_FILL_POINTS:
317 pipeline->cmd_sf_fill |= GEN7_SF_DW1_FRONTFACE_POINT |
318 GEN7_SF_DW1_BACKFACE_POINT;
319 break;
320 case XGL_FILL_WIREFRAME:
321 pipeline->cmd_sf_fill |= GEN7_SF_DW1_FRONTFACE_WIREFRAME |
322 GEN7_SF_DW1_BACKFACE_WIREFRAME;
323 break;
324 case XGL_FILL_SOLID:
325 default:
326 pipeline->cmd_sf_fill |= GEN7_SF_DW1_FRONTFACE_SOLID |
327 GEN7_SF_DW1_BACKFACE_SOLID;
328 break;
329 }
330
331 if (rs_state->frontFace == XGL_FRONT_FACE_CCW) {
332 pipeline->cmd_sf_fill |= GEN7_SF_DW1_FRONTWINDING_CCW;
333 pipeline->cmd_clip_cull |= GEN7_CLIP_DW1_FRONTWINDING_CCW;
334 }
335
336 switch (rs_state->cullMode) {
337 case XGL_CULL_NONE:
338 default:
339 pipeline->cmd_sf_cull |= GEN7_SF_DW2_CULLMODE_NONE;
340 pipeline->cmd_clip_cull |= GEN7_CLIP_DW1_CULLMODE_NONE;
341 break;
342 case XGL_CULL_FRONT:
343 pipeline->cmd_sf_cull |= GEN7_SF_DW2_CULLMODE_FRONT;
344 pipeline->cmd_clip_cull |= GEN7_CLIP_DW1_CULLMODE_FRONT;
345 break;
346 case XGL_CULL_BACK:
347 pipeline->cmd_sf_cull |= GEN7_SF_DW2_CULLMODE_BACK;
348 pipeline->cmd_clip_cull |= GEN7_CLIP_DW1_CULLMODE_BACK;
349 break;
350 case XGL_CULL_FRONT_AND_BACK:
351 pipeline->cmd_sf_cull |= GEN7_SF_DW2_CULLMODE_BOTH;
352 pipeline->cmd_clip_cull |= GEN7_CLIP_DW1_CULLMODE_BOTH;
353 break;
354 }
355
356 /* only GEN7+ needs cull mode in 3DSTATE_CLIP */
357 if (intel_gpu_gen(pipeline->dev->gpu) == INTEL_GEN(6))
358 pipeline->cmd_clip_cull = 0;
359
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600360 return XGL_SUCCESS;
361}
362
Courtney Goeltzenleuchter42509992014-08-21 17:33:46 -0600363static void pipeline_destroy(struct intel_obj *obj)
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600364{
365 struct intel_pipeline *pipeline = intel_pipeline_from_obj(obj);
366
Chia-I Wu3f239832014-12-11 22:57:18 +0800367 if (pipeline->active_shaders & SHADER_VERTEX_FLAG) {
368 intel_pipeline_shader_cleanup(&pipeline->vs);
369 }
370
371 if (pipeline->active_shaders & SHADER_TESS_CONTROL_FLAG) {
372 intel_pipeline_shader_cleanup(&pipeline->tcs);
373 }
374
375 if (pipeline->active_shaders & SHADER_TESS_EVAL_FLAG) {
376 intel_pipeline_shader_cleanup(&pipeline->tes);
377 }
378
379 if (pipeline->active_shaders & SHADER_GEOMETRY_FLAG) {
380 intel_pipeline_shader_cleanup(&pipeline->gs);
381 }
382
383 if (pipeline->active_shaders & SHADER_FRAGMENT_FLAG) {
384 intel_pipeline_shader_cleanup(&pipeline->fs);
385 }
386
387 if (pipeline->active_shaders & SHADER_COMPUTE_FLAG) {
388 intel_pipeline_shader_cleanup(&pipeline->cs);
389 }
Chia-I Wued833872014-08-23 17:00:35 +0800390
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600391 intel_base_destroy(&pipeline->obj.base);
392}
393
Chia-I Wub1024732014-12-19 13:00:29 +0800394static XGL_RESULT pipeline_get_info(struct intel_base *base, int type,
395 XGL_SIZE *size, XGL_VOID *data)
396{
Tony Barbourfa6cac72015-01-16 14:27:35 -0700397 static XGL_UINT pipelineHeaps[1] = {0}; /* always heap 0 */
Chia-I Wub1024732014-12-19 13:00:29 +0800398 struct intel_pipeline *pipeline = intel_pipeline_from_base(base);
399 XGL_RESULT ret = XGL_SUCCESS;
400
401 switch (type) {
402 case XGL_INFO_TYPE_MEMORY_REQUIREMENTS:
403 {
404 XGL_MEMORY_REQUIREMENTS *mem_req = data;
405
406 *size = sizeof(XGL_MEMORY_REQUIREMENTS);
407 if (data) {
408 mem_req->size = pipeline->scratch_size;
409 mem_req->alignment = 1024;
410 mem_req->heapCount = 1;
Tony Barbourfa6cac72015-01-16 14:27:35 -0700411 mem_req->pHeaps = pipelineHeaps;
Chia-I Wub1024732014-12-19 13:00:29 +0800412 }
413 }
414 break;
415 default:
416 ret = intel_base_get_info(base, type, size, data);
417 break;
418 }
419
420 return ret;
421}
422
Chia-I Wuf90ff0c2014-09-02 09:32:46 +0800423static XGL_RESULT pipeline_validate(struct intel_pipeline *pipeline)
Chia-I Wu3efef432014-08-28 15:00:16 +0800424{
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600425 /*
426 * Validate required elements
427 */
428 if (!(pipeline->active_shaders & SHADER_VERTEX_FLAG)) {
429 // TODO: Log debug message: Vertex Shader required.
Chia-I Wu3efef432014-08-28 15:00:16 +0800430 return XGL_ERROR_BAD_PIPELINE_DATA;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600431 }
432
433 /*
434 * Tessalation control and evaluation have to both have a shader defined or
435 * neither should have a shader defined.
436 */
437 if (((pipeline->active_shaders & SHADER_TESS_CONTROL_FLAG) == 0) !=
438 ((pipeline->active_shaders & SHADER_TESS_EVAL_FLAG) == 0) ) {
439 // TODO: Log debug message: Both Tess control and Tess eval are required to use tessalation
Chia-I Wu3efef432014-08-28 15:00:16 +0800440 return XGL_ERROR_BAD_PIPELINE_DATA;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600441 }
442
443 if ((pipeline->active_shaders & SHADER_COMPUTE_FLAG) &&
444 (pipeline->active_shaders & (SHADER_VERTEX_FLAG | SHADER_TESS_CONTROL_FLAG |
445 SHADER_TESS_EVAL_FLAG | SHADER_GEOMETRY_FLAG |
446 SHADER_FRAGMENT_FLAG))) {
447 // TODO: Log debug message: Can only specify compute shader when doing compute
Chia-I Wu3efef432014-08-28 15:00:16 +0800448 return XGL_ERROR_BAD_PIPELINE_DATA;
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600449 }
450
451 /*
Courtney Goeltzenleuchter42509992014-08-21 17:33:46 -0600452 * XGL_TOPOLOGY_PATCH primitive topology is only valid for tessellation pipelines.
453 * Mismatching primitive topology and tessellation fails graphics pipeline creation.
454 */
455 if (pipeline->active_shaders & (SHADER_TESS_CONTROL_FLAG | SHADER_TESS_EVAL_FLAG) &&
Chia-I Wube0a3d92014-09-02 13:20:59 +0800456 (pipeline->topology != XGL_TOPOLOGY_PATCH)) {
Courtney Goeltzenleuchter42509992014-08-21 17:33:46 -0600457 // TODO: Log debug message: Invalid topology used with tessalation shader.
Chia-I Wu3efef432014-08-28 15:00:16 +0800458 return XGL_ERROR_BAD_PIPELINE_DATA;
Courtney Goeltzenleuchter42509992014-08-21 17:33:46 -0600459 }
460
Chia-I Wube0a3d92014-09-02 13:20:59 +0800461 if ((pipeline->topology == XGL_TOPOLOGY_PATCH) &&
Courtney Goeltzenleuchter42509992014-08-21 17:33:46 -0600462 (pipeline->active_shaders & ~(SHADER_TESS_CONTROL_FLAG | SHADER_TESS_EVAL_FLAG))) {
463 // TODO: Log debug message: Cannot use TOPOLOGY_PATCH on non-tessalation shader.
Chia-I Wu3efef432014-08-28 15:00:16 +0800464 return XGL_ERROR_BAD_PIPELINE_DATA;
Courtney Goeltzenleuchter42509992014-08-21 17:33:46 -0600465 }
466
Chia-I Wu3efef432014-08-28 15:00:16 +0800467 return XGL_SUCCESS;
468}
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -0600469
Chia-I Wuf90ff0c2014-09-02 09:32:46 +0800470static void pipeline_build_urb_alloc_gen6(struct intel_pipeline *pipeline,
471 const struct intel_pipeline_create_info *info)
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800472{
Chia-I Wu509b3f22014-09-02 10:24:05 +0800473 const struct intel_gpu *gpu = pipeline->dev->gpu;
474 const int urb_size = ((gpu->gt == 2) ? 64 : 32) * 1024;
Chia-I Wua4d1b392014-10-10 13:57:29 +0800475 const struct intel_pipeline_shader *vs = &pipeline->vs;
476 const struct intel_pipeline_shader *gs = &pipeline->gs;
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800477 int vs_entry_size, gs_entry_size;
478 int vs_size, gs_size;
479
Chia-I Wu509b3f22014-09-02 10:24:05 +0800480 INTEL_GPU_ASSERT(gpu, 6, 6);
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800481
482 vs_entry_size = ((vs->in_count >= vs->out_count) ?
483 vs->in_count : vs->out_count);
484 gs_entry_size = (gs) ? gs->out_count : 0;
485
486 /* in bytes */
487 vs_entry_size *= sizeof(float) * 4;
488 gs_entry_size *= sizeof(float) * 4;
489
Chia-I Wua4d1b392014-10-10 13:57:29 +0800490 if (pipeline->active_shaders & SHADER_GEOMETRY_FLAG) {
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800491 vs_size = urb_size / 2;
492 gs_size = vs_size;
493 } else {
494 vs_size = urb_size;
495 gs_size = 0;
496 }
497
498 /* 3DSTATE_URB */
499 {
500 const uint8_t cmd_len = 3;
501 const uint32_t dw0 = GEN6_RENDER_CMD(3D, 3DSTATE_URB) |
502 (cmd_len - 2);
503 int vs_alloc_size, gs_alloc_size;
504 int vs_entry_count, gs_entry_count;
505 uint32_t *dw;
506
507 /* in 1024-bit rows */
508 vs_alloc_size = (vs_entry_size + 128 - 1) / 128;
509 gs_alloc_size = (gs_entry_size + 128 - 1) / 128;
510
511 /* valid range is [1, 5] */
512 if (!vs_alloc_size)
513 vs_alloc_size = 1;
514 if (!gs_alloc_size)
515 gs_alloc_size = 1;
516 assert(vs_alloc_size <= 5 && gs_alloc_size <= 5);
517
518 /* valid range is [24, 256], multiples of 4 */
519 vs_entry_count = (vs_size / 128 / vs_alloc_size) & ~3;
520 if (vs_entry_count > 256)
521 vs_entry_count = 256;
522 assert(vs_entry_count >= 24);
523
524 /* valid range is [0, 256], multiples of 4 */
525 gs_entry_count = (gs_size / 128 / gs_alloc_size) & ~3;
526 if (gs_entry_count > 256)
527 gs_entry_count = 256;
528
Courtney Goeltzenleuchter814cd292014-08-28 13:16:27 -0600529 dw = pipeline_cmd_ptr(pipeline, cmd_len);
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800530
531 dw[0] = dw0;
532 dw[1] = (vs_alloc_size - 1) << GEN6_URB_DW1_VS_ENTRY_SIZE__SHIFT |
533 vs_entry_count << GEN6_URB_DW1_VS_ENTRY_COUNT__SHIFT;
534 dw[2] = gs_entry_count << GEN6_URB_DW2_GS_ENTRY_COUNT__SHIFT |
535 (gs_alloc_size - 1) << GEN6_URB_DW2_GS_ENTRY_SIZE__SHIFT;
536 }
537}
538
Chia-I Wuf90ff0c2014-09-02 09:32:46 +0800539static void pipeline_build_urb_alloc_gen7(struct intel_pipeline *pipeline,
540 const struct intel_pipeline_create_info *info)
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800541{
Chia-I Wu509b3f22014-09-02 10:24:05 +0800542 const struct intel_gpu *gpu = pipeline->dev->gpu;
543 const int urb_size = ((gpu->gt == 3) ? 512 :
544 (gpu->gt == 2) ? 256 : 128) * 1024;
Cody Northrop306ec352014-10-06 15:11:45 -0600545 const struct intel_pipeline_shader *vs = &pipeline->vs;
546 const struct intel_pipeline_shader *gs = &pipeline->gs;
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800547 /* some space is reserved for PCBs */
Chia-I Wu509b3f22014-09-02 10:24:05 +0800548 int urb_offset = ((gpu->gt == 3) ? 32 : 16) * 1024;
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800549 int vs_entry_size, gs_entry_size;
550 int vs_size, gs_size;
551
Chia-I Wu509b3f22014-09-02 10:24:05 +0800552 INTEL_GPU_ASSERT(gpu, 7, 7.5);
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800553
554 vs_entry_size = ((vs->in_count >= vs->out_count) ?
555 vs->in_count : vs->out_count);
556 gs_entry_size = (gs) ? gs->out_count : 0;
557
558 /* in bytes */
559 vs_entry_size *= sizeof(float) * 4;
560 gs_entry_size *= sizeof(float) * 4;
561
Chia-I Wua4d1b392014-10-10 13:57:29 +0800562 if (pipeline->active_shaders & SHADER_GEOMETRY_FLAG) {
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800563 vs_size = (urb_size - urb_offset) / 2;
564 gs_size = vs_size;
565 } else {
566 vs_size = urb_size - urb_offset;
567 gs_size = 0;
568 }
569
570 /* 3DSTATE_URB_* */
571 {
572 const uint8_t cmd_len = 2;
573 int vs_alloc_size, gs_alloc_size;
574 int vs_entry_count, gs_entry_count;
575 uint32_t *dw;
576
577 /* in 512-bit rows */
578 vs_alloc_size = (vs_entry_size + 64 - 1) / 64;
579 gs_alloc_size = (gs_entry_size + 64 - 1) / 64;
580
581 if (!vs_alloc_size)
582 vs_alloc_size = 1;
583 if (!gs_alloc_size)
584 gs_alloc_size = 1;
585
586 /* avoid performance decrease due to banking */
587 if (vs_alloc_size == 5)
588 vs_alloc_size = 6;
589
590 /* in multiples of 8 */
591 vs_entry_count = (vs_size / 64 / vs_alloc_size) & ~7;
592 assert(vs_entry_count >= 32);
593
594 gs_entry_count = (gs_size / 64 / gs_alloc_size) & ~7;
595
Chia-I Wu509b3f22014-09-02 10:24:05 +0800596 if (intel_gpu_gen(gpu) >= INTEL_GEN(7.5)) {
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800597 const int max_vs_entry_count =
Chia-I Wu509b3f22014-09-02 10:24:05 +0800598 (gpu->gt >= 2) ? 1664 : 640;
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800599 const int max_gs_entry_count =
Chia-I Wu509b3f22014-09-02 10:24:05 +0800600 (gpu->gt >= 2) ? 640 : 256;
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800601 if (vs_entry_count >= max_vs_entry_count)
602 vs_entry_count = max_vs_entry_count;
603 if (gs_entry_count >= max_gs_entry_count)
604 gs_entry_count = max_gs_entry_count;
605 } else {
606 const int max_vs_entry_count =
Chia-I Wu509b3f22014-09-02 10:24:05 +0800607 (gpu->gt == 2) ? 704 : 512;
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800608 const int max_gs_entry_count =
Chia-I Wu509b3f22014-09-02 10:24:05 +0800609 (gpu->gt == 2) ? 320 : 192;
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800610 if (vs_entry_count >= max_vs_entry_count)
611 vs_entry_count = max_vs_entry_count;
612 if (gs_entry_count >= max_gs_entry_count)
613 gs_entry_count = max_gs_entry_count;
614 }
615
Courtney Goeltzenleuchter814cd292014-08-28 13:16:27 -0600616 dw = pipeline_cmd_ptr(pipeline, cmd_len*4);
Chia-I Wubb2d8ca2014-08-28 23:15:48 +0800617 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_URB_VS) | (cmd_len - 2);
618 dw[1] = (urb_offset / 8192) << GEN7_URB_ANY_DW1_OFFSET__SHIFT |
619 (vs_alloc_size - 1) << GEN7_URB_ANY_DW1_ENTRY_SIZE__SHIFT |
620 vs_entry_count;
621
622 dw += 2;
623 if (gs_size)
624 urb_offset += vs_size;
625 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_URB_GS) | (cmd_len - 2);
626 dw[1] = (urb_offset / 8192) << GEN7_URB_ANY_DW1_OFFSET__SHIFT |
627 (gs_alloc_size - 1) << GEN7_URB_ANY_DW1_ENTRY_SIZE__SHIFT |
628 gs_entry_count;
629
630 dw += 2;
631 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_URB_HS) | (cmd_len - 2);
632 dw[1] = (urb_offset / 8192) << GEN7_URB_ANY_DW1_OFFSET__SHIFT;
633
634 dw += 2;
635 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_URB_DS) | (cmd_len - 2);
636 dw[1] = (urb_offset / 8192) << GEN7_URB_ANY_DW1_OFFSET__SHIFT;
637 }
638}
639
Chia-I Wuf90ff0c2014-09-02 09:32:46 +0800640static void pipeline_build_push_const_alloc_gen7(struct intel_pipeline *pipeline,
641 const struct intel_pipeline_create_info *info)
Courtney Goeltzenleuchterb2867702014-08-28 17:44:05 -0600642{
643 const uint8_t cmd_len = 2;
644 uint32_t offset = 0;
645 uint32_t size = 8192;
646 uint32_t *dw;
647 int end;
648
Chia-I Wu509b3f22014-09-02 10:24:05 +0800649 INTEL_GPU_ASSERT(pipeline->dev->gpu, 7, 7.5);
Courtney Goeltzenleuchterb2867702014-08-28 17:44:05 -0600650
651 /*
652 * From the Ivy Bridge PRM, volume 2 part 1, page 68:
653 *
654 * "(A table that says the maximum size of each constant buffer is
655 * 16KB")
656 *
657 * From the Ivy Bridge PRM, volume 2 part 1, page 115:
658 *
659 * "The sum of the Constant Buffer Offset and the Constant Buffer Size
660 * may not exceed the maximum value of the Constant Buffer Size."
661 *
662 * Thus, the valid range of buffer end is [0KB, 16KB].
663 */
664 end = (offset + size) / 1024;
665 if (end > 16) {
666 assert(!"invalid constant buffer end");
667 end = 16;
668 }
669
670 /* the valid range of buffer offset is [0KB, 15KB] */
671 offset = (offset + 1023) / 1024;
672 if (offset > 15) {
673 assert(!"invalid constant buffer offset");
674 offset = 15;
675 }
676
677 if (offset > end) {
678 assert(!size);
679 offset = end;
680 }
681
682 /* the valid range of buffer size is [0KB, 15KB] */
683 size = end - offset;
684 if (size > 15) {
685 assert(!"invalid constant buffer size");
686 size = 15;
687 }
688
Chia-I Wuf90ff0c2014-09-02 09:32:46 +0800689 dw = pipeline_cmd_ptr(pipeline, cmd_len * 5);
Courtney Goeltzenleuchterb2867702014-08-28 17:44:05 -0600690 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_PUSH_CONSTANT_ALLOC_VS) | (cmd_len - 2);
691 dw[1] = offset << GEN7_PCB_ALLOC_ANY_DW1_OFFSET__SHIFT |
692 size << GEN7_PCB_ALLOC_ANY_DW1_SIZE__SHIFT;
693
694 dw += 2;
695 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_PUSH_CONSTANT_ALLOC_PS) | (cmd_len - 2);
696 dw[1] = size << GEN7_PCB_ALLOC_ANY_DW1_OFFSET__SHIFT |
697 size << GEN7_PCB_ALLOC_ANY_DW1_SIZE__SHIFT;
698
699 dw += 2;
700 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_PUSH_CONSTANT_ALLOC_HS) | (cmd_len - 2);
701 dw[1] = 0 << GEN7_PCB_ALLOC_ANY_DW1_OFFSET__SHIFT |
702 0 << GEN7_PCB_ALLOC_ANY_DW1_SIZE__SHIFT;
703
704 dw += 2;
705 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_PUSH_CONSTANT_ALLOC_DS) | (cmd_len - 2);
706 dw[1] = 0 << GEN7_PCB_ALLOC_ANY_DW1_OFFSET__SHIFT |
707 0 << GEN7_PCB_ALLOC_ANY_DW1_SIZE__SHIFT;
708
709 dw += 2;
710 dw[0] = GEN7_RENDER_CMD(3D, 3DSTATE_PUSH_CONSTANT_ALLOC_GS) | (cmd_len - 2);
711 dw[1] = 0 << GEN7_PCB_ALLOC_ANY_DW1_OFFSET__SHIFT |
712 0 << GEN7_PCB_ALLOC_ANY_DW1_SIZE__SHIFT;
Chia-I Wu8370b402014-08-29 12:28:37 +0800713
Courtney Goeltzenleuchterb2867702014-08-28 17:44:05 -0600714 // gen7_wa_pipe_control_cs_stall(p, true, true);
715 // looks equivalent to: gen6_wa_wm_multisample_flush - this does more
716 // than the documentation seems to imply
717}
718
Chia-I Wuf90ff0c2014-09-02 09:32:46 +0800719static void pipeline_build_vertex_elements(struct intel_pipeline *pipeline,
720 const struct intel_pipeline_create_info *info)
Chia-I Wu4d9ad912014-08-29 14:20:36 +0800721{
Cody Northrop306ec352014-10-06 15:11:45 -0600722 const struct intel_pipeline_shader *vs = &pipeline->vs;
Chia-I Wu1d125092014-10-08 08:49:38 +0800723 uint8_t cmd_len;
Chia-I Wu4d9ad912014-08-29 14:20:36 +0800724 uint32_t *dw;
Chia-I Wu1d125092014-10-08 08:49:38 +0800725 XGL_UINT i;
726 int comps[4];
Chia-I Wu4d9ad912014-08-29 14:20:36 +0800727
Chia-I Wu509b3f22014-09-02 10:24:05 +0800728 INTEL_GPU_ASSERT(pipeline->dev->gpu, 6, 7.5);
Chia-I Wu4d9ad912014-08-29 14:20:36 +0800729
GregF8cd81832014-11-18 18:01:01 -0700730 cmd_len = 1 + 2 * u_popcountll(vs->inputs_read);
Chia-I Wu1d125092014-10-08 08:49:38 +0800731 if (vs->uses & (INTEL_SHADER_USE_VID | INTEL_SHADER_USE_IID))
732 cmd_len += 2;
733
734 if (cmd_len == 1)
Chia-I Wu4d9ad912014-08-29 14:20:36 +0800735 return;
736
737 dw = pipeline_cmd_ptr(pipeline, cmd_len);
Chia-I Wu1d125092014-10-08 08:49:38 +0800738
739 dw[0] = GEN6_RENDER_CMD(3D, 3DSTATE_VERTEX_ELEMENTS) |
740 (cmd_len - 2);
Chia-I Wu4d9ad912014-08-29 14:20:36 +0800741 dw++;
742
Chia-I Wu4d9ad912014-08-29 14:20:36 +0800743 /* VERTEX_ELEMENT_STATE */
Chia-I Wu1d125092014-10-08 08:49:38 +0800744 for (i = 0; i < info->vi.attributeCount; i++) {
GregF8cd81832014-11-18 18:01:01 -0700745 if (!(vs->inputs_read & (1L << i)))
GregF2dc40212014-10-31 17:31:47 -0600746 continue;
Chia-I Wu1d125092014-10-08 08:49:38 +0800747 const XGL_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION *attr =
748 &info->vi.pVertexAttributeDescriptions[i];
749 const int format =
750 intel_format_translate_color(pipeline->dev->gpu, attr->format);
751
752 comps[0] = GEN6_VFCOMP_STORE_0;
753 comps[1] = GEN6_VFCOMP_STORE_0;
754 comps[2] = GEN6_VFCOMP_STORE_0;
755 comps[3] = icd_format_is_int(attr->format) ?
756 GEN6_VFCOMP_STORE_1_INT : GEN6_VFCOMP_STORE_1_FP;
757
758 switch (icd_format_get_channel_count(attr->format)) {
759 case 4: comps[3] = GEN6_VFCOMP_STORE_SRC; /* fall through */
760 case 3: comps[2] = GEN6_VFCOMP_STORE_SRC; /* fall through */
761 case 2: comps[1] = GEN6_VFCOMP_STORE_SRC; /* fall through */
762 case 1: comps[0] = GEN6_VFCOMP_STORE_SRC; break;
763 default:
764 break;
765 }
766
767 assert(attr->offsetInBytes <= 2047);
768
769 dw[0] = attr->binding << GEN6_VE_STATE_DW0_VB_INDEX__SHIFT |
770 GEN6_VE_STATE_DW0_VALID |
771 format << GEN6_VE_STATE_DW0_FORMAT__SHIFT |
772 attr->offsetInBytes;
773
774 dw[1] = comps[0] << GEN6_VE_STATE_DW1_COMP0__SHIFT |
775 comps[1] << GEN6_VE_STATE_DW1_COMP1__SHIFT |
776 comps[2] << GEN6_VE_STATE_DW1_COMP2__SHIFT |
777 comps[3] << GEN6_VE_STATE_DW1_COMP3__SHIFT;
778
779 dw += 2;
780 }
GregF932fcf52014-10-29 17:02:11 -0600781
782 if (vs->uses & (INTEL_SHADER_USE_VID | INTEL_SHADER_USE_IID)) {
783 comps[0] = (vs->uses & INTEL_SHADER_USE_VID) ?
784 GEN6_VFCOMP_STORE_VID : GEN6_VFCOMP_STORE_0;
785 comps[1] = (vs->uses & INTEL_SHADER_USE_IID) ?
786 GEN6_VFCOMP_STORE_IID : GEN6_VFCOMP_NOSTORE;
787 comps[2] = GEN6_VFCOMP_NOSTORE;
788 comps[3] = GEN6_VFCOMP_NOSTORE;
789
790 dw[0] = GEN6_VE_STATE_DW0_VALID;
791 dw[1] = comps[0] << GEN6_VE_STATE_DW1_COMP0__SHIFT |
792 comps[1] << GEN6_VE_STATE_DW1_COMP1__SHIFT |
793 comps[2] << GEN6_VE_STATE_DW1_COMP2__SHIFT |
794 comps[3] << GEN6_VE_STATE_DW1_COMP3__SHIFT;
795
796 dw += 2;
797 }
Chia-I Wu4d9ad912014-08-29 14:20:36 +0800798}
799
GregF8cd81832014-11-18 18:01:01 -0700800static void pipeline_build_fragment_SBE(struct intel_pipeline *pipeline)
801{
802 const struct intel_pipeline_shader *fs = &pipeline->fs;
803 const struct intel_pipeline_shader *vs = &pipeline->vs;
804 uint8_t cmd_len;
805 uint32_t *body;
806 XGL_UINT attr_skip, attr_count;
807 XGL_UINT vue_offset, vue_len;
808 XGL_UINT i;
809
810 INTEL_GPU_ASSERT(pipeline->dev->gpu, 6, 7.5);
811
812 cmd_len = 14;
813
814 body = pipeline_cmd_ptr(pipeline, cmd_len);
815 pipeline->cmd_sbe_body_offset = body - pipeline->cmds + 1;
816
817 /* VS outputs VUE header and position additionally */
818 assert(vs->out_count >= fs->in_count + 2);
819 assert(!fs->reads_user_clip || vs->enable_user_clip);
820 attr_skip = vs->outputs_offset;
821 if (vs->enable_user_clip != fs->reads_user_clip) {
822 attr_skip += 2;
823 }
824 assert(vs->out_count >= attr_skip);
825 attr_count = vs->out_count - attr_skip;
826
827 // LUNARG TODO: We currently are only handling 16 attrs;
828 // ultimately, we need to handle 32
829 assert(fs->in_count <= 16);
830 assert(attr_count <= 16);
831
832 vue_offset = attr_skip / 2;
833 vue_len = (attr_count + 1) / 2;
834 if (!vue_len)
835 vue_len = 1;
836
837 body[0] = GEN7_RENDER_CMD(3D, 3DSTATE_SBE) |
838 (cmd_len - 2);
839
840 // LUNARG TODO: If the attrs needed by the FS are exactly
841 // what is written by the VS, we don't need to enable
842 // swizzling, improving performance. Even if we swizzle,
843 // we can improve performance by reducing vue_len to
844 // just include the values needed by the FS:
845 // vue_len = ceiling((max_vs_out + 1)/2)
846
847 body[1] = GEN7_SBE_DW1_ATTR_SWIZZLE_ENABLE |
848 fs->in_count << GEN7_SBE_DW1_ATTR_COUNT__SHIFT |
849 vue_len << GEN7_SBE_DW1_URB_READ_LEN__SHIFT |
850 vue_offset << GEN7_SBE_DW1_URB_READ_OFFSET__SHIFT;
851
852 uint16_t vs_slot[fs->in_count];
853 XGL_INT fs_in = 0;
854 XGL_INT vs_out = - (vue_offset * 2 - vs->outputs_offset);
855 for (i=0; i < 64; i++) {
Cody Northropd75c13e2015-01-02 14:07:20 -0700856 bool vsWrites = vs->outputs_written & (1L << i);
857 bool fsReads = fs->inputs_read & (1L << i);
858
859 if (fsReads) {
GregF8cd81832014-11-18 18:01:01 -0700860 assert(vs_out >= 0);
861 assert(fs_in < fs->in_count);
862 vs_slot[fs_in] = vs_out;
Cody Northropd75c13e2015-01-02 14:07:20 -0700863
864 if (!vsWrites) {
865 // If the vertex shader did not write this input, we cannot
866 // program the SBE to read it. Our choices are to allow it to
867 // read junk from a GRF, or get zero. We're choosing zero.
868 if (i >= fs->generic_input_start) {
869 vs_slot[fs_in] = GEN7_SBE_ATTR_CONST_0000 |
870 GEN7_SBE_ATTR_OVERRIDE_X |
871 GEN7_SBE_ATTR_OVERRIDE_Y |
872 GEN7_SBE_ATTR_OVERRIDE_Z |
873 GEN7_SBE_ATTR_OVERRIDE_W;
874 }
875 }
876
GregF8cd81832014-11-18 18:01:01 -0700877 fs_in += 1;
878 }
Cody Northropd75c13e2015-01-02 14:07:20 -0700879 if (vsWrites) {
GregF8cd81832014-11-18 18:01:01 -0700880 vs_out += 1;
881 }
882 }
883
884 for (i = 0; i < 8; i++) {
885 uint16_t hi, lo;
886
887 /* no attr swizzles */
888 if (i * 2 + 1 < fs->in_count) {
889 lo = vs_slot[i * 2];
890 hi = vs_slot[i * 2 + 1];
891 } else if (i * 2 < fs->in_count) {
892 lo = vs_slot[i * 2];
893 hi = 0;
894 } else {
895 hi = 0;
896 lo = 0;
897 }
898
899 body[2 + i] = hi << GEN7_SBE_ATTR_HIGH__SHIFT | lo;
900 }
901
902 body[10] = 0; /* point sprite enables */
903 body[11] = 0; /* constant interpolation enables */
904 body[12] = 0; /* WrapShortest enables */
905 body[13] = 0;
906}
907
Chia-I Wuf90ff0c2014-09-02 09:32:46 +0800908static void pipeline_build_gs(struct intel_pipeline *pipeline,
909 const struct intel_pipeline_create_info *info)
Courtney Goeltzenleuchterb2867702014-08-28 17:44:05 -0600910{
Courtney Goeltzenleuchterb2867702014-08-28 17:44:05 -0600911 // gen7_emit_3DSTATE_GS done by cmd_pipeline
Courtney Goeltzenleuchterb2867702014-08-28 17:44:05 -0600912}
913
Chia-I Wuf90ff0c2014-09-02 09:32:46 +0800914static void pipeline_build_hs(struct intel_pipeline *pipeline,
915 const struct intel_pipeline_create_info *info)
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600916{
917 const uint8_t cmd_len = 7;
918 const uint32_t dw0 = GEN7_RENDER_CMD(3D, 3DSTATE_HS) | (cmd_len - 2);
919 uint32_t *dw;
920
Chia-I Wu509b3f22014-09-02 10:24:05 +0800921 INTEL_GPU_ASSERT(pipeline->dev->gpu, 7, 7.5);
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600922
Chia-I Wuf90ff0c2014-09-02 09:32:46 +0800923 dw = pipeline_cmd_ptr(pipeline, cmd_len);
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600924 dw[0] = dw0;
925 dw[1] = 0;
926 dw[2] = 0;
927 dw[3] = 0;
928 dw[4] = 0;
929 dw[5] = 0;
930 dw[6] = 0;
931}
932
Chia-I Wuf90ff0c2014-09-02 09:32:46 +0800933static void pipeline_build_te(struct intel_pipeline *pipeline,
934 const struct intel_pipeline_create_info *info)
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600935{
936 const uint8_t cmd_len = 4;
937 const uint32_t dw0 = GEN7_RENDER_CMD(3D, 3DSTATE_TE) | (cmd_len - 2);
938 uint32_t *dw;
939
Chia-I Wu509b3f22014-09-02 10:24:05 +0800940 INTEL_GPU_ASSERT(pipeline->dev->gpu, 7, 7.5);
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600941
Chia-I Wuf90ff0c2014-09-02 09:32:46 +0800942 dw = pipeline_cmd_ptr(pipeline, cmd_len);
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600943 dw[0] = dw0;
944 dw[1] = 0;
945 dw[2] = 0;
946 dw[3] = 0;
947}
948
Chia-I Wuf90ff0c2014-09-02 09:32:46 +0800949static void pipeline_build_ds(struct intel_pipeline *pipeline,
950 const struct intel_pipeline_create_info *info)
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600951{
952 const uint8_t cmd_len = 6;
953 const uint32_t dw0 = GEN7_RENDER_CMD(3D, 3DSTATE_DS) | (cmd_len - 2);
954 uint32_t *dw;
955
Chia-I Wu509b3f22014-09-02 10:24:05 +0800956 INTEL_GPU_ASSERT(pipeline->dev->gpu, 7, 7.5);
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600957
Chia-I Wuf90ff0c2014-09-02 09:32:46 +0800958 dw = pipeline_cmd_ptr(pipeline, cmd_len);
Courtney Goeltzenleuchterdee81a62014-08-28 18:05:24 -0600959 dw[0] = dw0;
960 dw[1] = 0;
961 dw[2] = 0;
962 dw[3] = 0;
963 dw[4] = 0;
964 dw[5] = 0;
965}
966
Tony Barbourfa6cac72015-01-16 14:27:35 -0700967static void pipeline_build_depth_stencil(struct intel_pipeline *pipeline,
968 const struct intel_pipeline_create_info *info)
969{
970 pipeline->cmd_depth_stencil = 0;
971
972 if (info->db.stencilTestEnable) {
973 pipeline->cmd_depth_stencil = 1 << 31 |
974 translate_compare_func(info->db.front.stencilFunc) << 28 |
975 translate_stencil_op(info->db.front.stencilFailOp) << 25 |
976 translate_stencil_op(info->db.front.stencilDepthFailOp) << 22 |
977 translate_stencil_op(info->db.front.stencilPassOp) << 19 |
978 1 << 15 |
979 translate_compare_func(info->db.back.stencilFunc) << 12 |
980 translate_stencil_op(info->db.back.stencilFailOp) << 9 |
981 translate_stencil_op(info->db.back.stencilDepthFailOp) << 6 |
982 translate_stencil_op(info->db.back.stencilPassOp) << 3;
983 }
984
985 pipeline->stencilTestEnable = info->db.stencilTestEnable;
986
987 /*
988 * From the Sandy Bridge PRM, volume 2 part 1, page 360:
989 *
990 * "Enabling the Depth Test function without defining a Depth Buffer is
991 * UNDEFINED."
992 *
993 * From the Sandy Bridge PRM, volume 2 part 1, page 375:
994 *
995 * "A Depth Buffer must be defined before enabling writes to it, or
996 * operation is UNDEFINED."
997 *
998 * TODO We do not check these yet.
999 */
1000 if (info->db.depthTestEnable) {
1001 pipeline->cmd_depth_test = GEN6_ZS_DW2_DEPTH_TEST_ENABLE |
1002 translate_compare_func(info->db.depthFunc) << 27;
1003 } else {
1004 pipeline->cmd_depth_test = GEN6_COMPAREFUNCTION_ALWAYS << 27;
1005 }
1006
1007 if (info->db.depthWriteEnable)
1008 pipeline->cmd_depth_test |= GEN6_ZS_DW2_DEPTH_WRITE_ENABLE;
1009}
1010
1011static void pipeline_init_sample_pattern(struct intel_pipeline *pipeline,
1012 uint8_t *samples)
1013{
1014 struct sample {
1015 int x, y;
1016 };
1017 static const struct sample default_pattern_2x[2] = {
1018 { -4, -4 },
1019 { 4, 4 },
1020 };
1021 static const struct sample default_pattern_4x[4] = {
1022 { -2, -6 },
1023 { 6, -2 },
1024 { -6, 2 },
1025 { 2, 6 },
1026 };
1027 static const struct sample default_pattern_8x[8] = {
1028 { 1, -3 },
1029 { -1, 3 },
1030 { 5, 1 },
1031 { -3, -5 },
1032 { -5, 5 },
1033 { -7, -1 },
1034 { 3, 7 },
1035 { 7, -7 },
1036 };
1037
1038 const struct sample *pattern;
1039 int i;
1040
1041 switch (pipeline->sample_count) {
1042 case 2:
1043 pattern = default_pattern_2x;
1044 break;
1045 case 4:
1046 pattern = default_pattern_4x;
1047 break;
1048 case 8:
1049 pattern = default_pattern_8x;
1050 break;
1051 default:
1052 memset(samples, 0, pipeline->sample_count);
1053 return;
1054 break;
1055 }
1056
1057 for (i = 0; i < pipeline->sample_count; i++)
1058 samples[i] = (pattern[i].x + 8) << 4 | (pattern[i].y + 8);
1059}
1060
1061static void pipeline_build_msaa(struct intel_pipeline *pipeline,
1062 const struct intel_pipeline_create_info *info)
1063{
1064 uint32_t cmd, cmd_len;
1065 uint32_t *dw;
1066
1067 INTEL_GPU_ASSERT(pipeline->dev->gpu, 6, 7.5);
1068
1069
1070 pipeline->sample_count = (info->ms.samples <= 1)?1:info->ms.samples;
1071
1072 /* 3DSTATE_MULTISAMPLE */
1073 cmd = GEN6_RENDER_CMD(3D, 3DSTATE_MULTISAMPLE);
1074 cmd_len = (intel_gpu_gen(pipeline->dev->gpu) >= INTEL_GEN(7)) ? 4 : 3;
1075 dw = pipeline_cmd_ptr(pipeline, cmd_len + 2);
1076 dw[0] = cmd | (cmd_len - 2);
1077 if (pipeline->sample_count <= 1)
1078 dw[1] = GEN6_MULTISAMPLE_DW1_NUMSAMPLES_1;
1079 else if (pipeline->sample_count <= 4 || intel_gpu_gen(pipeline->dev->gpu) == INTEL_GEN(6))
1080 dw[1] = GEN6_MULTISAMPLE_DW1_NUMSAMPLES_4;
1081 else
1082 dw[1] = GEN7_MULTISAMPLE_DW1_NUMSAMPLES_8;
1083
1084 pipeline_init_sample_pattern(pipeline, (uint8_t *) &dw[2]);
1085
1086 dw += cmd_len;
1087
1088 /* 3DSTATE_SAMPLE_MASK */
1089 cmd = GEN6_RENDER_CMD(3D, 3DSTATE_SAMPLE_MASK);
1090 cmd_len = 2;
1091
1092 dw[0] = cmd | (cmd_len - 2);
1093 dw[1] = info->ms.sampleMask & ((1 << pipeline->sample_count) - 1);
1094 pipeline->cmd_sample_mask = dw[1];
1095}
1096
1097static void pipeline_build_cb(struct intel_pipeline *pipeline,
1098 const struct intel_pipeline_create_info *info)
1099{
1100 XGL_UINT i;
1101
1102 INTEL_GPU_ASSERT(pipeline->dev->gpu, 6, 7.5);
1103 STATIC_ASSERT(ARRAY_SIZE(pipeline->cmd_cb) >= INTEL_MAX_RENDER_TARGETS*2);
1104 assert(info->cb.attachmentCount <= INTEL_MAX_RENDER_TARGETS);
1105
1106 uint32_t *dw = pipeline->cmd_cb;
1107
1108 for (i = 0; i < info->cb.attachmentCount; i++) {
1109 const XGL_PIPELINE_CB_ATTACHMENT_STATE *att = &info->cb.pAttachments[i];
1110 uint32_t dw0, dw1;
1111
1112
1113 dw0 = 0;
1114 dw1 = GEN6_BLEND_DW1_COLORCLAMP_RTFORMAT |
1115 GEN6_BLEND_DW1_PRE_BLEND_CLAMP |
1116 GEN6_BLEND_DW1_POST_BLEND_CLAMP;
1117
1118 if (att->blendEnable) {
1119 dw0 = 1 << 31 |
1120 translate_blend_func(att->blendFuncAlpha) << 26 |
1121 translate_blend(att->srcBlendAlpha) << 20 |
1122 translate_blend(att->destBlendAlpha) << 15 |
1123 translate_blend_func(att->blendFuncColor) << 11 |
1124 translate_blend(att->srcBlendColor) << 5 |
1125 translate_blend(att->destBlendColor);
1126
1127 if (att->blendFuncAlpha != att->blendFuncColor ||
1128 att->srcBlendAlpha != att->srcBlendColor ||
1129 att->destBlendAlpha != att->destBlendColor)
1130 dw0 |= 1 << 30;
1131 }
1132
1133 if (info->cb.logicOp != XGL_LOGIC_OP_COPY) {
1134 int logicop;
1135
1136 switch (info->cb.logicOp) {
1137 case XGL_LOGIC_OP_CLEAR: logicop = GEN6_LOGICOP_CLEAR; break;
1138 case XGL_LOGIC_OP_AND: logicop = GEN6_LOGICOP_AND; break;
1139 case XGL_LOGIC_OP_AND_REVERSE: logicop = GEN6_LOGICOP_AND_REVERSE; break;
1140 case XGL_LOGIC_OP_AND_INVERTED: logicop = GEN6_LOGICOP_AND_INVERTED; break;
1141 case XGL_LOGIC_OP_NOOP: logicop = GEN6_LOGICOP_NOOP; break;
1142 case XGL_LOGIC_OP_XOR: logicop = GEN6_LOGICOP_XOR; break;
1143 case XGL_LOGIC_OP_OR: logicop = GEN6_LOGICOP_OR; break;
1144 case XGL_LOGIC_OP_NOR: logicop = GEN6_LOGICOP_NOR; break;
1145 case XGL_LOGIC_OP_EQUIV: logicop = GEN6_LOGICOP_EQUIV; break;
1146 case XGL_LOGIC_OP_INVERT: logicop = GEN6_LOGICOP_INVERT; break;
1147 case XGL_LOGIC_OP_OR_REVERSE: logicop = GEN6_LOGICOP_OR_REVERSE; break;
1148 case XGL_LOGIC_OP_COPY_INVERTED: logicop = GEN6_LOGICOP_COPY_INVERTED; break;
1149 case XGL_LOGIC_OP_OR_INVERTED: logicop = GEN6_LOGICOP_OR_INVERTED; break;
1150 case XGL_LOGIC_OP_NAND: logicop = GEN6_LOGICOP_NAND; break;
1151 case XGL_LOGIC_OP_SET: logicop = GEN6_LOGICOP_SET; break;
1152 default:
1153 assert(!"unknown logic op");
1154 logicop = GEN6_LOGICOP_CLEAR;
1155 break;
1156 }
1157
1158 dw1 |= GEN6_BLEND_DW1_LOGICOP_ENABLE |
1159 logicop << GEN6_BLEND_DW1_LOGICOP_FUNC__SHIFT;
1160 }
1161
1162 if (!(att->channelWriteMask & 0x1))
1163 dw1 |= GEN6_BLEND_DW1_WRITE_DISABLE_R;
1164 if (!(att->channelWriteMask & 0x2))
1165 dw1 |= GEN6_BLEND_DW1_WRITE_DISABLE_G;
1166 if (!(att->channelWriteMask & 0x4))
1167 dw1 |= GEN6_BLEND_DW1_WRITE_DISABLE_B;
1168 if (!(att->channelWriteMask & 0x8))
1169 dw1 |= GEN6_BLEND_DW1_WRITE_DISABLE_A;
1170
1171 dw[2 * i] = dw0;
1172 dw[2 * i + 1] = dw1;
1173 }
1174
1175 for (i=info->cb.attachmentCount; i < INTEL_MAX_RENDER_TARGETS; i++)
1176 {
1177 dw[2 * i] = 0;
1178 dw[2 * i + 1] = GEN6_BLEND_DW1_COLORCLAMP_RTFORMAT |
1179 GEN6_BLEND_DW1_PRE_BLEND_CLAMP |
1180 GEN6_BLEND_DW1_POST_BLEND_CLAMP |
1181 GEN6_BLEND_DW1_WRITE_DISABLE_R |
1182 GEN6_BLEND_DW1_WRITE_DISABLE_G |
1183 GEN6_BLEND_DW1_WRITE_DISABLE_B |
1184 GEN6_BLEND_DW1_WRITE_DISABLE_A;
1185 }
1186
1187}
1188
1189
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001190static XGL_RESULT pipeline_build_all(struct intel_pipeline *pipeline,
1191 const struct intel_pipeline_create_info *info)
Chia-I Wu3efef432014-08-28 15:00:16 +08001192{
1193 XGL_RESULT ret;
1194
Chia-I Wu98824592014-09-02 09:42:46 +08001195 ret = pipeline_build_shaders(pipeline, info);
1196 if (ret != XGL_SUCCESS)
1197 return ret;
1198
Chia-I Wu1d125092014-10-08 08:49:38 +08001199 if (info->vi.bindingCount > ARRAY_SIZE(pipeline->vb) ||
1200 info->vi.attributeCount > ARRAY_SIZE(pipeline->vb))
1201 return XGL_ERROR_BAD_PIPELINE_DATA;
1202
1203 pipeline->vb_count = info->vi.bindingCount;
1204 memcpy(pipeline->vb, info->vi.pVertexBindingDescriptions,
1205 sizeof(pipeline->vb[0]) * pipeline->vb_count);
1206
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001207 pipeline_build_vertex_elements(pipeline, info);
GregF8cd81832014-11-18 18:01:01 -07001208 pipeline_build_fragment_SBE(pipeline);
Tony Barbourfa6cac72015-01-16 14:27:35 -07001209 pipeline_build_msaa(pipeline, info);
Chia-I Wu5bdb0962015-01-24 12:49:28 +08001210 pipeline_build_depth_stencil(pipeline, info);
Chia-I Wu4d9ad912014-08-29 14:20:36 +08001211
Chia-I Wu509b3f22014-09-02 10:24:05 +08001212 if (intel_gpu_gen(pipeline->dev->gpu) >= INTEL_GEN(7)) {
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001213 pipeline_build_urb_alloc_gen7(pipeline, info);
1214 pipeline_build_push_const_alloc_gen7(pipeline, info);
1215 pipeline_build_gs(pipeline, info);
1216 pipeline_build_hs(pipeline, info);
1217 pipeline_build_te(pipeline, info);
1218 pipeline_build_ds(pipeline, info);
Chia-I Wu8370b402014-08-29 12:28:37 +08001219
1220 pipeline->wa_flags = INTEL_CMD_WA_GEN6_PRE_DEPTH_STALL_WRITE |
1221 INTEL_CMD_WA_GEN6_PRE_COMMAND_SCOREBOARD_STALL |
1222 INTEL_CMD_WA_GEN7_PRE_VS_DEPTH_STALL_WRITE |
1223 INTEL_CMD_WA_GEN7_POST_COMMAND_CS_STALL |
1224 INTEL_CMD_WA_GEN7_POST_COMMAND_DEPTH_STALL;
Chia-I Wubb2d8ca2014-08-28 23:15:48 +08001225 } else {
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001226 pipeline_build_urb_alloc_gen6(pipeline, info);
Chia-I Wu8370b402014-08-29 12:28:37 +08001227
1228 pipeline->wa_flags = INTEL_CMD_WA_GEN6_PRE_DEPTH_STALL_WRITE |
1229 INTEL_CMD_WA_GEN6_PRE_COMMAND_SCOREBOARD_STALL;
Chia-I Wubb2d8ca2014-08-28 23:15:48 +08001230 }
1231
Chia-I Wube0a3d92014-09-02 13:20:59 +08001232 ret = pipeline_build_ia(pipeline, info);
Chia-I Wu3efef432014-08-28 15:00:16 +08001233
1234 if (ret == XGL_SUCCESS)
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001235 ret = pipeline_rs_state(pipeline, &info->rs);
Chia-I Wu3efef432014-08-28 15:00:16 +08001236
Chia-I Wu3efef432014-08-28 15:00:16 +08001237 if (ret == XGL_SUCCESS) {
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001238 pipeline->db_format = info->db.format;
Tony Barbourfa6cac72015-01-16 14:27:35 -07001239 pipeline_build_cb(pipeline, info);
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001240 pipeline->cb_state = info->cb;
1241 pipeline->tess_state = info->tess;
Chia-I Wu3efef432014-08-28 15:00:16 +08001242 }
1243
Tony Barbourfa6cac72015-01-16 14:27:35 -07001244 pipeline->scissor_enable = info->vp.scissorEnable;
1245
Chia-I Wu3efef432014-08-28 15:00:16 +08001246 return ret;
1247}
1248
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001249struct intel_pipeline_create_info_header {
1250 XGL_STRUCTURE_TYPE struct_type;
1251 const struct intel_pipeline_create_info_header *next;
1252};
1253
1254static XGL_RESULT pipeline_create_info_init(struct intel_pipeline_create_info *info,
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001255 const struct intel_pipeline_create_info_header *header)
Chia-I Wu3efef432014-08-28 15:00:16 +08001256{
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001257 memset(info, 0, sizeof(*info));
Chia-I Wu3efef432014-08-28 15:00:16 +08001258
Tony Barbourfa6cac72015-01-16 14:27:35 -07001259
1260 /*
1261 * Do we need to set safe defaults in case the app doesn't provide all of
1262 * the necessary create infos?
1263 */
1264 info->ms.samples = 1;
1265 info->ms.sampleMask = 1;
1266
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001267 while (header) {
1268 const void *src = (const void *) header;
Chia-I Wu3efef432014-08-28 15:00:16 +08001269 XGL_SIZE size;
1270 void *dst;
1271
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001272 switch (header->struct_type) {
Chia-I Wu3efef432014-08-28 15:00:16 +08001273 case XGL_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO:
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001274 size = sizeof(info->graphics);
1275 dst = &info->graphics;
Chia-I Wu3efef432014-08-28 15:00:16 +08001276 break;
Chia-I Wu1d125092014-10-08 08:49:38 +08001277 case XGL_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_CREATE_INFO:
1278 size = sizeof(info->vi);
1279 dst = &info->vi;
1280 break;
Chia-I Wu3efef432014-08-28 15:00:16 +08001281 case XGL_STRUCTURE_TYPE_PIPELINE_IA_STATE_CREATE_INFO:
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001282 size = sizeof(info->ia);
1283 dst = &info->ia;
Chia-I Wu3efef432014-08-28 15:00:16 +08001284 break;
Tony Barbourfa6cac72015-01-16 14:27:35 -07001285 case XGL_STRUCTURE_TYPE_PIPELINE_DS_STATE_CREATE_INFO:
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001286 size = sizeof(info->db);
1287 dst = &info->db;
Chia-I Wu3efef432014-08-28 15:00:16 +08001288 break;
1289 case XGL_STRUCTURE_TYPE_PIPELINE_CB_STATE_CREATE_INFO:
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001290 size = sizeof(info->cb);
1291 dst = &info->cb;
Chia-I Wu3efef432014-08-28 15:00:16 +08001292 break;
1293 case XGL_STRUCTURE_TYPE_PIPELINE_RS_STATE_CREATE_INFO:
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001294 size = sizeof(info->rs);
1295 dst = &info->rs;
Chia-I Wu3efef432014-08-28 15:00:16 +08001296 break;
1297 case XGL_STRUCTURE_TYPE_PIPELINE_TESS_STATE_CREATE_INFO:
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001298 size = sizeof(info->tess);
1299 dst = &info->tess;
Chia-I Wu3efef432014-08-28 15:00:16 +08001300 break;
Tony Barbourfa6cac72015-01-16 14:27:35 -07001301 case XGL_STRUCTURE_TYPE_PIPELINE_MS_STATE_CREATE_INFO:
1302 size = sizeof(info->ms);
1303 dst = &info->ms;
1304 break;
1305 case XGL_STRUCTURE_TYPE_PIPELINE_VP_STATE_CREATE_INFO:
1306 size = sizeof(info->vp);
1307 dst = &info->vp;
1308 break;
Chia-I Wu3efef432014-08-28 15:00:16 +08001309 case XGL_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO:
1310 {
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001311 const XGL_PIPELINE_SHADER *shader =
1312 (const XGL_PIPELINE_SHADER *) (header + 1);
Chia-I Wu3efef432014-08-28 15:00:16 +08001313
1314 src = (const void *) shader;
1315 size = sizeof(*shader);
1316
1317 switch (shader->stage) {
1318 case XGL_SHADER_STAGE_VERTEX:
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001319 dst = &info->vs;
Chia-I Wu3efef432014-08-28 15:00:16 +08001320 break;
1321 case XGL_SHADER_STAGE_TESS_CONTROL:
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001322 dst = &info->tcs;
Chia-I Wu3efef432014-08-28 15:00:16 +08001323 break;
1324 case XGL_SHADER_STAGE_TESS_EVALUATION:
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001325 dst = &info->tes;
Chia-I Wu3efef432014-08-28 15:00:16 +08001326 break;
1327 case XGL_SHADER_STAGE_GEOMETRY:
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001328 dst = &info->gs;
Chia-I Wu3efef432014-08-28 15:00:16 +08001329 break;
1330 case XGL_SHADER_STAGE_FRAGMENT:
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001331 dst = &info->fs;
Chia-I Wu3efef432014-08-28 15:00:16 +08001332 break;
Chia-I Wu3efef432014-08-28 15:00:16 +08001333 default:
1334 return XGL_ERROR_BAD_PIPELINE_DATA;
1335 break;
1336 }
1337 }
1338 break;
1339 case XGL_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO:
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001340 size = sizeof(info->compute);
1341 dst = &info->compute;
Chia-I Wu3efef432014-08-28 15:00:16 +08001342 break;
1343 default:
1344 return XGL_ERROR_BAD_PIPELINE_DATA;
1345 break;
1346 }
1347
1348 memcpy(dst, src, size);
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001349 header = header->next;
Chia-I Wu3efef432014-08-28 15:00:16 +08001350 }
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -06001351
1352 return XGL_SUCCESS;
Chia-I Wu3efef432014-08-28 15:00:16 +08001353}
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -06001354
Chia-I Wu3efef432014-08-28 15:00:16 +08001355static XGL_RESULT graphics_pipeline_create(struct intel_dev *dev,
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001356 const XGL_GRAPHICS_PIPELINE_CREATE_INFO *info_,
Chia-I Wu3efef432014-08-28 15:00:16 +08001357 struct intel_pipeline **pipeline_ret)
1358{
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001359 struct intel_pipeline_create_info info;
Chia-I Wu3efef432014-08-28 15:00:16 +08001360 struct intel_pipeline *pipeline;
1361 XGL_RESULT ret;
1362
Chia-I Wu509b3f22014-09-02 10:24:05 +08001363 ret = pipeline_create_info_init(&info,
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001364 (const struct intel_pipeline_create_info_header *) info_);
Chia-I Wu3efef432014-08-28 15:00:16 +08001365 if (ret != XGL_SUCCESS)
1366 return ret;
1367
1368 pipeline = (struct intel_pipeline *)
1369 intel_base_create(dev, sizeof(*pipeline), dev->base.dbg,
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001370 XGL_DBG_OBJECT_GRAPHICS_PIPELINE, info_, 0);
Chia-I Wu3efef432014-08-28 15:00:16 +08001371 if (!pipeline)
1372 return XGL_ERROR_OUT_OF_MEMORY;
1373
1374 pipeline->dev = dev;
Chia-I Wub1024732014-12-19 13:00:29 +08001375 pipeline->obj.base.get_info = pipeline_get_info;
Chia-I Wu3efef432014-08-28 15:00:16 +08001376 pipeline->obj.destroy = pipeline_destroy;
Chia-I Wu3efef432014-08-28 15:00:16 +08001377
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001378 ret = pipeline_build_all(pipeline, &info);
Chia-I Wu3efef432014-08-28 15:00:16 +08001379 if (ret == XGL_SUCCESS)
Chia-I Wuf90ff0c2014-09-02 09:32:46 +08001380 ret = pipeline_validate(pipeline);
Chia-I Wu3efef432014-08-28 15:00:16 +08001381 if (ret != XGL_SUCCESS) {
1382 pipeline_destroy(&pipeline->obj);
1383 return ret;
1384 }
1385
1386 *pipeline_ret = pipeline;
1387
1388 return XGL_SUCCESS;
1389}
1390
Chia-I Wu96177272015-01-03 15:27:41 +08001391ICD_EXPORT XGL_RESULT XGLAPI xglCreateGraphicsPipeline(
Chia-I Wu3efef432014-08-28 15:00:16 +08001392 XGL_DEVICE device,
1393 const XGL_GRAPHICS_PIPELINE_CREATE_INFO* pCreateInfo,
1394 XGL_PIPELINE* pPipeline)
1395{
1396 struct intel_dev *dev = intel_dev(device);
1397
1398 return graphics_pipeline_create(dev, pCreateInfo,
1399 (struct intel_pipeline **) pPipeline);
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -06001400}
1401
Chia-I Wu96177272015-01-03 15:27:41 +08001402ICD_EXPORT XGL_RESULT XGLAPI xglCreateComputePipeline(
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -06001403 XGL_DEVICE device,
1404 const XGL_COMPUTE_PIPELINE_CREATE_INFO* pCreateInfo,
1405 XGL_PIPELINE* pPipeline)
1406{
1407 return XGL_ERROR_UNAVAILABLE;
1408}
1409
Chia-I Wu96177272015-01-03 15:27:41 +08001410ICD_EXPORT XGL_RESULT XGLAPI xglStorePipeline(
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -06001411 XGL_PIPELINE pipeline,
1412 XGL_SIZE* pDataSize,
1413 XGL_VOID* pData)
1414{
1415 return XGL_ERROR_UNAVAILABLE;
1416}
1417
Chia-I Wu96177272015-01-03 15:27:41 +08001418ICD_EXPORT XGL_RESULT XGLAPI xglLoadPipeline(
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -06001419 XGL_DEVICE device,
1420 XGL_SIZE dataSize,
1421 const XGL_VOID* pData,
1422 XGL_PIPELINE* pPipeline)
1423{
1424 return XGL_ERROR_UNAVAILABLE;
1425}
1426
Chia-I Wu96177272015-01-03 15:27:41 +08001427ICD_EXPORT XGL_RESULT XGLAPI xglCreatePipelineDelta(
Courtney Goeltzenleuchter05a60542014-08-15 14:54:34 -06001428 XGL_DEVICE device,
1429 XGL_PIPELINE p1,
1430 XGL_PIPELINE p2,
1431 XGL_PIPELINE_DELTA* delta)
1432{
1433 return XGL_ERROR_UNAVAILABLE;
1434}