Skip to content

Instantly share code, notes, and snippets.

@Pokechu22
Last active April 17, 2021 03:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Pokechu22/0644659572c92d247ea7c703889015d5 to your computer and use it in GitHub Desktop.
Save Pokechu22/0644659572c92d247ea7c703889015d5 to your computer and use it in GitHub Desktop.
Dolphin normalization special case test - https://github.com/dolphin-emu/dolphin/pull/9315

Adapted from libogc texturetest.

Results:

Hardware:

ProjectionColorNormalization disabledNormalization enabled
XF_TEXPROJ_STNoNo normalizationNormalization
XF_TEXPROJ_STQNoNo normalizationNormalization
XF_TEXPROJ_STYesNo normalizationNormalization
XF_TEXPROJ_STQYesNo normalizationNormalization

Dolphin with this PR/in software renderer:

ProjectionColorNormalization disabledNormalization enabled
XF_TEXPROJ_STNoNo normalizationNo normalization
XF_TEXPROJ_STQNoNo normalizationNormalization
XF_TEXPROJ_STYesNo normalizationNormalization
XF_TEXPROJ_STQYesNo normalizationNormalization

Dolphin if the special case triggered on AB11 instead of XF_TEXPROJ_ST:

ProjectionColorNormalization disabledNormalization enabled
XF_TEXPROJ_STNoNo normalizationNo normalization
XF_TEXPROJ_STQNoNo normalizationNo normalization
XF_TEXPROJ_STYesNo normalizationNormalization
XF_TEXPROJ_STQYesNo normalizationNormalization
#---------------------------------------------------------------------------------
# Clear the implicit built in rules
#---------------------------------------------------------------------------------
.SUFFIXES:
.SECONDARY:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPPC)),)
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
endif
include $(DEVKITPPC)/wii_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := .
DATA :=
TEXTURES := .
INCLUDES :=
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE)
CXXFLAGS = $(CFLAGS)
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -logc -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS :=
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
$(foreach dir,$(TEXTURES),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
#---------------------------------------------------------------------------------
# automatically build a list of object files for our project
#---------------------------------------------------------------------------------
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
SCFFILES := $(foreach dir,$(TEXTURES),$(notdir $(wildcard $(dir)/*.scf)))
TPLFILES := $(SCFFILES:.scf=.tpl)
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
export LD := $(CC)
else
export LD := $(CXX)
endif
export OFILES_BIN := $(addsuffix .o,$(BINFILES)) $(addsuffix .o,$(TPLFILES))
export OFILES_SOURCES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(sFILES:.s=.o) $(SFILES:.S=.o)
export OFILES := $(OFILES_BIN) $(OFILES_SOURCES)
export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES))) $(addsuffix .h,$(subst .,_,$(TPLFILES)))
#---------------------------------------------------------------------------------
# build a list of include paths
#---------------------------------------------------------------------------------
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD) \
-I$(LIBOGC_INC)
#---------------------------------------------------------------------------------
# build a list of library paths
#---------------------------------------------------------------------------------
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
-L$(LIBOGC_LIB)
export OUTPUT := $(CURDIR)/$(TARGET)
.PHONY: $(BUILD) clean
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT).dol: $(OUTPUT).elf
$(OUTPUT).elf: $(OFILES)
$(OFILES_SOURCES) : $(HFILES)
#---------------------------------------------------------------------------------
# This rule links in binary data with the .bin extension
#---------------------------------------------------------------------------------
%.bin.o %_bin.h : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
#---------------------------------------------------------------------------------
%.tpl.o %_tpl.h : %.tpl
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPSDIR)/*.d
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
#---------------------------------------------------------------------------------
run:
wiiload $(TARGET).dol
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <math.h>
#include <gccore.h>
#include <ogc/tpl.h>
#include "textures_tpl.h"
#include "textures.h"
#define DEFAULT_FIFO_SIZE (256*1024)
typedef struct tagcamera {
guVector pos;
guVector up;
guVector view;
}camera;
s16 square[] ATTRIBUTE_ALIGN(32) =
{
// x y z
-30, 30, 0, // 0
30, 30, 0, // 1
30, -30, 0, // 2
-30, -30, 0, // 3
};
// color data
u8 colors[] ATTRIBUTE_ALIGN(32) = {
// r, g, b, a
0, 255, 0, 0, // 0 purple
240, 0, 0, 255, // 1 red
255, 180, 0, 255, // 2 orange
255, 255, 0, 255, // 3 yellow
10, 120, 40, 255, // 4 green
0, 20, 100, 255 // 5 blue
};
static float rotby=0;
static void *xfb = NULL;
static u32 do_copy = GX_FALSE;
GXRModeObj *rmode;
GXTexObj texObj;
TPLFile spriteTPL;
camera cam = {{0.0F, 0.0F, 0.0F},
{0.0F, 1.0F, 0.0F},
{0.0F, 0.0F, -1.0F}};
void draw_init(bool include_color, u32 tgen_type, bool normalize);
void draw_vert(u8 pos, u8 c, f32 s, f32 t);
void draw_square(Mtx v);
static void copy_to_xfb(u32 count);
void movecamera(float speed);
int main() {
Mtx v,p; // view and perspective matrices
GXColor background = {0, 0, 0, 0xff};
VIDEO_Init();
rmode = VIDEO_GetPreferredMode(NULL);
PAD_Init();
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
VIDEO_Configure(rmode);
VIDEO_SetNextFramebuffer(xfb);
VIDEO_SetPostRetraceCallback(copy_to_xfb);
VIDEO_SetBlack(FALSE);
VIDEO_Flush();
VIDEO_WaitVSync();
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
void *gp_fifo = NULL;
gp_fifo = MEM_K0_TO_K1(memalign(32,DEFAULT_FIFO_SIZE));
memset(gp_fifo,0,DEFAULT_FIFO_SIZE);
GX_Init(gp_fifo,DEFAULT_FIFO_SIZE);
GX_SetCopyClear(background, 0x00ffffff);
GX_SetViewport(0,0,rmode->fbWidth,rmode->efbHeight,0,1);
GX_SetDispCopyYScale((f32)rmode->xfbHeight/(f32)rmode->efbHeight);
GX_SetScissor(0,0,rmode->fbWidth,rmode->efbHeight);
GX_SetDispCopySrc(0,0,rmode->fbWidth,rmode->efbHeight);
GX_SetDispCopyDst(rmode->fbWidth,rmode->xfbHeight);
GX_SetCopyFilter(rmode->aa,rmode->sample_pattern,GX_TRUE,rmode->vfilter);
GX_SetFieldMode(rmode->field_rendering,((rmode->viHeight==2*rmode->xfbHeight)?GX_ENABLE:GX_DISABLE));
if (rmode->aa) {
GX_SetPixelFmt(GX_PF_RGB565_Z16, GX_ZC_LINEAR);
} else {
GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);
}
GX_SetCullMode(GX_CULL_NONE);
GX_CopyDisp(xfb,GX_TRUE);
GX_SetDispCopyGamma(GX_GM_1_0);
guPerspective(p, 60, 1.33F, 10.0F, 1000.0F);
GX_LoadProjectionMtx(p, GX_PERSPECTIVE);
GX_InvalidateTexAll();
TPL_OpenTPLFromMemory(&spriteTPL, (void *)textures_tpl,textures_tpl_size);
TPL_GetTexture(&spriteTPL,test_image,&texObj);
GX_LoadTexObj(&texObj, GX_TEXMAP0);
for (u32 type_counter = 0; type_counter < 8; type_counter++) {
printf("Test case %d\n", type_counter);
bool normalize = type_counter & 1;
u32 tgen_type = (type_counter & 2) ? GX_TG_MTX3x4 : GX_TG_MTX2x4;
bool color = type_counter & 4;
draw_init(color, tgen_type, normalize);
for (u32 frame_counter = 0; frame_counter < 30; frame_counter++) {
guLookAt(v, &cam.pos, &cam.up, &cam.view);
GX_SetViewport(0,0,rmode->fbWidth,rmode->efbHeight,0,1);
GX_InvVtxCache();
GX_InvalidateTexAll();
GX_SetTevOp(GX_TEVSTAGE0, GX_DECAL);
GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
GX_SetNumChans(1);
GX_LoadTexObj(&texObj, GX_TEXMAP0);
draw_square(v);
GX_DrawDone();
do_copy = GX_TRUE;
VIDEO_WaitVSync();
PAD_ScanPads();
int stickY = PAD_StickY(0);
if( stickY > 18 || stickY < -18)
movecamera((float) stickY/-18);
if(PAD_ButtonsDown(0) & PAD_BUTTON_START) {
exit(0);
}
}
}
return 0;
}
static bool g_include_color = false;
void draw_init(bool include_color, u32 tgen_type, bool normalize) {
g_include_color = include_color;
GX_ClearVtxDesc();
GX_SetVtxDesc(GX_VA_POS, GX_INDEX8);
if (g_include_color)
GX_SetVtxDesc(GX_VA_CLR0, GX_INDEX8);
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0);
if (g_include_color)
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
GX_SetArray(GX_VA_POS, square, 3*sizeof(s16));
if (g_include_color)
GX_SetArray(GX_VA_CLR0, colors, 4*sizeof(u8));
GX_SetNumTexGens(1);
GX_SetTexCoordGen2(GX_TEXCOORD0, tgen_type, GX_TG_TEX0, GX_IDENTITY, normalize, GX_DTTIDENTITY);
}
void draw_vert(u8 pos, u8 c, f32 s, f32 t) {
GX_Position1x8(pos);
if (g_include_color)
GX_Color1x8(c);
GX_TexCoord2f32(s, t);
}
void draw_square(Mtx v) {
Mtx m; // model matrix.
Mtx mv; // modelview matrix.
guVector axis = {0,0,1};
guMtxIdentity(m);
guMtxRotAxisDeg(m, &axis, rotby);
guMtxTransApply(m, m, 0, 0, -100);
guMtxConcat(v,m,mv);
GX_LoadPosMtxImm(mv, GX_PNMTX0);
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
draw_vert(0, 0, 0.0, 0.0);
draw_vert(1, 0, 2.0, 0.0);
draw_vert(2, 0, 2.0, 2.0);
draw_vert(3, 0, 0.0, 2.0);
GX_End();
}
// copy efb to xfb when ready
static void copy_to_xfb(u32 count) {
if(do_copy==GX_TRUE) {
GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
GX_SetColorUpdate(GX_TRUE);
GX_CopyDisp(xfb,GX_TRUE);
GX_Flush();
do_copy = GX_FALSE;
}
}
void movecamera(float speed) {
guVector v;
v.x = cam.view.x - cam.pos.x;
v.y = cam.view.y - cam.pos.y;
v.z = cam.view.z - cam.pos.z;
cam.pos.x += v.x * speed;
cam.pos.z += v.z * speed;
cam.view.x += v.x * speed;
cam.view.z += v.z * speed;
}
<filepath="test_image.png" id="test_image" colfmt=5 />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment