fixed textures overlapping
This commit is contained in:
@@ -1,11 +1,9 @@
|
|||||||
------------ Tyra's v2.0 roadmap to publish on GitHub ------------
|
------------ Tyra's v2.0 roadmap to publish on GitHub ------------
|
||||||
|
|
||||||
--- H4570
|
--- H4570
|
||||||
- [Renderer] Fix sync problems with textures
|
|
||||||
- [Renderer] Fix color issue in clipper
|
- [Renderer] Fix color issue in clipper
|
||||||
- [Loaders] DFF loader as static Mesh loader
|
- [Loaders] DFF loader as static Mesh loader
|
||||||
- [Game] Update intellisense from docker
|
- [Game] Update intellisense from docker
|
||||||
- [Texture] Test cache hits with large amount of textures (dolphin sample?)
|
|
||||||
- [Demo] Create cool demo which will show all features of Tyra (I will take this one)
|
- [Demo] Create cool demo which will show all features of Tyra (I will take this one)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "renderer/renderer_settings.hpp"
|
#include "renderer/renderer_settings.hpp"
|
||||||
|
#include "./renderer_core_gs_vram.hpp"
|
||||||
|
|
||||||
namespace Tyra {
|
namespace Tyra {
|
||||||
|
|
||||||
@@ -22,23 +23,16 @@ class RendererCoreGS {
|
|||||||
prim_t prim;
|
prim_t prim;
|
||||||
lod_t lod;
|
lod_t lod;
|
||||||
zbuffer_t zBuffer;
|
zbuffer_t zBuffer;
|
||||||
|
RendererCoreGSVRam vram;
|
||||||
|
|
||||||
void init(RendererSettings* settings);
|
void init(RendererSettings* settings);
|
||||||
|
|
||||||
void flipBuffers();
|
void flipBuffers();
|
||||||
|
|
||||||
float getVRamFreeSpaceInMB() const {
|
|
||||||
return 4.0F - spaceOccupiedByFrameBuffers - spaceOccupiedByZBuffer -
|
|
||||||
vramMargin;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
constexpr static float gsCenter = 4096.0F;
|
constexpr static float gsCenter = 4096.0F;
|
||||||
constexpr static float screenCenter = gsCenter / 2.0F;
|
constexpr static float screenCenter = gsCenter / 2.0F;
|
||||||
constexpr static float vramMargin =
|
|
||||||
0.003F; // We don't have perfectly 4MB of VRAM
|
|
||||||
|
|
||||||
float spaceOccupiedByFrameBuffers, spaceOccupiedByZBuffer;
|
|
||||||
RendererSettings* settings;
|
RendererSettings* settings;
|
||||||
framebuffer_t frameBuffers[2];
|
framebuffer_t frameBuffers[2];
|
||||||
packet2_t* flipPacket;
|
packet2_t* flipPacket;
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "renderer/renderer_settings.hpp"
|
||||||
|
#include "renderer/core/texture/models/texture.hpp"
|
||||||
|
|
||||||
|
namespace Tyra {
|
||||||
|
|
||||||
|
class RendererCoreGSVRam {
|
||||||
|
public:
|
||||||
|
RendererCoreGSVRam();
|
||||||
|
~RendererCoreGSVRam();
|
||||||
|
|
||||||
|
const float& getFreeSpaceInMB();
|
||||||
|
|
||||||
|
float getSizeInMB(const Texture& texture);
|
||||||
|
float getSizeInMB(const TextureData& texData);
|
||||||
|
float getSizeInMB(int width, const int& height, const int& psm,
|
||||||
|
const int& alignment);
|
||||||
|
|
||||||
|
int allocate(const TextureData& texData);
|
||||||
|
int allocateBuffer(const int& width, const int& height, const int& psm);
|
||||||
|
|
||||||
|
/** Free texture, FIFO order */
|
||||||
|
void free(const int& address);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int allocate(const int& width, const int& height, const int& psm,
|
||||||
|
const int& alignment);
|
||||||
|
|
||||||
|
int getSize(int width, const int& height, const int& psm,
|
||||||
|
const int& alignment);
|
||||||
|
|
||||||
|
static constexpr float ptr2MB = 262144.0F;
|
||||||
|
bool touched;
|
||||||
|
int pointer;
|
||||||
|
float cachedFreeSpace;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Tyra
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
# ______ ____ ___
|
|
||||||
# | \/ ____| |___|
|
|
||||||
# | | | \ | |
|
|
||||||
#-----------------------------------------------------------------------
|
|
||||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
|
||||||
# Licenced under Apache License 2.0
|
|
||||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <tamtypes.h>
|
|
||||||
#include <draw_buffers.h>
|
|
||||||
#include <vector>
|
|
||||||
#include "renderer/core/texture/models/texture.hpp"
|
|
||||||
#include "./renderer_texture_cm_analysis.hpp"
|
|
||||||
#include "../renderer_core_texture_buffers.hpp"
|
|
||||||
|
|
||||||
namespace Tyra {
|
|
||||||
|
|
||||||
class RendererTextureCacheManager {
|
|
||||||
public:
|
|
||||||
RendererTextureCacheManager();
|
|
||||||
~RendererTextureCacheManager();
|
|
||||||
|
|
||||||
void onFrameChange();
|
|
||||||
|
|
||||||
void addRequestedTexture(Texture* texture);
|
|
||||||
|
|
||||||
u32 getTextureIdToDealloc(
|
|
||||||
const std::vector<RendererCoreTextureBuffers>& currentAllocs);
|
|
||||||
|
|
||||||
private:
|
|
||||||
RendererTextureCMAnalysis statistics;
|
|
||||||
|
|
||||||
void tryAddIdThatNotExistInAnalysis(
|
|
||||||
std::vector<u32>* result,
|
|
||||||
const std::vector<RendererCoreTextureBuffers>& currentAllocs,
|
|
||||||
const std::vector<u32>& analysis);
|
|
||||||
|
|
||||||
void addIdThatExistInAnalysisButIsOnTheBottom(
|
|
||||||
std::vector<u32>* result,
|
|
||||||
const std::vector<RendererCoreTextureBuffers>& currentAllocs,
|
|
||||||
const std::vector<u32>& analysis);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Tyra
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
/*
|
|
||||||
# ______ ____ ___
|
|
||||||
# | \/ ____| |___|
|
|
||||||
# | | | \ | |
|
|
||||||
#-----------------------------------------------------------------------
|
|
||||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
|
||||||
# Licenced under Apache License 2.0
|
|
||||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include "debug/debug.hpp"
|
|
||||||
#include <tamtypes.h>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace Tyra {
|
|
||||||
|
|
||||||
struct RendererTextureCMAnalysisWeight {
|
|
||||||
u32 id;
|
|
||||||
u16 weight;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RendererTextureCMAnalysisOccurence {
|
|
||||||
u32 id;
|
|
||||||
u8 occurence;
|
|
||||||
};
|
|
||||||
|
|
||||||
class RendererTextureCMAnalysis {
|
|
||||||
public:
|
|
||||||
RendererTextureCMAnalysis();
|
|
||||||
~RendererTextureCMAnalysis();
|
|
||||||
|
|
||||||
void changeFrame();
|
|
||||||
|
|
||||||
void addNewRequest(const u32& id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns top list (from most used to least used) of textures to be
|
|
||||||
* deallocated.
|
|
||||||
*
|
|
||||||
* @param count Number of textures to be returned.
|
|
||||||
*/
|
|
||||||
std::vector<u32> getTopTextureIdsForNextChanges(const u8& count);
|
|
||||||
|
|
||||||
bool isReady();
|
|
||||||
|
|
||||||
bool isProbablyNotCorrect();
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<u32>*current, *last;
|
|
||||||
std::vector<u32> buffers[2];
|
|
||||||
u32 currentIndex;
|
|
||||||
|
|
||||||
void flipBuffers();
|
|
||||||
|
|
||||||
std::vector<u32> getNextTextureIds(const u8& count);
|
|
||||||
|
|
||||||
std::vector<RendererTextureCMAnalysisOccurence> getOccurencesForTextureIds(
|
|
||||||
const std::vector<u32>& textureIds);
|
|
||||||
|
|
||||||
std::vector<u32> getTextureIdsUnique(const std::vector<u32>& textureIds);
|
|
||||||
|
|
||||||
std::vector<RendererTextureCMAnalysisWeight> getWeights(
|
|
||||||
const std::vector<u32>& uniqueTexIds,
|
|
||||||
const std::vector<RendererTextureCMAnalysisOccurence>& occurencies);
|
|
||||||
|
|
||||||
std::vector<u32> weightsToResult(
|
|
||||||
std::vector<RendererTextureCMAnalysisWeight>* weights);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Tyra
|
|
||||||
@@ -47,7 +47,7 @@ class Texture {
|
|||||||
|
|
||||||
const TextureData& getCoreData() const { return *core; }
|
const TextureData& getCoreData() const { return *core; }
|
||||||
|
|
||||||
TextureData* getClutData() { return clut; }
|
const TextureData* getClutData() const { return clut; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get texture name.
|
* Get texture name.
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
#include "./texture_repository.hpp"
|
#include "./texture_repository.hpp"
|
||||||
#include "./renderer_core_texture_sender.hpp"
|
#include "./renderer_core_texture_sender.hpp"
|
||||||
#include "renderer/core/paths/path3/path3.hpp"
|
#include "renderer/core/paths/path3/path3.hpp"
|
||||||
#include "./cache_manager/renderer_texture_cache_manager.hpp"
|
|
||||||
#include "./renderer_core_texture_buffers.hpp"
|
#include "./renderer_core_texture_buffers.hpp"
|
||||||
|
|
||||||
namespace Tyra {
|
namespace Tyra {
|
||||||
@@ -33,14 +32,10 @@ class RendererCoreTexture {
|
|||||||
/** Called by renderer during initialization */
|
/** Called by renderer during initialization */
|
||||||
void init(RendererCoreGS* gs, Path3* path3);
|
void init(RendererCoreGS* gs, Path3* path3);
|
||||||
|
|
||||||
/** Called by renderer during beginFrame() */
|
|
||||||
void onFrameChange();
|
|
||||||
|
|
||||||
/** Called by renderer during rendering */
|
/** Called by renderer during rendering */
|
||||||
void updateClutBuffer(texbuffer_t* clutBuffer);
|
void updateClutBuffer(texbuffer_t* clutBuffer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RendererTextureCacheManager cacheManager;
|
|
||||||
std::vector<RendererCoreTextureBuffers> currentAllocations;
|
std::vector<RendererCoreTextureBuffers> currentAllocations;
|
||||||
|
|
||||||
void initClut();
|
void initClut();
|
||||||
@@ -48,6 +43,7 @@ class RendererCoreTexture {
|
|||||||
void unregisterAllocation(const u32& textureId);
|
void unregisterAllocation(const u32& textureId);
|
||||||
RendererCoreTextureBuffers getAllocatedBuffersByTextureId(const u32& id);
|
RendererCoreTextureBuffers getAllocatedBuffersByTextureId(const u32& id);
|
||||||
|
|
||||||
|
RendererCoreGS* gs;
|
||||||
RendererCoreTextureSender sender;
|
RendererCoreTextureSender sender;
|
||||||
Path3* path3;
|
Path3* path3;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -31,19 +31,14 @@ class RendererCoreTextureSender {
|
|||||||
|
|
||||||
void deallocate(const RendererCoreTextureBuffers& texBuffers);
|
void deallocate(const RendererCoreTextureBuffers& texBuffers);
|
||||||
|
|
||||||
float getFreeVRamInMB();
|
|
||||||
|
|
||||||
float getSizeInMB(texbuffer_t* texBuffer);
|
float getSizeInMB(texbuffer_t* texBuffer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float allocatedVRamMemForTextures;
|
|
||||||
RendererCoreGS* gs;
|
RendererCoreGS* gs;
|
||||||
Path3* path3;
|
Path3* path3;
|
||||||
TextureBpp getBppByPsm(const u32& psm);
|
TextureBpp getBppByPsm(const u32& psm);
|
||||||
texbuffer_t* allocateTextureCore(Texture* t_texture);
|
texbuffer_t* allocateTextureCore(Texture* t_texture);
|
||||||
texbuffer_t* allocateTextureClut(Texture* t_texture);
|
texbuffer_t* allocateTextureClut(Texture* t_texture);
|
||||||
|
|
||||||
u8 isTextureVRAMAllocated, isVSyncEnabled;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Tyra
|
} // namespace Tyra
|
||||||
|
|||||||
@@ -16,10 +16,10 @@
|
|||||||
namespace Tyra {
|
namespace Tyra {
|
||||||
|
|
||||||
DynamicMesh::DynamicMesh(const MeshBuilderData& data) : Mesh(data) {
|
DynamicMesh::DynamicMesh(const MeshBuilderData& data) : Mesh(data) {
|
||||||
TYRA_ASSERT(framesCount > 1, "Frames count must be greater than 1");
|
|
||||||
|
|
||||||
framesCount = data.framesCount;
|
framesCount = data.framesCount;
|
||||||
|
|
||||||
|
TYRA_ASSERT(framesCount > 1, "Frames count must be greater than 1");
|
||||||
|
|
||||||
frames = new MeshFrame*[framesCount];
|
frames = new MeshFrame*[framesCount];
|
||||||
for (u32 i = 0; i < framesCount; i++) {
|
for (u32 i = 0; i < framesCount; i++) {
|
||||||
frames[i] = new MeshFrame(data, i);
|
frames[i] = new MeshFrame(data, i);
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ namespace Tyra {
|
|||||||
|
|
||||||
RendererCoreGS::RendererCoreGS() {
|
RendererCoreGS::RendererCoreGS() {
|
||||||
context = 0;
|
context = 0;
|
||||||
spaceOccupiedByFrameBuffers = 0;
|
|
||||||
spaceOccupiedByZBuffer = 0;
|
|
||||||
currentField = 0;
|
currentField = 0;
|
||||||
}
|
}
|
||||||
RendererCoreGS::~RendererCoreGS() {
|
RendererCoreGS::~RendererCoreGS() {
|
||||||
@@ -56,28 +54,25 @@ void RendererCoreGS::allocateBuffers() {
|
|||||||
frameBuffers[0].width = static_cast<unsigned int>(settings->getWidth());
|
frameBuffers[0].width = static_cast<unsigned int>(settings->getWidth());
|
||||||
frameBuffers[0].height = static_cast<unsigned int>(settings->getHeight());
|
frameBuffers[0].height = static_cast<unsigned int>(settings->getHeight());
|
||||||
frameBuffers[0].mask = 0;
|
frameBuffers[0].mask = 0;
|
||||||
const u16 fpsm = 32;
|
|
||||||
frameBuffers[0].psm = GS_PSM_32;
|
frameBuffers[0].psm = GS_PSM_32;
|
||||||
frameBuffers[0].address =
|
frameBuffers[0].address =
|
||||||
graph_vram_allocate(frameBuffers[0].width, frameBuffers[0].height,
|
vram.allocateBuffer(frameBuffers[0].width, frameBuffers[0].height,
|
||||||
frameBuffers[0].psm, GRAPH_ALIGN_PAGE);
|
frameBuffers[0].psm);
|
||||||
|
|
||||||
frameBuffers[1].width = frameBuffers[0].width;
|
frameBuffers[1].width = frameBuffers[0].width;
|
||||||
frameBuffers[1].height = frameBuffers[0].height;
|
frameBuffers[1].height = frameBuffers[0].height;
|
||||||
frameBuffers[1].mask = frameBuffers[0].mask;
|
frameBuffers[1].mask = frameBuffers[0].mask;
|
||||||
frameBuffers[1].psm = frameBuffers[0].psm;
|
frameBuffers[1].psm = frameBuffers[0].psm;
|
||||||
frameBuffers[1].address =
|
frameBuffers[1].address =
|
||||||
graph_vram_allocate(frameBuffers[1].width, frameBuffers[1].height,
|
vram.allocateBuffer(frameBuffers[1].width, frameBuffers[1].height,
|
||||||
frameBuffers[1].psm, GRAPH_ALIGN_PAGE);
|
frameBuffers[1].psm);
|
||||||
|
|
||||||
zBuffer.enable = DRAW_ENABLE;
|
zBuffer.enable = DRAW_ENABLE;
|
||||||
zBuffer.mask = 0;
|
zBuffer.mask = 0;
|
||||||
zBuffer.method = ZTEST_METHOD_GREATER_EQUAL;
|
zBuffer.method = ZTEST_METHOD_GREATER_EQUAL;
|
||||||
const u16 zpsm = 32;
|
|
||||||
zBuffer.zsm = GS_ZBUF_32;
|
zBuffer.zsm = GS_ZBUF_32;
|
||||||
zBuffer.address =
|
zBuffer.address = vram.allocateBuffer(frameBuffers[0].width, frameBuffers[0].height,
|
||||||
graph_vram_allocate(frameBuffers[0].width, frameBuffers[0].height,
|
zBuffer.zsm);
|
||||||
zBuffer.zsm, GRAPH_ALIGN_PAGE);
|
|
||||||
|
|
||||||
graph_initialize(frameBuffers[1].address, frameBuffers[1].width,
|
graph_initialize(frameBuffers[1].address, frameBuffers[1].width,
|
||||||
frameBuffers[1].height, frameBuffers[1].psm, 0, 0);
|
frameBuffers[1].height, frameBuffers[1].psm, 0, 0);
|
||||||
@@ -93,17 +88,6 @@ void RendererCoreGS::allocateBuffers() {
|
|||||||
// frameBuffers[1].psm, 0, 0);
|
// frameBuffers[1].psm, 0, 0);
|
||||||
// graph_enable_output();
|
// 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!");
|
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) {
|
void RendererCore::beginFrame(const CameraInfo3D& cameraInfo) {
|
||||||
renderer3D.update(cameraInfo);
|
renderer3D.update(cameraInfo);
|
||||||
texture.onFrameChange();
|
|
||||||
Threading::switchThread();
|
Threading::switchThread();
|
||||||
path3.clearScreen(&gs.zBuffer, bgColor);
|
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() {}
|
RendererCoreTexture::~RendererCoreTexture() {}
|
||||||
|
|
||||||
void RendererCoreTexture::onFrameChange() { cacheManager.onFrameChange(); }
|
|
||||||
|
|
||||||
void RendererCoreTexture::init(RendererCoreGS* t_gs, Path3* t_path3) {
|
void RendererCoreTexture::init(RendererCoreGS* t_gs, Path3* t_path3) {
|
||||||
|
gs = t_gs;
|
||||||
sender.init(t_path3, t_gs);
|
sender.init(t_path3, t_gs);
|
||||||
path3 = t_path3;
|
path3 = t_path3;
|
||||||
initClut();
|
initClut();
|
||||||
@@ -39,29 +38,16 @@ void RendererCoreTexture::updateClutBuffer(texbuffer_t* clutBuffer) {
|
|||||||
RendererCoreTextureBuffers RendererCoreTexture::useTexture(Texture* t_tex) {
|
RendererCoreTextureBuffers RendererCoreTexture::useTexture(Texture* t_tex) {
|
||||||
TYRA_ASSERT(t_tex != nullptr, "Provided nullptr texture!");
|
TYRA_ASSERT(t_tex != nullptr, "Provided nullptr texture!");
|
||||||
|
|
||||||
// cacheManager.addRequestedTexture(t_tex);
|
|
||||||
|
|
||||||
auto allocated = getAllocatedBuffersByTextureId(t_tex->getId());
|
auto allocated = getAllocatedBuffersByTextureId(t_tex->getId());
|
||||||
if (allocated.id != 0) return allocated;
|
if (allocated.id != 0) return allocated;
|
||||||
|
|
||||||
// TODO: FIXME!
|
if (gs->vram.getSizeInMB(*t_tex) >= gs->vram.getFreeSpaceInMB()) {
|
||||||
if (currentAllocations.size()) {
|
|
||||||
// if (t_tex->getSizeInMB() > sender.getFreeVRamInMB()) {
|
|
||||||
for (int i = currentAllocations.size() - 1; i >= 0; i--) {
|
for (int i = currentAllocations.size() - 1; i >= 0; i--) {
|
||||||
sender.deallocate(currentAllocations[i]);
|
sender.deallocate(currentAllocations[i]);
|
||||||
}
|
}
|
||||||
currentAllocations.clear();
|
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);
|
auto newTexBuffer = sender.allocate(t_tex);
|
||||||
path3->sendTexture(t_tex, newTexBuffer);
|
path3->sendTexture(t_tex, newTexBuffer);
|
||||||
registerAllocation(newTexBuffer);
|
registerAllocation(newTexBuffer);
|
||||||
|
|||||||
@@ -13,10 +13,7 @@
|
|||||||
|
|
||||||
namespace Tyra {
|
namespace Tyra {
|
||||||
|
|
||||||
RendererCoreTextureSender::RendererCoreTextureSender() {
|
RendererCoreTextureSender::RendererCoreTextureSender() {}
|
||||||
isTextureVRAMAllocated = false;
|
|
||||||
allocatedVRamMemForTextures = 0;
|
|
||||||
}
|
|
||||||
RendererCoreTextureSender::~RendererCoreTextureSender() {}
|
RendererCoreTextureSender::~RendererCoreTextureSender() {}
|
||||||
|
|
||||||
void RendererCoreTextureSender::init(Path3* t_path3, RendererCoreGS* t_gs) {
|
void RendererCoreTextureSender::init(Path3* t_path3, RendererCoreGS* t_gs) {
|
||||||
@@ -47,36 +44,28 @@ float RendererCoreTextureSender::getSizeInMB(texbuffer_t* texBuffer) {
|
|||||||
void RendererCoreTextureSender::deallocate(
|
void RendererCoreTextureSender::deallocate(
|
||||||
const RendererCoreTextureBuffers& texBuffers) {
|
const RendererCoreTextureBuffers& texBuffers) {
|
||||||
if (texBuffers.clut != nullptr && texBuffers.clut->width > 0) {
|
if (texBuffers.clut != nullptr && texBuffers.clut->width > 0) {
|
||||||
graph_vram_free(texBuffers.clut->address);
|
gs->vram.free(texBuffers.clut->address);
|
||||||
delete texBuffers.clut;
|
delete texBuffers.clut;
|
||||||
}
|
}
|
||||||
|
|
||||||
graph_vram_free(texBuffers.core->address);
|
gs->vram.free(texBuffers.core->address);
|
||||||
|
|
||||||
float deallocateSize = getSizeInMB(texBuffers.core);
|
|
||||||
|
|
||||||
delete texBuffers.core;
|
delete texBuffers.core;
|
||||||
|
|
||||||
allocatedVRamMemForTextures -= deallocateSize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
texbuffer_t* RendererCoreTextureSender::allocateTextureCore(
|
texbuffer_t* RendererCoreTextureSender::allocateTextureCore(
|
||||||
Texture* t_texture) {
|
Texture* t_texture) {
|
||||||
auto* result = new texbuffer_t;
|
auto* result = new texbuffer_t;
|
||||||
|
const auto& core = t_texture->getCoreData();
|
||||||
|
|
||||||
result->width = t_texture->getWidth();
|
result->width = t_texture->getWidth();
|
||||||
result->psm = t_texture->getCoreData().psm;
|
result->psm = core.psm;
|
||||||
result->info.components = t_texture->getCoreData().components;
|
result->info.components = core.components;
|
||||||
|
|
||||||
TYRA_ASSERT(t_texture->getSizeInMB() <= getFreeVRamInMB(),
|
auto address = gs->vram.allocate(core);
|
||||||
"Not enough VRAM memory for texture!");
|
|
||||||
|
|
||||||
auto address =
|
|
||||||
graph_vram_allocate(t_texture->getWidth(), t_texture->getHeight(),
|
|
||||||
result->psm, GRAPH_ALIGN_BLOCK);
|
|
||||||
TYRA_ASSERT(address > 0, "Texture buffer allocation error, no memory!");
|
TYRA_ASSERT(address > 0, "Texture buffer allocation error, no memory!");
|
||||||
result->address = address;
|
result->address = address;
|
||||||
|
|
||||||
allocatedVRamMemForTextures += t_texture->getSizeInMB();
|
|
||||||
result->info.width = draw_log2(t_texture->getWidth());
|
result->info.width = draw_log2(t_texture->getWidth());
|
||||||
result->info.height = draw_log2(t_texture->getHeight());
|
result->info.height = draw_log2(t_texture->getHeight());
|
||||||
result->info.function = TEXTURE_FUNCTION_MODULATE;
|
result->info.function = TEXTURE_FUNCTION_MODULATE;
|
||||||
@@ -92,8 +81,7 @@ texbuffer_t* RendererCoreTextureSender::allocateTextureClut(
|
|||||||
result->psm = clut->psm;
|
result->psm = clut->psm;
|
||||||
result->info.components = clut->components;
|
result->info.components = clut->components;
|
||||||
|
|
||||||
auto address = graph_vram_allocate(clut->width, clut->height, result->psm,
|
auto address = gs->vram.allocate(*clut);
|
||||||
GRAPH_ALIGN_BLOCK);
|
|
||||||
TYRA_ASSERT(address > 0, "Texture clut buffer allocation error, no memory!");
|
TYRA_ASSERT(address > 0, "Texture clut buffer allocation error, no memory!");
|
||||||
result->address = address;
|
result->address = address;
|
||||||
|
|
||||||
@@ -103,10 +91,6 @@ texbuffer_t* RendererCoreTextureSender::allocateTextureClut(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
float RendererCoreTextureSender::getFreeVRamInMB() {
|
|
||||||
return gs->getVRamFreeSpaceInMB() - allocatedVRamMemForTextures;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextureBpp RendererCoreTextureSender::getBppByPsm(const u32& psm) {
|
TextureBpp RendererCoreTextureSender::getBppByPsm(const u32& psm) {
|
||||||
if (psm == GS_PSM_32) {
|
if (psm == GS_PSM_32) {
|
||||||
return bpp32;
|
return bpp32;
|
||||||
|
|||||||
Reference in New Issue
Block a user