added retrace tool

This commit is contained in:
Anthony Pesch 2017-05-23 13:34:27 -04:00
parent d3118a9ae8
commit e914e0df48
8 changed files with 306 additions and 28 deletions

View File

@ -167,6 +167,7 @@ set(REDREAM_SOURCES
src/core/profiler.cc
src/core/ringbuf.cc
src/core/rb_tree.c
src/core/sort.c
src/core/string.c
src/hw/aica/aica.c
src/hw/arm7/arm7.c
@ -335,6 +336,16 @@ target_link_libraries(recc ${REDREAM_LIBS})
target_compile_definitions(recc PRIVATE ${REDREAM_DEFS} MICROPROFILE_ENABLED=0)
target_compile_options(recc PRIVATE ${REDREAM_FLAGS})
add_executable(retrace $<TARGET_OBJECTS:relib>
src/null_host.c
tools/retrace/depth.c
tools/retrace/main.c)
target_include_directories(retrace SYSTEM PUBLIC ${REDREAM_INCLUDE_DIRS})
target_include_directories(retrace PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
target_link_libraries(retrace ${REDREAM_LIBS})
target_compile_definitions(retrace PRIVATE ${REDREAM_DEFS} MICROPROFILE_ENABLED=0)
target_compile_options(retrace PRIVATE ${REDREAM_FLAGS})
endif()
#--------------------------------------------------

46
src/core/sort.c Normal file
View File

@ -0,0 +1,46 @@
#include <stdlib.h>
#include <string.h>
#include "core/sort.h"
static void merge(void *in, void *out, size_t size, int l, int m, int r,
sort_cmp cmp) {
int i = l;
int j = m;
int k = l;
while (k < r) {
if ((i < m && cmp(in + i * size, in + j * size)) || j >= r) {
memcpy(out + k * size, in + i * size, size);
k++;
i++;
} else {
memcpy(out + k * size, in + j * size, size);
k++;
j++;
}
}
}
static void mergesort_r(void *in, void *out, size_t size, int l, int r,
sort_cmp cmp) {
if ((r - l) < 2) {
return;
}
int m = (l + r) / 2;
mergesort_r(out, in, size, l, m, cmp);
mergesort_r(out, in, size, m, r, cmp);
merge(in, out, size, l, m, r, cmp);
}
void mergesort_fixed(void *data, void *tmp, int num, size_t size,
sort_cmp cmp) {
memcpy(tmp, data, num * size);
mergesort_r(tmp, data, size, 0, num, cmp);
}
void mergesort(void *data, int num, size_t size, sort_cmp cmp) {
void *tmp = malloc(num * size);
mergesort_fixed(data, tmp, num, size, cmp);
free(tmp);
}

12
src/core/sort.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef SORT_H
#define SORT_H
#include <stddef.h>
/* returns if a is <= b */
typedef int (*sort_cmp)(const void *, const void *);
void mergesort_fixed(void *data, void *tmp, int num, size_t size, sort_cmp cmp);
void mergesort(void *data, int num, size_t size, sort_cmp cmp);
#endif

View File

@ -175,6 +175,24 @@ void trace_destroy(struct trace *trace) {
free(trace);
}
void trace_copy_context(const struct trace_cmd *cmd, struct tile_context *ctx) {
CHECK_EQ(cmd->type, TRACE_CMD_CONTEXT);
ctx->autosort = cmd->context.autosort;
ctx->stride = cmd->context.stride;
ctx->pal_pxl_format = cmd->context.pal_pxl_format;
ctx->bg_isp = cmd->context.bg_isp;
ctx->bg_tsp = cmd->context.bg_tsp;
ctx->bg_tcw = cmd->context.bg_tcw;
ctx->bg_depth = cmd->context.bg_depth;
ctx->video_width = cmd->context.video_width;
ctx->video_height = cmd->context.video_height;
memcpy(ctx->bg_vertices, cmd->context.bg_vertices,
cmd->context.bg_vertices_size);
memcpy(ctx->params, cmd->context.params, cmd->context.params_size);
ctx->size = cmd->context.params_size;
}
struct trace *trace_parse(const char *filename) {
struct trace *trace = calloc(1, sizeof(struct trace));

View File

@ -63,16 +63,17 @@ struct trace_writer {
void get_next_trace_filename(char *filename, size_t size);
void trace_writer_close(struct trace_writer *writer);
void trace_writer_render_context(struct trace_writer *writer,
struct tile_context *ctx);
struct trace *trace_parse(const char *filename);
void trace_copy_context(const struct trace_cmd *cmd, struct tile_context *ctx);
void trace_destroy(struct trace *trace);
struct trace_writer *trace_writer_open(const char *filename);
void trace_writer_insert_texture(struct trace_writer *writer, union tsp tsp,
union tcw tcw, unsigned frame,
const uint8_t *palette, int palette_size,
const uint8_t *texture, int texture_size);
struct trace_writer *trace_writer_open(const char *filename);
void trace_destroy(struct trace *trace);
struct trace *trace_parse(const char *filename);
void trace_writer_render_context(struct trace_writer *writer,
struct tile_context *ctx);
void trace_writer_close(struct trace_writer *writer);
#endif

View File

@ -149,25 +149,6 @@ static void tracer_add_texture(struct tracer *tracer,
tex->palette_size = cmd->texture.palette_size;
}
static void tracer_copy_context(const struct trace_cmd *cmd,
struct tile_context *ctx) {
CHECK_EQ(cmd->type, TRACE_CMD_CONTEXT);
ctx->autosort = cmd->context.autosort;
ctx->stride = cmd->context.stride;
ctx->pal_pxl_format = cmd->context.pal_pxl_format;
ctx->bg_isp = cmd->context.bg_isp;
ctx->bg_tsp = cmd->context.bg_tsp;
ctx->bg_tcw = cmd->context.bg_tcw;
ctx->bg_depth = cmd->context.bg_depth;
ctx->video_width = cmd->context.video_width;
ctx->video_height = cmd->context.video_height;
memcpy(ctx->bg_vertices, cmd->context.bg_vertices,
cmd->context.bg_vertices_size);
memcpy(ctx->params, cmd->context.params, cmd->context.params_size);
ctx->size = cmd->context.params_size;
}
static void tracer_prev_param(struct tracer *tracer) {
int i = tracer->current_param;
@ -225,7 +206,7 @@ static void tracer_prev_context(struct tracer *tracer) {
tracer->current_cmd = prev;
tracer->current_param = -1;
tracer->scroll_to_param = 0;
tracer_copy_context(tracer->current_cmd, &tracer->ctx);
trace_copy_context(tracer->current_cmd, &tracer->ctx);
tr_convert_context(tracer->r, tracer, &tracer_find_texture, &tracer->ctx,
&tracer->rc);
}
@ -264,7 +245,7 @@ static void tracer_next_context(struct tracer *tracer) {
tracer->current_cmd = next;
tracer->current_param = -1;
tracer->scroll_to_param = 0;
tracer_copy_context(tracer->current_cmd, &tracer->ctx);
trace_copy_context(tracer->current_cmd, &tracer->ctx);
tr_convert_context(tracer->r, tracer, &tracer_find_texture, &tracer->ctx,
&tracer->rc);
}

181
tools/retrace/depth.c Normal file
View File

@ -0,0 +1,181 @@
#include <math.h>
#include <stdlib.h>
#include "core/assert.h"
#include "core/sort.h"
#include "hw/pvr/tr.h"
#include "hw/pvr/trace.h"
struct depth_entry {
/* vertex index */
int n;
/* depth buffer value */
union {
float f;
uint32_t i;
} d;
};
typedef void (*depth_cb)(float, float, float, struct depth_entry *);
struct test {
const char *name;
depth_cb depth;
sort_cmp cmp;
int match;
int total;
};
static struct tr_texture *find_texture(void *userdata, union tsp tsp,
union tcw tcw) {
/* return a non-zero handle so it doesn't try to create a texture with
the render backend (which is NULL) */
static struct tr_texture tex;
tex.handle = 1;
return &tex;
}
static int depth_cmp(const void *a, const void *b) {
const struct depth_entry *ea = (const struct depth_entry *)a;
const struct depth_entry *eb = (const struct depth_entry *)b;
return ea->d.i <= eb->d.i;
}
static int depth_cmpf(const void *a, const void *b) {
const struct depth_entry *ea = (const struct depth_entry *)a;
const struct depth_entry *eb = (const struct depth_entry *)b;
return ea->d.f <= eb->d.f;
}
static void test_context(struct trace_cmd *cmd, struct test *tests,
int num_tests) {
CHECK_EQ(cmd->type, TRACE_CMD_CONTEXT);
struct tile_context *ctx = calloc(1, sizeof(struct tile_context));
struct tr_context *rc = calloc(1, sizeof(struct tr_context));
/* parse the context */
trace_copy_context(cmd, ctx);
tr_convert_context(NULL, NULL, &find_texture, ctx, rc);
/* sort each vertex by the original w */
struct depth_entry *original =
calloc(rc->num_verts, sizeof(struct depth_entry));
float minw = FLT_MAX;
float maxw = -FLT_MAX;
for (int i = 0; i < rc->num_verts; i++) {
struct ta_vertex *vert = &rc->verts[i];
struct depth_entry *entry = &original[i];
entry->n = i;
entry->d.f = 1.0f / vert->xyz[2];
minw = MIN(minw, entry->d.f);
maxw = MAX(maxw, entry->d.f);
}
mergesort(original, rc->num_verts, sizeof(struct depth_entry), &depth_cmpf);
for (int i = 0; i < num_tests; i++) {
struct test *test = &tests[i];
/* calculate the depth for each vertex using the test's depth function */
struct depth_entry *tmp = calloc(rc->num_verts, sizeof(struct depth_entry));
for (int j = 0; j < rc->num_verts; j++) {
struct ta_vertex *vert = &rc->verts[j];
struct depth_entry *entry = &tmp[j];
entry->n = j;
test->depth(1.0f / vert->xyz[2], minw, maxw, entry);
}
/* sort the vertices based on the depth value */
mergesort(tmp, rc->num_verts, sizeof(struct depth_entry), test->cmp);
/* compare sorted results with original results */
for (int j = 0; j < rc->num_verts; j++) {
if (original[j].n == tmp[j].n) {
test->match++;
}
}
test->total += rc->num_verts;
free(tmp);
}
free(original);
free(rc);
free(ctx);
}
static void test_flt(float w, float minw, float maxw,
struct depth_entry *entry) {
entry->d.f = (w - minw) / (maxw - minw);
}
static void test_int(float w, float minw, float maxw,
struct depth_entry *entry) {
entry->d.i = ((w - minw) / (maxw - minw)) * ((1 << 24) - 1);
}
static void test_log2(float w, float minw, float maxw,
struct depth_entry *entry) {
entry->d.i = (log2(1.0f + w - minw) / log2(maxw - minw)) * ((1 << 24) - 1);
}
static void test_log2_fixed(float w, float minw, float maxw,
struct depth_entry *entry) {
entry->d.i = (log2(1.0f + w) / 17.0f) * ((1 << 24) - 1);
}
int cmd_depth(int argc, const char **argv) {
if (argc < 1) {
return 0;
}
const char *filename = argv[0];
struct trace *trace = trace_parse(filename);
struct test tests[] = {
{"32-bit float", &test_flt, &depth_cmpf, 0, 0},
{"24-bit int", &test_int, &depth_cmp, 0, 0},
{"24-bit int using log2", &test_log2, &depth_cmp, 0, 0},
{"24-bit int using log2 w/ fixed max", &test_log2_fixed, &depth_cmp, 0,
0},
};
int num_tests = array_size(tests);
/* check each context in the trace */
struct trace_cmd *next = trace->cmds;
while (next) {
if (next->type == TRACE_CMD_CONTEXT) {
test_context(next, tests, num_tests);
break;
}
next = next->next;
}
trace_destroy(trace);
/* print results */
LOG_INFO("===-----------------------------------------------------===");
LOG_INFO("depth test results");
LOG_INFO("===-----------------------------------------------------===");
LOG_INFO("");
int max_name_length = 0;
for (int i = 0; i < num_tests; i++) {
struct test *test = &tests[i];
int l = (int)strlen(test->name);
max_name_length = MAX(max_name_length, l);
}
for (int i = 0; i < num_tests; i++) {
struct test *test = &tests[i];
LOG_INFO("%-*s %f%%", max_name_length, test->name,
((float)test->match / test->total) * 100.0f);
}
return 1;
}

28
tools/retrace/main.c Normal file
View File

@ -0,0 +1,28 @@
#include "core/log.h"
extern int cmd_depth(int argc, const char **argv);
static void print_help() {
LOG_INFO("usage: retrace <command> [<args> ...]");
LOG_INFO("the available commands are:");
LOG_INFO(" depth compare depth function accuracies");
}
int main(int argc, const char **argv) {
int res = 0;
if (argc >= 2) {
const char *cmd = argv[1];
if (!strcmp(cmd, "depth")) {
res = cmd_depth(argc - 2, argv + 2);
}
}
if (!res) {
print_help();
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}