D3D11RenderTexture::getCustomAttribute missing?

Problems building or running the engine, queries about how to use features etc.
User avatar
Arthurfernandes
Gnoblar
Posts: 19
Joined: Mon Oct 28, 2024 10:50 pm
x 1

D3D11RenderTexture::getCustomAttribute missing?

Post by Arthurfernandes »

Ogre Version: 14.3.1
Operating System: Windows
Render System: DirectX 11

Hey everyone!

I have a post here discussing the integration of Ogre with WPF, specifically using D3DImage. After successfully initializing Ogre inside D3DImage with DirectX 9, I am now attempting to do the same with DirectX 11.

There are some challenges: the first is that D3DImage does not work directly with DirectX 11. I am currently researching potential solutions. Another issue I encountered is that the DirectX 11 render system in Ogre does not have a getCustomAttribute method for RenderTexture. Every time I tried to use a custom attribute, it would fail with the same generic error:

Code: Select all

Attribute not found. " + name, " RenderTarget::getCustomAttribute"

To address this, I made manual changes to the source code, specifically in the OgreD3D11Texture.cpp class:

Code: Select all

void D3D11RenderTexture::getCustomAttribute(const String& name, void* pData)
{
    if (name == "D3DDEVICE")
    {
        *(ID3D11DeviceN**)pData = mDevice.get();
    }
    else
    {
        D3D11RenderTexture::getCustomAttribute(name, pData);
    }
}

And in OgreD3D11Texture.h:

Code: Select all

void getCustomAttribute(const String& name, void* pData);

I'm not sure if this is the correct approach, but now, when I execute the following code:

Code: Select all

renderTarget.getCustomAttribute("D3DDEVICE", out surface);

I can successfully obtain a pointer, unlike before.

paroj
OGRE Team Member
OGRE Team Member
Posts: 2106
Joined: Sun Mar 30, 2014 2:51 pm
x 1132

Re: D3D11RenderTexture::getCustomAttribute missing?

Post by paroj »

yes, this is the correct approach

User avatar
Arthurfernandes
Gnoblar
Posts: 19
Joined: Mon Oct 28, 2024 10:50 pm
x 1

Re: D3D11RenderTexture::getCustomAttribute missing?

Post by Arthurfernandes »

So, theoretically, I created a method in OgreD3D11Texture.cpp that gives me a shared handle which I can use in Microsoft.Wpf.Interop.Directx.D3D11Image.

Code: Select all

void D3D11Texture::_createShared2DTex()
{
    assert(mSrcWidth > 0 || mSrcHeight > 0);

UINT numMips = (mNumMipmaps == MIP_UNLIMITED || (1U << mNumMipmaps) > std::max(mSrcWidth, mSrcHeight))
                   ? 0
                   : mNumMipmaps + 1;
if (D3D11Mappings::_isBinaryCompressedFormat(mD3DFormat) && numMips > 1)
    numMips = std::max(1U, numMips - 2);

D3D11_TEXTURE2D_DESC desc;
desc.Width = static_cast<UINT>(mSrcWidth);
desc.Height = static_cast<UINT>(mSrcHeight);
desc.MipLevels = numMips;
desc.ArraySize = mDepth == 0 ? 1 : mDepth;
desc.Format = mD3DFormat;
desc.SampleDesc = mFSAAType;
desc.Usage = D3D11Mappings::_getUsage(_getTextureUsage());
desc.BindFlags = D3D11Mappings::_getTextureBindFlags(mD3DFormat, _getTextureUsage());
desc.CPUAccessFlags = D3D11Mappings::_getAccessFlags(_getTextureUsage());
desc.MiscFlags = D3D11Mappings::_getTextureMiscFlags(desc.BindFlags, getTextureType(), _getTextureUsage());

// Ensure that the texture is shared
desc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED;

if (PixelUtil::isDepth(mFormat))
{
    desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
    desc.Usage = D3D11_USAGE_DEFAULT;
    desc.CPUAccessFlags = 0;
    desc.MiscFlags = 0;
}

if (this->getTextureType() == TEX_TYPE_CUBE_MAP)
{
    desc.ArraySize = 6;
}

D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(Root::getSingleton().getRenderSystem());
if (rs->_getFeatureLevel() < D3D_FEATURE_LEVEL_10_0)
{
    if (!IsPowerOfTwo(desc.Width) || !IsPowerOfTwo(desc.Height))
    {
        desc.MipLevels = 1;
    }
}

HRESULT hr = mDevice->CreateTexture2D(&desc,                          
                                      NULL,                            
                                      mp2DTex.ReleaseAndGetAddressOf() 
);

if (FAILED(hr) || mDevice.isError())
{
    this->unloadImpl();
    String errorDescription = mDevice.getErrorDescription(hr);
    OGRE_EXCEPT_EX(Exception::ERR_RENDERINGAPI_ERROR, hr,
                   "Error creating texture\nError Description:" + errorDescription,
                   "D3D11Texture::_create2DTex");
}

// Getting shared Handle
ComPtr<IDXGIResource> dxgiResource;
mp2DTex.As(&dxgiResource); // Converte para IDXGIResource
HANDLE sharedHandle;
hr = dxgiResource->GetSharedHandle(&sharedHandle);
if (FAILED(hr) || !sharedHandle)
{
    throw std::runtime_error("Failed to retrieve shared handle for the texture");
}

// Here, I would pass the shared handle to the D3D11Image.
_queryInterface<ID3D11Texture2D, ID3D11Resource>(mp2DTex, &mpTex);

_create2DResourceView();
}

