diff options
author | Konstantin Käfer <mail@kkaefer.com> | 2019-03-15 20:31:12 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-15 20:31:12 +0100 |
commit | c8cfdb1ced822711e772dfcc8f708b1a7a68b5fc (patch) | |
tree | bf511253e25459cafc91a5f3bea2f5c773677162 /src/mbgl/gl | |
parent | 62695c56956add5560933137a479f29f2d3a091b (diff) | |
download | qtlocation-mapboxgl-c8cfdb1ced822711e772dfcc8f708b1a7a68b5fc.tar.gz |
Merge pull request #14126 from mapbox/gfx-refactor-4
Graphics refactor #4
Diffstat (limited to 'src/mbgl/gl')
-rw-r--r-- | src/mbgl/gl/attribute.cpp | 11 | ||||
-rw-r--r-- | src/mbgl/gl/attribute.hpp | 114 | ||||
-rw-r--r-- | src/mbgl/gl/binary_program.cpp | 142 | ||||
-rw-r--r-- | src/mbgl/gl/binary_program.hpp | 50 | ||||
-rw-r--r-- | src/mbgl/gl/context.cpp | 52 | ||||
-rw-r--r-- | src/mbgl/gl/context.hpp | 12 | ||||
-rw-r--r-- | src/mbgl/gl/draw_scope_resource.hpp | 18 | ||||
-rw-r--r-- | src/mbgl/gl/enum.cpp | 16 | ||||
-rw-r--r-- | src/mbgl/gl/program.hpp | 118 | ||||
-rw-r--r-- | src/mbgl/gl/texture.hpp | 15 | ||||
-rw-r--r-- | src/mbgl/gl/uniform.hpp | 35 | ||||
-rw-r--r-- | src/mbgl/gl/value.cpp | 4 | ||||
-rw-r--r-- | src/mbgl/gl/value.hpp | 2 |
13 files changed, 369 insertions, 220 deletions
diff --git a/src/mbgl/gl/attribute.cpp b/src/mbgl/gl/attribute.cpp index 1b43ad2b64..4983a8c204 100644 --- a/src/mbgl/gl/attribute.cpp +++ b/src/mbgl/gl/attribute.cpp @@ -7,17 +7,6 @@ namespace gl { using namespace platform; -optional<AttributeBinding> offsetAttributeBinding(const optional<AttributeBinding>& binding, std::size_t vertexOffset) { - assert(vertexOffset <= std::numeric_limits<uint32_t>::max()); - if (binding) { - AttributeBinding result = *binding; - result.vertexOffset = static_cast<uint32_t>(vertexOffset); - return result; - } else { - return binding; - } -} - void bindAttributeLocation(Context& context, ProgramID id, AttributeLocation location, const char* name) { // We're using sequentially numberered attribute locations starting with 0. Therefore we can use // the location as a proxy for the number of attributes. diff --git a/src/mbgl/gl/attribute.hpp b/src/mbgl/gl/attribute.hpp index dc112c1ad8..c4fe8b993f 100644 --- a/src/mbgl/gl/attribute.hpp +++ b/src/mbgl/gl/attribute.hpp @@ -2,7 +2,6 @@ #include <mbgl/gfx/attribute.hpp> #include <mbgl/gl/types.hpp> -#include <mbgl/gfx/vertex_buffer.hpp> #include <mbgl/util/ignore.hpp> #include <mbgl/util/indexed_tuple.hpp> #include <mbgl/util/optional.hpp> @@ -18,83 +17,50 @@ namespace mbgl { namespace gl { -class AttributeBinding { -public: - gfx::AttributeDescriptor attribute; - uint8_t vertexStride; - const gfx::VertexBufferResource* vertexBufferResource; - uint32_t vertexOffset; - - friend bool operator==(const AttributeBinding& lhs, const AttributeBinding& rhs) { - return lhs.attribute == rhs.attribute && - lhs.vertexStride == rhs.vertexStride && - lhs.vertexBufferResource == rhs.vertexBufferResource && - lhs.vertexOffset == rhs.vertexOffset; - } -}; - -using AttributeBindingArray = std::vector<optional<AttributeBinding>>; - - /* - Create a binding for this attribute. The `attributeSize` parameter may be used to - override the number of components available in the buffer for each vertex. Thus, - a buffer with only one float for each vertex can be bound to a `vec2` attribute - */ -template <std::size_t I, typename Vertex> -AttributeBinding attributeBinding(const gfx::VertexBuffer<Vertex>& buffer) { - static_assert(I < gfx::VertexDescriptorOf<Vertex>::data.count, "vertex attribute index out of range"); - return { - gfx::VertexDescriptorOf<Vertex>::data.attributes[I], - gfx::VertexDescriptorOf<Vertex>::data.stride, - buffer.resource.get(), - 0, - }; -} - -optional<AttributeBinding> offsetAttributeBinding(const optional<AttributeBinding>& binding, std::size_t vertexOffset); +using AttributeBindingArray = std::vector<optional<gfx::AttributeBinding>>; +using NamedAttributeLocations = std::vector<std::pair<const std::string, AttributeLocation>>; class Context; void bindAttributeLocation(Context&, ProgramID, AttributeLocation, const char * name); std::set<std::string> getActiveAttributes(ProgramID); template <class> -class Attributes; +class AttributeLocations; template <class... As> -class Attributes<TypeList<As...>> final { -public: - using Types = TypeList<As...>; - using Locations = IndexedTuple< - TypeList<As...>, - TypeList<ExpandToType<As, optional<AttributeLocation>>...>>; - using Bindings = IndexedTuple< - TypeList<As...>, - TypeList<ExpandToType<As, optional<AttributeBinding>>...>>; - using NamedLocations = std::vector<std::pair<const std::string, AttributeLocation>>; - - static Locations bindLocations(Context& context, const ProgramID& id) { - std::set<std::string> activeAttributes = getActiveAttributes(id); - - AttributeLocation location = 0; - auto maybeBindLocation = [&](const char* name) -> optional<AttributeLocation> { - if (activeAttributes.count(name)) { - bindAttributeLocation(context, id, location, name); - return location++; - } else { - return {}; - } - }; +class AttributeLocations<TypeList<As...>> final { +private: + using Locations = + IndexedTuple<TypeList<As...>, TypeList<ExpandToType<As, optional<AttributeLocation>>...>>; + + Locations locations; - return Locations { maybeBindLocation(As::name())... }; +public: + AttributeLocations(Context& context, const ProgramID& id) + : locations([&] { + std::set<std::string> activeAttributes = getActiveAttributes(id); + + AttributeLocation location = 0; + auto maybeBindLocation = [&](const char* name) -> optional<AttributeLocation> { + if (activeAttributes.count(name)) { + bindAttributeLocation(context, id, location, name); + return location++; + } else { + return {}; + } + }; + + return Locations{ maybeBindLocation(As::name())... }; + }()) { } - template <class Program> - static Locations loadNamedLocations(const Program& program) { - return Locations{ program.attributeLocation(As::name())... }; + template <class BinaryProgram> + AttributeLocations(const BinaryProgram& program) + : locations{ program.attributeLocation(As::name())... } { } - static NamedLocations getNamedLocations(const Locations& locations) { - NamedLocations result; + NamedAttributeLocations getNamedLocations() const { + NamedAttributeLocations result; auto maybeAddLocation = [&] (const std::string& name, const optional<AttributeLocation>& location) { if (location) { @@ -107,20 +73,12 @@ public: return result; } - static Bindings bindings(const gfx::VertexBuffer<gfx::Vertex<Types>>& buffer) { - return Bindings { attributeBinding<TypeIndex<As, As...>::value>(buffer)... }; - } - - static Bindings offsetBindings(const Bindings& bindings, std::size_t vertexOffset) { - return Bindings { offsetAttributeBinding(bindings.template get<As>(), vertexOffset)... }; - } - - static AttributeBindingArray toBindingArray(const Locations& locations, const Bindings& bindings) { + AttributeBindingArray toBindingArray(const gfx::AttributeBindings<TypeList<As...>>& bindings) const { AttributeBindingArray result; result.resize(sizeof...(As)); auto maybeAddBinding = [&] (const optional<AttributeLocation>& location, - const optional<AttributeBinding>& binding) { + const optional<gfx::AttributeBinding>& binding) { if (location) { result.at(*location) = binding; } @@ -130,12 +88,6 @@ public: return result; } - - static uint32_t activeBindingCount(const Bindings& bindings) { - uint32_t result = 0; - util::ignore({ ((result += bool(bindings.template get<As>())), 0)... }); - return result; - } }; } // namespace gl diff --git a/src/mbgl/gl/binary_program.cpp b/src/mbgl/gl/binary_program.cpp new file mode 100644 index 0000000000..9fdbdb8ee1 --- /dev/null +++ b/src/mbgl/gl/binary_program.cpp @@ -0,0 +1,142 @@ +#include <mbgl/gl/binary_program.hpp> + +#include <protozero/pbf_reader.hpp> +#include <protozero/pbf_writer.hpp> +#include <utility> +#include <stdexcept> + +template <class Binding> +static std::pair<const std::string, Binding> parseBinding(protozero::pbf_reader&& pbf) { + bool hasName = false, hasValue = false; + std::pair<std::string, Binding> binding; + while (pbf.next()) { + switch (pbf.tag()) { + case 1: // name + binding.first = pbf.get_string(); + hasName = true; + break; + case 2: // value + binding.second = pbf.get_uint32(); + hasValue = true; + break; + default: + pbf.skip(); + break; + } + } + if (!hasName || !hasValue) { + throw std::runtime_error("BinaryProgram binding is missing required fields"); + } + return binding; +} + +namespace mbgl { +namespace gl { + +BinaryProgram::BinaryProgram(std::string&& data) { + bool hasFormat = false, hasCode = false; + protozero::pbf_reader pbf(data); + while (pbf.next()) { + switch (pbf.tag()) { + case 1: // format + binaryFormat = pbf.get_uint32(); + hasFormat = true; + break; + case 2: // code + binaryCode = pbf.get_bytes(); + hasCode = true; + break; + case 3: // variable + attributes.emplace_back(parseBinding<gl::AttributeLocation>(pbf.get_message())); + break; + case 4: // uniform + uniforms.emplace_back(parseBinding<gl::UniformLocation>(pbf.get_message())); + break; + case 5: // identifier + binaryIdentifier = pbf.get_string(); + break; + case 6: // uniform + textures.emplace_back(parseBinding<gl::UniformLocation>(pbf.get_message())); + break; + default: + pbf.skip(); + break; + } + } + + if (!hasFormat || !hasCode) { + throw std::runtime_error("BinaryProgram is missing required fields"); + } +} + +BinaryProgram::BinaryProgram( + gl::BinaryProgramFormat binaryFormat_, + std::string&& binaryCode_, + std::string binaryIdentifier_, + std::vector<std::pair<const std::string, gl::AttributeLocation>>&& attributes_, + std::vector<std::pair<const std::string, gl::UniformLocation>>&& uniforms_, + std::vector<std::pair<const std::string, gl::UniformLocation>>&& textures_) + : binaryFormat(binaryFormat_), + binaryCode(std::move(binaryCode_)), + binaryIdentifier(std::move(binaryIdentifier_)), + attributes(std::move(attributes_)), + uniforms(std::move(uniforms_)), + textures(std::move(textures_)) { +} + +std::string BinaryProgram::serialize() const { + std::string data; + data.reserve(32 + binaryCode.size() + uniforms.size() * 32 + attributes.size() * 32); + protozero::pbf_writer pbf(data); + pbf.add_uint32(1 /* format */, binaryFormat); + pbf.add_bytes(2 /* code */, binaryCode.data(), binaryCode.size()); + for (const auto& binding : attributes) { + protozero::pbf_writer pbf_binding(pbf, 3 /* attribute */); + pbf_binding.add_string(1 /* name */, binding.first); + pbf_binding.add_uint32(2 /* value */, binding.second); + } + for (const auto& binding : uniforms) { + protozero::pbf_writer pbf_binding(pbf, 4 /* uniform */); + pbf_binding.add_string(1 /* name */, binding.first); + pbf_binding.add_uint32(2 /* value */, binding.second); + } + for (const auto& binding : textures) { + protozero::pbf_writer pbf_binding(pbf, 6 /* texture */); + pbf_binding.add_string(1 /* name */, binding.first); + pbf_binding.add_uint32(2 /* value */, binding.second); + } + if (!binaryIdentifier.empty()) { + pbf.add_string(5 /* identifier */, binaryIdentifier); + } + return data; +} + +optional<gl::AttributeLocation> BinaryProgram::attributeLocation(const std::string& name) const { + for (const auto& pair : attributes) { + if (pair.first == name) { + return pair.second; + } + } + return {}; +} + +gl::UniformLocation BinaryProgram::uniformLocation(const std::string& name) const { + for (const auto& pair : uniforms) { + if (pair.first == name) { + return pair.second; + } + } + return -1; +} + +gl::UniformLocation BinaryProgram::textureLocation(const std::string& name) const { + for (const auto& pair : textures) { + if (pair.first == name) { + return pair.second; + } + } + return -1; +} + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/binary_program.hpp b/src/mbgl/gl/binary_program.hpp new file mode 100644 index 0000000000..38160b62b5 --- /dev/null +++ b/src/mbgl/gl/binary_program.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include <mbgl/gl/types.hpp> +#include <mbgl/util/optional.hpp> + +#include <string> +#include <vector> + +namespace mbgl { +namespace gl { + +class BinaryProgram { +public: + // Initialize a BinaryProgram object from a serialized represenation. + BinaryProgram(std::string&& data); + + BinaryProgram(gl::BinaryProgramFormat, + std::string&& binaryCode, + std::string binaryIdentifier, + std::vector<std::pair<const std::string, gl::AttributeLocation>>&&, + std::vector<std::pair<const std::string, gl::UniformLocation>>&&, + std::vector<std::pair<const std::string, gl::UniformLocation>>&&); + + std::string serialize() const; + + gl::BinaryProgramFormat format() const { + return binaryFormat; + } + const std::string& code() const { + return binaryCode; + } + const std::string& identifier() const { + return binaryIdentifier; + } + + optional<gl::AttributeLocation> attributeLocation(const std::string& name) const; + gl::UniformLocation uniformLocation(const std::string& name) const; + gl::UniformLocation textureLocation(const std::string& name) const; + +private: + gl::BinaryProgramFormat binaryFormat = 0; + std::string binaryCode; + std::string binaryIdentifier; + std::vector<std::pair<const std::string, gl::AttributeLocation>> attributes; + std::vector<std::pair<const std::string, gl::UniformLocation>> uniforms; + std::vector<std::pair<const std::string, gl::UniformLocation>> textures; +}; + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index ca06ab660d..5193381251 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -3,6 +3,7 @@ #include <mbgl/gl/vertex_buffer_resource.hpp> #include <mbgl/gl/index_buffer_resource.hpp> #include <mbgl/gl/texture_resource.hpp> +#include <mbgl/gl/draw_scope_resource.hpp> #include <mbgl/gl/texture.hpp> #include <mbgl/gl/debugging_extension.hpp> #include <mbgl/gl/vertex_array_extension.hpp> @@ -66,7 +67,7 @@ static_assert(underlying_type(UniformDataType::SamplerCube) == GL_SAMPLER_CUBE, static_assert(std::is_same<BinaryProgramFormat, GLenum>::value, "OpenGL type mismatch"); Context::Context() - : maximumVertexBindingCount([] { + : gfx::Context(gfx::ContextType::OpenGL), maximumVertexBindingCount([] { GLint value; MBGL_CHECK_ERROR(glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &value)); return value; @@ -190,6 +191,8 @@ UniqueProgram Context::createProgram(ShaderID vertexShader, ShaderID fragmentSha MBGL_CHECK_ERROR(glAttachShader(result, vertexShader)); MBGL_CHECK_ERROR(glAttachShader(result, fragmentShader)); + linkProgram(result); + return result; } @@ -544,6 +547,10 @@ void Context::updateTextureResource(const gfx::TextureResource& resource, Enum<gfx::TextureChannelDataType>::to(type), data)); } +std::unique_ptr<gfx::DrawScopeResource> Context::createDrawScopeResource() { + return std::make_unique<gl::DrawScopeResource>(createVertexArray()); +} + void Context::reset() { std::copy(pooledTextures.begin(), pooledTextures.end(), std::back_inserter(abandonedTextures)); pooledTextures.resize(0); @@ -628,29 +635,6 @@ void Context::setCullFaceMode(const gfx::CullFaceMode& mode) { cullFaceWinding = mode.winding; } -#if not MBGL_USE_GLES2 -void Context::setDrawMode(const gfx::Points& points) { - pointSize = points.pointSize; -} -#else -void Context::setDrawMode(const gfx::Points&) { -} -#endif // MBGL_USE_GLES2 - -void Context::setDrawMode(const gfx::Lines& lines) { - lineWidth = lines.lineWidth; -} - -void Context::setDrawMode(const gfx::LineStrip& lineStrip) { - lineWidth = lineStrip.lineWidth; -} - -void Context::setDrawMode(const gfx::Triangles&) { -} - -void Context::setDrawMode(const gfx::TriangleStrip&) { -} - void Context::setDepthMode(const gfx::DepthMode& depth) { if (depth.func == gfx::DepthFunctionType::Always && depth.mask != gfx::DepthMaskType::ReadWrite) { depthTest = false; @@ -697,11 +681,27 @@ void Context::setColorMode(const gfx::ColorMode& color) { colorMask = color.mask; } -void Context::draw(gfx::PrimitiveType primitiveType, +void Context::draw(const gfx::DrawMode& drawMode, std::size_t indexOffset, std::size_t indexLength) { + switch (drawMode.type) { + case gfx::DrawModeType::Points: +#if not MBGL_USE_GLES2 + // In OpenGL ES 2, the point size is set in the vertex shader. + pointSize = drawMode.size; +#endif // MBGL_USE_GLES2 + break; + case gfx::DrawModeType::Lines: + case gfx::DrawModeType::LineLoop: + case gfx::DrawModeType::LineStrip: + lineWidth = drawMode.size; + break; + default: + break; + } + MBGL_CHECK_ERROR(glDrawElements( - Enum<gfx::PrimitiveType>::to(primitiveType), + Enum<gfx::DrawModeType>::to(drawMode.type), static_cast<GLsizei>(indexLength), GL_UNSIGNED_SHORT, reinterpret_cast<GLvoid*>(sizeof(uint16_t) * indexOffset))); diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index 51b79200ba..fe09390cc6 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -52,7 +52,6 @@ public: void verifyProgramLinkage(ProgramID); void linkProgram(ProgramID); UniqueTexture createUniqueTexture(); - VertexArray createVertexArray(); #if MBGL_HAS_BINARY_PROGRAMS bool supportsProgramBinaries() const; @@ -100,18 +99,12 @@ public: optional<float> depth, optional<int32_t> stencil); - void setDrawMode(const gfx::Points&); - void setDrawMode(const gfx::Lines&); - void setDrawMode(const gfx::LineStrip&); - void setDrawMode(const gfx::Triangles&); - void setDrawMode(const gfx::TriangleStrip&); - void setDepthMode(const gfx::DepthMode&); void setStencilMode(const gfx::StencilMode&); void setColorMode(const gfx::ColorMode&); void setCullFaceMode(const gfx::CullFaceMode&); - void draw(gfx::PrimitiveType, + void draw(const gfx::DrawMode&, std::size_t indexOffset, std::size_t indexLength); @@ -216,6 +209,8 @@ private: std::unique_ptr<gfx::TextureResource> createTextureResource(Size, const void* data, gfx::TexturePixelType, gfx::TextureChannelDataType) override; void updateTextureResource(const gfx::TextureResource&, Size, const void* data, gfx::TexturePixelType, gfx::TextureChannelDataType) override; + std::unique_ptr<gfx::DrawScopeResource> createDrawScopeResource() override; + UniqueFramebuffer createFramebuffer(); UniqueRenderbuffer createRenderbuffer(RenderbufferType, Size size); std::unique_ptr<uint8_t[]> readFramebuffer(Size, gfx::TexturePixelType, bool flip); @@ -223,6 +218,7 @@ private: void drawPixels(Size size, const void* data, gfx::TexturePixelType); #endif // MBGL_USE_GLES2 + VertexArray createVertexArray(); bool supportsVertexArrays() const; friend detail::ProgramDeleter; diff --git a/src/mbgl/gl/draw_scope_resource.hpp b/src/mbgl/gl/draw_scope_resource.hpp new file mode 100644 index 0000000000..4c446cd4fe --- /dev/null +++ b/src/mbgl/gl/draw_scope_resource.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include <mbgl/gfx/draw_scope.hpp> +#include <mbgl/gl/vertex_array.hpp> + +namespace mbgl { +namespace gl { + +class DrawScopeResource : public gfx::DrawScopeResource { +public: + DrawScopeResource(VertexArray&& vertexArray_) : vertexArray(std::move(vertexArray_)) { + } + + VertexArray vertexArray; +}; + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/enum.cpp b/src/mbgl/gl/enum.cpp index c1a51944de..673d43b5d6 100644 --- a/src/mbgl/gl/enum.cpp +++ b/src/mbgl/gl/enum.cpp @@ -6,15 +6,15 @@ namespace mbgl { namespace gl { template <> -platform::GLenum Enum<gfx::PrimitiveType>::to(const gfx::PrimitiveType value) { +platform::GLenum Enum<gfx::DrawModeType>::to(const gfx::DrawModeType value) { switch (value) { - case gfx::PrimitiveType::Points: return GL_POINTS; - case gfx::PrimitiveType::Lines: return GL_LINES; - case gfx::PrimitiveType::LineLoop: return GL_LINE_LOOP; - case gfx::PrimitiveType::LineStrip: return GL_LINE_STRIP; - case gfx::PrimitiveType::Triangles: return GL_TRIANGLES; - case gfx::PrimitiveType::TriangleStrip: return GL_TRIANGLE_STRIP; - case gfx::PrimitiveType::TriangleFan: return GL_TRIANGLE_FAN; + case gfx::DrawModeType::Points: return GL_POINTS; + case gfx::DrawModeType::Lines: return GL_LINES; + case gfx::DrawModeType::LineLoop: return GL_LINE_LOOP; + case gfx::DrawModeType::LineStrip: return GL_LINE_STRIP; + case gfx::DrawModeType::Triangles: return GL_TRIANGLES; + case gfx::DrawModeType::TriangleStrip: return GL_TRIANGLE_STRIP; + case gfx::DrawModeType::TriangleFan: return GL_TRIANGLE_FAN; } return GL_INVALID_ENUM; } diff --git a/src/mbgl/gl/program.hpp b/src/mbgl/gl/program.hpp index ffa3e07391..9028ffdf53 100644 --- a/src/mbgl/gl/program.hpp +++ b/src/mbgl/gl/program.hpp @@ -1,80 +1,79 @@ #pragma once +#include <mbgl/gfx/program.hpp> #include <mbgl/gl/types.hpp> #include <mbgl/gl/object.hpp> #include <mbgl/gl/context.hpp> +#include <mbgl/gl/draw_scope_resource.hpp> #include <mbgl/gfx/vertex_buffer.hpp> #include <mbgl/gfx/index_buffer.hpp> +#include <mbgl/gfx/uniform.hpp> #include <mbgl/gl/vertex_array.hpp> #include <mbgl/gl/attribute.hpp> #include <mbgl/gl/uniform.hpp> #include <mbgl/gl/texture.hpp> - +#include <mbgl/gl/features.hpp> +#include <mbgl/gl/binary_program.hpp> #include <mbgl/util/io.hpp> + #include <mbgl/util/logging.hpp> -#include <mbgl/programs/binary_program.hpp> #include <mbgl/programs/program_parameters.hpp> -#include <mbgl/shaders/shaders.hpp> +#include <mbgl/programs/gl/shaders.hpp> #include <string> namespace mbgl { namespace gl { -template <class P, class As, class Us, class TextureList> -class Program { +template <class Name> +class Program final : public gfx::Program<Name> { public: - using Primitive = P; - using Attributes = As; - using Uniforms = Us; - - using UniformValues = typename Uniforms::Values; - using AttributeBindings = typename Attributes::Bindings; - using TextureBindings = gfx::TextureBindings<TextureList>; - + using AttributeList = typename Name::AttributeList; + using UniformList = typename Name::UniformList; + using TextureList = typename Name::TextureList; + Program(Context& context, const std::string& vertexSource, const std::string& fragmentSource) : program( context.createProgram(context.createShader(ShaderType::Vertex, vertexSource), context.createShader(ShaderType::Fragment, fragmentSource))), - uniformsState((context.linkProgram(program), Uniforms::bindLocations(program))), - attributeLocations(Attributes::bindLocations(context, program)) { - // Re-link program after manually binding only active attributes in Attributes::bindLocations + attributeLocations(context, program) { + // Re-link program after manually binding only active attributes in Attributes::queryLocations context.linkProgram(program); // We have to re-initialize the uniforms state from the bindings as the uniform locations // get shifted on some implementations - uniformsState = Uniforms::bindLocations(program); + uniformStates.queryLocations(program); // Texture units are specified via uniforms as well, so we need query their locations - textures.queryLocations(program); + textureStates.queryLocations(program); } template <class BinaryProgram> Program(Context& context, const BinaryProgram& binaryProgram) : program(context.createProgram(binaryProgram.format(), binaryProgram.code())), - uniformsState(Uniforms::loadNamedLocations(binaryProgram)), - attributeLocations(Attributes::loadNamedLocations(binaryProgram)) { - textures.loadNamedLocations(binaryProgram); + attributeLocations(binaryProgram) { + uniformStates.loadNamedLocations(binaryProgram); + textureStates.loadNamedLocations(binaryProgram); } - - static Program createProgram(gl::Context& context, - const ProgramParameters& programParameters, - const char* name, - const char* vertexSource_, - const char* fragmentSource_) { - const std::string vertexSource = shaders::vertexSource(programParameters, vertexSource_); - const std::string fragmentSource = shaders::fragmentSource(programParameters, fragmentSource_); + + static std::unique_ptr<Program> createProgram(gl::Context& context, + const ProgramParameters& programParameters, + const char* name, + const char* vertexSource_, + const char* fragmentSource_) { + const std::string vertexSource = programs::gl::vertexSource(programParameters, vertexSource_); + const std::string fragmentSource = programs::gl::fragmentSource(programParameters, fragmentSource_); #if MBGL_HAS_BINARY_PROGRAMS optional<std::string> cachePath = programParameters.cachePath(name); if (cachePath && context.supportsProgramBinaries()) { - const std::string identifier = shaders::programIdentifier(vertexSource, fragmentSource); + const std::string identifier = programs::gl::programIdentifier(vertexSource, fragmentSource); try { if (auto cachedBinaryProgram = util::readFile(*cachePath)) { const BinaryProgram binaryProgram(std::move(*cachedBinaryProgram)); if (binaryProgram.identifier() == identifier) { - return Program { context, binaryProgram }; + return std::make_unique<Program>(context, binaryProgram); } else { Log::Warning(Event::OpenGL, "Cached program %s changed. Recompilation required.", @@ -87,11 +86,11 @@ public: } // Compile the shader - Program result{ context, vertexSource, fragmentSource }; + auto result = std::make_unique<Program>(context, vertexSource, fragmentSource); try { if (const auto binaryProgram = - result.template get<BinaryProgram>(context, identifier)) { + result->template get<BinaryProgram>(context, identifier)) { util::write_file(*cachePath, binaryProgram->serialize()); Log::Warning(Event::OpenGL, "Caching program in: %s", (*cachePath).c_str()); } @@ -104,37 +103,37 @@ public: #endif (void)name; - return Program { context, vertexSource, fragmentSource }; + return std::make_unique<Program>(context, vertexSource, fragmentSource); } template <class BinaryProgram> optional<BinaryProgram> get(Context& context, const std::string& identifier) const { if (auto binaryProgram = context.getBinaryProgram(program)) { - return BinaryProgram{ binaryProgram->first, std::move(binaryProgram->second), - identifier, Attributes::getNamedLocations(attributeLocations), - Uniforms::getNamedLocations(uniformsState), - textures.getNamedLocations() }; + return BinaryProgram{ binaryProgram->first, + std::move(binaryProgram->second), + identifier, + attributeLocations.getNamedLocations(), + uniformStates.getNamedLocations(), + textureStates.getNamedLocations() }; } return {}; } - template <class DrawMode> - void draw(Context& context, - DrawMode drawMode, - gfx::DepthMode depthMode, - gfx::StencilMode stencilMode, - gfx::ColorMode colorMode, - gfx::CullFaceMode cullFaceMode, - const UniformValues& uniformValues, - gl::VertexArray& vertexArray, - const AttributeBindings& attributeBindings, - const TextureBindings& textureBindings, + void draw(gfx::Context& genericContext, + const gfx::DrawMode& drawMode, + const gfx::DepthMode& depthMode, + const gfx::StencilMode& stencilMode, + const gfx::ColorMode& colorMode, + const gfx::CullFaceMode& cullFaceMode, + const gfx::UniformValues<UniformList>& uniformValues, + gfx::DrawScope& drawScope, + const gfx::AttributeBindings<AttributeList>& attributeBindings, + const gfx::TextureBindings<TextureList>& textureBindings, const gfx::IndexBuffer& indexBuffer, std::size_t indexOffset, - std::size_t indexLength) { - static_assert(std::is_same<Primitive, typename DrawMode::Primitive>::value, "incompatible draw mode"); + std::size_t indexLength) override { + auto& context = reinterpret_cast<gl::Context&>(genericContext); - context.setDrawMode(drawMode); context.setDepthMode(depthMode); context.setStencilMode(stencilMode); context.setColorMode(colorMode); @@ -142,15 +141,16 @@ public: context.program = program; - Uniforms::bind(uniformsState, uniformValues); + uniformStates.bind(uniformValues); - textures.bind(context, textureBindings); + textureStates.bind(context, textureBindings); + auto& vertexArray = reinterpret_cast<gl::DrawScopeResource&>(*drawScope.resource).vertexArray; vertexArray.bind(context, indexBuffer, - Attributes::toBindingArray(attributeLocations, attributeBindings)); + attributeLocations.toBindingArray(attributeBindings)); - context.draw(drawMode.primitiveType, + context.draw(drawMode, indexOffset, indexLength); } @@ -158,9 +158,9 @@ public: private: UniqueProgram program; - typename Uniforms::State uniformsState; - typename Attributes::Locations attributeLocations; - gl::Textures<TextureList> textures; + gl::AttributeLocations<AttributeList> attributeLocations; + gl::UniformStates<UniformList> uniformStates; + gl::TextureStates<TextureList> textureStates; }; } // namespace gl diff --git a/src/mbgl/gl/texture.hpp b/src/mbgl/gl/texture.hpp index 8230be1652..0569adc3b0 100644 --- a/src/mbgl/gl/texture.hpp +++ b/src/mbgl/gl/texture.hpp @@ -15,13 +15,15 @@ class Context; void bindTexture(gl::Context&, uint8_t unit, const gfx::TextureBinding&); template <class> -class Textures; +class TextureStates; template <class... Ts> -class Textures<TypeList<Ts...>> { +class TextureStates<TypeList<Ts...>> { +private: using State = IndexedTuple<TypeList<Ts...>, TypeList<ExpandToType<Ts, gl::UniformState<uint8_t>>...>>; - using NamedLocations = std::vector<std::pair<const std::string, gl::UniformLocation>>; + + State state; public: void queryLocations(const ProgramID& id) { @@ -33,8 +35,8 @@ public: state = State{ program.textureLocation(Ts::name())... }; } - NamedLocations getNamedLocations() const { - return NamedLocations{ { Ts::name(), state.template get<Ts>().location }... }; + NamedUniformLocations getNamedLocations() const { + return NamedUniformLocations{ { Ts::name(), state.template get<Ts>().location }... }; } void bind(gl::Context& context, const gfx::TextureBindings<TypeList<Ts...>>& bindings) { @@ -43,9 +45,6 @@ public: gl::bindTexture(context, TypeIndex<Ts, Ts...>::value, bindings.template get<Ts>()), 0)... }); } - -private: - State state; }; } // namespace gl diff --git a/src/mbgl/gl/uniform.hpp b/src/mbgl/gl/uniform.hpp index 3827015bb3..770f3e2294 100644 --- a/src/mbgl/gl/uniform.hpp +++ b/src/mbgl/gl/uniform.hpp @@ -1,5 +1,6 @@ #pragma once +#include <mbgl/gfx/uniform.hpp> #include <mbgl/gl/types.hpp> #include <mbgl/util/optional.hpp> #include <mbgl/util/ignore.hpp> @@ -49,23 +50,25 @@ public: optional<Value> current = {}; }; -UniformLocation uniformLocation(ProgramID, const char * name); +UniformLocation uniformLocation(ProgramID, const char* name); + +using NamedUniformLocations = std::vector<std::pair<const std::string, UniformLocation>>; template <class> -class Uniforms; +class UniformStates; template <class... Us> -class Uniforms<TypeList<Us...>> final { -public: - using Types = TypeList<Us...>; +class UniformStates<TypeList<Us...>> final { +private: using State = IndexedTuple<TypeList<Us...>, TypeList<UniformState<typename Us::Value>...>>; - using Values = IndexedTuple<TypeList<Us...>, TypeList<typename Us::Value...>>; - using NamedLocations = std::vector<std::pair<const std::string, UniformLocation>>; - static State bindLocations(const ProgramID& id) { + State state; + +public: + void queryLocations(const ProgramID& id) { #ifndef NDEBUG // Verify active uniform types match the enum - const auto active = activeUniforms(id); + const auto active = gl::activeUniforms(id); util::ignore( { // Some shader programs have uniforms declared, but not used, so they're not active. @@ -75,19 +78,19 @@ public: : false)... }); #endif - return State(uniformLocation(id, Us::name())...); + state = State{ gl::uniformLocation(id, Us::name())... }; } - template <class Program> - static State loadNamedLocations(const Program& program) { - return State(UniformState<typename Us::Value>(program.uniformLocation(Us::name()))...); + template <class BinaryProgram> + void loadNamedLocations(const BinaryProgram& program) { + state = State{ UniformState<typename Us::Value>(program.uniformLocation(Us::name()))... }; } - static NamedLocations getNamedLocations(const State& state) { - return NamedLocations{ { Us::name(), state.template get<Us>().location }... }; + NamedUniformLocations getNamedLocations() const { + return NamedUniformLocations{ { Us::name(), state.template get<Us>().location }... }; } - static void bind(State& state, const Values& values) { + void bind(const gfx::UniformValues<TypeList<Us...>>& values) { util::ignore({ (state.template get<Us>() = values.template get<Us>(), 0)... }); } }; diff --git a/src/mbgl/gl/value.cpp b/src/mbgl/gl/value.cpp index 8f5b53fcac..bd08ac48fc 100644 --- a/src/mbgl/gl/value.cpp +++ b/src/mbgl/gl/value.cpp @@ -397,7 +397,7 @@ BindVertexArray::Type BindVertexArray::Get(const Context& context) { return binding; } -const optional<AttributeBinding> VertexAttribute::Default {}; +const VertexAttribute::Type VertexAttribute::Default {}; namespace { @@ -484,7 +484,7 @@ GLint components(const gfx::AttributeDataType type) { } // namespace -void VertexAttribute::Set(const optional<AttributeBinding>& binding, Context& context, AttributeLocation location) { +void VertexAttribute::Set(const Type& binding, Context& context, AttributeLocation location) { if (binding) { context.vertexBuffer = reinterpret_cast<const gl::VertexBufferResource&>(*binding->vertexBufferResource).buffer; MBGL_CHECK_ERROR(glEnableVertexAttribArray(location)); diff --git a/src/mbgl/gl/value.hpp b/src/mbgl/gl/value.hpp index 15812a49bd..5bd2132ecf 100644 --- a/src/mbgl/gl/value.hpp +++ b/src/mbgl/gl/value.hpp @@ -264,7 +264,7 @@ struct BindVertexArray { }; struct VertexAttribute { - using Type = optional<gl::AttributeBinding>; + using Type = optional<gfx::AttributeBinding>; static const Type Default; static void Set(const Type&, Context&, AttributeLocation); }; |