diff --git a/include/mbgl/gfx/drawable.hpp b/include/mbgl/gfx/drawable.hpp index 620eecf24..00e7d1ed3 100644 --- a/include/mbgl/gfx/drawable.hpp +++ b/include/mbgl/gfx/drawable.hpp @@ -14,6 +14,8 @@ class PaintParameters; namespace gfx { class DrawableTweaker; +class ShaderProgramBase; +using ShaderProgramBasePtr = std::shared_ptr; using DrawPriority = int64_t; using DrawableTweakerPtr = std::shared_ptr; @@ -32,10 +34,8 @@ public: virtual void draw(const PaintParameters &) const = 0; /// Which shader to use when rendering this drawable - //util::SimpleIdentity getShaderID() const { return shaderID; } - //void setShaderID(util::SimpleIdentity value) { shaderID = value; } - const std::string& getShaderID() const { return shaderID; } - void setShaderID(std::string value) { shaderID = std::move(value); } + const gfx::ShaderProgramBasePtr& getShader() const { return shader; } + void setShader(gfx::ShaderProgramBasePtr value) { shader = std::move(value); } /// DrawPriority determines the drawing order DrawPriority getDrawPriority() const { return drawPriority; } @@ -58,8 +58,7 @@ public: protected: util::SimpleIdentity uniqueID; - //util::SimpleIdentity shaderID = util::SimpleIdentity::Empty; - std::string shaderID; + gfx::ShaderProgramBasePtr shader; DrawPriority drawPriority = 0; diff --git a/include/mbgl/gfx/drawable_builder.hpp b/include/mbgl/gfx/drawable_builder.hpp index cd0c856e8..63b4856d3 100644 --- a/include/mbgl/gfx/drawable_builder.hpp +++ b/include/mbgl/gfx/drawable_builder.hpp @@ -13,8 +13,10 @@ class Color; namespace gfx { class DrawableTweaker; +class ShaderProgramBase; using DrawableTweakerPtr = std::shared_ptr; +using ShaderProgramBasePtr = std::shared_ptr; /** Base class for drawable builders, which construct Drawables from primitives @@ -54,10 +56,8 @@ public: void setColor(const Color& value); /// Which shader to use when rendering emitted drawables - //util::SimpleIdentity getShaderID() const { return shaderID; } - //void setShaderID(util::SimpleIdentity value) { shaderID = value; } - const std::string& getShaderID() const { return shaderID; } - void setShaderID(std::string value) { shaderID = std::move(value); } + const gfx::ShaderProgramBasePtr& getShader() const { return shader; } + void setShader(gfx::ShaderProgramBasePtr value) { shader = std::move(value); } /// Get the vertex attributes that override default values in the shader program virtual const gfx::VertexAttributeArray& getVertexAttributes() const = 0; @@ -83,8 +83,7 @@ protected: protected: DrawPriority drawPriority = 0; - //util::SimpleIdentity shaderID = util::SimpleIdentity::Empty; - std::string shaderID; + gfx::ShaderProgramBasePtr shader; DrawablePtr currentDrawable; std::vector drawables; diff --git a/include/mbgl/gfx/renderer_backend.hpp b/include/mbgl/gfx/renderer_backend.hpp index b63483600..48a50f99a 100644 --- a/include/mbgl/gfx/renderer_backend.hpp +++ b/include/mbgl/gfx/renderer_backend.hpp @@ -8,9 +8,10 @@ namespace mbgl { namespace gfx { +class BackendScope; class Context; class Renderable; -class BackendScope; +class ShaderRegistry; // We can make some optimizations if we know that the drawing context is not shared with other code. enum class ContextMode : bool { @@ -40,6 +41,9 @@ public: /// Returns a reference to the default surface that should be rendered on. virtual Renderable& getDefaultRenderable() = 0; + /// One-time shader initialization + virtual void initShaders(gfx::ShaderRegistry&) = 0; + protected: virtual std::unique_ptr createContext() = 0; diff --git a/include/mbgl/gl/renderer_backend.hpp b/include/mbgl/gl/renderer_backend.hpp index 3d781c0c5..1e2474dbf 100644 --- a/include/mbgl/gl/renderer_backend.hpp +++ b/include/mbgl/gl/renderer_backend.hpp @@ -19,6 +19,9 @@ public: /// Called prior to rendering to update the internally assumed OpenGL state. virtual void updateAssumedState() = 0; + /// One-time shader initialization + void initShaders(gfx::ShaderRegistry&) override; + protected: std::unique_ptr createContext() override; diff --git a/include/mbgl/gl/vertex_attribute_gl.hpp b/include/mbgl/gl/vertex_attribute_gl.hpp index 8e706af01..04f50c839 100644 --- a/include/mbgl/gl/vertex_attribute_gl.hpp +++ b/include/mbgl/gl/vertex_attribute_gl.hpp @@ -45,8 +45,8 @@ private: class VertexAttributeArrayGL final : public gfx::VertexAttributeArray { public: VertexAttributeArrayGL(int initCapacity = 10) : VertexAttributeArray(initCapacity) { } - VertexAttributeArrayGL(VertexAttributeArray &&other) : VertexAttributeArray(std::move(other)) { } - VertexAttributeArrayGL(const VertexAttributeArray& other) : VertexAttributeArray(other) { } + VertexAttributeArrayGL(VertexAttributeArrayGL &&other) : VertexAttributeArray(std::move(other)) { } + VertexAttributeArrayGL(const VertexAttributeArrayGL& other) : VertexAttributeArray(other) { } ~VertexAttributeArrayGL() = default; VertexAttributeArrayGL& operator=(VertexAttributeArrayGL &&other) { diff --git a/include/mbgl/shaders/gl/shader_program_gl.hpp b/include/mbgl/shaders/gl/shader_program_gl.hpp index 7d8439f2e..31b26443a 100644 --- a/include/mbgl/shaders/gl/shader_program_gl.hpp +++ b/include/mbgl/shaders/gl/shader_program_gl.hpp @@ -10,6 +10,7 @@ namespace gl { class ShaderProgramGL final : public gfx::ShaderProgramBase { public: ShaderProgramGL(UniqueProgram&& glProgram_); + ShaderProgramGL(UniqueProgram&& glProgram_, VertexAttributeArrayGL&& attributes); ShaderProgramGL(ShaderProgramGL&& other); virtual ~ShaderProgramGL() noexcept = default; @@ -24,6 +25,8 @@ public: const gfx::VertexAttributeArray& getVertexAttributes() const override { return vertexAttributes; } + ProgramID getGLProgramID() const { return glProgram; } + protected: UniqueProgram glProgram; diff --git a/src/mbgl/gfx/context.hpp b/src/mbgl/gfx/context.hpp index 71cfd0912..d8dfa8320 100644 --- a/src/mbgl/gfx/context.hpp +++ b/src/mbgl/gfx/context.hpp @@ -15,7 +15,12 @@ class ProgramParameters; namespace gfx { +class Drawable; class OffscreenTexture; +class ShaderProgramBase; + +using ShaderProgramBasePtr = std::shared_ptr; + class Context { protected: @@ -81,6 +86,17 @@ public: #endif virtual void clearStencilBuffer(int32_t) = 0; + + +public: + const gfx::ShaderProgramBasePtr& getCurrentShader() const { return currentShader; } + virtual void setCurrentShader(ShaderProgramBasePtr) = 0; + + /// Activate the shader, vertex attributes, etc., specified by the drawable + virtual void setupDraw(const gfx::Drawable&) = 0; + +protected: + ShaderProgramBasePtr currentShader; }; } // namespace gfx diff --git a/src/mbgl/gfx/drawable_builder.cpp b/src/mbgl/gfx/drawable_builder.cpp index 9124e65cf..b37e06da1 100644 --- a/src/mbgl/gfx/drawable_builder.cpp +++ b/src/mbgl/gfx/drawable_builder.cpp @@ -28,7 +28,7 @@ void DrawableBuilder::flush() { if (!impl->vertices.empty()) { auto draw = getCurrentDrawable(/*create=*/true); currentDrawable->setDrawPriority(drawPriority); - currentDrawable->setShaderID(shaderID); + currentDrawable->setShader(shader); currentDrawable->setVertexAttributes(getVertexAttributes()); currentDrawable->addTweakers(tweakers.begin(), tweakers.end()); init(); diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index 2d3e0b067..e57e59578 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -9,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -445,7 +447,34 @@ void Context::setDirtyState() { globalVertexArrayState.setDirty(); } -void Context::clear(std::optional color, std::optional depth, std::optional stencil) { +void Context::setupDraw(const gfx::Drawable& drawable) { + if (auto &shader = drawable.getShader()) { + if (shader != currentShader) { + setCurrentShader(shader); + } + } + + auto& drawableGL = static_cast(drawable); + auto& vao = drawableGL.getVertexArray(); + if (vao.isValid()) { + bindVertexArray = vao.getID(); // glBindVertexArray + } else { + bindVertexArray = value::BindVertexArray::Default; + } +} + +void Context::setCurrentShader(gfx::ShaderProgramBasePtr value) { + if ((currentShader = std::move(value))) { + auto& shaderGL = static_cast(*currentShader); + this->program = shaderGL.getGLProgramID(); + } else { + this->program = value::Program::Default; + } +} + +void Context::clear(std::optional color, + std::optional depth, + std::optional stencil) { GLbitfield mask = 0; if (color) { diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index 88b7dc1bb..1819492b7 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -104,6 +104,10 @@ public: void setCleanupOnDestruction(bool cleanup) { cleanupOnDestruction = cleanup; } + void setupDraw(const gfx::Drawable&) override; + + void setCurrentShader(gfx::ShaderProgramBasePtr) override; + private: RendererBackend& backend; bool cleanupOnDestruction = true; diff --git a/src/mbgl/gl/renderer_backend.cpp b/src/mbgl/gl/renderer_backend.cpp index 6a2bf2fb2..cee61b53a 100644 --- a/src/mbgl/gl/renderer_backend.cpp +++ b/src/mbgl/gl/renderer_backend.cpp @@ -1,7 +1,10 @@ #include #include +#include #include #include +#include +#include #include @@ -62,5 +65,67 @@ void RendererBackend::setScissorTest(bool enabled) { RendererBackend::~RendererBackend() = default; +void RendererBackend::initShaders(gfx::ShaderRegistry& shaders) { + constexpr auto shaderName = "background_generic"; + + gl::Context& glContext = static_cast(*context); + + auto shader = shaders.get(shaderName); + if (!shader) { + constexpr auto vert = R"( + #version 300 es + precision highp float; + uniform float a; + uniform int b; + uniform mat4 c; + layout (location = 0) in vec3 pos; + in float d; + in int e; + in mat2 f; + in mat4 g; + void main() { + gl_Position = vec4(d, float(e), f[0][0], a)/1.0e12; + gl_Position = vec4(pos, 1.0); + })"; + constexpr auto frag = R"( + #version 300 es + precision highp float; + in vec4 pos; + out vec4 color; + void main() { + color = vec4(1.0,0.0,0.0,1.0); + })"; + + try { + // Compile + shader = gl::ShaderProgramGL::create(glContext, shaderName, vert, frag); + if (shader) { + // Set default values + if (auto *attr = shader->getVertexAttributes().get("d")) { + attr->set(0, 12.3f); + } + if (auto *attr = shader->getVertexAttributes().get("e")) { + attr->set(0, 123); + } + if (auto *attr = shader->getVertexAttributes().get("f")) { + attr->set(0, gfx::VertexAttribute::matf2{ 1.0f, 2.0f, 3.0f, 4.0f }); + } + + // Add to the registry + if (!shaders.registerShader(shader, shaderName)) { + Log::Warning(Event::General, "Shader conflict - " + std::string(shaderName)); + return; + } + } else { + Log::Warning(Event::General, "Shader create failed - " + std::string(shaderName)); + return; + } + } catch (const std::runtime_error& ex) { + Log::Warning(Event::General, "Shader create exception - " + std::string(ex.what())); + return; + } + } +} + } // namespace gl } // namespace mbgl diff --git a/src/mbgl/gl/vertex_array.hpp b/src/mbgl/gl/vertex_array.hpp index 47a32facc..6a9ec974e 100644 --- a/src/mbgl/gl/vertex_array.hpp +++ b/src/mbgl/gl/vertex_array.hpp @@ -72,6 +72,8 @@ public: bool isValid() const { return state.operator bool(); } + VertexArrayID getID() const { return state->vertexArray; } + private: UniqueVertexArrayState state; }; diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index 967107243..8348b6a4e 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -61,6 +61,10 @@ void Renderer::Impl::render(const RenderTree& renderTree) { auto& context = backend.getContext(); + // Now that the shader registry is set up, do one-time shader init. + // TODO: Both should be done earlier. + backend.initShaders(*staticData->shaders); + // Blocks execution until the renderable is available. backend.getDefaultRenderable().wait(); @@ -109,34 +113,32 @@ void Renderer::Impl::render(const RenderTree& renderTree) { // Generate a vertex array object for the drawable state, if necessary auto& drawableGL = static_cast(drawable); - if (!drawableGL.getVertexArray().isValid() && !drawable.getShaderID().empty()) { - // TODO: avoid having to do this lookup twice - if (auto shader = parameters.shaders.get(drawable.getShaderID())) { - const auto usage = gfx::BufferUsageType::StaticDraw; + const auto& shader = drawable.getShader(); + if (shader && !drawableGL.getVertexArray().isValid()) { + const auto usage = gfx::BufferUsageType::StaticDraw; - // Build index buffer - const auto& indexData = drawable.getIndexData(); - auto indexBuffer = gfx::IndexBuffer { - indexData.size(), - uploadPass->createIndexBufferResource( - &indexData[0], - indexData.size() * sizeof(indexData[0]), - usage) - }; + // Build index buffer + const auto& indexData = drawable.getIndexData(); + auto indexBuffer = gfx::IndexBuffer { + indexData.size(), + uploadPass->createIndexBufferResource( + &indexData[0], + indexData.size() * sizeof(indexData[0]), + usage) + }; - // Apply drawable values to shader defaults - const auto& defaults = shader->getVertexAttributes(); - const auto& overrides = drawable.getVertexAttributes(); - auto bindingsAndBuffer = uploadPass->buildAttributeBindings(defaults, overrides, usage); + // Apply drawable values to shader defaults + const auto& defaults = shader->getVertexAttributes(); + const auto& overrides = drawable.getVertexAttributes(); + auto bindingsAndBuffer = uploadPass->buildAttributeBindings(defaults, overrides, usage); - auto& glContext = static_cast(context); - auto vertexArray = glContext.createVertexArray(); - vertexArray.bind(glContext, indexBuffer, bindingsAndBuffer.first); - - drawableGL.setVertexArray(std::move(vertexArray), - std::move(bindingsAndBuffer.second), - std::move(indexBuffer)); - } + auto& glContext = static_cast(context); + auto vertexArray = glContext.createVertexArray(); + vertexArray.bind(glContext, indexBuffer, bindingsAndBuffer.first); + + drawableGL.setVertexArray(std::move(vertexArray), + std::move(bindingsAndBuffer.second), + std::move(indexBuffer)); } } } @@ -196,15 +198,8 @@ void Renderer::Impl::render(const RenderTree& renderTree) { { for (const auto &pair : orchestrator.getDrawables()) { const auto& drawable = *pair.second; - - if (!drawable.getShaderID().empty()) { - // if shader != currentShader - if (auto shader = parameters.shaders.get(drawable.getShaderID())) { - // Context.activate(shader) - } - } - // Context.bind(drawable vao) + context.setupDraw(drawable); drawable.draw(parameters); } diff --git a/src/mbgl/shaders/gl/shader_program_gl.cpp b/src/mbgl/shaders/gl/shader_program_gl.cpp index 74665eda3..8da6b327e 100644 --- a/src/mbgl/shaders/gl/shader_program_gl.cpp +++ b/src/mbgl/shaders/gl/shader_program_gl.cpp @@ -57,9 +57,17 @@ ShaderProgramGL::ShaderProgramGL(UniqueProgram&& glProgram_) glProgram(std::move(glProgram_)) { } +ShaderProgramGL::ShaderProgramGL(UniqueProgram&& glProgram_, + VertexAttributeArrayGL&& attributes) + : ShaderProgramBase(), + glProgram(std::move(glProgram_)), + vertexAttributes(std::move(attributes)) { +} + ShaderProgramGL::ShaderProgramGL(ShaderProgramGL&& other) : ShaderProgramBase(std::forward(other)), - glProgram(std::move(other.glProgram)) { + glProgram(std::move(other.glProgram)), + vertexAttributes(std::move(other.vertexAttributes)) { } std::shared_ptr ShaderProgramGL::create( @@ -111,7 +119,7 @@ std::shared_ptr ShaderProgramGL::create( } } - return std::make_shared(std::move(program)); + return std::make_shared(std::move(program), std::move(attrs)); } } // namespace gl diff --git a/src/mbgl/style/layers/background_layer_impl.cpp b/src/mbgl/style/layers/background_layer_impl.cpp index d641dc236..873b545de 100644 --- a/src/mbgl/style/layers/background_layer_impl.cpp +++ b/src/mbgl/style/layers/background_layer_impl.cpp @@ -19,62 +19,8 @@ bool BackgroundLayer::Impl::hasLayoutDifference(const Layer::Impl&) const { constexpr auto shaderName = "background_generic"; void BackgroundLayer::Impl::layerAdded(PaintParameters& parameters, UniqueChangeRequestVec& changes) const { - // TODO: this should happen a GL-specific part of map initialization - auto &glContext = static_cast(parameters.context); - auto shader = parameters.shaders.get(shaderName); if (!shader) { - constexpr auto vert = R"( - //#version 300 es - precision highp float; - uniform float a; - uniform int b; - uniform mat4 c; - attribute vec3 pos; //layout (location = 0) in vec3 pos; - attribute float d; - //attribute int e; - attribute mat2 f; - attribute mat4 g; - void main() { - gl_Position = vec4(a, g[0][0], f[0][0], d); - gl_Position = vec4(pos, 1.0); - })"; - constexpr auto frag = R"( - //#version 300 es - precision highp float; - //out vec4 color; - void main() { - //color = vec4(1.0,0.0,0.0,1.0); - gl_FragColor = vec4(1.0,0.0,0.0,1.0); - })"; - - try { - // Compile - shader = gl::ShaderProgramGL::create(glContext, shaderName, vert, frag); - if (shader) { - // Set default values - if (auto *attr = shader->getVertexAttributes().get("a")) { - attr->set(0, 12.3f); - } - if (auto *attr = shader->getVertexAttributes().get("b")) { - attr->set(0, 123); - } - if (auto *attr = shader->getVertexAttributes().get("f")) { - attr->set(0, gfx::VertexAttribute::matf2{ 1.0f, 2.0f, 3.0f, 4.0f }); - } - - // Add to the registry - if (!parameters.shaders.registerShader(shader, shaderName)) { - Log::Warning(Event::General, "Shader conflict - " + std::string(shaderName)); - return; - } - } else { - Log::Warning(Event::General, "Shader create failed - " + std::string(shaderName)); - return; - } - } catch (const std::runtime_error& ex) { - Log::Warning(Event::General, "Shader create exception - " + std::string(ex.what())); - return; - } + shader = parameters.shaders.get(shaderName); } buildDrawables(changes); @@ -88,8 +34,13 @@ void BackgroundLayer::Impl::layerRemoved(PaintParameters&, UniqueChangeRequestVe } void BackgroundLayer::Impl::buildDrawables(UniqueChangeRequestVec& changes) const { + + if (!shader) { + return; + } + auto builder = std::make_unique(); // from GL-specific code via virtual method? - builder->setShaderID(shaderName); + builder->setShader(shader); builder->addTweaker(std::make_shared()); // generally shared across drawables builder->addQuad(0, 0, util::EXTENT, util::EXTENT); builder->flush(); diff --git a/src/mbgl/style/layers/background_layer_impl.hpp b/src/mbgl/style/layers/background_layer_impl.hpp index 09eb052a2..822782f68 100644 --- a/src/mbgl/style/layers/background_layer_impl.hpp +++ b/src/mbgl/style/layers/background_layer_impl.hpp @@ -10,7 +10,9 @@ namespace mbgl { namespace gfx { class Drawable; +class ShaderProgramBase; using DrawablePtr = std::shared_ptr; +using ShaderProgramBasePtr = std::shared_ptr; } // namespace gfx @@ -27,7 +29,7 @@ public: void layerRemoved(PaintParameters&, UniqueChangeRequestVec&) const override; /// Generate any changes needed by the layer - void update(UniqueChangeRequestVec& changes) const override; + void update(UniqueChangeRequestVec&) const override; private: void buildDrawables(UniqueChangeRequestVec&) const; @@ -35,6 +37,7 @@ private: public: BackgroundPaintProperties::Transitionable paint; + mutable gfx::ShaderProgramBasePtr shader; mutable gfx::DrawablePtr drawable; DECLARE_LAYER_TYPE_INFO;