fixed textures overlapping

This commit is contained in:
h4570
2022-07-29 19:04:55 +02:00
parent 7ec6bb71b8
commit 97946e1c6d
16 changed files with 221 additions and 434 deletions
@@ -16,10 +16,10 @@
namespace Tyra {
DynamicMesh::DynamicMesh(const MeshBuilderData& data) : Mesh(data) {
TYRA_ASSERT(framesCount > 1, "Frames count must be greater than 1");
framesCount = data.framesCount;
TYRA_ASSERT(framesCount > 1, "Frames count must be greater than 1");
frames = new MeshFrame*[framesCount];
for (u32 i = 0; i < framesCount; i++) {
frames[i] = new MeshFrame(data, i);
@@ -25,8 +25,6 @@ namespace Tyra {
RendererCoreGS::RendererCoreGS() {
context = 0;
spaceOccupiedByFrameBuffers = 0;
spaceOccupiedByZBuffer = 0;
currentField = 0;
}
RendererCoreGS::~RendererCoreGS() {
@@ -56,28 +54,25 @@ void RendererCoreGS::allocateBuffers() {
frameBuffers[0].width = static_cast<unsigned int>(settings->getWidth());
frameBuffers[0].height = static_cast<unsigned int>(settings->getHeight());
frameBuffers[0].mask = 0;
const u16 fpsm = 32;
frameBuffers[0].psm = GS_PSM_32;
frameBuffers[0].address =
graph_vram_allocate(frameBuffers[0].width, frameBuffers[0].height,
frameBuffers[0].psm, GRAPH_ALIGN_PAGE);
vram.allocateBuffer(frameBuffers[0].width, frameBuffers[0].height,
frameBuffers[0].psm);
frameBuffers[1].width = frameBuffers[0].width;
frameBuffers[1].height = frameBuffers[0].height;
frameBuffers[1].mask = frameBuffers[0].mask;
frameBuffers[1].psm = frameBuffers[0].psm;
frameBuffers[1].address =
graph_vram_allocate(frameBuffers[1].width, frameBuffers[1].height,
frameBuffers[1].psm, GRAPH_ALIGN_PAGE);
vram.allocateBuffer(frameBuffers[1].width, frameBuffers[1].height,
frameBuffers[1].psm);
zBuffer.enable = DRAW_ENABLE;
zBuffer.mask = 0;
zBuffer.method = ZTEST_METHOD_GREATER_EQUAL;
const u16 zpsm = 32;
zBuffer.zsm = GS_ZBUF_32;
zBuffer.address =
graph_vram_allocate(frameBuffers[0].width, frameBuffers[0].height,
zBuffer.zsm, GRAPH_ALIGN_PAGE);
zBuffer.address = vram.allocateBuffer(frameBuffers[0].width, frameBuffers[0].height,
zBuffer.zsm);
graph_initialize(frameBuffers[1].address, frameBuffers[1].width,
frameBuffers[1].height, frameBuffers[1].psm, 0, 0);
@@ -93,17 +88,6 @@ void RendererCoreGS::allocateBuffers() {
// frameBuffers[1].psm, 0, 0);
// graph_enable_output();
spaceOccupiedByZBuffer =
((frameBuffers[0].width / 100.0F) * (frameBuffers[0].height / 100.0F) *
(zpsm / 100.0F)) /
8.0F;
spaceOccupiedByFrameBuffers =
((frameBuffers[0].width / 100.0F) * (frameBuffers[0].height / 100.0F) *
(fpsm / 100.0F)) /
8.0F;
spaceOccupiedByFrameBuffers *= 2;
TYRA_LOG("Framebuffers, zBuffer set and allocated!");
}
@@ -0,0 +1,149 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include <dma.h>
#include <graph.h>
#include <gs_psm.h>
#include "renderer/core/gs/renderer_core_gs_vram.hpp"
#define GS_VRAM_TEXTURE_ALIGNMENT GRAPH_ALIGN_BLOCK
#define GS_VRAM_BUFFER_ALIGNMENT GRAPH_ALIGN_PAGE
namespace Tyra {
RendererCoreGSVRam::RendererCoreGSVRam() {
touched = false;
pointer = 0;
cachedFreeSpace = getFreeSpaceInMB();
}
RendererCoreGSVRam::~RendererCoreGSVRam() {}
const float& RendererCoreGSVRam::getFreeSpaceInMB() {
if (touched) {
cachedFreeSpace = (GRAPH_VRAM_MAX_WORDS - pointer) / ptr2MB;
touched = false;
}
return cachedFreeSpace;
}
float RendererCoreGSVRam::getSizeInMB(const Texture& texture) {
float result = getSizeInMB(texture.getCoreData());
if (texture.getClutData() != nullptr) {
result += getSizeInMB(*texture.getClutData());
}
return result;
}
float RendererCoreGSVRam::getSizeInMB(const TextureData& texData) {
return getSizeInMB(texData.width, texData.height, texData.psm,
GS_VRAM_TEXTURE_ALIGNMENT);
}
float RendererCoreGSVRam::getSizeInMB(int width, const int& height,
const int& psm, const int& alignment) {
return getSize(width, height, psm, alignment) / ptr2MB;
}
int RendererCoreGSVRam::allocate(const TextureData& texData) {
return allocate(texData.width, texData.height, texData.psm,
GS_VRAM_TEXTURE_ALIGNMENT);
}
int RendererCoreGSVRam::allocateBuffer(const int& width, const int& height,
const int& psm) {
return allocate(width, height, psm, GS_VRAM_BUFFER_ALIGNMENT);
}
int RendererCoreGSVRam::allocate(const int& width, const int& height,
const int& psm, const int& alignment) {
auto size = getSize(width, height, psm, alignment);
pointer += size;
// If the pointer overflows the vram size
if (pointer > GRAPH_VRAM_MAX_WORDS) {
pointer -= size;
return -1;
}
touched = true;
return pointer - size;
}
void RendererCoreGSVRam::free(const int& address) {
pointer = address;
touched = true;
}
int RendererCoreGSVRam::getSize(int width, const int& height, const int& psm,
const int& alignment) {
int size = 0;
// First correct the buffer width to be a multiple of 64 or 128
// If the width is less than or equal to 16, then it's a palette
if (width > 16) {
switch (psm) {
case GS_PSM_8:
case GS_PSM_4:
case GS_PSM_8H:
case GS_PSM_4HL:
case GS_PSM_4HH:
width = -128 & (width + 127);
break;
default:
width = -64 & (width + 63);
break;
}
}
// Texture storage size is in pixels/word
switch (psm) {
case GS_PSM_4:
size = width * (height >> 3);
break;
case GS_PSM_8:
size = width * (height >> 2);
break;
case GS_PSM_24:
case GS_PSM_32:
case GS_PSM_8H:
case GS_PSM_4HL:
case GS_PSM_4HH:
case GS_PSMZ_24:
case GS_PSMZ_32:
size = width * height;
break;
case GS_PSM_16:
case GS_PSM_16S:
case GS_PSMZ_16:
case GS_PSMZ_16S:
size = width * (height >> 1);
break;
default:
return 0;
}
if (alignment == GS_VRAM_TEXTURE_ALIGNMENT) {
// TODO: Without this hack, textures are overlapping ourselves
size += 1024 * 2;
}
// The buffer size is dependent on alignment
size = -alignment & (size + (alignment - 1));
return size;
}
} // namespace Tyra
@@ -29,7 +29,6 @@ void RendererCore::setClearScreenColor(const Color& color) { bgColor = color; }
void RendererCore::beginFrame(const CameraInfo3D& cameraInfo) {
renderer3D.update(cameraInfo);
texture.onFrameChange();
Threading::switchThread();
path3.clearScreen(&gs.zBuffer, bgColor);
}
@@ -1,74 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "renderer/core/texture/cache_manager/renderer_texture_cache_manager.hpp"
namespace Tyra {
RendererTextureCacheManager::RendererTextureCacheManager() {}
RendererTextureCacheManager::~RendererTextureCacheManager() {}
void RendererTextureCacheManager::onFrameChange() { statistics.changeFrame(); }
void RendererTextureCacheManager::addRequestedTexture(Texture* texture) {
statistics.addNewRequest(texture->getId());
}
u32 RendererTextureCacheManager::getTextureIdToDealloc(
const std::vector<RendererCoreTextureBuffers>& currentAllocs) {
if (!statistics.isReady() || statistics.isProbablyNotCorrect()) {
return currentAllocs.size() > 0 ? currentAllocs.at(0).id : 0;
}
u8 tuner = currentAllocs.size() > 254 ? 254 : currentAllocs.size();
if (tuner >= 6) {
tuner /= 3;
} else if (tuner >= 4) {
tuner /= 2;
} else {
tuner = 1;
}
std::vector<u32> temp;
auto probableTextureIds = statistics.getTopTextureIdsForNextChanges(tuner);
tryAddIdThatNotExistInAnalysis(&temp, currentAllocs, probableTextureIds);
if (temp.size() == 0) {
addIdThatExistInAnalysisButIsOnTheBottom(&temp, currentAllocs,
probableTextureIds);
}
return temp.at(0);
}
void RendererTextureCacheManager::tryAddIdThatNotExistInAnalysis(
std::vector<u32>* result,
const std::vector<RendererCoreTextureBuffers>& currentAllocs,
const std::vector<u32>& analysis) {
for (u32 i = 0; i < currentAllocs.size(); i++) {
if (std::find(analysis.begin(), analysis.end(), currentAllocs.at(i).id) ==
analysis.end()) {
result->push_back(currentAllocs.at(i).id);
break;
}
}
}
void RendererTextureCacheManager::addIdThatExistInAnalysisButIsOnTheBottom(
std::vector<u32>* result,
const std::vector<RendererCoreTextureBuffers>& currentAllocs,
const std::vector<u32>& analysis) {
u32 lastId = analysis.at(analysis.size() - 1);
result->push_back(lastId);
}
} // namespace Tyra
@@ -1,152 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "renderer/core/texture/cache_manager/renderer_texture_cm_analysis.hpp"
namespace Tyra {
RendererTextureCMAnalysis::RendererTextureCMAnalysis() {
last = &buffers[0];
current = &buffers[1];
currentIndex = 0;
}
RendererTextureCMAnalysis::~RendererTextureCMAnalysis() {}
void RendererTextureCMAnalysis::changeFrame() {
flipBuffers();
current->clear();
currentIndex = 0;
}
void RendererTextureCMAnalysis::addNewRequest(const u32& id) {
current->push_back(id);
currentIndex++;
}
std::vector<u32> RendererTextureCMAnalysis::getTopTextureIdsForNextChanges(
const u8& count) {
TYRA_ASSERT(!isProbablyNotCorrect(),
"Analysis not available, because its probably not correct - "
"internal error");
auto nextTextureIds = getNextTextureIds(count);
auto occurences = getOccurencesForTextureIds(nextTextureIds);
auto uniqueTextureIds = getTextureIdsUnique(nextTextureIds);
auto weights = getWeights(uniqueTextureIds, occurences);
auto result = weightsToResult(&weights);
return result;
}
std::vector<u32> RendererTextureCMAnalysis::getNextTextureIds(const u8& count) {
std::vector<u32> result;
for (u32 i = 0; i < count; i++) {
u32 index = i + currentIndex;
u32 offset = index >= last->size() ? index - last->size() : index;
result.push_back(last->at(offset));
}
return result;
}
std::vector<RendererTextureCMAnalysisOccurence>
RendererTextureCMAnalysis::getOccurencesForTextureIds(
const std::vector<u32>& textureIds) {
std::vector<RendererTextureCMAnalysisOccurence> result;
for (u8 i = 0; i < textureIds.size(); i++) {
// If not exist, add with 1 occurence
if (std::find_if(result.begin(), result.end(),
[textureIds,
i](const RendererTextureCMAnalysisOccurence& occurence) {
return occurence.id == textureIds[i];
}) == result.end()) {
result.push_back({textureIds[i], 1});
} else {
// If exist, increase occurence
auto occurence = std::find_if(
result.begin(), result.end(),
[textureIds, i](const RendererTextureCMAnalysisOccurence& occurence) {
return occurence.id == textureIds[i];
});
occurence->occurence++;
}
}
return result;
}
std::vector<u32> RendererTextureCMAnalysis::getTextureIdsUnique(
const std::vector<u32>& textureIds) {
std::vector<u32> result;
for (u8 i = 0; i < textureIds.size(); i++) {
if (std::find(result.begin(), result.end(), textureIds[i]) ==
result.end()) {
result.push_back(textureIds[i]);
}
}
return result;
}
std::vector<RendererTextureCMAnalysisWeight>
RendererTextureCMAnalysis::getWeights(
const std::vector<u32>& uniqueTexIds,
const std::vector<RendererTextureCMAnalysisOccurence>& occurencies) {
std::vector<RendererTextureCMAnalysisWeight> result;
for (u8 i = 0; i < uniqueTexIds.size(); i++) {
u16 weight = uniqueTexIds.size() - i;
for (u8 j = 0; j < occurencies.size(); j++) {
if (occurencies[j].id == uniqueTexIds[i]) {
weight *= occurencies[j].occurence;
break;
}
}
result.push_back({uniqueTexIds[i], weight});
}
return result;
}
std::vector<u32> RendererTextureCMAnalysis::weightsToResult(
std::vector<RendererTextureCMAnalysisWeight>* weights) {
std::sort(weights->begin(), weights->end(),
[](const auto& a, const auto& b) { return a.weight > b.weight; });
std::vector<u32> result;
for (u8 i = 0; i < weights->size(); i++) {
result.push_back(weights->at(i).id);
}
return result;
}
bool RendererTextureCMAnalysis::isReady() { return last->size() != 0; }
bool RendererTextureCMAnalysis::isProbablyNotCorrect() {
return currentIndex > last->size();
}
void RendererTextureCMAnalysis::flipBuffers() {
if (current == &buffers[0]) {
current = &buffers[1];
last = &buffers[0];
} else {
current = &buffers[0];
last = &buffers[1];
}
}
} // namespace Tyra
@@ -16,9 +16,8 @@ RendererCoreTexture::RendererCoreTexture() {}
RendererCoreTexture::~RendererCoreTexture() {}
void RendererCoreTexture::onFrameChange() { cacheManager.onFrameChange(); }
void RendererCoreTexture::init(RendererCoreGS* t_gs, Path3* t_path3) {
gs = t_gs;
sender.init(t_path3, t_gs);
path3 = t_path3;
initClut();
@@ -39,29 +38,16 @@ void RendererCoreTexture::updateClutBuffer(texbuffer_t* clutBuffer) {
RendererCoreTextureBuffers RendererCoreTexture::useTexture(Texture* t_tex) {
TYRA_ASSERT(t_tex != nullptr, "Provided nullptr texture!");
// cacheManager.addRequestedTexture(t_tex);
auto allocated = getAllocatedBuffersByTextureId(t_tex->getId());
if (allocated.id != 0) return allocated;
// TODO: FIXME!
if (currentAllocations.size()) {
// if (t_tex->getSizeInMB() > sender.getFreeVRamInMB()) {
if (gs->vram.getSizeInMB(*t_tex) >= gs->vram.getFreeSpaceInMB()) {
for (int i = currentAllocations.size() - 1; i >= 0; i--) {
sender.deallocate(currentAllocations[i]);
}
currentAllocations.clear();
}
// while (t_tex->getSizeInMB() > sender.getFreeVRamInMB()) {
// auto idToDealloc =
// cacheManager.getTextureIdToDealloc(currentAllocations);
// auto buffToDealloc = getAllocatedBuffersByTextureId(idToDealloc);
// TYRA_LOG("Deallocate(", buffToDealloc.id, ")");
// sender.deallocate(buffToDealloc);
// unregisterAllocation(idToDealloc);
// }
auto newTexBuffer = sender.allocate(t_tex);
path3->sendTexture(t_tex, newTexBuffer);
registerAllocation(newTexBuffer);
@@ -13,10 +13,7 @@
namespace Tyra {
RendererCoreTextureSender::RendererCoreTextureSender() {
isTextureVRAMAllocated = false;
allocatedVRamMemForTextures = 0;
}
RendererCoreTextureSender::RendererCoreTextureSender() {}
RendererCoreTextureSender::~RendererCoreTextureSender() {}
void RendererCoreTextureSender::init(Path3* t_path3, RendererCoreGS* t_gs) {
@@ -47,36 +44,28 @@ float RendererCoreTextureSender::getSizeInMB(texbuffer_t* texBuffer) {
void RendererCoreTextureSender::deallocate(
const RendererCoreTextureBuffers& texBuffers) {
if (texBuffers.clut != nullptr && texBuffers.clut->width > 0) {
graph_vram_free(texBuffers.clut->address);
gs->vram.free(texBuffers.clut->address);
delete texBuffers.clut;
}
graph_vram_free(texBuffers.core->address);
float deallocateSize = getSizeInMB(texBuffers.core);
gs->vram.free(texBuffers.core->address);
delete texBuffers.core;
allocatedVRamMemForTextures -= deallocateSize;
}
texbuffer_t* RendererCoreTextureSender::allocateTextureCore(
Texture* t_texture) {
auto* result = new texbuffer_t;
const auto& core = t_texture->getCoreData();
result->width = t_texture->getWidth();
result->psm = t_texture->getCoreData().psm;
result->info.components = t_texture->getCoreData().components;
result->psm = core.psm;
result->info.components = core.components;
TYRA_ASSERT(t_texture->getSizeInMB() <= getFreeVRamInMB(),
"Not enough VRAM memory for texture!");
auto address =
graph_vram_allocate(t_texture->getWidth(), t_texture->getHeight(),
result->psm, GRAPH_ALIGN_BLOCK);
auto address = gs->vram.allocate(core);
TYRA_ASSERT(address > 0, "Texture buffer allocation error, no memory!");
result->address = address;
allocatedVRamMemForTextures += t_texture->getSizeInMB();
result->info.width = draw_log2(t_texture->getWidth());
result->info.height = draw_log2(t_texture->getHeight());
result->info.function = TEXTURE_FUNCTION_MODULATE;
@@ -92,8 +81,7 @@ texbuffer_t* RendererCoreTextureSender::allocateTextureClut(
result->psm = clut->psm;
result->info.components = clut->components;
auto address = graph_vram_allocate(clut->width, clut->height, result->psm,
GRAPH_ALIGN_BLOCK);
auto address = gs->vram.allocate(*clut);
TYRA_ASSERT(address > 0, "Texture clut buffer allocation error, no memory!");
result->address = address;
@@ -103,10 +91,6 @@ texbuffer_t* RendererCoreTextureSender::allocateTextureClut(
return result;
}
float RendererCoreTextureSender::getFreeVRamInMB() {
return gs->getVRamFreeSpaceInMB() - allocatedVRamMemForTextures;
}
TextureBpp RendererCoreTextureSender::getBppByPsm(const u32& psm) {
if (psm == GS_PSM_32) {
return bpp32;