struct anv_vertex_binding vertex_bindings[MAX_VBS];
struct anv_descriptor_set * descriptors[MAX_SETS];
struct anv_push_constants * push_constants[MESA_SHADER_STAGES];
+ struct anv_state binding_tables[MESA_SHADER_STAGES];
+ struct anv_state samplers[MESA_SHADER_STAGES];
struct anv_dynamic_state dynamic;
struct {
unsigned stage, struct anv_state *bt_state);
VkResult anv_cmd_buffer_emit_samplers(struct anv_cmd_buffer *cmd_buffer,
unsigned stage, struct anv_state *state);
-void gen7_cmd_buffer_flush_descriptor_sets(struct anv_cmd_buffer *cmd_buffer);
+uint32_t gen7_cmd_buffer_flush_descriptor_sets(struct anv_cmd_buffer *cmd_buffer);
+void gen7_cmd_buffer_emit_descriptor_pointers(struct anv_cmd_buffer *cmd_buffer,
+ uint32_t stages);
struct anv_state anv_cmd_buffer_emit_dynamic(struct anv_cmd_buffer *cmd_buffer,
const void *data, uint32_t size, uint32_t alignment);
#include "gen7_pack.h"
#include "gen75_pack.h"
-static void
+static uint32_t
cmd_buffer_flush_push_constants(struct anv_cmd_buffer *cmd_buffer)
{
static const uint32_t push_constant_opcodes[] = {
}
cmd_buffer->state.push_constants_dirty &= ~flushed;
+
+ return flushed;
}
-static VkResult
-flush_descriptor_set(struct anv_cmd_buffer *cmd_buffer, gl_shader_stage stage)
+GENX_FUNC(GEN7, GEN7) void
+genX(cmd_buffer_emit_descriptor_pointers)(struct anv_cmd_buffer *cmd_buffer,
+ uint32_t stages)
{
- struct anv_state surfaces = { 0, }, samplers = { 0, };
- VkResult result;
-
- result = anv_cmd_buffer_emit_samplers(cmd_buffer, stage, &samplers);
- if (result != VK_SUCCESS)
- return result;
- result = anv_cmd_buffer_emit_binding_table(cmd_buffer, stage, &surfaces);
- if (result != VK_SUCCESS)
- return result;
-
static const uint32_t sampler_state_opcodes[] = {
[MESA_SHADER_VERTEX] = 43,
[MESA_SHADER_TESS_CTRL] = 44, /* HS */
[MESA_SHADER_COMPUTE] = 0,
};
- if (samplers.alloc_size > 0) {
- anv_batch_emit(&cmd_buffer->batch,
- GEN7_3DSTATE_SAMPLER_STATE_POINTERS_VS,
- ._3DCommandSubOpcode = sampler_state_opcodes[stage],
- .PointertoVSSamplerState = samplers.offset);
- }
+ anv_foreach_stage(s, stages) {
+ if (cmd_buffer->state.samplers[s].alloc_size > 0) {
+ anv_batch_emit(&cmd_buffer->batch,
+ GEN7_3DSTATE_SAMPLER_STATE_POINTERS_VS,
+ ._3DCommandSubOpcode = sampler_state_opcodes[s],
+ .PointertoVSSamplerState = cmd_buffer->state.samplers[s].offset);
+ }
- if (surfaces.alloc_size > 0) {
+ /* Always emit binding table pointers if we're asked to, since on SKL
+ * this is what flushes push constants. */
anv_batch_emit(&cmd_buffer->batch,
GEN7_3DSTATE_BINDING_TABLE_POINTERS_VS,
- ._3DCommandSubOpcode = binding_table_opcodes[stage],
- .PointertoVSBindingTable = surfaces.offset);
+ ._3DCommandSubOpcode = binding_table_opcodes[s],
+ .PointertoVSBindingTable = cmd_buffer->state.binding_tables[s].offset);
}
-
- return VK_SUCCESS;
}
-GENX_FUNC(GEN7, GEN7) void
+GENX_FUNC(GEN7, GEN7) uint32_t
genX(cmd_buffer_flush_descriptor_sets)(struct anv_cmd_buffer *cmd_buffer)
{
VkShaderStageFlags dirty = cmd_buffer->state.descriptors_dirty &
VkResult result = VK_SUCCESS;
anv_foreach_stage(s, dirty) {
- result = flush_descriptor_set(cmd_buffer, s);
+ result = anv_cmd_buffer_emit_samplers(cmd_buffer, s,
+ &cmd_buffer->state.samplers[s]);
+ if (result != VK_SUCCESS)
+ break;
+ result = anv_cmd_buffer_emit_binding_table(cmd_buffer, s,
+ &cmd_buffer->state.binding_tables[s]);
if (result != VK_SUCCESS)
break;
}
anv_cmd_buffer_emit_state_base_address(cmd_buffer);
/* Re-emit all active binding tables */
- anv_foreach_stage(s, cmd_buffer->state.pipeline->active_stages) {
- result = flush_descriptor_set(cmd_buffer, s);
-
- /* It had better succeed this time */
- assert(result == VK_SUCCESS);
+ dirty |= cmd_buffer->state.pipeline->active_stages;
+ anv_foreach_stage(s, dirty) {
+ result = anv_cmd_buffer_emit_samplers(cmd_buffer, s,
+ &cmd_buffer->state.samplers[s]);
+ if (result != VK_SUCCESS)
+ return result;
+ result = anv_cmd_buffer_emit_binding_table(cmd_buffer, s,
+ &cmd_buffer->state.binding_tables[s]);
+ if (result != VK_SUCCESS)
+ return result;
}
}
- cmd_buffer->state.descriptors_dirty &= ~cmd_buffer->state.pipeline->active_stages;
+ cmd_buffer->state.descriptors_dirty &= ~dirty;
+
+ return dirty;
}
static inline int64_t
.Address = { &cmd_buffer->device->workaround_bo, 0 });
}
- if (cmd_buffer->state.descriptors_dirty)
- gen7_cmd_buffer_flush_descriptor_sets(cmd_buffer);
+ uint32_t dirty = 0;
+ if (cmd_buffer->state.descriptors_dirty) {
+ dirty = gen7_cmd_buffer_flush_descriptor_sets(cmd_buffer);
+ gen7_cmd_buffer_emit_descriptor_pointers(cmd_buffer, dirty);
+ }
if (cmd_buffer->state.push_constants_dirty)
cmd_buffer_flush_push_constants(cmd_buffer);
#include "gen8_pack.h"
#include "gen9_pack.h"
-static void
+static uint32_t
cmd_buffer_flush_push_constants(struct anv_cmd_buffer *cmd_buffer)
{
static const uint32_t push_constant_opcodes[] = {
}
cmd_buffer->state.push_constants_dirty &= ~flushed;
+
+ return flushed;
}
#if ANV_GEN == 8
anv_batch_emit_batch(&cmd_buffer->batch, &pipeline->batch);
}
-#if ANV_GEN >= 9
- /* On SKL+ the new constants don't take effect until the next corresponding
- * 3DSTATE_BINDING_TABLE_POINTER_* command is parsed so we need to ensure
- * that is sent. As it is, we re-emit binding tables but we could hold on
- * to the offset of the most recent binding table and only re-emit the
- * 3DSTATE_BINDING_TABLE_POINTER_* command.
+ /* We emit the binding tables and sampler tables first, then emit push
+ * constants and then finally emit binding table and sampler table
+ * pointers. It has to happen in this order, since emitting the binding
+ * tables may change the push constants (in case of storage images). After
+ * emitting push constants, on SKL+ we have to emit the corresponding
+ * 3DSTATE_BINDING_TABLE_POINTER_* for the push constants to take effect.
*/
- cmd_buffer->state.descriptors_dirty |=
- cmd_buffer->state.push_constants_dirty &
- cmd_buffer->state.pipeline->active_stages;
-#endif
-
+ uint32_t dirty = 0;
if (cmd_buffer->state.descriptors_dirty)
- gen7_cmd_buffer_flush_descriptor_sets(cmd_buffer);
+ dirty = gen7_cmd_buffer_flush_descriptor_sets(cmd_buffer);
if (cmd_buffer->state.push_constants_dirty)
- cmd_buffer_flush_push_constants(cmd_buffer);
+ dirty |= cmd_buffer_flush_push_constants(cmd_buffer);
+
+ if (dirty)
+ gen7_cmd_buffer_emit_descriptor_pointers(cmd_buffer, dirty);
if (cmd_buffer->state.dirty & ANV_CMD_DIRTY_DYNAMIC_VIEWPORT)
gen8_cmd_buffer_emit_viewport(cmd_buffer);