diff --git a/src/freedreno/computerator/README.rst b/src/freedreno/computerator/README.rst index 4e5f81c5b73..c8ebd9c35c2 100644 --- a/src/freedreno/computerator/README.rst +++ b/src/freedreno/computerator/README.rst @@ -14,9 +14,10 @@ Headers The shader assembly can be prefixed with headers to control state setup: * ``@localsize X, Y, Z`` - configures local workgroup size -* ``@buf SZ`` - configures an SSBO of the specified size (in dwords). +* ``@buf SZ (cN.c)`` - configures an SSBO of the specified size (in dwords). The order of the ``@buf`` headers determines the index, ie the first - ``@buf`` header is ``g[0]``, the second ``g[1]``, and so on + ``@buf`` header is ``g[0]``, the second ``g[1]``, and so on. + The iova of the buffer is written as a vec2 to ``cN.c`` * ``@const(cN.c)`` configures a const vec4 starting at specified const register, ie ``@const(c1.x) 1.0, 2.0, 3.0, 4.0`` will populate ``c1.xyzw`` with ``vec4(1.0, 2.0, 3.0, 4.0)`` diff --git a/src/freedreno/computerator/a6xx.c b/src/freedreno/computerator/a6xx.c index b17d7dcac38..4347cd36fe2 100644 --- a/src/freedreno/computerator/a6xx.c +++ b/src/freedreno/computerator/a6xx.c @@ -232,6 +232,18 @@ cs_const_emit(struct fd_ringbuffer *ring, struct kernel *kernel, const_state->immediates[idx * 4 + 2] = grid[2]; } + for (int i = 0; i < MAX_BUFS; i++) { + if (kernel->buf_addr_regs[i] != INVALID_REG) { + assert((kernel->buf_addr_regs[i] & 0x3) == 0); + int idx = kernel->buf_addr_regs[i] >> 2; + + uint64_t iova = fd_bo_get_iova(kernel->bufs[i]); + + const_state->immediates[idx * 4 + 1] = iova >> 32; + const_state->immediates[idx * 4 + 0] = (iova << 32) >> 32; + } + } + /* truncate size to avoid writing constants that shader * does not use: */ diff --git a/src/freedreno/computerator/ir3_asm.c b/src/freedreno/computerator/ir3_asm.c index efca35e83f5..8539d4dde31 100644 --- a/src/freedreno/computerator/ir3_asm.c +++ b/src/freedreno/computerator/ir3_asm.c @@ -46,6 +46,8 @@ ir3_asm_assemble(struct ir3_compiler *c, FILE *in) kernel->base.num_bufs = kernel->info.num_bufs; memcpy(kernel->base.buf_sizes, kernel->info.buf_sizes, sizeof(kernel->base.buf_sizes)); + memcpy(kernel->base.buf_addr_regs, kernel->info.buf_addr_regs, + sizeof(kernel->base.buf_addr_regs)); unsigned sz = v->info.size; diff --git a/src/freedreno/computerator/main.h b/src/freedreno/computerator/main.h index b8984a5d414..dd52bad7ade 100644 --- a/src/freedreno/computerator/main.h +++ b/src/freedreno/computerator/main.h @@ -41,6 +41,7 @@ struct kernel { uint32_t local_size[3]; uint32_t num_bufs; uint32_t buf_sizes[MAX_BUFS]; /* size in dwords */ + uint32_t buf_addr_regs[MAX_BUFS]; /* filled in by frontend before launching grid: */ struct fd_bo *bufs[MAX_BUFS]; diff --git a/src/freedreno/ir3/ir3_assembler.c b/src/freedreno/ir3/ir3_assembler.c index fda3ea472c4..e71d4a3e441 100644 --- a/src/freedreno/ir3/ir3_assembler.c +++ b/src/freedreno/ir3/ir3_assembler.c @@ -47,6 +47,10 @@ ir3_parse_asm(struct ir3_compiler *c, struct ir3_kernel_info *info, FILE *in) info->numwg = INVALID_REG; + for (int i = 0; i < MAX_BUFS; i++) { + info->buf_addr_regs[i] = INVALID_REG; + } + /* Provide a default local_size in case the shader doesn't set it, so that * we don't crash at least. */ diff --git a/src/freedreno/ir3/ir3_assembler.h b/src/freedreno/ir3/ir3_assembler.h index e1b3e6521ee..1bbe4f60ff1 100644 --- a/src/freedreno/ir3/ir3_assembler.h +++ b/src/freedreno/ir3/ir3_assembler.h @@ -32,6 +32,7 @@ struct ir3_kernel_info { uint32_t num_bufs; uint32_t buf_sizes[MAX_BUFS]; /* size in dwords */ + uint32_t buf_addr_regs[MAX_BUFS]; /* driver-param uniforms: */ unsigned numwg; diff --git a/src/freedreno/ir3/ir3_parser.y b/src/freedreno/ir3/ir3_parser.y index f4cec9cc96d..713676e24b1 100644 --- a/src/freedreno/ir3/ir3_parser.y +++ b/src/freedreno/ir3/ir3_parser.y @@ -667,11 +667,21 @@ const_header: T_A_CONST '(' T_CONSTANT ')' const_val ',' const_val ',' cons add_const($3, $5, $7, $9, $11); } +buf_header_addr_reg: +| '(' T_CONSTANT ')' { + assert(($2 & 0x1) == 0); /* half-reg not allowed */ + unsigned reg = $2 >> 1; + + info->buf_addr_regs[info->num_bufs - 1] = reg; + /* reserve space in immediates for the actual value to be plugged in later: */ + add_const($2, 0, 0, 0, 0); +} + buf_header: T_A_BUF const_val { int idx = info->num_bufs++; assert(idx < MAX_BUFS); info->buf_sizes[idx] = $2; -} +} buf_header_addr_reg invocationid_header: T_A_INVOCATIONID '(' T_REGISTER ')' { assert(($3 & 0x1) == 0); /* half-reg not allowed */