Diligent Graphics > Diligent Engine > Native API Interoperability > Direct3D11 Interoperability
Direct3D11 Interoperability
This page describes interfaces and methods that provide interoperability with Direct3D11.
Accessing Native D3D11 objects
- ID3D11Buffer *IBufferD3D11::GetD3D11Buffer() – returns a pointer to the ID3D11Buffer interface of the internal Direct3D11 buffer object.
-
ID3D11Resource* ITextureD3D11::GetD3D11Texture() – returns a pointer to the ID3D11Resource interface of the internal Direct3D11 texture object. Depending on the texture type, the pointer can be cast to:
- ID3D11Texture1D – for 1D textures/texture arrays
- ID3D11Texture2D – for 2D textures/texture arrays
- ID3D11Texture3D – for 3D textures
Pause and squeeze method – One can viagra online canada also opt for an overnight delivery. One cannot be sure for what has made the cialis overnight delivery legendary figure’s designs successful. Erectile dysfunction is an inability to attain or sustain an erection. the cost of viagra Some cytokines appear to encourage the development of new usually in stock brand cialis price blood vessels that nourish tumors, the crucial process in tumor metastasis.
-
ID3D11View* IBufferViewD3D11()::GetD3D11View() – returns a pointer to the ID3D11View interface of the internal d3d11 object representing the buffer view. Depending on the view type, the pointer can be cast to
- ID3D11ShaderResourceView – if the type of the buffer view is BUFFER_VIEW_SHADER_RESOURCE
- ID3D11UnorderedAccessView – if the type of the buffer view is BUFFER_VIEW_UNORDERED_ACCESS
-
ID3D11View* ITextureViewD3D11::GetD3D11View() – returns a pointer to the ID3D11View interface of the internal d3d11 object representing the texture view. Depending on the view type, the pointer can be cast to
- ID3D11ShaderResourceView – if the type of the texture view is TEXTURE_VIEW_SHADER_RESOURCE
- ID3D11RenderTargetView – if the type of the texture view is TEXTURE_VIEW_RENDER_TARGET
- ID3D11DepthStencilView – if the type of the texture view is TEXTURE_VIEW_DEPTH_STENCIL
- ID3D11UnorderedAccessView – if the type of the texture view is TEXTURE_VIEW_UNORDERED_ACCESS
- ID3D11Device* IRenderDeviceD3D11::GetD3D11Device() – returns a pointer to the native D3D11 device object
- ID3D11DeviceContext* IDeviceContextD3D11::GetD3D11DeviceContext() – returns a pointer to the native ID3D11DeviceContext object
- ID3D11SamplerState* ISamplerD3D11::GetD3D11SamplerState() – returns a pointer to the native ID3D11SamplerState interface.
-
ID3D11DeviceChild* IShaderD3D11::GetD3D11Shader() – returns a pointer to the ID3D11DeviceChild interface of the D3D11 shader object. Depending on the shader type, the pointer can be cast to
- ID3D11VertexShader if the type of the shader is SHADER_TYPE_VERTEX
- ID3D11PixelShader if the type of the shader is SHADER_TYPE_PIXEL
- ID3D11GeometryShader if the type of the shader is SHADER_TYPE_GEOMETRY
- ID3D11HullShader if the type of the shader is SHADER_TYPE_HULL
- ID3D11DomainShader if the type of the shader is SHADER_TYPE_DOMAIN
- ID3D11ComputeShader if the type of the shader is SHADER_TYPE_COMPUTE
- ID3D11BlendState* IPipelineStateD3D11::GetD3D11BlendState() – returns a pointer to the ID3D11BlendState interface of the internal Direct3D11 object
- ID3D11RasterizerState* IPipelineStateD3D11::GetD3D11RasterizerState() – returns a pointer to the ID3D11RasterizerState interface of the internal Direct3D11 object
- ID3D11DepthStencilState* IPipelineStateD3D11::GetD3D11DepthStencilState() – returns a pointer to the ID3D11DepthStencilState interface of the internal Direct3D11 object
- ID3D11InputLayout* IPipelineStateD3D11::GetD3D11InputLayout() – returns a pointer to the ID3D11InputLayout interface of the internal Direct3D11 object
- ID3D11VertexShader* IPipelineStateD3D11::GetD3D11VertexShader() – returns a pointer to the ID3D11VertexShader interface of the internal vertex shader object
- ID3D11PixelShader* IPipelineStateD3D11::GetD3D11PixelShader() – returns a pointer to the ID3D11PixelShader interface of the internal pixel shader object
- ID3D11GeometryShader* IPipelineStateD3D11::GetD3D11GeometryShader() – returns a pointer to the ID3D11GeometryShader interface of the internal geometry shader object
- ID3D11DomainShader* IPipelineStateD3D11::GetD3D11DomainShader() – returns a pointer to the ID3D11DomainShader interface of the internal domain shader object
- ID3D11HullShader* IPipelineStateD3D11::GetD3D11HullShader() – returns a pointer to the ID3D11HullShader interface of the internal hull shader object
- ID3D11ComputeShader* IPipelineStateD3D11::GetD3D11ComputeShader() – returns a pointer to the ID3D11ComputeShader interface of the internal compute shader object
Note that the methods listed above do not call AddRef() on the returned interface, so the application must not call Release().
Examples:
1 2 3 4 5 6 7 8 |
// Get a pointer to the native D3D11 buffer from IBuffer RefCntAutoPtr<IBufferD3D11> pBufferD3D11(pBuffer, IID_BufferD3D11); auto *pd3d11NativeBuffer = pBufferD3D11->GetD3D11Buffer(); // Get a pointer to the native D3D11 texture from ITexture RefCntAutoPtr<ITextureD3D11> pTextureD3D11(pTexture, IID_TextureD3D11); auto *pd3d11Resource = pTextureD3D11->GetD3D11Texture(); auto *pd3d11Texture2D = reinterpret_cast<ID3D11Texture2D*>(pd3d11Resource); |
Creating Diligent Engine Objects from D3D11 Resources
- void IRenderDeviceD3D11::CreateBufferFromD3DResource(ID3D11Buffer *pd3d11Buffer, const BufferDesc& BuffDesc, IBuffer **ppBuffer) – creates a diligent engine buffer object from the native d3d11 buffer. The method takes a pointer to the native d3d11 buffer pd3d11Buffer, buffer description BuffDesc and writes a pointer to the IBuffer interface at the memory location pointed to by ppBuffer. Most members of the BuffDesc structure can keep default values, and the engine will populate them based on the attributes of D3D11 buffer. The only field that must be populated is BufferDesc::Format, when creating a formatted buffer.
-
void IRenderDeviceD3D11::CreateTextureFromD3DResource(ID3D11Texture1D *pd3d11Texture, ITexture **ppTexture)
void IRenderDeviceD3D11::CreateTextureFromD3DResource(ID3D11Texture2D *pd3d11Texture, ITexture **ppTexture)
void IRenderDeviceD3D11::CreateTextureFromD3DResource(ID3D11Texture3D *pd3d11Texture, ITexture **ppTexture) –
These functions create a diligent engine texture object from the native D3D11 1D texture, 2D texture, and 3D texture correspondingly. The methods do not take texture description as all attributes are extracted from the attributes of the native object
Note that diligent engine objects will keep strong reference to the D3D11 interface. As a result, D3D11 object will not be released until Diligent Engine object is destroyed.
Example:
1 2 3 4 5 6 7 8 9 |
// Create a diligent engine buffer from native D3D11 buffer BufferDesc BuffDesc; BuffDesc.Name = "Test buffer from D3D11 buffer"; RefCntAutoPtr<IBuffer> pBufferFromNativeD3D11Handle; pDeviceD3D11->CreateBufferFromD3DResource(pd3d11NativeBuffer, BuffDesc, &pBufferFromNativeD3D11Handle); // Create a diligent engine texture from the native D3D11 texture RefCntAutoPtr<ITexture> pTextureFromNativeD3D11Handle; pDeviceD3D11->CreateTextureFromD3DResource(pd3d11Texture2D, &pTextureFromNativeD3D11Handle); |
Initializing the Engine by Attaching to Existing D3D11 Device and Immediate Context
To attach diligent engine to existing D3D11 device and immediate context, use the following factory function:
1 2 3 4 5 6 |
void IEngineFactoryD3D11::AttachToD3D11Device(void *pd3d11NativeDevice, void *pd3d11ImmediateContext, EngineD3D11Attribs& EngineAttribs, IRenderDevice **ppDevice, IDeviceContext **ppContexts, Uint32 NumDeferredContexts); |
The method takes a pointer to the native D3D11 device pd3d11NativeDevice, a pointer to the d3d11 immediate context pd3d11ImmediateContext, initialization parameters EngineAttribs, and returns diligent engine device interface in ppDevice, and diligent engine contexts in ppContexts. Pointer to the immediate goes at position 0. If NumDeferredContexts > 0, pointers to deferred contexts go afterwards.
The code snippet below shows how diligent engine can be attached to D3D11 device returned by Unity:
1 2 3 4 5 6 7 8 |
IUnityGraphicsD3D11* d3d = interfaces->Get<IUnityGraphicsD3D11>(); ID3D11Device* d3d11NativeDevice = d3d->GetDevice(); CComPtr<ID3D11DeviceContext> d3d11ImmediateContext; d3d11NativeDevice->GetImmediateContext(&d3d11ImmediateContext); auto *pFactoryD3d11 = GetEngineFactoryD3D11(); EngineD3D11Attribs Attribs; pFactoryD3d11->AttachToD3D11Device(d3d11NativeDevice, d3d11ImmediateContext, Attribs, &m_Device, &m_Context, 0); |
Diligent Engine keeps track of all states bound to the D3D11 immediate context (vertex and index buffers, shaders and shader resources, render targets etc.). Since main application also uses the same context, the state cache needs to be invalidated every time the control flow returns to the main application:
1 2 3 4 5 |
void EndRendering() { if (m_Context) m_Context->InvalidateState(); } |
Initializing proxy swap chain
After initialization through AttachToD3D11Device(), diligent engine has no notion of the swap chain. There are several special commands that can be executed from the diligent engine context that require swap to be initialized in the context:
- SetRenderTargets(0, nullptr, nullptr) – bind the default back buffer & depth buffer
- SetViewports(1, nullptr, 0, 0) – set the viewport to match the size of the back buffer
- ClearRenderTarget(nullptr, color) – clear the default back buffer
- ClearDepthStencil(nullptr, ...) – clear the default depth-stencil buffer
If the application is using any of these commands, it needs to implement ISwapChainD3D11 interface:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/// Interface to the swap chain object implemented in D3D11 class ISwapChainD3D11 : public ISwapChain { public: /// Returns a pointer to the IDXGISwapChain interface of the internal DXGI object. virtual IDXGISwapChain *GetDXGISwapChain() = 0; /// Returns d3d11 render target view of the swap chain's back buffer virtual ID3D11RenderTargetView *GetRTV() = 0; /// Returns d3d11 depth stencil view of the internal depth buffer object virtual ID3D11DepthStencilView *GetDSV() = 0; }; |
A possible implementation may look like this:
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 |
class ProxySwapChainD3D11 : public SwapChainBase<ISwapChainD3D11> { public: using TBase = SwapChainBase<ISwapChainD3D11>; ProxySwapChainD3D11( IReferenceCounters *pRefCounters, IRenderDevice *pDevice, IDeviceContext *pDeviceContext, const SwapChainDesc& SCDesc ) : TBase(pRefCounters, pDevice, pDeviceContext,SCDesc) {} IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_SwapChainD3D11, TBase) virtual IDXGISwapChain *GetDXGISwapChain()override final { UNEXPECTED("DXGI swap chain cannot be requested through the proxy swap chain") return nullptr; } virtual ID3D11RenderTargetView *GetRTV()override final{ return m_pRTV; } virtual ID3D11DepthStencilView *GetDSV()override final { return m_pDSV; } virtual void Present()override final { UNEXPECTED("Present is not expected to be called directly") } virtual void Resize(Uint32 NewWidth, Uint32 NewHeight)override final { TBase::Resize(NewWidth, NewHeight, 0); } void SetSwapChainAttribs(ID3D11RenderTargetView *pRTV, ID3D11DepthStencilView *pDSV, Uint32 Width, Uint32 Height) { TBase::Resize(Width, Height, 0); m_pRTV = pRTV; m_pDSV = pDSV; } private: ID3D11RenderTargetView *m_pRTV = nullptr; ID3D11DepthStencilView *m_pDSV = nullptr; }; |
An instance of ProxySwapChainD3D11 should then be set in the device context after it has been initialized:
1 2 3 4 5 6 7 |
auto &DefaultAllocator = DefaultRawMemoryAllocator::GetAllocator(); auto pProxySwapChainD3D11 = NEW_RC_OBJ(DefaultAllocator, "ProxySwapChainD3D11 instance", ProxySwapChainD3D11) (m_pDevice, m_pDeviceCtx, SCDesc); pProxySwapChainD3D11->QueryInterface(IID_SwapChain, reinterpret_cast<IObject**>(static_cast<ISwapChain**>(&m_pProxySwapChain))); m_Context->SetSwapChain(m_pProxySwapChain); |