drm/shadertoy: add time-based animation

This commit is contained in:
Zack Buhman 2025-10-21 15:39:25 -05:00
parent ae3fa0f2e6
commit b4310b4fef
3 changed files with 180 additions and 112 deletions

View File

@ -16,6 +16,19 @@
#include "3d_registers_bits.h"
#include "command_processor.h"
static inline uint32_t rreg(void * rmmio, uint32_t offset)
{
uint32_t value = *((volatile uint32_t *)(((uintptr_t)rmmio) + offset));
asm volatile ("" ::: "memory");
return value;
}
static inline void wreg(void * rmmio, uint32_t offset, uint32_t value)
{
*((volatile uint32_t *)(((uintptr_t)rmmio) + offset)) = value;
asm volatile ("" ::: "memory");
}
union u32_f32 {
uint32_t u32;
float f32;
@ -23,7 +36,7 @@ union u32_f32 {
static union u32_f32 ib[16384];
int indirect_buffer()
int indirect_buffer(float time)
{
int ix = 0;
@ -437,7 +450,7 @@ int indirect_buffer()
// fragment constants
const float fragment_consts[] = {
-0.1f, 0, 0, 0,
time, 0, 0, 0,
};
int fragment_consts_length = (sizeof (fragment_consts)) / (sizeof (fragment_consts[0]));
@ -452,7 +465,7 @@ int indirect_buffer()
// fragment code
const uint32_t fragment_shader[] = {
#include "shadertoy_circle.fs.inc"
#include "shadertoy_sin.fs.inc"
};
const int fragment_shader_length = (sizeof (fragment_shader)) / (sizeof (fragment_shader[0]));
assert(fragment_shader_length % 6 == 0);
@ -526,18 +539,10 @@ int indirect_buffer()
return ix;
}
int main()
int create_colorbuffer(int fd, int colorbuffer_size)
{
int ret;
int fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
const int colorbuffer_size = 1600 * 1200 * 4;
int colorbuffer_handle;
void * colorbuffer_ptr;
int flush_handle;
// colorbuffer
{
struct drm_radeon_gem_create args = {
.size = colorbuffer_size,
.alignment = 4096,
@ -552,12 +557,8 @@ int main()
}
assert(args.handle != 0);
colorbuffer_handle = args.handle;
}
{
struct drm_radeon_gem_mmap mmap_args = {
.handle = colorbuffer_handle,
.handle = args.handle,
.offset = 0,
.size = colorbuffer_size,
};
@ -566,16 +567,57 @@ int main()
perror("drmCommandWriteRead(DRM_RADEON_GEM_MMAP)");
}
colorbuffer_ptr = mmap(0, mmap_args.size, PROT_READ|PROT_WRITE, MAP_SHARED,
fd, mmap_args.addr_ptr);
}
void * ptr = mmap(0,
colorbuffer_size,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd,
mmap_args.addr_ptr);
assert(ptr != MAP_FAILED);
{ // clear colorbuffer
// clear colorbuffer
for (int i = 0; i < colorbuffer_size / 4; i++) {
((uint32_t*)colorbuffer_ptr)[i] = 0;
((uint32_t*)ptr)[i] = 0x00000000;
}
asm volatile ("" ::: "memory");
}
munmap(ptr, colorbuffer_size);
return args.handle;
}
int main()
{
//////////////////////////////////////////////////////////////////////////////
// PCI resource0
//////////////////////////////////////////////////////////////////////////////
const char * resource2_path = "/sys/bus/pci/devices/0000:01:00.0/resource2";
int resource2_fd = open(resource2_path, O_RDWR | O_SYNC);
assert(resource2_fd >= 0);
uint32_t resource2_size = 0x10000;
void * resource2_base = mmap(0, resource2_size, PROT_READ | PROT_WRITE, MAP_SHARED, resource2_fd, 0);
assert(resource2_base != MAP_FAILED);
void * rmmio = resource2_base;
//////////////////////////////////////////////////////////////////////////////
// DRI card0
//////////////////////////////////////////////////////////////////////////////
int ret;
int fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
const int colorbuffer_size = 1600 * 1200 * 4;
int colorbuffer_handle[2];
int flush_handle;
// colorbuffer
colorbuffer_handle[0] = create_colorbuffer(fd, colorbuffer_size);
colorbuffer_handle[1] = create_colorbuffer(fd, colorbuffer_size);
fprintf(stderr, "colorbuffer handle[0] %d\n", colorbuffer_handle[0]);
fprintf(stderr, "colorbuffer handle[1] %d\n", colorbuffer_handle[1]);
// flush
{
@ -596,12 +638,21 @@ int main()
flush_handle = args.handle;
}
uint32_t flags[2] = {
5, // RADEON_CS_KEEP_TILING_FLAGS | RADEON_CS_END_OF_FRAME
0, // RADEON_CS_RING_GFX
};
fprintf(stderr, "colorbuffer handle %d\n", colorbuffer_handle);
float time = 0;
int ib_dwords = indirect_buffer(time);
int colorbuffer_ix = 0;
while (true) {
struct drm_radeon_cs_reloc relocs[] = {
{
.handle = colorbuffer_handle,
.handle = colorbuffer_handle[colorbuffer_ix],
.read_domains = 4, // RADEON_GEM_DOMAIN_VRAM
.write_domain = 4, // RADEON_GEM_DOMAIN_VRAM
.flags = 8,
@ -614,14 +665,6 @@ int main()
}
};
uint32_t flags[2] = {
5, // RADEON_CS_KEEP_TILING_FLAGS | RADEON_CS_END_OF_FRAME
0, // RADEON_CS_RING_GFX
};
int ib_dwords = indirect_buffer();
//int ib_dwords = (sizeof (ib2)) / (sizeof (ib2[0]));
struct drm_radeon_cs_chunk chunks[3] = {
{
.chunk_id = RADEON_CHUNK_ID_IB,
@ -659,11 +702,36 @@ int main()
perror("drmCommandWriteRead(DRM_RADEON_CS)");
}
struct drm_radeon_gem_wait_idle args = {
.handle = flush_handle
};
while (drmCommandWrite(fd, DRM_RADEON_GEM_WAIT_IDLE, &args, (sizeof (struct drm_radeon_gem_wait_idle))) == -EBUSY);
#define D1CRTC_DOUBLE_BUFFER_CONTROL 0x60ec
#define D1GRPH_PRIMARY_SURFACE_ADDRESS 0x6110
#define D1GRPH_UPDATE 0x6144
#define D1GRPH_UPDATE__D1GRPH_SURFACE_UPDATE_PENDING (1 << 2)
uint32_t d1crtc_double_buffer_control = rreg(rmmio, D1CRTC_DOUBLE_BUFFER_CONTROL);
printf("D1CRTC_DOUBLE_BUFFER_CONTROL: %08x\n", d1crtc_double_buffer_control);
assert(d1crtc_double_buffer_control == (1 << 8));
// addresses were retrieved from /sys/kernel/debug/radeon_vram_mm
//
// This assumes GEM buffer allocation always starts from the lowest
// unallocated address.
const uint32_t colorbuffer_addresses[2] = {
0x813000,
0xf66000,
};
wreg(rmmio, D1GRPH_PRIMARY_SURFACE_ADDRESS, colorbuffer_addresses[colorbuffer_ix]);
while ((rreg(rmmio, D1GRPH_UPDATE) & D1GRPH_UPDATE__D1GRPH_SURFACE_UPDATE_PENDING) != 0);
// next state
time += 0.01f;
colorbuffer_ix = (colorbuffer_ix + 1) & 1;
// next indirect buffer
ib_dwords = indirect_buffer(time);
}
/*
int out_fd = open("colorbuffer.data", O_RDWR|O_CREAT);
assert(out_fd >= 0);
ssize_t write_length = write(out_fd, colorbuffer_ptr, colorbuffer_size);
@ -682,8 +750,7 @@ int main()
}
}
close(mm_fd);
munmap(colorbuffer_ptr, colorbuffer_size);
*/
close(fd);
}

View File

@ -1,4 +1,4 @@
# d = length(uv)
-- d = length(uv)
src0.rgb = temp[0] :
temp[0].r = DP3 src0.rg0 src0.rg0 ;
src0.rgb = temp[0] :
@ -6,16 +6,17 @@ src0.rgb = temp[0] :
src0.a = temp[0] :
temp[0].a = RCP src0.a ;
# d = d * 1.625 + 0
-- d = d * 1.625 + time
src0.a = temp[0],
src1.a = float(61) : # 1.625
temp[0].a = MAD src0.a src1.a src0.0 ;
src1.a = float(61), -- 1.625
src2.rgb = const[0] :
temp[0].a = MAD src0.a src1.a src2.r ;
# d = frc(d)
-- d = frc(d)
src0.a = temp[0] :
temp[0].a = FRC src0.a ;
# d = cos(d * 2π)
-- d = cos(d * 2π)
OUT TEX_SEM_WAIT
src0.a = temp[0] :
COS src0.a ,

View File

@ -972,6 +972,10 @@ int main()
colorbuffer_handle[1] = create_colorbuffer(fd, colorbuffer_size);
zbuffer_handle = create_colorbuffer(fd, colorbuffer_size);
fprintf(stderr, "colorbuffer handle[0] %d\n", colorbuffer_handle[0]);
fprintf(stderr, "colorbuffer handle[1] %d\n", colorbuffer_handle[1]);
fprintf(stderr, "zbuffer handle %d\n", zbuffer_handle);
// texture
{
const int texture_size = 1024 * 1024 * 4;
@ -1037,16 +1041,12 @@ int main()
flush_handle = args.handle;
}
fprintf(stderr, "colorbuffer handle[0] %d\n", colorbuffer_handle[0]);
fprintf(stderr, "colorbuffer handle[1] %d\n", colorbuffer_handle[1]);
uint32_t flags[2] = {
5, // RADEON_CS_KEEP_TILING_FLAGS | RADEON_CS_END_OF_FRAME
0, // RADEON_CS_RING_GFX
};
int ib_dwords = indirect_buffer(0);
//int ib_dwords = (sizeof (ib2)) / (sizeof (ib2[0]));
int colorbuffer_ix = 0;
float theta = 0;