Merge pull request #74 from h4570/feature/renderer

New VU1 renderer, added VCL preprocessor
This commit is contained in:
Michał Mostowik
2020-12-24 14:38:39 +01:00
committed by GitHub
12 changed files with 302 additions and 293 deletions
+4 -2
View File
@@ -35,8 +35,10 @@ all: $(EE_OBJS)
ar rcs $(LIB_NAME) $(EE_OBJS) ar rcs $(LIB_NAME) $(EE_OBJS)
rm -f $(EE_OBJS) rm -f $(EE_OBJS)
# https://github.com/microsoft/wsl/issues/2468#issuecomment-374904520 #%.vcl: %.vclpp
#%.vsm: %.vcl # sudo service binfmt-support start # $(EE_VCLPP) $< $@
#%.vsm: %.vcl
# $(EE_VCL) $< >> $@ # $(EE_VCL) $< >> $@
%.o: %.vsm %.o: %.vsm
+1
View File
@@ -5,6 +5,7 @@ EE_CFLAGS := -DHAVE_LIBPNG -DHAVE_ZLIB $(EE_CFLAGS)
EE_CXXFLAGS := -DHAVE_LIBPNG -DHAVE_ZLIB $(EE_CXXFLAGS) EE_CXXFLAGS := -DHAVE_LIBPNG -DHAVE_ZLIB $(EE_CXXFLAGS)
EE_DVP = dvp-as EE_DVP = dvp-as
EE_VCL = vcl EE_VCL = vcl
EE_VCLPP = vclpp
LIB_NAME = libtyra.a LIB_NAME = libtyra.a
include $(PS2SDK)/samples/Makefile.pref include $(PS2SDK)/samples/Makefile.pref
+2 -2
View File
@@ -134,8 +134,8 @@ private:
VifSender *vifSender; VifSender *vifSender;
packet2_t *flipPacket; packet2_t *flipPacket;
color_t worldColor; color_t worldColor;
void allocateBuffers(float t_screenW, float t_screenH); void allocateBuffers(int t_screenW, int t_screenH);
void initDrawingEnv(float t_screenW, float t_screenH); void initDrawingEnv();
void setPrim(); void setPrim();
}; };
+1 -2
View File
@@ -30,7 +30,7 @@ public:
// TODO refactor // TODO refactor
void drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 vertCount2, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer); void drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 vertCount2, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer);
void sendMatrices(const RenderData &t_renderData, const Vector3 &t_position, const Vector3 &t_rotation); void calcMatrix(const RenderData &t_renderData, const Vector3 &t_position, const Vector3 &t_rotation);
private: private:
Light *light; Light *light;
@@ -50,7 +50,6 @@ private:
*/ */
Matrix modelViewProj; Matrix modelViewProj;
u8 context; u8 context;
packet2_t *matricesPacket __attribute__((aligned(64)));
VECTOR position, rotation; VECTOR position, rotation;
u32 vertCount; u32 vertCount;
}; };
+25 -21
View File
@@ -22,6 +22,9 @@
// Constructors/Destructors // Constructors/Destructors
// ---- // ----
static const float GS_CENTER = 4096.0F;
static const float SCREEN_CENTER = GS_CENTER / 2.0F;
/** Initialize DMA<->GIF channel /** Initialize DMA<->GIF channel
* Allocate buffers * Allocate buffers
* Initialize screen * Initialize screen
@@ -35,19 +38,19 @@ Renderer::Renderer(u32 t_packetSize, ScreenSettings *t_screen)
PRINT_LOG("Initializing renderer"); PRINT_LOG("Initializing renderer");
dma_channel_initialize(DMA_CHANNEL_GIF, NULL, 0); // Initialize DMA to enable data transfer dma_channel_initialize(DMA_CHANNEL_GIF, NULL, 0); // Initialize DMA to enable data transfer
dma_channel_fast_waits(DMA_CHANNEL_GIF); dma_channel_fast_waits(DMA_CHANNEL_GIF);
screen = t_screen;
context = 0; context = 0;
isTextureVRAMAllocated = false; isTextureVRAMAllocated = false;
isVSyncEnabled = true; isVSyncEnabled = true;
isFrameEmpty = false; isFrameEmpty = false;
lastTextureId = 0; lastTextureId = 0;
flipPacket = packet2_create(4, P2_TYPE_UNCACHED_ACCL, P2_MODE_NORMAL, 0); flipPacket = packet2_create(4, P2_TYPE_UNCACHED_ACCL, P2_MODE_NORMAL, 0);
allocateBuffers(t_screen->width, t_screen->height); allocateBuffers((int)t_screen->width, (int)t_screen->height);
initDrawingEnv(t_screen->width, t_screen->height); initDrawingEnv();
setPrim(); setPrim();
worldColor.r = 0x10; worldColor.r = 0x10;
worldColor.g = 0x10; worldColor.g = 0x10;
worldColor.b = 0x10; worldColor.b = 0x10;
screen = t_screen;
gifSender = new GifSender(t_packetSize, t_screen, &light); gifSender = new GifSender(t_packetSize, t_screen, &light);
vifSender = new VifSender(&light); vifSender = new VifSender(&light);
perspective.setPerspective(*t_screen); perspective.setPerspective(*t_screen);
@@ -142,7 +145,7 @@ void Renderer::draw(Sprite &t_sprite)
beginFrameIfNeeded(); beginFrameIfNeeded();
changeTexture(texture); changeTexture(texture);
packet2_t *packet2 = packet2_create(12, P2_TYPE_NORMAL, P2_MODE_NORMAL, 0); packet2_t *packet2 = packet2_create(12, P2_TYPE_NORMAL, P2_MODE_NORMAL, 0);
packet2_update(packet2, draw_primitive_xyoffset(packet2->next, 0, 2048, 2048)); packet2_update(packet2, draw_primitive_xyoffset(packet2->next, 0, SCREEN_CENTER, SCREEN_CENTER));
packet2_utils_gif_add_set(packet2, 1); packet2_utils_gif_add_set(packet2, 1);
packet2_utils_gs_add_texbuff_clut(packet2, &textureBuffer, &t_sprite.clut); packet2_utils_gs_add_texbuff_clut(packet2, &textureBuffer, &t_sprite.clut);
draw_enable_blending(); draw_enable_blending();
@@ -151,7 +154,8 @@ void Renderer::draw(Sprite &t_sprite)
draw_primitive_xyoffset( draw_primitive_xyoffset(
packet2->next, packet2->next,
0, 0,
(2048 - (screen->width / 2)), (2048 - (screen->height / 2)))); SCREEN_CENTER - (screen->width / 2.0F),
SCREEN_CENTER - (screen->height / 2.0F)));
draw_disable_blending(); draw_disable_blending();
packet2_update(packet2, draw_finish(packet2->next)); packet2_update(packet2, draw_finish(packet2->next));
dma_channel_wait(DMA_CHANNEL_GIF, 0); dma_channel_wait(DMA_CHANNEL_GIF, 0);
@@ -160,14 +164,14 @@ void Renderer::draw(Sprite &t_sprite)
} }
/** Initializes drawing environment (1st app packet) */ /** Initializes drawing environment (1st app packet) */
void Renderer::initDrawingEnv(float t_screenW, float t_screenH) void Renderer::initDrawingEnv()
{ {
PRINT_LOG("Initializing drawing environment"); PRINT_LOG("Initializing drawing environment");
u16 halfW = (u16)t_screenW / 2;
u16 halfH = (u16)t_screenH / 2;
packet2_t *packet2 = packet2_create(20, P2_TYPE_NORMAL, P2_MODE_NORMAL, 0); packet2_t *packet2 = packet2_create(20, P2_TYPE_NORMAL, P2_MODE_NORMAL, 0);
packet2_update(packet2, draw_setup_environment(packet2->base, 0, frameBuffers, &(zBuffer))); packet2_update(packet2, draw_setup_environment(packet2->base, 0, frameBuffers, &(zBuffer)));
packet2_update(packet2, draw_primitive_xyoffset(packet2->next, 0, (2048 - halfW), (2048 - halfH))); packet2_update(packet2, draw_primitive_xyoffset(packet2->next, 0,
SCREEN_CENTER - (screen->width / 2.0F),
SCREEN_CENTER - (screen->height / 2.0F)));
packet2_update(packet2, draw_finish(packet2->next)); packet2_update(packet2, draw_finish(packet2->next));
dma_channel_send_packet2(packet2, DMA_CHANNEL_GIF, true); dma_channel_send_packet2(packet2, DMA_CHANNEL_GIF, true);
dma_channel_wait(DMA_CHANNEL_GIF, 0); dma_channel_wait(DMA_CHANNEL_GIF, 0);
@@ -198,29 +202,29 @@ void Renderer::setWorldColor(const color_t &t_rgb)
} }
/** Defines and allocates framebuffers and zbuffer */ /** Defines and allocates framebuffers and zbuffer */
void Renderer::allocateBuffers(float t_screenW, float t_screenH) void Renderer::allocateBuffers(int t_screenW, int t_screenH)
{ {
frameBuffers[0].width = (u16)t_screenW; frameBuffers[0].width = (unsigned int)t_screenW;
frameBuffers[0].height = (u16)t_screenH; frameBuffers[0].height = (unsigned int)t_screenH;
frameBuffers[0].mask = 0; frameBuffers[0].mask = 0;
frameBuffers[0].psm = GS_PSM_24; frameBuffers[0].psm = GS_PSM_32;
frameBuffers[0].address = graph_vram_allocate((u16)t_screenW, (u16)t_screenH, frameBuffers[0].psm, GRAPH_ALIGN_PAGE); frameBuffers[0].address = graph_vram_allocate(t_screenW, t_screenH, frameBuffers[0].psm, GRAPH_ALIGN_PAGE);
frameBuffers[1].width = (u16)t_screenW; frameBuffers[1].width = (unsigned int)t_screenW;
frameBuffers[1].height = (u16)t_screenH; frameBuffers[1].height = (unsigned int)t_screenH;
frameBuffers[1].mask = 0; frameBuffers[1].mask = 0;
frameBuffers[1].psm = GS_PSM_24; frameBuffers[1].psm = GS_PSM_32;
frameBuffers[1].address = graph_vram_allocate((u16)t_screenW, (u16)t_screenH, frameBuffers[1].psm, GRAPH_ALIGN_PAGE); frameBuffers[1].address = graph_vram_allocate(t_screenW, t_screenH, frameBuffers[1].psm, GRAPH_ALIGN_PAGE);
zBuffer.enable = DRAW_ENABLE; zBuffer.enable = DRAW_ENABLE;
zBuffer.mask = 0; zBuffer.mask = 0;
zBuffer.method = ZTEST_METHOD_GREATER_EQUAL; zBuffer.method = ZTEST_METHOD_GREATER_EQUAL;
zBuffer.zsm = GS_ZBUF_24; zBuffer.zsm = GS_ZBUF_24;
zBuffer.address = graph_vram_allocate((u16)t_screenW, (u16)t_screenH, zBuffer.zsm, GRAPH_ALIGN_PAGE); zBuffer.address = graph_vram_allocate(t_screenW, t_screenH, zBuffer.zsm, GRAPH_ALIGN_PAGE);
PRINT_LOG("Framebuffers, zBuffer set and allocated!"); PRINT_LOG("Framebuffers, zBuffer set and allocated!");
// Initialize the screen and tie the first framebuffer to the read circuits. // Initialize the screen and tie the first framebuffer to the read circuits.
graph_initialize(frameBuffers[1].address, frameBuffers[1].width, frameBuffers[1].height, frameBuffers[1].psm, 0, 0); graph_initialize(frameBuffers[0].address, frameBuffers[0].width, frameBuffers[0].height, frameBuffers[0].psm, 0, 0);
} }
/// --- Draw: PATH3 /// --- Draw: PATH3
@@ -273,7 +277,7 @@ void Renderer::draw(Mesh *t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulb
void Renderer::draw(Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount) void Renderer::draw(Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount)
{ {
beginFrameIfNeeded(); beginFrameIfNeeded();
vifSender->sendMatrices(renderData, t_mesh.position, t_mesh.rotation); vifSender->calcMatrix(renderData, t_mesh.position, t_mesh.rotation);
if (!t_mesh.isDataLoaded()) if (!t_mesh.isDataLoaded())
PRINT_ERR("Can't draw, because no mesh data was loaded!"); PRINT_ERR("Can't draw, because no mesh data was loaded!");
+14 -67
View File
@@ -17,8 +17,8 @@
#include "../include/utils/debug.hpp" #include "../include/utils/debug.hpp"
const u32 VU1_PACKAGE_VERTS_PER_BUFF = 96; // Remember to modify buffer size in vu1 also const u32 VU1_PACKAGE_VERTS_PER_BUFF = 96; // Remember to modify buffer size in vu1 also
const u32 VU1_PACKAGES_PER_PACKET = 6; const u32 VU1_PACKAGES_PER_PACKET = 9;
const u32 VU1_PACKET_SIZE = 128; const u32 VU1_PACKET_SIZE = 256; // should be 128, but 256 is more safe for future
// ---- // ----
// Constructors/Destructors // Constructors/Destructors
@@ -39,7 +39,6 @@ VifSender::VifSender(Light *t_light)
uploadMicroProgram(); uploadMicroProgram();
packets[0] = packet2_create(VU1_PACKET_SIZE, P2_TYPE_NORMAL, P2_MODE_CHAIN, true); packets[0] = packet2_create(VU1_PACKET_SIZE, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
packets[1] = packet2_create(VU1_PACKET_SIZE, P2_TYPE_NORMAL, P2_MODE_CHAIN, true); packets[1] = packet2_create(VU1_PACKET_SIZE, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
matricesPacket = packet2_create(4, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
context = 0; context = 0;
setDoubleBuffer(); setDoubleBuffer();
} }
@@ -48,7 +47,6 @@ VifSender::~VifSender()
{ {
packet2_free(packets[0]); packet2_free(packets[0]);
packet2_free(packets[1]); packet2_free(packets[1]);
packet2_free(matricesPacket);
} }
// ---- // ----
@@ -68,11 +66,9 @@ void VifSender::uploadMicroProgram()
dma_channel_send_packet2(packet2, DMA_CHANNEL_VIF1, 1); dma_channel_send_packet2(packet2, DMA_CHANNEL_VIF1, 1);
packet2_free(packet2); packet2_free(packet2);
} }
#include <fastmath.h>
void VifSender::sendMatrices(const RenderData &t_renderData, const Vector3 &t_position, const Vector3 &t_rotation)
{
Matrix model; void VifSender::calcMatrix(const RenderData &t_renderData, const Vector3 &t_position, const Vector3 &t_rotation)
{
model.identity(); model.identity();
model.rotate(t_rotation); model.rotate(t_rotation);
model.translate(t_position); model.translate(t_position);
@@ -81,12 +77,6 @@ void VifSender::sendMatrices(const RenderData &t_renderData, const Vector3 &t_po
modelViewProj = model * modelViewProj; modelViewProj = model * modelViewProj;
modelViewProj = *t_renderData.view * modelViewProj; modelViewProj = *t_renderData.view * modelViewProj;
modelViewProj = *t_renderData.projection * modelViewProj; modelViewProj = *t_renderData.projection * modelViewProj;
packet2_reset(matricesPacket, false);
packet2_utils_vu_add_unpack_data(matricesPacket, 0, &modelViewProj.data, 8, 0);
packet2_utils_vu_add_end_tag(matricesPacket);
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
dma_channel_send_packet2(matricesPacket, DMA_CHANNEL_VIF1, 1);
} }
void VifSender::drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 vertCount2, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer) void VifSender::drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 vertCount2, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer)
@@ -122,9 +112,9 @@ void VifSender::drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 ver
void VifSender::setDoubleBuffer() void VifSender::setDoubleBuffer()
{ {
packet2_t *settings = packet2_create(2, P2_TYPE_NORMAL, P2_MODE_CHAIN, true); packet2_t *settings = packet2_create(2, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
packet2_utils_vu_add_double_buffer(settings, 8, 496); packet2_utils_vu_add_double_buffer(settings, 10, 498);
packet2_utils_vu_add_end_tag(settings); packet2_utils_vu_add_end_tag(settings);
dma_channel_send_packet2(settings, DMA_CHANNEL_VIF1, 1); dma_channel_send_packet2(settings, DMA_CHANNEL_VIF1, true);
dma_channel_wait(DMA_CHANNEL_VIF1, 0); dma_channel_wait(DMA_CHANNEL_VIF1, 0);
packet2_free(settings); packet2_free(settings);
} }
@@ -134,67 +124,24 @@ void VifSender::drawVertices(Mesh &t_mesh, u32 t_start, u32 t_end, VECTOR *t_ver
{ {
const u32 vertCount = t_end - t_start; const u32 vertCount = t_end - t_start;
u32 vif_added_bytes = 0; u32 vif_added_bytes = 0;
packet2_utils_vu_open_unpack(currPacket, 0, 1); packet2_utils_vu_open_unpack(currPacket, 0, true);
// TODO get this via screensettings packet2_add_data(currPacket, modelViewProj.data, 4);
packet2_add_float(currPacket, 2048.0F); // scale packet2_add_u32(currPacket, 0); // Free
packet2_add_float(currPacket, 2048.0F); // scale packet2_add_u32(currPacket, vertCount); // Vertex count
packet2_add_float(currPacket, ((float)0xFFFFFF) / 32.0F); // scale packet2_add_u32(currPacket, vertCount / 3); // Triangles count
packet2_add_u32(currPacket, vertCount); // vertex count packet2_add_u32(currPacket, 0); // Free
packet2_utils_gif_add_set(currPacket, 1); packet2_utils_gif_add_set(currPacket, 1);
packet2_utils_gs_add_lod(currPacket, &t_mesh.lod); packet2_utils_gs_add_lod(currPacket, &t_mesh.lod);
packet2_utils_gs_add_texbuff_clut(currPacket, textureBuffer, &t_mesh.clut); packet2_utils_gs_add_texbuff_clut(currPacket, textureBuffer, &t_mesh.clut);
packet2_utils_gs_add_prim_giftag(currPacket, t_prim, vertCount, DRAW_STQ2_REGLIST, 3, 0); packet2_utils_gs_add_prim_giftag(currPacket, t_prim, vertCount, DRAW_STQ2_REGLIST, 3, 0);
packet2_add_u32(currPacket, t_mesh.color.r); packet2_add_u32(currPacket, t_mesh.color.r);
packet2_add_u32(currPacket, t_mesh.color.g); packet2_add_u32(currPacket, t_mesh.color.g);
packet2_add_u32(currPacket, t_mesh.color.b); packet2_add_u32(currPacket, t_mesh.color.b);
packet2_add_u32(currPacket, t_mesh.color.a); packet2_add_u32(currPacket, t_mesh.color.a);
// Clipping tests start
// // const float minZ = 1;
// // const float maxZ = 65535;
// // const int iGuardDimXY = 2048;
// // vu1.addFloat(1.0F); // f_TODO clipping maybe there is problem?
// // vu1.addFloat(1.0F);
// // vu1.addFloat(1.0F);
// // vu1.addFloat(1.0F);
// // float xClip = (float)2048.0f/(drawContext.GetFBWidth() * 0.5f * 2.0f);
// // packet += Math::Max( xClip, 1.0f );
// // float yClip = (float)2048.0f/(drawContext.GetFBHeight() * 0.5f * 2.0f);
// // packet += Math::Max( yClip, 1.0f );
// // float depthClip = 2048.0f / depthClipToGs;
// // // F_FIXME: maybe these 2048's should be 2047.5s...
// // depthClip *= 1.003f; // round up a bit for fp error (????)
// // packet += depthClip;
// // // enable/disable clipping
// // packet += (drawContext.GetDoClipping()) ? 1 : 0;
// u32 depthBits = 24; // or 28(fog) or 16
// float depthClipToGs = (float)((1 << depthBits) - 1) / 2.0f;
// vu1.addFloat(2048.0f / (640.0F * 0.5f * 2.0f));
// vu1.addFloat(2048.0f / (480.0F * 0.5f * 2.0f));
// vu1.addFloat((2048.0f / depthClipToGs) * 1.003F);
// // vu1.addFloat(2048.0F); // scale
// // vu1.addFloat(2048.0F); // scale
// // vu1.addFloat(((float)0xFFFFFF) / 32.0F); // scale
// vu1.addFloat(0.0F);
// // vu1.addFloat(0.5f * iGuardDimXY);
// // vu1.addFloat(-0.5f * iGuardDimXY);
// // vu1.addFloat(1.0F);
// // vu1.addFloat(500.0F); // far
packet2_add_float(currPacket, 0.0F);
packet2_add_float(currPacket, 0.0F);
packet2_add_float(currPacket, 0.0F);
packet2_add_float(currPacket, 0.0F);
//// Clipping tests end
vif_added_bytes += packet2_utils_vu_close_unpack(currPacket); vif_added_bytes += packet2_utils_vu_close_unpack(currPacket);
packet2_utils_vu_add_unpack_data(currPacket, vif_added_bytes, t_vertices + t_start, vertCount, 1); packet2_utils_vu_add_unpack_data(currPacket, vif_added_bytes, t_vertices + t_start, vertCount, true);
vif_added_bytes += vertCount; vif_added_bytes += vertCount;
packet2_utils_vu_add_unpack_data(currPacket, vif_added_bytes, t_coordinates + t_start, vertCount, 1); packet2_utils_vu_add_unpack_data(currPacket, vif_added_bytes, t_coordinates + t_start, vertCount, true);
vif_added_bytes += vertCount; vif_added_bytes += vertCount;
packet2_utils_vu_add_start_program(currPacket, 0); packet2_utils_vu_add_start_program(currPacket, 0);
} }
-154
View File
@@ -1,154 +0,0 @@
; ______ ____ ___
; | \/ ____| |___|
; | | | \ | |
;---------------------------
; Copyright 2020, tyra - https://github.com/h4570/tyra
; Sandro Sobczyński <sandro.sobczynski@gmail.com>
;
;---------------------------------------------------------------
; draw3D.vcl |
;---------------------------------------------------------------
; A VU1 microprogram to draw 3D object using XYZ2, RGBAQ and ST|
; This program uses double buffering (xtop) |
; |
; Many thanks to: |
; - Dr Henry Fortuna |
; - Jesper Svennevid, Daniel Collin |
; - Guilherme Lampert |
;---------------------------------------------------------------
; TODO
; - Fix vertex clipping (is clipping visible triangles :/)
; - Move lerp() from EE to VU1 (performance)
; - Add dynamic lighting (feature)
; - Add --cont + MSCNT instead of alltime MSCAL (performance)
.syntax new
.name VU1Draw3D
.vu
.init_vf_all
.init_vi_all
--enter
--endenter
;//////////// --- Load data 1 --- /////////////
; Updated once per frame
lq matrixRow0, 0(vi00) ; load view-projection matrix
lq matrixRow1, 1(vi00)
lq matrixRow2, 2(vi00)
lq matrixRow3, 3(vi00)
;/////////////////////////////////////////////
fcset 0x000000 ; VCL won't let us use CLIP without first zeroing
; the clip flags
;//////////// --- Load data 2 --- /////////////
; Updated dynamically
xtop iBase
lq.xyz scale, 0(iBase) ; load program params
; float : X, Y, Z - scale vector that we will use to scale the verts after projecting them.
; float : W - vert count.
lq gifSetTag, 1(iBase) ; GIF tag - set
lq texGifTag1, 2(iBase) ; GIF tag - texture LOD
lq texGifTag2, 3(iBase) ; GIF tag - texture buffer & CLUT
lq primTag, 4(iBase) ; GIF tag - tell GS how many data we will send
lq rgba, 5(iBase) ; RGBA
;lq clipScale, 6(iBase) ; TODO clipping tests
; u32 : R, G, B, A (0-128)
iaddiu vertexData, iBase, 7 ; pointer to vertex data
ilw.w vertCount, 0(iBase) ; load vert count from scale vector
iadd stqData, vertexData, vertCount ; pointer to stq
iadd kickAddress, stqData, vertCount ; pointer for XGKICK
iadd destAddress, stqData, vertCount ; helper pointer for data inserting
;////////////////////////////////////////////
;/////////// --- Store tags --- /////////////
sqi gifSetTag, (destAddress++) ;
sqi texGifTag1, (destAddress++) ; texture LOD tag
sqi gifSetTag, (destAddress++) ;
sqi texGifTag2, (destAddress++) ; texture buffer & CLUT tag
sqi primTag, (destAddress++) ; prim + tell gs how many data will be
;////////////////////////////////////////////
;/////////////// --- Loop --- ///////////////
iadd vertexCounter, iBase, vertCount ; loop vertCount times
vertexLoop:
;////////// --- Load loop data --- //////////
lq vertex, 0(vertexData) ; load xyz
; float : X, Y, Z
; any32 : _ = 0
lq stq, 0(stqData) ; load stq
; float : S, T
; any32 : Q = 1 ; 1, because we will mul this by 1/vert[w] and this
; will be our q for texture perspective correction
; any32 : _ = 0
;////////////////////////////////////////////
;////////////// --- Vertex --- //////////////
mul acc, matrixRow0, vertex[x] ; transform each vertex by the matrix
madd acc, matrixRow1, vertex[y]
madd acc, matrixRow2, vertex[z]
madd vertex, matrixRow3, vertex[w]
;add.z acc, vf0, clipScale[w] ; TODO clipping maybe this?
;madd.z clipVec, clipScale, vertex
;mul.xy clipVec, clipScale, vertex
;mul.w clipVec, vf0, vertex[z]
;mul.xyz clipVec, vertex, clipScale ; TODO clipping maybe this?
clipw.xyz vertex, vertex ; Dr. Fortuna: This instruction checks if the vertex is outside
; the viewing frustum. If it is, then the appropriate
; clipping flags are set
fcand VI01, 0x3FFFF ; Bitwise AND the clipping flags with 0x3FFFF, this makes
; sure that we get the clipping judgement for the last three
; verts (i.e. that make up the triangle we are about to draw)
iaddiu iADC, VI01, 0x7FFF ; Add 0x7FFF. If any of the clipping flags were set this will
; cause the triangle not to be drawn (any values above 0x8000
; that are stored in the w component of XYZ2 will set the ADC
; bit, which tells the GS not to perform a drawing kick on this
; triangle.
;ilw.w iNoDraw, UVStart(Counter) ; Load the iNoDraw flag. If true we should set the ADC bit so the vert isn't drawn
;iadd iADC, iADC, iNoDraw ; TODO clipping maybe this?
isw.w iADC, 2(destAddress)
div q, vf00[w], vertex[w] ; perspective divide (1/vert[w]):
mul.xyz vertex, vertex, q
mula.xyz acc, scale, vf00[w] ; scale to GS screen space
madd.xyz vertex, vertex, scale ; multiply and add the scales -> vert = vert * scale + scale
ftoi4.xyz vertex, vertex ; convert vertex to 12:4 fixed point format
;////////////////////////////////////////////
;//////////////// --- ST --- ////////////////
mulq modStq, stq, q
;////////////////////////////////////////////
;//////////// --- Store data --- ////////////
sq modStq, 0(destAddress) ; STQ
sq rgba, 1(destAddress) ; RGBA ; q is grabbed from stq
sq.xyz vertex, 2(destAddress) ; XYZ2
;////////////////////////////////////////////
iaddiu vertexData, vertexData, 1
iaddiu stqData, stqData, 1
iaddiu destAddress, destAddress, 3
iaddi vertexCounter, vertexCounter, -1 ; decrement the loop counter
ibne vertexCounter, iBase, vertexLoop ; and repeat if needed
;////////////////////////////////////////////
--barrier
xgkick kickAddress ; dispatch to the GS rasterizer.
--exit
--endexit
+143
View File
@@ -0,0 +1,143 @@
; ______ ____ ___
; | \/ ____| |___|
; | | | \ | |
;---------------------------
; Copyright 2020, tyra - https://github.com/h4570/tyra
; Sandro Sobczyński <sandro.sobczynski@gmail.com>
;
;---------------------------------------------------------------
; draw3D.vcl |
;---------------------------------------------------------------
; First tyra VU1 microprogram. |
; Features: |
; - Draw triangles (no strip) with STQ (textures) and 1 RGBA. |
; This program uses double buffering (xtop) |
; |
; I want to say thank you to: |
; - Dr Henry Fortuna - for teaching how things work |
; - Jesper Svennevid, Daniel Collin - for openvcl samples |
; - Guilherme Lampert - for VU1 idea for PS2 Quake and vclpp |
; - Tyler Daniel - for PS2GL source code for PS2 Linux |
;---------------------------------------------------------------
; TODO
; - Add dynamic lighting (feature)
; - Add --cont + MSCNT instead of alltime MSCAL
#include "/repos/tyra/src/engine/vu1_progs/geometry.inc"
#include "/repos/tyra/src/engine/vu1_progs/matrix.inc"
#include "/repos/tyra/src/engine/vu1_progs/vector.inc"
#vuprog draw3D
.syntax new
.name VU1Draw3D
.vu
.init_vf_all
.init_vi_all
--enter
--endenter
xtop double_buffer
;//////// LOAD CURRENT BUFFER DATA //////////
MatrixLoad{ matrix, 0, double_buffer }
ilw.z triangles_count, 4(double_buffer) ; Triangles count
ilw.y vertex_count, 4(double_buffer) ; Vertex count
lq gif_set_tag, 5(double_buffer) ; GIF tag - set
lq tex_gif_tag_1, 6(double_buffer) ; GIF tag - texture LOD
lq tex_gif_tag_2, 7(double_buffer) ; GIF tag - texture buffer & CLUT
lq prim_tag, 8(double_buffer) ; GIF tag - tell GS how many data we will send
lq rgba, 9(double_buffer) ; Mesh RGBA
iaddiu vertex_data, double_buffer, 10 ; pointer to vertex data
iadd stq_data, vertex_data, vertex_count ; pointer to stq
iadd kick_address, stq_data, vertex_count ; pointer for XGKICK
iadd dest_address, stq_data, vertex_count ; helper pointer for data inserting
;////////////////////////////////////////////
LoadScaleConstant{ gs_scale }
fcset 0x000000 ; VCL won't let us use CLIP without first zeroing the clip flags
;/////////////// STORE TAGS /////////////////
sqi gif_set_tag, (dest_address++) ;
sqi tex_gif_tag_1, (dest_address++) ; texture LOD tag
sqi gif_set_tag, (dest_address++) ;
sqi tex_gif_tag_2, (dest_address++) ; texture buffer & CLUT tag
sqi prim_tag, (dest_address++) ; prim + tell gs how many data will be
;////////////////////////////////////////////
;//////// FIX ADC BIT FOR CLIPPING //////////
iaddiu adc_bit, vi00, 0x7FFF
iaddiu adc_bit, adc_bit, 1
;////////////////////////////////////////////
;/////////// START TRIANGLE LOOP ////////////
iaddiu triangle_counter, vi00, 0 ; Reset counter
triangle_loop: --LoopCS 1,3
;//////////////// VERTEX 1 //////////////////
VectorLoad{ vertex, vertex_data, 0 }
VectorLoad{ stq1, stq_data, 0 }
MatrixXForm{ xformed_vertex, matrix, vertex }
VectorClip{ gs_vertex, xformed_vertex }
VectorPerspectiveDivide{ xformed_vertex }
VectorAddGSScales{ gs_vertex, xformed_vertex, gs_scale }
VectorTexturePerspectiveCorrection{ pers_stq, stq1 }
VectorStore{ pers_stq, dest_address, 0 }
VectorStore{ rgba, dest_address, 1 }
VectorStore{ gs_vertex, dest_address, 2 }
;////////////////////////////////////////////
;//////////////// VERTEX 2 //////////////////
VectorLoad{ vertex, vertex_data, 1 }
VectorLoad{ stq2, stq_data, 1 }
MatrixXForm{ xformed_vertex, matrix, vertex }
VectorClip{ gs_vertex, xformed_vertex }
VectorPerspectiveDivide{ xformed_vertex }
VectorAddGSScales{ gs_vertex, xformed_vertex, gs_scale }
VectorTexturePerspectiveCorrection{ pers_stq, stq2 }
VectorStore{ pers_stq, dest_address, 3 }
VectorStore{ rgba, dest_address, 4 }
VectorStore{ gs_vertex, dest_address, 5 }
;////////////////////////////////////////////
;//////////////// VERTEX 3 //////////////////
VectorLoad{ vertex, vertex_data, 2 }
VectorLoad{ stq3, stq_data, 2 }
MatrixXForm{ xformed_vertex, matrix, vertex }
VectorClip{ gs_vertex, xformed_vertex }
VectorPerspectiveDivide{ xformed_vertex }
VectorAddGSScales{ gs_vertex, xformed_vertex, gs_scale }
VectorTexturePerspectiveCorrection{ pers_stq, stq3 }
VectorStore{ pers_stq, dest_address, 6 }
VectorStore{ rgba, dest_address, 7 }
fcand vi01, 0x03FFFF
iaddiu new_adc_bit, vi01, 0x7FFF
mfir.w gs_vertex, new_adc_bit
VectorStore{ gs_vertex, dest_address, 8 }
;////////////////////////////////////////////
;////////////// LOOP CONTROL ////////////////
iaddiu vertex_data, vertex_data, 3
iaddiu stq_data, stq_data, 3
iaddiu dest_address, dest_address, 9
iaddiu triangle_counter, triangle_counter, 1 // Incrementing this
// by other value than 1 is causing HUGE problems, but.. why?
// My first idea was do vertex_counter and incrementing by 3
ibne triangle_counter, triangles_count, triangle_loop
;////////////////////////////////////////////
;////////////////////////////////////////////
--barrier
xgkick kick_address ; dispatch to the GS rasterizer.
--exit
--endexit
#endvuprog
+65 -45
View File
@@ -11,63 +11,83 @@
.global VU1Draw3D_CodeEnd .global VU1Draw3D_CodeEnd
VU1Draw3D_CodeStart: VU1Draw3D_CodeStart:
__v_draw3D_vcl_4: __v_draw3D_vcl_4:
; _LNOPT_w=[ normal2 ] 23 [23 0] 23 [__v_draw3D_vcl_4] ; _LNOPT_w=[ normal2 ] 27 [27 0] 27 [__v_draw3D_vcl_4]
NOP lq VF01,0(VI00) NOP xtop VI07
NOP xtop VI02 NOP lq VF01,0(VI07)
NOP lq VF02,1(VI00) NOP ilw.y VI05,4(VI07)
NOP lq VF06,1(VI02) NOP lq VF05,5(VI07)
NOP lq VF09,2(VI02) NOP lq VF09,6(VI07)
NOP lq VF08,3(VI02) NOP lq VF08,7(VI07)
NOP lq VF07,4(VI02) NOP lq VF07,8(VI07)
NOP lq VF03,2(VI00) NOP lq VF02,1(VI07)
NOP iaddiu VI03,VI02,0x00000007 NOP iaddiu VI03,VI07,0x0000000a
NOP ilw.w VI07,0(VI02) NOP iadd VI04,VI03,VI05
NOP lq VF04,3(VI00) NOP lq VF03,2(VI07)
NOP fcset 0 NOP iadd VI06,VI04,VI05
NOP lq.xyz VF05,0(VI02) NOP loi 0x44fff000
NOP iadd VI04,VI03,VI07 NOP lq VF04,3(VI07)
NOP iadd VI06,VI04,VI07 NOP ilw.z VI02,4(VI07)
NOP sqi VF06,(VI06++) NOP sqi VF05,(VI06++)
NOP sqi VF09,(VI06++) NOP sqi VF09,(VI06++)
NOP sqi VF06,(VI06++) NOP sqi VF05,(VI06++)
NOP sqi VF08,(VI06++) NOP sqi VF08,(VI06++)
NOP lq VF06,5(VI02) NOP lq VF05,9(VI07)
NOP iadd VI05,VI04,VI07 NOP iaddiu VI07,VI00,0x00007fff
NOP iadd VI05,VI04,VI05
addi.xy VF06,VF00,I loi 0x492aaaaa
NOP fcset 0
NOP sqi VF07,(VI06++) NOP sqi VF07,(VI06++)
NOP iadd VI07,VI02,VI07 NOP iaddiu VI07,VI07,0x00000001
vertexLoop: addi.z VF06,VF00,I iaddiu VI08,VI00,0
; _LNOPT_w=[ normal2 ] 21 [31 14] 31 [vertexLoop] triangle_loop:
; _LNOPT_w=[ normal ] 37 [31 30] 45 [triangle_loop]
NOP lq VF07,0(VI03) NOP lq VF07,0(VI03)
mulax ACC,VF01,VF07x sq VF06,1(VI06) ; STALL_LATENCY ?3 mulax ACC,VF01,VF07x iaddiu VI08,VI08,0x00000001 ; STALL_LATENCY ?3
madday ACC,VF02,VF07y lq VF08,0(VI04) madday ACC,VF02,VF07y NOP
maddaz ACC,VF03,VF07z iaddiu VI06,VI06,0x00000003 maddaz ACC,VF03,VF07z NOP
maddw VF10,VF04,VF07w lq VF08,2(VI03)
mulax ACC,VF01,VF08x div Q,VF00w,VF10w ; STALL_LATENCY ?3
madday ACC,VF02,VF08y NOP
maddaz ACC,VF03,VF08z lq VF07,1(VI03)
maddw VF08,VF04,VF08w NOP
clipw.xyz VF10xyz,VF10w NOP
mulax ACC,VF01,VF07x NOP ; STALL_LATENCY ?1
madday ACC,VF02,VF07y div Q,VF00w,VF08w
maddaz ACC,VF03,VF07z lq VF09,0(VI04)
maddw VF07,VF04,VF07w NOP maddw VF07,VF04,VF07w NOP
clipw.xyz VF07xyz,VF07w div Q,VF00w,VF07w ; STALL_LATENCY ?3 mulaw.xyz ACC,VF06,VF00w NOP
NOP NOP mulq.xyz VF10,VF10,Q NOP
NOP NOP mulq VF09,VF09,Q sq VF05,1(VI06)
NOP NOP clipw.xyz VF07xyz,VF07w lq VF11,2(VI04)
NOP NOP clipw.xyz VF08xyz,VF08w div Q,VF00w,VF07w
NOP NOP mulq.xyz VF08,VF08,Q sq VF05,4(VI06)
NOP NOP madd.xyz VF09,VF10,VF06 sq VF09,0(VI06)
mulq.xyz VF07,VF07,Q fcand VI01,262143 mulq VF10,VF11,Q sq VF05,7(VI06)
mulaw.xyz ACC,VF05,VF00w iaddiu VI03,VI03,0x00000001 mulaw.xyz ACC,VF06,VF00w mfir.w VF09,VI07
madd.xyz VF07,VF07,VF05 iaddiu VI04,VI04,0x00000001 ; STALL_LATENCY ?2 madd.xyz VF08,VF08,VF06 fcand VI01,262143
mulq VF08,VF08,Q isubiu VI07,VI07,1 NOP iaddiu VI01,VI01,0x00007fff
ftoi4.xyz VF07,VF07 iaddiu VI01,VI01,0x00007fff ; STALL_LATENCY ?2 mulq.xyz VF10,VF07,Q sq VF10,6(VI06)
NOP isw.w VI01,-1(VI06) ftoi4.xyz VF09,VF09 mfir.w VF07,VI01
NOP sq VF08,-3(VI06) ftoi4.xyz VF07,VF08 lq VF11,1(VI04)
NOP ibne VI07,VI02,vertexLoop mulaw.xyz ACC,VF06,VF00w iaddiu VI03,VI03,0x00000003
NOP sq.xyz VF07,-1(VI06) madd.xyz VF08,VF10,VF06 iaddiu VI04,VI04,0x00000003
NOP sq VF09,2(VI06)
mulq VF09,VF11,Q sq VF07,8(VI06)
NOP mfir.w VF07,VI07
ftoi4.xyz VF07,VF08 iaddiu VI06,VI06,0x00000009
NOP sq VF09,-6(VI06) ; STALL_LATENCY ?1
NOP ibne VI08,VI02,triangle_loop
NOP sq VF07,-4(VI06)
; _LNOPT_w=[ normal2 ] 3 [1 0] 3 [__v_draw3D_vcl_7] ; _LNOPT_w=[ normal2 ] 3 [1 0] 3 [__v_draw3D_vcl_7]
NOP xgkick VI05 NOP xgkick VI05
NOP[E] NOP NOP[E] NOP
NOP NOP NOP NOP
.align 4 .align 4
VU1Draw3D_CodeEnd: VU1Draw3D_CodeEnd:
; iCount=47 ; iCount=67
; register stats: ; register stats:
; 8 VU User integer ; 9 VU User integer
; 10 VU User floating point ; 12 VU User floating point
;------------------------- ;-------------------------
;------------------------- ;-------------------------
;------------------------- ;-------------------------
+7
View File
@@ -0,0 +1,7 @@
; Load GS offsets to center xformed vertex in gs coord space and color clamping constant
#macro LoadScaleConstant: gs_scale
loi 2047.5
addi.xy gs_scale, vf00, i
loi 699050.625000 // ((float)0xFFFFFF) / 24.0F
addi.z gs_scale, vf00, i
#endmacro
+13
View File
@@ -0,0 +1,13 @@
#macro MatrixLoad: matrix, offset, vumem
lq matrix[0], offset+0(vumem)
lq matrix[1], offset+1(vumem)
lq matrix[2], offset+2(vumem)
lq matrix[3], offset+3(vumem)
#endmacro
#macro MatrixXForm: output_vertex, matrix, input_vertex
mul acc, matrix[0], input_vertex[x]
madd acc, matrix[1], input_vertex[y]
madd acc, matrix[2], input_vertex[z]
madd output_vertex, matrix[3], input_vertex[w]
#endmacro
+27
View File
@@ -0,0 +1,27 @@
#macro VectorPerspectiveDivide: vertex
div q, vf00[w], vertex[w]
mulq.xyz vertex, vertex, q
#endmacro
#macro VectorAddGSScales: output_vertex, input_vertex, gs_scale
mula.xyz acc, gs_scale, vf00[w]
madd.xyz output_vertex, input_vertex, gs_scale
ftoi4.xyz output_vertex, output_vertex
#endmacro
#macro VectorTexturePerspectiveCorrection: output_vertex, input_vertex
mulq output_vertex, input_vertex, q
#endmacro
#macro VectorStore: vertex, vumem, num
sq vertex, num(vumem)
#endmacro
#macro VectorClip: output_vertex, input_vertex
clipw.xyz input_vertex, input_vertex
mfir.w output_vertex, adc_bit
#endmacro
#macro VectorLoad: output_vertex, vumem, offset
lq output_vertex, offset(vumem)
#endmacro