#include "brw_defines.h"
#include "intel_batchbuffer.h"
#include "intel_buffer_objects.h"
+#include "main/transformfeedback.h"
static void
upload_3dstate_so_buffers(struct brw_context *brw)
{
- struct intel_context *intel = &brw->intel;
- struct gl_context *ctx = &intel->ctx;
+ struct gl_context *ctx = &brw->ctx;
/* BRW_NEW_VERTEX_PROGRAM */
const struct gl_shader_program *vs_prog =
ctx->Shader.CurrentVertexProgram;
const struct gl_transform_feedback_info *linked_xfb_info =
&vs_prog->LinkedTransformFeedback;
- /* _NEW_TRANSFORM_FEEDBACK */
+ /* BRW_NEW_TRANSFORM_FEEDBACK */
struct gl_transform_feedback_object *xfb_obj =
ctx->TransformFeedback.CurrentObject;
int i;
* gl_transform_feedback_object.
*/
for (i = 0; i < 4; i++) {
- struct gl_buffer_object *bufferobj = xfb_obj->Buffers[i];
+ struct intel_buffer_object *bufferobj =
+ intel_buffer_object(xfb_obj->Buffers[i]);
drm_intel_bo *bo;
uint32_t start, end;
+ uint32_t stride;
if (!xfb_obj->Buffers[i]) {
/* The pitch of 0 in this command indicates that the buffer is
continue;
}
- bo = intel_buffer_object(bufferobj)->buffer;
+ bo = intel_bufferobj_buffer(brw, bufferobj, INTEL_WRITE_PART);
+ stride = linked_xfb_info->BufferStride[i] * 4;
start = xfb_obj->Offset[i];
assert(start % 4 == 0);
BEGIN_BATCH(4);
OUT_BATCH(_3DSTATE_SO_BUFFER << 16 | (4 - 2));
- OUT_BATCH((i << SO_BUFFER_INDEX_SHIFT) |
- ((linked_xfb_info->BufferStride[i] * 4) <<
- SO_BUFFER_PITCH_SHIFT));
+ OUT_BATCH((i << SO_BUFFER_INDEX_SHIFT) | stride);
OUT_RELOC(bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, start);
OUT_RELOC(bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, end);
ADVANCE_BATCH();
* stream. We only have one stream of rendering coming out of the GS unit, so
* we only emit stream 0 (low 16 bits) SO_DECLs.
*/
-static void
-upload_3dstate_so_decl_list(struct brw_context *brw,
- struct brw_vue_map *vue_map)
+void
+gen7_upload_3dstate_so_decl_list(struct brw_context *brw,
+ const struct brw_vue_map *vue_map)
{
- struct intel_context *intel = &brw->intel;
- struct gl_context *ctx = &intel->ctx;
+ struct gl_context *ctx = &brw->ctx;
/* BRW_NEW_VERTEX_PROGRAM */
const struct gl_shader_program *vs_prog =
ctx->Shader.CurrentVertexProgram;
- /* _NEW_TRANSFORM_FEEDBACK */
+ /* BRW_NEW_TRANSFORM_FEEDBACK */
const struct gl_transform_feedback_info *linked_xfb_info =
&vs_prog->LinkedTransformFeedback;
int i;
for (i = 0; i < linked_xfb_info->NumOutputs; i++) {
int buffer = linked_xfb_info->Outputs[i].OutputBuffer;
uint16_t decl = 0;
- int vert_result = linked_xfb_info->Outputs[i].OutputRegister;
+ int varying = linked_xfb_info->Outputs[i].OutputRegister;
+ unsigned component_mask =
+ (1 << linked_xfb_info->Outputs[i].NumComponents) - 1;
+
+ /* gl_PointSize is stored in VARYING_SLOT_PSIZ.w. */
+ if (varying == VARYING_SLOT_PSIZ) {
+ assert(linked_xfb_info->Outputs[i].NumComponents == 1);
+ component_mask <<= 3;
+ } else {
+ component_mask <<= linked_xfb_info->Outputs[i].ComponentOffset;
+ }
buffer_mask |= 1 << buffer;
decl |= buffer << SO_DECL_OUTPUT_BUFFER_SLOT_SHIFT;
- decl |= vue_map->vert_result_to_slot[vert_result] <<
+ decl |= vue_map->varying_to_slot[varying] <<
SO_DECL_REGISTER_INDEX_SHIFT;
- decl |= ((1 << linked_xfb_info->Outputs[i].NumComponents) - 1) <<
- SO_DECL_COMPONENT_MASK_SHIFT;
+ decl |= component_mask << SO_DECL_COMPONENT_MASK_SHIFT;
/* This assert should be true until GL_ARB_transform_feedback_instanced
* is added and we start using the hole flag.
static void
upload_3dstate_streamout(struct brw_context *brw, bool active,
- struct brw_vue_map *vue_map)
+ const struct brw_vue_map *vue_map)
{
- struct intel_context *intel = &brw->intel;
- struct gl_context *ctx = &intel->ctx;
- /* _NEW_TRANSFORM_FEEDBACK */
+ struct gl_context *ctx = &brw->ctx;
+ /* BRW_NEW_TRANSFORM_FEEDBACK */
struct gl_transform_feedback_object *xfb_obj =
ctx->TransformFeedback.CurrentObject;
uint32_t dw1 = 0, dw2 = 0;
int i;
- /* _NEW_RASTERIZER_DISCARD */
- if (ctx->RasterDiscard)
- dw1 |= SO_RENDERING_DISABLE;
-
if (active) {
int urb_entry_read_offset = 0;
int urb_entry_read_length = (vue_map->num_slots + 1) / 2 -
static void
upload_sol_state(struct brw_context *brw)
{
- struct intel_context *intel = &brw->intel;
- struct gl_context *ctx = &intel->ctx;
- /* _NEW_TRANSFORM_FEEDBACK */
- struct gl_transform_feedback_object *xfb_obj =
- ctx->TransformFeedback.CurrentObject;
- bool active = xfb_obj->Active && !xfb_obj->Paused;
- struct brw_vue_map vue_map;
-
- /* _NEW_TRANSFORM, CACHE_NEW_VS_PROG */
- brw_compute_vue_map(&vue_map, intel, ctx->Transform.ClipPlanesEnabled != 0,
- brw->vs.prog_data->outputs_written);
+ struct gl_context *ctx = &brw->ctx;
+ /* BRW_NEW_TRANSFORM_FEEDBACK */
+ bool active = _mesa_is_xfb_active_and_unpaused(ctx);
if (active) {
upload_3dstate_so_buffers(brw);
- upload_3dstate_so_decl_list(brw, &vue_map);
+ /* BRW_NEW_VUE_MAP_GEOM_OUT */
+ gen7_upload_3dstate_so_decl_list(brw, &brw->vue_map_geom_out);
}
/* Finally, set up the SOL stage. This command must always follow updates to
* MMIO register updates (current performed by the kernel at each batch
* emit).
*/
- upload_3dstate_streamout(brw, active, &vue_map);
+ upload_3dstate_streamout(brw, active, &brw->vue_map_geom_out);
}
const struct brw_tracked_state gen7_sol_state = {
.dirty = {
- .mesa = (_NEW_RASTERIZER_DISCARD |
- _NEW_LIGHT |
- _NEW_TRANSFORM_FEEDBACK |
- _NEW_TRANSFORM),
+ .mesa = (_NEW_LIGHT),
.brw = (BRW_NEW_BATCH |
- BRW_NEW_VERTEX_PROGRAM),
- .cache = CACHE_NEW_VS_PROG,
+ BRW_NEW_VERTEX_PROGRAM |
+ BRW_NEW_VUE_MAP_GEOM_OUT |
+ BRW_NEW_TRANSFORM_FEEDBACK)
},
.emit = upload_sol_state,
};
+
+void
+gen7_begin_transform_feedback(struct gl_context *ctx, GLenum mode,
+ struct gl_transform_feedback_object *obj)
+{
+ struct brw_context *brw = brw_context(ctx);
+
+ intel_batchbuffer_flush(brw);
+ brw->batch.needs_sol_reset = true;
+}
+
+void
+gen7_end_transform_feedback(struct gl_context *ctx,
+ struct gl_transform_feedback_object *obj)
+{
+ /* Because we have to rely on the kernel to reset our SO write offsets, and
+ * we only get to do it once per batchbuffer, flush the batch after feedback
+ * so another transform feedback can get the write offset reset it needs.
+ *
+ * This also covers any cache flushing required.
+ */
+ struct brw_context *brw = brw_context(ctx);
+
+ intel_batchbuffer_flush(brw);
+}