microsoft / DirectXTK

The DirectX Tool Kit (aka DirectXTK) is a collection of helper classes for writing DirectX 11.x code in C++

Home Page:https://walbourn.github.io/directxtk/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Question: Black Textures WIC Loader

aaronstackpole opened this issue · comments

I've got a problem with my code where the textures that I load with WIC texture loader are rendering in black. The transparency part is working, and I can adjust the alpha from 0 to 1, but the display of the texture is all black. This is PROBABLY not a problem specifically with DirectX Toolkit, but the way that I'm using it, so I'm wondering if you have any ideas on where I should look in my code to ensure I'm using the COM pointers correctly, for example. Is there a way to see the contents of a texture pointer in debugger, for example, to see what data is being loaded by the WIC texture loader function? That is to say I've not figured out how to debug resources that are allocated on the GPU, maybe I just need to learn a new tool? Note it was working in an earlier version of my own code, I did some restructuring to how I'm loading textures, obviously the issue is in that area, I'm just not really sure of a good strategy to debug the issue is really my main concern.

One quick test is to programmatically create a single-color texture and use that to verify your rendering works.

static const uint32_t s_pixel = 0xffffffff;

D3D11_SUBRESOURCE_DATA initData = { &s_pixel, sizeof(uint32_t), 0 };

D3D11_TEXTURE2D_DESC desc = {};
desc.Width = desc.Height = desc.MipLevels = desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_IMMUTABLE;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;

ComPtr<ID3D11Texture2D> tex;
HRESULT hr = mDevice->CreateTexture2D(&desc, &initData, tex.GetAddressOf());

-or- using the DirectX Tool Kit BufferHelpers header:

const uint32_t s_pixel = 0xffffffff;

D3D11_SUBRESOURCE_DATA initData = { &s_pixel, sizeof(uint32_t), 0 };

ComPtr<ID3D11ShaderResourceView> defaultTex;
DX::ThrowIfFailed(
    CreateTextureFromMemory(device, 1u, 1u, DXGI_FORMAT_R8G8B8A8_UNORM, initData,
        nullptr, &defaultTex)
    );

The code above creates a white texture, but you'll want to use some other values for the pixel.

As for debugging tools, for DirectX 11 the Visual Studio Graphics Debugging is probably your best option.

Great tips, thanks Chuck. Programmatic texture will be a good test. It's bizarre. I'm instantiating the shader resource view objects into a map with emplace so that I can easily get pointers to them for various scene elements, and the really odd thing is it was working in the past, I literally have video recording of it with colors and then after some changes it stopped working. I rolled back my code to an earlier change set that I thought was working and it was still black, so maybe I'm just going crazy. LOL Thanks!

https://pastebin.com/xfBKwQV5 Here's a pastebin of my Textures system, probably just as easy for you to see if you think there's anything particularly wrong with it, it's just a couple functions. I've got a class that reads texture names out of a JSON DOM and calls AddTexture as part of the startup routine for the application, so it happens basically just after I've created the DX11 factory and basic resources (device/context). After that a scene manager starts up and reads a different JSON that starts to populate the sprite class elements which pull their texture pointers from the above class.

There's nothing about that code that looks 'wrong', but I suspect it has much more to do with the rendering than the loading.

Finally got around to looking at this deeper and there was one significant change I made to the rendering system from the base code, in particular, instead of passing a pointer to the SpriteBatch during the call to Draw, the object retains its own pointer to the SpriteBatch. I still perform the normal Clear Start and Stop commands on the SpriteBatch, but I let the callbacks to each of the Sprite objects themselves draw to their cached pointer. Do you think this might be problematic?

The old_draw_callbacks collection used the original implementation of passing the pointer. I don't think it actually has any objects in it at this iteration of the code, it's just orphaned at this point.

rs->Clear();
draw_mutex.lock();
rs->GetSpriteBatch()->Begin();
std::for_each(draw_callbacks.begin(), draw_callbacks.end(), [&](DrawCallback element) { element(); });
std::for_each(old_draw_callbacks.begin(), old_draw_callbacks.end(), [&](OldDrawCallback element) { element(rs->GetSpriteBatch()); });
rs->GetSpriteBatch()->End();
draw_mutex.unlock();
rs->Present();