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 /* BRW_NEW_VERTEX_PROGRAM */
45 const struct gl_shader_program
*shaderprog
=
46 ctx
->Shader
.CurrentProgram
[MESA_SHADER_VERTEX
];
47 const struct gl_transform_feedback_info
*linked_xfb_info
=
48 &shaderprog
->LinkedTransformFeedback
;
51 for (i
= 0; i
< BRW_MAX_SOL_BINDINGS
; ++i
) {
52 const int surf_index
= SURF_INDEX_GEN6_SOL_BINDING(i
);
53 if (_mesa_is_xfb_active_and_unpaused(ctx
) &&
54 i
< linked_xfb_info
->NumOutputs
) {
55 unsigned buffer
= linked_xfb_info
->Outputs
[i
].OutputBuffer
;
56 unsigned buffer_offset
=
57 xfb_obj
->Offset
[buffer
] / 4 +
58 linked_xfb_info
->Outputs
[i
].DstOffset
;
59 brw_update_sol_surface(
60 brw
, xfb_obj
->Buffers
[buffer
], &brw
->ff_gs
.surf_offset
[surf_index
],
61 linked_xfb_info
->Outputs
[i
].NumComponents
,
62 linked_xfb_info
->BufferStride
[buffer
], buffer_offset
);
64 brw
->ff_gs
.surf_offset
[surf_index
] = 0;
68 brw
->state
.dirty
.brw
|= BRW_NEW_SURFACES
;
71 const struct brw_tracked_state gen6_sol_surface
= {
74 .brw
= (BRW_NEW_BATCH
|
75 BRW_NEW_VERTEX_PROGRAM
|
76 BRW_NEW_TRANSFORM_FEEDBACK
),
79 .emit
= gen6_update_sol_surfaces
,
83 * Constructs the binding table for the WM surface state, which maps unit
84 * numbers to surface state objects.
87 brw_gs_upload_binding_table(struct brw_context
*brw
)
89 struct gl_context
*ctx
= &brw
->ctx
;
90 /* BRW_NEW_VERTEX_PROGRAM */
91 const struct gl_shader_program
*shaderprog
=
92 ctx
->Shader
.CurrentProgram
[MESA_SHADER_VERTEX
];
93 bool has_surfaces
= false;
97 const struct gl_transform_feedback_info
*linked_xfb_info
=
98 &shaderprog
->LinkedTransformFeedback
;
99 /* Currently we only ever upload surfaces for SOL. */
100 has_surfaces
= linked_xfb_info
->NumOutputs
!= 0;
103 /* Skip making a binding table if we don't have anything to put in it. */
105 if (brw
->ff_gs
.bind_bo_offset
!= 0) {
106 brw
->state
.dirty
.brw
|= BRW_NEW_GS_BINDING_TABLE
;
107 brw
->ff_gs
.bind_bo_offset
= 0;
112 /* Might want to calculate nr_surfaces first, to avoid taking up so much
113 * space for the binding table.
115 bind
= brw_state_batch(brw
, AUB_TRACE_BINDING_TABLE
,
116 sizeof(uint32_t) * BRW_MAX_GEN6_GS_SURFACES
,
117 32, &brw
->ff_gs
.bind_bo_offset
);
119 /* BRW_NEW_SURFACES */
120 memcpy(bind
, brw
->ff_gs
.surf_offset
, BRW_MAX_GEN6_GS_SURFACES
* sizeof(uint32_t));
122 brw
->state
.dirty
.brw
|= BRW_NEW_GS_BINDING_TABLE
;
125 const struct brw_tracked_state gen6_gs_binding_table
= {
128 .brw
= (BRW_NEW_BATCH
|
129 BRW_NEW_VERTEX_PROGRAM
|
133 .emit
= brw_gs_upload_binding_table
,
136 struct gl_transform_feedback_object
*
137 brw_new_transform_feedback(struct gl_context
*ctx
, GLuint name
)
139 struct brw_context
*brw
= brw_context(ctx
);
140 struct brw_transform_feedback_object
*brw_obj
=
141 CALLOC_STRUCT(brw_transform_feedback_object
);
145 _mesa_init_transform_feedback_object(&brw_obj
->base
, name
);
148 drm_intel_bo_alloc(brw
->bufmgr
, "transform feedback offsets", 16, 64);
149 brw_obj
->prim_count_bo
=
150 drm_intel_bo_alloc(brw
->bufmgr
, "xfb primitive counts", 4096, 64);
152 return &brw_obj
->base
;
156 brw_delete_transform_feedback(struct gl_context
*ctx
,
157 struct gl_transform_feedback_object
*obj
)
159 struct brw_transform_feedback_object
*brw_obj
=
160 (struct brw_transform_feedback_object
*) obj
;
162 for (unsigned i
= 0; i
< Elements(obj
->Buffers
); i
++) {
163 _mesa_reference_buffer_object(ctx
, &obj
->Buffers
[i
], NULL
);
166 drm_intel_bo_unreference(brw_obj
->offset_bo
);
167 drm_intel_bo_unreference(brw_obj
->prim_count_bo
);
173 brw_begin_transform_feedback(struct gl_context
*ctx
, GLenum mode
,
174 struct gl_transform_feedback_object
*obj
)
176 struct brw_context
*brw
= brw_context(ctx
);
177 const struct gl_shader_program
*vs_prog
=
178 ctx
->Shader
.CurrentProgram
[MESA_SHADER_VERTEX
];
179 const struct gl_transform_feedback_info
*linked_xfb_info
=
180 &vs_prog
->LinkedTransformFeedback
;
181 struct gl_transform_feedback_object
*xfb_obj
=
182 ctx
->TransformFeedback
.CurrentObject
;
184 assert(brw
->gen
== 6);
186 /* Compute the maximum number of vertices that we can write without
187 * overflowing any of the buffers currently being used for feedback.
190 = _mesa_compute_max_transform_feedback_vertices(xfb_obj
,
193 /* 3DSTATE_GS_SVB_INDEX is non-pipelined. */
194 intel_emit_post_sync_nonzero_flush(brw
);
196 /* Initialize the SVBI 0 register to zero and set the maximum index. */
198 OUT_BATCH(_3DSTATE_GS_SVB_INDEX
<< 16 | (4 - 2));
199 OUT_BATCH(0); /* SVBI 0 */
200 OUT_BATCH(0); /* starting index */
201 OUT_BATCH(max_index
);
204 /* Initialize the rest of the unused streams to sane values. Otherwise,
205 * they may indicate that there is no room to write data and prevent
206 * anything from happening at all.
208 for (int i
= 1; i
< 4; i
++) {
210 OUT_BATCH(_3DSTATE_GS_SVB_INDEX
<< 16 | (4 - 2));
211 OUT_BATCH(i
<< SVB_INDEX_SHIFT
);
212 OUT_BATCH(0); /* starting index */
213 OUT_BATCH(0xffffffff);
219 brw_end_transform_feedback(struct gl_context
*ctx
,
220 struct gl_transform_feedback_object
*obj
)
222 /* After EndTransformFeedback, it's likely that the client program will try
223 * to draw using the contents of the transform feedback buffer as vertex
224 * input. In order for this to work, we need to flush the data through at
225 * least the GS stage of the pipeline, and flush out the render cache. For
226 * simplicity, just do a full flush.
228 struct brw_context
*brw
= brw_context(ctx
);
229 intel_batchbuffer_emit_mi_flush(brw
);