From c097c6aad2e4c19ef4ec586d5dde7c9fa7077b08 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 6 Mar 2015 10:41:53 -0800 Subject: [PATCH] Adding the self introspection of shaders --- libraries/gpu/src/gpu/Format.h | 28 +- libraries/gpu/src/gpu/GLBackend.h | 4 + libraries/gpu/src/gpu/GLBackendShader.cpp | 331 ++++++++++++++++++++++ libraries/gpu/src/gpu/Shader.cpp | 21 +- libraries/gpu/src/gpu/Shader.h | 72 +++-- libraries/model/src/model/Stage.cpp | 7 +- libraries/render-utils/src/Model.cpp | 9 + 7 files changed, 428 insertions(+), 44 deletions(-) diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index cbf90384ce..73c3c92c0a 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -53,6 +53,8 @@ enum Type { NUINT8, NUM_TYPES, + + BOOL = UINT8, }; // Array providing the size in bytes for a given scalar type static const int TYPE_SIZE[NUM_TYPES] = { @@ -81,9 +83,9 @@ enum Dimension { VEC2, VEC3, VEC4, + MAT2, MAT3, MAT4, - NUM_DIMENSIONS, }; // Count (of scalars) in an Element for a given Dimension @@ -92,8 +94,9 @@ static const int DIMENSION_COUNT[NUM_DIMENSIONS] = { 2, 3, 4, + 4, 9, - 16 + 16, }; // Semantic of an Element @@ -118,6 +121,27 @@ enum Semantic { SRGBA, SBGRA, + UNIFORM, + + TEXTURE, + BUFFER, + + SAMPLER_1D, + SAMPLER_2D, + SAMPLER_2D_MS, + SAMPLER_3D, + SAMPLER_CUBE, + SAMPLER_1D_ARRAY, + SAMPLER_2D_ARRAY, + SAMPLER_2D_MS_ARRAY, + SAMPLER_3D_ARRAY, + SAMPLER_CUBE_ARRAY, + SAMPLER_2D_SHADOW, + SAMPLER_2D_SHADOW_ARRAY, + SAMPLER_CUBE_SHADOW, + SAMPLER_CUBE_SHADOW_ARRAY, + + NUM_SEMANTICS, }; diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 81271851bb..535d7a3e1f 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -33,6 +33,7 @@ public: static void checkGLError(); + static bool makeShader(Shader& shader); class GLBuffer : public GPUObject { @@ -65,6 +66,9 @@ public: GLuint _shader; GLuint _program; + GLuint _transformCameraSlot = -1; + GLuint _transformObjectSlot = -1; + GLShader(); ~GLShader(); }; diff --git a/libraries/gpu/src/gpu/GLBackendShader.cpp b/libraries/gpu/src/gpu/GLBackendShader.cpp index 4d84d33a5f..724f1ad019 100755 --- a/libraries/gpu/src/gpu/GLBackendShader.cpp +++ b/libraries/gpu/src/gpu/GLBackendShader.cpp @@ -10,6 +10,9 @@ // #include "GLBackendShared.h" +#include "Format.h" + +using namespace gpu; GLBackend::GLShader::GLShader() : _shader(0), @@ -25,6 +28,78 @@ GLBackend::GLShader::~GLShader() { } } + +void makeBindings(GLBackend::GLShader* shader) { + if(!shader || !shader->_program) { + return; + } + GLuint glprogram = shader->_program; + GLint loc = -1; + + //Check for gpu specific attribute bindings + loc = glGetAttribLocation(glprogram, "position"); + if (loc >= 0) { + glBindAttribLocation(glprogram, gpu::Stream::POSITION, "position"); + } + + loc = glGetAttribLocation(glprogram, "normal"); + if (loc >= 0) { + glBindAttribLocation(glprogram, gpu::Stream::NORMAL, "normal"); + } + + loc = glGetAttribLocation(glprogram, "color"); + if (loc >= 0) { + glBindAttribLocation(glprogram, gpu::Stream::COLOR, "color"); + } + + loc = glGetAttribLocation(glprogram, "texcoord"); + if (loc >= 0) { + glBindAttribLocation(glprogram, gpu::Stream::TEXCOORD, "texcoord"); + } + + loc = glGetAttribLocation(glprogram, "tangent"); + if (loc >= 0) { + glBindAttribLocation(glprogram, gpu::Stream::TANGENT, "tangent"); + } + + loc = glGetAttribLocation(glprogram, "texcoord1"); + if (loc >= 0) { + glBindAttribLocation(glprogram, gpu::Stream::TEXCOORD1, "texcoord1"); + } + + loc = glGetAttribLocation(glprogram, "clusterIndices"); + if (loc >= 0) { + glBindAttribLocation(glprogram, gpu::Stream::SKIN_CLUSTER_INDEX, "clusterIndices"); + } + + loc = glGetAttribLocation(glprogram, "clusterWeights"); + if (loc >= 0) { + glBindAttribLocation(glprogram, gpu::Stream::SKIN_CLUSTER_WEIGHT, "clusterWeights"); + } + + //Check for gpu specific uniform bindings + loc = glGetUniformBlockIndex(glprogram, "transformObjectBuffer"); + if (loc >= 0) { + glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_OBJECT_SLOT); + shader->_transformObjectSlot = gpu::TRANSFORM_OBJECT_SLOT; + } + + loc = glGetUniformBlockIndex(glprogram, "transformCameraBuffer"); + if (loc >= 0) { + glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_CAMERA_SLOT); + shader->_transformCameraSlot = gpu::TRANSFORM_OBJECT_SLOT; + } + + // Link again + glLinkProgram(glprogram); + + GLint linked = 0; + glGetProgramiv(glprogram, GL_LINK_STATUS, &linked); + if (!linked) { + qDebug() << "GLShader::makeBindings - failed to link after assigning bindings?"; + } +} + GLBackend::GLShader* compileShader(const Shader& shader) { // Any GLSLprogram ? normally yes... const std::string& shaderSource = shader.getSource().getCode(); @@ -144,6 +219,8 @@ GLBackend::GLShader* compileShader(const Shader& shader) { object->_shader = glshader; object->_program = glprogram; + makeBindings(object); + return object; } @@ -220,6 +297,8 @@ GLBackend::GLShader* compileProgram(const Shader& program) { object->_shader = 0; object->_program = glprogram; + makeBindings(object); + return object; } @@ -265,3 +344,255 @@ GLuint GLBackend::getShaderID(const ShaderPointer& shader) { } } +Element getFormatFromGLUniform(GLenum gltype) { + switch (gltype) { + case GL_FLOAT: return Element(SCALAR, gpu::FLOAT, UNIFORM); + case GL_FLOAT_VEC2: return Element(VEC2, gpu::FLOAT, UNIFORM); + case GL_FLOAT_VEC3: return Element(VEC3, gpu::FLOAT, UNIFORM); + case GL_FLOAT_VEC4: return Element(VEC4, gpu::FLOAT, UNIFORM); + + case GL_DOUBLE: return Element(SCALAR, gpu::FLOAT, UNIFORM); + case GL_DOUBLE_VEC2: return Element(VEC2, gpu::FLOAT, UNIFORM); + case GL_DOUBLE_VEC3: return Element(VEC3, gpu::FLOAT, UNIFORM); + case GL_DOUBLE_VEC4: return Element(VEC4, gpu::FLOAT, UNIFORM); + + case GL_INT: return Element(SCALAR, gpu::INT32, UNIFORM); + case GL_INT_VEC2: return Element(VEC2, gpu::INT32, UNIFORM); + case GL_INT_VEC3: return Element(VEC3, gpu::INT32, UNIFORM); + case GL_INT_VEC4: return Element(VEC4, gpu::INT32, UNIFORM); + + case GL_UNSIGNED_INT: return Element(SCALAR, gpu::UINT32, UNIFORM); + case GL_UNSIGNED_INT_VEC2: return Element(VEC2, gpu::UINT32, UNIFORM); + case GL_UNSIGNED_INT_VEC3: return Element(VEC3, gpu::UINT32, UNIFORM); + case GL_UNSIGNED_INT_VEC4: return Element(VEC4, gpu::UINT32, UNIFORM); + + case GL_BOOL: return Element(SCALAR, gpu::BOOL, UNIFORM); + case GL_BOOL_VEC2: return Element(VEC2, gpu::BOOL, UNIFORM); + case GL_BOOL_VEC3: return Element(VEC3, gpu::BOOL, UNIFORM); + case GL_BOOL_VEC4: return Element(VEC4, gpu::BOOL, UNIFORM); + + + case GL_FLOAT_MAT2: return Element(gpu::MAT2, gpu::FLOAT, UNIFORM); + case GL_FLOAT_MAT3: return Element(MAT3, gpu::FLOAT, UNIFORM); + case GL_FLOAT_MAT4: return Element(MAT4, gpu::FLOAT, UNIFORM); + +/* {GL_FLOAT_MAT2x3 mat2x3}, + {GL_FLOAT_MAT2x4 mat2x4}, + {GL_FLOAT_MAT3x2 mat3x2}, + {GL_FLOAT_MAT3x4 mat3x4}, + {GL_FLOAT_MAT4x2 mat4x2}, + {GL_FLOAT_MAT4x3 mat4x3}, + {GL_DOUBLE_MAT2 dmat2}, + {GL_DOUBLE_MAT3 dmat3}, + {GL_DOUBLE_MAT4 dmat4}, + {GL_DOUBLE_MAT2x3 dmat2x3}, + {GL_DOUBLE_MAT2x4 dmat2x4}, + {GL_DOUBLE_MAT3x2 dmat3x2}, + {GL_DOUBLE_MAT3x4 dmat3x4}, + {GL_DOUBLE_MAT4x2 dmat4x2}, + {GL_DOUBLE_MAT4x3 dmat4x3}, + */ + + case GL_SAMPLER_1D: return Element(SCALAR, gpu::FLOAT, SAMPLER_1D); + case GL_SAMPLER_2D: return Element(SCALAR, gpu::FLOAT, SAMPLER_2D); + case GL_SAMPLER_2D_MULTISAMPLE: return Element(SCALAR, gpu::FLOAT, SAMPLER_2D_MS); + case GL_SAMPLER_3D: return Element(SCALAR, gpu::FLOAT, SAMPLER_3D); + case GL_SAMPLER_CUBE: return Element(SCALAR, gpu::FLOAT, SAMPLER_CUBE); + + case GL_SAMPLER_1D_ARRAY: return Element(SCALAR, gpu::FLOAT, SAMPLER_1D_ARRAY); + case GL_SAMPLER_2D_ARRAY: return Element(SCALAR, gpu::FLOAT, SAMPLER_2D_ARRAY); + case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: return Element(SCALAR, gpu::FLOAT, SAMPLER_2D_MS_ARRAY); + + case GL_SAMPLER_2D_SHADOW: return Element(SCALAR, gpu::FLOAT, SAMPLER_2D_SHADOW); + case GL_SAMPLER_CUBE_SHADOW: return Element(SCALAR, gpu::FLOAT, SAMPLER_CUBE_SHADOW); + + case GL_SAMPLER_2D_ARRAY_SHADOW: return Element(SCALAR, gpu::FLOAT, SAMPLER_2D_SHADOW_ARRAY); + +// {GL_SAMPLER_1D_SHADOW sampler1DShadow}, + // {GL_SAMPLER_1D_ARRAY_SHADOW sampler1DArrayShadow}, + +// {GL_SAMPLER_BUFFER samplerBuffer}, +// {GL_SAMPLER_2D_RECT sampler2DRect}, + // {GL_SAMPLER_2D_RECT_SHADOW sampler2DRectShadow}, + + case GL_INT_SAMPLER_1D: return Element(SCALAR, gpu::INT32, SAMPLER_1D); + case GL_INT_SAMPLER_2D: return Element(SCALAR, gpu::INT32, SAMPLER_2D); + case GL_INT_SAMPLER_2D_MULTISAMPLE: return Element(SCALAR, gpu::INT32, SAMPLER_2D_MS); + case GL_INT_SAMPLER_3D: return Element(SCALAR, gpu::INT32, SAMPLER_3D); + case GL_INT_SAMPLER_CUBE: return Element(SCALAR, gpu::INT32, SAMPLER_CUBE); + + case GL_INT_SAMPLER_1D_ARRAY: return Element(SCALAR, gpu::INT32, SAMPLER_1D_ARRAY); + case GL_INT_SAMPLER_2D_ARRAY: return Element(SCALAR, gpu::INT32, SAMPLER_2D_ARRAY); + case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: return Element(SCALAR, gpu::INT32, SAMPLER_2D_MS_ARRAY); + + // {GL_INT_SAMPLER_BUFFER isamplerBuffer}, + // {GL_INT_SAMPLER_2D_RECT isampler2DRect}, + + case GL_UNSIGNED_INT_SAMPLER_1D: return Element(SCALAR, gpu::UINT32, SAMPLER_1D); + case GL_UNSIGNED_INT_SAMPLER_2D: return Element(SCALAR, gpu::UINT32, SAMPLER_2D); + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: return Element(SCALAR, gpu::UINT32, SAMPLER_2D_MS); + case GL_UNSIGNED_INT_SAMPLER_3D: return Element(SCALAR, gpu::UINT32, SAMPLER_3D); + case GL_UNSIGNED_INT_SAMPLER_CUBE: return Element(SCALAR, gpu::UINT32, SAMPLER_CUBE); + + case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY: return Element(SCALAR, gpu::UINT32, SAMPLER_1D_ARRAY); + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: return Element(SCALAR, gpu::UINT32, SAMPLER_2D_ARRAY); + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: return Element(SCALAR, gpu::UINT32, SAMPLER_2D_MS_ARRAY); + +// {GL_UNSIGNED_INT_SAMPLER_BUFFER usamplerBuffer}, +// {GL_UNSIGNED_INT_SAMPLER_2D_RECT usampler2DRect}, +/* + {GL_IMAGE_1D image1D}, + {GL_IMAGE_2D image2D}, + {GL_IMAGE_3D image3D}, + {GL_IMAGE_2D_RECT image2DRect}, + {GL_IMAGE_CUBE imageCube}, + {GL_IMAGE_BUFFER imageBuffer}, + {GL_IMAGE_1D_ARRAY image1DArray}, + {GL_IMAGE_2D_ARRAY image2DArray}, + {GL_IMAGE_2D_MULTISAMPLE image2DMS}, + {GL_IMAGE_2D_MULTISAMPLE_ARRAY image2DMSArray}, + {GL_INT_IMAGE_1D iimage1D}, + {GL_INT_IMAGE_2D iimage2D}, + {GL_INT_IMAGE_3D iimage3D}, + {GL_INT_IMAGE_2D_RECT iimage2DRect}, + {GL_INT_IMAGE_CUBE iimageCube}, + {GL_INT_IMAGE_BUFFER iimageBuffer}, + {GL_INT_IMAGE_1D_ARRAY iimage1DArray}, + {GL_INT_IMAGE_2D_ARRAY iimage2DArray}, + {GL_INT_IMAGE_2D_MULTISAMPLE iimage2DMS}, + {GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY iimage2DMSArray}, + {GL_UNSIGNED_INT_IMAGE_1D uimage1D}, + {GL_UNSIGNED_INT_IMAGE_2D uimage2D}, + {GL_UNSIGNED_INT_IMAGE_3D uimage3D}, + {GL_UNSIGNED_INT_IMAGE_2D_RECT uimage2DRect}, + {GL_UNSIGNED_INT_IMAGE_CUBE uimageCube},+ [0] {_name="fInnerRadius" _location=0 _element={_semantic=15 '\xf' _dimension=0 '\0' _type=0 '\0' } } gpu::Shader::Slot + + {GL_UNSIGNED_INT_IMAGE_BUFFER uimageBuffer}, + {GL_UNSIGNED_INT_IMAGE_1D_ARRAY uimage1DArray}, + {GL_UNSIGNED_INT_IMAGE_2D_ARRAY uimage2DArray}, + {GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE uimage2DMS}, + {GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY uimage2DMSArray}, + {GL_UNSIGNED_INT_ATOMIC_COUNTER atomic_uint} +*/ + default: + return Element(); + } + +}; + + +int makeUniformSlots(GLuint glprogram, Shader::SlotSet& uniforms, Shader::SlotSet& textures, Shader::SlotSet& samplers) { + GLint uniformsCount = 0; + + glGetProgramiv(glprogram, GL_ACTIVE_UNIFORMS, &uniformsCount); + + for (int i = 0; i < uniformsCount; i++) { + const GLint NAME_LENGTH = 256; + GLchar name[NAME_LENGTH]; + GLint length = 0; + GLint size = 0; + GLenum type = 0; + glGetActiveUniform(glprogram, i, NAME_LENGTH, &length, &size, &type, name); + + auto element = getFormatFromGLUniform(type); + uniforms.insert(Shader::Slot(name, i, element)); + } + + return uniformsCount; +} + +int makeUniformBlockSlots(GLuint glprogram, Shader::SlotSet& buffers) { + GLint buffersCount = 0; + + glGetProgramiv(glprogram, GL_ACTIVE_UNIFORM_BLOCKS, &buffersCount); + + for (int i = 0; i < buffersCount; i++) { + const GLint NAME_LENGTH = 256; + GLchar name[NAME_LENGTH]; + GLint length = 0; + GLint size = 0; + GLenum type = 0; + GLint binding = -1; + glGetActiveUniformBlockiv(glprogram, i, GL_UNIFORM_BLOCK_BINDING, &binding); + glGetActiveUniformBlockiv(glprogram, i, GL_UNIFORM_BLOCK_DATA_SIZE, &size); + glGetActiveUniformBlockiv(glprogram, i, GL_UNIFORM_BLOCK_NAME_LENGTH, &length); + glGetActiveUniformBlockName(glprogram, i, NAME_LENGTH, &length, name); + + Element element(SCALAR, gpu::FLOAT, BUFFER); + buffers.insert(Shader::Slot(name, binding, element)); + } + + return buffersCount; +} + +int makeInputSlots(GLuint glprogram, Shader::SlotSet& inputs) { + GLint inputsCount = 0; + + glGetProgramiv(glprogram, GL_ACTIVE_ATTRIBUTES, &inputsCount); + + for (int i = 0; i < inputsCount; i++) { + const GLint NAME_LENGTH = 256; + GLchar name[NAME_LENGTH]; + GLint length = 0; + GLint size = 0; + GLenum type = 0; + glGetActiveAttrib(glprogram, i, NAME_LENGTH, &length, &size, &type, name); + + auto element = getFormatFromGLUniform(type); + inputs.insert(Shader::Slot(name, i, element)); + } + + return inputsCount; +} + +int makeOutputSlots(GLuint glprogram, Shader::SlotSet& outputs) { + /* GLint outputsCount = 0; + + glGetProgramiv(glprogram, GL_ACTIVE_, &outputsCount); + + for (int i = 0; i < inputsCount; i++) { + const GLint NAME_LENGTH = 256; + GLchar name[NAME_LENGTH]; + GLint length = 0; + GLint size = 0; + GLenum type = 0; + glGetActiveAttrib(glprogram, i, NAME_LENGTH, &length, &size, &type, name); + + auto element = getFormatFromGLUniform(type); + outputs.insert(Shader::Slot(name, i, element)); + } + */ + return 0; //inputsCount; +} + +bool GLBackend::makeShader(Shader& shader) { + + // First make sure the SHader has been compiled + GLShader* object = GLBackend::syncGPUObject(shader); + if (!object) { + return false; + } + + if (object->_program) { + Shader::SlotSet uniforms; + Shader::SlotSet textures; + Shader::SlotSet samplers; + makeUniformSlots(object->_program, uniforms, textures, samplers); + + Shader::SlotSet buffers; + makeUniformBlockSlots(object->_program, buffers); + + Shader::SlotSet inputs; + makeInputSlots(object->_program, inputs); + + Shader::SlotSet outputs; + makeOutputSlots(object->_program, outputs); + + shader.defineSlots(uniforms, buffers, textures, samplers, inputs, outputs); + + } else if (object->_shader) { + + } + + return true; +} diff --git a/libraries/gpu/src/gpu/Shader.cpp b/libraries/gpu/src/gpu/Shader.cpp index 87365e245e..164778b0e2 100755 --- a/libraries/gpu/src/gpu/Shader.cpp +++ b/libraries/gpu/src/gpu/Shader.cpp @@ -33,18 +33,6 @@ Shader::Shader(Type type, Pointer& vertex, Pointer& pixel): Shader::~Shader() { } - -/* -Program::Program(): - _storage(), - _type(GRAPHICS) -{ -} - -Program::~Program() -{ -} -*/ Shader* Shader::createVertex(const Source& source) { Shader* shader = new Shader(VERTEX, source); @@ -65,3 +53,12 @@ Shader* Shader::createProgram(Pointer& vertexShader, Pointer& pixelShader) { } return nullptr; } + +void Shader::defineSlots(const SlotSet& uniforms, const SlotSet& buffers, const SlotSet& textures, const SlotSet& samplers, const SlotSet& inputs, const SlotSet& outputs) { + _uniforms = uniforms; + _buffers = buffers; + _textures = textures; + _samplers = samplers; + _inputs = inputs; + _outputs = outputs; +} diff --git a/libraries/gpu/src/gpu/Shader.h b/libraries/gpu/src/gpu/Shader.h index 57177639ae..3a374d91c8 100755 --- a/libraries/gpu/src/gpu/Shader.h +++ b/libraries/gpu/src/gpu/Shader.h @@ -13,6 +13,7 @@ #include "Resource.h" #include +#include namespace gpu { @@ -40,6 +41,24 @@ public: Language _lang = GLSL; }; + class Slot { + public: + + std::string _name; + uint16 _location; + Element _element; + + Slot(const std::string& name, uint16 location, const Element& element) : _name(name), _location(location), _element(element) {} + + + class Less { + public: + bool operator() (const Slot& x, const Slot& y) const { return x._name < y._name; } + }; + }; + typedef std::set SlotSet; + + enum Type { VERTEX = 0, PIXEL, @@ -65,6 +84,22 @@ public: const Shaders& getShaders() const { return _shaders; } + // Access the exposed uniform, input and output slot + const SlotSet& getUniforms() const { return _uniforms; } + const SlotSet& getBuffers() const { return _buffers; } + const SlotSet& getTextures() const { return _textures; } + const SlotSet& getSamplers() const { return _samplers; } + const SlotSet& getInputs() const { return _inputs; } + const SlotSet& getOutputs() const { return _outputs; } + + // Define the list of uniforms, inputs and outputs for the shader + // This call is intendend to build the list of exposed slots in order + // to correctly bind resource to the shader. + // These can be build "manually" from knowledge of the atual shader code + // or automatically by calling "Context::makeShader()", this is the preferred way + void defineSlots(const SlotSet& uniforms, const SlotSet& buffers, const SlotSet& textures, const SlotSet& samplers, const SlotSet& inputs, const SlotSet& outputs); + + protected: Shader(Type type, const Source& source); Shader(Type type, Pointer& vertex, Pointer& pixel); @@ -78,6 +113,14 @@ protected: // if shader is composed of sub shaders, here they are Shaders _shaders; + // List of exposed uniform, input and output slots + SlotSet _uniforms; + SlotSet _buffers; + SlotSet _textures; + SlotSet _samplers; + SlotSet _inputs; + SlotSet _outputs; + // The type of the shader, the master key Type _type; @@ -91,35 +134,6 @@ protected: typedef Shader::Pointer ShaderPointer; typedef std::vector< ShaderPointer > Shaders; -/* -class Program { -public: - - enum Type { - GRAPHICS = 0, - - NUM_TYPES, - }; - - - Program(); - Program(const Program& program); // deep copy of the sysmem shader - Program& operator=(const Program& program); // deep copy of the sysmem texture - ~Program(); - -protected: - Shaders _shaders; - Type _type; - - // This shouldn't be used by anything else than the Backend class with the proper casting. - mutable GPUObject* _gpuObject = NULL; - void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; } - GPUObject* getGPUObject() const { return _gpuObject; } - friend class Backend; -}; - -typedef QSharedPointer ShaderPointer; -*/ }; diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index 9a68779caf..1ebb2e6ece 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -216,8 +216,13 @@ void SunSkyStage::updateGraphicsObject() const { double originAlt = _earthSunModel.getAltitude(); _sunLight->setPosition(Vec3(0.0f, originAlt, 0.0f)); - GLuint program = gpu::GLBackend::getShaderID(_skyShader); + GLuint program = gpu::GLBackend::getShaderID(_skyShader); + static int firstTime = 0; + if (firstTime == 0) { + firstTime++; + gpu::GLBackend::makeShader(*_skyShader); + } } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index c7e5b71b22..3fcf181812 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -299,6 +299,15 @@ void Model::init() { _program.addShaderFromSourceCode(QGLShader::Fragment, model_frag); initProgram(_program, _locations); + + auto defaultShader = gpu::ShaderPointer( + gpu::Shader::createProgram( + gpu::ShaderPointer(gpu::Shader::createVertex(std::string(model_vert))), + gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_frag))) + ) + ); + gpu::GLBackend::makeShader(*defaultShader); + _normalMapProgram.addShaderFromSourceCode(QGLShader::Vertex, model_normal_map_vert); _normalMapProgram.addShaderFromSourceCode(QGLShader::Fragment, model_normal_map_frag); initProgram(_normalMapProgram, _normalMapLocations);