1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-09-03 17:19:46 +02:00

Improving handling game shaders (#302)

* move delete to earlier stage

* lines for better readability

* Added detach shader

* Addition forgotten glDeleteProgram

https://github.com/rwengine/openrw/search?utf8=%E2%9C%93&q=glDeleteProgram&type=
In project there's no necessary clearing call of glDeleteProgram.

* Removing/Closing shader programs

Each shader program should be taken care by glDeleteProgram.
To make it works/usefull, each shader's raw ptr will convertet to unique_ptr
in next commit.

* Converting ShaderProgram's ptr to unique

Actually deleting isn't handled,
so this commit removes memory leak.
This commit is contained in:
Filip 2017-10-29 19:47:52 +01:00 committed by Daniel Evans
parent c54cfa0ae8
commit b9d306ae70
13 changed files with 67 additions and 57 deletions

View File

@ -33,6 +33,7 @@ protected:
GeometryBuffer *lineBuff;
DrawBuffer *dbuff;
//Ownership is handled by worldProg in renderer
Renderer::ShaderProgram *shaderProgram;
GLuint texture;

View File

@ -81,22 +81,22 @@ GameRenderer::GameRenderer(Logger* log, GameData* _data)
renderer->createShader(GameShaders::WorldObject::VertexShader,
GameShaders::WorldObject::FragmentShader);
renderer->setUniformTexture(worldProg, "texture", 0);
renderer->setProgramBlockBinding(worldProg, "SceneData", 1);
renderer->setProgramBlockBinding(worldProg, "ObjectData", 2);
renderer->setUniformTexture(worldProg.get(), "texture", 0);
renderer->setProgramBlockBinding(worldProg.get(), "SceneData", 1);
renderer->setProgramBlockBinding(worldProg.get(), "ObjectData", 2);
particleProg =
renderer->createShader(GameShaders::WorldObject::VertexShader,
GameShaders::Particle::FragmentShader);
renderer->setUniformTexture(particleProg, "texture", 0);
renderer->setProgramBlockBinding(particleProg, "SceneData", 1);
renderer->setProgramBlockBinding(particleProg, "ObjectData", 2);
renderer->setUniformTexture(particleProg.get(), "texture", 0);
renderer->setProgramBlockBinding(particleProg.get(), "SceneData", 1);
renderer->setProgramBlockBinding(particleProg.get(), "ObjectData", 2);
skyProg = renderer->createShader(GameShaders::Sky::VertexShader,
GameShaders::Sky::FragmentShader);
renderer->setProgramBlockBinding(skyProg, "SceneData", 1);
renderer->setProgramBlockBinding(skyProg.get(), "SceneData", 1);
postProg =
renderer->createShader(GameShaders::DefaultPostProcess::VertexShader,
@ -212,6 +212,7 @@ GameRenderer::GameRenderer(Logger* log, GameData* _data)
GameRenderer::~GameRenderer() {
glDeleteFramebuffers(1, &framebufferName);
glDeleteProgram(ssRectProgram);
}
float mix(uint8_t a, uint8_t b, float num) {
@ -283,7 +284,7 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera& camera,
culled = 0;
renderer->useProgram(worldProg);
renderer->useProgram(worldProg.get());
//===============================================================
// Render List Construction
@ -384,9 +385,9 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera& camera,
dp.start = 0;
dp.count = skydomeSegments * skydomeRows * 6;
renderer->useProgram(skyProg);
renderer->setUniform(skyProg, "TopColor", glm::vec4(skyTop, 1.f));
renderer->setUniform(skyProg, "BottomColor", glm::vec4(skyBottom, 1.f));
renderer->useProgram(skyProg.get());
renderer->setUniform(skyProg.get(), "TopColor", glm::vec4(skyTop, 1.f));
renderer->setUniform(skyProg.get(), "BottomColor", glm::vec4(skyBottom, 1.f));
renderer->draw(glm::mat4(), &skyDbuff, dp);
@ -462,7 +463,7 @@ void GameRenderer::renderPostProcess() {
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT |
GL_STENCIL_BUFFER_BIT);
renderer->useProgram(postProg);
renderer->useProgram(postProg.get());
Renderer::DrawParameters wdp;
wdp.start = 0;
@ -473,7 +474,7 @@ void GameRenderer::renderPostProcess() {
}
void GameRenderer::renderEffects(GameWorld* world) {
renderer->useProgram(particleProg);
renderer->useProgram(particleProg.get());
auto cpos = _camera.position;
auto cfwd = glm::normalize(glm::inverse(_camera.rotation) *
@ -614,8 +615,8 @@ void GameRenderer::renderPaths() {
static std::vector<glm::vec3> carlines;
static std::vector<glm::vec3> pedlines;
GLint posAttrib = glGetAttribLocation(worldProgram, "position");
GLint uniModel = glGetUniformLocation(worldProgram, "model");
GLint posAttrib = glGetAttribLocation(worldProg.get(), "position");
GLint uniModel = glGetUniformLocation(worldProg.get(), "model");
glBindVertexArray( vao );

View File

@ -69,7 +69,7 @@ class GameRenderer {
GLuint framebufferName;
GLuint fbTextures[2];
GLuint fbRenderBuffers[1];
Renderer::ShaderProgram* postProg;
std::unique_ptr<Renderer::ShaderProgram> postProg;
/// Texture used to replace textures missing from the data
GLuint m_missingTexture;
@ -79,9 +79,9 @@ public:
~GameRenderer();
/** @todo Clean up all these shader program and location variables */
Renderer::ShaderProgram* worldProg;
Renderer::ShaderProgram* skyProg;
Renderer::ShaderProgram* particleProg;
std::unique_ptr<Renderer::ShaderProgram> worldProg;
std::unique_ptr<Renderer::ShaderProgram> skyProg;
std::unique_ptr<Renderer::ShaderProgram> particleProg;
GLuint ssRectProgram;
GLint ssRectTexture, ssRectColour, ssRectSize, ssRectOffset;

View File

@ -57,14 +57,14 @@ MapRenderer::MapRenderer(std::shared_ptr<Renderer> renderer, GameData* _data)
rectProg = renderer->createShader(MapVertexShader, MapFragmentShader);
renderer->setUniform(rectProg, "colour", glm::vec4(1.f));
renderer->setUniform(rectProg.get(), "colour", glm::vec4(1.f));
}
#define GAME_MAP_SIZE 4000
void MapRenderer::draw(GameWorld* world, const MapInfo& mi) {
renderer->pushDebugGroup("Map");
renderer->useProgram(rectProg);
renderer->useProgram(rectProg.get());
Renderer::DrawParameters dp { };
dp.start = 0;
@ -80,15 +80,15 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi) {
auto proj = renderer->get2DProjection();
glm::mat4 view, model;
renderer->setUniform(rectProg, "proj", proj);
renderer->setUniform(rectProg, "model", glm::mat4());
renderer->setUniform(rectProg, "colour", glm::vec4(0.f, 0.f, 0.f, 1.f));
renderer->setUniform(rectProg.get(), "proj", proj);
renderer->setUniform(rectProg.get(), "model", glm::mat4());
renderer->setUniform(rectProg.get(), "colour", glm::vec4(0.f, 0.f, 0.f, 1.f));
view = glm::translate(view, glm::vec3(mi.screenPosition, 0.f));
if (mi.clipToSize) {
glm::mat4 circleView = glm::scale(view, glm::vec3(mi.screenSize));
renderer->setUniform(rectProg, "view", circleView);
renderer->setUniform(rectProg.get(), "view", circleView);
dp.count = 182;
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
@ -104,7 +104,7 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi) {
view = glm::rotate(view, mi.rotation, glm::vec3(0.f, 0.f, 1.f));
view = glm::translate(
view, glm::vec3(glm::vec2(-1.f, 1.f) * mi.worldCenter, 0.f));
renderer->setUniform(rectProg, "view", view);
renderer->setUniform(rectProg.get(), "view", view);
// radar00 = -x, +y
// incrementing in X, then Y
@ -129,13 +129,13 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi) {
tilemodel = glm::translate(tilemodel, glm::vec3(tc, 0.f));
tilemodel = glm::scale(tilemodel, glm::vec3(tileSize, 1.f));
renderer->setUniform(rectProg, "model", tilemodel);
renderer->setUniform(rectProg.get(), "model", tilemodel);
renderer->drawArrays(glm::mat4(), &rect, dp);
}
// From here on out we will work in screenspace
renderer->setUniform(rectProg, "view", glm::mat4());
renderer->setUniform(rectProg.get(), "view", glm::mat4());
if (mi.clipToSize) {
glDisable(GL_STENCIL_TEST);
@ -148,7 +148,7 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi) {
glm::mat4 model;
model = glm::translate(model, glm::vec3(mi.screenPosition, 0.0f));
model = glm::scale(model, glm::vec3(mi.screenSize * 1.07f));
renderer->setUniform(rectProg, "model", model);
renderer->setUniform(rectProg.get(), "model", model);
renderer->drawArrays(glm::mat4(), &rect, dp);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE,
GL_ZERO);
@ -251,14 +251,14 @@ void MapRenderer::prepareBlip(const glm::vec2& coord, const glm::mat4& view,
model = glm::translate(model, viewPos);
model = glm::scale(model, glm::vec3(size));
model = glm::rotate(model, heading, glm::vec3(0.f, 0.f, 1.f));
renderer->setUniform(rectProg, "model", model);
renderer->setUniform(rectProg.get(), "model", model);
GLuint tex = 0;
if (!texture.empty()) {
auto sprite = data->findSlotTexture("hud", texture);
tex = sprite->getName();
}
renderer->setUniform(rectProg, "colour", colour);
renderer->setUniform(rectProg.get(), "colour", colour);
glBindTexture(GL_TEXTURE_2D, tex);
@ -277,6 +277,6 @@ void MapRenderer::drawBlip(const glm::vec2& coord, const glm::mat4& view,
const MapInfo& mi, glm::vec4 colour, float size) {
drawBlip(coord, view, mi, "", colour, size);
// Draw outline
renderer->setUniform(rectProg, "colour", glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
renderer->setUniform(rectProg.get(), "colour", glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
glDrawArrays(GL_LINE_LOOP, 0, 4);
}

View File

@ -40,7 +40,7 @@ private:
GeometryBuffer circleGeom;
DrawBuffer circle;
Renderer::ShaderProgram* rectProg;
std::unique_ptr<Renderer::ShaderProgram> rectProg;
void prepareBlip(const glm::vec2& coord, const glm::mat4& view,
const MapInfo& mi, const std::string& texture,

View File

@ -51,11 +51,19 @@ GLuint compileShader(GLenum type, const char* source) {
GLuint compileProgram(const char* vertex, const char* fragment) {
GLuint vertexShader = compileShader(GL_VERTEX_SHADER, vertex);
GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragment);
GLuint prog = glCreateProgram();
glAttachShader(prog, vertexShader);
glAttachShader(prog, fragmentShader);
glLinkProgram(prog);
glDetachShader(prog, vertexShader);
glDetachShader(prog, fragmentShader);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
GLint status;
glGetProgramiv(prog, GL_LINK_STATUS, &status);
@ -79,9 +87,6 @@ GLuint compileProgram(const char* vertex, const char* fragment) {
exit(1);
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return prog;
}
@ -177,9 +182,9 @@ std::string OpenGLRenderer::getIDString() const {
return ss.str();
}
Renderer::ShaderProgram* OpenGLRenderer::createShader(const std::string& vert,
std::unique_ptr<Renderer::ShaderProgram> OpenGLRenderer::createShader(const std::string& vert,
const std::string& frag) {
return new OpenGLShaderProgram(compileProgram(vert.c_str(), frag.c_str()));
return std::make_unique<OpenGLShaderProgram>(compileProgram(vert.c_str(), frag.c_str()));
}
void OpenGLRenderer::setProgramBlockBinding(Renderer::ShaderProgram* p,

View File

@ -136,7 +136,7 @@ public:
virtual std::string getIDString() const = 0;
virtual ShaderProgram* createShader(const std::string& vert,
virtual std::unique_ptr<ShaderProgram> createShader(const std::string& vert,
const std::string& frag) = 0;
virtual void useProgram(ShaderProgram* p) = 0;
@ -241,6 +241,9 @@ public:
public:
OpenGLShaderProgram(GLuint p) : program(p) {
}
~OpenGLShaderProgram() {
glDeleteProgram(program);
}
GLuint getName() const {
return program;
@ -263,7 +266,7 @@ public:
std::string getIDString() const override;
ShaderProgram* createShader(const std::string& vert,
std::unique_ptr<ShaderProgram> createShader(const std::string& vert,
const std::string& frag) override;
void setProgramBlockBinding(ShaderProgram* p, const std::string& name,
GLint point) override;

View File

@ -139,7 +139,7 @@ void TextRenderer::setFontTexture(int index, const std::string& texture) {
void TextRenderer::renderText(const TextRenderer::TextInfo& ti,
bool forceColour) {
renderer->getRenderer()->pushDebugGroup("Text");
renderer->getRenderer()->useProgram(textShader);
renderer->getRenderer()->useProgram(textShader.get());
glm::vec2 coord(0.f, 0.f);
glm::vec2 alignment = ti.screenPosition;
@ -281,9 +281,9 @@ void TextRenderer::renderText(const TextRenderer::TextInfo& ti,
}
renderer->getRenderer()->setUniform(
textShader, "proj", renderer->getRenderer()->get2DProjection());
renderer->getRenderer()->setUniformTexture(textShader, "fontTexture", 0);
renderer->getRenderer()->setUniform(textShader, "alignment", alignment);
textShader.get(), "proj", renderer->getRenderer()->get2DProjection());
renderer->getRenderer()->setUniformTexture(textShader.get(), "fontTexture", 0);
renderer->getRenderer()->setUniform(textShader.get(), "alignment", alignment);
gb.uploadVertices(geo);
db.addGeometry(&gb);

View File

@ -60,7 +60,7 @@ private:
GlyphInfo glyphData[GAME_GLYPHS];
GameRenderer* renderer;
Renderer::ShaderProgram* textShader;
std::unique_ptr<Renderer::ShaderProgram> textShader;
GeometryBuffer gb;
DrawBuffer db;

View File

@ -15,10 +15,10 @@ WaterRenderer::WaterRenderer(GameRenderer* renderer) : waterProg(nullptr) {
maskProg = renderer->getRenderer()->createShader(
GameShaders::Mask3D::VertexShader, GameShaders::Mask3D::FragmentShader);
renderer->getRenderer()->setProgramBlockBinding(waterProg, "SceneData", 1);
renderer->getRenderer()->setProgramBlockBinding(maskProg, "SceneData", 1);
renderer->getRenderer()->setProgramBlockBinding(waterProg.get(), "SceneData", 1);
renderer->getRenderer()->setProgramBlockBinding(maskProg.get(), "SceneData", 1);
renderer->getRenderer()->setUniformTexture(waterProg, "data", 1);
renderer->getRenderer()->setUniformTexture(waterProg.get(), "data", 1);
// Generate grid mesh
int gridres = 60;
@ -121,7 +121,7 @@ void WaterRenderer::render(GameRenderer* renderer, GameWorld* world) {
glDrawBuffers(1, buffers);
glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
r->useProgram(maskProg);
r->useProgram(maskProg.get());
r->drawArrays(m, &maskDraw, wdp);
@ -129,17 +129,17 @@ void WaterRenderer::render(GameRenderer* renderer, GameWorld* world) {
glStencilMask(0x00);
glEnable(GL_DEPTH_TEST);
r->useProgram(waterProg);
r->useProgram(waterProg.get());
buffers[0] = GL_COLOR_ATTACHMENT0;
glDrawBuffers(1, buffers);
r->setUniform(waterProg, "time", world->getGameTime());
r->setUniform(waterProg, "waveParams",
r->setUniform(waterProg.get(), "time", world->getGameTime());
r->setUniform(waterProg.get(), "waveParams",
glm::vec2(WATER_SCALE, WATER_HEIGHT));
auto ivp =
glm::inverse(r->getSceneData().projection * r->getSceneData().view);
r->setUniform(waterProg, "inverseVP", ivp);
r->setUniform(waterProg.get(), "inverseVP", ivp);
wdp.count = gridGeom.getCount();
wdp.textures = {waterTex->getName(), dataTexture};

View File

@ -33,8 +33,8 @@ public:
void render(GameRenderer* renderer, GameWorld* world);
private:
Renderer::ShaderProgram* waterProg;
Renderer::ShaderProgram* maskProg;
std::unique_ptr<Renderer::ShaderProgram> waterProg;
std::unique_ptr<Renderer::ShaderProgram> maskProg;
DrawBuffer maskDraw;
GeometryBuffer maskGeom;

View File

@ -68,7 +68,7 @@ RWGame::RWGame(Logger& log, int argc, char* argv[])
debug.setDebugMode(btIDebugDraw::DBG_DrawWireframe |
btIDebugDraw::DBG_DrawConstraints |
btIDebugDraw::DBG_DrawConstraintLimits);
debug.setShaderProgram(renderer.worldProg);
debug.setShaderProgram(renderer.worldProg.get());
data.loadDynamicObjects(config.getGameDataPath() + "/data/object.dat");

View File

@ -92,7 +92,7 @@ void ViewerWidget::paintGL() {
glm::mat4 m(1.f);
r.getRenderer()->useProgram(r.worldProg);
r.getRenderer()->useProgram(r.worldProg.get());
ViewCamera vc;