Skip to content

Commit

Permalink
renderer: store shader usage in opengl context
Browse files Browse the repository at this point in the history
  • Loading branch information
TheJJ committed Dec 21, 2019
1 parent 11ba40f commit f5182e4
Show file tree
Hide file tree
Showing 11 changed files with 108 additions and 37 deletions.
11 changes: 11 additions & 0 deletions libopenage/renderer/opengl/context.cpp
Expand Up @@ -223,4 +223,15 @@ void GlContext::set_vsync(bool on) {
}
}


const std::weak_ptr<GlShaderProgram> &GlContext::get_current_program() const {
return this->last_program;
}


void GlContext::set_current_program(const std::shared_ptr<GlShaderProgram> &prog) {
this->last_program = prog;
}


}}} // openage::renderer::opengl
11 changes: 11 additions & 0 deletions libopenage/renderer/opengl/context.h
Expand Up @@ -11,6 +11,8 @@ namespace openage {
namespace renderer {
namespace opengl {

class GlShaderProgram;

/// Stores information about context capabilities and limitations.
struct gl_context_capabilities {
/// The maximum number of vertex attributes in a shader.
Expand Down Expand Up @@ -55,6 +57,12 @@ class GlContext {
/// and throws an exception if it did. Note that it's static.
static void check_error();

/// Returns a handle to the last-activated shader program
const std::weak_ptr<GlShaderProgram> &get_current_program() const;

/// Store the last-activated shader program
void set_current_program(const std::shared_ptr<GlShaderProgram> &);

private:
/// The associated SDL window is held here so the context remains active.
std::shared_ptr<SDL_Window> window;
Expand All @@ -64,6 +72,9 @@ class GlContext {

/// Context capabilities.
gl_context_capabilities capabilities{};

// The last-active shader program
std::weak_ptr<GlShaderProgram> last_program;
};

}}} // openage::renderer::opengl
13 changes: 11 additions & 2 deletions libopenage/renderer/opengl/renderer.cpp
Expand Up @@ -120,8 +120,17 @@ void GlRenderer::render(const std::shared_ptr<RenderPass> &pass) {
}

auto in = std::dynamic_pointer_cast<GlUniformInput>(obj.unif_in);
auto geom = std::dynamic_pointer_cast<GlGeometry>(obj.geometry);
std::static_pointer_cast<GlShaderProgram>(in->get_program())->execute_with(in, geom);
auto program = std::static_pointer_cast<GlShaderProgram>(in->get_program());

// this also calls program->use()
program->update_uniforms(in);

// draw the geometry
if (obj.geometry != nullptr) {
auto geom = std::dynamic_pointer_cast<GlGeometry>(obj.geometry);
// TODO read obj.blend + family
geom->draw();
}
}
}

