//----------------------------------------------------------------------------- // Copyright (c) 2012 GarageGames, LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //----------------------------------------------------------------------------- #ifndef _GFXGLSHADER_H_ #define _GFXGLSHADER_H_ #include "core/util/refBase.h" #include "gfx/gfxShader.h" #include "gfx/gl/tGL/tGL.h" #include "core/util/tSignal.h" #include "core/util/tDictionary.h" class FileStream; class GFXGLDevice; class GFXGLShader; struct BufferRange { U32 mBufMin = U32_MAX; U32 mBufMax = 0; inline void addSlot(U32 slot) { mBufMin = getMin(mBufMin, slot); mBufMax = getMax(mBufMax, slot); } inline bool isValid() const { return mBufMin <= mBufMax; } }; struct ConstantBuffer { GLuint bufHandle; U8* data; U32 size; bool isDirty; }; class GFXGLShaderConstHandle : public GFXShaderConstHandle { friend class GFXGLShader; public: // DX side needs the description map as the same uniform can exist across stages. for gl it is program wide. GFXGLShaderConstHandle(GFXGLShader* shader); GFXGLShaderConstHandle(GFXGLShader* shader, const GFXShaderConstDesc& desc); void reinit(const GFXShaderConstDesc& desc); virtual ~GFXGLShaderConstHandle(); const GFXShaderConstDesc getDesc(); const String& getName() const override { return mDesc.name; } GFXShaderConstType getType() const override { return mDesc.constType; } U32 getArraySize() const override { return mDesc.arraySize; } U32 getSize() const { return mDesc.size; } void setValid(bool valid) { mValid = valid; } /// @warning This will always return the value assigned when the shader was /// initialized. If the value is later changed this method won't reflect that. S32 getSamplerRegister() const override { return (!isSampler() || !mValid) ? -1 : mDesc.samplerReg; } // Returns true if this is a handle to a sampler register. bool isSampler() const { return (getType() >= GFXSCT_Sampler); } /// Restore to uninitialized state. void clear() { mShader = NULL; mInstancingConstant = false; mValid = false; } GFXShaderConstDesc mDesc; GFXGLShader* mShader; bool mUBOUniform; bool mInstancingConstant; }; class GFXGLShaderConstBuffer : public GFXShaderConstBuffer { public: // -1 is the global buffer. typedef Map BufferMap; GFXGLShaderConstBuffer(GFXGLShader* shader); ~GFXGLShaderConstBuffer(); /// Called by GFXGLDevice to activate this buffer. void activate(GFXGLShaderConstBuffer* prevShaderBuffer); void addBuffer(const GFXShaderConstDesc desc); /// Called when the shader this buffer references is reloaded. void onShaderReload(GFXGLShader* shader); // GFXShaderConstBuffer GFXShader* getShader() override; void set(GFXShaderConstHandle* handle, const F32 fv) override; void set(GFXShaderConstHandle* handle, const Point2F& fv) override; void set(GFXShaderConstHandle* handle, const Point3F& fv) override; void set(GFXShaderConstHandle* handle, const Point4F& fv) override; void set(GFXShaderConstHandle* handle, const PlaneF& fv) override; void set(GFXShaderConstHandle* handle, const LinearColorF& fv) override; void set(GFXShaderConstHandle* handle, const S32 f) override; void set(GFXShaderConstHandle* handle, const Point2I& fv) override; void set(GFXShaderConstHandle* handle, const Point3I& fv) override; void set(GFXShaderConstHandle* handle, const Point4I& fv) override; void set(GFXShaderConstHandle* handle, const AlignedArray& fv) override; void set(GFXShaderConstHandle* handle, const AlignedArray& fv) override; void set(GFXShaderConstHandle* handle, const AlignedArray& fv) override; void set(GFXShaderConstHandle* handle, const AlignedArray& fv) override; void set(GFXShaderConstHandle* handle, const AlignedArray& fv) override; void set(GFXShaderConstHandle* handle, const AlignedArray& fv) override; void set(GFXShaderConstHandle* handle, const AlignedArray& fv) override; void set(GFXShaderConstHandle* handle, const AlignedArray& fv) override; void set(GFXShaderConstHandle* handle, const MatrixF& mat, const GFXShaderConstType matType = GFXSCT_Float4x4) override; void set(GFXShaderConstHandle* handle, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType = GFXSCT_Float4x4) override; // GFXResource const String describeSelf() const override; void zombify() override {} void resurrect() override {} private: friend class GFXGLShader; WeakRefPtr mShader; BufferMap mBufferMap; template void internalSet(GFXShaderConstHandle* handle, const ConstType& param); template void internalSet(GFXShaderConstHandle* handle, const AlignedArray& fv); }; class GFXGLShader : public GFXShader { friend class GFXGLShaderConstBuffer; friend class GFXGLShaderConstHandle; public: typedef Map HandleMap; typedef Map BufferMap; GFXGLShader(GFXGLDevice* device); virtual ~GFXGLShader(); /// @name GFXShader interface /// @{ GFXShaderConstHandle* getShaderConstHandle(const String& name) override; GFXShaderConstHandle* findShaderConstHandle(const String& name) override; /// Returns our list of shader constants, the material can get this and just set the constants it knows about const Vector& getShaderConstDesc() const override; /// Returns the alignment value for constType U32 getAlignmentValue(const GFXShaderConstType constType) const override; GFXShaderConstBufferRef allocConstBuffer() override; /// @} /// @name GFXResource interface /// @{ void zombify() override; void resurrect() override { reload(); } const String describeSelf() const override; /// @} /// Activates this shader in the GL context. void useProgram(); protected: bool _init() override; bool initShader(const Torque::Path& file, GFXShaderStage stage, const Vector& macros); void clearShaders(); void initConstantDescs(); void initHandles(); void setConstantsFromBuffer(U8* buffer); static char* _handleIncludes(const Torque::Path& path, FileStream* s); static bool _loadShaderFromStream(GLuint shader, const Torque::Path& path, FileStream* s, const Vector& macros); /// @name Internal GL handles /// @{ GLuint mVertexShader; GLuint mPixelShader; GLuint mGeometryShader; GLuint mProgram; /// @} U8* mGlobalConstBuffer; Vector mShaderConsts; HandleMap mHandles; BufferMap mBuffers; GFXGLDevice* mDevice; GFXShaderConstType convertConstType(GLenum constType); }; #endif // _GFXGLSHADER_H_