Merge pull request #74 from h4570/feature/renderer
New VU1 renderer, added VCL preprocessor
This commit is contained in:
+4
-2
@@ -35,8 +35,10 @@ all: $(EE_OBJS)
|
||||
ar rcs $(LIB_NAME) $(EE_OBJS)
|
||||
rm -f $(EE_OBJS)
|
||||
|
||||
# https://github.com/microsoft/wsl/issues/2468#issuecomment-374904520
|
||||
#%.vsm: %.vcl # sudo service binfmt-support start
|
||||
#%.vcl: %.vclpp
|
||||
# $(EE_VCLPP) $< $@
|
||||
|
||||
#%.vsm: %.vcl
|
||||
# $(EE_VCL) $< >> $@
|
||||
|
||||
%.o: %.vsm
|
||||
|
||||
@@ -5,6 +5,7 @@ EE_CFLAGS := -DHAVE_LIBPNG -DHAVE_ZLIB $(EE_CFLAGS)
|
||||
EE_CXXFLAGS := -DHAVE_LIBPNG -DHAVE_ZLIB $(EE_CXXFLAGS)
|
||||
EE_DVP = dvp-as
|
||||
EE_VCL = vcl
|
||||
EE_VCLPP = vclpp
|
||||
LIB_NAME = libtyra.a
|
||||
|
||||
include $(PS2SDK)/samples/Makefile.pref
|
||||
|
||||
@@ -134,8 +134,8 @@ private:
|
||||
VifSender *vifSender;
|
||||
packet2_t *flipPacket;
|
||||
color_t worldColor;
|
||||
void allocateBuffers(float t_screenW, float t_screenH);
|
||||
void initDrawingEnv(float t_screenW, float t_screenH);
|
||||
void allocateBuffers(int t_screenW, int t_screenH);
|
||||
void initDrawingEnv();
|
||||
void setPrim();
|
||||
};
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ public:
|
||||
|
||||
// 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 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:
|
||||
Light *light;
|
||||
@@ -50,7 +50,6 @@ private:
|
||||
*/
|
||||
Matrix modelViewProj;
|
||||
u8 context;
|
||||
packet2_t *matricesPacket __attribute__((aligned(64)));
|
||||
VECTOR position, rotation;
|
||||
u32 vertCount;
|
||||
};
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
static const float GS_CENTER = 4096.0F;
|
||||
static const float SCREEN_CENTER = GS_CENTER / 2.0F;
|
||||
|
||||
/** Initialize DMA<->GIF channel
|
||||
* Allocate buffers
|
||||
* Initialize screen
|
||||
@@ -35,19 +38,19 @@ Renderer::Renderer(u32 t_packetSize, ScreenSettings *t_screen)
|
||||
PRINT_LOG("Initializing renderer");
|
||||
dma_channel_initialize(DMA_CHANNEL_GIF, NULL, 0); // Initialize DMA to enable data transfer
|
||||
dma_channel_fast_waits(DMA_CHANNEL_GIF);
|
||||
screen = t_screen;
|
||||
context = 0;
|
||||
isTextureVRAMAllocated = false;
|
||||
isVSyncEnabled = true;
|
||||
isFrameEmpty = false;
|
||||
lastTextureId = 0;
|
||||
flipPacket = packet2_create(4, P2_TYPE_UNCACHED_ACCL, P2_MODE_NORMAL, 0);
|
||||
allocateBuffers(t_screen->width, t_screen->height);
|
||||
initDrawingEnv(t_screen->width, t_screen->height);
|
||||
allocateBuffers((int)t_screen->width, (int)t_screen->height);
|
||||
initDrawingEnv();
|
||||
setPrim();
|
||||
worldColor.r = 0x10;
|
||||
worldColor.g = 0x10;
|
||||
worldColor.b = 0x10;
|
||||
screen = t_screen;
|
||||
gifSender = new GifSender(t_packetSize, t_screen, &light);
|
||||
vifSender = new VifSender(&light);
|
||||
perspective.setPerspective(*t_screen);
|
||||
@@ -142,7 +145,7 @@ void Renderer::draw(Sprite &t_sprite)
|
||||
beginFrameIfNeeded();
|
||||
changeTexture(texture);
|
||||
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_gs_add_texbuff_clut(packet2, &textureBuffer, &t_sprite.clut);
|
||||
draw_enable_blending();
|
||||
@@ -151,7 +154,8 @@ void Renderer::draw(Sprite &t_sprite)
|
||||
draw_primitive_xyoffset(
|
||||
packet2->next,
|
||||
0,
|
||||
(2048 - (screen->width / 2)), (2048 - (screen->height / 2))));
|
||||
SCREEN_CENTER - (screen->width / 2.0F),
|
||||
SCREEN_CENTER - (screen->height / 2.0F)));
|
||||
draw_disable_blending();
|
||||
packet2_update(packet2, draw_finish(packet2->next));
|
||||
dma_channel_wait(DMA_CHANNEL_GIF, 0);
|
||||
@@ -160,14 +164,14 @@ void Renderer::draw(Sprite &t_sprite)
|
||||
}
|
||||
|
||||
/** Initializes drawing environment (1st app packet) */
|
||||
void Renderer::initDrawingEnv(float t_screenW, float t_screenH)
|
||||
void Renderer::initDrawingEnv()
|
||||
{
|
||||
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_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));
|
||||
dma_channel_send_packet2(packet2, DMA_CHANNEL_GIF, true);
|
||||
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 */
|
||||
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].height = (u16)t_screenH;
|
||||
frameBuffers[0].width = (unsigned int)t_screenW;
|
||||
frameBuffers[0].height = (unsigned int)t_screenH;
|
||||
frameBuffers[0].mask = 0;
|
||||
frameBuffers[0].psm = GS_PSM_24;
|
||||
frameBuffers[0].address = graph_vram_allocate((u16)t_screenW, (u16)t_screenH, frameBuffers[0].psm, GRAPH_ALIGN_PAGE);
|
||||
frameBuffers[0].psm = GS_PSM_32;
|
||||
frameBuffers[0].address = graph_vram_allocate(t_screenW, t_screenH, frameBuffers[0].psm, GRAPH_ALIGN_PAGE);
|
||||
|
||||
frameBuffers[1].width = (u16)t_screenW;
|
||||
frameBuffers[1].height = (u16)t_screenH;
|
||||
frameBuffers[1].width = (unsigned int)t_screenW;
|
||||
frameBuffers[1].height = (unsigned int)t_screenH;
|
||||
frameBuffers[1].mask = 0;
|
||||
frameBuffers[1].psm = GS_PSM_24;
|
||||
frameBuffers[1].address = graph_vram_allocate((u16)t_screenW, (u16)t_screenH, frameBuffers[1].psm, GRAPH_ALIGN_PAGE);
|
||||
frameBuffers[1].psm = GS_PSM_32;
|
||||
frameBuffers[1].address = graph_vram_allocate(t_screenW, t_screenH, frameBuffers[1].psm, GRAPH_ALIGN_PAGE);
|
||||
|
||||
zBuffer.enable = DRAW_ENABLE;
|
||||
zBuffer.mask = 0;
|
||||
zBuffer.method = ZTEST_METHOD_GREATER_EQUAL;
|
||||
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!");
|
||||
|
||||
// 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
|
||||
@@ -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)
|
||||
{
|
||||
beginFrameIfNeeded();
|
||||
vifSender->sendMatrices(renderData, t_mesh.position, t_mesh.rotation);
|
||||
vifSender->calcMatrix(renderData, t_mesh.position, t_mesh.rotation);
|
||||
if (!t_mesh.isDataLoaded())
|
||||
PRINT_ERR("Can't draw, because no mesh data was loaded!");
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
#include "../include/utils/debug.hpp"
|
||||
|
||||
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_PACKET_SIZE = 128;
|
||||
const u32 VU1_PACKAGES_PER_PACKET = 9;
|
||||
const u32 VU1_PACKET_SIZE = 256; // should be 128, but 256 is more safe for future
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
@@ -39,7 +39,6 @@ VifSender::VifSender(Light *t_light)
|
||||
uploadMicroProgram();
|
||||
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);
|
||||
matricesPacket = packet2_create(4, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
|
||||
context = 0;
|
||||
setDoubleBuffer();
|
||||
}
|
||||
@@ -48,7 +47,6 @@ VifSender::~VifSender()
|
||||
{
|
||||
packet2_free(packets[0]);
|
||||
packet2_free(packets[1]);
|
||||
packet2_free(matricesPacket);
|
||||
}
|
||||
|
||||
// ----
|
||||
@@ -68,11 +66,9 @@ void VifSender::uploadMicroProgram()
|
||||
dma_channel_send_packet2(packet2, DMA_CHANNEL_VIF1, 1);
|
||||
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.rotate(t_rotation);
|
||||
model.translate(t_position);
|
||||
@@ -81,12 +77,6 @@ void VifSender::sendMatrices(const RenderData &t_renderData, const Vector3 &t_po
|
||||
modelViewProj = model * modelViewProj;
|
||||
modelViewProj = *t_renderData.view * 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)
|
||||
@@ -122,9 +112,9 @@ void VifSender::drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 ver
|
||||
void VifSender::setDoubleBuffer()
|
||||
{
|
||||
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);
|
||||
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);
|
||||
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;
|
||||
u32 vif_added_bytes = 0;
|
||||
packet2_utils_vu_open_unpack(currPacket, 0, 1);
|
||||
// TODO get this via screensettings
|
||||
packet2_add_float(currPacket, 2048.0F); // scale
|
||||
packet2_add_float(currPacket, 2048.0F); // scale
|
||||
packet2_add_float(currPacket, ((float)0xFFFFFF) / 32.0F); // scale
|
||||
packet2_add_u32(currPacket, vertCount); // vertex count
|
||||
packet2_utils_vu_open_unpack(currPacket, 0, true);
|
||||
packet2_add_data(currPacket, modelViewProj.data, 4);
|
||||
packet2_add_u32(currPacket, 0); // Free
|
||||
packet2_add_u32(currPacket, vertCount); // Vertex count
|
||||
packet2_add_u32(currPacket, vertCount / 3); // Triangles count
|
||||
packet2_add_u32(currPacket, 0); // Free
|
||||
packet2_utils_gif_add_set(currPacket, 1);
|
||||
packet2_utils_gs_add_lod(currPacket, &t_mesh.lod);
|
||||
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_add_u32(currPacket, t_mesh.color.r);
|
||||
packet2_add_u32(currPacket, t_mesh.color.g);
|
||||
packet2_add_u32(currPacket, t_mesh.color.b);
|
||||
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);
|
||||
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;
|
||||
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;
|
||||
packet2_utils_vu_add_start_program(currPacket, 0);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -11,63 +11,83 @@
|
||||
.global VU1Draw3D_CodeEnd
|
||||
VU1Draw3D_CodeStart:
|
||||
__v_draw3D_vcl_4:
|
||||
; _LNOPT_w=[ normal2 ] 23 [23 0] 23 [__v_draw3D_vcl_4]
|
||||
NOP lq VF01,0(VI00)
|
||||
NOP xtop VI02
|
||||
NOP lq VF02,1(VI00)
|
||||
NOP lq VF06,1(VI02)
|
||||
NOP lq VF09,2(VI02)
|
||||
NOP lq VF08,3(VI02)
|
||||
NOP lq VF07,4(VI02)
|
||||
NOP lq VF03,2(VI00)
|
||||
NOP iaddiu VI03,VI02,0x00000007
|
||||
NOP ilw.w VI07,0(VI02)
|
||||
NOP lq VF04,3(VI00)
|
||||
NOP fcset 0
|
||||
NOP lq.xyz VF05,0(VI02)
|
||||
NOP iadd VI04,VI03,VI07
|
||||
NOP iadd VI06,VI04,VI07
|
||||
NOP sqi VF06,(VI06++)
|
||||
; _LNOPT_w=[ normal2 ] 27 [27 0] 27 [__v_draw3D_vcl_4]
|
||||
NOP xtop VI07
|
||||
NOP lq VF01,0(VI07)
|
||||
NOP ilw.y VI05,4(VI07)
|
||||
NOP lq VF05,5(VI07)
|
||||
NOP lq VF09,6(VI07)
|
||||
NOP lq VF08,7(VI07)
|
||||
NOP lq VF07,8(VI07)
|
||||
NOP lq VF02,1(VI07)
|
||||
NOP iaddiu VI03,VI07,0x0000000a
|
||||
NOP iadd VI04,VI03,VI05
|
||||
NOP lq VF03,2(VI07)
|
||||
NOP iadd VI06,VI04,VI05
|
||||
NOP loi 0x44fff000
|
||||
NOP lq VF04,3(VI07)
|
||||
NOP ilw.z VI02,4(VI07)
|
||||
NOP sqi VF05,(VI06++)
|
||||
NOP sqi VF09,(VI06++)
|
||||
NOP sqi VF06,(VI06++)
|
||||
NOP sqi VF05,(VI06++)
|
||||
NOP sqi VF08,(VI06++)
|
||||
NOP lq VF06,5(VI02)
|
||||
NOP iadd VI05,VI04,VI07
|
||||
NOP lq VF05,9(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 iadd VI07,VI02,VI07
|
||||
vertexLoop:
|
||||
; _LNOPT_w=[ normal2 ] 21 [31 14] 31 [vertexLoop]
|
||||
NOP iaddiu VI07,VI07,0x00000001
|
||||
addi.z VF06,VF00,I iaddiu VI08,VI00,0
|
||||
triangle_loop:
|
||||
; _LNOPT_w=[ normal ] 37 [31 30] 45 [triangle_loop]
|
||||
NOP lq VF07,0(VI03)
|
||||
mulax ACC,VF01,VF07x sq VF06,1(VI06) ; STALL_LATENCY ?3
|
||||
madday ACC,VF02,VF07y lq VF08,0(VI04)
|
||||
maddaz ACC,VF03,VF07z iaddiu VI06,VI06,0x00000003
|
||||
mulax ACC,VF01,VF07x iaddiu VI08,VI08,0x00000001 ; STALL_LATENCY ?3
|
||||
madday ACC,VF02,VF07y NOP
|
||||
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
|
||||
clipw.xyz VF07xyz,VF07w div Q,VF00w,VF07w ; STALL_LATENCY ?3
|
||||
NOP NOP
|
||||
NOP NOP
|
||||
NOP NOP
|
||||
NOP NOP
|
||||
NOP NOP
|
||||
NOP NOP
|
||||
mulq.xyz VF07,VF07,Q fcand VI01,262143
|
||||
mulaw.xyz ACC,VF05,VF00w iaddiu VI03,VI03,0x00000001
|
||||
madd.xyz VF07,VF07,VF05 iaddiu VI04,VI04,0x00000001 ; STALL_LATENCY ?2
|
||||
mulq VF08,VF08,Q isubiu VI07,VI07,1
|
||||
ftoi4.xyz VF07,VF07 iaddiu VI01,VI01,0x00007fff ; STALL_LATENCY ?2
|
||||
NOP isw.w VI01,-1(VI06)
|
||||
NOP sq VF08,-3(VI06)
|
||||
NOP ibne VI07,VI02,vertexLoop
|
||||
NOP sq.xyz VF07,-1(VI06)
|
||||
mulaw.xyz ACC,VF06,VF00w NOP
|
||||
mulq.xyz VF10,VF10,Q NOP
|
||||
mulq VF09,VF09,Q sq VF05,1(VI06)
|
||||
clipw.xyz VF07xyz,VF07w lq VF11,2(VI04)
|
||||
clipw.xyz VF08xyz,VF08w div Q,VF00w,VF07w
|
||||
mulq.xyz VF08,VF08,Q sq VF05,4(VI06)
|
||||
madd.xyz VF09,VF10,VF06 sq VF09,0(VI06)
|
||||
mulq VF10,VF11,Q sq VF05,7(VI06)
|
||||
mulaw.xyz ACC,VF06,VF00w mfir.w VF09,VI07
|
||||
madd.xyz VF08,VF08,VF06 fcand VI01,262143
|
||||
NOP iaddiu VI01,VI01,0x00007fff
|
||||
mulq.xyz VF10,VF07,Q sq VF10,6(VI06)
|
||||
ftoi4.xyz VF09,VF09 mfir.w VF07,VI01
|
||||
ftoi4.xyz VF07,VF08 lq VF11,1(VI04)
|
||||
mulaw.xyz ACC,VF06,VF00w iaddiu VI03,VI03,0x00000003
|
||||
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]
|
||||
NOP xgkick VI05
|
||||
NOP[E] NOP
|
||||
NOP NOP
|
||||
.align 4
|
||||
VU1Draw3D_CodeEnd:
|
||||
; iCount=47
|
||||
; iCount=67
|
||||
; register stats:
|
||||
; 8 VU User integer
|
||||
; 10 VU User floating point
|
||||
; 9 VU User integer
|
||||
; 12 VU User floating point
|
||||
;-------------------------
|
||||
;-------------------------
|
||||
;-------------------------
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user