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
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
#include "Headers/Texture.h"

#include "Core/Headers/Console.h"
#include "Core/Headers/TaskPool.h"
#include "Core/Headers/StringHelper.h"
#include "Utility/Headers/Localization.h"
#include "Platform/Video/Headers/GFXDevice.h"

namespace Divide {

namespace {
    static const U16 g_partitionSize = 128;
};

const char* Texture::s_missingTextureFileName = nullptr;

Texture::Texture(GFXDevice& context,
                 const stringImpl& name,
                 const stringImpl& resourceName,
                 const stringImpl& resourceLocation,
                 TextureType type,
                 bool asyncLoad)
    : Resource(ResourceType::GPU_OBJECT, name, resourceName, resourceLocation),
      GraphicsResource(context, getGUID()),
      _numLayers(1),
      _lockMipMaps(false),
      _samplerDirty(true),
      _mipMapsDirty(true),
      _hasTransparency(false),
      _asyncLoad(asyncLoad)
{
    _width = _height = 0;
    _mipMaxLevel = _mipMinLevel = 0;
    _textureData._textureType = type;
    _textureData._samplerHash = _descriptor._samplerDescriptor.getHash();
}

Texture::~Texture()
{
}

bool Texture::load() {
    _context.loadInContext(_asyncLoad ? CurrentContext::GFX_LOADING_CTX
                                      : CurrentContext::GFX_RENDERING_CTX,
        [&](const Task& parent) {
            threadedLoad();
            Resource::load();
        }
    );

    return true;
}

/// Load texture data using the specified file name
void Texture::threadedLoad() {
    TextureLoadInfo info;
    info._type = _textureData._textureType;

    // Each texture face/layer must be in a comma separated list
    stringstreamImpl textureLocationList(getResourceLocation());
    stringstreamImpl textureFileList(getResourceName());

    // We loop over every texture in the above list and store it in this
    // temporary string
    stringImpl currentTextureFile;
    stringImpl currentTextureLocation;
    stringImpl currentTextureFullPath;
    while (std::getline(textureLocationList, currentTextureLocation, ',') &&
           std::getline(textureFileList, currentTextureFile, ','))
    {
        Util::Trim(currentTextureFile);
        // Skip invalid entries
        if (!currentTextureFile.empty()) {
            currentTextureFullPath = (currentTextureLocation.empty() ? Paths::g_texturesLocation
                                                                     : currentTextureLocation) +
                                     "/" +
                                     currentTextureFile;

                // Attempt to load the current entry
                if (!loadFile(info, currentTextureFullPath)) {
                    // Invalid texture files are not handled yet, so stop loading
                    return;
                }
                info._layerIndex++;
                if (info._type == TextureType::TEXTURE_CUBE_ARRAY) {
                    if (info._layerIndex == 6) {
                        info._layerIndex = 0;
                        info._cubeMapCount++;
                    }
                }
        }
    }

    if (info._type == TextureType::TEXTURE_CUBE_MAP ||
        info._type == TextureType::TEXTURE_CUBE_ARRAY) {
        if (info._layerIndex != 6) {
            Console::errorfn(
                Locale::get(_ID("ERROR_TEXTURE_LOADER_CUBMAP_INIT_COUNT")),
                getResourceLocation().c_str());
            return;
        }
    }

    if (info._type == TextureType::TEXTURE_2D_ARRAY ||
        info._type == TextureType::TEXTURE_2D_ARRAY_MS) {
        if (info._layerIndex != _numLayers) {
            Console::errorfn(
                Locale::get(_ID("ERROR_TEXTURE_LOADER_ARRAY_INIT_COUNT")),
                getResourceLocation().c_str());
            return;
        }
    }

    if (info._type == TextureType::TEXTURE_CUBE_ARRAY) {
        if (info._cubeMapCount != _numLayers) {
            Console::errorfn(
                Locale::get(_ID("ERROR_TEXTURE_LOADER_ARRAY_INIT_COUNT")),
                getResourceLocation().c_str());
            return;
        }
    }
}

bool Texture::loadFile(const TextureLoadInfo& info, const stringImpl& name) {
    // Create a new imageData object
    ImageTools::ImageData img;
    // Flip image if needed
    img.flip(true);
    // Save file contents in  the "img" object
    ImageTools::ImageDataInterface::CreateImageData(name, img);

    // Validate data
    if (!img.data()) {
        if (info._layerIndex > 0) {
            Console::errorfn(Locale::get(_ID("ERROR_TEXTURE_LAYER_LOAD")), name.c_str());
            return false;
        }
        Console::errorfn(Locale::get(_ID("ERROR_TEXTURE_LOAD")), name.c_str());
        // Missing texture fallback.
        img.flip(false);
        // missing_texture.jpg must be something that really stands out
        ImageTools::ImageDataInterface::CreateImageData(Paths::g_assetsLocation + Paths::g_texturesLocation + s_missingTextureFileName, img);

    }
    
    // Extract width, height and bitdepth
    U16 width = img.dimensions().width;
    U16 height = img.dimensions().height;
    // If we have an alpha channel, we must check for translucency
    if (img.alpha()) {

        // Each pixel is independent so this is a brilliant place to parallelize work
        // should this be atomic? At most, we run an extra task -Ionut
        std::atomic_bool abort = false;

        auto findAlpha = [&abort, &img, height](const Task& parent, U32 start, U32 end) {
            U8 tempR, tempG, tempB, tempA;
            for (U32 i = start; i < end; ++i) {
                for (I32 j = 0; j < height; ++j) {
                    if (!abort) {
                        img.getColour(i, j, tempR, tempG, tempB, tempA);
                        if (tempA < 250) {
                            abort = true;
                        }
                    }
                }
                if (parent.stopRequested()) {
                    break;
                }
            }
        };

        parallel_for(findAlpha, width, g_partitionSize);

        _hasTransparency = abort;
    }

    Console::d_printfn(Locale::get(_ID("TEXTURE_HAS_TRANSPARENCY")),
                       name.c_str(),
                       _hasTransparency ? "yes" : "no");

    // Create a new Rendering API-dependent texture object
    _descriptor._type = info._type;
    _descriptor._internalFormat = GFXImageFormat::RGB8;
    // Select the proper colour space internal format
    bool srgb = _descriptor._samplerDescriptor.srgb();
    // We only support 8 bit per pixel, 1/2/3/4 channel textures
    switch (img.format()) {
        case GFXImageFormat::LUMINANCE:
            _descriptor._internalFormat = GFXImageFormat::LUMINANCE;
            break;
        case GFXImageFormat::RED:
            _descriptor._internalFormat = GFXImageFormat::RED8;
            break;
        case GFXImageFormat::RG:
            _descriptor._internalFormat = GFXImageFormat::RG8;
            break;
        case GFXImageFormat::BGR:
        case GFXImageFormat::RGB:
            _descriptor._internalFormat =
                srgb ? GFXImageFormat::SRGB8 : 
                       GFXImageFormat::RGB8;
            break;
        case GFXImageFormat::BGRA:
        case GFXImageFormat::RGBA:
            _descriptor._internalFormat =
                srgb ? GFXImageFormat::SRGBA8 : 
                       GFXImageFormat::RGBA8;
            break;
        case GFXImageFormat::COMPRESSED_RGB_DXT1: {
            _descriptor._internalFormat = 
                srgb ? GFXImageFormat::COMPRESSED_SRGB_DXT1 :
                       GFXImageFormat::COMPRESSED_RGB_DXT1;
            _descriptor._compressed = true;
        } break;
        case GFXImageFormat::COMPRESSED_RGBA_DXT1: {
            _descriptor._internalFormat =
                srgb ? GFXImageFormat::COMPRESSED_SRGB_ALPHA_DXT1 :
                       GFXImageFormat::COMPRESSED_RGBA_DXT1;
            _descriptor._compressed = true;
        } break;
        case GFXImageFormat::COMPRESSED_RGBA_DXT3: {
            _descriptor._internalFormat =
                srgb ? GFXImageFormat::COMPRESSED_SRGB_ALPHA_DXT3 :
                       GFXImageFormat::COMPRESSED_RGBA_DXT3;
            _descriptor._compressed = true;
        } break;
        case GFXImageFormat::COMPRESSED_RGBA_DXT5: {
            _descriptor._internalFormat =
                srgb ? GFXImageFormat::COMPRESSED_SRGB_ALPHA_DXT5 :
                       GFXImageFormat::COMPRESSED_RGBA_DXT5;
            _descriptor._compressed = true;
        } break;
    }

    U16 mipMaxLevel = to_ushort(img.mipCount());
    
    if (!_descriptor._compressed) {
        if (_descriptor._samplerDescriptor.generateMipMaps()) {
            if (mipMaxLevel <= 1) {
                mipMaxLevel = computeMipCount(width, height);
            }

            mipMaxLevel += 1;
        }
    }
    // Uploading to the GPU dependents on the rendering API
    loadData(info,
             _descriptor,
             img.imageLayers(),
             vec2<U16>(0, mipMaxLevel));

    // We will always return true because we load the "missing_texture.jpg" in case of errors
    return true;
}

U16 Texture::computeMipCount(U16 width, U16 height) {
    return to_ushort(std::floorf(std::log2f(std::fmaxf(to_float(width), to_float(height)))));
}
};

