perf: optimize texture caching

This commit is contained in:
2026-01-16 17:56:41 +08:00
parent 562599b8b4
commit 94502e6104
3 changed files with 44 additions and 21 deletions

View File

@@ -81,7 +81,7 @@ void BoardRenderer::drawPiece(std::optional<std::pair<int, int>> selectedPiece)
// 确定棋子颜色 // 确定棋子颜色
SDL_Color color; SDL_Color color;
if (selectedPiece && selectedPiece->first == row && selectedPiece->second == col) { if (selectedPiece && selectedPiece->first == row && selectedPiece->second == col) {
// 选中状态的棋子 // 选中状态的棋子,暂时不渲染黄色的选中状态
color = m_colors.selected; color = m_colors.selected;
isSelected = true; isSelected = true;
} else { } else {
@@ -102,7 +102,7 @@ void BoardRenderer::drawPiece(std::optional<std::pair<int, int>> selectedPiece)
//SDL_RenderFillRect(m_renderer, &rect); //SDL_RenderFillRect(m_renderer, &rect);
bool isRenderered = false; bool isRenderered = false;
auto texture = m_textureManager->createTextureFromRect(rect.x, rect.y, rect, color); auto texture = m_textureManager->createTextureFromRect(rect, color);
//SDL_FRect srect = {0, 0, rect.w, rect.h}; //SDL_FRect srect = {0, 0, rect.w, rect.h};
if (isSelected) { if (isSelected) {
// 如果被选择 // 如果被选择
@@ -286,15 +286,31 @@ void BoardRenderer::renderBlackOverlay() {
void BoardRenderer::handleGamePieceEvent(GamePieceEvent event, int row, int col) { void BoardRenderer::handleGamePieceEvent(GamePieceEvent event, int row, int col) {
auto area = getBoardArea(); auto area = getBoardArea();
// 计算棋子中心位置
float x = area.x + col * area.cellSize; float x = area.x + col * area.cellSize;
float y = area.y + row * area.cellSize; float y = area.y + row * area.cellSize;
float pieceRadius = m_cellSize * m_pieceRadiusRatio / 2.0f; float pieceRadius = m_cellSize * m_pieceRadiusRatio / 2.0f;
SDL_FRect rect{
x + (area.cellSize - pieceRadius * 2) / 2.0f,
y + (area.cellSize - pieceRadius * 2) / 2.0f,
pieceRadius * 2,
pieceRadius * 2
};
const Piece* piece = m_board->getPieceAt(row, col);
if (!piece) {
SDL_Log("BoardRenderer: piece is null\n");
return;
}
SDL_Color color = (piece->getPieceOwner() == PlayerID::P1) ?
m_colors.P1 : m_colors.P2;
switch (event) { switch (event) {
case (GamePieceEvent::REMOVE_PIECE): case (GamePieceEvent::REMOVE_PIECE):
//SDL_Log("BoardRenderer: try to destory texture\n"); //SDL_Log("BoardRenderer: try to destory texture\n");
m_textureManager->destoryTexture( m_textureManager->destoryTexture(rect, color);
x + (area.cellSize - pieceRadius * 2) / 2.0f,
y + (area.cellSize - pieceRadius * 2) / 2.0f);
break; break;
case (GamePieceEvent::PLACE_PIECE): case (GamePieceEvent::PLACE_PIECE):
break; break;

View File

@@ -24,10 +24,10 @@ void TextureManager::cleanupAllTexture() {
SDL_Texture* TextureManager::createTextureFromRect(int x, int y, SDL_FRect& rect, SDL_Color& color) { SDL_Texture* TextureManager::createTextureFromRect(SDL_FRect& rect, SDL_Color& color) {
// 先在缓存中查找是否存在 // 先在缓存中查找是否存在
auto it = getTexture(x, y); auto it = getTexture(rect, color);
if(it) { if(it) {
return it; return it;
} }
@@ -53,37 +53,44 @@ SDL_Texture* TextureManager::createTextureFromRect(int x, int y, SDL_FRect& rect
SDL_FRect renderRect = {0, 0, rect.w, rect.h}; SDL_FRect renderRect = {0, 0, rect.w, rect.h};
SDL_RenderFillRect(m_renderer, &renderRect); SDL_RenderFillRect(m_renderer, &renderRect);
// 缓存 // 缓存
m_cacheTexture.emplace(makeHash(x, y), newTexture); m_cacheTexture.emplace(makeHash(rect, color), newTexture);
// 恢复渲染目标 // 恢复渲染目标
SDL_SetRenderTarget(m_renderer, currentTexture); SDL_SetRenderTarget(m_renderer, currentTexture);
return newTexture; return newTexture;
} }
size_t TextureManager::makeHash(int x, int y) { size_t TextureManager::makeHash(SDL_FRect& rect, SDL_Color& color) {
// 分别计算字体名称和大小的哈希值 // 分别计算字体名称和大小的哈希值
size_t h1 = std::hash<int>{}(x); size_t h1 = std::hash<float>{}(rect.x);
size_t h2 = std::hash<int>{}(y); size_t h2 = std::hash<float>{}(rect.y);
size_t h3 = std::hash<float>{}(rect.w);
size_t h4 = std::hash<float>{}(rect.h);
size_t h5 = std::hash<Uint8>{}(color.r);
size_t h6 = std::hash<Uint8>{}(color.g);
size_t h7 = std::hash<Uint8>{}(color.b);
size_t h8 = std::hash<Uint8>{}(color.a);
// 组合两个哈希值使用XOR运算和位左移组合两个独立的哈希值 // 组合两个哈希值使用XOR运算和位左移组合两个独立的哈希值
// 这样可以确保不同的fontID或ptSize组合都会产生不同的哈希值 // 这样可以确保不同的fontID或ptSize组合都会产生不同的哈希值
return h1 ^ (h2 << 1); return h1 ^ (h2 << 1) ^ (h3 << 2) ^ (h4 << 3) ^ (h5 << 4) ^ (h6 << 5) ^ (h7 << 6) ^ (h8 << 7);
} }
SDL_Texture* TextureManager::getTexture(int x, int y) { SDL_Texture* TextureManager::getTexture(SDL_FRect& rect, SDL_Color& color) {
auto key = makeHash(x, y); auto key = makeHash(rect, color);
auto it = m_cacheTexture.find(key); auto it = m_cacheTexture.find(key);
if (it != m_cacheTexture.end()) { if (it != m_cacheTexture.end()) {
return it->second; return it->second;
} else { } else {
SDL_Log("TextureManager: texture %d %d not exist!", x, y); SDL_Log("TextureManager: texture not exist!");
return nullptr; return nullptr;
} }
} }
bool TextureManager::destoryTexture(int x, int y) { bool TextureManager::destoryTexture(SDL_FRect& rect, SDL_Color& color) {
int key = makeHash(x, y); int key = makeHash(rect, color);
auto it = m_cacheTexture.find(key); auto it = m_cacheTexture.find(key);
if (it == m_cacheTexture.end()) { if (it == m_cacheTexture.end()) {
SDL_Log("can't find the texture\n"); SDL_Log("can't find the texture\n");

View File

@@ -10,13 +10,13 @@ public:
~TextureManager(); ~TextureManager();
SDL_Texture* createTextureFromRect(int x, int y, SDL_FRect& rect, SDL_Color& coler); SDL_Texture* createTextureFromRect(SDL_FRect& rect, SDL_Color& coler);
void cleanupAllTexture(); void cleanupAllTexture();
SDL_Texture* getTexture(int x, int y); SDL_Texture* getTexture(SDL_FRect& rect, SDL_Color& color);
bool destoryTexture(int x, int y); bool destoryTexture(SDL_FRect& rect, SDL_Color& color);
private: private:
@@ -24,6 +24,6 @@ private:
std::unordered_map<size_t, SDL_Texture*> m_cacheTexture; std::unordered_map<size_t, SDL_Texture*> m_cacheTexture;
size_t makeHash(int x, int y); size_t makeHash(SDL_FRect& rect, SDL_Color& color);
}; };