Expand Down
36 changes: 26 additions & 10 deletions libopenage/renderer/opengl/shader_program.cpp
Expand Up @@ -284,6 +284,11 @@ GlShaderProgram::GlShaderProgram(const std::shared_ptr<GlContext> &context,


void GlShaderProgram::use() {
// the setup doesn't need to be done if this program is already active.
if (this->in_use()) {
return;
}

if (!this->validated) {
// TODO(Vtec234): validation depends on the context state, so this might be worth calling
// more than once. However, once per frame is probably too much.
Expand All @@ -295,27 +300,43 @@ void GlShaderProgram::use() {

glUseProgram(*this->handle);

// store this program as the active one
this->context->set_current_program(
std::static_pointer_cast<GlShaderProgram>(
this->shared_from_this()
)
);

for (auto const &pair : this->textures_per_texunits) {
// We have to bind the texture to their texture units here because
// the texture unit bindings are global to the context. Each time
// the shader switches, it is possible that some other shader overwrote
// these, and since we want the uniform values to persist across execute_with
// calls, we have to set them more often than just on execute_with.
// these, and since we want the uniform values to persist across update_uniforms
// calls, we have to set them more often than just on update_uniforms.
glActiveTexture(GL_TEXTURE0 + pair.first);
glBindTexture(GL_TEXTURE_2D, pair.second);

// By the time we call bind, the texture may have been deleted, but if it's fixed
// afterwards using execute_with, the render state will still be fine, so we can ignore
// afterwards using update_uniforms, the render state will still be fine, so we can ignore
// this error.
// TODO this will swallow actual errors elsewhere, and should be avoided. how?
// probably by holding the texture object as shared_ptr as long as it is bound
glGetError();
}
}

void GlShaderProgram::execute_with(std::shared_ptr<GlUniformInput> const& unif_in, std::shared_ptr<GlGeometry> const& geom) {

bool GlShaderProgram::in_use() const {
return this->context->get_current_program().lock() == this->shared_from_this();
}


void GlShaderProgram::update_uniforms(std::shared_ptr<GlUniformInput> const& unif_in) {
ENSURE(unif_in->get_program() == this->shared_from_this(), "Uniform input passed to different shader than it was created with.");

this->use();
if (not this->in_use()) {
this->use();
}

uint8_t const* data = unif_in->update_data.data();
for (auto const &pair : unif_in->update_offs) {
Expand Down Expand Up @@ -371,11 +392,6 @@ void GlShaderProgram::execute_with(std::shared_ptr<GlUniformInput> const& unif_i
throw Error(MSG(err) << "Tried to upload unknown uniform type to GL shader.");
}
}

if (geom != nullptr) {
// TODO read obj.blend + family
geom->draw();
}
}

std::map<size_t, resources::vertex_input_t> GlShaderProgram::vertex_attributes() const {
Expand Down
9 changes: 5 additions & 4 deletions libopenage/renderer/opengl/shader_program.h
Expand Up @@ -30,10 +30,11 @@ class GlShaderProgram final : public ShaderProgram, public GlSimpleObject {
/// Bind this program as the currently used one in the OpenGL context.
void use();

/// Does what the description of Renderable specifies - updates the uniform values
/// and draws the Geometry if it's not nullptr. If geometry is null, only the
/// uniform values are updated.
void execute_with(std::shared_ptr<GlUniformInput> const&, std::shared_ptr<GlGeometry> const&);
/// Check if this program is currently in use in the OpenGL context.
bool in_use() const;

/// Updates the uniform values with the given input specification.
void update_uniforms(std::shared_ptr<GlUniformInput> const&);

bool has_uniform(const char*) override;

Expand Down
11 changes: 6 additions & 5 deletions libopenage/renderer/opengl/window.cpp
Expand Up @@ -26,8 +26,8 @@ GlWindow::GlWindow(const char *title, size_t width, size_t height)
title,
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
this->size.first,
this->size.second,
this->size[0],
this->size[1],
window_flags
),
[] (SDL_Window *window) {
Expand All @@ -48,9 +48,9 @@ GlWindow::GlWindow(const char *title, size_t width, size_t height)


void GlWindow::set_size(size_t width, size_t height) {
if (this->size.first != width || this->size.second != height) {
if (this->size[0] != width || this->size[1] != height) {
SDL_SetWindowSize(this->window.get(), width, height);
this->size = std::make_pair(width, height);
this->size = {width, height};
}

for (auto& cb : this->on_resize) {
Expand All @@ -67,7 +67,8 @@ void GlWindow::update() {
size_t width = event.window.data1;
size_t height = event.window.data2;
log::log(MSG(dbg) << "Window resized to: " << width << "x" << height);
this->size = std::make_pair(width, height);

this->size = {width, height};
for (auto& cb : this->on_resize) {
cb(width, height);
}
Expand Down
6 changes: 3 additions & 3 deletions libopenage/renderer/tests.cpp
Expand Up @@ -181,9 +181,9 @@ void main() {
* which we can later read in order to determine which object was clicked. The depth texture is required,
* but mostly irrelevant in this case. */
auto size = window.get_size();
auto color_texture = renderer->add_texture(resources::Texture2dInfo(size.first, size.second, resources::pixel_format::rgba8));
auto id_texture = renderer->add_texture(resources::Texture2dInfo(size.first, size.second, resources::pixel_format::r32ui));
auto depth_texture = renderer->add_texture(resources::Texture2dInfo(size.first, size.second, resources::pixel_format::depth24));
auto color_texture = renderer->add_texture(resources::Texture2dInfo(size[0], size[1], resources::pixel_format::rgba8));
auto id_texture = renderer->add_texture(resources::Texture2dInfo(size[0], size[1], resources::pixel_format::r32ui));
auto depth_texture = renderer->add_texture(resources::Texture2dInfo(size[0], size[1], resources::pixel_format::depth24));
auto fbo = renderer->create_texture_target( { color_texture, id_texture, depth_texture } );

/* Make an object to update the projection matrix in pass 1 according to changes in the screen size.
Expand Down
6 changes: 3 additions & 3 deletions libopenage/renderer/vulkan/windowvk.cpp
@@ -1,4 +1,4 @@
// Copyright 2017-2018 the openage authors. See copying.md for legal info.
// Copyright 2017-2019 the openage authors. See copying.md for legal info.

#include "windowvk.h"

Expand Down Expand Up @@ -87,8 +87,8 @@ VlkWindow::VlkWindow(const char* title)
title,
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
this->size.first,
this->size.second,
this->size[0],
this->size[1],
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_MAXIMIZED
);

Expand Down
4 changes: 2 additions & 2 deletions libopenage/renderer/window.cpp
Expand Up @@ -7,9 +7,9 @@ namespace openage {
namespace renderer {

Window::Window(size_t width, size_t height)
: size(std::make_pair(width, height)) {}
: size{width, height} {}

std::pair<size_t, size_t> Window::get_size() const {
const util::Vector2s &Window::get_size() const {
return this->size;
}

Expand Down
7 changes: 4 additions & 3 deletions libopenage/renderer/window.h
@@ -1,4 +1,4 @@
// Copyright 2015-2018 the openage authors. See copying.md for legal info.
// Copyright 2015-2019 the openage authors. See copying.md for legal info.

#pragma once

Expand All @@ -9,6 +9,7 @@
#include <SDL2/SDL.h>

#include "renderer.h"
#include "../util/vector.h"


namespace openage {
Expand All @@ -19,7 +20,7 @@ class Window {
virtual ~Window() = default;

/// Returns the dimensions of this window.
std::pair<size_t, size_t> get_size() const;
const util::Vector2s &get_size() const;

/// Returns true if this window should be closed.
bool should_close() const;
Expand Down Expand Up @@ -51,7 +52,7 @@ class Window {
bool should_be_closed = false;

/// The current size of the framebuffer.
std::pair<size_t, size_t> size;
util::Vector2s size;

std::vector<key_cb_t> on_key;
std::vector<mouse_button_cb_t> on_mouse_button;
Expand Down
31 changes: 26 additions & 5 deletions libopenage/util/vector.h
@@ -1,7 +1,8 @@
// Copyright 2015-2018 the openage authors. See copying.md for legal info.
// Copyright 2015-2019 the openage authors. See copying.md for legal info.

#pragma once

#include <algorithm>
#include <array>
#include <cmath>
#include <cstring>
Expand Down Expand Up @@ -33,12 +34,10 @@ class Vector : public std::array<T, N> {
static constexpr T default_eps = 1e-4;

/**
* Default, random-value constructor.
* Default, zero-value constructor.
*/
Vector() {
for (size_t i = 0; i < N; i++) {
(*this)[i] = 0;
}
this->fill(0);
}

~Vector() = default;
Expand All @@ -54,6 +53,16 @@ class Vector : public std::array<T, N> {
static_assert(sizeof...(args) == N, "not all values supplied.");
}

/**
* Cast every value to NT and return the new Vector.
*/
template<typename NT>
Vector<N, NT> casted() const {
Vector<N, NT> ret;
std::copy(std::begin(*this), std::end(*this), std::begin(ret));
return ret;
}

/**
* Equality test with given precision.
*/
Expand Down Expand Up @@ -226,4 +235,16 @@ using Vector2d = Vector<2, double>;
using Vector3d = Vector<3, double>;
using Vector4d = Vector<4, double>;

using Vector2i = Vector<2, int>;
using Vector3i = Vector<3, int>;
using Vector4i = Vector<4, int>;

using Vector2s = Vector<2, size_t>;
using Vector3s = Vector<3, size_t>;
using Vector4s = Vector<4, size_t>;

using Vector2ss = Vector<2, ssize_t>;
using Vector3ss = Vector<3, ssize_t>;
using Vector4ss = Vector<4, ssize_t>;

} // openage::util

0 comments on commit f5182e4

Please sign in to comment.