Commits for Divide-Framework/trunk/Source Code/Platform/Video/Textures/Texture.cpp

Diff revisions: vs.
Revision Author Commited Message
832 Diff Diff IonutCava picture IonutCava Thu 26 Jan, 2017 17:23:11 +0000

[IonutCava]
- More path related work
- Initial code to centralize file I/O (does not compile yet)

831 Diff Diff IonutCava picture IonutCava Wed 25 Jan, 2017 23:52:34 +0000

[IonutCava]
- More path related updates

829 Diff Diff IonutCava picture IonutCava Tue 24 Jan, 2017 17:28:39 +0000

[IonutCava]
- Separate resourceLocation for resources into resourceLocation and resourceName.
- More XML config loading refactoring

811 Diff Diff IonutCava picture IonutCava Wed 11 Jan, 2017 17:26:49 +0000

[IonutCava]
- Fix some threadpool cleanup bugs
- Fix terrain rendering (except underwater caustics)
- Fix terrain loading
- Fix terrain unloading

807 Diff Diff IonutCava picture IonutCava Mon 09 Jan, 2017 17:06:26 +0000

[IonutCava]
- Split PlatformDefines.h into 2. Move data type defines to PlatformDataTypes.h
- Continue to improve velocity map calculation
- Remove “destroy()” calls from most classes. Attempt to move as many classes to the RAII system.

