From 9d18a81c2a96b77f790e8c07ac78459d8e1e6e52 Mon Sep 17 00:00:00 2001 From: h4570 Date: Sun, 24 Jul 2022 12:21:21 +0200 Subject: [PATCH] vu1 packet spamming in static pipeline --- ROADMAP.txt | 11 +- .../3d/pipeline/static/core/stapip_core.hpp | 2 +- .../static/core/stapip_qbuffer_renderer.hpp | 18 ++- .../3d/pipeline/static/static_pipeline.hpp | 6 +- .../core/texture/texture_repository.hpp | 7 +- .../renderer/3d/mesh/static/static_mesh.cpp | 7 +- .../3d/pipeline/static/core/stapip_core.cpp | 2 + .../static/core/stapip_qbuffer_renderer.cpp | 132 ++++++++++++++---- .../3d/pipeline/static/static_pipeline.cpp | 10 +- .../core/texture/texture_repository.cpp | 2 +- samples/h4570/inc/h4570.hpp | 2 + samples/h4570/src/h4570.cpp | 26 ++++ 12 files changed, 173 insertions(+), 52 deletions(-) diff --git a/ROADMAP.txt b/ROADMAP.txt index 1ffc8e1..06048de 100644 --- a/ROADMAP.txt +++ b/ROADMAP.txt @@ -1,6 +1,16 @@ ------------ Tyra's v2.0 roadmap to publish on GitHub ------------ +- [StaPip] FPS before: 175 +- [StaPip] FPS spamming: 190 + --- H4570 +- [Renderer] Fix current visual bug +- [StaPip] Te same parametry frustumcheck jak w dynamic +- [StaPip] No frustum check -> bez +- [StaPip] Simple frustum check -> check bboxa z Mesh +- [StaPip] Precise frustum check -> tak jak teraz? +- [StaPip] Poprawic opis od noFullClipChecks, ze bedzie tylko dzialac na PreciseFrustumCheck +- [Renderer] Allocate dynamic pipeline memory only in "onUse" (core,qbuffrenderer,pipeline..) - [McPip] Clipping mode - [McPip] VU1 packets spamming - [Loaders] Think about ".tyrobj" format - implement it (add multicolor support) @@ -57,4 +67,3 @@ because Mesh rendering uses only core.render() ------------ Github issues for Tyra v2 ------------ - [3D] Add drawLine(x, y , color, size) - [3D] Add drawBBox(x, y , color, size) -- [Renderer] Github: Allocate dynamic pipeline memory only in "onUse" (core,qbuffrenderer,pipeline..) \ No newline at end of file diff --git a/engine/inc/renderer/3d/pipeline/static/core/stapip_core.hpp b/engine/inc/renderer/3d/pipeline/static/core/stapip_core.hpp index 2a7e4e9..33d70c1 100644 --- a/engine/inc/renderer/3d/pipeline/static/core/stapip_core.hpp +++ b/engine/inc/renderer/3d/pipeline/static/core/stapip_core.hpp @@ -27,7 +27,7 @@ class StaPipCore { void init(RendererCore* t_core); /** Render 3D via "bags" */ - void render(StaPipBag* data, StaPipBagPackagesBBox* bbox = nullptr); + void render(StaPipBag* bag, StaPipBagPackagesBBox* bbox = nullptr); /** Get max vert count of VU1 qbuffer (for optimizations) */ u32 getMaxVertCountByParams(const bool& isSingleColor, diff --git a/engine/inc/renderer/3d/pipeline/static/core/stapip_qbuffer_renderer.hpp b/engine/inc/renderer/3d/pipeline/static/core/stapip_qbuffer_renderer.hpp index 9426861..3b1201e 100644 --- a/engine/inc/renderer/3d/pipeline/static/core/stapip_qbuffer_renderer.hpp +++ b/engine/inc/renderer/3d/pipeline/static/core/stapip_qbuffer_renderer.hpp @@ -54,6 +54,8 @@ class StaPipQBufferRenderer { /** Slower render with clipping */ void clip(StaPipQBuffer* buffer); + void flushBuffers(); + void clearLastProgramName(); StaPipVU1Program* getCullProgramByBag(const StaPipBag* bag); @@ -64,22 +66,30 @@ class StaPipQBufferRenderer { const u16& getBufferSize() { return bufferSize; } private: + bool is1stDBufferFlushTime(); + bool is2ndDBufferFlushTime(); + void sendStaticData() const; void setProgramsCache(); void uploadPrograms(); void setDoubleBuffer(); + u16 getQBufferIndex(StaPipQBuffer* buffer); + + static const u16 buffersCount; StaPipVU1Program* getProgramByName(const StaPipProgramName& name); - void addBufferDataToPacket(StaPipVU1Program* program, StaPipQBuffer* buffer); + void addBufferDataToPacket(StaPipQBuffer** buffers, const u32& count); void sendPacket(); StaPipVU1Program* getAsIsProgramByBag(const StaPipBag* bag); StaPipVU1Program* getCullProgramByType(const StaPipProgramType& programType); StaPipProgramType getDrawProgramTypeByBag(const StaPipBag* bag) const; StaPipProgramType getDrawProgramTypeByParams( const bool& isLightingEnabled, const bool& isTextureEnabled) const; - packet2_t* packets[2]; packet2_t* programsPacket; - StaPipQBuffer buffers[2]; + + packet2_t** packets; + StaPipVU1Program** programs; // dbuffer + StaPipQBuffer** buffers; packet2_t* currentPacket; packet2_t* staticDataPacket; packet2_t* objectDataPacket; @@ -91,7 +101,7 @@ class StaPipQBufferRenderer { StaPipClipper clipper; StaPipProgramsRepository repository; - u16 bufferSize; + u16 bufferSize, nextBufferIndex, currentBufferIndex; u8 context; }; diff --git a/engine/inc/renderer/3d/pipeline/static/static_pipeline.hpp b/engine/inc/renderer/3d/pipeline/static/static_pipeline.hpp index 6fca5d4..e3d45ec 100644 --- a/engine/inc/renderer/3d/pipeline/static/static_pipeline.hpp +++ b/engine/inc/renderer/3d/pipeline/static/static_pipeline.hpp @@ -14,7 +14,7 @@ #include "../renderer_3d_pipeline.hpp" #include "../shared/pipeline_lighting_options.hpp" #include "renderer/core/renderer_core.hpp" -#include "renderer/3d/mesh/dynamic/dynamic_mesh.hpp" +#include "renderer/3d/mesh/static/static_mesh.hpp" #include "./core/stapip_core.hpp" #include "./stapip_options.hpp" @@ -43,7 +43,7 @@ class StaticPipeline : public Renderer3DPipeline { * Render static model * This render() method is a bridge to core.render() method. */ - void render(DynamicMesh* mesh, const StaPipOptions* options = nullptr); + void render(StaticMesh* mesh, const StaPipOptions* options = nullptr); private: RendererCore* rendererCore; @@ -51,7 +51,7 @@ class StaticPipeline : public Renderer3DPipeline { void addVertices(MeshMaterialFrame* materialFrame, StaPipBag* bag) const; - PipelineInfoBag* getInfoBag(DynamicMesh* mesh, const StaPipOptions* options, + PipelineInfoBag* getInfoBag(StaticMesh* mesh, const StaPipOptions* options, M4x4* model) const; StaPipColorBag* getColorBag(MeshMaterial* material, diff --git a/engine/inc/renderer/core/texture/texture_repository.hpp b/engine/inc/renderer/core/texture/texture_repository.hpp index 6ab1638..0382337 100644 --- a/engine/inc/renderer/core/texture/texture_repository.hpp +++ b/engine/inc/renderer/core/texture/texture_repository.hpp @@ -14,7 +14,7 @@ #include #include #include "./models/texture.hpp" -#include "renderer/3d/mesh/dynamic/dynamic_mesh.hpp" +#include "renderer/3d/mesh/mesh.hpp" #include "loaders/texture/base/texture_loader_selector.hpp" #include @@ -81,13 +81,12 @@ class TextureRepository { /** * Add linked textures in given path for mesh material names. */ - void addByMesh(DynamicMesh* mesh, const char* directory, - const char* extension); + void addByMesh(Mesh* mesh, const char* directory, const char* extension); /** * Add linked textures in given path for mesh material names. */ - inline void addByMesh(DynamicMesh* mesh, const std::string& directory, + inline void addByMesh(Mesh* mesh, const std::string& directory, const char* extension) { addByMesh(mesh, directory.c_str(), extension); } diff --git a/engine/src/renderer/3d/mesh/static/static_mesh.cpp b/engine/src/renderer/3d/mesh/static/static_mesh.cpp index e324d1d..e1b4392 100644 --- a/engine/src/renderer/3d/mesh/static/static_mesh.cpp +++ b/engine/src/renderer/3d/mesh/static/static_mesh.cpp @@ -14,7 +14,12 @@ namespace Tyra { StaticMesh::StaticMesh(const MeshBuilderData& data) : Mesh(data) { - TYRA_ASSERT(data.framesCount == 1, "Static meshes must have only one frame"); + TYRA_ASSERT(data.framesCount > 0, "Frames count must be greater than 0"); + + if (data.framesCount > 1) + TYRA_WARN("Static meshes should have only one frame, but ", + data.framesCount, " frames were found"); + frame = new MeshFrame(data, 0); } diff --git a/engine/src/renderer/3d/pipeline/static/core/stapip_core.cpp b/engine/src/renderer/3d/pipeline/static/core/stapip_core.cpp index ce1daf5..0027df7 100644 --- a/engine/src/renderer/3d/pipeline/static/core/stapip_core.cpp +++ b/engine/src/renderer/3d/pipeline/static/core/stapip_core.cpp @@ -136,6 +136,8 @@ void StaPipCore::render(StaPipBag* bag, StaPipBagPackagesBBox* bbox) { if (!bbox) delete renderBbox; if (texBuffers) delete texBuffers; + qbufferRenderer.flushBuffers(); + Verbose("Render finished"); } diff --git a/engine/src/renderer/3d/pipeline/static/core/stapip_qbuffer_renderer.cpp b/engine/src/renderer/3d/pipeline/static/core/stapip_qbuffer_renderer.cpp index 4d9efc9..10e4a01 100644 --- a/engine/src/renderer/3d/pipeline/static/core/stapip_qbuffer_renderer.cpp +++ b/engine/src/renderer/3d/pipeline/static/core/stapip_qbuffer_renderer.cpp @@ -34,18 +34,45 @@ namespace Tyra { * */ +const u16 StaPipQBufferRenderer::buffersCount = 16; + StaPipQBufferRenderer::StaPipQBufferRenderer() { + currentBufferIndex = 0; + nextBufferIndex = 0; context = 0; lastProgramName = StaPipUndefinedProgram; + + u32 qbuffersPacketSize = 4 * buffersCount; + + packets = new packet2_t*[buffersCount]; + packets[0] = + packet2_create(qbuffersPacketSize, P2_TYPE_NORMAL, P2_MODE_CHAIN, true); + packets[1] = + packet2_create(qbuffersPacketSize, P2_TYPE_NORMAL, P2_MODE_CHAIN, true); + staticDataPacket = packet2_create(3, P2_TYPE_NORMAL, P2_MODE_CHAIN, true); objectDataPacket = packet2_create(16, P2_TYPE_NORMAL, P2_MODE_CHAIN, true); + programsPacket = nullptr; + + buffers = new StaPipQBuffer*[buffersCount]; + programs = new StaPipVU1Program*[buffersCount]; + for (u16 i = 0; i < buffersCount; i++) { + buffers[i] = new StaPipQBuffer(); + } } StaPipQBufferRenderer::~StaPipQBufferRenderer() { - packet2_free(packets[0]); - packet2_free(packets[1]); packet2_free(staticDataPacket); packet2_free(objectDataPacket); + packet2_free(packets[0]); + packet2_free(packets[1]); + + for (u16 i = 0; i < buffersCount; i++) { + delete buffers[i]; + } + + delete[] packets; + delete[] buffers; if (programsPacket) packet2_free(programsPacket); } @@ -58,14 +85,6 @@ void StaPipQBufferRenderer::init(RendererCore* t_core) { dma_channel_initialize(DMA_CHANNEL_VIF1, NULL, 0); dma_channel_fast_waits(DMA_CHANNEL_VIF1); - const u32 VU1_PACKET_SIZE = 16; - - 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); - setProgramsCache(); reinitVU1(); @@ -79,8 +98,6 @@ void StaPipQBufferRenderer::reinitVU1() { setDoubleBuffer(); } -StaPipQBuffer* StaPipQBufferRenderer::getBuffer() { return &buffers[context]; } - void StaPipQBufferRenderer::sendObjectData( StaPipBag* bag, M4x4* mvp, RendererCoreTextureBuffers* texBuffers) const { packet2_reset(objectDataPacket, false); @@ -179,14 +196,59 @@ void StaPipQBufferRenderer::setDoubleBuffer() { // buffer, to first addr of second buffer } +StaPipQBuffer* StaPipQBufferRenderer::getBuffer() { + currentBufferIndex = nextBufferIndex++; + auto* result = buffers[currentBufferIndex]; + if (nextBufferIndex >= buffersCount) nextBufferIndex = 0; + return result; +} + +u16 StaPipQBufferRenderer::getQBufferIndex(StaPipQBuffer* buffer) { + for (u16 i = 0; i < buffersCount; i++) { + if (buffers[i] == buffer) return i; + } + return 0; +} + +bool StaPipQBufferRenderer::is1stDBufferFlushTime() { + return nextBufferIndex == buffersCount / 2; +} + +bool StaPipQBufferRenderer::is2ndDBufferFlushTime() { + return nextBufferIndex == 0; +} + +void StaPipQBufferRenderer::flushBuffers() { + auto is1stDBuffer = is1stDBufferFlushTime(); + auto is2ndDBuffer = is2ndDBufferFlushTime(); + + if (!is1stDBuffer && !is2ndDBuffer) { + auto offset = currentBufferIndex >= buffersCount / 2 ? buffersCount / 2 : 0; + auto size = (currentBufferIndex + 1) - offset; + auto dbuffer = &buffers[offset]; + addBufferDataToPacket(dbuffer, size); + sendPacket(); + } + + currentBufferIndex = 0; + nextBufferIndex = 0; +} + void StaPipQBufferRenderer::cull(StaPipQBuffer* buffer) { if (buffer->size == 0) { return; } - auto program = getCullProgramByBag(buffer->bag); - addBufferDataToPacket(program, buffer); - sendPacket(); + programs[getQBufferIndex(buffer)] = getCullProgramByBag(buffer->bag); + + auto is1stDBuffer = is1stDBufferFlushTime(); + auto is2ndDBuffer = is2ndDBufferFlushTime(); + + if (is1stDBuffer || is2ndDBuffer) { + auto dbuffer = &buffers[is1stDBuffer ? 0 : buffersCount / 2]; + addBufferDataToPacket(dbuffer, buffersCount / 2); + sendPacket(); + } } void StaPipQBufferRenderer::clip(StaPipQBuffer* buffer) { @@ -194,11 +256,16 @@ void StaPipQBufferRenderer::clip(StaPipQBuffer* buffer) { return; } - auto program = getAsIsProgramByBag(buffer->bag); + programs[getQBufferIndex(buffer)] = getAsIsProgramByBag(buffer->bag); + clipper.clip(buffer); - if (buffer->any()) { - if (buffer) addBufferDataToPacket(program, buffer); + auto is1stDBuffer = is1stDBufferFlushTime(); + auto is2ndDBuffer = is2ndDBufferFlushTime(); + + if (is1stDBuffer || is2ndDBuffer) { + auto dbuffer = &buffers[is1stDBuffer ? 0 : buffersCount / 2]; + addBufferDataToPacket(dbuffer, buffersCount / 2); sendPacket(); } } @@ -207,20 +274,26 @@ void StaPipQBufferRenderer::clearLastProgramName() { lastProgramName = StaPipUndefinedProgram; } -void StaPipQBufferRenderer::addBufferDataToPacket(StaPipVU1Program* program, - StaPipQBuffer* buffer) { +void StaPipQBufferRenderer::addBufferDataToPacket(StaPipQBuffer** buffers, + const u32& count) { currentPacket = packets[context]; packet2_reset(currentPacket, false); - program->addBufferDataToPacket(currentPacket, buffer, &rendererCore->gs.prim); + for (u32 i = 0; i < count; i++) { + if (!buffers[i]->any()) continue; - if (lastProgramName != program->getName()) { - packet2_utils_vu_add_start_program(currentPacket, - program->getDestinationAddress()); - lastProgramName = program->getName(); - } else { - packet2_utils_vu_add_continue_program(currentPacket); + programs[i]->addBufferDataToPacket(currentPacket, buffers[i], + &rendererCore->gs.prim); + + if (lastProgramName != programs[i]->getName()) { + packet2_utils_vu_add_start_program(currentPacket, + programs[i]->getDestinationAddress()); + lastProgramName = programs[i]->getName(); + } else { + packet2_utils_vu_add_continue_program(currentPacket); + } } + packet2_utils_vu_add_end_tag(currentPacket); } @@ -233,8 +306,9 @@ void StaPipQBufferRenderer::sendPacket() { } void StaPipQBufferRenderer::setMaxVertCount(const u32& count) { - buffers[0].setMaxVertCount(count); - buffers[1].setMaxVertCount(count); + for (u32 i = 0; i < buffersCount; i++) { + buffers[i]->setMaxVertCount(count); + } clipper.setMaxVertCount(count); } diff --git a/engine/src/renderer/3d/pipeline/static/static_pipeline.cpp b/engine/src/renderer/3d/pipeline/static/static_pipeline.cpp index c2ca289..119aa15 100644 --- a/engine/src/renderer/3d/pipeline/static/static_pipeline.cpp +++ b/engine/src/renderer/3d/pipeline/static/static_pipeline.cpp @@ -23,13 +23,7 @@ void StaticPipeline::init(RendererCore* t_core) { void StaticPipeline::onUse() { core.reinitVU1Programs(); } -// TODO - StaPipCore::render(StaPipBag* bags, StaPipBagPackagesBBox* bboxes, -// const u32& count) -// TODO - MD2 loader - choose between static/dynamic mesh -// TODO - Dynamic -> StaticMesh -// TODO - DBuffering + spamming - -void StaticPipeline::render(DynamicMesh* mesh, const StaPipOptions* options) { +void StaticPipeline::render(StaticMesh* mesh, const StaPipOptions* options) { auto model = mesh->getModelMatrix(); auto* infoBag = getInfoBag(mesh, options, &model); @@ -68,7 +62,7 @@ void StaticPipeline::addVertices(MeshMaterialFrame* materialFrame, bag->vertices = materialFrame->getVertices(); } -PipelineInfoBag* StaticPipeline::getInfoBag(DynamicMesh* mesh, +PipelineInfoBag* StaticPipeline::getInfoBag(StaticMesh* mesh, const StaPipOptions* options, M4x4* model) const { auto* result = new PipelineInfoBag(); diff --git a/engine/src/renderer/core/texture/texture_repository.cpp b/engine/src/renderer/core/texture/texture_repository.cpp index 92952cc..63ec8a1 100644 --- a/engine/src/renderer/core/texture/texture_repository.cpp +++ b/engine/src/renderer/core/texture/texture_repository.cpp @@ -57,7 +57,7 @@ Texture* TextureRepository::add(const char* fullpath) { return texture; } -void TextureRepository::addByMesh(DynamicMesh* mesh, const char* directory, +void TextureRepository::addByMesh(Mesh* mesh, const char* directory, const char* extension) { auto& loader = texLoaderSelector.getLoaderByExtension(extension); diff --git a/samples/h4570/inc/h4570.hpp b/samples/h4570/inc/h4570.hpp index 30bd4ab..d340a18 100644 --- a/samples/h4570/inc/h4570.hpp +++ b/samples/h4570/inc/h4570.hpp @@ -15,6 +15,7 @@ #include "renderer/3d/pipeline/minecraft/minecraft_pipeline.hpp" #include "renderer/3d/pipeline/static/static_pipeline.hpp" #include "renderer/3d/pipeline/dynamic/dynamic_pipeline.hpp" +#include "renderer/3d/mesh/static/static_mesh.hpp" namespace Tyra { @@ -29,6 +30,7 @@ class H4570 : public Game { private: Engine* engine; + StaticMesh* staticMesh; DynamicMesh* warrior; u8 warriorsCount; DynamicMesh** warriors; diff --git a/samples/h4570/src/h4570.cpp b/samples/h4570/src/h4570.cpp index 9584b78..0785eed 100644 --- a/samples/h4570/src/h4570.cpp +++ b/samples/h4570/src/h4570.cpp @@ -27,6 +27,7 @@ int getRandomInt(int a, int b) { return (rand() % (b - a + 1)) + a; } H4570::H4570(Engine* t_engine) { engine = t_engine; } H4570::~H4570() {} +StaticMesh* getStaticMesh(Renderer* renderer); DynamicMesh* getWarrior(Renderer* renderer); StaPipOptions* getStaPipOptions(); DynPipOptions* getDynPipOptions(); @@ -45,6 +46,8 @@ void H4570::init() { engine->renderer.setClearScreenColor(Color(64.0F, 64.0F, 64.0F)); + staticMesh = getStaticMesh(&engine->renderer); + warrior = getWarrior(&engine->renderer); warriorTex = engine->renderer.core.texture.repository.getBySpriteOrMesh( warrior->getMaterial(0)->getId()); @@ -114,7 +117,14 @@ void H4570::init() { engine->renderer.setFrameLimit(false); } +u32 counter = 0; + void H4570::loop() { + if (counter++ > 30) { + TYRA_LOG(engine->info.getFps()); + counter = 0; + } + for (u8 i = 0; i < warriorsCount; i++) warriors[i]->animate(); engine->renderer.beginFrame(CameraInfo3D(&cameraPosition, &cameraLookAt)); @@ -127,6 +137,9 @@ void H4570::loop() { blocks[i].model = translations[i] * rotations[i] * scales[i]; } + engine->renderer.renderer3D.usePipeline(&stapip); + { stapip.render(staticMesh, staOptions); } + engine->renderer.renderer3D.usePipeline(&dynpip); { Threading::switchThread(); @@ -144,6 +157,19 @@ void H4570::loop() { engine->renderer.endFrame(); } +StaticMesh* getStaticMesh(Renderer* renderer) { + MD2Loader loader; + auto* data = loader.load(FileUtils::fromCwd("warrior.md2"), .08F, false); + auto* result = new StaticMesh(*data); + // result->translation.translateZ(-30.0F); + delete data; + + renderer->core.texture.repository.addByMesh(result, FileUtils::getCwd(), + "png"); + + return result; +} + DynamicMesh* getWarrior(Renderer* renderer) { MD2Loader loader; auto* data = loader.load(FileUtils::fromCwd("warrior.md2"), .08F, false);