/** Maximum number of actual buffers used for stream output */
#define BRW_MAX_SOL_BUFFERS 4
+#define BRW_MAX_WM_UBOS 12
+#define BRW_MAX_VS_UBOS 12
+
/**
* Helpers to create Surface Binding Table indexes for draw buffers,
* textures, and constant buffers.
* | . | . |
* | : | : |
* | 24 | Texture 15 |
+ * |-----|-------------------------|
+ * | 25 | UBO 0 |
+ * | . | . |
+ * | : | : |
+ * | 36 | UBO 11 |
* +-------------------------------+
*
* Our VS binding tables are programmed as follows:
* | . | . |
* | : | : |
* | 16 | Texture 15 |
+ * +-----+-------------------------+
+ * | 17 | UBO 0 |
+ * | . | . |
+ * | : | : |
+ * | 28 | UBO 11 |
* +-------------------------------+
*
* Our (gen6) GS binding tables are programmed as follows:
#define SURF_INDEX_DRAW(d) (d)
#define SURF_INDEX_FRAG_CONST_BUFFER (BRW_MAX_DRAW_BUFFERS + 1)
#define SURF_INDEX_TEXTURE(t) (BRW_MAX_DRAW_BUFFERS + 2 + (t))
+#define SURF_INDEX_WM_UBO(u) (SURF_INDEX_TEXTURE(BRW_MAX_TEX_UNIT) + u)
/** Maximum size of the binding table. */
-#define BRW_MAX_WM_SURFACES SURF_INDEX_TEXTURE(BRW_MAX_TEX_UNIT)
+#define BRW_MAX_WM_SURFACES SURF_INDEX_WM_UBO(BRW_MAX_WM_UBOS)
#define SURF_INDEX_VERT_CONST_BUFFER (0)
#define SURF_INDEX_VS_TEXTURE(t) (SURF_INDEX_VERT_CONST_BUFFER + 1 + (t))
-#define BRW_MAX_VS_SURFACES SURF_INDEX_VS_TEXTURE(BRW_MAX_TEX_UNIT)
+#define SURF_INDEX_VS_UBO(u) (SURF_INDEX_VS_TEXTURE(BRW_MAX_TEX_UNIT) + u)
+#define BRW_MAX_VS_SURFACES SURF_INDEX_VS_UBO(BRW_MAX_VS_UBOS)
#define SURF_INDEX_SOL_BINDING(t) ((t))
#define BRW_MAX_GS_SURFACES SURF_INDEX_SOL_BINDING(BRW_MAX_SOL_BINDINGS)
struct gl_buffer_object *buffer_obj,
uint32_t *out_offset, unsigned num_vector_components,
unsigned stride_dwords, unsigned offset_dwords);
+void brw_upload_ubo_surfaces(struct brw_context *brw,
+ struct gl_shader *shader,
+ uint32_t *surf_offsets);
/* gen6_sol.c */
void
extern const struct brw_tracked_state brw_urb_fence;
extern const struct brw_tracked_state brw_vertex_state;
extern const struct brw_tracked_state brw_vs_prog;
+extern const struct brw_tracked_state brw_vs_ubo_surfaces;
extern const struct brw_tracked_state brw_vs_unit;
extern const struct brw_tracked_state brw_wm_input_sizes;
extern const struct brw_tracked_state brw_wm_prog;
extern const struct brw_tracked_state brw_texture_surfaces;
extern const struct brw_tracked_state brw_wm_binding_table;
extern const struct brw_tracked_state brw_vs_binding_table;
+extern const struct brw_tracked_state brw_wm_ubo_surfaces;
extern const struct brw_tracked_state brw_wm_unit;
extern const struct brw_tracked_state brw_psp_urb_cbs;
* table upload must be last.
*/
&brw_vs_pull_constants,
+ &brw_vs_ubo_surfaces,
&brw_wm_pull_constants,
+ &brw_wm_ubo_surfaces,
&gen6_renderbuffer_surfaces,
&brw_texture_surfaces,
&gen6_sol_surface,
* table upload must be last.
*/
&brw_vs_pull_constants,
+ &brw_vs_ubo_surfaces,
&brw_wm_pull_constants,
+ &brw_wm_ubo_surfaces,
&gen6_renderbuffer_surfaces,
&brw_texture_surfaces,
&brw_vs_binding_table,
if (c.prog_data.nr_pull_params)
c.prog_data.num_surfaces = 1;
if (c.vp->program.Base.SamplersUsed)
- c.prog_data.num_surfaces = BRW_MAX_VS_SURFACES;
+ c.prog_data.num_surfaces = SURF_INDEX_VS_TEXTURE(BRW_MAX_TEX_UNIT);
/* Scratch space is used for register spilling */
if (c.last_scratch) {
.emit = brw_upload_vs_pull_constants,
};
+static void
+brw_upload_vs_ubo_surfaces(struct brw_context *brw)
+{
+ struct gl_context *ctx = &brw->intel.ctx;
+ /* _NEW_PROGRAM */
+ struct gl_shader_program *prog = ctx->Shader.CurrentVertexProgram;
+
+ if (!prog)
+ return;
+
+ brw_upload_ubo_surfaces(brw, prog->_LinkedShaders[MESA_SHADER_VERTEX],
+ &brw->vs.surf_offset[SURF_INDEX_VS_UBO(0)]);
+}
+
+const struct brw_tracked_state brw_vs_ubo_surfaces = {
+ .dirty = {
+ .mesa = (_NEW_PROGRAM |
+ _NEW_BUFFER_OBJECT),
+ .brw = BRW_NEW_BATCH,
+ .cache = 0,
+ },
+ .emit = brw_upload_vs_ubo_surfaces,
+};
+
/**
* Constructs the binding table for the WM surface state, which maps unit
* numbers to surface state objects.
.emit = brw_update_texture_surfaces,
};
+void
+brw_upload_ubo_surfaces(struct brw_context *brw,
+ struct gl_shader *shader,
+ uint32_t *surf_offsets)
+{
+ struct gl_context *ctx = &brw->intel.ctx;
+ struct intel_context *intel = &brw->intel;
+
+ if (!shader)
+ return;
+
+ for (int i = 0; i < shader->NumUniformBlocks; i++) {
+ struct gl_uniform_buffer_binding *binding;
+ struct intel_buffer_object *intel_bo;
+
+ binding = &ctx->UniformBufferBindings[shader->UniformBlocks[i].Binding];
+ intel_bo = intel_buffer_object(binding->BufferObject);
+ drm_intel_bo *bo = intel_bufferobj_buffer(intel, intel_bo, INTEL_READ);
+
+ /* Because behavior for referencing outside of the binding's size in the
+ * glBindBufferRange case is undefined, we can just bind the whole buffer
+ * glBindBufferBase wants and be a correct implementation.
+ */
+ int size = bo->size - binding->Offset;
+ size = ALIGN(size, 16) / 16; /* The interface takes a number of vec4s */
+
+ intel->vtbl.create_constant_surface(brw, bo, binding->Offset,
+ size,
+ &surf_offsets[i]);
+ }
+
+ if (shader->NumUniformBlocks)
+ brw->state.dirty.brw |= BRW_NEW_SURFACES;
+}
+
+static void
+brw_upload_wm_ubo_surfaces(struct brw_context *brw)
+{
+ struct gl_context *ctx = &brw->intel.ctx;
+ /* _NEW_PROGRAM */
+ struct gl_shader_program *prog = ctx->Shader._CurrentFragmentProgram;
+
+ if (!prog)
+ return;
+
+ brw_upload_ubo_surfaces(brw, prog->_LinkedShaders[MESA_SHADER_FRAGMENT],
+ &brw->wm.surf_offset[SURF_INDEX_WM_UBO(0)]);
+}
+
+const struct brw_tracked_state brw_wm_ubo_surfaces = {
+ .dirty = {
+ .mesa = (_NEW_PROGRAM |
+ _NEW_BUFFER_OBJECT),
+ .brw = BRW_NEW_BATCH,
+ .cache = 0,
+ },
+ .emit = brw_upload_wm_ubo_surfaces,
+};
+
/**
* Constructs the binding table for the WM surface state, which maps unit
* numbers to surface state objects.