1 /*
2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics to
4 develop this 3D driver.
5
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
13
14 The above copyright notice and this permission notice (including the
15 next paragraph) shall be included in all copies or substantial
16 portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **********************************************************************/
27 /*
28 * Authors:
29 * Keith Whitwell <keithw@vmware.com>
30 */
31
32 #include "main/macros.h"
33 #include "main/enums.h"
34 #include "main/transformfeedback.h"
35
36 #include "brw_batch.h"
37
38 #include "brw_defines.h"
39 #include "brw_context.h"
40 #include "brw_util.h"
41 #include "brw_state.h"
42 #include "brw_ff_gs.h"
43 #include "util/ralloc.h"
44
45 static void
compile_ff_gs_prog(struct brw_context * brw,struct brw_ff_gs_prog_key * key)46 compile_ff_gs_prog(struct brw_context *brw,
47 struct brw_ff_gs_prog_key *key)
48 {
49 const GLuint *program;
50 void *mem_ctx;
51 GLuint program_size;
52
53 mem_ctx = ralloc_context(NULL);
54
55 struct brw_ff_gs_prog_data prog_data;
56 program = brw_compile_ff_gs_prog(brw->screen->compiler, mem_ctx, key,
57 &prog_data,
58 &brw_vue_prog_data(brw->vs.base.prog_data)->vue_map,
59 &program_size);
60
61 brw_upload_cache(&brw->cache, BRW_CACHE_FF_GS_PROG,
62 key, sizeof(*key),
63 program, program_size,
64 &prog_data, sizeof(prog_data),
65 &brw->ff_gs.prog_offset, &brw->ff_gs.prog_data);
66 ralloc_free(mem_ctx);
67 }
68
69 static bool
brw_ff_gs_state_dirty(const struct brw_context * brw)70 brw_ff_gs_state_dirty(const struct brw_context *brw)
71 {
72 return brw_state_dirty(brw,
73 _NEW_LIGHT,
74 BRW_NEW_PRIMITIVE |
75 BRW_NEW_TRANSFORM_FEEDBACK |
76 BRW_NEW_VS_PROG_DATA);
77 }
78
79 static void
brw_ff_gs_populate_key(struct brw_context * brw,struct brw_ff_gs_prog_key * key)80 brw_ff_gs_populate_key(struct brw_context *brw,
81 struct brw_ff_gs_prog_key *key)
82 {
83 const struct intel_device_info *devinfo = &brw->screen->devinfo;
84 static const unsigned swizzle_for_offset[4] = {
85 BRW_SWIZZLE4(0, 1, 2, 3),
86 BRW_SWIZZLE4(1, 2, 3, 3),
87 BRW_SWIZZLE4(2, 3, 3, 3),
88 BRW_SWIZZLE4(3, 3, 3, 3)
89 };
90
91 struct gl_context *ctx = &brw->ctx;
92
93 assert(devinfo->ver < 7);
94
95 memset(key, 0, sizeof(*key));
96
97 /* BRW_NEW_VS_PROG_DATA (part of VUE map) */
98 key->attrs = brw_vue_prog_data(brw->vs.base.prog_data)->vue_map.slots_valid;
99
100 /* BRW_NEW_PRIMITIVE */
101 key->primitive = brw->primitive;
102
103 /* _NEW_LIGHT */
104 key->pv_first = (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION);
105 if (key->primitive == _3DPRIM_QUADLIST && ctx->Light.ShadeModel != GL_FLAT) {
106 /* Provide consistent primitive order with brw_set_prim's
107 * optimization of single quads to trifans.
108 */
109 key->pv_first = true;
110 }
111
112 if (devinfo->ver == 6) {
113 /* On Gfx6, GS is used for transform feedback. */
114 /* BRW_NEW_TRANSFORM_FEEDBACK */
115 if (_mesa_is_xfb_active_and_unpaused(ctx)) {
116 const struct gl_program *prog =
117 ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX];
118 const struct gl_transform_feedback_info *linked_xfb_info =
119 prog->sh.LinkedTransformFeedback;
120 int i;
121
122 /* Make sure that the VUE slots won't overflow the unsigned chars in
123 * key->transform_feedback_bindings[].
124 */
125 STATIC_ASSERT(BRW_VARYING_SLOT_COUNT <= 256);
126
127 /* Make sure that we don't need more binding table entries than we've
128 * set aside for use in transform feedback. (We shouldn't, since we
129 * set aside enough binding table entries to have one per component).
130 */
131 assert(linked_xfb_info->NumOutputs <= BRW_MAX_SOL_BINDINGS);
132
133 key->need_gs_prog = true;
134 key->num_transform_feedback_bindings = linked_xfb_info->NumOutputs;
135 for (i = 0; i < key->num_transform_feedback_bindings; ++i) {
136 key->transform_feedback_bindings[i] =
137 linked_xfb_info->Outputs[i].OutputRegister;
138 key->transform_feedback_swizzles[i] =
139 swizzle_for_offset[linked_xfb_info->Outputs[i].ComponentOffset];
140 }
141 }
142 } else {
143 /* Pre-gfx6, GS is used to transform QUADLIST, QUADSTRIP, and LINELOOP
144 * into simpler primitives.
145 */
146 key->need_gs_prog = (brw->primitive == _3DPRIM_QUADLIST ||
147 brw->primitive == _3DPRIM_QUADSTRIP ||
148 brw->primitive == _3DPRIM_LINELOOP);
149 }
150 }
151
152 /* Calculate interpolants for triangle and line rasterization.
153 */
154 void
brw_upload_ff_gs_prog(struct brw_context * brw)155 brw_upload_ff_gs_prog(struct brw_context *brw)
156 {
157 struct brw_ff_gs_prog_key key;
158
159 if (!brw_ff_gs_state_dirty(brw))
160 return;
161
162 /* Populate the key:
163 */
164 brw_ff_gs_populate_key(brw, &key);
165
166 if (brw->ff_gs.prog_active != key.need_gs_prog) {
167 brw->ctx.NewDriverState |= BRW_NEW_FF_GS_PROG_DATA;
168 brw->ff_gs.prog_active = key.need_gs_prog;
169 }
170
171 if (brw->ff_gs.prog_active) {
172 if (!brw_search_cache(&brw->cache, BRW_CACHE_FF_GS_PROG, &key,
173 sizeof(key), &brw->ff_gs.prog_offset,
174 &brw->ff_gs.prog_data, true)) {
175 compile_ff_gs_prog(brw, &key);
176 }
177 }
178 }
179