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 "3d_registers_bits.h"
#include "command_processor.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 { union u32_f32 {
uint32_t u32; uint32_t u32;
float f32; float f32;
@ -23,7 +36,7 @@ union u32_f32 {
static union u32_f32 ib[16384]; static union u32_f32 ib[16384];
int indirect_buffer() int indirect_buffer(float time)
{ {
int ix = 0; int ix = 0;
@ -437,7 +450,7 @@ int indirect_buffer()
// fragment constants // fragment constants
const float fragment_consts[] = { const float fragment_consts[] = {
-0.1f, 0, 0, 0, time, 0, 0, 0,
}; };
int fragment_consts_length = (sizeof (fragment_consts)) / (sizeof (fragment_consts[0])); int fragment_consts_length = (sizeof (fragment_consts)) / (sizeof (fragment_consts[0]));
@ -452,7 +465,7 @@ int indirect_buffer()
// fragment code // fragment code
const uint32_t fragment_shader[] = { 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])); const int fragment_shader_length = (sizeof (fragment_shader)) / (sizeof (fragment_shader[0]));
assert(fragment_shader_length % 6 == 0); assert(fragment_shader_length % 6 == 0);
@ -526,18 +539,10 @@ int indirect_buffer()
return ix; return ix;
} }
int main() int create_colorbuffer(int fd, int colorbuffer_size)
{ {
int ret; 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 = { struct drm_radeon_gem_create args = {
.size = colorbuffer_size, .size = colorbuffer_size,
.alignment = 4096, .alignment = 4096,
@ -552,12 +557,8 @@ int main()
} }
assert(args.handle != 0); assert(args.handle != 0);
colorbuffer_handle = args.handle;
}
{
struct drm_radeon_gem_mmap mmap_args = { struct drm_radeon_gem_mmap mmap_args = {
.handle = colorbuffer_handle, .handle = args.handle,
.offset = 0, .offset = 0,
.size = colorbuffer_size, .size = colorbuffer_size,
}; };
@ -566,16 +567,57 @@ int main()
perror("drmCommandWriteRead(DRM_RADEON_GEM_MMAP)"); perror("drmCommandWriteRead(DRM_RADEON_GEM_MMAP)");
} }
colorbuffer_ptr = mmap(0, mmap_args.size, PROT_READ|PROT_WRITE, MAP_SHARED, void * ptr = mmap(0,
fd, mmap_args.addr_ptr); 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++) { for (int i = 0; i < colorbuffer_size / 4; i++) {
((uint32_t*)colorbuffer_ptr)[i] = 0; ((uint32_t*)ptr)[i] = 0x00000000;
} }
asm volatile ("" ::: "memory"); 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 // flush
{ {
@ -596,12 +638,21 @@ int main()
flush_handle = args.handle; 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[] = { struct drm_radeon_cs_reloc relocs[] = {
{ {
.handle = colorbuffer_handle, .handle = colorbuffer_handle[colorbuffer_ix],
.read_domains = 4, // RADEON_GEM_DOMAIN_VRAM .read_domains = 4, // RADEON_GEM_DOMAIN_VRAM
.write_domain = 4, // RADEON_GEM_DOMAIN_VRAM .write_domain = 4, // RADEON_GEM_DOMAIN_VRAM
.flags = 8, .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] = { struct drm_radeon_cs_chunk chunks[3] = {
{ {
.chunk_id = RADEON_CHUNK_ID_IB, .chunk_id = RADEON_CHUNK_ID_IB,
@ -659,11 +702,36 @@ int main()
perror("drmCommandWriteRead(DRM_RADEON_CS)"); perror("drmCommandWriteRead(DRM_RADEON_CS)");
} }
struct drm_radeon_gem_wait_idle args = { #define D1CRTC_DOUBLE_BUFFER_CONTROL 0x60ec
.handle = flush_handle #define D1GRPH_PRIMARY_SURFACE_ADDRESS 0x6110
}; #define D1GRPH_UPDATE 0x6144
while (drmCommandWrite(fd, DRM_RADEON_GEM_WAIT_IDLE, &args, (sizeof (struct drm_radeon_gem_wait_idle))) == -EBUSY); #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); int out_fd = open("colorbuffer.data", O_RDWR|O_CREAT);
assert(out_fd >= 0); assert(out_fd >= 0);
ssize_t write_length = write(out_fd, colorbuffer_ptr, colorbuffer_size); ssize_t write_length = write(out_fd, colorbuffer_ptr, colorbuffer_size);
@ -682,8 +750,7 @@ int main()
} }
} }
close(mm_fd); close(mm_fd);
*/
munmap(colorbuffer_ptr, colorbuffer_size);
close(fd); close(fd);
} }

View File

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

View File

@ -972,6 +972,10 @@ int main()
colorbuffer_handle[1] = create_colorbuffer(fd, colorbuffer_size); colorbuffer_handle[1] = create_colorbuffer(fd, colorbuffer_size);
zbuffer_handle = 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 // texture
{ {
const int texture_size = 1024 * 1024 * 4; const int texture_size = 1024 * 1024 * 4;
@ -1037,16 +1041,12 @@ int main()
flush_handle = args.handle; 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] = { uint32_t flags[2] = {
5, // RADEON_CS_KEEP_TILING_FLAGS | RADEON_CS_END_OF_FRAME 5, // RADEON_CS_KEEP_TILING_FLAGS | RADEON_CS_END_OF_FRAME
0, // RADEON_CS_RING_GFX 0, // RADEON_CS_RING_GFX
}; };
int ib_dwords = indirect_buffer(0); int ib_dwords = indirect_buffer(0);
//int ib_dwords = (sizeof (ib2)) / (sizeof (ib2[0]));
int colorbuffer_ix = 0; int colorbuffer_ix = 0;
float theta = 0; float theta = 0;