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
#include "Headers/ShaderProgram.h"

#include "Managers/Headers/LightManager.h"
#include "Managers/Headers/SceneManager.h"
#include "core/Headers/Kernel.h"
#include "Core/Headers/ParamHandler.h"
#include "Core/Headers/Application.h"
#include "Geometry/Material/Headers/Material.h"
#include "Rendering/Lighting/ShadowMapping/Headers/ShadowMap.h"
#include "Hardware/Video/Headers/GFXDevice.h"
#include "Hardware/Video/Shaders/Headers/ShaderManager.h"

namespace Divide {

ShaderProgram::ShaderProgram(const bool optimise) : HardwareResource("temp_shader_program"),
                                                    _optimise(optimise),
                                                    _dirty(true),
                                                    _outputCount(0),
                                                    _elapsedTime(0ULL),
                                                    _elapsedTimeMS(0.0f)
{
	_bound = false;
	_linked = false;
    // Override in concrete implementations with appropriate invalid values
    _shaderProgramId = 0;
    // Start with clean refresh flags
    memset(_refreshStage, false, ShaderType_PLACEHOLDER * sizeof(bool));
    // Cache some frequently updated uniform locations
    _sceneDataDirty = true;
    _timeLoc            = -1;
    _enableFogLoc       = -1;
    _lightAmbientLoc    = -1;
    _invScreenDimension = -1;
    _fogColorLoc        = -1;
    _fogDensityLoc      = -1;
}

ShaderProgram::~ShaderProgram()
{
    D_PRINT_FN(Locale::get("SHADER_PROGRAM_REMOVE"), getName().c_str());
    // Remove every shader attached to this program
	for (ShaderIdMap::value_type& it : _shaderIdMap) {
        ShaderManager::getInstance().removeShader( it.second );
    }
    // Unregister the program from the manager
    ShaderManager::getInstance().unregisterShaderProgram(getName());
    _shaderIdMap.clear();
}

/// Called once per frame. Update common values used across programs
bool ShaderProgram::update(const U64 deltaTime) {
    ParamHandler& par = ParamHandler::getInstance();
    LightManager& lightMgr = LightManager::getInstance();

    // Update internal timers
    _elapsedTime += deltaTime;
    _elapsedTimeMS = static_cast<F32>(getUsToMs(_elapsedTime));
    // Skip programs that aren't fully loaded
    if (!isHWInitComplete()) {
        return false;
    }
    // Toggle fog on or off
    bool enableFog = par.getParam<bool>("rendering.enableFog");
#   ifdef _DEBUG
        // Shadow splits are only visible in debug builds
        this->Uniform("dvd_showShadowSplits", par.getParam<bool>("rendering.debug.showSplits"));
#   endif
    // Time, fog, ambient light
    this->Uniform(_timeLoc, _elapsedTimeMS);
    this->Uniform(_enableFogLoc, enableFog);
    this->Uniform(_lightAmbientLoc, lightMgr.getAmbientLight());
    // Scene specific data is updated only if it changed
    if (_sceneDataDirty) {
        // Check and update fog properties
        if (enableFog) {
            this->Uniform(_fogColorLoc, vec3<F32>(par.getParam<F32>("rendering.sceneState.fogColor.r"),
                                                  par.getParam<F32>("rendering.sceneState.fogColor.g"),
                                                  par.getParam<F32>("rendering.sceneState.fogColor.b")));
            this->Uniform(_fogDensityLoc, par.getParam<F32>("rendering.sceneState.fogDensity"));
        }
        // Upload wind data
        Scene* activeScene = GET_ACTIVE_SCENE();
        this->Uniform("windDirection", vec2<F32>(activeScene->state().getWindDirX(), activeScene->state().getWindDirZ()));
        this->Uniform("windSpeed", activeScene->state().getWindSpeed());
        _sceneDataDirty = false;
    }
    // The following values are updated only if a call to the ShaderManager's refresh() function is made
    if (_dirty) {
        // Inverse screen resolution
        const vec2<U16>& screenRes = GFX_DEVICE.getRenderTarget(GFXDevice::RENDER_TARGET_SCREEN)->getResolution();
        this->Uniform(_invScreenDimension, vec2<F32>(1.0f / screenRes.width, 1.0f / screenRes.height));
        // Shadow mapping specific values
        this->Uniform("dvd_lightBleedBias", 0.0000002f);
        this->Uniform("dvd_minShadowVariance", 0.0002f);
        this->Uniform("dvd_shadowMaxDist", 250.0f);
        this->Uniform("dvd_shadowFadeDist",150.0f);
        _dirty = false;
    }

    return true;
}

/// Rendering API specific loading (called after the API specific derived calls processed the request)
bool ShaderProgram::generateHWResource(const stringImpl& name) {
    _name = name;

    if (!HardwareResource::generateHWResource(name)) {
        return false;
    }
    // Finish threaded loading
    HardwareResource::threadedLoad(name);
    // Validate loading state
    DIVIDE_ASSERT(isHWInitComplete(), "ShaderProgram error: hardware initialization failed!");
    // Get the location for our frequently used uniforms
    if (_linked) {
        _timeLoc             = this->cachedLoc("dvd_time");
        _enableFogLoc        = this->cachedLoc("dvd_enableFog");
        _lightAmbientLoc     = this->cachedLoc("dvd_lightAmbient");
        _invScreenDimension  = this->cachedLoc("dvd_invScreenDimension");
        _fogColorLoc         = this->cachedLoc("fogColor");
        _fogDensityLoc       = this->cachedLoc("fogDensity");
    }
    // Make sure the first call to update processes all of the needed data
    _dirty = _sceneDataDirty = true;

    return true;
}

/// Mark the shader as bound
bool ShaderProgram::bind() {
    _bound = true;
    return _shaderProgramId != 0;
}

/// Mark the shader as unbound
void ShaderProgram::unbind(bool resetActiveProgram) {
    _bound = false;
}

/// Add a define to the shader. The defined must not have been added previously
void ShaderProgram::addShaderDefine(const stringImpl& define) {
    // Find the string in the list of program defines
    vectorImpl<stringImpl >::iterator it = find(_definesList.begin(), _definesList.end(), define);
    // If we can't find it, we add it
    if (it == _definesList.end()) {
        _definesList.push_back(define);
    } else {
        // If we did find it, we'll show an error message in debug builds about double add
        D_ERROR_FN(Locale::get("ERROR_INVALID_SHADER_DEFINE_ADD"), define.c_str(), getName().c_str());
    }
    
}

/// Remove a define from the shader. The defined must have been added previously
void ShaderProgram::removeShaderDefine(const stringImpl& define) {
    // Find the string in the list of program defines
    vectorImpl<stringImpl >::iterator it = find(_definesList.begin(), _definesList.end(), define);
    // If we find it, we remove it
    if (it != _definesList.end()) {
        _definesList.erase(it);
    } else {
        // If we did not find it, we'll show an error message in debug builds
        D_ERROR_FN(Locale::get("ERROR_INVALID_SHADER_DEFINE_DELETE"),define.c_str(),getName().c_str());
    }
}

void ShaderProgram::addShaderUniform(const stringImpl& uniform, const ShaderType& type) {
    // Find the string in the list of uniforms
    vectorImpl<stringImpl >::iterator it = find(_customUniforms[type].begin(), _customUniforms[type].end(), uniform);
    // If we can't find it, we add it
    if (it == _definesList.end()) {
        _customUniforms[type].push_back(uniform);
    } else {
        // If we did find it, we'll show an error message in debug builds about double add
        D_ERROR_FN(Locale::get("ERROR_INVALID_SHADER_UNIFORM_ADD"), uniform.c_str(), (U32)type, getName().c_str());
    }
}

/// Remove an uniform from the shader. The uniform must have been added previously for the specified shader type
void ShaderProgram::removeUniform(const stringImpl& uniform, const ShaderType& type) {
    // Find the string in the list of uniforms
    vectorImpl<stringImpl >::iterator it = find(_customUniforms[type].begin(), _customUniforms[type].end(), uniform);
    // If we find it, we remove it
    if (it != _customUniforms[type].end()) {
        _customUniforms[type].erase(it);
    } else {
        // If we did find it, we'll show an error message in debug builds about double add
        D_ERROR_FN(Locale::get("ERROR_INVALID_SHADER_UNIFORM_DELETE"), uniform.c_str(), (U32)type , getName().c_str());
    }
}

/// Rebuild the specified shader stages from source code
void ShaderProgram::recompile(const bool vertex, 
                              const bool fragment, 
                              const bool geometry, 
                              const bool tessellation, 
                              const bool compute) {
    _linked = false;
    // Remember bind state
    bool wasBound = _bound;
    if (wasBound) {
        unbind();
    }
    // Update refresh flags
    _refreshStage[VERTEX_SHADER] = vertex;
    _refreshStage[FRAGMENT_SHADER] = fragment;
    _refreshStage[GEOMETRY_SHADER] = geometry;
    _refreshStage[TESSELATION_CTRL_SHADER] = tessellation;
    _refreshStage[TESSELATION_EVAL_SHADER] = tessellation;
    _refreshStage[COMPUTE_SHADER] = compute;
    // Recreate all of the needed shaders
    generateHWResource(getName());
    // Restore bind state
    if (wasBound) {
        bind();
    }
}

};

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

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)

326 Diff Diff IonutCava picture IonutCava Tue 30 Sep, 2014 21:11:32 +0000

[Ionut]
- Fixed more memory leaks
- Simplified Task interface and timing System
- Improved compatibility between Boost, STL and EASTL with random combinations of vectors, strings and maps
- Simplified Light class by removing the “slot” member
- Random optimizations

325 Diff Diff IonutCava picture IonutCava Wed 17 Sep, 2014 20:06:13 +0000

[Ionut]
- Reworked transform system:
— Parent transform chain system moved from Transform class to the PhysicsComponent
— PhysicsComponent now returns all transform values needed both global and local (still needs heavy optimization and caching)

- Reworked SceneGraph node management:
— Proper ref counting of SceneNodes and proper removing of resource (ResourceCache is now empty on destruction, as it should be)
— Removed parent transform tracking as that’s the PhysicsComponent’s responsibility
— Only nodes loaded via the ResourceCache are allowed to be added to the SceneGraph (added proper loaders for Impostors, Sky, etc)

- Optimized some of the math classes (mat4, mat3)

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 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