core renderer refactor finish

This commit is contained in:
h4570
2022-07-25 20:10:46 +02:00
parent 819a7c3de3
commit 0c63de8ac9
18 changed files with 258 additions and 109 deletions
+5 -13
View File
@@ -1,17 +1,10 @@
------------ Tyra's v2.0 roadmap to publish on GitHub ------------ ------------ Tyra's v2.0 roadmap to publish on GitHub ------------
- [StaPip] FPS before: 175
- [StaPip] FPS spamming: 190
--- H4570 --- 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..) - [Renderer] Allocate dynamic pipeline memory only in "onUse" (core,qbuffrenderer,pipeline..)
- [McPip] Clipping mode - [Texture] Unload texture
- [McPip] VU1 packets spamming - [Texture] Dont load loaded texture by name
- [Loaders] Think about ".tyrobj" format - implement it (add multicolor support) - [Loaders] Think about ".tyrobj" format - implement it (add multicolor support)
- [Loaders] DFF loader as static Mesh loader - [Loaders] DFF loader as static Mesh loader
- [Game] Update intellisense from docker - [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] 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! - [DMA] Check if all chain transfers have end tag!
- [General] Change libs of sample? (remove -lpng, -lz...), probably they are not required - [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))) - [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 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 - [General] CI in Github via docker image
@@ -66,3 +57,4 @@ because Mesh rendering uses only core.render()
------------ Github issues for Tyra v2 ------------ ------------ Github issues for Tyra v2 ------------
- [3D] Add drawLine(x, y , color, size) - [3D] Add drawLine(x, y , color, size)
- [3D] Add drawBBox(x, y , color, size) - [3D] Add drawBBox(x, y , color, size)
- [File] Async file loading
@@ -52,10 +52,10 @@ class DynamicPipeline : public Renderer3DPipeline {
static const u32 halfBuffersCount; static const u32 halfBuffersCount;
void setBuffer(DynPipBag* buffers, DynPipBag* buffer, u16* bufferIndex, void setBuffer(DynPipBag* buffers, DynPipBag* buffer, u16* bufferIndex,
const DynPipFrustumCulling& frustumCulling); const PipelineFrustumCulling& frustumCulling);
void sendRestOfBuffers(DynPipBag* buffers, u16* bufferIndex, void sendRestOfBuffers(DynPipBag* buffers, u16* bufferIndex,
const DynPipFrustumCulling& frustumCulling); const PipelineFrustumCulling& frustumCulling);
void addVertices(MeshMaterialFrame* materialFrameFrom, void addVertices(MeshMaterialFrame* materialFrameFrom,
MeshMaterialFrame* materialFrameTo, DynPipBag* bag, MeshMaterialFrame* materialFrameTo, DynPipBag* bag,
@@ -14,19 +14,10 @@
namespace Tyra { namespace Tyra {
enum DynPipFrustumCulling {
DynPipFrustumCulling_None = 0,
DynPipFrustumCulling_Simple = 1,
DynPipFrustumCulling_Precise = 2,
};
class DynPipOptions : public PipelineOptions { class DynPipOptions : public PipelineOptions {
public: public:
DynPipOptions() {} DynPipOptions() {}
~DynPipOptions() {} ~DynPipOptions() {}
/** Default: Simple */
DynPipFrustumCulling frustumCulling;
}; };
} // namespace Tyra } // namespace Tyra
@@ -22,7 +22,7 @@ namespace Tyra {
* Pipeline specialized in fast rendering of voxels * Pipeline specialized in fast rendering of voxels
* Supports: * Supports:
* - Full "against each plane" clipping * - Full "against each plane" clipping
* - Frustum culling (on noFullClipChecks = false) * - Frustum culling (on fullClipChecks = true)
*/ */
class MinecraftPipeline : public Renderer3DPipeline { class MinecraftPipeline : public Renderer3DPipeline {
public: public:
@@ -40,11 +40,11 @@ class MinecraftPipeline : public Renderer3DPipeline {
* @param count number of blocks to render * @param count number of blocks to render
* @param t_tex texture to use * @param t_tex texture to use
* @param isMulti is this a 6 texture voxel? * @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. * "against each plane" clipping.
*/ */
void render(McpipBlock* blocks, const u32& count, Texture* t_tex, 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 { inline const float& getTextureOffset() const {
return manager.getTextureOffset(); return manager.getTextureOffset();
@@ -58,12 +58,17 @@ class MinecraftPipeline : public Renderer3DPipeline {
RenderBBox* bbox; RenderBBox* bbox;
McpipProgramName latestMode; McpipProgramName latestMode;
McpipBlock*** spamBuffers;
u32* spamCounts;
u32 spamBuffersCount;
u32 spammerIndex;
void initBBox(); void initBBox();
void changeMode(const McpipProgramName& requestedMode, const u8& force); void changeMode(const McpipProgramName& requestedMode, const u8& force);
void cull(McpipBlock* blocks, const std::vector<u32>& indexes, void cull(McpipBlock* blocks, const std::vector<u32>& indexes,
RendererCoreTextureBuffers* texBuffers, RendererCoreTextureBuffers* texBuffers, const bool& isCullOnly,
const bool& isMulti = false); const bool& isMulti = false);
void clip(McpipBlock* blocks, const std::vector<u32>& indexes, void clip(McpipBlock* blocks, const std::vector<u32>& indexes,
@@ -71,6 +76,12 @@ class MinecraftPipeline : public Renderer3DPipeline {
const bool& isMulti = false); const bool& isMulti = false);
Tyra::CoreBBoxFrustum isInFrustum(const McpipBlock& block) const; 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 } // namespace Tyra
@@ -42,6 +42,10 @@ class BlockizerProgramsManager {
void clearLastProgram() { lastProgramName = UndefinedMcpipProgram; } void clearLastProgram() { lastProgramName = UndefinedMcpipProgram; }
void cullSpam(McpipBlock*** blockPointerArrays, u32* blockPointerArrayCounts,
u32 blockPointerArraysCount,
RendererCoreTextureBuffers* texBuffers, const bool& isMulti);
void cull(McpipBlock** blockPointerArray, u32 blockPointerArrayCount, void cull(McpipBlock** blockPointerArray, u32 blockPointerArrayCount,
RendererCoreTextureBuffers* texBuffers, const bool& isMulti); RendererCoreTextureBuffers* texBuffers, const bool& isMulti);
@@ -69,6 +73,7 @@ class BlockizerProgramsManager {
void setProgramsCache(); void setProgramsCache();
void uploadBlock(bool isMulti); void uploadBlock(bool isMulti);
void addProgram(McpipProgram* program);
void sendPacket(McpipProgram* program); void sendPacket(McpipProgram* program);
}; };
@@ -30,15 +30,15 @@ class PipelineInfoBag {
bool antiAliasingEnabled; bool antiAliasingEnabled;
/** /**
* @brief True -> disables "clip against each plane" algorithm. * @brief False -> disables "clip against each plane" algorithm.
* Default: false. * Default: True.
* *
* Full clip checks are slow, but they are * Full clip checks are slow, but they are
* preventing visual artifacts, which can happen * preventing visual artifacts, which can happen
* for big 3D objects (or objects near camera eyes) * for big 3D objects (or objects near camera eyes)
* Force enabled in dynamic pipe, because of efficiency. * Force enabled in dynamic pipe, because of efficiency.
*/ */
bool noFullClipChecks; bool fullClipChecks;
}; };
} // namespace Tyra } // namespace Tyra
@@ -0,0 +1,24 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#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,
};
}
@@ -12,6 +12,7 @@
#include "renderer/3d/pipeline/shared/pipeline_shading_type.hpp" #include "renderer/3d/pipeline/shared/pipeline_shading_type.hpp"
#include "../shared/pipeline_lighting_options.hpp" #include "../shared/pipeline_lighting_options.hpp"
#include "./pipeline_frustum_culling.hpp"
namespace Tyra { namespace Tyra {
@@ -20,6 +21,7 @@ class PipelineOptions {
PipelineOptions() { lighting = nullptr; } PipelineOptions() { lighting = nullptr; }
~PipelineOptions() {} ~PipelineOptions() {}
PipelineFrustumCulling frustumCulling;
PipelineShadingType shadingType; PipelineShadingType shadingType;
bool blendingEnabled; bool blendingEnabled;
bool antiAliasingEnabled; bool antiAliasingEnabled;
@@ -16,6 +16,7 @@
#include "./bag/packaging/stapip_bag_package.hpp" #include "./bag/packaging/stapip_bag_package.hpp"
#include "./bag/packaging/stapip_bag_packager.hpp" #include "./bag/packaging/stapip_bag_packager.hpp"
#include "./stapip_qbuffer_renderer.hpp" #include "./stapip_qbuffer_renderer.hpp"
#include "renderer/3d/pipeline/shared/pipeline_frustum_culling.hpp"
namespace Tyra { namespace Tyra {
@@ -27,7 +28,8 @@ class StaPipCore {
void init(RendererCore* t_core); void init(RendererCore* t_core);
/** Render 3D via "bags" */ /** 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) */ /** Get max vert count of VU1 qbuffer (for optimizations) */
u32 getMaxVertCountByParams(const bool& isSingleColor, u32 getMaxVertCountByParams(const bool& isSingleColor,
@@ -52,7 +54,7 @@ class StaPipCore {
void setMaxVertCount(const u32& count); void setMaxVertCount(const u32& count);
StaPipBagPackager packager; StaPipBagPackager packager;
StaPipQBufferRenderer qbufferRenderer; StaPipQBufferRenderer qbufferRenderer;
void renderPkgs(StaPipBagPackage* packages, u16 count); void renderPkgs(StaPipBagPackage* packages, const bool& doClip, u16 count);
void renderSubpkgs(StaPipBagPackage* packages, u16 count); void renderSubpkgs(StaPipBagPackage* packages, u16 count);
}; };
@@ -16,18 +16,18 @@ namespace Tyra {
class StaPipOptions : public PipelineOptions { class StaPipOptions : public PipelineOptions {
public: public:
StaPipOptions() {} StaPipOptions() { fullClipChecks = false; }
~StaPipOptions() {} ~StaPipOptions() {}
/** /**
* @brief True -> disables "clip against each plane" algorithm. * @brief False -> disables "clip against each plane" algorithm.
* Mandatory, default: false. * Mandatory, default: True.
* *
* Full clip checks are slow, but they are * Full clip checks are slow, but they are
* preventing visual artifacts, which can happen * preventing visual artifacts, which can happen
* for big 3D objects (or objects near camera eyes) * for big 3D objects (or objects near camera eyes)
*/ */
bool noFullClipChecks; bool fullClipChecks;
}; };
} // namespace Tyra } // namespace Tyra
@@ -24,7 +24,7 @@ namespace Tyra {
* Pipeline for static models (StaticMesh). * Pipeline for static models (StaticMesh).
* Supports: * Supports:
* - Full "against each plane" clipping and simple PS2 clipping * - Full "against each plane" clipping and simple PS2 clipping
* (noFullClipChecks), * (fullClipChecks),
* - Force enabled precise frustum culling (checks parts of given mesh) * - Force enabled precise frustum culling (checks parts of given mesh)
* - Modes: color(s), texture+color(s), dir lights, texture + dir lights * - Modes: color(s), texture+color(s), dir lights, texture + dir lights
*/ */
@@ -40,9 +40,9 @@ void DynamicPipeline::render(DynamicMesh* mesh, const DynPipOptions* options) {
auto* infoBag = getInfoBag(mesh, options, &model); auto* infoBag = getInfoBag(mesh, options, &model);
PipelineDirLightsBag* dirLights = nullptr; PipelineDirLightsBag* dirLights = nullptr;
auto frustumCulling = 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()); auto* frameTo = mesh->getFrame(mesh->getNextAnimationFrame());
if (frameTo->getBBox().isInFrustum( if (frameTo->getBBox().isInFrustum(
rendererCore->renderer3D.frustumPlanes.getAll(), model) == rendererCore->renderer3D.frustumPlanes.getAll(), model) ==
@@ -117,7 +117,7 @@ void DynamicPipeline::render(DynamicMesh* mesh, const DynPipOptions* options) {
void DynamicPipeline::setBuffer(DynPipBag* buffers, DynPipBag* buffer, void DynamicPipeline::setBuffer(DynPipBag* buffers, DynPipBag* buffer,
u16* bufferIndex, u16* bufferIndex,
const DynPipFrustumCulling& frustumCulling) { const PipelineFrustumCulling& frustumCulling) {
auto isEndOf1stDBuffer = *bufferIndex == halfBuffersCount - 1; auto isEndOf1stDBuffer = *bufferIndex == halfBuffersCount - 1;
auto isEndOf2ndDBuffer = *bufferIndex == buffersCount - 1; auto isEndOf2ndDBuffer = *bufferIndex == buffersCount - 1;
@@ -130,7 +130,7 @@ void DynamicPipeline::setBuffer(DynPipBag* buffers, DynPipBag* buffer,
sendBuffers[i] = &buffers[offset + i]; sendBuffers[i] = &buffers[offset + i];
core.renderPart(sendBuffers, halfBuffersCount, core.renderPart(sendBuffers, halfBuffersCount,
frustumCulling == DynPipFrustumCulling_Precise); frustumCulling == PipelineFrustumCulling_Precise);
delete[] sendBuffers; delete[] sendBuffers;
} }
@@ -143,7 +143,7 @@ void DynamicPipeline::setBuffer(DynPipBag* buffers, DynPipBag* buffer,
void DynamicPipeline::sendRestOfBuffers( void DynamicPipeline::sendRestOfBuffers(
DynPipBag* buffers, u16* bufferIndex, DynPipBag* buffers, u16* bufferIndex,
const DynPipFrustumCulling& frustumCulling) { const PipelineFrustumCulling& frustumCulling) {
auto isEndOf1stDBuffer = *bufferIndex <= halfBuffersCount - 1; auto isEndOf1stDBuffer = *bufferIndex <= halfBuffersCount - 1;
u32 offset = isEndOf1stDBuffer ? 0 : halfBuffersCount; u32 offset = isEndOf1stDBuffer ? 0 : halfBuffersCount;
@@ -157,7 +157,7 @@ void DynamicPipeline::sendRestOfBuffers(
} }
core.renderPart(sendBuffers, size, core.renderPart(sendBuffers, size,
frustumCulling == DynPipFrustumCulling_Precise); frustumCulling == PipelineFrustumCulling_Precise);
delete[] sendBuffers; delete[] sendBuffers;
} }
@@ -14,12 +14,20 @@
namespace Tyra { namespace Tyra {
MinecraftPipeline::MinecraftPipeline() { latestMode = UndefinedMcpipProgram; } MinecraftPipeline::MinecraftPipeline() {
latestMode = UndefinedMcpipProgram;
spamBuffersCount = 4;
spamBuffers = new McpipBlock**[spamBuffersCount];
spamCounts = new u32[spamBuffersCount];
spammerIndex = 0;
}
MinecraftPipeline::~MinecraftPipeline() { MinecraftPipeline::~MinecraftPipeline() {
if (bbox) { if (bbox) {
delete bbox; delete bbox;
} }
delete[] spamBuffers;
delete[] spamCounts;
} }
void MinecraftPipeline::init(RendererCore* core) { void MinecraftPipeline::init(RendererCore* core) {
@@ -42,35 +50,35 @@ void MinecraftPipeline::initBBox() {
void MinecraftPipeline::render(McpipBlock* blocks, const u32& count, void MinecraftPipeline::render(McpipBlock* blocks, const u32& count,
Texture* t_tex, const bool& isMulti, Texture* t_tex, const bool& isMulti,
const bool& noFullClipChecks) { const bool& fullClipChecks) {
auto texBuffers = rendererCore->texture.useTexture(t_tex); auto texBuffers = rendererCore->texture.useTexture(t_tex);
rendererCore->gs.prim.mapping = 1; rendererCore->gs.prim.mapping = 1;
manager.clearLastProgram(); manager.clearLastProgram();
std::vector<u32> cullIndexes; std::vector<u32> cullIndexes;
if (noFullClipChecks) { if (!fullClipChecks) {
for (u32 i = 0; i < count; i++) cullIndexes.push_back(i); for (u32 i = 0; i < count; i++) cullIndexes.push_back(i);
cull(blocks, cullIndexes, &texBuffers, isMulti); cull(blocks, cullIndexes, &texBuffers, true, isMulti);
return; return;
} else {
u32 culled = 0, clipped = 0;
std::vector<u32> 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<u32> 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 { CoreBBoxFrustum MinecraftPipeline::isInFrustum(const McpipBlock& block) const {
@@ -81,7 +89,7 @@ CoreBBoxFrustum MinecraftPipeline::isInFrustum(const McpipBlock& block) const {
void MinecraftPipeline::cull(McpipBlock* blocks, void MinecraftPipeline::cull(McpipBlock* blocks,
const std::vector<u32>& indexes, const std::vector<u32>& indexes,
RendererCoreTextureBuffers* texBuffers, RendererCoreTextureBuffers* texBuffers,
const bool& isMulti) { const bool& isCullOnly, const bool& isMulti) {
changeMode(McPipCull, false); changeMode(McPipCull, false);
auto maxBlocksPerQBuffer = manager.culler.getMaxBlocksCountPerQBuffer(); auto maxBlocksPerQBuffer = manager.culler.getMaxBlocksCountPerQBuffer();
@@ -100,10 +108,18 @@ void MinecraftPipeline::cull(McpipBlock* blocks,
&blocks[indexes[i * maxBlocksPerQBuffer + j]]; &blocks[indexes[i * maxBlocksPerQBuffer + j]];
} }
manager.cull(blockPointerArray, blockPointerArrayCount, texBuffers, if (isCullOnly) {
isMulti); 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 } // namespace Tyra
@@ -107,8 +107,6 @@ void McpipCull::sendVU1StaticData() {
void McpipCull::addData(packet2_t* packet, McpipBlock** blockPointerArray, void McpipCull::addData(packet2_t* packet, McpipBlock** blockPointerArray,
u32 blockPointerArrayCount, u32 blockPointerArrayCount,
RendererCoreTextureBuffers* texBuffers, bool isMulti) { RendererCoreTextureBuffers* texBuffers, bool isMulti) {
packet2_reset(packet, false);
rendererCore->texture.updateClutBuffer(texBuffers->clut); rendererCore->texture.updateClutBuffer(texBuffers->clut);
packet2_utils_vu_open_unpack( packet2_utils_vu_open_unpack(
@@ -16,8 +16,8 @@ BlockizerProgramsManager::BlockizerProgramsManager() {
lastProgramName = UndefinedMcpipProgram; lastProgramName = UndefinedMcpipProgram;
context = 0; context = 0;
vu1BlockData = BlockNotUploaded; vu1BlockData = BlockNotUploaded;
dynamicPackets[0] = 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(100, 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); staticPacket = packet2_create(2, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
setProgramsCache(); setProgramsCache();
} }
@@ -79,6 +79,32 @@ void BlockizerProgramsManager::uploadBlock(bool isMulti) {
dma_channel_send_packet2(staticPacket, DMA_CHANNEL_VIF1, true); 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, void BlockizerProgramsManager::cull(McpipBlock** blockPointerArray,
u32 blockPointerArrayCount, u32 blockPointerArrayCount,
RendererCoreTextureBuffers* texBuffers, RendererCoreTextureBuffers* texBuffers,
@@ -89,9 +115,12 @@ void BlockizerProgramsManager::cull(McpipBlock** blockPointerArray,
auto* program = repo.getProgram(McpipProgramName::McPipCull); auto* program = repo.getProgram(McpipProgramName::McPipCull);
packet2_reset(currentPacket, false);
culler.addData(currentPacket, blockPointerArray, blockPointerArrayCount, culler.addData(currentPacket, blockPointerArray, blockPointerArrayCount,
texBuffers, isMulti); texBuffers, isMulti);
addProgram(program);
sendPacket(program); sendPacket(program);
} }
@@ -106,10 +135,11 @@ void BlockizerProgramsManager::clip(McpipBlock* block,
clipper.addData(block, isMulti, texBuffers, currentPacket, context); clipper.addData(block, isMulti, texBuffers, currentPacket, context);
addProgram(program);
sendPacket(program); sendPacket(program);
} }
void BlockizerProgramsManager::sendPacket(McpipProgram* program) { void BlockizerProgramsManager::addProgram(McpipProgram* program) {
auto* currentPacket = dynamicPackets[context]; auto* currentPacket = dynamicPackets[context];
if (lastProgramName != program->getName()) { if (lastProgramName != program->getName()) {
@@ -119,6 +149,10 @@ void BlockizerProgramsManager::sendPacket(McpipProgram* program) {
} else { } else {
packet2_utils_vu_add_continue_program(currentPacket); packet2_utils_vu_add_continue_program(currentPacket);
} }
}
void BlockizerProgramsManager::sendPacket(McpipProgram* program) {
auto* currentPacket = dynamicPackets[context];
packet2_utils_vu_add_end_tag(currentPacket); packet2_utils_vu_add_end_tag(currentPacket);
@@ -100,6 +100,8 @@ StaPipBagPackage* StaPipBagPackager::create(u16* o_count,
} }
CoreBBoxFrustum StaPipBagPackager::checkFrustum(const StaPipBagPackage& pkg) { CoreBBoxFrustum StaPipBagPackager::checkFrustum(const StaPipBagPackage& pkg) {
if (!renderBBox) return CoreBBoxFrustum::OUTSIDE_FRUSTUM;
if (pkg.size <= (maxVertCount / 3)) { // Is subpackage if (pkg.size <= (maxVertCount / 3)) { // Is subpackage
auto& bbox = renderBBox->getChildBBox1By3(pkg.indexOf1By3BBox); auto& bbox = renderBBox->getChildBBox1By3(pkg.indexOf1By3BBox);
return bbox.clipIsInFrustum(frustumPlanes->getAll(), *pkg.bag->info->model); return bbox.clipIsInFrustum(frustumPlanes->getAll(), *pkg.bag->info->model);
@@ -47,7 +47,8 @@ u32 StaPipCore::getMaxVertCountByParams(const bool& isSingleColor,
->getMaxVertCount(isSingleColor, qbufferRenderer.getBufferSize()); ->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; if (bag->count <= 0) return;
TYRA_ASSERT(bag->vertices != nullptr, TYRA_ASSERT(bag->vertices != nullptr,
@@ -70,25 +71,33 @@ void StaPipCore::render(StaPipBag* bag, StaPipBagPackagesBBox* bbox) {
TYRA_ASSERT( TYRA_ASSERT(
!bag->texture || (bag->texture->texture && bag->texture->coordinates), !bag->texture || (bag->texture->texture && bag->texture->coordinates),
"If you want texture, please provide texture and coordinates!"); "If you want texture, please provide texture and coordinates!");
TYRA_ASSERT(!(frustumCull == false && bag->info->fullClipChecks == true),
StaPipBagPackagesBBox* renderBbox; "Full clip checks are not supported with frustum culling = off!");
u32 maxVertCount = getMaxVertCountByBag(bag); u32 maxVertCount = getMaxVertCountByBag(bag);
setMaxVertCount(maxVertCount); setMaxVertCount(maxVertCount);
if (!bbox) StaPipBagPackagesBBox* renderBbox = nullptr;
renderBbox =
new StaPipBagPackagesBBox(bag->vertices, bag->count, maxVertCount); CoreBBoxFrustum frustumCheck = OUTSIDE_FRUSTUM;
else
renderBbox = bbox; 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; auto mvp = rendererCore->renderer3D.getViewProj() * *bag->info->model;
if (frustumCheck == OUTSIDE_FRUSTUM) return;
RendererCoreTextureBuffers* texBuffers = nullptr; RendererCoreTextureBuffers* texBuffers = nullptr;
if (bag->texture) { if (bag->texture) {
auto temp = rendererCore->texture.useTexture(bag->texture->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); qbufferRenderer.sendObjectData(bag, &mvp, texBuffers);
packager.setRenderBBox(renderBbox);
qbufferRenderer.setClipperMVP(&mvp); qbufferRenderer.setClipperMVP(&mvp);
qbufferRenderer.setInfo(bag->info); qbufferRenderer.setInfo(bag->info);
if (frustumCheck == IN_FRUSTUM || auto checkYesFrustumInClipYes = // cull all
(frustumCheck == PARTIALLY_IN_FRUSTUM && bag->info->noFullClipChecks)) { 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; u16 packagesCount = 0;
auto biggerPkgs = packager.create(&packagesCount, bag, maxVertCount); auto biggerPkgs = packager.create(&packagesCount, bag, maxVertCount);
Verbose("Material - in frustum. Pkgs: ", packagesCount, Verbose("Material - in frustum. Pkgs: ", packagesCount,
@@ -118,12 +141,13 @@ void StaPipCore::render(StaPipBag* bag, StaPipBagPackagesBBox* bbox) {
qbufferRenderer.cull(buffer); qbufferRenderer.cull(buffer);
} }
delete[] biggerPkgs; delete[] biggerPkgs;
} else if (frustumCheck == PARTIALLY_IN_FRUSTUM) { } else if (checkYesFrustumPartialClipYes || checkYesFrustumPartialClipNo) {
u16 packagesCount = 0; u16 packagesCount = 0;
if (bag->count >= maxVertCount * 2) { auto doClip = checkYesFrustumPartialClipYes;
if (!doClip || bag->count >= maxVertCount * 2) {
auto packages = packager.create(&packagesCount, bag, maxVertCount); auto packages = packager.create(&packagesCount, bag, maxVertCount);
Verbose("Material - partial. Packages: ", packagesCount); Verbose("Material - partial. Packages: ", packagesCount);
renderPkgs(packages, packagesCount); renderPkgs(packages, doClip, packagesCount);
delete[] packages; delete[] packages;
} else { } else {
auto subpkgs = packager.create(&packagesCount, bag, maxVertCount / 3); 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; if (texBuffers) delete texBuffers;
qbufferRenderer.flushBuffers(); qbufferRenderer.flushBuffers();
@@ -141,14 +165,18 @@ void StaPipCore::render(StaPipBag* bag, StaPipBagPackagesBBox* bbox) {
Verbose("Render finished"); 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++) { 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"); Verbose(i, " - package in frustum -> cull");
auto buffer = qbufferRenderer.getBuffer(); auto buffer = qbufferRenderer.getBuffer();
buffer->fillByPointer(packages[i]); buffer->fillByPointer(packages[i]);
qbufferRenderer.cull(buffer); qbufferRenderer.cull(buffer);
} else if (packages[i].isInFrustum == PARTIALLY_IN_FRUSTUM) { } else if (doSubpkgs) {
u16 subpkgsSize = 0; u16 subpkgsSize = 0;
auto packages1By3 = auto packages1By3 =
packager.create(&subpkgsSize, packages[i], maxVertCount / 3); packager.create(&subpkgsSize, packages[i], maxVertCount / 3);
@@ -9,6 +9,7 @@
*/ */
#include "renderer/3d/pipeline/static/static_pipeline.hpp" #include "renderer/3d/pipeline/static/static_pipeline.hpp"
#include "debug/debug.hpp"
namespace Tyra { namespace Tyra {
@@ -27,20 +28,29 @@ void StaticPipeline::render(StaticMesh* mesh, const StaPipOptions* options) {
auto model = mesh->getModelMatrix(); auto model = mesh->getModelMatrix();
auto* infoBag = getInfoBag(mesh, options, &model); 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); if (options && options->lighting) setLightingColorsCache(options->lighting);
for (u32 i = 0; i < mesh->getMaterialsCount(); i++) { for (u32 i = 0; i < mesh->getMaterialsCount(); i++) {
auto* material = mesh->getMaterial(i); auto* material = mesh->getMaterial(i);
auto* materialFrame = material->getFrame(0); 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; StaPipBag bag;
addVertices(materialFrame, &bag); addVertices(materialFrame, &bag);
bag.info = infoBag; bag.info = infoBag;
@@ -48,7 +58,7 @@ void StaticPipeline::render(StaticMesh* mesh, const StaPipOptions* options) {
bag.texture = getTextureBag(material, materialFrame); bag.texture = getTextureBag(material, materialFrame);
bag.lighting = getLightingBag(materialFrame, &model, options); bag.lighting = getLightingBag(materialFrame, &model, options);
core.render(&bag); core.render(&bag, frustumCulling == PipelineFrustumCulling_Precise);
deallocDrawBags(&bag, material); deallocDrawBags(&bag, material);
} }
@@ -71,12 +81,12 @@ PipelineInfoBag* StaticPipeline::getInfoBag(StaticMesh* mesh,
result->antiAliasingEnabled = options->antiAliasingEnabled; result->antiAliasingEnabled = options->antiAliasingEnabled;
result->blendingEnabled = options->blendingEnabled; result->blendingEnabled = options->blendingEnabled;
result->shadingType = options->shadingType; result->shadingType = options->shadingType;
result->noFullClipChecks = options->noFullClipChecks; result->fullClipChecks = options->fullClipChecks;
} else { } else {
result->antiAliasingEnabled = false; result->antiAliasingEnabled = false;
result->blendingEnabled = true; result->blendingEnabled = true;
result->shadingType = TyraShadingFlat; result->shadingType = TyraShadingFlat;
result->noFullClipChecks = false; result->fullClipChecks = false;
} }
result->model = model; result->model = model;