From 0c63de8ac949daaea10f28d66e1b664564bf3f19 Mon Sep 17 00:00:00 2001 From: h4570 Date: Mon, 25 Jul 2022 20:10:46 +0200 Subject: [PATCH] core renderer refactor finish --- ROADMAP.txt | 18 +--- .../3d/pipeline/dynamic/dynamic_pipeline.hpp | 4 +- .../3d/pipeline/dynamic/dynpip_options.hpp | 9 -- .../pipeline/minecraft/minecraft_pipeline.hpp | 19 +++- .../programs/mcpip_programs_manager.hpp | 5 + .../pipeline/shared/bag/pipeline_info_bag.hpp | 6 +- .../shared/pipeline_frustum_culling.hpp | 24 +++++ .../3d/pipeline/shared/pipeline_options.hpp | 2 + .../3d/pipeline/static/core/stapip_core.hpp | 6 +- .../3d/pipeline/static/stapip_options.hpp | 8 +- .../3d/pipeline/static/static_pipeline.hpp | 2 +- .../3d/pipeline/dynamic/dynamic_pipeline.cpp | 12 +-- .../pipeline/minecraft/minecraft_pipeline.cpp | 100 +++++++++++++----- .../minecraft/programs/cull/mcpip_cull.cpp | 2 - .../programs/mcpip_programs_manager.cpp | 40 ++++++- .../bag/packaging/stapip_bag_packager.cpp | 2 + .../3d/pipeline/static/core/stapip_core.cpp | 76 ++++++++----- .../3d/pipeline/static/static_pipeline.cpp | 32 ++++-- 18 files changed, 258 insertions(+), 109 deletions(-) create mode 100644 engine/inc/renderer/3d/pipeline/shared/pipeline_frustum_culling.hpp diff --git a/ROADMAP.txt b/ROADMAP.txt index 69d723e..eac4da5 100644 --- a/ROADMAP.txt +++ b/ROADMAP.txt @@ -1,17 +1,10 @@ ------------ Tyra's v2.0 roadmap to publish on GitHub ------------ -- [StaPip] FPS before: 175 -- [StaPip] FPS spamming: 190 - --- H4570 -- [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 +- [Texture] Unload texture +- [Texture] Dont load loaded texture by name + - [Loaders] Think about ".tyrobj" format - implement it (add multicolor support) - [Loaders] DFF loader as static Mesh loader - [Game] Update intellisense from docker @@ -25,8 +18,6 @@ - [General] Control generated id to avoid duplication. Maybe Just increment from 0? Add interface IIdentificable? -- [General] rsync is excluding folder like "objects" lol XD - - [DMA] Check if all chain transfers have end tag! - [General] Change libs of sample? (remove -lpng, -lz...), probably they are not required @@ -36,7 +27,7 @@ - [General] Check all TYRA_ASSERT() if there are no asserts like (TYRA_ASSERT(!audsrv_load_adpcm(result, data, adpcmFileSize))) because this lines will be removed on make-release. Only debug stuff should be checked in assert -- [General] All Copyrights to 2020-2022 +- [General] All Copyrights to 2022 - [General] CI in Github via docker image @@ -66,3 +57,4 @@ 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) +- [File] Async file loading diff --git a/engine/inc/renderer/3d/pipeline/dynamic/dynamic_pipeline.hpp b/engine/inc/renderer/3d/pipeline/dynamic/dynamic_pipeline.hpp index a3273e1..ae1d64d 100644 --- a/engine/inc/renderer/3d/pipeline/dynamic/dynamic_pipeline.hpp +++ b/engine/inc/renderer/3d/pipeline/dynamic/dynamic_pipeline.hpp @@ -52,10 +52,10 @@ class DynamicPipeline : public Renderer3DPipeline { static const u32 halfBuffersCount; void setBuffer(DynPipBag* buffers, DynPipBag* buffer, u16* bufferIndex, - const DynPipFrustumCulling& frustumCulling); + const PipelineFrustumCulling& frustumCulling); void sendRestOfBuffers(DynPipBag* buffers, u16* bufferIndex, - const DynPipFrustumCulling& frustumCulling); + const PipelineFrustumCulling& frustumCulling); void addVertices(MeshMaterialFrame* materialFrameFrom, MeshMaterialFrame* materialFrameTo, DynPipBag* bag, diff --git a/engine/inc/renderer/3d/pipeline/dynamic/dynpip_options.hpp b/engine/inc/renderer/3d/pipeline/dynamic/dynpip_options.hpp index 9f0ce84..ece1bad 100644 --- a/engine/inc/renderer/3d/pipeline/dynamic/dynpip_options.hpp +++ b/engine/inc/renderer/3d/pipeline/dynamic/dynpip_options.hpp @@ -14,19 +14,10 @@ namespace Tyra { -enum DynPipFrustumCulling { - DynPipFrustumCulling_None = 0, - DynPipFrustumCulling_Simple = 1, - DynPipFrustumCulling_Precise = 2, -}; - class DynPipOptions : public PipelineOptions { public: DynPipOptions() {} ~DynPipOptions() {} - - /** Default: Simple */ - DynPipFrustumCulling frustumCulling; }; } // namespace Tyra diff --git a/engine/inc/renderer/3d/pipeline/minecraft/minecraft_pipeline.hpp b/engine/inc/renderer/3d/pipeline/minecraft/minecraft_pipeline.hpp index 0801d40..275b83f 100644 --- a/engine/inc/renderer/3d/pipeline/minecraft/minecraft_pipeline.hpp +++ b/engine/inc/renderer/3d/pipeline/minecraft/minecraft_pipeline.hpp @@ -22,7 +22,7 @@ namespace Tyra { * Pipeline specialized in fast rendering of voxels * Supports: * - Full "against each plane" clipping - * - Frustum culling (on noFullClipChecks = false) + * - Frustum culling (on fullClipChecks = true) */ class MinecraftPipeline : public Renderer3DPipeline { public: @@ -40,11 +40,11 @@ class MinecraftPipeline : public Renderer3DPipeline { * @param count number of blocks to render * @param t_tex texture to use * @param isMulti is this a 6 texture voxel? - * @param noFullClipChecks true = faster, simple PS2 clipping. False = slower + * @param fullClipChecks false = faster, simple PS2 clipping. True = slower * "against each plane" clipping. */ void render(McpipBlock* blocks, const u32& count, Texture* t_tex, - const bool& isMulti = false, const bool& noFullClipChecks = true); + const bool& isMulti = false, const bool& fullClipChecks = false); inline const float& getTextureOffset() const { return manager.getTextureOffset(); @@ -58,12 +58,17 @@ class MinecraftPipeline : public Renderer3DPipeline { RenderBBox* bbox; McpipProgramName latestMode; + McpipBlock*** spamBuffers; + u32* spamCounts; + u32 spamBuffersCount; + u32 spammerIndex; + void initBBox(); void changeMode(const McpipProgramName& requestedMode, const u8& force); void cull(McpipBlock* blocks, const std::vector& indexes, - RendererCoreTextureBuffers* texBuffers, + RendererCoreTextureBuffers* texBuffers, const bool& isCullOnly, const bool& isMulti = false); void clip(McpipBlock* blocks, const std::vector& indexes, @@ -71,6 +76,12 @@ class MinecraftPipeline : public Renderer3DPipeline { const bool& isMulti = false); Tyra::CoreBBoxFrustum isInFrustum(const McpipBlock& block) const; + + void addToSpammer(McpipBlock** blockPointerArray, const u32& count, + RendererCoreTextureBuffers* texBuffers, + const bool& isMulti); + void flushSpammer(RendererCoreTextureBuffers* texBuffers, + const bool& isMulti); }; } // namespace Tyra diff --git a/engine/inc/renderer/3d/pipeline/minecraft/programs/mcpip_programs_manager.hpp b/engine/inc/renderer/3d/pipeline/minecraft/programs/mcpip_programs_manager.hpp index aecff93..2864a46 100644 --- a/engine/inc/renderer/3d/pipeline/minecraft/programs/mcpip_programs_manager.hpp +++ b/engine/inc/renderer/3d/pipeline/minecraft/programs/mcpip_programs_manager.hpp @@ -42,6 +42,10 @@ class BlockizerProgramsManager { void clearLastProgram() { lastProgramName = UndefinedMcpipProgram; } + void cullSpam(McpipBlock*** blockPointerArrays, u32* blockPointerArrayCounts, + u32 blockPointerArraysCount, + RendererCoreTextureBuffers* texBuffers, const bool& isMulti); + void cull(McpipBlock** blockPointerArray, u32 blockPointerArrayCount, RendererCoreTextureBuffers* texBuffers, const bool& isMulti); @@ -69,6 +73,7 @@ class BlockizerProgramsManager { void setProgramsCache(); void uploadBlock(bool isMulti); + void addProgram(McpipProgram* program); void sendPacket(McpipProgram* program); }; diff --git a/engine/inc/renderer/3d/pipeline/shared/bag/pipeline_info_bag.hpp b/engine/inc/renderer/3d/pipeline/shared/bag/pipeline_info_bag.hpp index cc7492a..aa14523 100644 --- a/engine/inc/renderer/3d/pipeline/shared/bag/pipeline_info_bag.hpp +++ b/engine/inc/renderer/3d/pipeline/shared/bag/pipeline_info_bag.hpp @@ -30,15 +30,15 @@ class PipelineInfoBag { bool antiAliasingEnabled; /** - * @brief True -> disables "clip against each plane" algorithm. - * Default: false. + * @brief False -> disables "clip against each plane" algorithm. + * Default: True. * * Full clip checks are slow, but they are * preventing visual artifacts, which can happen * for big 3D objects (or objects near camera eyes) * Force enabled in dynamic pipe, because of efficiency. */ - bool noFullClipChecks; + bool fullClipChecks; }; } // namespace Tyra diff --git a/engine/inc/renderer/3d/pipeline/shared/pipeline_frustum_culling.hpp b/engine/inc/renderer/3d/pipeline/shared/pipeline_frustum_culling.hpp new file mode 100644 index 0000000..a374e44 --- /dev/null +++ b/engine/inc/renderer/3d/pipeline/shared/pipeline_frustum_culling.hpp @@ -0,0 +1,24 @@ +/* +# ______ ____ ___ +# | \/ ____| |___| +# | | | \ | | +#----------------------------------------------------------------------- +# Copyright 2022, tyra - https://github.com/h4570/tyra +# Licenced under Apache License 2.0 +# Sandro Sobczyński +*/ + +#pragma once + +namespace Tyra { + +enum PipelineFrustumCulling { + /** No frustum culling */ + PipelineFrustumCulling_None = 0, + /** Frustum culling of whole object */ + PipelineFrustumCulling_Simple = 1, + /** Frustum culling of parts of an object */ + PipelineFrustumCulling_Precise = 2, +}; + +} diff --git a/engine/inc/renderer/3d/pipeline/shared/pipeline_options.hpp b/engine/inc/renderer/3d/pipeline/shared/pipeline_options.hpp index ced7f37..214f999 100644 --- a/engine/inc/renderer/3d/pipeline/shared/pipeline_options.hpp +++ b/engine/inc/renderer/3d/pipeline/shared/pipeline_options.hpp @@ -12,6 +12,7 @@ #include "renderer/3d/pipeline/shared/pipeline_shading_type.hpp" #include "../shared/pipeline_lighting_options.hpp" +#include "./pipeline_frustum_culling.hpp" namespace Tyra { @@ -20,6 +21,7 @@ class PipelineOptions { PipelineOptions() { lighting = nullptr; } ~PipelineOptions() {} + PipelineFrustumCulling frustumCulling; PipelineShadingType shadingType; bool blendingEnabled; bool antiAliasingEnabled; 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 33d70c1..0573b66 100644 --- a/engine/inc/renderer/3d/pipeline/static/core/stapip_core.hpp +++ b/engine/inc/renderer/3d/pipeline/static/core/stapip_core.hpp @@ -16,6 +16,7 @@ #include "./bag/packaging/stapip_bag_package.hpp" #include "./bag/packaging/stapip_bag_packager.hpp" #include "./stapip_qbuffer_renderer.hpp" +#include "renderer/3d/pipeline/shared/pipeline_frustum_culling.hpp" namespace Tyra { @@ -27,7 +28,8 @@ class StaPipCore { void init(RendererCore* t_core); /** Render 3D via "bags" */ - void render(StaPipBag* bag, StaPipBagPackagesBBox* bbox = nullptr); + void render(StaPipBag* bag, const bool& frustumCull, + StaPipBagPackagesBBox* bbox = nullptr); /** Get max vert count of VU1 qbuffer (for optimizations) */ u32 getMaxVertCountByParams(const bool& isSingleColor, @@ -52,7 +54,7 @@ class StaPipCore { void setMaxVertCount(const u32& count); StaPipBagPackager packager; StaPipQBufferRenderer qbufferRenderer; - void renderPkgs(StaPipBagPackage* packages, u16 count); + void renderPkgs(StaPipBagPackage* packages, const bool& doClip, u16 count); void renderSubpkgs(StaPipBagPackage* packages, u16 count); }; diff --git a/engine/inc/renderer/3d/pipeline/static/stapip_options.hpp b/engine/inc/renderer/3d/pipeline/static/stapip_options.hpp index 17108d6..90c23c2 100644 --- a/engine/inc/renderer/3d/pipeline/static/stapip_options.hpp +++ b/engine/inc/renderer/3d/pipeline/static/stapip_options.hpp @@ -16,18 +16,18 @@ namespace Tyra { class StaPipOptions : public PipelineOptions { public: - StaPipOptions() {} + StaPipOptions() { fullClipChecks = false; } ~StaPipOptions() {} /** - * @brief True -> disables "clip against each plane" algorithm. - * Mandatory, default: false. + * @brief False -> disables "clip against each plane" algorithm. + * Mandatory, default: True. * * Full clip checks are slow, but they are * preventing visual artifacts, which can happen * for big 3D objects (or objects near camera eyes) */ - bool noFullClipChecks; + bool fullClipChecks; }; } // namespace Tyra diff --git a/engine/inc/renderer/3d/pipeline/static/static_pipeline.hpp b/engine/inc/renderer/3d/pipeline/static/static_pipeline.hpp index e3d45ec..b5c3d50 100644 --- a/engine/inc/renderer/3d/pipeline/static/static_pipeline.hpp +++ b/engine/inc/renderer/3d/pipeline/static/static_pipeline.hpp @@ -24,7 +24,7 @@ namespace Tyra { * Pipeline for static models (StaticMesh). * Supports: * - Full "against each plane" clipping and simple PS2 clipping - * (noFullClipChecks), + * (fullClipChecks), * - Force enabled precise frustum culling (checks parts of given mesh) * - Modes: color(s), texture+color(s), dir lights, texture + dir lights */ diff --git a/engine/src/renderer/3d/pipeline/dynamic/dynamic_pipeline.cpp b/engine/src/renderer/3d/pipeline/dynamic/dynamic_pipeline.cpp index f2f81ba..c40dc2e 100644 --- a/engine/src/renderer/3d/pipeline/dynamic/dynamic_pipeline.cpp +++ b/engine/src/renderer/3d/pipeline/dynamic/dynamic_pipeline.cpp @@ -40,9 +40,9 @@ void DynamicPipeline::render(DynamicMesh* mesh, const DynPipOptions* options) { auto* infoBag = getInfoBag(mesh, options, &model); PipelineDirLightsBag* dirLights = nullptr; auto frustumCulling = - options ? options->frustumCulling : DynPipFrustumCulling_Simple; + options ? options->frustumCulling : PipelineFrustumCulling_Simple; - if (frustumCulling == DynPipFrustumCulling_Simple) { + if (frustumCulling == PipelineFrustumCulling_Simple) { auto* frameTo = mesh->getFrame(mesh->getNextAnimationFrame()); if (frameTo->getBBox().isInFrustum( rendererCore->renderer3D.frustumPlanes.getAll(), model) == @@ -117,7 +117,7 @@ void DynamicPipeline::render(DynamicMesh* mesh, const DynPipOptions* options) { void DynamicPipeline::setBuffer(DynPipBag* buffers, DynPipBag* buffer, u16* bufferIndex, - const DynPipFrustumCulling& frustumCulling) { + const PipelineFrustumCulling& frustumCulling) { auto isEndOf1stDBuffer = *bufferIndex == halfBuffersCount - 1; auto isEndOf2ndDBuffer = *bufferIndex == buffersCount - 1; @@ -130,7 +130,7 @@ void DynamicPipeline::setBuffer(DynPipBag* buffers, DynPipBag* buffer, sendBuffers[i] = &buffers[offset + i]; core.renderPart(sendBuffers, halfBuffersCount, - frustumCulling == DynPipFrustumCulling_Precise); + frustumCulling == PipelineFrustumCulling_Precise); delete[] sendBuffers; } @@ -143,7 +143,7 @@ void DynamicPipeline::setBuffer(DynPipBag* buffers, DynPipBag* buffer, void DynamicPipeline::sendRestOfBuffers( DynPipBag* buffers, u16* bufferIndex, - const DynPipFrustumCulling& frustumCulling) { + const PipelineFrustumCulling& frustumCulling) { auto isEndOf1stDBuffer = *bufferIndex <= halfBuffersCount - 1; u32 offset = isEndOf1stDBuffer ? 0 : halfBuffersCount; @@ -157,7 +157,7 @@ void DynamicPipeline::sendRestOfBuffers( } core.renderPart(sendBuffers, size, - frustumCulling == DynPipFrustumCulling_Precise); + frustumCulling == PipelineFrustumCulling_Precise); delete[] sendBuffers; } diff --git a/engine/src/renderer/3d/pipeline/minecraft/minecraft_pipeline.cpp b/engine/src/renderer/3d/pipeline/minecraft/minecraft_pipeline.cpp index 7db26ba..4cca364 100644 --- a/engine/src/renderer/3d/pipeline/minecraft/minecraft_pipeline.cpp +++ b/engine/src/renderer/3d/pipeline/minecraft/minecraft_pipeline.cpp @@ -14,12 +14,20 @@ namespace Tyra { -MinecraftPipeline::MinecraftPipeline() { latestMode = UndefinedMcpipProgram; } +MinecraftPipeline::MinecraftPipeline() { + latestMode = UndefinedMcpipProgram; + spamBuffersCount = 4; + spamBuffers = new McpipBlock**[spamBuffersCount]; + spamCounts = new u32[spamBuffersCount]; + spammerIndex = 0; +} MinecraftPipeline::~MinecraftPipeline() { if (bbox) { delete bbox; } + delete[] spamBuffers; + delete[] spamCounts; } void MinecraftPipeline::init(RendererCore* core) { @@ -42,35 +50,35 @@ void MinecraftPipeline::initBBox() { void MinecraftPipeline::render(McpipBlock* blocks, const u32& count, Texture* t_tex, const bool& isMulti, - const bool& noFullClipChecks) { + const bool& fullClipChecks) { auto texBuffers = rendererCore->texture.useTexture(t_tex); rendererCore->gs.prim.mapping = 1; manager.clearLastProgram(); std::vector cullIndexes; - if (noFullClipChecks) { + if (!fullClipChecks) { for (u32 i = 0; i < count; i++) cullIndexes.push_back(i); - cull(blocks, cullIndexes, &texBuffers, isMulti); + cull(blocks, cullIndexes, &texBuffers, true, isMulti); return; - } else { - u32 culled = 0, clipped = 0; - std::vector clipIndexes; - - for (u32 i = 0; i < count; i++) { - auto frustum = isInFrustum(blocks[i]); - if (frustum == CoreBBoxFrustum::IN_FRUSTUM) { - cullIndexes.push_back(i); - culled++; - } else if (frustum == CoreBBoxFrustum::PARTIALLY_IN_FRUSTUM) { - clipIndexes.push_back(i); - clipped++; - } - } - - if (culled > 0) cull(blocks, cullIndexes, &texBuffers, isMulti); - if (clipped > 0) clip(blocks, clipIndexes, &texBuffers, isMulti); } + + u32 culled = 0, clipped = 0; + std::vector clipIndexes; + + for (u32 i = 0; i < count; i++) { + auto frustum = isInFrustum(blocks[i]); + if (frustum == CoreBBoxFrustum::IN_FRUSTUM) { + cullIndexes.push_back(i); + culled++; + } else if (frustum == CoreBBoxFrustum::PARTIALLY_IN_FRUSTUM) { + clipIndexes.push_back(i); + clipped++; + } + } + + if (culled > 0) cull(blocks, cullIndexes, &texBuffers, false, isMulti); + if (clipped > 0) clip(blocks, clipIndexes, &texBuffers, isMulti); } CoreBBoxFrustum MinecraftPipeline::isInFrustum(const McpipBlock& block) const { @@ -81,7 +89,7 @@ CoreBBoxFrustum MinecraftPipeline::isInFrustum(const McpipBlock& block) const { void MinecraftPipeline::cull(McpipBlock* blocks, const std::vector& indexes, RendererCoreTextureBuffers* texBuffers, - const bool& isMulti) { + const bool& isCullOnly, const bool& isMulti) { changeMode(McPipCull, false); auto maxBlocksPerQBuffer = manager.culler.getMaxBlocksCountPerQBuffer(); @@ -100,10 +108,18 @@ void MinecraftPipeline::cull(McpipBlock* blocks, &blocks[indexes[i * maxBlocksPerQBuffer + j]]; } - manager.cull(blockPointerArray, blockPointerArrayCount, texBuffers, - isMulti); + if (isCullOnly) { + addToSpammer(blockPointerArray, blockPointerArrayCount, texBuffers, + isMulti); + } else { + manager.cull(blockPointerArray, blockPointerArrayCount, texBuffers, + isMulti); + delete[] blockPointerArray; + } + } - delete[] blockPointerArray; + if (isCullOnly) { + flushSpammer(texBuffers, isMulti); } } @@ -139,4 +155,38 @@ void MinecraftPipeline::changeMode(const McpipProgramName& requestedMode, } } +void MinecraftPipeline::addToSpammer(McpipBlock** blockPointerArray, + const u32& count, + RendererCoreTextureBuffers* texBuffers, + const bool& isMulti) { + spamBuffers[spammerIndex] = blockPointerArray; + spamCounts[spammerIndex] = count; + + spammerIndex++; + + if (spammerIndex == spamBuffersCount) { + spammerIndex = 0; + + manager.cullSpam(spamBuffers, spamCounts, spamBuffersCount, texBuffers, + isMulti); + + for (u32 i = 0; i < spamBuffersCount; i++) { + delete[] spamBuffers[i]; + } + } +} + +void MinecraftPipeline::flushSpammer(RendererCoreTextureBuffers* texBuffers, + const bool& isMulti) { + if (spammerIndex == 0) return; + + manager.cullSpam(spamBuffers, spamCounts, spammerIndex, texBuffers, isMulti); + + for (u32 i = 0; i < spammerIndex; i++) { + delete[] spamBuffers[i]; + } + + spammerIndex = 0; +} + } // namespace Tyra diff --git a/engine/src/renderer/3d/pipeline/minecraft/programs/cull/mcpip_cull.cpp b/engine/src/renderer/3d/pipeline/minecraft/programs/cull/mcpip_cull.cpp index e3c3fe4..5f04d46 100644 --- a/engine/src/renderer/3d/pipeline/minecraft/programs/cull/mcpip_cull.cpp +++ b/engine/src/renderer/3d/pipeline/minecraft/programs/cull/mcpip_cull.cpp @@ -107,8 +107,6 @@ void McpipCull::sendVU1StaticData() { void McpipCull::addData(packet2_t* packet, McpipBlock** blockPointerArray, u32 blockPointerArrayCount, RendererCoreTextureBuffers* texBuffers, bool isMulti) { - packet2_reset(packet, false); - rendererCore->texture.updateClutBuffer(texBuffers->clut); packet2_utils_vu_open_unpack( diff --git a/engine/src/renderer/3d/pipeline/minecraft/programs/mcpip_programs_manager.cpp b/engine/src/renderer/3d/pipeline/minecraft/programs/mcpip_programs_manager.cpp index aa89c39..7e6c95b 100644 --- a/engine/src/renderer/3d/pipeline/minecraft/programs/mcpip_programs_manager.cpp +++ b/engine/src/renderer/3d/pipeline/minecraft/programs/mcpip_programs_manager.cpp @@ -16,8 +16,8 @@ BlockizerProgramsManager::BlockizerProgramsManager() { lastProgramName = UndefinedMcpipProgram; context = 0; vu1BlockData = BlockNotUploaded; - dynamicPackets[0] = packet2_create(100, P2_TYPE_NORMAL, P2_MODE_CHAIN, true); - dynamicPackets[1] = packet2_create(100, P2_TYPE_NORMAL, P2_MODE_CHAIN, true); + dynamicPackets[0] = packet2_create(300, P2_TYPE_NORMAL, P2_MODE_CHAIN, true); + dynamicPackets[1] = packet2_create(300, P2_TYPE_NORMAL, P2_MODE_CHAIN, true); staticPacket = packet2_create(2, P2_TYPE_NORMAL, P2_MODE_CHAIN, true); setProgramsCache(); } @@ -79,6 +79,32 @@ void BlockizerProgramsManager::uploadBlock(bool isMulti) { dma_channel_send_packet2(staticPacket, DMA_CHANNEL_VIF1, true); } +void BlockizerProgramsManager::cullSpam(McpipBlock*** blockPointerArrays, + u32* blockPointerArrayCounts, + u32 blockPointerArraysCount, + RendererCoreTextureBuffers* texBuffers, + const bool& isMulti) { + uploadBlock(isMulti); + + auto* currentPacket = dynamicPackets[context]; + + auto* program = repo.getProgram(McpipProgramName::McPipCull); + + packet2_reset(currentPacket, false); + + for (u32 i = 0; i < blockPointerArraysCount; i++) { + auto* blockPointerArray = blockPointerArrays[i]; + auto blockPointerArrayCount = blockPointerArrayCounts[i]; + + culler.addData(currentPacket, blockPointerArray, blockPointerArrayCount, + texBuffers, isMulti); + + addProgram(program); + } + + sendPacket(program); +} + void BlockizerProgramsManager::cull(McpipBlock** blockPointerArray, u32 blockPointerArrayCount, RendererCoreTextureBuffers* texBuffers, @@ -89,9 +115,12 @@ void BlockizerProgramsManager::cull(McpipBlock** blockPointerArray, auto* program = repo.getProgram(McpipProgramName::McPipCull); + packet2_reset(currentPacket, false); + culler.addData(currentPacket, blockPointerArray, blockPointerArrayCount, texBuffers, isMulti); + addProgram(program); sendPacket(program); } @@ -106,10 +135,11 @@ void BlockizerProgramsManager::clip(McpipBlock* block, clipper.addData(block, isMulti, texBuffers, currentPacket, context); + addProgram(program); sendPacket(program); } -void BlockizerProgramsManager::sendPacket(McpipProgram* program) { +void BlockizerProgramsManager::addProgram(McpipProgram* program) { auto* currentPacket = dynamicPackets[context]; if (lastProgramName != program->getName()) { @@ -119,6 +149,10 @@ void BlockizerProgramsManager::sendPacket(McpipProgram* program) { } else { packet2_utils_vu_add_continue_program(currentPacket); } +} + +void BlockizerProgramsManager::sendPacket(McpipProgram* program) { + auto* currentPacket = dynamicPackets[context]; packet2_utils_vu_add_end_tag(currentPacket); diff --git a/engine/src/renderer/3d/pipeline/static/core/bag/packaging/stapip_bag_packager.cpp b/engine/src/renderer/3d/pipeline/static/core/bag/packaging/stapip_bag_packager.cpp index f484702..649e4a8 100644 --- a/engine/src/renderer/3d/pipeline/static/core/bag/packaging/stapip_bag_packager.cpp +++ b/engine/src/renderer/3d/pipeline/static/core/bag/packaging/stapip_bag_packager.cpp @@ -100,6 +100,8 @@ StaPipBagPackage* StaPipBagPackager::create(u16* o_count, } CoreBBoxFrustum StaPipBagPackager::checkFrustum(const StaPipBagPackage& pkg) { + if (!renderBBox) return CoreBBoxFrustum::OUTSIDE_FRUSTUM; + if (pkg.size <= (maxVertCount / 3)) { // Is subpackage auto& bbox = renderBBox->getChildBBox1By3(pkg.indexOf1By3BBox); return bbox.clipIsInFrustum(frustumPlanes->getAll(), *pkg.bag->info->model); 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 0027df7..efb179b 100644 --- a/engine/src/renderer/3d/pipeline/static/core/stapip_core.cpp +++ b/engine/src/renderer/3d/pipeline/static/core/stapip_core.cpp @@ -47,7 +47,8 @@ u32 StaPipCore::getMaxVertCountByParams(const bool& isSingleColor, ->getMaxVertCount(isSingleColor, qbufferRenderer.getBufferSize()); } -void StaPipCore::render(StaPipBag* bag, StaPipBagPackagesBBox* bbox) { +void StaPipCore::render(StaPipBag* bag, const bool& frustumCull, + StaPipBagPackagesBBox* bbox) { if (bag->count <= 0) return; TYRA_ASSERT(bag->vertices != nullptr, @@ -70,25 +71,33 @@ void StaPipCore::render(StaPipBag* bag, StaPipBagPackagesBBox* bbox) { TYRA_ASSERT( !bag->texture || (bag->texture->texture && bag->texture->coordinates), "If you want texture, please provide texture and coordinates!"); - - StaPipBagPackagesBBox* renderBbox; + TYRA_ASSERT(!(frustumCull == false && bag->info->fullClipChecks == true), + "Full clip checks are not supported with frustum culling = off!"); u32 maxVertCount = getMaxVertCountByBag(bag); - setMaxVertCount(maxVertCount); - if (!bbox) - renderBbox = - new StaPipBagPackagesBBox(bag->vertices, bag->count, maxVertCount); - else - renderBbox = bbox; + StaPipBagPackagesBBox* renderBbox = nullptr; + + CoreBBoxFrustum frustumCheck = OUTSIDE_FRUSTUM; + + if (frustumCull) { + if (!bbox) + renderBbox = + new StaPipBagPackagesBBox(bag->vertices, bag->count, maxVertCount); + else + renderBbox = bbox; + + frustumCheck = renderBbox->getMainBBox()->clipIsInFrustum( + rendererCore->renderer3D.frustumPlanes.getAll(), *bag->info->model); + + if (frustumCheck == OUTSIDE_FRUSTUM) return; + } + + packager.setRenderBBox(renderBbox); - auto frustumCheck = renderBbox->getMainBBox()->clipIsInFrustum( - rendererCore->renderer3D.frustumPlanes.getAll(), *bag->info->model); auto mvp = rendererCore->renderer3D.getViewProj() * *bag->info->model; - if (frustumCheck == OUTSIDE_FRUSTUM) return; - RendererCoreTextureBuffers* texBuffers = nullptr; if (bag->texture) { auto temp = rendererCore->texture.useTexture(bag->texture->texture); @@ -99,14 +108,28 @@ void StaPipCore::render(StaPipBag* bag, StaPipBagPackagesBBox* bbox) { qbufferRenderer.sendObjectData(bag, &mvp, texBuffers); - packager.setRenderBBox(renderBbox); - qbufferRenderer.setClipperMVP(&mvp); qbufferRenderer.setInfo(bag->info); - if (frustumCheck == IN_FRUSTUM || - (frustumCheck == PARTIALLY_IN_FRUSTUM && bag->info->noFullClipChecks)) { + auto checkYesFrustumInClipYes = // cull all + frustumCull && frustumCheck == IN_FRUSTUM && bag->info->fullClipChecks; + + auto checkYesFrustumPartialClipYes = // pkgs, cull + clip + frustumCull && frustumCheck == PARTIALLY_IN_FRUSTUM && + bag->info->fullClipChecks; + + auto checkYesFrustumInClipNo = // cull all + frustumCull && frustumCheck == IN_FRUSTUM && !bag->info->fullClipChecks; + + auto checkYesFrustumPartialClipNo = // pkgs, cull all + frustumCull && frustumCheck == PARTIALLY_IN_FRUSTUM && + !bag->info->fullClipChecks; + + auto checkNoClipNo = // cull all + !frustumCull && !bag->info->fullClipChecks; + + if (checkYesFrustumInClipYes || checkYesFrustumInClipNo || checkNoClipNo) { u16 packagesCount = 0; auto biggerPkgs = packager.create(&packagesCount, bag, maxVertCount); Verbose("Material - in frustum. Pkgs: ", packagesCount, @@ -118,12 +141,13 @@ void StaPipCore::render(StaPipBag* bag, StaPipBagPackagesBBox* bbox) { qbufferRenderer.cull(buffer); } delete[] biggerPkgs; - } else if (frustumCheck == PARTIALLY_IN_FRUSTUM) { + } else if (checkYesFrustumPartialClipYes || checkYesFrustumPartialClipNo) { u16 packagesCount = 0; - if (bag->count >= maxVertCount * 2) { + auto doClip = checkYesFrustumPartialClipYes; + if (!doClip || bag->count >= maxVertCount * 2) { auto packages = packager.create(&packagesCount, bag, maxVertCount); Verbose("Material - partial. Packages: ", packagesCount); - renderPkgs(packages, packagesCount); + renderPkgs(packages, doClip, packagesCount); delete[] packages; } else { auto subpkgs = packager.create(&packagesCount, bag, maxVertCount / 3); @@ -133,7 +157,7 @@ void StaPipCore::render(StaPipBag* bag, StaPipBagPackagesBBox* bbox) { } } - if (!bbox) delete renderBbox; + if (frustumCull && !bbox) delete renderBbox; if (texBuffers) delete texBuffers; qbufferRenderer.flushBuffers(); @@ -141,14 +165,18 @@ void StaPipCore::render(StaPipBag* bag, StaPipBagPackagesBBox* bbox) { Verbose("Render finished"); } -void StaPipCore::renderPkgs(StaPipBagPackage* packages, u16 count) { +void StaPipCore::renderPkgs(StaPipBagPackage* packages, const bool& doClip, + u16 count) { for (u16 i = 0; i < count; i++) { - if (packages[i].isInFrustum == IN_FRUSTUM) { + auto cull = (doClip && packages[i].isInFrustum == IN_FRUSTUM) || !doClip; + auto doSubpkgs = doClip && packages[i].isInFrustum == PARTIALLY_IN_FRUSTUM; + + if (cull) { Verbose(i, " - package in frustum -> cull"); auto buffer = qbufferRenderer.getBuffer(); buffer->fillByPointer(packages[i]); qbufferRenderer.cull(buffer); - } else if (packages[i].isInFrustum == PARTIALLY_IN_FRUSTUM) { + } else if (doSubpkgs) { u16 subpkgsSize = 0; auto packages1By3 = packager.create(&subpkgsSize, packages[i], maxVertCount / 3); diff --git a/engine/src/renderer/3d/pipeline/static/static_pipeline.cpp b/engine/src/renderer/3d/pipeline/static/static_pipeline.cpp index 119aa15..c1fbf7c 100644 --- a/engine/src/renderer/3d/pipeline/static/static_pipeline.cpp +++ b/engine/src/renderer/3d/pipeline/static/static_pipeline.cpp @@ -9,6 +9,7 @@ */ #include "renderer/3d/pipeline/static/static_pipeline.hpp" +#include "debug/debug.hpp" namespace Tyra { @@ -27,20 +28,29 @@ void StaticPipeline::render(StaticMesh* mesh, const StaPipOptions* options) { auto model = mesh->getModelMatrix(); auto* infoBag = getInfoBag(mesh, options, &model); + auto frustumCulling = + options ? options->frustumCulling : PipelineFrustumCulling_Simple; + + TYRA_ASSERT( + !(frustumCulling != PipelineFrustumCulling_Precise && + infoBag->fullClipChecks == true), + "Full clip checks are only supported with frustum culling == Precise!"); + + if (frustumCulling == PipelineFrustumCulling_Simple) { + auto* frame = mesh->getFrame(); + if (frame->getBBox().isInFrustum( + rendererCore->renderer3D.frustumPlanes.getAll(), model) == + CoreBBoxFrustum::OUTSIDE_FRUSTUM) { + return; + } + } + if (options && options->lighting) setLightingColorsCache(options->lighting); for (u32 i = 0; i < mesh->getMaterialsCount(); i++) { auto* material = mesh->getMaterial(i); auto* materialFrame = material->getFrame(0); - // 2x bufory[maxVertCount*2] -> pętla po mniejszych częściach i czestsze - // rendery - - // TODO: Double buffering in future - // auto maxVertCount = core->renderer3D.getMaxVertCountByParams( - // material->isSingleColorActivated(), material->getNormalFaces(), - // material->getTextureCoordFaces()); - StaPipBag bag; addVertices(materialFrame, &bag); bag.info = infoBag; @@ -48,7 +58,7 @@ void StaticPipeline::render(StaticMesh* mesh, const StaPipOptions* options) { bag.texture = getTextureBag(material, materialFrame); bag.lighting = getLightingBag(materialFrame, &model, options); - core.render(&bag); + core.render(&bag, frustumCulling == PipelineFrustumCulling_Precise); deallocDrawBags(&bag, material); } @@ -71,12 +81,12 @@ PipelineInfoBag* StaticPipeline::getInfoBag(StaticMesh* mesh, result->antiAliasingEnabled = options->antiAliasingEnabled; result->blendingEnabled = options->blendingEnabled; result->shadingType = options->shadingType; - result->noFullClipChecks = options->noFullClipChecks; + result->fullClipChecks = options->fullClipChecks; } else { result->antiAliasingEnabled = false; result->blendingEnabled = true; result->shadingType = TyraShadingFlat; - result->noFullClipChecks = false; + result->fullClipChecks = false; } result->model = model;