mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 07:28:11 +02:00
tu: Add CRB builder.
Loosely based on freedreno's, but simplified since a lot of overflow handling was already there in tu_cs. It successfully catches issues of: - Overflowing the CRB reservation - Starting a new CRB with one in progress. - Emitting a pkt4 while a CRB emit is in progress. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38762>
This commit is contained in:
parent
2d6c15ad57
commit
1b93a4b778
2 changed files with 151 additions and 0 deletions
|
|
@ -628,3 +628,9 @@ tu_cs_trace_end(struct u_trace_context *utctx, void *cs, const char *fmt, ...)
|
|||
tu_cs_emit_debug_magic_strv((struct tu_cs *) cs, CP_NOP_END, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
tu_crb
|
||||
tu_cs::crb(uint32_t nregs)
|
||||
{
|
||||
return tu_crb(this, nregs);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,6 +80,9 @@ struct tu_bo_array {
|
|||
|
||||
#define TU_COND_EXEC_STACK_SIZE 4
|
||||
|
||||
struct tu_pkt;
|
||||
struct tu_crb;
|
||||
|
||||
struct tu_cs
|
||||
{
|
||||
uint32_t *start;
|
||||
|
|
@ -111,6 +114,10 @@ struct tu_cs
|
|||
uint32_t *cond_dwords[TU_COND_EXEC_STACK_SIZE];
|
||||
|
||||
uint32_t breadcrumb_emit_after;
|
||||
|
||||
tu_pkt *pkt;
|
||||
|
||||
tu_crb crb(uint32_t nregs);
|
||||
};
|
||||
|
||||
void
|
||||
|
|
@ -327,6 +334,7 @@ tu_cs_reserve(struct tu_cs *cs, uint32_t reserved_size)
|
|||
static inline void
|
||||
tu_cs_emit_pkt4(struct tu_cs *cs, uint16_t regindx, uint16_t cnt)
|
||||
{
|
||||
assert(!cs->pkt); /* No mixing with the packet builders.*/
|
||||
tu_cs_reserve(cs, cnt + 1);
|
||||
tu_cs_emit(cs, pm4_pkt4_hdr(regindx, cnt));
|
||||
}
|
||||
|
|
@ -337,6 +345,7 @@ tu_cs_emit_pkt4(struct tu_cs *cs, uint16_t regindx, uint16_t cnt)
|
|||
static inline void
|
||||
tu_cs_emit_pkt7(struct tu_cs *cs, uint8_t opcode, uint16_t cnt)
|
||||
{
|
||||
assert(!cs->pkt); /* No mixing with the packet builders.*/
|
||||
#if TU_BREADCRUMBS_ENABLED
|
||||
tu_cs_emit_sync_breadcrumb(cs, opcode, cnt + 1);
|
||||
#endif
|
||||
|
|
@ -657,4 +666,140 @@ struct tu_reg_value {
|
|||
(cs)->cur = p; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Helper base class for any pkt building.
|
||||
*/
|
||||
struct tu_pkt {
|
||||
protected:
|
||||
tu_pkt(tu_cs *cs, enum adreno_pm4_type3_packets pkt, unsigned ndwords)
|
||||
: cs(cs), pkt(pkt)
|
||||
{
|
||||
tu_cs_reserve(cs, ndwords + 1);
|
||||
start = cs->cur;
|
||||
cs->cur++; /* Leave a slot for the packet header when we're done. */
|
||||
assert(!cs->pkt);
|
||||
#if !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpragmas"
|
||||
#pragma GCC diagnostic ignored "-Wdangling-pointer="
|
||||
#endif
|
||||
/* Safe because destructor calls flush() which clears the potentially
|
||||
* dangling pointer:
|
||||
*/
|
||||
cs->pkt = this;
|
||||
#if !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
}
|
||||
|
||||
~tu_pkt()
|
||||
{
|
||||
flush();
|
||||
}
|
||||
|
||||
void append(uint32_t value)
|
||||
{
|
||||
tu_cs_emit(cs, value);
|
||||
}
|
||||
|
||||
void append(const uint32_t *dwords, uint32_t sizedwords)
|
||||
{
|
||||
tu_cs_emit_array(cs, dwords, sizedwords);
|
||||
}
|
||||
|
||||
public:
|
||||
void flush()
|
||||
{
|
||||
bool skip_empty = (pkt == CP_CONTEXT_REG_BUNCH);
|
||||
|
||||
if (!cs) {
|
||||
/* Skip double flushing, such as an early flush and then going out of
|
||||
* scope later.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
assert(start);
|
||||
assert(cs->pkt == this);
|
||||
|
||||
unsigned cnt = cs->cur - start - 1;
|
||||
|
||||
if (skip_empty && !cnt) {
|
||||
/* rewind the start pointer to the start of the packet. */
|
||||
cs->cur = start;
|
||||
} else {
|
||||
*start = pm4_pkt7_hdr(pkt, cnt);
|
||||
}
|
||||
cs->pkt = NULL;
|
||||
cs = NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
tu_cs *cs;
|
||||
enum adreno_pm4_type3_packets pkt;
|
||||
uint32_t *start;
|
||||
};
|
||||
|
||||
/**
|
||||
* A builder for CP_CONTEXT_REG_BUNCH. This packet can write an arbitrary
|
||||
* sequence of registers (payload consists of pairs of offset,value). It should
|
||||
* be as fast as a pkt4 packet writing a consecutive sequence of registers,
|
||||
* without the constraint of the registers being sequential, making it easier to
|
||||
* use when cmdstream emit involves if/else/loops. And should be less brittle
|
||||
* if registers shift around between generations. This builder intentionally
|
||||
* encourages use of tu_reg_value.
|
||||
*
|
||||
* For TU_CS_MODE_GROW command streams (cmd->cs, cmd->draw_cs), you have to pass
|
||||
* the maximum number of regs you might emit in the CONTEXT_REG_BUNCH. For
|
||||
* external/sub-stream CSes, you don't need to bother, and overflow of the
|
||||
* preallocated space will be caught by tu_cs_emit().
|
||||
*/
|
||||
struct tu_crb : public tu_pkt {
|
||||
public:
|
||||
/* Constructor to use with tu_cs: */
|
||||
tu_crb(tu_cs *cs, unsigned nregs)
|
||||
: tu_pkt(cs, CP_CONTEXT_REG_BUNCH, nregs * 2)
|
||||
{
|
||||
assert(nregs != 0 || cs->mode != TU_CS_MODE_GROW);
|
||||
}
|
||||
|
||||
tu_crb(tu_cs *cs): tu_pkt(cs, CP_CONTEXT_REG_BUNCH, 0)
|
||||
{
|
||||
assert(cs->mode != TU_CS_MODE_GROW);
|
||||
}
|
||||
|
||||
/* Append a <reg32> to CRB: */
|
||||
tu_crb &add(struct tu_reg_value reg)
|
||||
{
|
||||
append(reg.reg);
|
||||
append(reg.value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* Append a <reg64> to CRB: */
|
||||
tu_crb &add(struct tu_reg_value reg_lo, struct tu_reg_value reg_hi)
|
||||
{
|
||||
__assert_eq(reg_hi.reg, 0);
|
||||
uint64_t val = reg_lo.value;
|
||||
append(reg_lo.reg);
|
||||
append(val);
|
||||
append(reg_lo.reg + 1);
|
||||
append(val >> 32);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* for with_crb() */
|
||||
bool first = true;
|
||||
|
||||
private:
|
||||
/* Disallow copy constructor to prevent mistakes with using tu_crb instead
|
||||
* of tu_crb& as function param:
|
||||
*/
|
||||
tu_crb(const tu_crb &);
|
||||
};
|
||||
|
||||
|
||||
#define with_crb(...) \
|
||||
for (tu_crb crb(__VA_ARGS__); crb.first; crb.first = false)
|
||||
|
||||
#endif /* TU_CS_H */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue