spamming with vu1 packets 2
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<u32>(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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user