1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-17 03:53:07 +01:00

Minor performance improvements

This commit is contained in:
ZehMatt
2017-09-18 17:13:12 +02:00
committed by Michael Steenbeek
parent 09517caa88
commit c238265834
7 changed files with 154 additions and 103 deletions

View File

@@ -17,10 +17,53 @@
#pragma once
#include <openrct2/common.h>
#include <vector>
#include "OpenGLAPI.h"
#include "GLSLTypes.h"
#include "TextureCache.h"
template<typename T>
class CommandBatch
{
private:
std::vector<T> _instances;
size_t _numInstances;
public:
CommandBatch()
: _numInstances(0)
{
}
bool empty() const
{
return _numInstances == 0;
}
void reset()
{
_numInstances = 0;
}
T& allocate()
{
if (_numInstances + 1 > _instances.size())
{
_instances.resize((_numInstances + 1) << 1);
}
return _instances[_numInstances++];
}
size_t size() const
{
return _numInstances;
}
const T* data() const
{
return &_instances.at(0);
}
const T& operator[](size_t idx) const
{
return _instances.at(idx);
}
};
struct DrawRectCommand {
uint32 flags;
GLuint sourceFramebuffer;
@@ -35,4 +78,29 @@ struct DrawLineCommand {
sint32 pos[4];
};
typedef DrawImageInstance DrawImageCommand;
// Per-instance data for images
struct DrawImageCommand {
vec4i clip;
sint32 texColourAtlas;
vec4f texColourBounds;
sint32 texMaskAtlas;
vec4f texMaskBounds;
sint32 texPaletteAtlas;
vec4f texPaletteBounds;
sint32 flags;
vec4f colour;
vec4i bounds;
sint32 mask;
enum
{
FLAG_COLOUR = (1 << 0),
FLAG_REMAP = (1 << 1),
FLAG_TRANSPARENT = (1 << 2),
FLAG_TRANSPARENT_SPECIAL = (1 << 3),
};
};
typedef CommandBatch<DrawImageCommand> ImageCommandBatch;
typedef CommandBatch<DrawLineCommand> LineCommandBatch;
typedef CommandBatch<DrawRectCommand> RectCommandBatch;

View File

@@ -35,17 +35,17 @@ DrawImageShader::DrawImageShader() : OpenGLShaderProgram("drawimage")
glVertexAttribIPointer(vIndex, 1, GL_INT, 0, nullptr);
glBindBuffer(GL_ARRAY_BUFFER, _vboInstances);
glVertexAttribIPointer(vClip, 4, GL_INT, sizeof(DrawImageInstance), (void*) offsetof(DrawImageInstance, clip));
glVertexAttribIPointer(vTexColourAtlas, 1, GL_INT, sizeof(DrawImageInstance), (void*) offsetof(DrawImageInstance, texColourAtlas));
glVertexAttribPointer(vTexColourBounds, 4, GL_FLOAT, GL_FALSE, sizeof(DrawImageInstance), (void*) offsetof(DrawImageInstance, texColourBounds));
glVertexAttribIPointer(vTexMaskAtlas, 1, GL_INT, sizeof(DrawImageInstance), (void*) offsetof(DrawImageInstance, texMaskAtlas));
glVertexAttribPointer(vTexMaskBounds, 4, GL_FLOAT, GL_FALSE, sizeof(DrawImageInstance), (void*) offsetof(DrawImageInstance, texMaskBounds));
glVertexAttribIPointer(vTexPaletteAtlas, 1, GL_INT, sizeof(DrawImageInstance), (void*) offsetof(DrawImageInstance, texPaletteAtlas));
glVertexAttribPointer(vTexPaletteBounds, 4, GL_FLOAT, GL_FALSE, sizeof(DrawImageInstance), (void*) offsetof(DrawImageInstance, texPaletteBounds));
glVertexAttribIPointer(vFlags, 1, GL_INT, sizeof(DrawImageInstance), (void*) offsetof(DrawImageInstance, flags));
glVertexAttribPointer(vColour, 4, GL_FLOAT, GL_FALSE, sizeof(DrawImageInstance), (void*) offsetof(DrawImageInstance, colour));
glVertexAttribIPointer(vBounds, 4, GL_INT, sizeof(DrawImageInstance), (void*) offsetof(DrawImageInstance, bounds));
glVertexAttribIPointer(vMask, 1, GL_INT, sizeof(DrawImageInstance), (void*) offsetof(DrawImageInstance, mask));
glVertexAttribIPointer(vClip, 4, GL_INT, sizeof(DrawImageCommand), (void*) offsetof(DrawImageCommand, clip));
glVertexAttribIPointer(vTexColourAtlas, 1, GL_INT, sizeof(DrawImageCommand), (void*) offsetof(DrawImageCommand, texColourAtlas));
glVertexAttribPointer(vTexColourBounds, 4, GL_FLOAT, GL_FALSE, sizeof(DrawImageCommand), (void*) offsetof(DrawImageCommand, texColourBounds));
glVertexAttribIPointer(vTexMaskAtlas, 1, GL_INT, sizeof(DrawImageCommand), (void*) offsetof(DrawImageCommand, texMaskAtlas));
glVertexAttribPointer(vTexMaskBounds, 4, GL_FLOAT, GL_FALSE, sizeof(DrawImageCommand), (void*) offsetof(DrawImageCommand, texMaskBounds));
glVertexAttribIPointer(vTexPaletteAtlas, 1, GL_INT, sizeof(DrawImageCommand), (void*) offsetof(DrawImageCommand, texPaletteAtlas));
glVertexAttribPointer(vTexPaletteBounds, 4, GL_FLOAT, GL_FALSE, sizeof(DrawImageCommand), (void*) offsetof(DrawImageCommand, texPaletteBounds));
glVertexAttribIPointer(vFlags, 1, GL_INT, sizeof(DrawImageCommand), (void*) offsetof(DrawImageCommand, flags));
glVertexAttribPointer(vColour, 4, GL_FLOAT, GL_FALSE, sizeof(DrawImageCommand), (void*) offsetof(DrawImageCommand, colour));
glVertexAttribIPointer(vBounds, 4, GL_INT, sizeof(DrawImageCommand), (void*) offsetof(DrawImageCommand, bounds));
glVertexAttribIPointer(vMask, 1, GL_INT, sizeof(DrawImageCommand), (void*) offsetof(DrawImageCommand, mask));
glEnableVertexAttribArray(vIndex);
glEnableVertexAttribArray(vClip);
@@ -113,12 +113,12 @@ void DrawImageShader::SetPalette(const vec4f *glPalette)
glUniform4fv(uPalette, 256, (const GLfloat *) glPalette);
}
void DrawImageShader::DrawInstances(const std::vector<DrawImageInstance>& instances)
void DrawImageShader::DrawInstances(const ImageCommandBatch& instances)
{
glBindVertexArray(_vao);
glBindBuffer(GL_ARRAY_BUFFER, _vboInstances);
glBufferData(GL_ARRAY_BUFFER, sizeof(instances[0]) * instances.size(), instances.data(), GL_STREAM_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(DrawImageCommand) * instances.size(), instances.data(), GL_STREAM_DRAW);
glDrawArraysInstanced(GL_TRIANGLES, 0, 6, (GLsizei)instances.size());
}