The problem is that I don't know how to access this method after building Ogre. Can I access this method directly, or is this kind of implementation specific? (I only know basic things about C++ :( )

paroj
OGRE Team Member
OGRE Team Member
Posts: 2106
Joined: Sun Mar 30, 2014 2:51 pm
x 1132

Re: D3D11RenderTexture::getCustomAttribute missing?

Post by paroj »

the changes are these lines, right?

Code: Select all

desc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED;
...
ComPtr<IDXGIResource> dxgiResource;
mp2DTex.As(&dxgiResource); // Converte para IDXGIResource
HANDLE sharedHandle;
hr = dxgiResource->GetSharedHandle(&sharedHandle);

then you will need to go through the Ogre public API to get what you want:

  1. add TU_SHARED_RESOURCE=0x100 to TextureUsage enum and specify it when creating that resource
  2. convert it to D3D11 in D3D11Mappings::_getTextureMiscFlags
  3. check it in _create2DTex and create sharedHandle if it is passed
  4. return sharedHandle via getCustomAttribute

that would be needed if you want to contribute that code back to Ogre.

If you just want a quick & dirty test, just add virtual void* _createShared2DTex() {} to the Texture class. This way it gets exposed in the bindings. However you will probably still need TU_SHARED_RESOURCE as you dont want both _createShared2DTex and _create2DTex to be called.

User avatar
Arthurfernandes
Gnoblar
Posts: 19
Joined: Mon Oct 28, 2024 10:50 pm
x 1

Re: D3D11RenderTexture::getCustomAttribute missing?

Post by Arthurfernandes »

Quick question while I'm trying to change everything necessary. Is creating a texture like this correct for the situation?

Code: Select all

texturePtr = TextureManager.getSingleton().createManual(
            "Ogre Render",
            ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME,
            TextureType.TEX_TYPE_SHARED_2D,
            (uint)ViewportSize.Width,
            (uint)ViewportSize.Height,
            32,
            0,
            PixelFormat.PF_R8G8B8A8,
            (int)TextureUsage.TU_SHARED_RESOURCE);

I was stuck on this for a while, but now it seems to be okay since in debug mode, it's no longer getting stuck here.

Another thing: I can't specify everything I've changed in the code, but now I'm getting a "System.ApplicationException: 'invalid vector subscript'" in getRenderTarget() from HardwarePixelBufferPtr.cs. This error happens right after creating the texture. Any tips?

Code: Select all

renderTarget = texturePtr.getBuffer().getRenderTarget();
User avatar
Arthurfernandes
Gnoblar
Posts: 19
Joined: Mon Oct 28, 2024 10:50 pm
x 1

Re: D3D11RenderTexture::getCustomAttribute missing?

Post by Arthurfernandes »

So, if I use (int)TextureUsage.TU_RENDERTARGET, I can get the renderTarget. However, if I choose (int)TextureUsage.TU_SHARED_RESOURCE, that error appears. I think it's now something more specific to investigate, but I still don't know exactly what to do. :?

paroj
OGRE Team Member
OGRE Team Member
Posts: 2106
Joined: Sun Mar 30, 2014 2:51 pm
x 1132

Re: D3D11RenderTexture::getCustomAttribute missing?

Post by paroj »

you should be able to specify both flags as TextureUsage.TU_RENDERTARGET|TextureUsage.TU_SHARED_RESOURCE