diff --git a/engine/inc/renderer/3d/pipeline/dynamic/core/dynpip_core.hpp b/engine/inc/renderer/3d/pipeline/dynamic/core/dynpip_core.hpp index 664f717..ffa127b 100644 --- a/engine/inc/renderer/3d/pipeline/dynamic/core/dynpip_core.hpp +++ b/engine/inc/renderer/3d/pipeline/dynamic/core/dynpip_core.hpp @@ -25,7 +25,7 @@ class DynPipCore { DynPipProgramsRepository repository; - void init(RendererCore* t_core); + void init(RendererCore* t_core, const u32& t_packetSize); /** Force starting VU1 program instead of continueing */ void clear() { qbufferRenderer.clearLastProgramName(); } @@ -36,11 +36,9 @@ class DynPipCore { */ void initParts(DynPipBag* data); - // TODO: TEST! - void renderTEST(DynPipBag** bags, const u32& count); - /** 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) */ u32 getMaxVertCountByParams(const bool& isLightingEnabled, diff --git a/engine/inc/renderer/3d/pipeline/dynamic/core/dynpip_renderer.hpp b/engine/inc/renderer/3d/pipeline/dynamic/core/dynpip_renderer.hpp index 8b95cad..bb111c8 100644 --- a/engine/inc/renderer/3d/pipeline/dynamic/core/dynpip_renderer.hpp +++ b/engine/inc/renderer/3d/pipeline/dynamic/core/dynpip_renderer.hpp @@ -21,15 +21,15 @@ class 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 sendObjectData(DynPipBag* bag, M4x4* mvp, RendererCoreTextureBuffers* texBuffers) const; - void render(DynPipBag* bag); - void renderTEST(DynPipBag** bags, const u32& count); + void render(DynPipBag** bags, const u32& count); void clearLastProgramName(); @@ -41,9 +41,8 @@ class DynPipRenderer { void uploadPrograms(); void setDoubleBuffer(); - void addBufferDataToPacketTEST(DynPipVU1Program* program, DynPipBag** bags, - const u32& count); - void addBufferDataToPacket(DynPipVU1Program* program, DynPipBag* bag); + void addBufferDataToPacket(DynPipVU1Program* program, DynPipBag** bags, + const u32& count); void sendPacket(); packet2_t* packets[2]; diff --git a/engine/inc/renderer/3d/pipeline/dynamic/dynamic_pipeline.hpp b/engine/inc/renderer/3d/pipeline/dynamic/dynamic_pipeline.hpp index b3ab7fb..8a53d21 100644 --- a/engine/inc/renderer/3d/pipeline/dynamic/dynamic_pipeline.hpp +++ b/engine/inc/renderer/3d/pipeline/dynamic/dynamic_pipeline.hpp @@ -24,6 +24,8 @@ class DynamicPipeline : public Renderer3DPipeline { DynamicPipeline(); ~DynamicPipeline(); + static const u32 buffersCount; + DynPipCore core; void init(RendererCore* core); @@ -39,6 +41,14 @@ class DynamicPipeline : public Renderer3DPipeline { private: RendererCore* rendererCore; 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, MeshMaterialFrame* materialFrameTo, DynPipBag* bag, diff --git a/engine/src/renderer/3d/pipeline/dynamic/core/dynpip_core.cpp b/engine/src/renderer/3d/pipeline/dynamic/core/dynpip_core.cpp index 4f519d1..df289f3 100644 --- a/engine/src/renderer/3d/pipeline/dynamic/core/dynpip_core.cpp +++ b/engine/src/renderer/3d/pipeline/dynamic/core/dynpip_core.cpp @@ -19,9 +19,9 @@ DynPipCore::DynPipCore() {} DynPipCore::~DynPipCore() {} -void DynPipCore::init(RendererCore* t_core) { +void DynPipCore::init(RendererCore* t_core, const u32& t_packetSize) { rendererCore = t_core; - qbufferRenderer.init(t_core, &repository); + qbufferRenderer.init(t_core, &repository, t_packetSize); } void DynPipCore::reinitVU1Programs() { qbufferRenderer.reinitVU1(); } @@ -46,41 +46,54 @@ void DynPipCore::initParts(DynPipBag* bag) { delete texBuffers; } -void DynPipCore::renderTEST(DynPipBag** bags, const u32& count) { - qbufferRenderer.renderTEST(bags, count); -} +void DynPipCore::renderPart(DynPipBag** bags, const u32& 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( - !bag->lighting || - (bag->lighting->lightMatrix && bag->lighting->normalsFrom && - bag->lighting->normalsTo && bag->lighting->dirLights), + bags[0]->verticesFrom != nullptr && bags[0]->verticesTo != nullptr, + "Vertices are required in 3D render bag!"); + 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 " "lights!"); - TYRA_ASSERT(!bag->texture || - (bag->texture->texture && bag->texture->coordinatesFrom && - bag->texture->coordinatesTo), + TYRA_ASSERT(!bags[0]->texture || (bags[0]->texture->texture && + bags[0]->texture->coordinatesFrom && + bags[0]->texture->coordinatesTo), "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); if (bbox.isInFrustum(rendererCore->renderer3D.frustumPlanes.getAll(), *bag->info->model) == CoreBBoxFrustum::OUTSIDE_FRUSTUM) { - return; + continue; } + + bagsToRender[inserted++] = bag; } - qbufferRenderer.render(bag); + qbufferRenderer.render(bagsToRender, inserted); + delete[] bagsToRender; } } // namespace Tyra diff --git a/engine/src/renderer/3d/pipeline/dynamic/core/dynpip_renderer.cpp b/engine/src/renderer/3d/pipeline/dynamic/core/dynpip_renderer.cpp index 438a7a8..e7ebad9 100644 --- a/engine/src/renderer/3d/pipeline/dynamic/core/dynpip_renderer.cpp +++ b/engine/src/renderer/3d/pipeline/dynamic/core/dynpip_renderer.cpp @@ -33,7 +33,8 @@ DynPipRenderer::~DynPipRenderer() { } void DynPipRenderer::init(RendererCore* t_core, - DynPipProgramsRepository* t_programRepo) { + DynPipProgramsRepository* t_programRepo, + const u32& t_packetSize) { path1 = t_core->getPath1(); rendererCore = t_core; programsRepo = t_programRepo; @@ -41,13 +42,11 @@ void DynPipRenderer::init(RendererCore* t_core, dma_channel_initialize(DMA_CHANNEL_VIF1, NULL, 0); dma_channel_fast_waits(DMA_CHANNEL_VIF1); - const u32 VU1_PACKET_SIZE = 256; - 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] = - packet2_create(VU1_PACKET_SIZE, P2_TYPE_NORMAL, P2_MODE_CHAIN, true); + packet2_create(t_packetSize, P2_TYPE_NORMAL, P2_MODE_CHAIN, true); setProgramsCache(); @@ -137,47 +136,28 @@ void DynPipRenderer::sendObjectData( // dma_channel_send_packet2(objectDataPacket, DMA_CHANNEL_VIF1, true); } -void DynPipRenderer::render(DynPipBag* bag) { - auto* program = programsRepo->getProgramByBag(bag); - addBufferDataToPacket(program, bag); - sendPacket(); -} - -void DynPipRenderer::renderTEST(DynPipBag** bags, const u32& count) { +void DynPipRenderer::render(DynPipBag** bags, const u32& count) { if (count <= 0) return; auto* program = programsRepo->getProgramByBag(bags[0]); - addBufferDataToPacketTEST(program, bags, count); + addBufferDataToPacket(program, bags, count); sendPacket(); } -void DynPipRenderer::addBufferDataToPacketTEST(DynPipVU1Program* program, - DynPipBag** bags, - const u32& count) { +void DynPipRenderer::addBufferDataToPacket(DynPipVU1Program* program, + DynPipBag** bags, const u32& count) { currentPacket = packets[context]; packet2_reset(currentPacket, false); + u32 sent = 0; for (u32 i = 0; i < count; i++) { + if (bags[i]->count <= 0) continue; program->addBufferDataToPacket(currentPacket, bags[i], &rendererCore->gs.prim); + sent++; } - if (lastProgramName != program->getName()) { - 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 (sent == 0) return; if (lastProgramName != program->getName()) { packet2_utils_vu_add_start_program(currentPacket, @@ -193,9 +173,6 @@ void DynPipRenderer::sendPacket() { dma_channel_wait(DMA_CHANNEL_VIF1, 0); 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 context = !context; } diff --git a/engine/src/renderer/3d/pipeline/dynamic/dynamic_pipeline.cpp b/engine/src/renderer/3d/pipeline/dynamic/dynamic_pipeline.cpp index f1bd708..7d42752 100644 --- a/engine/src/renderer/3d/pipeline/dynamic/dynamic_pipeline.cpp +++ b/engine/src/renderer/3d/pipeline/dynamic/dynamic_pipeline.cpp @@ -12,19 +12,28 @@ 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) { rendererCore = t_core; - core.init(t_core); + auto packetSize = buffersCount * 3.1F; + core.init(t_core, static_cast(packetSize)); } void DynamicPipeline::onUse() { core.reinitVU1Programs(); } -#define BUFFER_COUNT 64 - void DynamicPipeline::render(DynamicMesh* mesh, const DynPipOptions* options) { auto model = mesh->getModelMatrix(); auto* infoBag = getInfoBag(mesh, options, &model); @@ -48,8 +57,7 @@ void DynamicPipeline::render(DynamicMesh* mesh, const DynPipOptions* options) { options->lighting->directionalDirections); } - DynPipBag buffers[BUFFER_COUNT]; - u8 context = 0; + u16 bufferIndex = 0; setBuffersDefaultVars(buffers, mesh, infoBag); core.clear(); @@ -72,7 +80,7 @@ void DynamicPipeline::render(DynamicMesh* mesh, const DynPipOptions* options) { u8 isPartInitialized = false; for (u32 k = 0; k < partsCount; k++) { - auto& buffer = buffers[context++]; + auto& buffer = buffers[bufferIndex]; freeBuffer(&buffer); buffer.count = k == partsCount - 1 @@ -91,31 +99,19 @@ void DynamicPipeline::render(DynamicMesh* mesh, const DynPipOptions* options) { isPartInitialized = true; } - // core.renderPart(&buffer, 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; - } + setBuffer(buffers, &buffer, &bufferIndex, frustumCulling); } delete colorBag; } - // TODO: Refactor (define itd, wywalic te wszystkie TEST i poprawic) - // 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? + sendRestOfBuffers(buffers, &bufferIndex, frustumCulling); - 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) { delete dirLights; @@ -124,10 +120,57 @@ void DynamicPipeline::render(DynamicMesh* mesh, const DynPipOptions* options) { 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, DynamicMesh* mesh, PipelineInfoBag* infoBag) { - for (int i = 0; i < BUFFER_COUNT; i++) { + for (u32 i = 0; i < buffersCount; i++) { buffers[i].info = infoBag; buffers[i].interpolation = mesh->getAnimState().interpolation; } @@ -135,7 +178,7 @@ void DynamicPipeline::setBuffersDefaultVars(DynPipBag* buffers, void DynamicPipeline::setBuffersColorBag(DynPipBag* buffers, DynPipColorBag* colorBag) { - for (int i = 0; i < BUFFER_COUNT; i++) { + for (u32 i = 0; i < buffersCount; i++) { buffers[i].color = colorBag; } }