View File

@@ -18,32 +18,10 @@
#include "GLSLTypes.h"
#include "OpenGLShaderProgram.h"
#include "DrawCommands.h"
#include <SDL_pixels.h>
#include <vector>
// Per-instance data for images
struct DrawImageInstance {
vec4i clip;
sint32 texColourAtlas;
vec4f texColourBounds;
sint32 texMaskAtlas;
vec4f texMaskBounds;
sint32 texPaletteAtlas;
vec4f texPaletteBounds;
sint32 flags;
vec4f colour;
vec4i bounds;
sint32 mask;
enum
{
FLAG_COLOUR = (1 << 0),
FLAG_REMAP = (1 << 1),
FLAG_TRANSPARENT = (1 << 2),
FLAG_TRANSPARENT_SPECIAL = (1 << 3),
};
};
class DrawImageShader final : public OpenGLShaderProgram
{
private:
@@ -74,7 +52,7 @@ public:
void SetScreenSize(sint32 width, sint32 height);
void SetPalette(const vec4f *glPalette);
void DrawInstances(const std::vector<DrawImageInstance>& instances);
void DrawInstances(const ImageCommandBatch& instances);
private:
void GetLocations();

View File

@@ -81,9 +81,9 @@ private:
sint32 _clipBottom = 0;
struct {
std::vector<DrawRectCommand> rectangles;
std::vector<DrawLineCommand> lines;
std::vector<DrawImageCommand> images;
RectCommandBatch rectangles;
LineCommandBatch lines;
ImageCommandBatch images;
} _commandBuffers;
public:
@@ -462,7 +462,7 @@ void OpenGLDrawingContext::FillRect(uint32 colour, sint32 left, sint32 top, sint
right += _offsetX;
bottom += _offsetY;
DrawRectCommand command = {};
DrawRectCommand& command = _commandBuffers.rectangles.allocate();
command.sourceFramebuffer = _fillRectShader->GetSourceFramebuffer();
@@ -495,8 +495,6 @@ void OpenGLDrawingContext::FillRect(uint32 colour, sint32 left, sint32 top, sint
command.bounds[1] = top;
command.bounds[2] = right + 1;
command.bounds[3] = bottom + 1;
_commandBuffers.rectangles.push_back(command);
}
void OpenGLDrawingContext::FilterRect(FILTER_PALETTE_ID palette, sint32 left, sint32 top, sint32 right, sint32 bottom)
@@ -509,7 +507,7 @@ void OpenGLDrawingContext::FilterRect(FILTER_PALETTE_ID palette, sint32 left, si
right += _offsetX;
bottom += _offsetY;
DrawRectCommand command = {};
DrawRectCommand& command = _commandBuffers.rectangles.allocate();
// START FILTER
@@ -537,8 +535,6 @@ void OpenGLDrawingContext::FilterRect(FILTER_PALETTE_ID palette, sint32 left, si
command.bounds[1] = top;
command.bounds[2] = right + 1;
command.bounds[3] = bottom + 1;
_commandBuffers.rectangles.push_back(command);
}
void OpenGLDrawingContext::DrawLine(uint32 colour, sint32 x1, sint32 y1, sint32 x2, sint32 y2)
@@ -550,7 +546,7 @@ void OpenGLDrawingContext::DrawLine(uint32 colour, sint32 x1, sint32 y1, sint32
vec4f paletteColour = _engine->GLPalette[colour & 0xFF];
DrawLineCommand command = {};
DrawLineCommand& command = _commandBuffers.lines.allocate();
command.colour = paletteColour;
@@ -564,8 +560,6 @@ void OpenGLDrawingContext::DrawLine(uint32 colour, sint32 x1, sint32 y1, sint32
command.pos[2] = x2;
command.pos[3] = y2;
_commandBuffers.lines.push_back(command);
// Must be rendered in order right now, because it does not yet use depth
FlushCommandBuffers();
}
@@ -665,20 +659,15 @@ void OpenGLDrawingContext::DrawSprite(uint32 image, sint32 x, sint32 y, uint32 t
auto texture2 = _textureCache->GetOrLoadPaletteTexture(image, tertiaryColour, special);
DrawImageCommand command;
DrawImageCommand& command = _commandBuffers.images.allocate();
command.clip = { _clipLeft, _clipTop, _clipRight, _clipBottom };
command.texColourAtlas = texture.index;
command.texColourBounds = texture.normalizedBounds;
command.texColourAtlas = texture->index;
command.texColourBounds = texture->normalizedBounds;
command.texMaskAtlas = 0;
command.texMaskBounds = { 0.0f, 0.0f, 0.0f };
command.texPaletteAtlas = texture2.index;
command.texPaletteBounds = {
texture2.normalizedBounds.x,
texture2.normalizedBounds.y,
(texture2.normalizedBounds.z - texture2.normalizedBounds.x) / (float)(texture2.bounds.z - texture2.bounds.x),
(texture2.normalizedBounds.w - texture2.normalizedBounds.y) / (float)(texture2.bounds.w - texture2.bounds.y)
};
command.texPaletteAtlas = texture2->index;
command.texPaletteBounds = texture2->computedBounds;
command.colour = { 0.0f, 0.0f, 0.0f };
command.bounds = { left, top, right, bottom };
command.mask = 0;
@@ -697,8 +686,6 @@ void OpenGLDrawingContext::DrawSprite(uint32 image, sint32 x, sint32 y, uint32 t
{
command.flags |= DrawImageCommand::FLAG_REMAP;
}
_commandBuffers.images.emplace_back(std::move(command));
}
void OpenGLDrawingContext::DrawSpriteRawMasked(sint32 x, sint32 y, uint32 maskImage, uint32 colourImage)
@@ -745,21 +732,19 @@ void OpenGLDrawingContext::DrawSpriteRawMasked(sint32 x, sint32 y, uint32 maskIm
right += _clipLeft;
bottom += _clipTop;
DrawImageCommand command;
DrawImageCommand& command = _commandBuffers.images.allocate();
command.clip = { _clipLeft, _clipTop, _clipRight, _clipBottom };
command.texColourAtlas = textureColour.index;
command.texColourBounds = textureColour.normalizedBounds;
command.texMaskAtlas = textureMask.index;
command.texMaskBounds = textureMask.normalizedBounds;
command.texColourAtlas = textureColour->index;
command.texColourBounds = textureColour->normalizedBounds;
command.texMaskAtlas = textureMask->index;
command.texMaskBounds = textureMask->normalizedBounds;
command.texPaletteAtlas = 0;
command.texPaletteBounds = {0.0f, 0.0f, 0.0f};
command.flags = 0;
command.colour = {0.0f, 0.0f, 0.0f};
command.bounds = { left, top, right, bottom };
command.mask = 1;
_commandBuffers.images.emplace_back(std::move(command));
}
void OpenGLDrawingContext::DrawSpriteSolid(uint32 image, sint32 x, sint32 y, uint8 colour)
@@ -795,26 +780,19 @@ void OpenGLDrawingContext::DrawSpriteSolid(uint32 image, sint32 x, sint32 y, uin
right += _offsetX;
bottom += _offsetY;
DrawImageCommand command;
DrawImageCommand& command = _commandBuffers.images.allocate();
command.clip = { _clipLeft, _clipTop, _clipRight, _clipBottom };
command.texColourAtlas = texture.index;
command.texColourBounds = texture.normalizedBounds;
command.texColourAtlas = texture->index;
command.texColourBounds = texture->normalizedBounds;
command.texMaskAtlas = 0;
command.texMaskBounds = { 0.0f, 0.0f, 0.0f };
command.texPaletteAtlas = texture.index;
command.texPaletteBounds = {
texture.normalizedBounds.x,
texture.normalizedBounds.y,
(texture.normalizedBounds.z - texture.normalizedBounds.x) / (float)(texture.bounds.z - texture.bounds.x),
(texture.normalizedBounds.w - texture.normalizedBounds.y) / (float)(texture.bounds.w - texture.bounds.y)
};
command.texPaletteAtlas = texture->index;
command.texPaletteBounds = texture->computedBounds;
command.flags = DrawImageCommand::FLAG_COLOUR;
command.colour = paletteColour;
command.bounds = { left, top, right, bottom };
command.mask = 0;
_commandBuffers.images.emplace_back(std::move(command));
}
void OpenGLDrawingContext::DrawGlyph(uint32 image, sint32 x, sint32 y, uint8 * palette)
@@ -848,7 +826,7 @@ void OpenGLDrawingContext::DrawGlyph(uint32 image, sint32 x, sint32 y, uint8 * p
right += _offsetX;
bottom += _offsetY;
DrawImageCommand command;
DrawImageCommand& command = _commandBuffers.images.allocate();
command.clip = { _clipLeft, _clipTop, _clipRight, _clipBottom };
command.texColourAtlas = texture.index;
@@ -861,8 +839,6 @@ void OpenGLDrawingContext::DrawGlyph(uint32 image, sint32 x, sint32 y, uint8 * p
command.colour = { 0.0f, 0.0f, 0.0f };
command.bounds = { left, top, right, bottom };
command.mask = 0;
_commandBuffers.images.emplace_back(std::move(command));
}
void OpenGLDrawingContext::FlushCommandBuffers()
@@ -874,8 +850,10 @@ void OpenGLDrawingContext::FlushCommandBuffers()
void OpenGLDrawingContext::FlushRectangles()
{
for (const auto& command : _commandBuffers.rectangles)
for(size_t n = 0; n < _commandBuffers.rectangles.size(); n++)
{
const auto& command = _commandBuffers.rectangles[n];
_fillRectShader->Use();
_fillRectShader->SetFlags(command.flags);
_fillRectShader->SetSourceFramebuffer(command.sourceFramebuffer);
@@ -884,19 +862,22 @@ void OpenGLDrawingContext::FlushRectangles()
_fillRectShader->Draw(command.bounds[0], command.bounds[1], command.bounds[2], command.bounds[3]);
}
_commandBuffers.rectangles.clear();
_commandBuffers.rectangles.reset();
}
void OpenGLDrawingContext::FlushLines() {
for (const auto& command : _commandBuffers.lines)
void OpenGLDrawingContext::FlushLines()
{
for (size_t n = 0; n < _commandBuffers.lines.size(); n++)
{
const auto& command = _commandBuffers.lines[n];
_drawLineShader->Use();
_drawLineShader->SetColour(command.colour);
_drawLineShader->SetClip(command.clip[0], command.clip[1], command.clip[2], command.clip[3]);
_drawLineShader->Draw(command.pos[0], command.pos[1], command.pos[2], command.pos[3]);
}
_commandBuffers.lines.clear();
_commandBuffers.lines.reset();
}
void OpenGLDrawingContext::FlushImages()
@@ -908,7 +889,7 @@ void OpenGLDrawingContext::FlushImages()
_drawImageShader->Use();
_drawImageShader->DrawInstances(_commandBuffers.images);
_commandBuffers.images.clear();
_commandBuffers.images.reset();
}
void OpenGLDrawingContext::SetDPI(rct_drawpixelinfo * dpi)

View File

@@ -41,27 +41,32 @@ void TextureCache::InvalidateImage(uint32 image)
_atlases[kvp->second.index].Free(kvp->second);
_imageTextureMap.erase(kvp);
}
}
CachedTextureInfo TextureCache::GetOrLoadImageTexture(uint32 image)
const CachedTextureInfo* TextureCache::GetOrLoadImageTexture(uint32 image)
{
image &= 0x7FFFF;
auto kvp = _imageTextureMap.find(image);
if (kvp != _imageTextureMap.end())
{
return kvp->second;
return &kvp->second;
}
auto cacheInfo = LoadImageTexture(image);
_imageTextureMap[image] = cacheInfo;
auto cacheItr = _imageTextureMap.insert(std::make_pair(image, cacheInfo));
return cacheInfo;
return &(cacheItr.first->second);
}
CachedTextureInfo TextureCache::GetOrLoadPaletteTexture(uint32 image, uint32 tertiaryColour, bool special)
const CachedTextureInfo* TextureCache::GetOrLoadPaletteTexture(uint32 image, uint32 tertiaryColour, bool special)
{
if ((image & (IMAGE_TYPE_REMAP | IMAGE_TYPE_REMAP_2_PLUS | IMAGE_TYPE_TRANSPARENT)) == 0)
return CachedTextureInfo{ 0 };
{
static CachedTextureInfo invalidEntry{ 0 };
return &invalidEntry;
}
uint32 uniquePaletteId = image & (IMAGE_TYPE_REMAP | IMAGE_TYPE_REMAP_2_PLUS | IMAGE_TYPE_TRANSPARENT);
if (!(image & IMAGE_TYPE_REMAP_2_PLUS)) {
@@ -82,13 +87,13 @@ CachedTextureInfo TextureCache::GetOrLoadPaletteTexture(uint32 image, uint32 ter
auto kvp = _paletteTextureMap.find(uniquePaletteId);
if (kvp != _paletteTextureMap.end())
{
return kvp->second;
return &kvp->second;
}
auto cacheInfo = LoadPaletteTexture(image, tertiaryColour, special);
_paletteTextureMap[uniquePaletteId] = cacheInfo;
auto cacheItr = _paletteTextureMap.insert(std::make_pair(uniquePaletteId, cacheInfo));
return cacheInfo;
return &(cacheItr.first->second);
}
CachedTextureInfo TextureCache::GetOrLoadGlyphTexture(uint32 image, uint8 * palette)
@@ -172,6 +177,14 @@ CachedTextureInfo TextureCache::LoadImageTexture(uint32 image)
DeleteDPI(dpi);
cacheInfo.computedBounds =
{
cacheInfo.normalizedBounds.x,
cacheInfo.normalizedBounds.y,
(cacheInfo.normalizedBounds.z - cacheInfo.normalizedBounds.x) / (float)(cacheInfo.bounds.z - cacheInfo.bounds.x),
(cacheInfo.normalizedBounds.w - cacheInfo.normalizedBounds.y) / (float)(cacheInfo.bounds.w - cacheInfo.bounds.y)
};
return cacheInfo;
}
@@ -186,6 +199,14 @@ CachedTextureInfo TextureCache::LoadPaletteTexture(uint32 image, uint32 tertiary
glBindTexture(GL_TEXTURE_2D_ARRAY, _atlasesTexture);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, cacheInfo.bounds.x, cacheInfo.bounds.y, cacheInfo.index, dpi.width, dpi.height, 1, GL_RED_INTEGER, GL_UNSIGNED_BYTE, dpi.bits);
cacheInfo.computedBounds =
{
cacheInfo.normalizedBounds.x,
cacheInfo.normalizedBounds.y,
(cacheInfo.normalizedBounds.z - cacheInfo.normalizedBounds.x) / (float)(cacheInfo.bounds.z - cacheInfo.bounds.x),
(cacheInfo.normalizedBounds.w - cacheInfo.normalizedBounds.y) / (float)(cacheInfo.bounds.w - cacheInfo.bounds.y)
};
return cacheInfo;
}
@@ -326,6 +347,7 @@ void TextureCache::FreeTextures()
{
// Free array texture
glDeleteTextures(1, &_atlasesTexture);
_imageTextureMap.clear();
}
rct_drawpixelinfo * TextureCache::CreateDPI(sint32 width, sint32 height)

View File

@@ -67,6 +67,7 @@ struct CachedTextureInfo
GLuint slot;
vec4i bounds;
vec4f normalizedBounds;
vec4f computedBounds;
};
// Represents a texture atlas that images of a given maximum size can be allocated from
@@ -195,8 +196,8 @@ private:
GLint _atlasesTextureIndicesLimit = 0;
std::vector<Atlas> _atlases;
std::unordered_map<uint32, CachedTextureInfo> _imageTextureMap;
std::unordered_map<GlyphId, CachedTextureInfo, GlyphId::Hash, GlyphId::Equal> _glyphTextureMap;
std::unordered_map<uint32, CachedTextureInfo> _imageTextureMap;
std::unordered_map<uint32, CachedTextureInfo> _paletteTextureMap;
SDL_Color _palette[256];
@@ -206,9 +207,9 @@ public:
~TextureCache();
void SetPalette(const SDL_Color * palette);
void InvalidateImage(uint32 image);
CachedTextureInfo GetOrLoadImageTexture(uint32 image);
const CachedTextureInfo* GetOrLoadImageTexture(uint32 image);
CachedTextureInfo GetOrLoadGlyphTexture(uint32 image, uint8 * palette);
CachedTextureInfo GetOrLoadPaletteTexture(uint32 image, uint32 tertiaryColour, bool special);
const CachedTextureInfo* GetOrLoadPaletteTexture(uint32 image, uint32 tertiaryColour, bool special);
GLuint GetAtlasesTexture();

View File

@@ -83,7 +83,6 @@ void paint_session_free(paint_session * session)
static void paint_session_init(paint_session * session, rct_drawpixelinfo * dpi)
{
memset(session, 0, sizeof(paint_session));
session->Unk140E9A8 = dpi;
session->EndOfPaintStructArray = &session->PaintStructs[4000 - 1];
session->NextFreePaintStruct = session->PaintStructs;
@@ -97,6 +96,8 @@ static void paint_session_init(paint_session * session, rct_drawpixelinfo * dpi)
session->PSStringHead = NULL;
session->LastPSString = NULL;
session->WoodenSupportsPrependTo = NULL;
session->CurrentlyDrawnItem = NULL;
session->SurfaceElement = NULL;
}
static void paint_session_add_ps_to_quadrant(paint_session * session, paint_struct * ps, sint32 positionHash)