#ifndef _SGLRSHADERPROGRAM_HPP #define _SGLRSHADERPROGRAM_HPP /*------------------------------------------------------------------------- * drawElements Quality Program OpenGL ES Utilities * ------------------------------------------------ * * Copyright 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief SGLR shader program. *//*--------------------------------------------------------------------*/ #include "tcuDefs.hpp" #include "rrShaders.hpp" #include "gluShaderUtil.hpp" #include #include namespace sglr { namespace rc { class Texture1D; class Texture2D; class TextureCube; class Texture2DArray; class Texture3D; class TextureCubeArray; } // namespace rc class ShaderProgram; namespace pdec { enum VaryingFlags { VARYINGFLAG_NONE = 0, VARYINGFLAG_FLATSHADE = (1 << 0), }; struct VertexAttribute { VertexAttribute(const std::string &name_, rr::GenericVecType type_) : name(name_), type(type_) { } std::string name; rr::GenericVecType type; }; struct VertexToFragmentVarying { VertexToFragmentVarying(rr::GenericVecType type_, int flags = VARYINGFLAG_NONE) : type(type_) , flatshade((flags & VARYINGFLAG_FLATSHADE) != 0) { } rr::GenericVecType type; bool flatshade; }; struct VertexToGeometryVarying { VertexToGeometryVarying(rr::GenericVecType type_, int flags = VARYINGFLAG_NONE) : type(type_) , flatshade((flags & VARYINGFLAG_FLATSHADE) != 0) { } rr::GenericVecType type; bool flatshade; }; struct GeometryToFragmentVarying { GeometryToFragmentVarying(rr::GenericVecType type_, int flags = VARYINGFLAG_NONE) : type(type_) , flatshade((flags & VARYINGFLAG_FLATSHADE) != 0) { } rr::GenericVecType type; bool flatshade; }; struct FragmentOutput { FragmentOutput(rr::GenericVecType type_) : type(type_) { } rr::GenericVecType type; }; struct Uniform { Uniform(const std::string &name_, glu::DataType type_) : name(name_), type(type_) { } std::string name; glu::DataType type; }; struct VertexSource { VertexSource(const std::string &str) : source(str) { } std::string source; }; struct FragmentSource { FragmentSource(const std::string &str) : source(str) { } std::string source; }; struct GeometrySource { GeometrySource(const std::string &str) : source(str) { } std::string source; }; struct GeometryShaderDeclaration { GeometryShaderDeclaration(rr::GeometryShaderInputType inputType_, rr::GeometryShaderOutputType outputType_, size_t numOutputVertices_, size_t numInvocations_ = 1) : inputType(inputType_) , outputType(outputType_) , numOutputVertices(numOutputVertices_) , numInvocations(numInvocations_) { } rr::GeometryShaderInputType inputType; rr::GeometryShaderOutputType outputType; size_t numOutputVertices; size_t numInvocations; }; class ShaderProgramDeclaration { public: ShaderProgramDeclaration(void); ShaderProgramDeclaration &operator<<(const VertexAttribute &); ShaderProgramDeclaration &operator<<(const VertexToFragmentVarying &); ShaderProgramDeclaration &operator<<(const VertexToGeometryVarying &); ShaderProgramDeclaration &operator<<(const GeometryToFragmentVarying &); ShaderProgramDeclaration &operator<<(const FragmentOutput &); ShaderProgramDeclaration &operator<<(const Uniform &); ShaderProgramDeclaration &operator<<(const VertexSource &); ShaderProgramDeclaration &operator<<(const FragmentSource &); ShaderProgramDeclaration &operator<<(const GeometrySource &); ShaderProgramDeclaration &operator<<(const GeometryShaderDeclaration &); private: inline bool hasGeometryShader(void) const { return m_geometryShaderSet; } inline size_t getVertexInputCount(void) const { return m_vertexAttributes.size(); } inline size_t getVertexOutputCount(void) const { return hasGeometryShader() ? m_vertexToGeometryVaryings.size() : m_vertexToFragmentVaryings.size(); } inline size_t getFragmentInputCount(void) const { return hasGeometryShader() ? m_geometryToFragmentVaryings.size() : m_vertexToFragmentVaryings.size(); } inline size_t getFragmentOutputCount(void) const { return m_fragmentOutputs.size(); } inline size_t getGeometryInputCount(void) const { return hasGeometryShader() ? m_vertexToGeometryVaryings.size() : 0; } inline size_t getGeometryOutputCount(void) const { return hasGeometryShader() ? m_geometryToFragmentVaryings.size() : 0; } bool valid(void) const; std::vector m_vertexAttributes; std::vector m_vertexToFragmentVaryings; std::vector m_vertexToGeometryVaryings; std::vector m_geometryToFragmentVaryings; std::vector m_fragmentOutputs; std::vector m_uniforms; std::string m_vertexSource; std::string m_fragmentSource; std::string m_geometrySource; GeometryShaderDeclaration m_geometryDecl; bool m_vertexShaderSet; bool m_fragmentShaderSet; bool m_geometryShaderSet; friend class ::sglr::ShaderProgram; }; } // namespace pdec struct UniformSlot { std::string name; glu::DataType type; union { int32_t i; int32_t i4[4]; float f; float f4[4]; float m3[3 * 3]; //!< row major, can be fed directly to tcu::Matrix constructor float m4[4 * 4]; //!< row major, can be fed directly to tcu::Matrix constructor } value; union { const void *ptr; const rc::Texture1D *tex1D; const rc::Texture2D *tex2D; const rc::TextureCube *texCube; const rc::Texture2DArray *tex2DArray; const rc::Texture3D *tex3D; const rc::TextureCubeArray *texCubeArray; } sampler; inline UniformSlot(void) : type(glu::TYPE_LAST) { value.i = 0; sampler.ptr = DE_NULL; } }; class ShaderProgram : private rr::VertexShader, private rr::GeometryShader, private rr::FragmentShader { public: ShaderProgram(const pdec::ShaderProgramDeclaration &); virtual ~ShaderProgram(void); const UniformSlot &getUniformByName(const char *name) const; inline const rr::VertexShader *getVertexShader(void) const { return static_cast(this); } inline const rr::FragmentShader *getFragmentShader(void) const { return static_cast(this); } inline const rr::GeometryShader *getGeometryShader(void) const { return static_cast(this); } private: virtual void shadeVertices(const rr::VertexAttrib *inputs, rr::VertexPacket *const *packets, const int numPackets) const = 0; virtual void shadeFragments(rr::FragmentPacket *packets, const int numPackets, const rr::FragmentShadingContext &context) const = 0; virtual void shadePrimitives(rr::GeometryEmitter &output, int verticesIn, const rr::PrimitivePacket *packets, const int numPackets, int invocationID) const; std::vector m_attributeNames; protected: std::vector m_uniforms; private: const std::string m_vertSrc; const std::string m_fragSrc; const std::string m_geomSrc; const bool m_hasGeometryShader; friend class ReferenceContext; // for uniform access friend class GLContext; // for source string access } DE_WARN_UNUSED_TYPE; } // namespace sglr #endif // _SGLRSHADERPROGRAM_HPP