2 * Copyright © 2011 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
26 * Code to initialize the binding table entries used by transform feedback.
29 #include "main/bufferobj.h"
30 #include "main/macros.h"
31 #include "brw_context.h"
32 #include "intel_batchbuffer.h"
33 #include "brw_defines.h"
34 #include "brw_state.h"
35 #include "main/transformfeedback.h"
38 gen6_update_sol_surfaces(struct brw_context
*brw
)
40 struct gl_context
*ctx
= &brw
->ctx
;
41 /* BRW_NEW_TRANSFORM_FEEDBACK */
42 struct gl_transform_feedback_object
*xfb_obj
=
43 ctx
->TransformFeedback
.CurrentObject
;
44 const struct gl_shader_program
*shaderprog
;
45 const struct gl_transform_feedback_info
*linked_xfb_info
;
48 if (brw
->geometry_program
) {
49 /* BRW_NEW_GEOMETRY_PROGRAM */
51 ctx
->_Shader
->CurrentProgram
[MESA_SHADER_GEOMETRY
];
53 /* BRW_NEW_VERTEX_PROGRAM */
55 ctx
->_Shader
->CurrentProgram
[MESA_SHADER_VERTEX
];
57 linked_xfb_info
= &shaderprog
->LinkedTransformFeedback
;
59 for (i
= 0; i
< BRW_MAX_SOL_BINDINGS
; ++i
) {
60 const int surf_index
= SURF_INDEX_GEN6_SOL_BINDING(i
);
61 if (_mesa_is_xfb_active_and_unpaused(ctx
) &&
62 i
< linked_xfb_info
->NumOutputs
) {
63 unsigned buffer
= linked_xfb_info
->Outputs
[i
].OutputBuffer
;
64 unsigned buffer_offset
=
65 xfb_obj
->Offset
[buffer
] / 4 +
66 linked_xfb_info
->Outputs
[i
].DstOffset
;
67 if (brw
->geometry_program
) {
68 brw_update_sol_surface(
69 brw
, xfb_obj
->Buffers
[buffer
],
70 &brw
->gs
.base
.surf_offset
[surf_index
],
71 linked_xfb_info
->Outputs
[i
].NumComponents
,
72 linked_xfb_info
->BufferStride
[buffer
], buffer_offset
);
74 brw_update_sol_surface(
75 brw
, xfb_obj
->Buffers
[buffer
],
76 &brw
->ff_gs
.surf_offset
[surf_index
],
77 linked_xfb_info
->Outputs
[i
].NumComponents
,
78 linked_xfb_info
->BufferStride
[buffer
], buffer_offset
);
81 if (!brw
->geometry_program
)
82 brw
->ff_gs
.surf_offset
[surf_index
] = 0;
84 brw
->gs
.base
.surf_offset
[surf_index
] = 0;
88 brw
->ctx
.NewDriverState
|= BRW_NEW_SURFACES
;
91 const struct brw_tracked_state gen6_sol_surface
= {
94 .brw
= BRW_NEW_BATCH
|
95 BRW_NEW_GEOMETRY_PROGRAM
|
96 BRW_NEW_VERTEX_PROGRAM
|
97 BRW_NEW_TRANSFORM_FEEDBACK
,
99 .emit
= gen6_update_sol_surfaces
,
103 * Constructs the binding table for the WM surface state, which maps unit
104 * numbers to surface state objects.
107 brw_gs_upload_binding_table(struct brw_context
*brw
)
110 struct gl_context
*ctx
= &brw
->ctx
;
111 const struct gl_shader_program
*shaderprog
;
112 bool need_binding_table
= false;
114 /* We have two scenarios here:
115 * 1) We are using a geometry shader only to implement transform feedback
116 * for a vertex shader (brw->geometry_program == NULL). In this case, we
117 * only need surfaces for transform feedback in the GS stage.
118 * 2) We have a user-provided geometry shader. In this case we may need
119 * surfaces for transform feedback and/or other stuff, like textures,
123 if (!brw
->geometry_program
) {
124 /* BRW_NEW_VERTEX_PROGRAM */
125 shaderprog
= ctx
->_Shader
->CurrentProgram
[MESA_SHADER_VERTEX
];
127 /* Skip making a binding table if we don't have anything to put in it */
128 const struct gl_transform_feedback_info
*linked_xfb_info
=
129 &shaderprog
->LinkedTransformFeedback
;
130 need_binding_table
= linked_xfb_info
->NumOutputs
> 0;
132 if (!need_binding_table
) {
133 if (brw
->ff_gs
.bind_bo_offset
!= 0) {
134 brw
->ctx
.NewDriverState
|= BRW_NEW_GS_BINDING_TABLE
;
135 brw
->ff_gs
.bind_bo_offset
= 0;
140 /* Might want to calculate nr_surfaces first, to avoid taking up so much
141 * space for the binding table. Anyway, in this case we know that we only
142 * use BRW_MAX_SOL_BINDINGS surfaces at most.
144 bind
= brw_state_batch(brw
, AUB_TRACE_BINDING_TABLE
,
145 sizeof(uint32_t) * BRW_MAX_SOL_BINDINGS
,
146 32, &brw
->ff_gs
.bind_bo_offset
);
148 /* BRW_NEW_SURFACES */
149 memcpy(bind
, brw
->ff_gs
.surf_offset
,
150 BRW_MAX_SOL_BINDINGS
* sizeof(uint32_t));
152 /* BRW_NEW_GEOMETRY_PROGRAM */
153 shaderprog
= ctx
->_Shader
->CurrentProgram
[MESA_SHADER_GEOMETRY
];
155 /* Skip making a binding table if we don't have anything to put in it */
156 struct brw_stage_prog_data
*prog_data
= brw
->gs
.base
.prog_data
;
157 const struct gl_transform_feedback_info
*linked_xfb_info
=
158 &shaderprog
->LinkedTransformFeedback
;
159 need_binding_table
= linked_xfb_info
->NumOutputs
> 0 ||
160 prog_data
->binding_table
.size_bytes
> 0;
162 if (!need_binding_table
) {
163 if (brw
->gs
.base
.bind_bo_offset
!= 0) {
164 brw
->gs
.base
.bind_bo_offset
= 0;
165 brw
->ctx
.NewDriverState
|= BRW_NEW_GS_BINDING_TABLE
;
170 /* Might want to calculate nr_surfaces first, to avoid taking up so much
171 * space for the binding table.
173 bind
= brw_state_batch(brw
, AUB_TRACE_BINDING_TABLE
,
174 sizeof(uint32_t) * BRW_MAX_SURFACES
,
175 32, &brw
->gs
.base
.bind_bo_offset
);
177 /* BRW_NEW_SURFACES */
178 memcpy(bind
, brw
->gs
.base
.surf_offset
,
179 BRW_MAX_SURFACES
* sizeof(uint32_t));
182 brw
->ctx
.NewDriverState
|= BRW_NEW_GS_BINDING_TABLE
;
185 const struct brw_tracked_state gen6_gs_binding_table
= {
188 .brw
= BRW_NEW_BATCH
|
189 BRW_NEW_GEOMETRY_PROGRAM
|
190 BRW_NEW_VERTEX_PROGRAM
|
193 .emit
= brw_gs_upload_binding_table
,
196 struct gl_transform_feedback_object
*
197 brw_new_transform_feedback(struct gl_context
*ctx
, GLuint name
)
199 struct brw_context
*brw
= brw_context(ctx
);
200 struct brw_transform_feedback_object
*brw_obj
=
201 CALLOC_STRUCT(brw_transform_feedback_object
);
205 _mesa_init_transform_feedback_object(&brw_obj
->base
, name
);
208 drm_intel_bo_alloc(brw
->bufmgr
, "transform feedback offsets", 16, 64);
209 brw_obj
->prim_count_bo
=
210 drm_intel_bo_alloc(brw
->bufmgr
, "xfb primitive counts", 4096, 64);
212 return &brw_obj
->base
;
216 brw_delete_transform_feedback(struct gl_context
*ctx
,
217 struct gl_transform_feedback_object
*obj
)
219 struct brw_transform_feedback_object
*brw_obj
=
220 (struct brw_transform_feedback_object
*) obj
;
222 for (unsigned i
= 0; i
< ARRAY_SIZE(obj
->Buffers
); i
++) {
223 _mesa_reference_buffer_object(ctx
, &obj
->Buffers
[i
], NULL
);
226 drm_intel_bo_unreference(brw_obj
->offset_bo
);
227 drm_intel_bo_unreference(brw_obj
->prim_count_bo
);
233 brw_begin_transform_feedback(struct gl_context
*ctx
, GLenum mode
,
234 struct gl_transform_feedback_object
*obj
)
236 struct brw_context
*brw
= brw_context(ctx
);
237 const struct gl_shader_program
*shaderprog
;
238 const struct gl_transform_feedback_info
*linked_xfb_info
;
239 struct gl_transform_feedback_object
*xfb_obj
=
240 ctx
->TransformFeedback
.CurrentObject
;
242 assert(brw
->gen
== 6);
244 if (ctx
->_Shader
->CurrentProgram
[MESA_SHADER_GEOMETRY
]) {
245 /* BRW_NEW_GEOMETRY_PROGRAM */
247 ctx
->_Shader
->CurrentProgram
[MESA_SHADER_GEOMETRY
];
249 /* BRW_NEW_VERTEX_PROGRAM */
251 ctx
->_Shader
->CurrentProgram
[MESA_SHADER_VERTEX
];
253 linked_xfb_info
= &shaderprog
->LinkedTransformFeedback
;
255 /* Compute the maximum number of vertices that we can write without
256 * overflowing any of the buffers currently being used for feedback.
259 = _mesa_compute_max_transform_feedback_vertices(xfb_obj
,
262 /* Initialize the SVBI 0 register to zero and set the maximum index. */
264 OUT_BATCH(_3DSTATE_GS_SVB_INDEX
<< 16 | (4 - 2));
265 OUT_BATCH(0); /* SVBI 0 */
266 OUT_BATCH(0); /* starting index */
267 OUT_BATCH(max_index
);
270 /* Initialize the rest of the unused streams to sane values. Otherwise,
271 * they may indicate that there is no room to write data and prevent
272 * anything from happening at all.
274 for (int i
= 1; i
< 4; i
++) {
276 OUT_BATCH(_3DSTATE_GS_SVB_INDEX
<< 16 | (4 - 2));
277 OUT_BATCH(i
<< SVB_INDEX_SHIFT
);
278 OUT_BATCH(0); /* starting index */
279 OUT_BATCH(0xffffffff);
285 brw_end_transform_feedback(struct gl_context
*ctx
,
286 struct gl_transform_feedback_object
*obj
)
288 /* After EndTransformFeedback, it's likely that the client program will try
289 * to draw using the contents of the transform feedback buffer as vertex
290 * input. In order for this to work, we need to flush the data through at
291 * least the GS stage of the pipeline, and flush out the render cache. For
292 * simplicity, just do a full flush.
294 struct brw_context
*brw
= brw_context(ctx
);
295 brw_emit_mi_flush(brw
);