ac,radv: add ac_emit_sdma_constant_fill()

Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38430>
This commit is contained in:
Samuel Pitoiset 2025-11-13 18:13:57 +01:00
parent 0007644913
commit 191bf7aba6
3 changed files with 33 additions and 30 deletions

View file

@ -64,3 +64,25 @@ ac_emit_sdma_write_data_head(struct ac_cmdbuf *cs, uint64_t va, uint32_t count)
ac_cmdbuf_emit(count - 1);
ac_cmdbuf_end();
}
uint64_t
ac_emit_sdma_constant_fill(struct ac_cmdbuf *cs, enum sdma_version sdma_ip_version,
uint64_t va, uint64_t size, uint32_t value)
{
const uint32_t fill_size = 2; /* This means that count is in DWORDS. */
assert(sdma_ip_version >= SDMA_2_4);
const uint64_t max_fill_size = BITFIELD64_MASK(sdma_ip_version >= SDMA_6_0 ? 30 : 22) & ~0x3;
const uint64_t bytes_written = MIN2(size, max_fill_size);
ac_cmdbuf_begin(cs);
ac_cmdbuf_emit(SDMA_PACKET(SDMA_OPCODE_CONSTANT_FILL, 0, 0) | (fill_size << 30));
ac_cmdbuf_emit(va);
ac_cmdbuf_emit(va >> 32);
ac_cmdbuf_emit(value);
ac_cmdbuf_emit(bytes_written - 1); /* Must be programmed in bytes, even if the fill is done in dwords. */
ac_cmdbuf_end();
return bytes_written;
}

View file

@ -24,6 +24,10 @@ void ac_emit_sdma_wait_mem(struct ac_cmdbuf *cs, uint32_t op, uint64_t va, uint3
void ac_emit_sdma_write_data_head(struct ac_cmdbuf *cs, uint64_t va, uint32_t count);
uint64_t
ac_emit_sdma_constant_fill(struct ac_cmdbuf *cs, enum sdma_version sdma_ip_version,
uint64_t va, uint64_t size, uint32_t value);
#ifdef __cplusplus
}
#endif

View file

@ -404,41 +404,18 @@ radv_sdma_copy_memory(const struct radv_device *device, struct radv_cmd_stream *
}
void
radv_sdma_fill_memory(const struct radv_device *device, struct radv_cmd_stream *cs, const uint64_t va,
const uint64_t size, const uint32_t value)
radv_sdma_fill_memory(const struct radv_device *device, struct radv_cmd_stream *cs, uint64_t va, uint64_t size,
const uint32_t value)
{
const struct radv_physical_device *pdev = radv_device_physical(device);
const uint32_t fill_size = 2; /* This means that the count is in dwords. */
const uint32_t constant_fill_header = SDMA_PACKET(SDMA_OPCODE_CONSTANT_FILL, 0, 0) | (fill_size & 0x3) << 30;
while (size > 0) {
radeon_check_space(device->ws, cs->b, 5);
uint64_t bytes_written = ac_emit_sdma_constant_fill(cs->b, pdev->info.sdma_ip_version, va, size, value);
/* This packet is the same since SDMA v2.4, haven't bothered to check older versions. */
const enum sdma_version ver = pdev->info.sdma_ip_version;
assert(ver >= SDMA_2_4);
/* Maximum allowed fill size depends on the GPU.
* Emit as many packets as necessary to fill all the bytes we need.
*/
const uint64_t max_fill_bytes = BITFIELD64_MASK(ver >= SDMA_6_0 ? 30 : 22) & ~0x3;
const unsigned num_packets = DIV_ROUND_UP(size, max_fill_bytes);
ASSERTED unsigned cdw_max = radeon_check_space(device->ws, cs->b, num_packets * 5);
radeon_begin(cs);
for (unsigned i = 0; i < num_packets; ++i) {
const uint64_t offset = i * max_fill_bytes;
const uint64_t fill_bytes = MIN2(size - offset, max_fill_bytes);
const uint64_t fill_va = va + offset;
radeon_emit(constant_fill_header);
radeon_emit(fill_va);
radeon_emit(fill_va >> 32);
radeon_emit(value);
radeon_emit(fill_bytes - 1); /* Must be programmed in bytes, even if the fill is done in dwords. */
size -= bytes_written;
va += bytes_written;
}
radeon_end();
assert(cs->b->cdw <= cdw_max);
}
static void