spamming with vu1 packets 2

This commit is contained in:
h4570
2022-07-23 15:55:38 +02:00
parent 17d7634f1d
commit 1ffba47119
6 changed files with 139 additions and 99 deletions
@@ -25,7 +25,7 @@ class DynPipCore {
DynPipProgramsRepository repository; DynPipProgramsRepository repository;
void init(RendererCore* t_core); void init(RendererCore* t_core, const u32& t_packetSize);
/** Force starting VU1 program instead of continueing */ /** Force starting VU1 program instead of continueing */
void clear() { qbufferRenderer.clearLastProgramName(); } void clear() { qbufferRenderer.clearLastProgramName(); }
@@ -36,11 +36,9 @@ class DynPipCore {
*/ */
void initParts(DynPipBag* data); void initParts(DynPipBag* data);
// TODO: TEST!
void renderTEST(DynPipBag** bags, const u32& count);
/** Render 3D via "bags" */ /** Render 3D via "bags" */
void renderPart(DynPipBag* data, const bool& frustumCull = true); void renderPart(DynPipBag** bags, const u32& count,
const bool& frustumCull = true);
/** Get max vert count of VU1 qbuffer (for optimizations) */ /** Get max vert count of VU1 qbuffer (for optimizations) */
u32 getMaxVertCountByParams(const bool& isLightingEnabled, u32 getMaxVertCountByParams(const bool& isLightingEnabled,
@@ -21,15 +21,15 @@ class DynPipRenderer {
DynPipRenderer(); DynPipRenderer();
~DynPipRenderer(); ~DynPipRenderer();
void init(RendererCore* t_core, DynPipProgramsRepository* t_programRepo); void init(RendererCore* t_core, DynPipProgramsRepository* t_programRepo,
const u32& t_packetSize);
void reinitVU1(); void reinitVU1();
void sendObjectData(DynPipBag* bag, M4x4* mvp, void sendObjectData(DynPipBag* bag, M4x4* mvp,
RendererCoreTextureBuffers* texBuffers) const; RendererCoreTextureBuffers* texBuffers) const;
void render(DynPipBag* bag); void render(DynPipBag** bags, const u32& count);
void renderTEST(DynPipBag** bags, const u32& count);
void clearLastProgramName(); void clearLastProgramName();
@@ -41,9 +41,8 @@ class DynPipRenderer {
void uploadPrograms(); void uploadPrograms();
void setDoubleBuffer(); void setDoubleBuffer();
void addBufferDataToPacketTEST(DynPipVU1Program* program, DynPipBag** bags, void addBufferDataToPacket(DynPipVU1Program* program, DynPipBag** bags,
const u32& count); const u32& count);
void addBufferDataToPacket(DynPipVU1Program* program, DynPipBag* bag);
void sendPacket(); void sendPacket();
packet2_t* packets[2]; packet2_t* packets[2];
@@ -24,6 +24,8 @@ class DynamicPipeline : public Renderer3DPipeline {
DynamicPipeline(); DynamicPipeline();
~DynamicPipeline(); ~DynamicPipeline();
static const u32 buffersCount;
DynPipCore core; DynPipCore core;
void init(RendererCore* core); void init(RendererCore* core);
@@ -39,6 +41,14 @@ class DynamicPipeline : public Renderer3DPipeline {
private: private:
RendererCore* rendererCore; RendererCore* rendererCore;
Vec4* colorsCache; Vec4* colorsCache;
DynPipBag* buffers;
static const u32 halfBuffersCount;
void setBuffer(DynPipBag* buffers, DynPipBag* buffer, u16* bufferIndex,
const DynPipFrustumCulling& frustumCulling);
void sendRestOfBuffers(DynPipBag* buffers, u16* bufferIndex,
const DynPipFrustumCulling& frustumCulling);
void addVertices(MeshMaterialFrame* materialFrameFrom, void addVertices(MeshMaterialFrame* materialFrameFrom,
MeshMaterialFrame* materialFrameTo, DynPipBag* bag, MeshMaterialFrame* materialFrameTo, DynPipBag* bag,
@@ -19,9 +19,9 @@ DynPipCore::DynPipCore() {}
DynPipCore::~DynPipCore() {} DynPipCore::~DynPipCore() {}
void DynPipCore::init(RendererCore* t_core) { void DynPipCore::init(RendererCore* t_core, const u32& t_packetSize) {
rendererCore = t_core; rendererCore = t_core;
qbufferRenderer.init(t_core, &repository); qbufferRenderer.init(t_core, &repository, t_packetSize);
} }
void DynPipCore::reinitVU1Programs() { qbufferRenderer.reinitVU1(); } void DynPipCore::reinitVU1Programs() { qbufferRenderer.reinitVU1(); }
@@ -46,41 +46,54 @@ void DynPipCore::initParts(DynPipBag* bag) {
delete texBuffers; delete texBuffers;
} }
void DynPipCore::renderTEST(DynPipBag** bags, const u32& count) { void DynPipCore::renderPart(DynPipBag** bags, const u32& count,
qbufferRenderer.renderTEST(bags, count); const bool& frustumCull) {
} if (count <= 0) return;
void DynPipCore::renderPart(DynPipBag* bag, const bool& frustumCull) {
if (bag->count <= 0) return;
TYRA_ASSERT(bag->verticesFrom != nullptr && bag->verticesTo != nullptr,
"Vertices are required in 3D render bag!");
TYRA_ASSERT(bag->info != nullptr, "Info bag is required in 3D render bag!");
TYRA_ASSERT(bag->info->model != nullptr,
"Info bag's model pointer is empty!");
TYRA_ASSERT(bag->color != nullptr, "Color bag is required in 3D render bag!");
TYRA_ASSERT(bag->color->single, "Color is required in 3D render bag!");
TYRA_ASSERT( TYRA_ASSERT(
!bag->lighting || bags[0]->verticesFrom != nullptr && bags[0]->verticesTo != nullptr,
(bag->lighting->lightMatrix && bag->lighting->normalsFrom && "Vertices are required in 3D render bag!");
bag->lighting->normalsTo && bag->lighting->dirLights), TYRA_ASSERT(bags[0]->info != nullptr,
"Info bag is required in 3D render bag!");
TYRA_ASSERT(bags[0]->info->model != nullptr,
"Info bag's model pointer is empty!");
TYRA_ASSERT(bags[0]->color != nullptr,
"Color bag is required in 3D render bag!");
TYRA_ASSERT(bags[0]->color->single, "Color is required in 3D render bag!");
TYRA_ASSERT(
!bags[0]->lighting ||
(bags[0]->lighting->lightMatrix && bags[0]->lighting->normalsFrom &&
bags[0]->lighting->normalsTo && bags[0]->lighting->dirLights),
"If you want lighting, please provide light matrix normals and dir " "If you want lighting, please provide light matrix normals and dir "
"lights!"); "lights!");
TYRA_ASSERT(!bag->texture || TYRA_ASSERT(!bags[0]->texture || (bags[0]->texture->texture &&
(bag->texture->texture && bag->texture->coordinatesFrom && bags[0]->texture->coordinatesFrom &&
bag->texture->coordinatesTo), bags[0]->texture->coordinatesTo),
"If you want texture, please provide texture and coordinates!"); "If you want texture, please provide texture and coordinates!");
if (frustumCull) { if (!frustumCull) {
qbufferRenderer.render(bags, count);
return;
}
DynPipBag** bagsToRender = new DynPipBag*[count];
u32 inserted = 0;
for (u32 i = 0; i < count; i++) {
auto* bag = bags[i];
CoreBBox bbox(bag->verticesTo, bag->count); CoreBBox bbox(bag->verticesTo, bag->count);
if (bbox.isInFrustum(rendererCore->renderer3D.frustumPlanes.getAll(), if (bbox.isInFrustum(rendererCore->renderer3D.frustumPlanes.getAll(),
*bag->info->model) == *bag->info->model) ==
CoreBBoxFrustum::OUTSIDE_FRUSTUM) { CoreBBoxFrustum::OUTSIDE_FRUSTUM) {
return; continue;
} }
bagsToRender[inserted++] = bag;
} }
qbufferRenderer.render(bag); qbufferRenderer.render(bagsToRender, inserted);
delete[] bagsToRender;
} }
} // namespace Tyra } // namespace Tyra
@@ -33,7 +33,8 @@ DynPipRenderer::~DynPipRenderer() {
} }
void DynPipRenderer::init(RendererCore* t_core, void DynPipRenderer::init(RendererCore* t_core,
DynPipProgramsRepository* t_programRepo) { DynPipProgramsRepository* t_programRepo,
const u32& t_packetSize) {
path1 = t_core->getPath1(); path1 = t_core->getPath1();
rendererCore = t_core; rendererCore = t_core;
programsRepo = t_programRepo; programsRepo = t_programRepo;
@@ -41,13 +42,11 @@ void DynPipRenderer::init(RendererCore* t_core,
dma_channel_initialize(DMA_CHANNEL_VIF1, NULL, 0); dma_channel_initialize(DMA_CHANNEL_VIF1, NULL, 0);
dma_channel_fast_waits(DMA_CHANNEL_VIF1); dma_channel_fast_waits(DMA_CHANNEL_VIF1);
const u32 VU1_PACKET_SIZE = 256;
packets[0] = packets[0] =
packet2_create(VU1_PACKET_SIZE, P2_TYPE_NORMAL, P2_MODE_CHAIN, true); packet2_create(t_packetSize, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
packets[1] = packets[1] =
packet2_create(VU1_PACKET_SIZE, P2_TYPE_NORMAL, P2_MODE_CHAIN, true); packet2_create(t_packetSize, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
setProgramsCache(); setProgramsCache();
@@ -137,47 +136,28 @@ void DynPipRenderer::sendObjectData(
// dma_channel_send_packet2(objectDataPacket, DMA_CHANNEL_VIF1, true); // dma_channel_send_packet2(objectDataPacket, DMA_CHANNEL_VIF1, true);
} }
void DynPipRenderer::render(DynPipBag* bag) { void DynPipRenderer::render(DynPipBag** bags, const u32& count) {
auto* program = programsRepo->getProgramByBag(bag);
addBufferDataToPacket(program, bag);
sendPacket();
}
void DynPipRenderer::renderTEST(DynPipBag** bags, const u32& count) {
if (count <= 0) return; if (count <= 0) return;
auto* program = programsRepo->getProgramByBag(bags[0]); auto* program = programsRepo->getProgramByBag(bags[0]);
addBufferDataToPacketTEST(program, bags, count); addBufferDataToPacket(program, bags, count);
sendPacket(); sendPacket();
} }
void DynPipRenderer::addBufferDataToPacketTEST(DynPipVU1Program* program, void DynPipRenderer::addBufferDataToPacket(DynPipVU1Program* program,
DynPipBag** bags, DynPipBag** bags, const u32& count) {
const u32& count) {
currentPacket = packets[context]; currentPacket = packets[context];
packet2_reset(currentPacket, false); packet2_reset(currentPacket, false);
u32 sent = 0;
for (u32 i = 0; i < count; i++) { for (u32 i = 0; i < count; i++) {
if (bags[i]->count <= 0) continue;
program->addBufferDataToPacket(currentPacket, bags[i], program->addBufferDataToPacket(currentPacket, bags[i],
&rendererCore->gs.prim); &rendererCore->gs.prim);
sent++;
} }
if (lastProgramName != program->getName()) { if (sent == 0) return;
packet2_utils_vu_add_start_program(currentPacket,
program->getDestinationAddress());
lastProgramName = program->getName();
} else {
packet2_utils_vu_add_continue_program(currentPacket);
}
packet2_utils_vu_add_end_tag(currentPacket);
}
void DynPipRenderer::addBufferDataToPacket(DynPipVU1Program* program,
DynPipBag* bag) {
currentPacket = packets[context];
packet2_reset(currentPacket, false);
program->addBufferDataToPacket(currentPacket, bag, &rendererCore->gs.prim);
if (lastProgramName != program->getName()) { if (lastProgramName != program->getName()) {
packet2_utils_vu_add_start_program(currentPacket, packet2_utils_vu_add_start_program(currentPacket,
@@ -193,9 +173,6 @@ void DynPipRenderer::sendPacket() {
dma_channel_wait(DMA_CHANNEL_VIF1, 0); dma_channel_wait(DMA_CHANNEL_VIF1, 0);
dma_channel_send_packet2(currentPacket, DMA_CHANNEL_VIF1, true); dma_channel_send_packet2(currentPacket, DMA_CHANNEL_VIF1, true);
// TODO
// TYRA_LOG(packet2_get_qw_count(currentPacket));
// Switch packet, so we can proceed during DMA transfer // Switch packet, so we can proceed during DMA transfer
context = !context; context = !context;
} }
@@ -12,19 +12,28 @@
namespace Tyra { namespace Tyra {
DynamicPipeline::DynamicPipeline() { colorsCache = new Vec4[4]; } const u32 DynamicPipeline::buffersCount = 64;
const u32 DynamicPipeline::halfBuffersCount = buffersCount / 2;
DynamicPipeline::~DynamicPipeline() { delete[] colorsCache; } DynamicPipeline::DynamicPipeline() {
colorsCache = new Vec4[4];
buffers = new DynPipBag[buffersCount];
}
DynamicPipeline::~DynamicPipeline() {
delete[] colorsCache;
for (u32 i = 0; i < buffersCount; i++) freeBuffer(&buffers[i]);
delete[] buffers;
}
void DynamicPipeline::init(RendererCore* t_core) { void DynamicPipeline::init(RendererCore* t_core) {
rendererCore = t_core; rendererCore = t_core;
core.init(t_core); auto packetSize = buffersCount * 3.1F;
core.init(t_core, static_cast<u32>(packetSize));
} }
void DynamicPipeline::onUse() { core.reinitVU1Programs(); } void DynamicPipeline::onUse() { core.reinitVU1Programs(); }
#define BUFFER_COUNT 64
void DynamicPipeline::render(DynamicMesh* mesh, const DynPipOptions* options) { void DynamicPipeline::render(DynamicMesh* mesh, const DynPipOptions* options) {
auto model = mesh->getModelMatrix(); auto model = mesh->getModelMatrix();
auto* infoBag = getInfoBag(mesh, options, &model); auto* infoBag = getInfoBag(mesh, options, &model);
@@ -48,8 +57,7 @@ void DynamicPipeline::render(DynamicMesh* mesh, const DynPipOptions* options) {
options->lighting->directionalDirections); options->lighting->directionalDirections);
} }
DynPipBag buffers[BUFFER_COUNT]; u16 bufferIndex = 0;
u8 context = 0;
setBuffersDefaultVars(buffers, mesh, infoBag); setBuffersDefaultVars(buffers, mesh, infoBag);
core.clear(); core.clear();
@@ -72,7 +80,7 @@ void DynamicPipeline::render(DynamicMesh* mesh, const DynPipOptions* options) {
u8 isPartInitialized = false; u8 isPartInitialized = false;
for (u32 k = 0; k < partsCount; k++) { for (u32 k = 0; k < partsCount; k++) {
auto& buffer = buffers[context++]; auto& buffer = buffers[bufferIndex];
freeBuffer(&buffer); freeBuffer(&buffer);
buffer.count = k == partsCount - 1 buffer.count = k == partsCount - 1
@@ -91,31 +99,19 @@ void DynamicPipeline::render(DynamicMesh* mesh, const DynPipOptions* options) {
isPartInitialized = true; isPartInitialized = true;
} }
// core.renderPart(&buffer, frustumCulling == setBuffer(buffers, &buffer, &bufferIndex, frustumCulling);
// DynPipFrustumCulling_Precise);
if (context == BUFFER_COUNT / 2 || context == BUFFER_COUNT) {
DynPipBag** sendBuffers = new DynPipBag*[BUFFER_COUNT / 2];
for (u32 i = 0; i < BUFFER_COUNT / 2; i++) {
sendBuffers[i] = &buffers[context - ((BUFFER_COUNT / 2) - i)];
}
core.renderTEST(sendBuffers, BUFFER_COUNT / 2);
delete[] sendBuffers;
if (context == BUFFER_COUNT) context = 0;
}
} }
delete colorBag; delete colorBag;
} }
// TODO: Refactor (define itd, wywalic te wszystkie TEST i poprawic) sendRestOfBuffers(buffers, &bufferIndex, frustumCulling);
// TODO: Rozmiar pakietu VU1 na podstawie rozmiaru buforow
// TODO: Dorenderowac brakujace (np gdy context == 1-buffersize-1 itd)
// TODO: Program renderujacy w VU1
// TODO: Github: Ten sam myk zrobic w static pipeline?
for (u32 i = 0; i < BUFFER_COUNT; i++) freeBuffer(&buffers[i]); // TODO: Program renderujacy w VU1
// TODO: Github: Ten sam myk zrobic w static pipeline
// TODO: Github: Ten sam myk zrobic w mc pipeline
// TODO: Github: Allocate dynamic pipeline memory only in "onUse"
// (core,qbuffrenderer,pipeline..)
if (dirLights) { if (dirLights) {
delete dirLights; delete dirLights;
@@ -124,10 +120,57 @@ void DynamicPipeline::render(DynamicMesh* mesh, const DynPipOptions* options) {
delete infoBag; delete infoBag;
} }
void DynamicPipeline::setBuffer(DynPipBag* buffers, DynPipBag* buffer,
u16* bufferIndex,
const DynPipFrustumCulling& frustumCulling) {
auto isHalf = *bufferIndex == halfBuffersCount - 1;
auto isFull = *bufferIndex == buffersCount - 1;
if (isHalf || isFull) {
u32 offset = isHalf ? 0 : halfBuffersCount;
DynPipBag** sendBuffers = new DynPipBag*[halfBuffersCount];
for (u32 i = 0; i < halfBuffersCount; i++)
sendBuffers[i] = &buffers[offset + i];
core.renderPart(sendBuffers, halfBuffersCount,
frustumCulling == DynPipFrustumCulling_Precise);
delete[] sendBuffers;
}
if (isFull)
*bufferIndex = 0;
else
*bufferIndex += 1;
}
void DynamicPipeline::sendRestOfBuffers(
DynPipBag* buffers, u16* bufferIndex,
const DynPipFrustumCulling& frustumCulling) {
auto isHalf = *bufferIndex == halfBuffersCount - 1;
u32 offset = isHalf ? 0 : halfBuffersCount;
u32 size = *bufferIndex - offset;
if (size <= 0) return;
DynPipBag** sendBuffers = new DynPipBag*[size];
for (u32 i = 0; i < size; i++) {
sendBuffers[i] = &buffers[offset + i];
}
core.renderPart(sendBuffers, size,
frustumCulling == DynPipFrustumCulling_Precise);
delete[] sendBuffers;
}
void DynamicPipeline::setBuffersDefaultVars(DynPipBag* buffers, void DynamicPipeline::setBuffersDefaultVars(DynPipBag* buffers,
DynamicMesh* mesh, DynamicMesh* mesh,
PipelineInfoBag* infoBag) { PipelineInfoBag* infoBag) {
for (int i = 0; i < BUFFER_COUNT; i++) { for (u32 i = 0; i < buffersCount; i++) {
buffers[i].info = infoBag; buffers[i].info = infoBag;
buffers[i].interpolation = mesh->getAnimState().interpolation; buffers[i].interpolation = mesh->getAnimState().interpolation;
} }
@@ -135,7 +178,7 @@ void DynamicPipeline::setBuffersDefaultVars(DynPipBag* buffers,
void DynamicPipeline::setBuffersColorBag(DynPipBag* buffers, void DynamicPipeline::setBuffersColorBag(DynPipBag* buffers,
DynPipColorBag* colorBag) { DynPipColorBag* colorBag) {
for (int i = 0; i < BUFFER_COUNT; i++) { for (u32 i = 0; i < buffersCount; i++) {
buffers[i].color = colorBag; buffers[i].color = colorBag;
} }
} }