pumpkin_man: use blender.py exporter
@ -1,7 +1,7 @@
|
||||
OPT = -O0
|
||||
|
||||
CFLAGS += -g
|
||||
CFLAGS += -Wall -Werror -Wfatal-errors
|
||||
CFLAGS += -Wall -Werror -Wfatal-errors -Wno-error=unused-variable
|
||||
CFLAGS += $(shell pkg-config --cflags libdrm)
|
||||
|
||||
LDFLAGS += $(shell pkg-config --libs libdrm) -lm
|
||||
|
||||
@ -19,17 +19,22 @@
|
||||
#include "3d_registers_bits.h"
|
||||
#include "command_processor.h"
|
||||
|
||||
#define pumpkin_Material_002 0
|
||||
#define pumpkin_pumpkin 0
|
||||
#define pumpkin_belt 0
|
||||
|
||||
#include "../model/model.h"
|
||||
#include "../model/vec.h"
|
||||
#include "../model/blender_model.h"
|
||||
#include "../model/pumpkin/pumpkin.h"
|
||||
|
||||
#define PI (3.14159274101257324219f)
|
||||
#define PI_2 (PI * 2.0f)
|
||||
#define I_PI_2 (1.0f / (PI_2))
|
||||
|
||||
struct reloc_indices {
|
||||
int colorbuffer;
|
||||
int zbuffer;
|
||||
int vertexbuffer;
|
||||
int texturebuffer;
|
||||
int flush;
|
||||
};
|
||||
|
||||
static inline uint32_t rreg(void * rmmio, uint32_t offset)
|
||||
{
|
||||
uint32_t value = *((volatile uint32_t *)(((uintptr_t)rmmio) + offset));
|
||||
@ -43,7 +48,7 @@ static inline void wreg(void * rmmio, uint32_t offset, uint32_t value)
|
||||
asm volatile ("" ::: "memory");
|
||||
}
|
||||
|
||||
static void * read_file(const char * filename)
|
||||
static void * read_file(const char * filename, int * out_size)
|
||||
{
|
||||
int fd = open(filename, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
@ -74,6 +79,9 @@ static void * read_file(const char * filename)
|
||||
|
||||
close(fd);
|
||||
|
||||
if (out_size != NULL)
|
||||
*out_size = size;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
@ -98,7 +106,7 @@ union u32_f32 {
|
||||
|
||||
static union u32_f32 ib[16384];
|
||||
|
||||
int _3d_clear(int ix)
|
||||
int _3d_clear(int ix, const struct reloc_indices * reloc_indices)
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// ZB
|
||||
@ -118,7 +126,7 @@ int _3d_clear(int ix)
|
||||
|
||||
T0V(ZB_DEPTHOFFSET, 0);
|
||||
T3(_NOP, 0);
|
||||
ib[ix++].u32 = 1 * 4; // index into relocs array
|
||||
ib[ix++].u32 = reloc_indices->zbuffer * 4; // index into relocs array
|
||||
|
||||
T0V(ZB_DEPTHPITCH
|
||||
, ZB_DEPTHPITCH__DEPTHPITCH(1600 >> 2)
|
||||
@ -126,7 +134,7 @@ int _3d_clear(int ix)
|
||||
| ZB_DEPTHPITCH__DEPTHMICROTILE(1)
|
||||
);
|
||||
T3(_NOP, 0);
|
||||
ib[ix++].u32 = 1 * 4; // index into relocs array
|
||||
ib[ix++].u32 = reloc_indices->zbuffer * 4; // index into relocs array
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// RS
|
||||
@ -209,35 +217,6 @@ int _3d_clear(int ix)
|
||||
T0V(VAP_OUT_VTX_FMT_1
|
||||
, 0x0);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// AOS
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
T3(_3D_LOAD_VBPNTR, (4 - 1));
|
||||
ib[ix++].u32 // VAP_VTX_NUM_ARRAYS
|
||||
= VAP_VTX_NUM_ARRAYS__VTX_NUM_ARRAYS(2)
|
||||
| VAP_VTX_NUM_ARRAYS__VC_FORCE_PREFETCH(1)
|
||||
;
|
||||
ib[ix++].u32 // VAP_VTX_AOS_ATTR01
|
||||
= VAP_VTX_AOS_ATTR__VTX_AOS_COUNT0(3)
|
||||
| VAP_VTX_AOS_ATTR__VTX_AOS_STRIDE0(5)
|
||||
| VAP_VTX_AOS_ATTR__VTX_AOS_COUNT1(2)
|
||||
| VAP_VTX_AOS_ATTR__VTX_AOS_STRIDE1(5)
|
||||
;
|
||||
ib[ix++].u32 // VAP_VTX_AOS_ADDR0
|
||||
= (4 * 0);
|
||||
ib[ix++].u32 // VAP_VTX_AOS_ADDR1
|
||||
= (4 * 3);
|
||||
|
||||
// VAP_VTX_AOS_ADDR is an absolute address in VRAM. However, DRM_RADEON_CS
|
||||
// modifies this to be an offset relative to the GEM buffer handles given via
|
||||
// NOP:
|
||||
|
||||
T3(_NOP, 0);
|
||||
ib[ix++].u32 = 3 * 4; // index into relocs array for VAP_VTX_AOS_ADDR0
|
||||
T3(_NOP, 0);
|
||||
ib[ix++].u32 = 3 * 4; // index into relocs array for VAP_VTX_AOS_ADDR1
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// GA_US
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@ -278,7 +257,9 @@ int _3d_clear(int ix)
|
||||
return ix;
|
||||
}
|
||||
|
||||
int _3d_object(int ix, float theta, int vertex_count)
|
||||
int _3d_object(int ix, const struct reloc_indices * reloc_indices,
|
||||
float theta,
|
||||
int vertex_count)
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// ZB
|
||||
@ -298,7 +279,7 @@ int _3d_object(int ix, float theta, int vertex_count)
|
||||
|
||||
T0V(ZB_DEPTHOFFSET, 0);
|
||||
T3(_NOP, 0);
|
||||
ib[ix++].u32 = 1 * 4; // index into relocs array
|
||||
ib[ix++].u32 = reloc_indices->zbuffer * 4; // index into relocs array
|
||||
|
||||
T0V(ZB_DEPTHPITCH
|
||||
, ZB_DEPTHPITCH__DEPTHPITCH(1600 >> 2)
|
||||
@ -306,7 +287,7 @@ int _3d_object(int ix, float theta, int vertex_count)
|
||||
| ZB_DEPTHPITCH__DEPTHMICROTILE(1)
|
||||
);
|
||||
T3(_NOP, 0);
|
||||
ib[ix++].u32 = 1 * 4; // index into relocs array
|
||||
ib[ix++].u32 = reloc_indices->zbuffer * 4; // index into relocs array
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// RS
|
||||
@ -372,7 +353,7 @@ int _3d_object(int ix, float theta, int vertex_count)
|
||||
);
|
||||
|
||||
T3(_NOP, 0);
|
||||
ib[ix++].u32 = 2 * 4; // index into relocs array
|
||||
ib[ix++].u32 = reloc_indices->texturebuffer * 4; // index into relocs array
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// VAP_PVS
|
||||
@ -491,6 +472,35 @@ int _3d_object(int ix, float theta, int vertex_count)
|
||||
| US_CODE_ADDR__END_ADDR(fragment_shader_instructions - 1)
|
||||
);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// AOS
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
T3(_3D_LOAD_VBPNTR, (4 - 1));
|
||||
ib[ix++].u32 // VAP_VTX_NUM_ARRAYS
|
||||
= VAP_VTX_NUM_ARRAYS__VTX_NUM_ARRAYS(2)
|
||||
| VAP_VTX_NUM_ARRAYS__VC_FORCE_PREFETCH(1)
|
||||
;
|
||||
ib[ix++].u32 // VAP_VTX_AOS_ATTR01
|
||||
= VAP_VTX_AOS_ATTR__VTX_AOS_COUNT0(3)
|
||||
| VAP_VTX_AOS_ATTR__VTX_AOS_STRIDE0(5)
|
||||
| VAP_VTX_AOS_ATTR__VTX_AOS_COUNT1(2)
|
||||
| VAP_VTX_AOS_ATTR__VTX_AOS_STRIDE1(5)
|
||||
;
|
||||
ib[ix++].u32 // VAP_VTX_AOS_ADDR0
|
||||
= (4 * 0);
|
||||
ib[ix++].u32 // VAP_VTX_AOS_ADDR1
|
||||
= (4 * 3);
|
||||
|
||||
// VAP_VTX_AOS_ADDR is an absolute address in VRAM. However, DRM_RADEON_CS
|
||||
// modifies this to be an offset relative to the GEM buffer handles given via
|
||||
// NOP:
|
||||
|
||||
T3(_NOP, 0);
|
||||
ib[ix++].u32 = reloc_indices->vertexbuffer * 4; // index into relocs array for VAP_VTX_AOS_ADDR0
|
||||
T3(_NOP, 0);
|
||||
ib[ix++].u32 = reloc_indices->vertexbuffer * 4; // index into relocs array for VAP_VTX_AOS_ADDR1
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// 3D_DRAW
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@ -509,7 +519,7 @@ int _3d_object(int ix, float theta, int vertex_count)
|
||||
return ix;
|
||||
}
|
||||
|
||||
int indirect_buffer(float theta, int vertex_count)
|
||||
int indirect_buffer(float theta, int vertex_count, const struct reloc_indices * reloc_indices)
|
||||
{
|
||||
int ix = 0;
|
||||
|
||||
@ -753,7 +763,7 @@ int indirect_buffer(float theta, int vertex_count)
|
||||
, 0x00000000 // value replaced by kernel from relocs
|
||||
);
|
||||
T3(_NOP, 0);
|
||||
ib[ix++].u32 = 0 * 4; // index into relocs array
|
||||
ib[ix++].u32 = reloc_indices->colorbuffer * 4; // index into relocs array
|
||||
|
||||
T0V(RB3D_COLORPITCH0
|
||||
, RB3D_COLORPITCH__COLORPITCH(1600 >> 1)
|
||||
@ -762,7 +772,7 @@ int indirect_buffer(float theta, int vertex_count)
|
||||
// The COLORPITCH NOP is ignored/not applied due to
|
||||
// RADEON_CS_KEEP_TILING_FLAGS, but is still required.
|
||||
T3(_NOP, 0);
|
||||
ib[ix++].u32 = 0 * 4; // index into relocs array
|
||||
ib[ix++].u32 = reloc_indices->colorbuffer * 4; // index into relocs array
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// SC
|
||||
@ -825,8 +835,8 @@ int indirect_buffer(float theta, int vertex_count)
|
||||
// DRAW
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ix = _3d_clear(ix);
|
||||
ix = _3d_object(ix, theta, vertex_count);
|
||||
ix = _3d_clear(ix, reloc_indices);
|
||||
ix = _3d_object(ix, reloc_indices, theta, vertex_count);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// padding
|
||||
@ -896,31 +906,93 @@ int fill_vertexbuffer(void * ptr, int size)
|
||||
|
||||
int ix = 0;
|
||||
|
||||
const struct model * model = &pumpkin_model;
|
||||
const int object_count = (sizeof (objects)) / (sizeof (objects[0]));
|
||||
for (int object_ix = 0; object_ix < object_count; object_ix++) {
|
||||
const struct mesh * mesh = objects[object_ix].mesh;
|
||||
|
||||
for (int i = 0; i < model->object_count; i++) {
|
||||
const struct object * object = model->object[i];
|
||||
for (int j = 0; j < object->triangle_count; j++) {
|
||||
const union triangle * triangle = &object->triangle[j];
|
||||
for (int k = 0; k < 3; k++) {
|
||||
const struct vec3 * p = &model->position[triangle->v[k].position];
|
||||
const struct vec2 * t = &model->texture[triangle->v[k].texture];
|
||||
assert(mesh->uv_layers_length == 1);
|
||||
const vec2 * uvmap = mesh->uv_layers[0];
|
||||
const vec3 * position = mesh->position;
|
||||
for (int polygon_ix = 0; polygon_ix < mesh->polygons_length; polygon_ix++) {
|
||||
|
||||
assert((ix + 5) < (size / 4));
|
||||
int uv_ix = polygon_ix * 3;
|
||||
const struct polygon * polygon = &mesh->polygons[polygon_ix];
|
||||
const vec3 * ap = &position[polygon->a];
|
||||
const vec3 * bp = &position[polygon->b];
|
||||
const vec3 * cp = &position[polygon->c];
|
||||
const vec2 * at = &uvmap[uv_ix + 0];
|
||||
const vec2 * bt = &uvmap[uv_ix + 1];
|
||||
const vec2 * ct = &uvmap[uv_ix + 2];
|
||||
|
||||
fptr[ix++] = p->x;
|
||||
fptr[ix++] = p->y;
|
||||
fptr[ix++] = p->z;
|
||||
fptr[ix++] = t->x;
|
||||
fptr[ix++] = t->y;
|
||||
}
|
||||
assert((ix + (5 * 3)) < (size / 4));
|
||||
|
||||
fptr[ix++] = ap->x;
|
||||
fptr[ix++] = ap->y;
|
||||
fptr[ix++] = ap->z;
|
||||
fptr[ix++] = at->x;
|
||||
fptr[ix++] = 1.0f - at->y;
|
||||
|
||||
fptr[ix++] = bp->x;
|
||||
fptr[ix++] = bp->y;
|
||||
fptr[ix++] = bp->z;
|
||||
fptr[ix++] = bt->x;
|
||||
fptr[ix++] = 1.0f - bt->y;
|
||||
|
||||
fptr[ix++] = cp->x;
|
||||
fptr[ix++] = cp->y;
|
||||
fptr[ix++] = cp->z;
|
||||
fptr[ix++] = ct->x;
|
||||
fptr[ix++] = 1.0f - ct->y;
|
||||
}
|
||||
}
|
||||
|
||||
asm volatile("" ::: "memory");
|
||||
|
||||
return ix;
|
||||
}
|
||||
|
||||
static int * load_textures(int fd, int * length_out)
|
||||
{
|
||||
int * texture_handles = NULL;
|
||||
|
||||
const int materials_length = (sizeof (materials)) / (sizeof (materials[0]));
|
||||
|
||||
texture_handles = (int *)calloc((sizeof (int)), materials_length);
|
||||
|
||||
char buf[512];
|
||||
for (int i = 0; i < materials_length; i++) {
|
||||
assert(strlen(materials[i].name) < 300);
|
||||
snprintf(buf, (sizeof (buf)), "../model/pumpkin/textures/%s.data", materials[i].name);
|
||||
|
||||
int size = 0;
|
||||
void * file_ptr = read_file(buf, &size);
|
||||
assert(file_ptr != NULL);
|
||||
assert(size > 0);
|
||||
|
||||
printf("load %s %d\n", buf, size);
|
||||
|
||||
assert(materials[i].texture_id < materials_length);
|
||||
assert(texture_handles[materials[i].texture_id] == 0);
|
||||
|
||||
void * buffer_ptr;
|
||||
int handle = create_colorbuffer(fd, size, &buffer_ptr);
|
||||
for (int i = 0; i < size / 4; i++) {
|
||||
((uint32_t *)buffer_ptr)[i] = ((uint32_t *)file_ptr)[i];
|
||||
}
|
||||
asm volatile ("" ::: "memory");
|
||||
|
||||
free(file_ptr);
|
||||
munmap(buffer_ptr, size);
|
||||
|
||||
texture_handles[materials[i].texture_id] = handle;
|
||||
}
|
||||
|
||||
assert(length_out != NULL);
|
||||
*length_out = materials_length;
|
||||
|
||||
return texture_handles;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@ -948,7 +1020,6 @@ int main()
|
||||
|
||||
int colorbuffer_handle[2];
|
||||
int zbuffer_handle;
|
||||
int texturebuffer_handle;
|
||||
int vertexbuffer_handle;
|
||||
int flush_handle;
|
||||
|
||||
@ -968,54 +1039,10 @@ int main()
|
||||
int vertexbuffer_length = fill_vertexbuffer(vertexbuffer_ptr, vertexbuffer_size);
|
||||
munmap(vertexbuffer_ptr, vertexbuffer_size);
|
||||
fprintf(stderr, "vertexbuffer length %d\n", vertexbuffer_length);
|
||||
|
||||
int vertex_count = vertexbuffer_length / 5;
|
||||
|
||||
// texture
|
||||
{
|
||||
const int texture_size = 1024 * 1024 * 4;
|
||||
|
||||
struct drm_radeon_gem_create args = {
|
||||
.size = texture_size,
|
||||
.alignment = 4096,
|
||||
.handle = 0,
|
||||
.initial_domain = 4, // RADEON_GEM_DOMAIN_VRAM
|
||||
.flags = 4
|
||||
};
|
||||
|
||||
ret = drmCommandWriteRead(fd, DRM_RADEON_GEM_CREATE, &args, (sizeof (struct drm_radeon_gem_create)));
|
||||
if (ret != 0) {
|
||||
perror("drmCommandWriteRead(DRM_RADEON_GEM_CREATE)");
|
||||
}
|
||||
assert(args.handle != 0);
|
||||
|
||||
texturebuffer_handle = args.handle;
|
||||
|
||||
struct drm_radeon_gem_mmap mmap_args = {
|
||||
.handle = texturebuffer_handle,
|
||||
.offset = 0,
|
||||
.size = texture_size,
|
||||
};
|
||||
ret = drmCommandWriteRead(fd, DRM_RADEON_GEM_MMAP, &mmap_args, (sizeof (struct drm_radeon_gem_mmap)));
|
||||
if (ret != 0) {
|
||||
perror("drmCommandWriteRead(DRM_RADEON_GEM_MMAP)");
|
||||
}
|
||||
|
||||
void * texturebuffer_ptr = mmap(0, mmap_args.size, PROT_READ|PROT_WRITE, MAP_SHARED,
|
||||
fd, mmap_args.addr_ptr);
|
||||
assert(texturebuffer_ptr != MAP_FAILED);
|
||||
|
||||
// copy texture
|
||||
void * texture_buf = read_file("../texture/butterfly_1024x1024_argb8888.data");
|
||||
assert(texture_buf != NULL);
|
||||
|
||||
for (int i = 0; i < texture_size / 4; i++) {
|
||||
((uint32_t*)texturebuffer_ptr)[i] = ((uint32_t*)texture_buf)[i];
|
||||
}
|
||||
asm volatile ("" ::: "memory");
|
||||
free(texture_buf);
|
||||
munmap(texturebuffer_ptr, texture_size);
|
||||
}
|
||||
int texture_handles_length = 0;
|
||||
int * texture_handles = load_textures(fd, &texture_handles_length);
|
||||
|
||||
// flush
|
||||
{
|
||||
@ -1041,45 +1068,59 @@ int main()
|
||||
0, // RADEON_CS_RING_GFX
|
||||
};
|
||||
|
||||
int ib_dwords = indirect_buffer(0, vertex_count);
|
||||
|
||||
int colorbuffer_ix = 0;
|
||||
float theta = 0;
|
||||
|
||||
while (true) {
|
||||
struct drm_radeon_cs_reloc relocs[] = {
|
||||
{
|
||||
.handle = colorbuffer_handle[colorbuffer_ix],
|
||||
.read_domains = 4, // RADEON_GEM_DOMAIN_VRAM
|
||||
.write_domain = 4, // RADEON_GEM_DOMAIN_VRAM
|
||||
.flags = 8,
|
||||
},
|
||||
{
|
||||
int relocs_length = 4 + texture_handles_length;
|
||||
struct drm_radeon_cs_reloc * relocs = calloc((sizeof (struct drm_radeon_cs_reloc)), relocs_length);
|
||||
int relocs_size = (sizeof (struct drm_radeon_cs_reloc)) * relocs_length;
|
||||
|
||||
const struct reloc_indices reloc_indices = {
|
||||
.colorbuffer = 0,
|
||||
.zbuffer = 1,
|
||||
.vertexbuffer = 2,
|
||||
.texturebuffer = 3,
|
||||
.flush = relocs_length - 1,
|
||||
};
|
||||
|
||||
relocs[reloc_indices.zbuffer] = (struct drm_radeon_cs_reloc){
|
||||
.handle = zbuffer_handle,
|
||||
.read_domains = 4, // RADEON_GEM_DOMAIN_VRAM
|
||||
.write_domain = 4, // RADEON_GEM_DOMAIN_VRAM
|
||||
.flags = 8,
|
||||
},
|
||||
{
|
||||
.handle = texturebuffer_handle,
|
||||
.read_domains = 4, // RADEON_GEM_DOMAIN_VRAM
|
||||
.write_domain = 4, // RADEON_GEM_DOMAIN_VRAM
|
||||
.flags = 8,
|
||||
},
|
||||
{
|
||||
};
|
||||
relocs[reloc_indices.vertexbuffer] = (struct drm_radeon_cs_reloc){
|
||||
.handle = vertexbuffer_handle,
|
||||
.read_domains = 4, // RADEON_GEM_DOMAIN_VRAM
|
||||
.write_domain = 4, // RADEON_GEM_DOMAIN_VRAM
|
||||
.flags = 8,
|
||||
},
|
||||
{
|
||||
};
|
||||
relocs[reloc_indices.flush] = (struct drm_radeon_cs_reloc){
|
||||
.handle = flush_handle,
|
||||
.read_domains = 2, // RADEON_GEM_DOMAIN_GTT
|
||||
.write_domain = 2, // RADEON_GEM_DOMAIN_GTT
|
||||
.flags = 0,
|
||||
}
|
||||
};
|
||||
|
||||
for (int i = 0; i < texture_handles_length; i++) {
|
||||
relocs[reloc_indices.texturebuffer + i] = (struct drm_radeon_cs_reloc){
|
||||
.handle = texture_handles[i],
|
||||
.read_domains = 4, // RADEON_GEM_DOMAIN_VRAM
|
||||
.write_domain = 4, // RADEON_GEM_DOMAIN_VRAM
|
||||
.flags = 8,
|
||||
};
|
||||
}
|
||||
|
||||
while (true) {
|
||||
relocs[reloc_indices.colorbuffer] = (struct drm_radeon_cs_reloc){
|
||||
.handle = colorbuffer_handle[colorbuffer_ix],
|
||||
.read_domains = 4, // RADEON_GEM_DOMAIN_VRAM
|
||||
.write_domain = 4, // RADEON_GEM_DOMAIN_VRAM
|
||||
.flags = 8,
|
||||
};
|
||||
|
||||
int ib_dwords = indirect_buffer(theta, vertex_count, &reloc_indices);
|
||||
|
||||
struct drm_radeon_cs_chunk chunks[3] = {
|
||||
{
|
||||
.chunk_id = RADEON_CHUNK_ID_IB,
|
||||
@ -1088,7 +1129,7 @@ int main()
|
||||
},
|
||||
{
|
||||
.chunk_id = RADEON_CHUNK_ID_RELOCS,
|
||||
.length_dw = (sizeof (relocs)) / (sizeof (uint32_t)),
|
||||
.length_dw = relocs_size / (sizeof (uint32_t)),
|
||||
.chunk_data = (uint64_t)(uintptr_t)relocs,
|
||||
},
|
||||
{
|
||||
@ -1147,9 +1188,6 @@ int main()
|
||||
// next state
|
||||
theta += 0.01f;
|
||||
colorbuffer_ix = (colorbuffer_ix + 1) & 1;
|
||||
|
||||
// next indirect buffer
|
||||
ib_dwords = indirect_buffer(theta, vertex_count);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -57,12 +57,14 @@ union u32_f32 {
|
||||
float f32;
|
||||
};
|
||||
|
||||
static union u32_f32 ib[16384];
|
||||
static union u32_f32 ib[16384 * 20];
|
||||
|
||||
int indirect_buffer(int ix,
|
||||
int width,
|
||||
int height,
|
||||
int colorbuffer_reloc_ix,
|
||||
int texture_width,
|
||||
int texture_height,
|
||||
int texturebuffer_reloc_ix,
|
||||
int shader_ix,
|
||||
bool intermediate)
|
||||
@ -479,9 +481,9 @@ int indirect_buffer(int ix,
|
||||
T0V(TX_ENABLE
|
||||
, TX_ENABLE__TEX_0_ENABLE__ENABLE);
|
||||
T0V(TX_FILTER0_0
|
||||
//, TX_FILTER0__CLAMP_S(2) // clamp to (0.0, 1.0)
|
||||
//| TX_FILTER0__CLAMP_T(2) // clamp to (0.0, 1.0)
|
||||
, TX_FILTER0__MAG_FILTER__POINT
|
||||
, TX_FILTER0__CLAMP_S(2) // clamp to (0.0, 1.0)
|
||||
| TX_FILTER0__CLAMP_T(2) // clamp to (0.0, 1.0)
|
||||
| TX_FILTER0__MAG_FILTER__POINT
|
||||
| TX_FILTER0__MIN_FILTER__POINT
|
||||
);
|
||||
T0V(TX_FILTER1_0
|
||||
@ -489,8 +491,8 @@ int indirect_buffer(int ix,
|
||||
);
|
||||
T0V(TX_BORDER_COLOR_0, 0);
|
||||
T0V(TX_FORMAT0_0
|
||||
, TX_FORMAT0__TXWIDTH(128 - 1)
|
||||
| TX_FORMAT0__TXHEIGHT(128 - 1)
|
||||
, TX_FORMAT0__TXWIDTH(texture_width - 1)
|
||||
| TX_FORMAT0__TXHEIGHT(texture_height - 1)
|
||||
);
|
||||
|
||||
T0V(TX_FORMAT1_0
|
||||
@ -563,8 +565,8 @@ int indirect_buffer(int ix,
|
||||
}
|
||||
|
||||
const float fragment_consts[] = {
|
||||
-1.0f / 128.f, 1.0f / 128.f, -2.0f / 128.f, 2.0f / 128.f,
|
||||
-3.0f / 128.f, 3.0f / 128.f, 0.0f, 0.0f,
|
||||
-1.0f / 1024.f, 1.0f / 1024.f, -2.0f / 1024.f, 2.0f / 1024.f,
|
||||
-3.0f / 1024.f, 3.0f / 1024.f, 0.0f, 0.0f,
|
||||
0.24609375 + 0.021484375, 0.205078125, 0.1171875, 0.0439453125,
|
||||
};
|
||||
int fragment_consts_length = (sizeof (fragment_consts)) / (sizeof (fragment_consts[0]));
|
||||
@ -689,7 +691,7 @@ int main()
|
||||
int ret;
|
||||
int fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
|
||||
|
||||
const int texture_size = 128 * 128 * 4;
|
||||
const int texture_size = 1024 * 1024 * 4;
|
||||
const int colorbuffer_size = 1600 * 1200 * 4;
|
||||
int intermediate_handle[2];
|
||||
int colorbuffer_handle;
|
||||
@ -705,7 +707,7 @@ int main()
|
||||
intermediate_handle[1] = create_colorbuffer(fd, texture_size, NULL);
|
||||
|
||||
{
|
||||
void * texture_buf = read_file("../texture/butterfly_128x128_argb8888.data");
|
||||
void * texture_buf = read_file("../texture/butterfly_1024x1024_argb8888.data");
|
||||
assert(texture_buf != NULL);
|
||||
for (int i = 0; i < texture_size / 4; i++) {
|
||||
((uint32_t*)texturebuffer_ptr)[i] = ((uint32_t*)texture_buf)[i];
|
||||
@ -774,26 +776,30 @@ int main()
|
||||
0, // RADEON_CS_RING_GFX
|
||||
};
|
||||
|
||||
int image_dim = 1024;
|
||||
|
||||
int ib_dwords = 0;
|
||||
{
|
||||
int texturebuffer_reloc_ix = 1;
|
||||
int colorbuffer_reloc_ix = 2;
|
||||
int shader_ix = 0;
|
||||
ib_dwords = indirect_buffer(ib_dwords,
|
||||
128, 128,
|
||||
image_dim, image_dim,
|
||||
colorbuffer_reloc_ix,
|
||||
image_dim, image_dim,
|
||||
texturebuffer_reloc_ix,
|
||||
shader_ix,
|
||||
true);
|
||||
}
|
||||
for (int i = 0; i < 10; i++) {
|
||||
for (int i = 0; i < 40; i++) {
|
||||
{
|
||||
int texturebuffer_reloc_ix = 2;
|
||||
int colorbuffer_reloc_ix = 3;
|
||||
int shader_ix = 1;
|
||||
ib_dwords = indirect_buffer(ib_dwords,
|
||||
128, 128,
|
||||
image_dim, image_dim,
|
||||
colorbuffer_reloc_ix,
|
||||
image_dim, image_dim,
|
||||
texturebuffer_reloc_ix,
|
||||
shader_ix,
|
||||
true);
|
||||
@ -803,8 +809,9 @@ int main()
|
||||
int colorbuffer_reloc_ix = 2;
|
||||
int shader_ix = 0;
|
||||
ib_dwords = indirect_buffer(ib_dwords,
|
||||
128, 128,
|
||||
image_dim, image_dim,
|
||||
colorbuffer_reloc_ix,
|
||||
image_dim, image_dim,
|
||||
texturebuffer_reloc_ix,
|
||||
shader_ix,
|
||||
true);
|
||||
@ -817,6 +824,7 @@ int main()
|
||||
ib_dwords = indirect_buffer(ib_dwords,
|
||||
1600, 1200,
|
||||
colorbuffer_reloc_ix,
|
||||
image_dim, image_dim,
|
||||
texturebuffer_reloc_ix,
|
||||
shader_ix,
|
||||
false);
|
||||
|
||||
54
model/blender_model.h
Normal file
@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
struct polygon {
|
||||
int a, b, c;
|
||||
int material_index;
|
||||
};
|
||||
|
||||
struct mesh_material {
|
||||
const int width;
|
||||
const int height;
|
||||
const int texture_id;
|
||||
};
|
||||
|
||||
struct edge {
|
||||
int a; // vertices index
|
||||
int b; // vertices index
|
||||
};
|
||||
|
||||
struct edge_polygon {
|
||||
struct edge edge;
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
} polygon_index; // polygon indices
|
||||
};
|
||||
|
||||
struct mesh {
|
||||
const vec3 * position;
|
||||
const int position_length;
|
||||
const vec3 * normal;
|
||||
const int normal_length;
|
||||
const vec3 * polygon_normal;
|
||||
const int polygon_normal_length;
|
||||
const struct polygon * polygons;
|
||||
const int polygons_length;
|
||||
const vec2 ** uv_layers;
|
||||
const int uv_layers_length;
|
||||
const struct mesh_material * materials;
|
||||
const int materials_length;
|
||||
const struct edge_polygon * edge_polygons;
|
||||
const int edge_polygons_length;
|
||||
};
|
||||
|
||||
struct object {
|
||||
const struct mesh * mesh;
|
||||
vec3 scale;
|
||||
vec4 rotation;
|
||||
vec3 location;
|
||||
};
|
||||
|
||||
struct material {
|
||||
const char * name;
|
||||
const int texture_id;
|
||||
};
|
||||
@ -1,15 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
struct vec3 {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
struct vec2 {
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
|
||||
typedef struct vec3 vertex_position;
|
||||
typedef struct vec2 vertex_texture;
|
||||
typedef struct vec3 vertex_normal;
|
||||
|
||||
79669
model/pumpkin/pumpkin.h
BIN
model/pumpkin/textures/Untitled.data
Normal file
BIN
model/pumpkin/textures/Untitled.png
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
model/pumpkin/textures/armtext.data
Normal file
BIN
model/pumpkin/textures/armtext.png
Normal file
|
After Width: | Height: | Size: 218 KiB |
BIN
model/pumpkin/textures/bellytexture.data
Normal file
BIN
model/pumpkin/textures/bellytexture.png
Normal file
|
After Width: | Height: | Size: 158 KiB |
BIN
model/pumpkin/textures/belttexture.data
Normal file
BIN
model/pumpkin/textures/belttexture.png
Normal file
|
After Width: | Height: | Size: 140 KiB |
BIN
model/pumpkin/textures/chesttext.data
Normal file
BIN
model/pumpkin/textures/chesttext.png
Normal file
|
After Width: | Height: | Size: 248 KiB |
BIN
model/pumpkin/textures/eyetext.data
Normal file
BIN
model/pumpkin/textures/eyetext.png
Normal file
|
After Width: | Height: | Size: 102 KiB |
BIN
model/pumpkin/textures/legtext.data
Normal file
BIN
model/pumpkin/textures/legtext.png
Normal file
|
After Width: | Height: | Size: 219 KiB |
3
model/pumpkin/textures/pumpkin.data
Normal file
BIN
model/pumpkin/textures/pumpkin.png
Normal file
|
After Width: | Height: | Size: 337 KiB |
19
model/vec.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
typedef struct vec4 {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
} vec4;
|
||||
|
||||
typedef struct vec3 {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
} vec3;
|
||||
|
||||
typedef struct vec2 {
|
||||
float x;
|
||||
float y;
|
||||
} vec2;
|
||||
302
tools/blender.py
Normal file
@ -0,0 +1,302 @@
|
||||
import bpy
|
||||
from os import path
|
||||
from collections import defaultdict
|
||||
import bmesh
|
||||
|
||||
triangulate_meshes = True
|
||||
|
||||
def sprint(*text):
|
||||
screen = bpy.data.screens['Scripting']
|
||||
for area in screen.areas:
|
||||
if area.type != "CONSOLE":
|
||||
continue
|
||||
override = {'screen': screen, 'area': area}
|
||||
with bpy.context.temp_override(**override):
|
||||
bpy.ops.console.scrollback_append(text=" ".join(map(str, text)))
|
||||
|
||||
print = sprint
|
||||
|
||||
def render_vec3(v):
|
||||
return f"{{{v.x:.6f}, {v.y:.6f}, {v.z:.6f}}}"
|
||||
|
||||
def render_vec2(v):
|
||||
return f"{{{v.x:.6f}, {v.y:.6f}}}"
|
||||
|
||||
def render_mesh_vertices(f, name, vertices):
|
||||
f.write(f"static const vec3 {name}_position[] = {{\n")
|
||||
for vertex in vertices:
|
||||
f.write(f" {render_vec3(vertex.co)},\n")
|
||||
f.write("};\n\n")
|
||||
|
||||
def render_vertex_normals(f, name, vertices):
|
||||
f.write(f"static const vec3 {name}_normal[] = {{\n")
|
||||
for vertex in vertices:
|
||||
f.write(f" {render_vec3(vertex.normal)},\n")
|
||||
f.write("};\n\n")
|
||||
|
||||
def render_polygon_normals(f, name, polygon_normals):
|
||||
f.write(f"static const vec3 {name}_polygon_normal[] = {{\n")
|
||||
for normal in polygon_normals:
|
||||
f.write(f" {render_vec3(normal.vector)},\n")
|
||||
f.write("};\n\n")
|
||||
|
||||
def sort_by_material(polygons):
|
||||
return sorted(polygons, key=lambda p: p.material_index)
|
||||
|
||||
def render_polygons(f, name, polygons):
|
||||
f.write(f"static const struct polygon {name}_polygons[] = {{\n")
|
||||
|
||||
uv_ix = 0
|
||||
for i, polygon in enumerate(polygons):
|
||||
if triangulate_meshes:
|
||||
assert len(polygon.vertices) == 3
|
||||
|
||||
if len(polygon.vertices) not in {3, 4}:
|
||||
f.write(f" {{-1, -1, -1, -1, -1, -1}}, // {{{s}}}\n")
|
||||
continue
|
||||
|
||||
if triangulate_meshes:
|
||||
indices = [*polygon.vertices, polygon.material_index]
|
||||
elif len(polygon.vertices) == 4:
|
||||
indices = [*polygon.vertices, polygon.material_index, uv_ix]
|
||||
else:
|
||||
indices = [*polygon.vertices, -1, polygon.material_index, uv_ix]
|
||||
|
||||
uv_ix += len(polygon.vertices)
|
||||
s = ", ".join(map(str, indices))
|
||||
f.write(f" {{{s}}},\n")
|
||||
|
||||
f.write("};\n\n")
|
||||
|
||||
def render_polygon_edge_pairs(f, name, polygons):
|
||||
by_edge = defaultdict(list)
|
||||
for i, polygon in enumerate(polygons):
|
||||
for edge in polygon.edge_keys:
|
||||
by_edge[frozenset(edge)].append(i)
|
||||
|
||||
f.write(f"static const struct edge_polygon {name}_edge_polygons[] = {{\n")
|
||||
if all(len(p) == 2 for p in by_edge.values()):
|
||||
for edge, polygons in by_edge.items():
|
||||
edges = sorted(list(edge))
|
||||
assert len(edges) == 2, edges
|
||||
assert len(polygons) == 2, polygons
|
||||
f.write(f" {{{{{edges[0]}, {edges[1]}}}, {{{polygons[0]}, {polygons[1]}}}}},\n")
|
||||
else:
|
||||
f.write("// non-solid polygon\n")
|
||||
f.write("};\n\n")
|
||||
|
||||
def render_uv_map(f, name, name2, uvm):
|
||||
f.write(f"static const vec2 {name}_{name2}_uvmap[] = {{\n")
|
||||
for uv in uvm:
|
||||
s = render_vec2(uv.vector)
|
||||
f.write(f" {s},\n")
|
||||
f.write("};\n\n")
|
||||
|
||||
def render_location(f, location):
|
||||
s = render_vec3(location)
|
||||
f.write(f" .location = {s},\n")
|
||||
|
||||
def render_scale(f, scale):
|
||||
s = render_vec3(scale)
|
||||
f.write(f" .scale = {s},\n")
|
||||
|
||||
def render_rotation_axis_angle(f, r):
|
||||
r = f"{{{r[1]:.6f}, {r[2]:.6f}, {r[3]:.6f}, {r[0]:.6f}}}"
|
||||
f.write(f" .rotation = {r}, // rotation_axis_angle (XYZ T)\n")
|
||||
|
||||
def render_rotation_quaternion(f, r):
|
||||
r = f"{{{r[1]:.6f}, {r[2]:.6f}, {r[3]:.6f}, {r[0]:.6f}}}"
|
||||
f.write(f" .rotation = {r}, // quaternion (XYZW)\n")
|
||||
|
||||
def render_mesh(f, name, mesh):
|
||||
f.write(f"static const vec2 * {name}_uv_layers[] = {{\n")
|
||||
for layer_name in mesh.uv_layers.keys():
|
||||
f.write(f" {name}_{translate_name(layer_name)}_uvmap,\n");
|
||||
f.write( "};\n\n")
|
||||
|
||||
f.write(f"static const struct mesh {name} = {{\n")
|
||||
f.write(f" .position = {name}_position,\n")
|
||||
f.write(f" .position_length = (sizeof ({name}_position)) / (sizeof ({name}_position[0])),\n")
|
||||
f.write(f" .normal = {name}_normal,\n")
|
||||
f.write(f" .normal_length = (sizeof ({name}_normal)) / (sizeof ({name}_normal[0])),\n")
|
||||
f.write(f" .polygon_normal = {name}_polygon_normal,\n")
|
||||
f.write(f" .polygon_normal_length = (sizeof ({name}_polygon_normal)) / (sizeof ({name}_polygon_normal[0])),\n")
|
||||
f.write(f" .polygons = {name}_polygons,\n")
|
||||
f.write(f" .polygons_length = (sizeof ({name}_polygons)) / (sizeof ({name}_polygons[0])),\n")
|
||||
f.write(f" .uv_layers = {name}_uv_layers,\n")
|
||||
f.write(f" .uv_layers_length = (sizeof ({name}_uv_layers)) / (sizeof ({name}_uv_layers[0])),\n")
|
||||
f.write(f" .materials = {name}_materials,\n")
|
||||
f.write(f" .materials_length = (sizeof ({name}_materials)) / (sizeof ({name}_materials[0])),\n")
|
||||
f.write(f" .edge_polygons = {name}_edge_polygons,\n");
|
||||
f.write(f" .edge_polygons_length = (sizeof ({name}_edge_polygons)) / (sizeof ({name}_edge_polygons[0])),\n")
|
||||
f.write( "};\n\n")
|
||||
|
||||
def translate_name(name):
|
||||
return name.replace(".", "_").replace("-", "_").replace(" ", "_")
|
||||
|
||||
def mesh_objects(collections):
|
||||
objects = set()
|
||||
for collection in collections:
|
||||
if collection.hide_render:
|
||||
continue
|
||||
for object in collection.objects:
|
||||
assert object.name not in objects, object.name
|
||||
objects.add(object.name)
|
||||
if object.hide_render:
|
||||
continue
|
||||
if object.type == "MESH":
|
||||
yield object
|
||||
|
||||
def mesh_meshes(collections):
|
||||
mesh_names = set()
|
||||
for object in mesh_objects(collections):
|
||||
mesh = object.data
|
||||
if mesh.name in mesh_names:
|
||||
continue
|
||||
mesh_names.add(mesh.name)
|
||||
|
||||
if not triangulate_meshes:
|
||||
yield mesh.name, mesh
|
||||
else:
|
||||
# triangulate
|
||||
tri_mesh = mesh.copy()
|
||||
bm = bmesh.new()
|
||||
bm.from_mesh(mesh)
|
||||
bmesh.ops.triangulate(bm, faces=bm.faces[:])
|
||||
bm.to_mesh(tri_mesh)
|
||||
bm.free()
|
||||
yield mesh.name, tri_mesh
|
||||
bpy.data.meshes.remove(tri_mesh)
|
||||
|
||||
def get_texture(material):
|
||||
assert material.use_nodes, material.name
|
||||
for node in material.node_tree.nodes:
|
||||
if node.type == "TEX_IMAGE":
|
||||
return node.image
|
||||
|
||||
_offset = 0
|
||||
texture_ids = {}
|
||||
prefix = "textures_"
|
||||
|
||||
def get_texture_id(image):
|
||||
global _offset
|
||||
global texture_ids
|
||||
if image.name in texture_ids:
|
||||
value = texture_ids[image.name]
|
||||
return value
|
||||
value = _offset
|
||||
texture_ids[image.name] = value
|
||||
width, height = image.size
|
||||
#_offset += width * height * 2
|
||||
_offset += 1
|
||||
return value
|
||||
|
||||
def texture_data_name(name):
|
||||
name = path.splitext(name)[0]
|
||||
name = translate_name(name)
|
||||
return f"{prefix}{name}_data"
|
||||
|
||||
def render_mesh_materials(f, name, materials):
|
||||
f.write(f"static const struct mesh_material {name}_materials[] = {{\n")
|
||||
print("materials", materials)
|
||||
for material in materials:
|
||||
image = get_texture(material)
|
||||
print("image", image)
|
||||
if image is not None:
|
||||
f.write(f" {{ // {material.name} {image.name}\n")
|
||||
width, height = image.size
|
||||
texture_id = get_texture_id(image)
|
||||
f.write(f" .width = {width},\n")
|
||||
f.write(f" .height = {height},\n")
|
||||
f.write(f" .texture_id = {texture_id},\n")
|
||||
f.write(" },\n")
|
||||
else:
|
||||
f.write(" {},\n")
|
||||
f.write("};\n")
|
||||
|
||||
def render_materials(f):
|
||||
f.write("static const struct material materials[] = {\n")
|
||||
for image_name, texture_id in sorted(texture_ids.items(), key=lambda i: i[1]):
|
||||
name = texture_data_name(image_name)
|
||||
f.write(" {\n")
|
||||
#f.write(f" .start = (void *)&_binary_{name}_start,\n")
|
||||
#f.write(f" .size = (int)&_binary_{name}_size,\n")
|
||||
f.write(f" .name = \"{image_name}\",\n")
|
||||
f.write(f" .texture_id = {texture_id},\n")
|
||||
f.write(" },\n")
|
||||
f.write("};\n\n");
|
||||
|
||||
def export_meshes(f):
|
||||
for mesh_name, mesh in mesh_meshes(bpy.data.collections):
|
||||
#mesh.vertex_normals
|
||||
#mesh.vertex_colors
|
||||
#mesh.vertices
|
||||
#mesh.uv_layers
|
||||
#mesh.polygons
|
||||
#mesh.polygon_normals
|
||||
#mesh.name
|
||||
|
||||
mesh_name = "mesh_" + translate_name(mesh_name)
|
||||
|
||||
render_mesh_vertices(f, mesh_name, mesh.vertices)
|
||||
for layer_name, layer in mesh.uv_layers.items():
|
||||
render_uv_map(f, mesh_name, translate_name(layer_name), layer.uv)
|
||||
render_vertex_normals(f, mesh_name, mesh.vertices)
|
||||
render_polygon_normals(f, mesh_name, mesh.polygon_normals)
|
||||
render_polygons(f, mesh_name, mesh.polygons)
|
||||
render_polygon_edge_pairs(f, mesh_name, mesh.polygons)
|
||||
render_mesh_materials(f, mesh_name, mesh.materials)
|
||||
|
||||
render_mesh(f, mesh_name, mesh)
|
||||
|
||||
#mesh.polygons[0].vertices
|
||||
# [0, 1, 3, 2]
|
||||
|
||||
# v = mesh.vertices[0]
|
||||
# v.normal
|
||||
# v.index
|
||||
|
||||
def mesh_objects_sorted(objects):
|
||||
def key(o):
|
||||
return (o.data.name, o.name)
|
||||
return sorted(mesh_objects(objects), key=key)
|
||||
|
||||
def export_objects(f):
|
||||
f.write("static const struct object objects[] = {\n")
|
||||
for object in mesh_objects_sorted(bpy.data.collections):
|
||||
|
||||
#object.rotation_mode = 'AXIS_ANGLE'
|
||||
#object.name
|
||||
#object.rotation_axis_angle
|
||||
#object.rotation_euler
|
||||
#object.location
|
||||
|
||||
obj_name = "object_" + translate_name(object.name)
|
||||
|
||||
f.write(f" {{ // {obj_name}\n")
|
||||
|
||||
obj_mesh_name = "mesh_" + translate_name(object.data.name)
|
||||
|
||||
f.write(" ")
|
||||
f.write(f" .mesh = &{obj_mesh_name},\n")
|
||||
|
||||
location, rotation, scale = object.matrix_world.decompose()
|
||||
f.write(" ")
|
||||
render_scale(f, scale)
|
||||
f.write(" ")
|
||||
render_rotation_quaternion(f, rotation)
|
||||
f.write(" ")
|
||||
render_location(f, location)
|
||||
|
||||
f.write(" },\n")
|
||||
f.write("};\n\n")
|
||||
|
||||
def export_scene(f):
|
||||
export_meshes(f)
|
||||
export_objects(f)
|
||||
render_materials(f)
|
||||
|
||||
home = path.expanduser('~')
|
||||
with open(path.join(home, "output.h"), "w") as f:
|
||||
offset = 0
|
||||
export_scene(f)
|
||||
9
tools/png_to_data.py
Normal file
@ -0,0 +1,9 @@
|
||||
import sys
|
||||
from PIL import Image
|
||||
|
||||
im = Image.open(sys.argv[1])
|
||||
im = im.convert("RGBA")
|
||||
buf = im.tobytes()
|
||||
|
||||
with open(sys.argv[2], 'wb') as f:
|
||||
f.write(buf)
|
||||