Advertisement

WICTextureLoader sometimes fails

Started by March 31, 2019 12:04 PM
3 comments, last by MJP 5 years, 10 months ago

Hello, a week ago I started writing code for a game engine. Currently I am struggling to create textures using DirectXTK's WicTextureLoader.

The WICTextureLoader works about 50% of the time on Release the release build with CPU optimization and the ID3D11Device is not created with a debug flag. On Debug the texture loading always fails. Here is the code attempting to load textures:

    // Convert std::string to const wchar_t*
    const wchar_t* convertedFilePath = std::wstring(filePath.begin(), filePath.end()).c_str();
 
    // Load the texture
    ID3D11ShaderResourceView* srv = nullptr;
 
    HRESULT hr = DirectX::CreateWICTextureFromFile(TextureLoader::device, convertedFilePath, nullptr, &srv);
 
    if (FAILED(hr)) {
        Logger::LOG_WARNING("Failed to load texture: [%s]", filePath.c_str());
 
        return nullptr;
    } else {
        Logger::LOG_INFO("Loaded texture: [%s]", filePath.c_str());
        textures[filePath] = srv;
 
        return srv;
    }

Some more information:

  • The swap chain and device seem to be created just fine
  • The application is running in x64 mode
  • CoInitializeEx is called before attempting to load the texture
  • Linked libraries: assimp-vc140-mt.lib, d3d11.lib, runtimeobject.lib
  • The application's window is 'frozen'; it can't be dragged around and when the cursor hovers over it, the 'loading' cursor icon is shown

I would be very grateful if someone was able to help me. Let me know if any useful information is lacking.

Cheers!

What is the HRESULT value you're getting when it fails?

 

Do you have the debug layer enabled when you create the device/swapchain? Do you get any error messages in the output window regarding the failure?

Advertisement

I completely forgot HRESULT is more than a boolean. The value said 'the file could not be found'. Apparently the single-line conversion I do here:

const wchar_t* convertedFilePath = std::wstring(filePath.begin(), filePath.end()).c_str();

doesn't work, but this does:

std::wstring wString(filePath.begin(), filePath.end());
 
const wchar_t* convertedFilePath = wString.c_str();

Thanks a lot pindrought, you helped me solve it with just a question.

 

At some point I actually checked if it was the file path by hardcoding, but at that point there were also other issues causing the failure (the ID3D11Device was not properly set up or something). Also the fact that the conversion did occasionally work on the Release config didn't help make things clearer in my head.

The problem with your one-line version is that pointer returned to by c_str() is only valid while the string object itself is valid. This is because many implementations of std::string will allocate memory internally to store the characters, and c_str() will return a pointer to that internal data. When the destructor runs that memory will be freed, and the pointer returned by c_str() will now point to garbage data. Since you're calling c_str() on an rvalue (temporary) in your one-line version, the wstring is constructed and then immediately destructed by the time the next line of code executes. This is basically the same issue that you get when you take the address of a temporary.

Your second version should work OK, as long as your "wString" variable lives long enough for you to call CreateWICTextureFromFile.

This topic is closed to new replies.

Advertisement