806 Diff Diff IonutCava picture IonutCava Sun 08 Jan, 2017 22:00:48 +0000

[IonutCava]
- Finish implementing per-fragment velocity computation using a compute shader
— Further tuning still needed
- Add VS2017 build targets

796 Diff Diff IonutCava picture IonutCava Wed 23 Nov, 2016 20:04:11 +0000

[IonutCava]
- Fix a bad if statement in the RenderingComponent class relating additional texture dependencies that prevented non-Debug builds from using additional textures
- Fix a race condition relating to texture loading
- Small code cleanup

795 Diff Diff IonutCava picture IonutCava Wed 23 Nov, 2016 17:14:33 +0000

[IonutCava]
- Remove ULL. Use U64 instead
- Various small bug fixes and typos.

788 Diff Diff IonutCava picture IonutCava Fri 21 Oct, 2016 16:11:37 +0000

[IonutCava]
- Added support for the Arena Allocator by Mamasha Knows (http://www.codeproject.com/Articles/44850/Arena-Allocator-DTOR-and-Embedded-Preallocated-Buf)
— Used for GFX Related objects: Textures, shaders, etc

759 IonutCava picture IonutCava Sun 07 Aug, 2016 18:34:32 +0000

[IonutCava]
- Add workaround for singlethreaded texture loading
- Small corrections to ImageTools image loading