mirror of https://github.com/inolen/redream.git
removed microprofile
This commit is contained in:
parent
aaa58d7142
commit
2e629ab64d
|
@ -135,9 +135,6 @@ add_library(imgui-static STATIC
|
||||||
list(APPEND RELIB_INCLUDES deps/cimgui)
|
list(APPEND RELIB_INCLUDES deps/cimgui)
|
||||||
list(APPEND IMGUI_LIBS imgui-static)
|
list(APPEND IMGUI_LIBS imgui-static)
|
||||||
|
|
||||||
# microprofile
|
|
||||||
list(APPEND RELIB_INCLUDES deps/microprofile)
|
|
||||||
|
|
||||||
# sdl2
|
# sdl2
|
||||||
set(DIRECTX OFF CACHE BOOL "")
|
set(DIRECTX OFF CACHE BOOL "")
|
||||||
set(RENDER_D3D OFF CACHE BOOL "")
|
set(RENDER_D3D OFF CACHE BOOL "")
|
||||||
|
@ -188,7 +185,7 @@ set(RELIB_SOURCES
|
||||||
src/core/md5.c
|
src/core/md5.c
|
||||||
src/core/memory.c
|
src/core/memory.c
|
||||||
src/core/option.c
|
src/core/option.c
|
||||||
src/core/profiler.cc
|
src/core/profiler.c
|
||||||
src/core/ringbuf.cc
|
src/core/ringbuf.cc
|
||||||
src/core/rb_tree.c
|
src/core/rb_tree.c
|
||||||
src/core/sort.c
|
src/core/sort.c
|
||||||
|
@ -249,8 +246,7 @@ set(RELIB_SOURCES
|
||||||
src/jit/jit.c
|
src/jit/jit.c
|
||||||
src/jit/pass_stats.c
|
src/jit/pass_stats.c
|
||||||
src/render/gl_backend.c
|
src/render/gl_backend.c
|
||||||
src/imgui.cc
|
src/imgui.cc)
|
||||||
src/microprofile.cc)
|
|
||||||
|
|
||||||
if(PLATFORM_ANDROID)
|
if(PLATFORM_ANDROID)
|
||||||
list(APPEND RELIB_DEFS PLATFORM_ANDROID=1)
|
list(APPEND RELIB_DEFS PLATFORM_ANDROID=1)
|
||||||
|
@ -357,7 +353,7 @@ else()
|
||||||
set(REDREAM_SOURCES ${RELIB_SOURCES} src/host/sdl_host.c src/emulator.c src/tracer.c)
|
set(REDREAM_SOURCES ${RELIB_SOURCES} src/host/sdl_host.c src/emulator.c src/tracer.c)
|
||||||
set(REDREAM_INCLUDES ${RELIB_INCLUDES})
|
set(REDREAM_INCLUDES ${RELIB_INCLUDES})
|
||||||
set(REDREAM_LIBS ${RELIB_LIBS} ${IMGUI_LIBS} ${SDL_LIBS})
|
set(REDREAM_LIBS ${RELIB_LIBS} ${IMGUI_LIBS} ${SDL_LIBS})
|
||||||
set(REDREAM_DEFS ${RELIB_DEFS} HAVE_GDBSERVER HAVE_IMGUI HAVE_MICROPROFILE)
|
set(REDREAM_DEFS ${RELIB_DEFS} HAVE_GDBSERVER HAVE_IMGUI)
|
||||||
set(REDREAM_FLAGS ${RELIB_FLAGS})
|
set(REDREAM_FLAGS ${RELIB_FLAGS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -84,8 +84,7 @@ SOURCES_C := $(CORE_DIR)/src/core/assert.c \
|
||||||
$(CORE_DIR)/src/host/retro_host.c \
|
$(CORE_DIR)/src/host/retro_host.c \
|
||||||
$(CORE_DIR)/src/render/gl_backend.c
|
$(CORE_DIR)/src/render/gl_backend.c
|
||||||
|
|
||||||
SOURCES_CXX += $(CORE_DIR)/src/render/imgui.cc \
|
SOURCES_CXX += $(CORE_DIR)/src/imgui.cc
|
||||||
$(CORE_DIR)/src/render/microprofile.cc
|
|
||||||
|
|
||||||
#==--------------------------------------------------------------------------==#
|
#==--------------------------------------------------------------------------==#
|
||||||
# capstone
|
# capstone
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,75 @@
|
||||||
|
#include "core/profiler.h"
|
||||||
|
#include "core/assert.h"
|
||||||
|
#include "core/time.h"
|
||||||
|
|
||||||
|
#define PROFILER_MAX_COUNTERS 32
|
||||||
|
|
||||||
|
struct counter {
|
||||||
|
int aggregate;
|
||||||
|
int64_t value[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
struct counter counters[PROFILER_MAX_COUNTERS];
|
||||||
|
int num_counters;
|
||||||
|
|
||||||
|
int64_t last_aggregation;
|
||||||
|
} prof;
|
||||||
|
|
||||||
|
prof_token_t prof_get_next_token() {
|
||||||
|
prof_token_t tok = prof.num_counters++;
|
||||||
|
CHECK_LT(tok, PROFILER_MAX_COUNTERS);
|
||||||
|
return tok;
|
||||||
|
}
|
||||||
|
|
||||||
|
prof_token_t prof_get_counter_token(const char *name) {
|
||||||
|
prof_token_t tok = prof_get_next_token();
|
||||||
|
struct counter *c = &prof.counters[tok];
|
||||||
|
c->aggregate = 0;
|
||||||
|
return tok;
|
||||||
|
}
|
||||||
|
|
||||||
|
prof_token_t prof_get_aggregate_token(const char *name) {
|
||||||
|
prof_token_t tok = prof_get_next_token();
|
||||||
|
struct counter *c = &prof.counters[tok];
|
||||||
|
c->aggregate = 1;
|
||||||
|
return tok;
|
||||||
|
}
|
||||||
|
|
||||||
|
void prof_flip(int64_t now) {
|
||||||
|
/* update time-based aggregate counters every second */
|
||||||
|
int64_t next_aggregation = prof.last_aggregation + NS_PER_SEC;
|
||||||
|
|
||||||
|
if (now > next_aggregation) {
|
||||||
|
for (int i = 0; i < PROFILER_MAX_COUNTERS; i++) {
|
||||||
|
struct counter *c = &prof.counters[i];
|
||||||
|
|
||||||
|
if (c->aggregate) {
|
||||||
|
c->value[0] = c->value[1];
|
||||||
|
c->value[1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prof.last_aggregation = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void prof_counter_set(prof_token_t tok, int64_t count) {
|
||||||
|
struct counter *c = &prof.counters[tok];
|
||||||
|
c->value[1] = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void prof_counter_add(prof_token_t tok, int64_t count) {
|
||||||
|
struct counter *c = &prof.counters[tok];
|
||||||
|
c->value[1] += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t prof_counter_load(prof_token_t tok) {
|
||||||
|
struct counter *c = &prof.counters[tok];
|
||||||
|
if (c->aggregate) {
|
||||||
|
/* return the last aggregated value */
|
||||||
|
return c->value[0];
|
||||||
|
} else {
|
||||||
|
return c->value[1];
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,190 +0,0 @@
|
||||||
#include <atomic>
|
|
||||||
|
|
||||||
#ifdef HAVE_MICROPROFILE
|
|
||||||
#include <microprofile/microprofile.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
#include "core/profiler.h"
|
|
||||||
#include "core/time.h"
|
|
||||||
|
|
||||||
static struct {
|
|
||||||
#ifdef HAVE_MICROPROFILE
|
|
||||||
std::atomic<int64_t> counters[MICROPROFILE_MAX_COUNTERS];
|
|
||||||
int aggregate[MICROPROFILE_MAX_COUNTERS];
|
|
||||||
int64_t last_aggregation;
|
|
||||||
#else
|
|
||||||
/* avoid having an empty struct in c (only valid through GCC extension) */
|
|
||||||
int dummy;
|
|
||||||
#endif
|
|
||||||
} prof;
|
|
||||||
|
|
||||||
static inline float hue_to_rgb(float p, float q, float t) {
|
|
||||||
if (t < 0.0f) {
|
|
||||||
t += 1.0f;
|
|
||||||
}
|
|
||||||
if (t > 1.0f) {
|
|
||||||
t -= 1.0f;
|
|
||||||
}
|
|
||||||
if (t < 1.0f / 6.0f) {
|
|
||||||
return p + (q - p) * 6.0f * t;
|
|
||||||
}
|
|
||||||
if (t < 1.0f / 2.0f) {
|
|
||||||
return q;
|
|
||||||
}
|
|
||||||
if (t < 2.0f / 3.0f) {
|
|
||||||
return p + (q - p) * (2.0f / 3.0f - t) * 6.0f;
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void hsl_to_rgb(float h, float s, float l, uint8_t *r, uint8_t *g,
|
|
||||||
uint8_t *b) {
|
|
||||||
float fr, fg, fb;
|
|
||||||
|
|
||||||
if (s == 0.0f) {
|
|
||||||
fr = fg = fb = l;
|
|
||||||
} else {
|
|
||||||
float q = l < 0.5f ? l * (1.0f + s) : l + s - l * s;
|
|
||||||
float p = 2.0f * l - q;
|
|
||||||
fr = hue_to_rgb(p, q, h + 1.0f / 3.0f);
|
|
||||||
fg = hue_to_rgb(p, q, h);
|
|
||||||
fb = hue_to_rgb(p, q, h - 1.0f / 3.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
*r = (uint8_t)(fr * 255);
|
|
||||||
*g = (uint8_t)(fg * 255);
|
|
||||||
*b = (uint8_t)(fb * 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned prof_hash(const char *name) {
|
|
||||||
unsigned hash = 5381;
|
|
||||||
char c;
|
|
||||||
while ((c = *name++)) {
|
|
||||||
hash = ((hash << 5) + hash) + c;
|
|
||||||
}
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t prof_scope_color(const char *name) {
|
|
||||||
unsigned name_hash = prof_hash(name);
|
|
||||||
float h = (name_hash % 360) / 360.0f;
|
|
||||||
float s = 0.7f;
|
|
||||||
float l = 0.6f;
|
|
||||||
uint8_t r, g, b;
|
|
||||||
hsl_to_rgb(h, s, l, &r, &g, &b);
|
|
||||||
return (r << 16) | (g << 8) | b;
|
|
||||||
}
|
|
||||||
|
|
||||||
prof_token_t prof_get_token(const char *group, const char *name) {
|
|
||||||
prof_init();
|
|
||||||
|
|
||||||
#ifdef HAVE_MICROPROFILE
|
|
||||||
uint32_t color = prof_scope_color(name);
|
|
||||||
return MicroProfileGetToken(group, name, color, MicroProfileTokenTypeCpu);
|
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
prof_token_t prof_get_counter_token(const char *name) {
|
|
||||||
prof_init();
|
|
||||||
|
|
||||||
#ifdef HAVE_MICROPROFILE
|
|
||||||
prof_token_t tok = MicroProfileGetCounterToken(name);
|
|
||||||
prof.aggregate[tok] = 0;
|
|
||||||
return tok;
|
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
prof_token_t prof_get_aggregate_token(const char *name) {
|
|
||||||
prof_init();
|
|
||||||
#ifdef HAVE_MICROPROFILE
|
|
||||||
prof_token_t tok = MicroProfileGetCounterToken(name);
|
|
||||||
prof.aggregate[tok] = 1;
|
|
||||||
return tok;
|
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void prof_flip(int64_t now) {
|
|
||||||
#ifdef HAVE_MICROPROFILE
|
|
||||||
/* update time-based aggregate counters every second */
|
|
||||||
int64_t next_aggregation = prof.last_aggregation + NS_PER_SEC;
|
|
||||||
|
|
||||||
if (now > next_aggregation) {
|
|
||||||
for (int i = 0; i < MICROPROFILE_MAX_COUNTERS; i++) {
|
|
||||||
if (!prof.aggregate[i]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
MicroProfileCounterSet(i, prof.counters[i].load());
|
|
||||||
prof.counters[i].store(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
prof.last_aggregation = now;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* flip frame-based profile zones at the end of every frame */
|
|
||||||
MicroProfileFlip();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void prof_counter_set(prof_token_t tok, int64_t count) {
|
|
||||||
#ifdef HAVE_MICROPROFILE
|
|
||||||
if (prof.aggregate[tok]) {
|
|
||||||
prof.counters[tok].store(count);
|
|
||||||
} else {
|
|
||||||
MicroProfileCounterSet(tok, count);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void prof_counter_add(prof_token_t tok, int64_t count) {
|
|
||||||
#ifdef HAVE_MICROPROFILE
|
|
||||||
if (prof.aggregate[tok]) {
|
|
||||||
prof.counters[tok].fetch_add(count);
|
|
||||||
} else {
|
|
||||||
MicroProfileCounterAdd(tok, count);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t prof_counter_load(prof_token_t tok) {
|
|
||||||
#ifdef HAVE_MICROPROFILE
|
|
||||||
return MicroProfileCounterLoad(tok);
|
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void prof_leave(prof_token_t tok, uint64_t tick) {
|
|
||||||
#ifdef HAVE_MICROPROFILE
|
|
||||||
MicroProfileLeave(tok, tick);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t prof_enter(prof_token_t tok) {
|
|
||||||
#ifdef HAVE_MICROPROFILE
|
|
||||||
return MicroProfileEnter(tok);
|
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void prof_shutdown() {
|
|
||||||
#ifdef HAVE_MICROPROFILE
|
|
||||||
MicroProfileShutdown();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void prof_init() {
|
|
||||||
#ifdef HAVE_MICROPROFILE
|
|
||||||
MicroProfileInit();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "core/constructor.h"
|
#include "core/constructor.h"
|
||||||
#include "core/list.h"
|
#include "core/list.h"
|
||||||
|
|
||||||
typedef uint64_t prof_token_t;
|
typedef int prof_token_t;
|
||||||
|
|
||||||
#define DECLARE_COUNTER(name) extern prof_token_t COUNTER_##name;
|
#define DECLARE_COUNTER(name) extern prof_token_t COUNTER_##name;
|
||||||
|
|
||||||
|
@ -22,27 +22,10 @@ typedef uint64_t prof_token_t;
|
||||||
COUNTER_##name = prof_get_aggregate_token(#name); \
|
COUNTER_##name = prof_get_aggregate_token(#name); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PROF_ENTER(group, name) \
|
|
||||||
static int prof_init = 0; \
|
|
||||||
static prof_token_t prof_tok; \
|
|
||||||
if (!prof_init) { \
|
|
||||||
prof_tok = prof_get_token(group, name); \
|
|
||||||
prof_init = 1; \
|
|
||||||
} \
|
|
||||||
uint64_t prof_tick = prof_enter(prof_tok)
|
|
||||||
|
|
||||||
#define PROF_LEAVE() prof_leave(prof_tok, prof_tick)
|
|
||||||
|
|
||||||
prof_token_t prof_get_token(const char *group, const char *name);
|
prof_token_t prof_get_token(const char *group, const char *name);
|
||||||
prof_token_t prof_get_counter_token(const char *name);
|
prof_token_t prof_get_counter_token(const char *name);
|
||||||
prof_token_t prof_get_aggregate_token(const char *name);
|
prof_token_t prof_get_aggregate_token(const char *name);
|
||||||
|
|
||||||
void prof_init();
|
|
||||||
void prof_shutdown();
|
|
||||||
|
|
||||||
uint64_t prof_enter(prof_token_t tok);
|
|
||||||
void prof_leave(prof_token_t tok, uint64_t tick);
|
|
||||||
|
|
||||||
int64_t prof_counter_load(prof_token_t tok);
|
int64_t prof_counter_load(prof_token_t tok);
|
||||||
void prof_counter_add(prof_token_t tok, int64_t count);
|
void prof_counter_add(prof_token_t tok, int64_t count);
|
||||||
void prof_counter_set(prof_token_t tok, int64_t count);
|
void prof_counter_set(prof_token_t tok, int64_t count);
|
||||||
|
|
|
@ -155,8 +155,6 @@ void arm7_suspend(struct arm7 *arm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void arm7_run(struct device *dev, int64_t ns) {
|
static void arm7_run(struct device *dev, int64_t ns) {
|
||||||
PROF_ENTER("cpu", "arm7_run");
|
|
||||||
|
|
||||||
struct arm7 *arm = (struct arm7 *)dev;
|
struct arm7 *arm = (struct arm7 *)dev;
|
||||||
struct armv3_context *ctx = &arm->ctx;
|
struct armv3_context *ctx = &arm->ctx;
|
||||||
struct jit *jit = arm->jit;
|
struct jit *jit = arm->jit;
|
||||||
|
@ -167,8 +165,6 @@ static void arm7_run(struct device *dev, int64_t ns) {
|
||||||
jit_run(arm->jit, cycles);
|
jit_run(arm->jit, cycles);
|
||||||
|
|
||||||
prof_counter_add(COUNTER_arm7_instrs, arm->ctx.ran_instrs);
|
prof_counter_add(COUNTER_arm7_instrs, arm->ctx.ran_instrs);
|
||||||
|
|
||||||
PROF_LEAVE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void arm7_guest_destroy(struct jit_guest *guest) {
|
static void arm7_guest_destroy(struct jit_guest *guest) {
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
#include "guest/scheduler.h"
|
#include "guest/scheduler.h"
|
||||||
#include "guest/sh4/sh4.h"
|
#include "guest/sh4/sh4.h"
|
||||||
|
|
||||||
DEFINE_AGGREGATE_COUNTER(ta_data);
|
|
||||||
DEFINE_AGGREGATE_COUNTER(ta_renders);
|
DEFINE_AGGREGATE_COUNTER(ta_renders);
|
||||||
|
|
||||||
struct ta {
|
struct ta {
|
||||||
|
@ -410,9 +409,6 @@ static void ta_write_context(struct ta *ta, struct ta_context *ctx, void *ptr,
|
||||||
memcpy(&ctx->params[ctx->size], ptr, size);
|
memcpy(&ctx->params[ctx->size], ptr, size);
|
||||||
ctx->size += size;
|
ctx->size += size;
|
||||||
|
|
||||||
/* track how much TA data is written per second */
|
|
||||||
prof_counter_add(COUNTER_ta_data, size);
|
|
||||||
|
|
||||||
/* each TA command is either 32 or 64 bytes, with the pcw being in the first
|
/* each TA command is either 32 or 64 bytes, with the pcw being in the first
|
||||||
32 bytes always. check every 32 bytes to see if the command has been
|
32 bytes always. check every 32 bytes to see if the command has been
|
||||||
completely received or not */
|
completely received or not */
|
||||||
|
@ -731,8 +727,6 @@ static void ta_yuv_process_macroblock(struct ta *ta, void *data) {
|
||||||
* 3.) texture data - data that is written directly to vram
|
* 3.) texture data - data that is written directly to vram
|
||||||
*/
|
*/
|
||||||
static void ta_poly_write(struct ta *ta, uint32_t dst, void *ptr, int size) {
|
static void ta_poly_write(struct ta *ta, uint32_t dst, void *ptr, int size) {
|
||||||
PROF_ENTER("cpu", "ta_poly_write");
|
|
||||||
|
|
||||||
CHECK(size % 32 == 0);
|
CHECK(size % 32 == 0);
|
||||||
|
|
||||||
uint8_t *src = ptr;
|
uint8_t *src = ptr;
|
||||||
|
@ -741,13 +735,9 @@ static void ta_poly_write(struct ta *ta, uint32_t dst, void *ptr, int size) {
|
||||||
ta_write_context(ta, ta->curr_context, src, 32);
|
ta_write_context(ta, ta->curr_context, src, 32);
|
||||||
src += 32;
|
src += 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
PROF_LEAVE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ta_yuv_write(struct ta *ta, uint32_t dst, void *ptr, int size) {
|
static void ta_yuv_write(struct ta *ta, uint32_t dst, void *ptr, int size) {
|
||||||
PROF_ENTER("cpu", "ta_yuv_write");
|
|
||||||
|
|
||||||
struct holly *holly = ta->holly;
|
struct holly *holly = ta->holly;
|
||||||
struct pvr *pvr = ta->pvr;
|
struct pvr *pvr = ta->pvr;
|
||||||
|
|
||||||
|
@ -759,18 +749,12 @@ static void ta_yuv_write(struct ta *ta, uint32_t dst, void *ptr, int size) {
|
||||||
ta_yuv_process_macroblock(ta, src);
|
ta_yuv_process_macroblock(ta, src);
|
||||||
src += ta->yuv_macroblock_size;
|
src += ta->yuv_macroblock_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
PROF_LEAVE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ta_texture_write(struct ta *ta, uint32_t dst, void *ptr, int size) {
|
static void ta_texture_write(struct ta *ta, uint32_t dst, void *ptr, int size) {
|
||||||
PROF_ENTER("cpu", "ta_texture_write");
|
|
||||||
|
|
||||||
uint8_t *src = ptr;
|
uint8_t *src = ptr;
|
||||||
dst &= 0xeeffffff;
|
dst &= 0xeeffffff;
|
||||||
memcpy(&ta->video_ram[dst], src, size);
|
memcpy(&ta->video_ram[dst], src, size);
|
||||||
|
|
||||||
PROF_LEAVE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -127,8 +127,6 @@ static inline uint32_t float_to_rgba(float r, float g, float b, float a) {
|
||||||
static texture_handle_t tr_convert_texture(struct tr *tr,
|
static texture_handle_t tr_convert_texture(struct tr *tr,
|
||||||
const struct ta_context *ctx,
|
const struct ta_context *ctx,
|
||||||
union tsp tsp, union tcw tcw) {
|
union tsp tsp, union tcw tcw) {
|
||||||
PROF_ENTER("gpu", "tr_convert_texture");
|
|
||||||
|
|
||||||
/* TODO it's bad that textures are only cached based off tsp / tcw yet the
|
/* TODO it's bad that textures are only cached based off tsp / tcw yet the
|
||||||
TEXT_CONTROL registers and PAL_RAM_CTRL registers are used here to control
|
TEXT_CONTROL registers and PAL_RAM_CTRL registers are used here to control
|
||||||
texture generation */
|
texture generation */
|
||||||
|
@ -138,7 +136,6 @@ static texture_handle_t tr_convert_texture(struct tr *tr,
|
||||||
|
|
||||||
/* if there's a non-dirty handle, return it */
|
/* if there's a non-dirty handle, return it */
|
||||||
if (entry->handle && !entry->dirty) {
|
if (entry->handle && !entry->dirty) {
|
||||||
PROF_LEAVE();
|
|
||||||
return entry->handle;
|
return entry->handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,8 +180,6 @@ static texture_handle_t tr_convert_texture(struct tr *tr,
|
||||||
entry->height = height;
|
entry->height = height;
|
||||||
entry->dirty = 0;
|
entry->dirty = 0;
|
||||||
|
|
||||||
PROF_LEAVE();
|
|
||||||
|
|
||||||
return entry->handle;
|
return entry->handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -712,8 +707,6 @@ static int tr_compare_surf(const void *a, const void *b) {
|
||||||
|
|
||||||
static void tr_sort_render_list(struct tr *tr, struct tr_context *rc,
|
static void tr_sort_render_list(struct tr *tr, struct tr_context *rc,
|
||||||
int list_type) {
|
int list_type) {
|
||||||
PROF_ENTER("gpu", "tr_sort_render_list");
|
|
||||||
|
|
||||||
/* sort each surface from back to front based on its minz */
|
/* sort each surface from back to front based on its minz */
|
||||||
struct tr_list *list = &rc->lists[list_type];
|
struct tr_list *list = &rc->lists[list_type];
|
||||||
|
|
||||||
|
@ -735,8 +728,6 @@ static void tr_sort_render_list(struct tr *tr, struct tr_context *rc,
|
||||||
|
|
||||||
msort_noalloc(list->surfs, sort_tmp, list->num_surfs, sizeof(int),
|
msort_noalloc(list->surfs, sort_tmp, list->num_surfs, sizeof(int),
|
||||||
&tr_compare_surf);
|
&tr_compare_surf);
|
||||||
|
|
||||||
PROF_LEAVE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tr_parse_eol(struct tr *tr, const struct ta_context *ctx,
|
static void tr_parse_eol(struct tr *tr, const struct ta_context *ctx,
|
||||||
|
@ -791,8 +782,6 @@ static void tr_render_list(struct render_backend *r,
|
||||||
|
|
||||||
void tr_render_context_until(struct render_backend *r,
|
void tr_render_context_until(struct render_backend *r,
|
||||||
const struct tr_context *rc, int end_surf) {
|
const struct tr_context *rc, int end_surf) {
|
||||||
PROF_ENTER("gpu", "tr_render_context_until");
|
|
||||||
|
|
||||||
int stopped = 0;
|
int stopped = 0;
|
||||||
|
|
||||||
r_begin_ta_surfaces(r, rc->width, rc->height, rc->verts, rc->num_verts,
|
r_begin_ta_surfaces(r, rc->width, rc->height, rc->verts, rc->num_verts,
|
||||||
|
@ -803,8 +792,6 @@ void tr_render_context_until(struct render_backend *r,
|
||||||
tr_render_list(r, rc, TA_LIST_TRANSLUCENT, end_surf, &stopped);
|
tr_render_list(r, rc, TA_LIST_TRANSLUCENT, end_surf, &stopped);
|
||||||
|
|
||||||
r_end_ta_surfaces(r);
|
r_end_ta_surfaces(r);
|
||||||
|
|
||||||
PROF_LEAVE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void tr_render_context(struct render_backend *r, const struct tr_context *rc) {
|
void tr_render_context(struct render_backend *r, const struct tr_context *rc) {
|
||||||
|
@ -814,8 +801,6 @@ void tr_render_context(struct render_backend *r, const struct tr_context *rc) {
|
||||||
void tr_convert_context(struct render_backend *r, void *userdata,
|
void tr_convert_context(struct render_backend *r, void *userdata,
|
||||||
tr_find_texture_cb find_texture,
|
tr_find_texture_cb find_texture,
|
||||||
const struct ta_context *ctx, struct tr_context *rc) {
|
const struct ta_context *ctx, struct tr_context *rc) {
|
||||||
PROF_ENTER("gpu", "tr_convert_context");
|
|
||||||
|
|
||||||
struct tr tr;
|
struct tr tr;
|
||||||
tr.r = r;
|
tr.r = r;
|
||||||
tr.userdata = userdata;
|
tr.userdata = userdata;
|
||||||
|
@ -886,6 +871,4 @@ void tr_convert_context(struct render_backend *r, void *userdata,
|
||||||
LOG_INFO("tr_convert_convext merged %d / %d surfaces", tr.merged_surfs,
|
LOG_INFO("tr_convert_convext merged %d / %d surfaces", tr.merged_surfs,
|
||||||
tr.merged_surfs + rc->num_surfs);
|
tr.merged_surfs + rc->num_surfs);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PROF_LEAVE();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DEFINE_AGGREGATE_COUNTER(sh4_instrs);
|
DEFINE_AGGREGATE_COUNTER(sh4_instrs);
|
||||||
DEFINE_AGGREGATE_COUNTER(sh4_sr_updates);
|
|
||||||
|
|
||||||
/* callbacks to service sh4_reg_read / sh4_reg_write calls */
|
/* callbacks to service sh4_reg_read / sh4_reg_write calls */
|
||||||
struct reg_cb sh4_cb[SH4_NUM_REGS];
|
struct reg_cb sh4_cb[SH4_NUM_REGS];
|
||||||
|
@ -47,8 +46,6 @@ struct sh4_interrupt_info sh4_interrupts[SH4_NUM_INTERRUPTS] = {
|
||||||
static void sh4_sr_updated(struct sh4 *sh4, uint32_t old_sr) {
|
static void sh4_sr_updated(struct sh4 *sh4, uint32_t old_sr) {
|
||||||
struct sh4_context *ctx = &sh4->ctx;
|
struct sh4_context *ctx = &sh4->ctx;
|
||||||
|
|
||||||
prof_counter_add(COUNTER_sh4_sr_updates, 1);
|
|
||||||
|
|
||||||
if ((ctx->sr & RB_MASK) != (old_sr & RB_MASK)) {
|
if ((ctx->sr & RB_MASK) != (old_sr & RB_MASK)) {
|
||||||
sh4_swap_gpr_bank(ctx);
|
sh4_swap_gpr_bank(ctx);
|
||||||
}
|
}
|
||||||
|
@ -166,8 +163,6 @@ static void sh4_invalid_instr(struct sh4 *sh4) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sh4_run(struct device *dev, int64_t ns) {
|
static void sh4_run(struct device *dev, int64_t ns) {
|
||||||
PROF_ENTER("cpu", "sh4_run");
|
|
||||||
|
|
||||||
struct sh4 *sh4 = (struct sh4 *)dev;
|
struct sh4 *sh4 = (struct sh4 *)dev;
|
||||||
struct sh4_context *ctx = &sh4->ctx;
|
struct sh4_context *ctx = &sh4->ctx;
|
||||||
struct jit *jit = sh4->jit;
|
struct jit *jit = sh4->jit;
|
||||||
|
@ -178,8 +173,6 @@ static void sh4_run(struct device *dev, int64_t ns) {
|
||||||
jit_run(sh4->jit, cycles);
|
jit_run(sh4->jit, cycles);
|
||||||
|
|
||||||
prof_counter_add(COUNTER_sh4_instrs, sh4->ctx.ran_instrs);
|
prof_counter_add(COUNTER_sh4_instrs, sh4->ctx.ran_instrs);
|
||||||
|
|
||||||
PROF_LEAVE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sh4_guest_destroy(struct jit_guest *guest) {
|
static void sh4_guest_destroy(struct jit_guest *guest) {
|
||||||
|
|
|
@ -29,8 +29,6 @@ static void sh4_ccn_reset(struct sh4 *sh4) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void sh4_ccn_pref(struct sh4 *sh4, uint32_t addr) {
|
void sh4_ccn_pref(struct sh4 *sh4, uint32_t addr) {
|
||||||
PROF_ENTER("cpu", "sh4_ccn_pref");
|
|
||||||
|
|
||||||
/* make sure this is a sq related prefetch */
|
/* make sure this is a sq related prefetch */
|
||||||
DCHECK(addr >= 0xe0000000 && addr <= 0xe3ffffff);
|
DCHECK(addr >= 0xe0000000 && addr <= 0xe3ffffff);
|
||||||
|
|
||||||
|
@ -57,8 +55,6 @@ void sh4_ccn_pref(struct sh4 *sh4, uint32_t addr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
as_memcpy_to_guest(sh4->memory_if->space, dst, sh4->ctx.sq[sqi], 32);
|
as_memcpy_to_guest(sh4->memory_if->space, dst, sh4->ctx.sq[sqi], 32);
|
||||||
|
|
||||||
PROF_LEAVE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t sh4_ccn_cache_read(struct sh4 *sh4, uint32_t addr,
|
uint32_t sh4_ccn_cache_read(struct sh4 *sh4, uint32_t addr,
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
#include "emulator.h"
|
#include "emulator.h"
|
||||||
#include "host/host.h"
|
#include "host/host.h"
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "microprofile.h"
|
|
||||||
#include "render/render_backend.h"
|
#include "render/render_backend.h"
|
||||||
#include "tracer.h"
|
#include "tracer.h"
|
||||||
|
|
||||||
|
@ -50,7 +49,6 @@ struct sdl_host {
|
||||||
int video_width;
|
int video_width;
|
||||||
int video_height;
|
int video_height;
|
||||||
struct imgui *imgui;
|
struct imgui *imgui;
|
||||||
struct microprofile *mp;
|
|
||||||
|
|
||||||
/* input */
|
/* input */
|
||||||
int key_map[K_NUM_KEYS];
|
int key_map[K_NUM_KEYS];
|
||||||
|
@ -265,7 +263,6 @@ int video_can_fullscreen(struct host *base) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void video_shutdown(struct sdl_host *host) {
|
static void video_shutdown(struct sdl_host *host) {
|
||||||
mp_destroy(host->mp);
|
|
||||||
imgui_destroy(host->imgui);
|
imgui_destroy(host->imgui);
|
||||||
r_destroy(host->video_rb);
|
r_destroy(host->video_rb);
|
||||||
video_destroy_context(host, host->video_ctx);
|
video_destroy_context(host, host->video_ctx);
|
||||||
|
@ -275,7 +272,6 @@ static int video_init(struct sdl_host *host) {
|
||||||
host->video_ctx = video_create_context(host);
|
host->video_ctx = video_create_context(host);
|
||||||
host->video_rb = r_create();
|
host->video_rb = r_create();
|
||||||
host->imgui = imgui_create(host->video_rb);
|
host->imgui = imgui_create(host->video_rb);
|
||||||
host->mp = mp_create(host->video_rb);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -452,7 +448,6 @@ static void input_handle_mousemove(struct sdl_host *host, int port, int x,
|
||||||
}
|
}
|
||||||
|
|
||||||
imgui_mousemove(host->imgui, x, y);
|
imgui_mousemove(host->imgui, x, y);
|
||||||
mp_mousemove(host->mp, x, y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void input_handle_keydown(struct sdl_host *host, int port,
|
static void input_handle_keydown(struct sdl_host *host, int port,
|
||||||
|
@ -469,7 +464,6 @@ static void input_handle_keydown(struct sdl_host *host, int port,
|
||||||
}
|
}
|
||||||
|
|
||||||
imgui_keydown(host->imgui, key, value);
|
imgui_keydown(host->imgui, key, value);
|
||||||
mp_keydown(host->mp, key, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void input_handle_controller_removed(struct sdl_host *host, int port) {
|
static void input_handle_controller_removed(struct sdl_host *host, int port) {
|
||||||
|
@ -847,7 +841,6 @@ int main(int argc, char **argv) {
|
||||||
emu_render_frame(emu, host->video_width, host->video_height);
|
emu_render_frame(emu, host->video_width, host->video_height);
|
||||||
|
|
||||||
/* overlay user interface */
|
/* overlay user interface */
|
||||||
mp_render_frame(host->mp, host->video_width, host->video_height);
|
|
||||||
imgui_end_frame(host->imgui);
|
imgui_end_frame(host->imgui);
|
||||||
|
|
||||||
/* flip profiler at end of frame */
|
/* flip profiler at end of frame */
|
||||||
|
|
|
@ -663,8 +663,6 @@ static void x64_backend_emit(struct x64_backend *backend, struct ir *ir,
|
||||||
static int x64_backend_assemble_code(struct jit_backend *base, struct ir *ir,
|
static int x64_backend_assemble_code(struct jit_backend *base, struct ir *ir,
|
||||||
uint8_t **addr, int *size,
|
uint8_t **addr, int *size,
|
||||||
jit_emit_cb emit_cb, void *emit_data) {
|
jit_emit_cb emit_cb, void *emit_data) {
|
||||||
PROF_ENTER("cpu", "x64_backend_assemble_code");
|
|
||||||
|
|
||||||
struct x64_backend *backend = container_of(base, struct x64_backend, base);
|
struct x64_backend *backend = container_of(base, struct x64_backend, base);
|
||||||
auto &e = *backend->codegen;
|
auto &e = *backend->codegen;
|
||||||
|
|
||||||
|
@ -686,8 +684,6 @@ static int x64_backend_assemble_code(struct jit_backend *base, struct ir *ir,
|
||||||
*addr = code;
|
*addr = code;
|
||||||
*size = (int)(e.getCurr<uint8_t *>() - code);
|
*size = (int)(e.getCurr<uint8_t *>() - code);
|
||||||
|
|
||||||
PROF_LEAVE();
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,10 @@
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "core/assert.h"
|
#include "core/assert.h"
|
||||||
#include "core/profiler.h"
|
|
||||||
#include "jit/jit.h"
|
#include "jit/jit.h"
|
||||||
#include "jit/jit_guest.h"
|
#include "jit/jit_guest.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_COUNTER(edges_patched);
|
|
||||||
DEFINE_COUNTER(edges_restored);
|
|
||||||
|
|
||||||
/* log out pc each time dispatch is entered for debugging */
|
/* log out pc each time dispatch is entered for debugging */
|
||||||
#define LOG_DISPATCH_EVERY_N 0
|
#define LOG_DISPATCH_EVERY_N 0
|
||||||
|
|
||||||
|
@ -39,8 +35,6 @@ void x64_dispatch_restore_edge(struct jit_backend *base, void *code,
|
||||||
uint32_t dst) {
|
uint32_t dst) {
|
||||||
struct x64_backend *backend = container_of(base, struct x64_backend, base);
|
struct x64_backend *backend = container_of(base, struct x64_backend, base);
|
||||||
|
|
||||||
prof_counter_add(COUNTER_edges_restored, 1);
|
|
||||||
|
|
||||||
Xbyak::CodeGenerator e(32, code);
|
Xbyak::CodeGenerator e(32, code);
|
||||||
e.call(backend->dispatch_static);
|
e.call(backend->dispatch_static);
|
||||||
}
|
}
|
||||||
|
@ -48,8 +42,6 @@ void x64_dispatch_restore_edge(struct jit_backend *base, void *code,
|
||||||
void x64_dispatch_patch_edge(struct jit_backend *base, void *code, void *dst) {
|
void x64_dispatch_patch_edge(struct jit_backend *base, void *code, void *dst) {
|
||||||
struct x64_backend *backend = container_of(base, struct x64_backend, base);
|
struct x64_backend *backend = container_of(base, struct x64_backend, base);
|
||||||
|
|
||||||
prof_counter_add(COUNTER_edges_patched, 1);
|
|
||||||
|
|
||||||
Xbyak::CodeGenerator e(32, code);
|
Xbyak::CodeGenerator e(32, code);
|
||||||
e.jmp(dst);
|
e.jmp(dst);
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,8 +133,6 @@ static void sh4_frontend_translate_code(struct jit_frontend *base,
|
||||||
struct sh4_guest *guest = (struct sh4_guest *)frontend->guest;
|
struct sh4_guest *guest = (struct sh4_guest *)frontend->guest;
|
||||||
struct sh4_context *ctx = (struct sh4_context *)guest->ctx;
|
struct sh4_context *ctx = (struct sh4_context *)guest->ctx;
|
||||||
|
|
||||||
PROF_ENTER("cpu", "sh4_frontend_translate_code");
|
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
int use_fpscr = 0;
|
int use_fpscr = 0;
|
||||||
int was_delay = 0;
|
int was_delay = 0;
|
||||||
|
@ -271,8 +269,6 @@ static void sh4_frontend_translate_code(struct jit_frontend *base,
|
||||||
ir_alloc_i32(ir, ctx->fpscr & (PR_MASK | SZ_MASK));
|
ir_alloc_i32(ir, ctx->fpscr & (PR_MASK | SZ_MASK));
|
||||||
ir_assert_eq(ir, actual, expected);
|
ir_assert_eq(ir, actual, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
PROF_LEAVE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sh4_frontend_analyze_code(struct jit_frontend *base,
|
static void sh4_frontend_analyze_code(struct jit_frontend *base,
|
||||||
|
|
|
@ -100,8 +100,6 @@ static int jit_is_stale(struct jit *jit, struct jit_block *block) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void jit_patch_edges(struct jit *jit, struct jit_block *block) {
|
static void jit_patch_edges(struct jit *jit, struct jit_block *block) {
|
||||||
PROF_ENTER("cpu", "jit_patch_edges");
|
|
||||||
|
|
||||||
/* patch incoming edges to this block to directly jump to it instead of
|
/* patch incoming edges to this block to directly jump to it instead of
|
||||||
going through dispatch */
|
going through dispatch */
|
||||||
list_for_each_entry(edge, &block->in_edges, struct jit_edge, in_it) {
|
list_for_each_entry(edge, &block->in_edges, struct jit_edge, in_it) {
|
||||||
|
@ -120,13 +118,9 @@ static void jit_patch_edges(struct jit *jit, struct jit_block *block) {
|
||||||
edge->dst->host_addr);
|
edge->dst->host_addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PROF_LEAVE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void jit_restore_edges(struct jit *jit, struct jit_block *block) {
|
static void jit_restore_edges(struct jit *jit, struct jit_block *block) {
|
||||||
PROF_ENTER("cpu", "jit_restore_edges");
|
|
||||||
|
|
||||||
/* restore any patched branches to go back through dispatch */
|
/* restore any patched branches to go back through dispatch */
|
||||||
list_for_each_entry(edge, &block->in_edges, struct jit_edge, in_it) {
|
list_for_each_entry(edge, &block->in_edges, struct jit_edge, in_it) {
|
||||||
if (edge->patched) {
|
if (edge->patched) {
|
||||||
|
@ -135,8 +129,6 @@ static void jit_restore_edges(struct jit *jit, struct jit_block *block) {
|
||||||
edge->dst->guest_addr);
|
edge->dst->guest_addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PROF_LEAVE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void jit_invalidate_block(struct jit *jit, struct jit_block *block,
|
static void jit_invalidate_block(struct jit *jit, struct jit_block *block,
|
||||||
|
@ -338,8 +330,6 @@ static void jit_promote_fastmem(struct jit *jit, struct jit_block *block,
|
||||||
}
|
}
|
||||||
|
|
||||||
void jit_compile_code(struct jit *jit, uint32_t guest_addr) {
|
void jit_compile_code(struct jit *jit, uint32_t guest_addr) {
|
||||||
PROF_ENTER("cpu", "jit_compile_block");
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
LOG_INFO("jit_compile_block %s 0x%08x", jit->tag, guest_addr);
|
LOG_INFO("jit_compile_block %s 0x%08x", jit->tag, guest_addr);
|
||||||
#endif
|
#endif
|
||||||
|
@ -397,7 +387,6 @@ void jit_compile_code(struct jit *jit, uint32_t guest_addr) {
|
||||||
try to compile again */
|
try to compile again */
|
||||||
LOG_INFO("backend overflow, resetting code cache");
|
LOG_INFO("backend overflow, resetting code cache");
|
||||||
jit_free_code(jit);
|
jit_free_code(jit);
|
||||||
PROF_LEAVE();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,8 +404,6 @@ void jit_compile_code(struct jit *jit, uint32_t guest_addr) {
|
||||||
(uintptr_t)block->host_addr, block->host_size, jit->tag,
|
(uintptr_t)block->host_addr, block->host_size, jit->tag,
|
||||||
block->guest_addr);
|
block->guest_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
PROF_LEAVE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int jit_handle_exception(void *data, struct exception_state *ex) {
|
static int jit_handle_exception(void *data, struct exception_state *ex) {
|
||||||
|
|
|
@ -1,349 +0,0 @@
|
||||||
#ifdef HAVE_MICROPROFILE
|
|
||||||
#define MICROPROFILE_WEBSERVER 0
|
|
||||||
#define MICROPROFILE_GPU_TIMERS 0
|
|
||||||
#define MICROPROFILE_ENABLED 1
|
|
||||||
#define MICROPROFILEUI_ENABLED 1
|
|
||||||
#define MICROPROFILE_IMPL 1
|
|
||||||
#define MICROPROFILEUI_IMPL 1
|
|
||||||
#define MICROPROFILE_PER_THREAD_BUFFER_SIZE (1024 * 1024 * 20)
|
|
||||||
#define MICROPROFILE_CONTEXT_SWITCH_TRACE 0
|
|
||||||
#include <microprofile/microprofile.h>
|
|
||||||
#include <microprofile/microprofileui.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include "core/assert.h"
|
|
||||||
#include "core/math.h"
|
|
||||||
#include "microprofile.h"
|
|
||||||
#include "render/render_backend.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
static const int FONT_WIDTH = 1024;
|
|
||||||
static const int FONT_HEIGHT = 9;
|
|
||||||
#include "microprofile_font.inc"
|
|
||||||
|
|
||||||
static const int MAX_2D_VERTICES = 32768;
|
|
||||||
static const int MAX_2D_SURFACES = 256;
|
|
||||||
|
|
||||||
struct microprofile {
|
|
||||||
struct render_backend *r;
|
|
||||||
|
|
||||||
texture_handle_t font_texture;
|
|
||||||
struct ui_surface surfs[MAX_2D_SURFACES];
|
|
||||||
int num_surfs;
|
|
||||||
struct ui_vertex verts[MAX_2D_VERTICES];
|
|
||||||
int num_verts;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct microprofile *s_mp;
|
|
||||||
|
|
||||||
#define Q0(d, member, v) d[0].member = v
|
|
||||||
#define Q1(d, member, v) \
|
|
||||||
d[1].member = v; \
|
|
||||||
d[3].member = v
|
|
||||||
#define Q2(d, member, v) d[4].member = v
|
|
||||||
#define Q3(d, member, v) \
|
|
||||||
d[2].member = v; \
|
|
||||||
d[5].member = v
|
|
||||||
|
|
||||||
static struct ui_vertex *mp_alloc_verts(struct microprofile *mp,
|
|
||||||
const struct ui_surface &desc,
|
|
||||||
int count) {
|
|
||||||
#ifdef HAVE_MICROPROFILE
|
|
||||||
CHECK(mp->num_verts + count <= MAX_2D_VERTICES);
|
|
||||||
uint32_t first_vert = mp->num_verts;
|
|
||||||
mp->num_verts += count;
|
|
||||||
|
|
||||||
/* try to batch with the last surface if possible */
|
|
||||||
if (mp->num_surfs) {
|
|
||||||
struct ui_surface &last_surf = mp->surfs[mp->num_surfs - 1];
|
|
||||||
|
|
||||||
if (last_surf.prim_type == desc.prim_type &&
|
|
||||||
last_surf.texture == desc.texture &&
|
|
||||||
last_surf.src_blend == desc.src_blend &&
|
|
||||||
last_surf.dst_blend == desc.dst_blend) {
|
|
||||||
last_surf.num_verts += count;
|
|
||||||
return &mp->verts[first_vert];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* else, allocate a new surface */
|
|
||||||
CHECK(mp->num_surfs < MAX_2D_SURFACES);
|
|
||||||
struct ui_surface &next_surf = mp->surfs[mp->num_surfs];
|
|
||||||
next_surf.prim_type = desc.prim_type;
|
|
||||||
next_surf.texture = desc.texture;
|
|
||||||
next_surf.src_blend = desc.src_blend;
|
|
||||||
next_surf.dst_blend = desc.dst_blend;
|
|
||||||
next_surf.scissor = false;
|
|
||||||
next_surf.first_vert = first_vert;
|
|
||||||
next_surf.num_verts = count;
|
|
||||||
mp->num_surfs++;
|
|
||||||
return &mp->verts[first_vert];
|
|
||||||
#endif
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mp_draw_text(struct microprofile *mp, int x, int y, uint32_t color,
|
|
||||||
const char *text) {
|
|
||||||
#ifdef HAVE_MICROPROFILE
|
|
||||||
float fx = static_cast<float>(x);
|
|
||||||
float fy = static_cast<float>(y);
|
|
||||||
float fy2 = fy + (MICROPROFILE_TEXT_HEIGHT + 1);
|
|
||||||
int text_len = static_cast<int>(strlen(text));
|
|
||||||
|
|
||||||
struct ui_vertex *vertex = mp_alloc_verts(mp, {PRIM_TRIANGLES,
|
|
||||||
mp->font_texture,
|
|
||||||
BLEND_SRC_ALPHA,
|
|
||||||
BLEND_ONE_MINUS_SRC_ALPHA,
|
|
||||||
false,
|
|
||||||
{0.0f, 0.0f, 0.0f, 0.0f},
|
|
||||||
0,
|
|
||||||
0},
|
|
||||||
6 * text_len);
|
|
||||||
|
|
||||||
for (int i = 0; i < text_len; i++) {
|
|
||||||
float fx2 = fx + MICROPROFILE_TEXT_WIDTH;
|
|
||||||
float fu = s_font_offsets[static_cast<int>(text[i])] /
|
|
||||||
static_cast<float>(FONT_WIDTH);
|
|
||||||
float fu2 = fu + MICROPROFILE_TEXT_WIDTH / static_cast<float>(FONT_WIDTH);
|
|
||||||
|
|
||||||
Q0(vertex, xy[0], fx);
|
|
||||||
Q0(vertex, xy[1], fy);
|
|
||||||
Q0(vertex, color, color);
|
|
||||||
Q0(vertex, uv[0], fu);
|
|
||||||
Q0(vertex, uv[1], 0.0f);
|
|
||||||
|
|
||||||
Q1(vertex, xy[0], fx2);
|
|
||||||
Q1(vertex, xy[1], fy);
|
|
||||||
Q1(vertex, color, color);
|
|
||||||
Q1(vertex, uv[0], fu2);
|
|
||||||
Q1(vertex, uv[1], 0.0f);
|
|
||||||
|
|
||||||
Q2(vertex, xy[0], fx2);
|
|
||||||
Q2(vertex, xy[1], fy2);
|
|
||||||
Q2(vertex, color, color);
|
|
||||||
Q2(vertex, uv[0], fu2);
|
|
||||||
Q2(vertex, uv[1], 1.0f);
|
|
||||||
|
|
||||||
Q3(vertex, xy[0], fx);
|
|
||||||
Q3(vertex, xy[1], fy2);
|
|
||||||
Q3(vertex, color, color);
|
|
||||||
Q3(vertex, uv[0], fu);
|
|
||||||
Q3(vertex, uv[1], 1.0f);
|
|
||||||
|
|
||||||
fx = fx2 + 1.0f;
|
|
||||||
|
|
||||||
vertex += 6;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mp_draw_box(struct microprofile *mp, int x0, int y0, int x1, int y1,
|
|
||||||
uint32_t color, enum box_type type) {
|
|
||||||
#ifdef HAVE_MICROPROFILE
|
|
||||||
struct ui_vertex *vertex = mp_alloc_verts(mp, {PRIM_TRIANGLES,
|
|
||||||
0,
|
|
||||||
BLEND_SRC_ALPHA,
|
|
||||||
BLEND_ONE_MINUS_SRC_ALPHA,
|
|
||||||
false,
|
|
||||||
{0.0f, 0.0f, 0.0f, 0.0f},
|
|
||||||
0,
|
|
||||||
0},
|
|
||||||
6);
|
|
||||||
|
|
||||||
if (type == BOX_FLAT) {
|
|
||||||
Q0(vertex, xy[0], (float)x0);
|
|
||||||
Q0(vertex, xy[1], (float)y0);
|
|
||||||
Q0(vertex, color, color);
|
|
||||||
Q1(vertex, xy[0], (float)x1);
|
|
||||||
Q1(vertex, xy[1], (float)y0);
|
|
||||||
Q1(vertex, color, color);
|
|
||||||
Q2(vertex, xy[0], (float)x1);
|
|
||||||
Q2(vertex, xy[1], (float)y1);
|
|
||||||
Q2(vertex, color, color);
|
|
||||||
Q3(vertex, xy[0], (float)x0);
|
|
||||||
Q3(vertex, xy[1], (float)y1);
|
|
||||||
Q3(vertex, color, color);
|
|
||||||
} else {
|
|
||||||
uint32_t a = (color & 0xff000000) >> 24;
|
|
||||||
uint32_t r = (color & 0xff0000) >> 16;
|
|
||||||
uint32_t g = (color & 0xff00) >> 8;
|
|
||||||
uint32_t b = color & 0xff;
|
|
||||||
uint32_t max = MAX(MAX(MAX(r, g), b), 30u);
|
|
||||||
uint32_t min = MIN(MIN(MIN(r, g), b), 180u);
|
|
||||||
|
|
||||||
uint32_t r0 = 0xff & ((r + max) / 2);
|
|
||||||
uint32_t g0 = 0xff & ((g + max) / 2);
|
|
||||||
uint32_t b0 = 0xff & ((b + max) / 2);
|
|
||||||
uint32_t r1 = 0xff & ((r + min) / 2);
|
|
||||||
uint32_t g1 = 0xff & ((g + min) / 2);
|
|
||||||
uint32_t b1 = 0xff & ((b + min) / 2);
|
|
||||||
uint32_t color0 = (a << 24) | (b0 << 16) | (g0 << 8) | r0;
|
|
||||||
uint32_t color1 = (a << 24) | (b1 << 16) | (g1 << 8) | r1;
|
|
||||||
|
|
||||||
Q0(vertex, xy[0], (float)x0);
|
|
||||||
Q0(vertex, xy[1], (float)y0);
|
|
||||||
Q0(vertex, color, color0);
|
|
||||||
Q1(vertex, xy[0], (float)x1);
|
|
||||||
Q1(vertex, xy[1], (float)y0);
|
|
||||||
Q1(vertex, color, color0);
|
|
||||||
Q2(vertex, xy[0], (float)x1);
|
|
||||||
Q2(vertex, xy[1], (float)y1);
|
|
||||||
Q2(vertex, color, color1);
|
|
||||||
Q3(vertex, xy[0], (float)x0);
|
|
||||||
Q3(vertex, xy[1], (float)y1);
|
|
||||||
Q3(vertex, color, color1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mp_draw_line(struct microprofile *mp, float *verts, int num_verts,
|
|
||||||
uint32_t color) {
|
|
||||||
#ifdef HAVE_MICROPROFILE
|
|
||||||
CHECK(num_verts);
|
|
||||||
|
|
||||||
struct ui_vertex *vertex = mp_alloc_verts(mp, {PRIM_LINES,
|
|
||||||
0,
|
|
||||||
BLEND_SRC_ALPHA,
|
|
||||||
BLEND_ONE_MINUS_SRC_ALPHA,
|
|
||||||
false,
|
|
||||||
{0.0f, 0.0f, 0.0f, 0.0f},
|
|
||||||
0,
|
|
||||||
0},
|
|
||||||
2 * (num_verts - 1));
|
|
||||||
|
|
||||||
for (int i = 0; i < num_verts - 1; ++i) {
|
|
||||||
vertex[0].xy[0] = verts[i * 2];
|
|
||||||
vertex[0].xy[1] = verts[i * 2 + 1];
|
|
||||||
vertex[0].color = color;
|
|
||||||
vertex[1].xy[0] = verts[(i + 1) * 2];
|
|
||||||
vertex[1].xy[1] = verts[(i + 1) * 2 + 1];
|
|
||||||
vertex[1].color = color;
|
|
||||||
vertex += 2;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void mp_render_frame(struct microprofile *mp, int width, int height) {
|
|
||||||
#ifdef HAVE_MICROPROFILE
|
|
||||||
s_mp = mp;
|
|
||||||
|
|
||||||
/* update draw surfaces */
|
|
||||||
MicroProfileDraw(width, height);
|
|
||||||
|
|
||||||
/* render the surfaces */
|
|
||||||
r_viewport(mp->r, 0, 0, width, height);
|
|
||||||
|
|
||||||
r_begin_ui_surfaces(mp->r, mp->verts, mp->num_verts, nullptr, 0);
|
|
||||||
|
|
||||||
for (int i = 0; i < mp->num_surfs; i++) {
|
|
||||||
struct ui_surface *surf = &mp->surfs[i];
|
|
||||||
r_draw_ui_surface(mp->r, surf);
|
|
||||||
}
|
|
||||||
|
|
||||||
r_end_ui_surfaces(mp->r);
|
|
||||||
|
|
||||||
/* reset surfaces */
|
|
||||||
mp->num_surfs = 0;
|
|
||||||
mp->num_verts = 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void mp_mousemove(struct microprofile *mp, int x, int y) {
|
|
||||||
#ifdef HAVE_MICROPROFILE
|
|
||||||
MicroProfileMousePosition(x, y, 0);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void mp_keydown(struct microprofile *mp, enum keycode key, int16_t value) {
|
|
||||||
#ifdef HAVE_MICROPROFILE
|
|
||||||
if (key == K_F2) {
|
|
||||||
if (value > 0) {
|
|
||||||
MicroProfileToggleDisplayMode();
|
|
||||||
}
|
|
||||||
} else if (key == K_MOUSE1) {
|
|
||||||
int down = value > 0;
|
|
||||||
MicroProfileMouseButton(down, 0);
|
|
||||||
} else if (key == K_MOUSE2) {
|
|
||||||
int down = value > 0;
|
|
||||||
MicroProfileMouseButton(0, down);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void mp_destroy(struct microprofile *mp) {
|
|
||||||
#ifdef HAVE_MICROPROFILE
|
|
||||||
r_destroy_texture(mp->r, mp->font_texture);
|
|
||||||
|
|
||||||
free(mp);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
struct microprofile *mp_create(struct render_backend *r) {
|
|
||||||
#ifdef HAVE_MICROPROFILE
|
|
||||||
struct microprofile *mp = reinterpret_cast<struct microprofile *>(
|
|
||||||
calloc(1, sizeof(struct microprofile)));
|
|
||||||
|
|
||||||
mp->r = r;
|
|
||||||
|
|
||||||
/* register and enable cpu and gpu groups by default */
|
|
||||||
uint16_t cpu_group = MicroProfileGetGroup("cpu", MicroProfileTokenTypeCpu);
|
|
||||||
g_MicroProfile.nActiveGroupWanted |= 1ll << cpu_group;
|
|
||||||
|
|
||||||
uint16_t gpu_group = MicroProfileGetGroup("gpu", MicroProfileTokenTypeCpu);
|
|
||||||
g_MicroProfile.nActiveGroupWanted |= 1ll << gpu_group;
|
|
||||||
|
|
||||||
/* render time / average time bars by default */
|
|
||||||
g_MicroProfile.nBars |= MP_DRAW_TIMERS | MP_DRAW_AVERAGE | MP_DRAW_CALL_COUNT;
|
|
||||||
|
|
||||||
/* aggregate stats every 120 frames by default */
|
|
||||||
g_MicroProfile.nAggregateFlip = 120;
|
|
||||||
|
|
||||||
/* register the font texture */
|
|
||||||
mp->font_texture =
|
|
||||||
r_create_texture(mp->r, PXL_RGBA, FILTER_NEAREST, WRAP_CLAMP_TO_EDGE,
|
|
||||||
WRAP_CLAMP_TO_EDGE, 0, FONT_WIDTH, FONT_HEIGHT,
|
|
||||||
reinterpret_cast<const uint8_t *>(s_font_data));
|
|
||||||
|
|
||||||
return mp;
|
|
||||||
#else
|
|
||||||
return NULL;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* microprofile expects the following three functions to be defined, they're
|
|
||||||
called during MicroProfileDraw */
|
|
||||||
#ifdef HAVE_MICROPROFILE
|
|
||||||
void MicroProfileDrawText(int x, int y, uint32_t color, const char *text,
|
|
||||||
uint32_t len) {
|
|
||||||
/* microprofile provides 24-bit rgb values for text color */
|
|
||||||
color = 0xff000000 | color;
|
|
||||||
|
|
||||||
/* convert color from argb -> abgr */
|
|
||||||
color = (color & 0xff000000) | ((color & 0xff) << 16) | (color & 0xff00) |
|
|
||||||
((color & 0xff0000) >> 16);
|
|
||||||
|
|
||||||
mp_draw_text(s_mp, x, y, color, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MicroProfileDrawBox(int x0, int y0, int x1, int y1, uint32_t color,
|
|
||||||
MicroProfileBoxType type) {
|
|
||||||
/* convert color from argb -> abgr */
|
|
||||||
color = (color & 0xff000000) | ((color & 0xff) << 16) | (color & 0xff00) |
|
|
||||||
((color & 0xff0000) >> 16);
|
|
||||||
|
|
||||||
mp_draw_box(s_mp, x0, y0, x1, y1, color, (enum box_type)type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MicroProfileDrawLine2D(uint32_t num_vertices, float *vertices,
|
|
||||||
uint32_t color) {
|
|
||||||
/* microprofile provides 24-bit rgb values for line color */
|
|
||||||
color = 0xff000000 | color;
|
|
||||||
|
|
||||||
/* convert color from argb -> abgr */
|
|
||||||
color = (color & 0xff000000) | ((color & 0xff) << 16) | (color & 0xff00) |
|
|
||||||
((color & 0xff0000) >> 16);
|
|
||||||
|
|
||||||
mp_draw_line(s_mp, vertices, num_vertices, color);
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,17 +0,0 @@
|
||||||
#ifndef MICROPROFILE_IMPL_H
|
|
||||||
#define MICROPROFILE_IMPL_H
|
|
||||||
|
|
||||||
#include "host/keycode.h"
|
|
||||||
|
|
||||||
struct microprofile;
|
|
||||||
struct render_backend;
|
|
||||||
|
|
||||||
struct microprofile *mp_create(struct render_backend *r);
|
|
||||||
void mp_destroy(struct microprofile *mp);
|
|
||||||
|
|
||||||
void mp_keydown(struct microprofile *mp, enum keycode key, int16_t value);
|
|
||||||
void mp_mousemove(struct microprofile *mp, int x, int y);
|
|
||||||
|
|
||||||
void mp_render_frame(struct microprofile *mp, int width, int height);
|
|
||||||
|
|
||||||
#endif
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue