Subversion Repository Public Repository

Divide-Framework

This repository has no backups
This repository's network speed is throttled to 100KB/sec

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
/*
   Copyright (c) 2014 DIVIDE-Studio
   Copyright (c) 2009 Ionut Cava

   This file is part of DIVIDE Framework.

   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 _SHADER_HANDLER_H_
#define _SHADER_HANDLER_H_

#include "Core/Resources/Headers/HardwareResource.h"
#include "Hardware/Video/Headers/RenderAPIEnums.h"
#include "Hardware/Video/Shaders/Headers/Shader.h"

namespace Divide {

class Camera;
class Material;
class Shader;
struct GenericDrawCommand;

class ShaderProgram : public HardwareResource {
public:
    /// A list of built-in sampler slots. Use these if possible
    enum TextureUsage {
        TEXTURE_UNIT0 = 0,
        TEXTURE_UNIT1 = 1,
        TEXTURE_NORMALMAP = 2,
        TEXTURE_OPACITY   = 3,
        TEXTURE_SPECULAR  = 4,
        TEXTURE_PROJECTION = 5,
        TextureUsage_PLACEHOLDER = 6,
        TEXTURE_GLOSS = TEXTURE_SPECULAR,
        TEXTURE_ROUGHNESS = TEXTURE_GLOSS
    };

    virtual ~ShaderProgram();

    virtual bool bind();
    virtual void unbind(bool resetActiveProgram = true);
    virtual bool update(const U64 deltaTime);
    virtual bool unload() { return true; }
    ///Attributes
    inline void Attribute(const stringImpl& ext, D32 value) { Attribute(cachedLoc(ext,false), value); }
    inline void Attribute(const stringImpl& ext, F32 value) { Attribute(cachedLoc(ext, false), value); }
    inline void Attribute(const stringImpl& ext, const vec2<F32>& value) { Attribute(cachedLoc(ext, false), value); }
    inline void Attribute(const stringImpl& ext, const vec3<F32>& value) { Attribute(cachedLoc(ext, false), value); }
    inline void Attribute(const stringImpl& ext, const vec4<F32>& value) { Attribute(cachedLoc(ext, false), value); }
    ///Uniforms (update constant buffer for D3D. Use index as location in buffer)
    inline void Uniform(const stringImpl& ext, U32 value) { Uniform(cachedLoc(ext), value); }
    inline void Uniform(const stringImpl& ext, I32 value) { Uniform(cachedLoc(ext), value); }
    inline void Uniform(const stringImpl& ext, F32 value) { Uniform(cachedLoc(ext), value); }
    inline void Uniform(const stringImpl& ext, bool value) { Uniform(cachedLoc(ext), value); }
    inline void Uniform(const stringImpl& ext, const vec2<F32>& value) { Uniform(cachedLoc(ext), value); }
    inline void Uniform(const stringImpl& ext, const vec2<I32>& value) { Uniform(cachedLoc(ext), value); }
    inline void Uniform(const stringImpl& ext, const vec2<U16>& value) { Uniform(cachedLoc(ext), value); }
    inline void Uniform(const stringImpl& ext, const vec3<F32>& value) { Uniform(cachedLoc(ext), value); }
    inline void Uniform(const stringImpl& ext, const vec4<F32>& value) { Uniform(cachedLoc(ext), value); }
    inline void Uniform(const stringImpl& ext, const mat3<F32>& value, bool rowMajor = false) { 
        Uniform(cachedLoc(ext), value, rowMajor); 
    }
    inline void Uniform(const stringImpl& ext, const mat4<F32>& value, bool rowMajor = false) { 
        Uniform(cachedLoc(ext), value, rowMajor); 
    }
    inline void Uniform(const stringImpl& ext, const vectorImpl<I32 >& values) { Uniform(cachedLoc(ext), values); }
    inline void Uniform(const stringImpl& ext, const vectorImpl<F32 >& values) { Uniform(cachedLoc(ext), values); }
    inline void Uniform(const stringImpl& ext, const vectorImpl<vec2<F32> >& values) { Uniform(cachedLoc(ext), values); }
    inline void Uniform(const stringImpl& ext, const vectorImpl<vec3<F32> >& values) { Uniform(cachedLoc(ext), values); }
    inline void Uniform(const stringImpl& ext, const vectorImpl<vec4<F32> >& values) { Uniform(cachedLoc(ext), values); }
    inline void Uniform(const stringImpl& ext, const vectorImpl<mat3<F32> >& values, bool rowMajor = false) { 
        Uniform(cachedLoc(ext), values, rowMajor); 
    }
    inline void Uniform(const stringImpl& ext, const vectorImpl<mat4<F32> >& values, bool rowMajor = false) { 
        Uniform(cachedLoc(ext), values, rowMajor); 
    }
    ///Uniform Texture
    inline void UniformTexture(const stringImpl& ext, U16 slot) { UniformTexture(cachedLoc(ext), slot); }
    ///Subroutine
    virtual void SetSubroutines(ShaderType type, const vectorImpl<U32>& indices) const = 0;
    virtual void SetSubroutine(ShaderType type, U32 index) const = 0;
    virtual U32  GetSubroutineIndex(ShaderType type, const stringImpl& name) const = 0;
    virtual U32  GetSubroutineUniformLocation(ShaderType type, const stringImpl& name) const = 0;
    virtual U32  GetSubroutineUniformCount(ShaderType type) const = 0;
    ///Attribute+Uniform+UniformTexture implementation
    virtual void Attribute(I32 location, D32 value) const = 0;
    virtual void Attribute(I32 location, F32 value) const = 0;
    virtual void Attribute(I32 location, const vec2<F32>& value) const = 0;
    virtual void Attribute(I32 location, const vec3<F32>& value) const = 0;
    virtual void Attribute(I32 location, const vec4<F32>& value) const = 0;
    virtual void Uniform(I32 location, U32 value) const = 0;
    virtual void Uniform(I32 location, I32 value) const = 0;
    virtual void Uniform(I32 location, F32 value) const = 0;
    virtual void Uniform(I32 location, const vec2<F32>& value) const = 0;
    virtual void Uniform(I32 location, const vec2<I32>& value) const = 0;
    virtual void Uniform(I32 location, const vec2<U16>& value) const = 0;
    virtual void Uniform(I32 location, const vec3<F32>& value) const = 0;
    virtual void Uniform(I32 location, const vec4<F32>& value) const = 0;
    virtual void Uniform(I32 location, const mat3<F32>& value, bool rowMajor = false) const = 0;
    virtual void Uniform(I32 location, const mat4<F32>& value, bool rowMajor = false) const = 0;
    virtual void Uniform(I32 location, const vectorImpl<I32 >& values) const = 0;
    virtual void Uniform(I32 location, const vectorImpl<F32 >& values) const = 0;
    virtual void Uniform(I32 location, const vectorImpl<vec2<F32> >& values) const = 0;
    virtual void Uniform(I32 location, const vectorImpl<vec3<F32> >& values) const = 0;
    virtual void Uniform(I32 location, const vectorImpl<vec4<F32> >& values) const = 0;
    virtual void Uniform(I32 location, const vectorImpl<mat3<F32> >& values, bool rowMajor = false) const = 0;
    virtual void Uniform(I32 location, const vectorImpl<mat4<F32> >& values, bool rowMajor = false) const = 0;
    virtual void UniformTexture(I32, U16 slot) = 0;

    inline void Uniform(I32 location, bool value) const { Uniform(location, value ? 1 : 0); }

    inline  void SetOutputCount(U8 count) { _outputCount = std::min(std::max(count, (U8)1), (U8)4); }
    virtual void attachShader(Shader* const shader,const bool refresh = false) = 0;
    virtual void detachShader(Shader* const shader) = 0;
    ///ShaderProgram object id (i.e.: for OGL _shaderProgramId = glCreateProgram())
    inline U32  getId()   const { return _shaderProgramId; }
    ///Currently active
    inline bool isBound() const {return _bound;}
    ///Is the shader ready for drawing?
    virtual bool isValid() const = 0;
    ///  Calling recompile will re-create the marked shaders from source files and update them in the ShaderManager if needed
    void recompile(const bool vertex, 
                   const bool fragment, 
                   const bool geometry = false, 
                   const bool tessellation = false, 
                   const bool compute = false);
    /// Add a define to the shader. The defined must not have been added previously
    void addShaderDefine(const stringImpl& define);
    /// Remove a define from the shader. The defined must have been added previously
    void removeShaderDefine(const stringImpl& define);
    /// Add either fragment or vertex uniforms (without the "uniform" word. e.g. addShaderUniform("vec3 eyePos", VERTEX_SHADER);)
    void addShaderUniform(const stringImpl& uniform, const ShaderType& type);
    /// Remove an uniform from the shader. The uniform must have been added previously for the specified shader type
    void removeUniform(const stringImpl& uniform, const ShaderType& type);
    /// Flush stored uniform locations
    virtual void flushLocCache() = 0;

    /** ------ BEGIN EXPERIMENTAL CODE ----- **/
    inline vectorAlg::vecSize getFunctionCount(ShaderType shader, U8 LoD){
        return _functionIndex[shader][LoD].size();
    }

    inline void setFunctionCount(ShaderType shader, U8 LoD, vectorAlg::vecSize count){
        _functionIndex[shader][LoD].resize(count, 0);
    }

    inline void setFunctionCount(ShaderType shader, vectorAlg::vecSize count){
        for (U8 i = 0; i < Config::SCENE_NODE_LOD; ++i) {
            setFunctionCount(shader, i, count);
        }
    }

    inline void setFunctionIndex(ShaderType shader, U8 LoD, U32 index, U32 functionEntry){
        if(_functionIndex[shader][LoD].empty()) return;

        DIVIDE_ASSERT(index < _functionIndex[shader][LoD].size(), 
                      "ShaderProgram error: Invalid function index specified for update!");
        if(_availableFunctionIndex[shader].empty()) return;

        DIVIDE_ASSERT(functionEntry < _availableFunctionIndex[shader].size(), 
                      "ShaderProgram error: Specified function entry does not exist!");
        _functionIndex[shader][LoD][index] = _availableFunctionIndex[shader][functionEntry];
    }

    inline U32 addFunctionIndex(ShaderType type, U32 index){
        _availableFunctionIndex[type].push_back(index);
        return U32(_availableFunctionIndex[type].size() - 1);
    }
    /** ------ END EXPERIMENTAL CODE ----- **/

protected:
    friend class ShaderManager;
    /// Calling refreshSceneData will force an update on scene specific shader uniforms
    inline void refreshSceneData()  { _sceneDataDirty = true; }
    /// Calling refreshShaderData will force an update on default shader uniforms
    inline void refreshShaderData() { _dirty = true;}
    I32 operator==(const ShaderProgram &_v) { return this->getGUID() == _v.getGUID(); }
    I32 operator!=(const ShaderProgram &_v) { return !(*this == _v); }

protected:

    ShaderProgram(const bool optimise = false);

    virtual I32 cachedLoc(const stringImpl& name, const bool uniform = true) = 0;
    template<typename T>
    friend class ImplResourceLoader;
    virtual bool generateHWResource(const stringImpl& name);
    void updateMatrices();
    const vectorImpl<U32>& getAvailableFunctions(ShaderType type) const;

protected:
    bool _refreshStage[ShaderType_PLACEHOLDER];
    bool _optimise;
    bool _dirty;
    std::atomic_bool _bound;
    std::atomic_bool _linked;
    U32 _shaderProgramId; //<not thread-safe. Make sure assignment is protected with a mutex or something
    U64 _elapsedTime;
    F32 _elapsedTimeMS;
    U8  _outputCount;
    ///A list of preprocessor defines
    vectorImpl<stringImpl > _definesList;
    ///A list of custom shader uniforms
    vectorImpl<stringImpl > _customUniforms[ShaderType_PLACEHOLDER];
    ///ID<->shaders pair
    typedef hashMapImpl<U32, Shader* > ShaderIdMap;
    ShaderIdMap _shaderIdMap;

private:
    bool _sceneDataDirty;
    ///Various uniform/attribute locations
    I32 _timeLoc;
    I32 _enableFogLoc;
    I32 _lightAmbientLoc;
    I32 _invScreenDimension;
    I32 _fogColorLoc;
    I32 _fogDensityLoc;

    vectorImpl<U32> _functionIndex[ShaderType_PLACEHOLDER][Config::SCENE_NODE_LOD];
    vectorImpl<U32> _availableFunctionIndex[ShaderType_PLACEHOLDER];
};

}; //namespace Divide
#endif

Commits for Divide-Framework/trunk/Source Code/Hardware/Video/Shaders/Headers/ShaderProgram.h

Diff revisions: vs.
Revision Author Commited Message
331 Diff Diff IonutCava picture IonutCava Sat 06 Dec, 2014 20:53:45 +0000

[Ionut]
- Limited line length to 132 characters to improve readability and diff-comparisons
- Refactored memory allocation/deallocation functions
- Fixed a few compatibility issues with HashMap.h
- Fixed a bug in GPU Skinning shaders (cast a float to int)

328 Diff Diff IonutCava picture IonutCava Sat 04 Oct, 2014 18:03:36 +0000

[Ionut]
- Added per SceneGraphNode material instances. (Cloned from the SceneNode’s material)
- Improved shader loading for materials

322 Diff Diff IonutCava picture IonutCava Sat 06 Sep, 2014 20:33:47 +0000

[Ionut]
- Refactored most of Boost related code to be C++11 based
— Boost is only used for ThreadPool, Mutex handling, XML parsing and networking (ASIO)
— Function binds, threads, regex, NonCopyable base, Hashing algorithms and more are now using C++11 libraries
- Replaced all FOR_EACH calls with standard, range, “for” calls

321 Diff Diff IonutCava picture IonutCava Wed 03 Sep, 2014 22:05:15 +0000

[Ionut]
- Added support (and enabled by default) for the EASTL library (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2271.html / https://github.com/paulhodge/EASTL)
— Strings, vectors and hash_maps can be combined from EASTL, STL and Boost (not all combinations work. e.g. EASTL strings with STL/Boost containers due to the lack of a proper hash function)

318 Diff Diff IonutCava picture IonutCava Sat 30 Aug, 2014 17:35:53 +0000

[Ionut]
- Wrapped the entire code in a “Divide” namespace
- VertexBuffers now call “shrink_to_fit” on all internal data storage
- Improved some vector performance by preferring “emplace_back” instead of “push_back” + proepr usage of reserve / resize
- Wrapped OIS specific types and classes in Divide::Input namespace
- Added the messageBox.layout file (forgot it in the previous few commits)

301 Diff Diff IonutCava picture IonutCava Tue 05 Aug, 2014 20:55:30 +0000

[Ionut]
- Code cleanups and comments (ShaderManager, ShaderProgram, Texture)
- Fixed some singleton destruction order between ResourceCache and ShaderManager to properly unload remaining shader programs

296 Diff Diff k1ngp1n picture k1ngp1n Sun 03 Aug, 2014 14:54:21 +0000

[Ionut]
- nVidia compatibility fixes (GUI, shadows, post-processing)
- Texture bind slots are now part of ShaderProgram class
- Renamed ForwardRenderer class to ForwardPlusRenderer and moved ligh grid creation to it
- More code cleanups and comments

295 Diff Diff k1ngp1n picture k1ngp1n Fri 01 Aug, 2014 20:10:44 +0000

[Ionut]
- If a shader fails to bind, skip draw call. A shader will fail to bind if it wasn’t linked properly, as well
- Moved ShaderManager to the Hardware project due to its tight coupling
- More code cleanup and comments:
— OpenGL wrapper code : GLWrapper.h, GLWrapper.cpp, GLStates.cpp, glShaderProgram.cpp
- Cleaned up Shader.cpp
- Binary shader dump also saves binary format in .fmt file for each binary shader
- Renamed immediate mode primitive files

293 Diff Diff k1ngp1n picture k1ngp1n Tue 29 Jul, 2014 20:01:28 +0000

[Ionut]
- Code cleanup and comments in GLFWWrapper (for starters. more to follow)
- Reworked main loop logic (no more delegates and rendering api querying)
- Replaced all GLvoid with regular void
- replaced all boost::this_thread::sleep (deprecated calls) with boost::this_thread::sleep_for

287 IonutCava picture IonutCava Tue 22 Jul, 2014 16:11:05 +0000

[Ionut]
- Unified matrix transforms and node info and made it a vertex-shader only buffer
- World matrix queries have to be issued from the SceneGraphNode instead of the SGN’s Transform class to allow future interpolation algorithms to be more easily implemented
- Moved all lighting calculations per pixel to save varying and register space (caused compilation issues both on nVidia and AMD)
- Stored GPU buffer info (view, projection, viewport etc) into a special struct to avoid multiple redundant buffer uploads and to remove redundant client side matrix caches
- Some work on shader buffer locking system
- Cleaned up MathClasses.h and Transform.h
- Updated ASSIMP to 3.1.1