{
const struct tu_tiling_config *tiling = &cmd->state.tiling_config;
+ /* XFB commands are emitted for BINNING || SYSMEM, which makes it incompatible
+ * with non-hw binning GMEM rendering. this is required because some of the
+ * XFB commands need to only be executed once
+ */
+ if (cmd->state.xfb_used)
+ return true;
+
if (unlikely(cmd->device->physical_device->instance->debug_flags & TU_DEBUG_NOBIN))
return false;
tu_cs_emit(cs, CP_SET_DRAW_STATE__1_ADDR_LO(0));
tu_cs_emit(cs, CP_SET_DRAW_STATE__2_ADDR_HI(0));
- /* Set not to use streamout by default, */
- tu_cs_emit_pkt7(cs, CP_CONTEXT_REG_BUNCH, 4);
- tu_cs_emit(cs, REG_A6XX_VPC_SO_CNTL);
- tu_cs_emit(cs, 0);
- tu_cs_emit(cs, REG_A6XX_VPC_SO_BUF_CNTL);
- tu_cs_emit(cs, 0);
-
tu_cs_emit_regs(cs,
A6XX_SP_HS_CTRL_REG0(0));
{
const struct tu_tiling_config *tiling = &cmd->state.tiling_config;
+ if (use_hw_binning(cmd))
+ cmd->use_vsc_data = true;
+
tu6_tile_render_begin(cmd, &cmd->cs);
for (uint32_t y = 0; y < tiling->tile_count.height; y++) {
const VkDeviceSize *pSizes)
{
TU_FROM_HANDLE(tu_cmd_buffer, cmd, commandBuffer);
- assert(firstBinding + bindingCount <= IR3_MAX_SO_BUFFERS);
+ struct tu_cs *cs = &cmd->draw_cs;
+
+ /* using COND_REG_EXEC for xfb commands matches the blob behavior
+ * presumably there isn't any benefit using a draw state when the
+ * condition is (SYSMEM | BINNING)
+ */
+ tu_cond_exec_start(cs, CP_COND_REG_EXEC_0_MODE(RENDER_MODE) |
+ CP_COND_REG_EXEC_0_SYSMEM |
+ CP_COND_REG_EXEC_0_BINNING);
for (uint32_t i = 0; i < bindingCount; i++) {
- uint32_t idx = firstBinding + i;
TU_FROM_HANDLE(tu_buffer, buf, pBuffers[i]);
+ uint64_t iova = buf->bo->iova + pOffsets[i];
+ uint32_t size = buf->bo->size - pOffsets[i];
+ uint32_t idx = i + firstBinding;
- if (pOffsets[i] != 0)
- cmd->state.streamout_reset |= 1 << idx;
+ if (pSizes && pSizes[i] != VK_WHOLE_SIZE)
+ size = pSizes[i];
- cmd->state.streamout_buf.buffers[idx] = buf;
- cmd->state.streamout_buf.offsets[idx] = pOffsets[i];
- cmd->state.streamout_buf.sizes[idx] = pSizes[i];
+ /* BUFFER_BASE is 32-byte aligned, add remaining offset to BUFFER_OFFSET */
+ uint32_t offset = iova & 0x1f;
+ iova &= ~(uint64_t) 0x1f;
- cmd->state.streamout_enabled |= 1 << idx;
+ tu_cs_emit_pkt4(cs, REG_A6XX_VPC_SO_BUFFER_BASE(idx), 3);
+ tu_cs_emit_qw(cs, iova);
+ tu_cs_emit(cs, size + offset);
+
+ cmd->state.streamout_offset[idx] = offset;
+
+ tu_bo_list_add(&cmd->bo_list, buf->bo, MSM_SUBMIT_BO_WRITE);
}
- cmd->state.dirty |= TU_CMD_DIRTY_STREAMOUT_BUFFERS;
+ tu_cond_exec_end(cs);
}
-void tu_CmdBeginTransformFeedbackEXT(VkCommandBuffer commandBuffer,
- uint32_t firstCounterBuffer,
- uint32_t counterBufferCount,
- const VkBuffer *pCounterBuffers,
- const VkDeviceSize *pCounterBufferOffsets)
+void
+tu_CmdBeginTransformFeedbackEXT(VkCommandBuffer commandBuffer,
+ uint32_t firstCounterBuffer,
+ uint32_t counterBufferCount,
+ const VkBuffer *pCounterBuffers,
+ const VkDeviceSize *pCounterBufferOffsets)
{
- assert(firstCounterBuffer + counterBufferCount <= IR3_MAX_SO_BUFFERS);
- /* TODO do something with counter buffer? */
+ TU_FROM_HANDLE(tu_cmd_buffer, cmd, commandBuffer);
+ struct tu_cs *cs = &cmd->draw_cs;
+
+ tu_cond_exec_start(cs, CP_COND_REG_EXEC_0_MODE(RENDER_MODE) |
+ CP_COND_REG_EXEC_0_SYSMEM |
+ CP_COND_REG_EXEC_0_BINNING);
+
+ /* TODO: only update offset for active buffers */
+ for (uint32_t i = 0; i < IR3_MAX_SO_BUFFERS; i++)
+ tu_cs_emit_regs(cs, A6XX_VPC_SO_BUFFER_OFFSET(i, cmd->state.streamout_offset[i]));
+
+ for (uint32_t i = 0; i < counterBufferCount; i++) {
+ uint32_t idx = firstCounterBuffer + i;
+ uint32_t offset = cmd->state.streamout_offset[idx];
+
+ if (!pCounterBuffers[i])
+ continue;
+
+ TU_FROM_HANDLE(tu_buffer, buf, pCounterBuffers[i]);
+
+ tu_bo_list_add(&cmd->bo_list, buf->bo, MSM_SUBMIT_BO_READ);
+
+ tu_cs_emit_pkt7(cs, CP_MEM_TO_REG, 3);
+ tu_cs_emit(cs, CP_MEM_TO_REG_0_REG(REG_A6XX_VPC_SO_BUFFER_OFFSET(idx)) |
+ CP_MEM_TO_REG_0_UNK31 |
+ CP_MEM_TO_REG_0_CNT(1));
+ tu_cs_emit_qw(cs, buf->bo->iova + pCounterBufferOffsets[i]);
+
+ if (offset) {
+ tu_cs_emit_pkt7(cs, CP_REG_RMW, 3);
+ tu_cs_emit(cs, CP_REG_RMW_0_DST_REG(REG_A6XX_VPC_SO_BUFFER_OFFSET(idx)) |
+ CP_REG_RMW_0_SRC1_ADD);
+ tu_cs_emit_qw(cs, 0xffffffff);
+ tu_cs_emit_qw(cs, offset);
+ }
+ }
+
+ tu_cond_exec_end(cs);
}
void tu_CmdEndTransformFeedbackEXT(VkCommandBuffer commandBuffer,
const VkBuffer *pCounterBuffers,
const VkDeviceSize *pCounterBufferOffsets)
{
- assert(firstCounterBuffer + counterBufferCount <= IR3_MAX_SO_BUFFERS);
- /* TODO do something with counter buffer? */
-
TU_FROM_HANDLE(tu_cmd_buffer, cmd, commandBuffer);
- cmd->state.streamout_enabled = 0;
+ struct tu_cs *cs = &cmd->draw_cs;
+
+ tu_cond_exec_start(cs, CP_COND_REG_EXEC_0_MODE(RENDER_MODE) |
+ CP_COND_REG_EXEC_0_SYSMEM |
+ CP_COND_REG_EXEC_0_BINNING);
+
+ /* TODO: only flush buffers that need to be flushed */
+ for (uint32_t i = 0; i < IR3_MAX_SO_BUFFERS; i++) {
+ /* note: FLUSH_BASE is always the same, so it could go in init_hw()? */
+ tu_cs_emit_pkt4(cs, REG_A6XX_VPC_SO_FLUSH_BASE(i), 2);
+ tu_cs_emit_qw(cs, cmd->scratch_bo.iova + ctrl_offset(flush_base[i]));
+ tu6_emit_event_write(cmd, cs, FLUSH_SO_0 + i);
+ }
+
+ for (uint32_t i = 0; i < counterBufferCount; i++) {
+ uint32_t idx = firstCounterBuffer + i;
+ uint32_t offset = cmd->state.streamout_offset[idx];
+
+ if (!pCounterBuffers[i])
+ continue;
+
+ TU_FROM_HANDLE(tu_buffer, buf, pCounterBuffers[i]);
+
+ tu_bo_list_add(&cmd->bo_list, buf->bo, MSM_SUBMIT_BO_WRITE);
+
+ /* VPC_SO_FLUSH_BASE has dwords counter, but counter should be in bytes */
+ tu_cs_emit_pkt7(cs, CP_MEM_TO_REG, 3);
+ tu_cs_emit(cs, CP_MEM_TO_REG_0_REG(REG_A6XX_CP_SCRATCH_REG(0)) |
+ CP_MEM_TO_REG_0_SHIFT_BY_2 |
+ 0x40000 | /* ??? */
+ CP_MEM_TO_REG_0_UNK31 |
+ CP_MEM_TO_REG_0_CNT(1));
+ tu_cs_emit_qw(cs, cmd->scratch_bo.iova + ctrl_offset(flush_base[idx]));
+
+ if (offset) {
+ tu_cs_emit_pkt7(cs, CP_REG_RMW, 3);
+ tu_cs_emit(cs, CP_REG_RMW_0_DST_REG(REG_A6XX_CP_SCRATCH_REG(0)) |
+ CP_REG_RMW_0_SRC1_ADD);
+ tu_cs_emit_qw(cs, 0xffffffff);
+ tu_cs_emit_qw(cs, -offset);
+ }
+
+ tu_cs_emit_pkt7(cs, CP_REG_TO_MEM, 3);
+ tu_cs_emit(cs, CP_REG_TO_MEM_0_REG(REG_A6XX_CP_SCRATCH_REG(0)) |
+ CP_REG_TO_MEM_0_CNT(1));
+ tu_cs_emit_qw(cs, buf->bo->iova + pCounterBufferOffsets[i]);
+ }
+
+ tu_cond_exec_end(cs);
+
+ cmd->state.xfb_used = true;
}
void
tu_set_input_attachments(cmd, cmd->state.subpass);
- /* note: use_hw_binning only checks tiling config */
- if (use_hw_binning(cmd))
- cmd->use_vsc_data = true;
-
for (uint32_t i = 0; i < fb->attachment_count; ++i) {
const struct tu_image_view *iview = fb->attachments[i].attachment;
tu_bo_list_add(&cmd->bo_list, iview->image->bo,
return tu_cs_end_sub_stream(&cmd->sub_cs, &cs);
}
-static void
-tu6_emit_streamout(struct tu_cmd_buffer *cmd, struct tu_cs *cs)
-{
- struct tu_streamout_state *tf = &cmd->state.pipeline->streamout;
-
- for (unsigned i = 0; i < IR3_MAX_SO_BUFFERS; i++) {
- struct tu_buffer *buf = cmd->state.streamout_buf.buffers[i];
- if (!buf)
- continue;
-
- uint32_t offset;
- offset = cmd->state.streamout_buf.offsets[i];
-
- tu_cs_emit_regs(cs, A6XX_VPC_SO_BUFFER_BASE(i, .bo = buf->bo,
- .bo_offset = buf->bo_offset));
- tu_cs_emit_regs(cs, A6XX_VPC_SO_BUFFER_SIZE(i, buf->size));
-
- if (cmd->state.streamout_reset & (1 << i)) {
- tu_cs_emit_regs(cs, A6XX_VPC_SO_BUFFER_OFFSET(i, offset));
- cmd->state.streamout_reset &= ~(1 << i);
- } else {
- tu_cs_emit_pkt7(cs, CP_MEM_TO_REG, 3);
- tu_cs_emit(cs, CP_MEM_TO_REG_0_REG(REG_A6XX_VPC_SO_BUFFER_OFFSET(i)) |
- CP_MEM_TO_REG_0_SHIFT_BY_2 | CP_MEM_TO_REG_0_UNK31 |
- CP_MEM_TO_REG_0_CNT(0));
- tu_cs_emit_qw(cs, cmd->scratch_bo.iova +
- ctrl_offset(flush_base[i].offset));
- }
-
- tu_cs_emit_regs(cs, A6XX_VPC_SO_FLUSH_BASE(i, .bo = &cmd->scratch_bo,
- .bo_offset =
- ctrl_offset(flush_base[i])));
- }
-
- if (cmd->state.streamout_enabled) {
- tu_cs_emit_pkt7(cs, CP_CONTEXT_REG_BUNCH, 12 + (2 * tf->prog_count));
- tu_cs_emit(cs, REG_A6XX_VPC_SO_BUF_CNTL);
- tu_cs_emit(cs, tf->vpc_so_buf_cntl);
- tu_cs_emit(cs, REG_A6XX_VPC_SO_NCOMP(0));
- tu_cs_emit(cs, tf->ncomp[0]);
- tu_cs_emit(cs, REG_A6XX_VPC_SO_NCOMP(1));
- tu_cs_emit(cs, tf->ncomp[1]);
- tu_cs_emit(cs, REG_A6XX_VPC_SO_NCOMP(2));
- tu_cs_emit(cs, tf->ncomp[2]);
- tu_cs_emit(cs, REG_A6XX_VPC_SO_NCOMP(3));
- tu_cs_emit(cs, tf->ncomp[3]);
- tu_cs_emit(cs, REG_A6XX_VPC_SO_CNTL);
- tu_cs_emit(cs, A6XX_VPC_SO_CNTL_ENABLE);
- for (unsigned i = 0; i < tf->prog_count; i++) {
- tu_cs_emit(cs, REG_A6XX_VPC_SO_PROG);
- tu_cs_emit(cs, tf->prog[i]);
- }
- } else {
- tu_cs_emit_pkt7(cs, CP_CONTEXT_REG_BUNCH, 4);
- tu_cs_emit(cs, REG_A6XX_VPC_SO_CNTL);
- tu_cs_emit(cs, 0);
- tu_cs_emit(cs, REG_A6XX_VPC_SO_BUF_CNTL);
- tu_cs_emit(cs, 0);
- }
-}
-
static uint64_t
get_tess_param_bo_size(const struct tu_pipeline *pipeline,
const struct tu_draw_info *draw_info)
tu6_emit_consts(cmd, pipeline, descriptors_state, MESA_SHADER_FRAGMENT);
}
- if (cmd->state.dirty & TU_CMD_DIRTY_STREAMOUT_BUFFERS)
- tu6_emit_streamout(cmd, cs);
-
if (cmd->state.dirty & TU_CMD_DIRTY_DESCRIPTOR_SETS) {
/* We need to reload the descriptors every time the descriptor sets
* change. However, the commands we send only depend on the pipeline
tu_cs_sanity_check(cs);
- /* track BOs */
- if (cmd->state.dirty & TU_CMD_DIRTY_STREAMOUT_BUFFERS) {
- for (unsigned i = 0; i < IR3_MAX_SO_BUFFERS; i++) {
- const struct tu_buffer *buf = cmd->state.streamout_buf.buffers[i];
- if (buf) {
- tu_bo_list_add(&cmd->bo_list, buf->bo,
- MSM_SUBMIT_BO_READ | MSM_SUBMIT_BO_WRITE);
- }
- }
- }
-
/* There are too many graphics dirty bits to list here, so just list the
* bits to preserve instead. The only things not emitted here are
* compute-related state.
else
tu6_emit_draw_direct(cmd, cs, draw);
- if (cmd->state.streamout_enabled) {
- for (unsigned i = 0; i < IR3_MAX_SO_BUFFERS; i++) {
- if (cmd->state.streamout_enabled & (1 << i))
- tu6_emit_event_write(cmd, cs, FLUSH_SO_0 + i);
- }
- }
-
tu_cs_sanity_check(cs);
}
}
static void
-tu6_setup_streamout(const struct ir3_shader_variant *v,
- struct ir3_shader_linkage *l, struct tu_streamout_state *tf)
+tu6_setup_streamout(struct tu_cs *cs,
+ const struct ir3_shader_variant *v,
+ struct ir3_shader_linkage *l)
{
const struct ir3_stream_output_info *info = &v->shader->stream_output;
+ uint32_t prog[IR3_MAX_SO_OUTPUTS * 2] = {};
+ uint32_t ncomp[IR3_MAX_SO_BUFFERS] = {};
+ uint32_t prog_count = align(l->max_loc, 2) / 2;
- memset(tf, 0, sizeof(*tf));
+ /* TODO: streamout state should be in a non-GMEM draw state */
- tf->prog_count = align(l->max_loc, 2) / 2;
-
- debug_assert(tf->prog_count < ARRAY_SIZE(tf->prog));
+ /* no streamout: */
+ if (info->num_outputs == 0) {
+ tu_cs_emit_pkt7(cs, CP_CONTEXT_REG_BUNCH, 4);
+ tu_cs_emit(cs, REG_A6XX_VPC_SO_CNTL);
+ tu_cs_emit(cs, 0);
+ tu_cs_emit(cs, REG_A6XX_VPC_SO_BUF_CNTL);
+ tu_cs_emit(cs, 0);
+ return;
+ }
- /* set stride info to the streamout state */
- for (unsigned i = 0; i < IR3_MAX_SO_BUFFERS; i++)
- tf->stride[i] = info->stride[i];
+ /* is there something to do with info->stride[i]? */
for (unsigned i = 0; i < info->num_outputs; i++) {
const struct ir3_stream_output *out = &info->output[i];
if (v->outputs[k].regid == INVALID_REG)
continue;
- tf->ncomp[out->output_buffer] += out->num_components;
+ ncomp[out->output_buffer] += out->num_components;
/* linkage map sorted by order frag shader wants things, so
* a bit less ideal here..
unsigned off = j + out->dst_offset; /* in dwords */
if (loc & 1) {
- tf->prog[loc/2] |= A6XX_VPC_SO_PROG_B_EN |
- A6XX_VPC_SO_PROG_B_BUF(out->output_buffer) |
- A6XX_VPC_SO_PROG_B_OFF(off * 4);
+ prog[loc/2] |= A6XX_VPC_SO_PROG_B_EN |
+ A6XX_VPC_SO_PROG_B_BUF(out->output_buffer) |
+ A6XX_VPC_SO_PROG_B_OFF(off * 4);
} else {
- tf->prog[loc/2] |= A6XX_VPC_SO_PROG_A_EN |
- A6XX_VPC_SO_PROG_A_BUF(out->output_buffer) |
- A6XX_VPC_SO_PROG_A_OFF(off * 4);
+ prog[loc/2] |= A6XX_VPC_SO_PROG_A_EN |
+ A6XX_VPC_SO_PROG_A_BUF(out->output_buffer) |
+ A6XX_VPC_SO_PROG_A_OFF(off * 4);
}
}
}
- tf->vpc_so_buf_cntl = A6XX_VPC_SO_BUF_CNTL_ENABLE |
- COND(tf->ncomp[0] > 0, A6XX_VPC_SO_BUF_CNTL_BUF0) |
- COND(tf->ncomp[1] > 0, A6XX_VPC_SO_BUF_CNTL_BUF1) |
- COND(tf->ncomp[2] > 0, A6XX_VPC_SO_BUF_CNTL_BUF2) |
- COND(tf->ncomp[3] > 0, A6XX_VPC_SO_BUF_CNTL_BUF3);
+ tu_cs_emit_pkt7(cs, CP_CONTEXT_REG_BUNCH, 12 + 2 * prog_count);
+ tu_cs_emit(cs, REG_A6XX_VPC_SO_BUF_CNTL);
+ tu_cs_emit(cs, A6XX_VPC_SO_BUF_CNTL_ENABLE |
+ COND(ncomp[0] > 0, A6XX_VPC_SO_BUF_CNTL_BUF0) |
+ COND(ncomp[1] > 0, A6XX_VPC_SO_BUF_CNTL_BUF1) |
+ COND(ncomp[2] > 0, A6XX_VPC_SO_BUF_CNTL_BUF2) |
+ COND(ncomp[3] > 0, A6XX_VPC_SO_BUF_CNTL_BUF3));
+ for (uint32_t i = 0; i < 4; i++) {
+ tu_cs_emit(cs, REG_A6XX_VPC_SO_NCOMP(i));
+ tu_cs_emit(cs, ncomp[i]);
+ }
+ /* note: "VPC_SO_CNTL" write seems to be responsible for resetting the SO_PROG */
+ tu_cs_emit(cs, REG_A6XX_VPC_SO_CNTL);
+ tu_cs_emit(cs, A6XX_VPC_SO_CNTL_ENABLE);
+ for (uint32_t i = 0; i < prog_count; i++) {
+ tu_cs_emit(cs, REG_A6XX_VPC_SO_PROG);
+ tu_cs_emit(cs, prog[i]);
+ }
}
static void
const struct ir3_shader_variant *hs,
const struct ir3_shader_variant *ds,
const struct ir3_shader_variant *gs,
- const struct ir3_shader_variant *fs,
- struct tu_streamout_state *tf)
+ const struct ir3_shader_variant *fs)
{
const struct ir3_shader_variant *last_shader;
if (gs) {
ir3_link_add(&linkage, pointsize_regid, 0x1, linkage.max_loc);
}
- if (last_shader->shader->stream_output.num_outputs)
- tu6_setup_streamout(last_shader, &linkage, tf);
+ tu6_setup_streamout(cs, last_shader, &linkage);
/* map outputs of the last shader to VPC */
assert(linkage.cnt <= 32);
tu6_emit_program(struct tu_cs *cs,
struct tu_pipeline_builder *builder,
const struct tu_bo *binary_bo,
- bool binning_pass,
- struct tu_streamout_state *tf)
+ bool binning_pass)
{
const struct ir3_shader_variant *vs = builder->variants[MESA_SHADER_VERTEX];
const struct ir3_shader_variant *bs = builder->binning_variant;
tu_cs_emit_pkt4(cs, REG_A6XX_SP_HS_UNKNOWN_A831, 1);
tu_cs_emit(cs, 0);
- tu6_emit_vpc(cs, vs, hs, ds, gs, fs, tf);
+ tu6_emit_vpc(cs, vs, hs, ds, gs, fs);
tu6_emit_vpc_varying_modes(cs, fs);
if (fs) {
{
struct tu_cs prog_cs;
tu_cs_begin_sub_stream(&pipeline->cs, 512, &prog_cs);
- tu6_emit_program(&prog_cs, builder, &pipeline->program.binary_bo, false, &pipeline->streamout);
+ tu6_emit_program(&prog_cs, builder, &pipeline->program.binary_bo, false);
pipeline->program.state_ib = tu_cs_end_sub_stream(&pipeline->cs, &prog_cs);
tu_cs_begin_sub_stream(&pipeline->cs, 512, &prog_cs);
- tu6_emit_program(&prog_cs, builder, &pipeline->program.binary_bo, true, &pipeline->streamout);
+ tu6_emit_program(&prog_cs, builder, &pipeline->program.binary_bo, true);
pipeline->program.binning_state_ib = tu_cs_end_sub_stream(&pipeline->cs, &prog_cs);
VkShaderStageFlags stages = 0;
TU_CMD_DIRTY_DESCRIPTOR_SETS = 1 << 3,
TU_CMD_DIRTY_COMPUTE_DESCRIPTOR_SETS = 1 << 4,
TU_CMD_DIRTY_SHADER_CONSTS = 1 << 5,
- TU_CMD_DIRTY_STREAMOUT_BUFFERS = 1 << 6,
/* all draw states were disabled and need to be re-enabled: */
TU_CMD_DIRTY_DRAW_STATE = 1 << 7,
};
-struct tu_streamout_state {
- uint16_t stride[IR3_MAX_SO_BUFFERS];
- uint32_t ncomp[IR3_MAX_SO_BUFFERS];
- uint32_t prog[IR3_MAX_SO_OUTPUTS * 2];
- uint32_t prog_count;
- uint32_t vpc_so_buf_cntl;
-};
-
/* There are only three cache domains we have to care about: the CCU, or
* color cache unit, which is used for color and depth/stencil attachments
* and copy/blit destinations, and is split conceptually into color and depth,
struct tu_cs_entry desc_sets_ib, desc_sets_load_ib;
struct tu_cs_entry ia_gmem_ib, ia_sysmem_ib;
- /* Stream output buffers */
- struct
- {
- struct tu_buffer *buffers[IR3_MAX_SO_BUFFERS];
- VkDeviceSize offsets[IR3_MAX_SO_BUFFERS];
- VkDeviceSize sizes[IR3_MAX_SO_BUFFERS];
- } streamout_buf;
-
- uint8_t streamout_reset;
- uint8_t streamout_enabled;
-
/* Index buffer */
struct tu_buffer *index_buffer;
uint64_t index_offset;
uint32_t max_index_count;
uint64_t index_va;
+ /* because streamout base has to be 32-byte aligned
+ * there is an extra offset to deal with when it is
+ * unaligned
+ */
+ uint8_t streamout_offset[IR3_MAX_SO_BUFFERS];
+
/* Renderpasses are tricky, because we may need to flush differently if
* using sysmem vs. gmem and therefore we have to delay any flushing that
* happens before a renderpass. So we have to have two copies of the flush
struct tu_tiling_config tiling_config;
struct tu_cs_entry tile_store_ib;
+
+ bool xfb_used;
};
struct tu_cmd_pool
VkShaderStageFlags active_stages;
uint32_t active_desc_sets;
- struct tu_streamout_state streamout;
-
/* mask of enabled dynamic states
* if BIT(i) is set, pipeline->dynamic_state[i] is *NOT* used
*/
const struct ir3_shader_variant *hs,
const struct ir3_shader_variant *ds,
const struct ir3_shader_variant *gs,
- const struct ir3_shader_variant *fs,
- struct tu_streamout_state *tf);
+ const struct ir3_shader_variant *fs);
void
tu6_emit_fs_inputs(struct tu_cs *cs, const struct ir3_shader_variant *fs);