Failing to get D2D into my DX11 Engine

Started by
9 comments, last by bondehagen 12 years, 4 months ago
So I have a working DX11 Engine right now for rendering models and I felt I should add Texts right now and learned that Direct2D was the way.

However I don't understand how to do it.

Class Declaration of the DX11 Engine is:

ID3D11Device* m_pDevice;
ID3D11DeviceContext* m_pDeviceContext;
IDXGISwapChain* m_pSwapChain;


And the Engine Render Function is as follows:

m_D2DEngine is what I wanted to take care of the Rendering of a queue of texts.

void DX11Engine::Render()
{
m_pDeviceContext->ClearRenderTargetView(m_pBackbuffer, D3DXCOLOR(0.0f, 0.2f, 0.4f, 1.0f));

m_pDeviceContext->ClearDepthStencilView(m_pDepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);

m_pScene->Render();

m_D2DEngine.Render();

m_pSwapChain->Present(0, 0);
}
]



Render Function in the D2DEngine looks as follows:



ID3D10Device* m_pDevice;


D2D Needed a D3D10Device



void Direct2DEngine::Render()
{
HRESULT hr = S_OK;

m_pBackBuffer->BeginDraw();
m_pBackBuffer->SetTransform(D2D1::Matrix3x2F::Identity());

D2D1_SIZE_F rtSize = m_pBackBuffer->GetSize();

ID2D1SolidColorBrush* pBackBufferTextBrush = NULL;
hr = m_pBackBuffer->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::Red),
&pBackBufferTextBrush
);

for (unsigned int index = 0; index < m_vecTextToRender.size(); index++)
{
m_pBackBuffer->DrawText(
StringToWideString(m_vecTextToRender[index].m_strText).c_str(),
m_vecTextToRender[index].m_strText.size(),
m_pTextFormat,
D2D1::RectF(0.0f, 0.0f, rtSize.width, rtSize.height),
pBackBufferTextBrush
);

}

hr = m_pBackBuffer->EndDraw();

if (SUCCEEDED(hr) && m_pRenderTarget)
{
// Swap chain will tell us how big the back buffer is
DXGI_SWAP_CHAIN_DESC swapDesc;
hr = m_pSwapChain->GetDesc(&swapDesc);

if (SUCCEEDED(hr))
{
m_pDevice->ClearDepthStencilView(
m_pDepthStencilView,
D3D10_CLEAR_DEPTH,
1,
0
);

if (SUCCEEDED(hr))
{
m_pDiffuseVariableNoRef->SetResource(NULL);
m_pTechniqueNoRef->GetPassByIndex(0)->Apply(0);

// Draw the D2D content into a D3D surface.
hr = RenderD2DContentIntoSurface();
}
if (SUCCEEDED(hr))
{
m_pDiffuseVariableNoRef->SetResource(m_pTextureResourceView);

// Update variables that change once per frame.
m_pWorldVariableNoRef->SetMatrix((float*)&m_WorldMatrix);

// Set the index buffer.
m_pDevice->IASetIndexBuffer(m_pFacesIndexBuffer, DXGI_FORMAT_R16_UINT, 0);

// Render the scene
m_pTechniqueNoRef->GetPassByIndex(0)->Apply(0);

m_pDevice->DrawIndexed(
ARRAYSIZE(s_FacesIndexArray),
0,
0
);

// Draw some text using a red brush on top of everything
//if (m_pBackBuffer)
//{
//m_pBackBuffer->BeginDraw();

//m_pBackBuffer->SetTransform(D2D1::Matrix3x2F::Identity());

// Text format object will center the text in layout
//D2D1_SIZE_F rtSize = m_pBackBuffer->GetSize();

//ID2D1SolidColorBrush* pBackBufferTextBrush = NULL;
//hr = m_pBackBuffer->CreateSolidColorBrush(
// D2D1::ColorF(D2D1::ColorF::Red),
// &pBackBufferTextBrush
// );

//for (unsigned int index = 0; index < m_vecTextToRender.size(); index++)
//{
// m_pBackBuffer->DrawText(
// StringToWideString(m_vecTextToRender[index].m_strText).c_str(),
// m_vecTextToRender[index].m_strText.size(),
// m_pTextFormat,
// D2D1::RectF(0.0f, 0.0f, rtSize.width, rtSize.height),
// pBackBufferTextBrush
// );

//}

//hr = m_pBackBuffer->EndDraw();
//}
if (SUCCEEDED(hr))
{
hr = m_pSwapChain->Present(1, 0);
}
}
}
}

m_vecTextToRender.clear();
}



So my problem here is that it flicker betweens the rendered
1st: DX11 Picture - Blue background atm
2nd: D2DText - Black backround - Red Text

So how should I change the D2D Render function to draw it to my normal Picture?
I'm so unclear with everything since I had to create the D3D10Device also.
Advertisement

So how should I change the D2D Render function to draw it to my normal Picture?
I'm so unclear with everything since I had to create the D3D10Device also.

The flickering is coming from the fact that you are using two swap chains, that are conflicting when rendering.

Currently, Direct3D11 doesn't interop directly with Direct2D, and as Direct2D is only working with Direct3D10.1 you need to use surface sharing between Direct3D10.1 and Direct3D11 through DXGI, in order to compose Direct2D into a Direct3D11 application.
You can have a look at "Surface Sharing Between Windows Graphics APIs". more specifically, "DXGI 1.1 Synchronized Shared Surfaces" part.

Direct3D11.1 (from Win8 Developer Preview) is solving this issue and allows Direct2D to interop directly with Direct3D11.

[quote name='indiehjaerta' timestamp='1321064311' post='4883111']
So how should I change the D2D Render function to draw it to my normal Picture?
I'm so unclear with everything since I had to create the D3D10Device also.

The flickering is coming from the fact that you are using two swap chains, that are conflicting when rendering.

Currently, Direct3D11 doesn't interop directly with Direct2D, and as Direct2D is only working with Direct3D10.1 you need to use surface sharing between Direct3D10.1 and Direct3D11 through DXGI, in order to compose Direct2D into a Direct3D11 application.
You can have a look at "Surface Sharing Between Windows Graphics APIs". more specifically, "DXGI 1.1 Synchronized Shared Surfaces" part.

Direct3D11.1 (from Win8 Developer Preview) is solving this issue and allows Direct2D to interop directly with Direct3D11.
[/quote]


Okey thank you, looks like this will take some time sad.gif
Remember how easy it was back with DX10 angry.gif

Getting an Error when trying the code descirbed though:


D3D10_TEXTURE2D_DESC desc;
ZeroMemory( &desc, sizeof(desc) );
desc.Width = nWidth;
desc.Height = nHeight;
desc.MipLevels = 1;
desc.ArraySize = 1;
// must match swapchain format in order to CopySubresourceRegion.
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.Usage = D3D10_USAGE_DEFAULT;
// creates 2D texture as a Synchronized Shared Surface.
desc.MiscFlags = D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX;
desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
ID3D10Texture2D* g_pShared = NULL;
hr = m_pDevice->CreateTexture2D( &desc, NULL, &g_pShared );



hr returns E_INVALIDARG

I found some german site mentioning multisample, where would I change that?
In case you only want text I made a font-wrapper that caches DirectWrite glyphs to textures and draws them using quads to a D3D11 render target: http://fw1.codeplex.com/.
It can either be used as a standalone DLL, or you can just add the source-files to a project and use it directly and change it as you need. It is not dependent on D2D, only DirectWrite, and works similar to the old D3DX font.
Yeah, if you want just text, the way i showed how to do it is pretty inefficient... That will be VERY nice when direct3d 11.1 supports interopability with D2D directly... (now why wasn't D3D11 directly compatible with D2D?... I just think its funny how they suggested D2D and DirectWrite for text with D3D11, when saying it's not that simple is a major understatement laugh.gif)

Heres a little lesson on putting d2d into your d3d 11 app ;)

http://braynzarsoft....php?p=D3D11FONT


Thanks tryign it out now.

Though getting E_INVALIDARG at:


hr = m_pD3D101Device->OpenSharedResource(sharedHandle10, __uuidof(IDXGISurface1), (void**)(&sharedSurface10));



Setting up the D3D10 Device is more or less copy paste:

//Create our Direc3D 10.1 Device
hr = D3D10CreateDevice1(aAdapter, D3D10_DRIVER_TYPE_HARDWARE, NULL,D3D10_CREATE_DEVICE_DEBUG | D3D10_CREATE_DEVICE_BGRA_SUPPORT,
D3D10_FEATURE_LEVEL_9_3, D3D10_1_SDK_VERSION, &m_pD3D101Device );

//Create Shared Texture that Direct3D 10.1 will render on
D3D11_TEXTURE2D_DESC sharedTexDesc;
ZeroMemory(&sharedTexDesc, sizeof(sharedTexDesc));
sharedTexDesc.Width = aScreenWidth;
sharedTexDesc.Height = aScreenHeight;
sharedTexDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
sharedTexDesc.MipLevels = 1;
sharedTexDesc.ArraySize = 1;
sharedTexDesc.SampleDesc.Count = 1;
sharedTexDesc.Usage = D3D11_USAGE_DEFAULT;
sharedTexDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
sharedTexDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;



And when creating the DirectX10 Device I have:

hr = D3D11CreateDeviceAndSwapChain(m_pAdapter,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
D3D11_CREATE_DEVICE_DEBUG | D3D11_CREATE_DEVICE_BGRA_SUPPORT,
NULL,
NULL,
D3D11_SDK_VERSION,
&SwapChainDesc,
&m_pSwapChain,
&m_pDevice,
NULL,
&m_pDeviceContext);



Anyone have any idea? :/

EDIT: Had to change D3D_DRIVER_TYPE_HARDWARE to D3D_DRIVER_TYPE_UNKNOWN when specifyng Adapter... blink.gif

[quote name='iedoc' timestamp='1321105254' post='4883194']
Heres a little lesson on putting d2d into your d3d 11 app ;)

http://braynzarsoft....php?p=D3D11FONT


Thanks tryign it out now.

Though getting E_INVALIDARG at:


hr = m_pD3D101Device->OpenSharedResource(sharedHandle10, __uuidof(IDXGISurface1), (void**)(&sharedSurface10));



Setting up the D3D10 Device is more or less copy paste:

//Create our Direc3D 10.1 Device
hr = D3D10CreateDevice1(aAdapter, D3D10_DRIVER_TYPE_HARDWARE, NULL,D3D10_CREATE_DEVICE_DEBUG | D3D10_CREATE_DEVICE_BGRA_SUPPORT,
D3D10_FEATURE_LEVEL_9_3, D3D10_1_SDK_VERSION, &m_pD3D101Device );

//Create Shared Texture that Direct3D 10.1 will render on
D3D11_TEXTURE2D_DESC sharedTexDesc;
ZeroMemory(&sharedTexDesc, sizeof(sharedTexDesc));
sharedTexDesc.Width = aScreenWidth;
sharedTexDesc.Height = aScreenHeight;
sharedTexDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
sharedTexDesc.MipLevels = 1;
sharedTexDesc.ArraySize = 1;
sharedTexDesc.SampleDesc.Count = 1;
sharedTexDesc.Usage = D3D11_USAGE_DEFAULT;
sharedTexDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
sharedTexDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;



And when creating the DirectX10 Device I have:

hr = D3D11CreateDeviceAndSwapChain(m_pAdapter,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
D3D11_CREATE_DEVICE_DEBUG | D3D11_CREATE_DEVICE_BGRA_SUPPORT,
NULL,
NULL,
D3D11_SDK_VERSION,
&SwapChainDesc,
&m_pSwapChain,
&m_pDevice,
NULL,
&m_pDeviceContext);



Anyone have any idea? :/

EDIT: Solved it... Had to change D3D_DRIVER_TYPE_HARDWARE to D3D_DRIVER_TYPE_UNKNOWN when specifyng Adapter... blink.gif
[/quote]
[s]I am not stuck at this snippet


WVP = XMMatrixIdentity();
cbPerObj.WVP = XMMatrixTranspose(WVP);
DX11Engine::GetInstance()->GetDeviceContext()->UpdateSubresource( cbPerObjectBuffer, 0, NULL, &cbPerObj, 0, 0 );
DX11Engine::GetInstance()->GetDeviceContext()->VSSetConstantBuffers( 0, 1, &cbPerObjectBuffer );
DX11Engine::GetInstance()->GetDeviceContext()->PSSetShaderResources( 0, 1, &m_pD2DTexture);
DX11Engine::GetInstance()->GetDeviceContext()->PSSetSamplers( 0, 1, &m_pCubesTexSamplerState );


DX11Engine::GetInstance()->GetDeviceContext()->RSSetState(m_pCWcullMode);
//Draw the second cube

DX11Engine::GetInstance()->GetDeviceContext()->DrawIndexed( 6, 0, 0 );


My questions is:
1. Do I need to load the Effect file on their site too for this to work?
2. Are all these lines above neccessary?
2a. Do I need to create cbPerObjectBuffer
2b. Do I need to create cbPerObj
3. What's the D3D equivalent to XMMATRIX (and identity), I don't want to include any XNA stuff into this.

Up to this everything seems fine at the moment.[/s]
[s]
[/s]
[s]EDIT:
I'm doing something wrong but I can't find it:

DX11Engine::GetInstance()->GetDeviceContext()->DrawIndexed( 6, 0, 0 );


D3D11: ERROR: ID3D11DeviceContext::DrawIndexed: The Vertex Shader expects application provided input data (which is to say data other than hardware auto-generated values such as VertexID or InstanceID). Therefore an Input Assembler object is expected, but none is bound. [ EXECUTION ERROR #349: DEVICE_DRAW_INPUTLAYOUT_NOT_SET ][/s]
[s]
[/s]
EDIT2: Forgot to set Vertex Layout

Still don't see anything, no warning. :(

No Errors setting up anything.
No output error either.

Render Function Looks like this now:
void Direct2DEngine::Render()
{
HRESULT hr;

//Release the D3D 11 Device
hr = m_pKeyedMutex11->ReleaseSync(0);

//Use D3D10.1 device
hr = m_pKeyedMutex10->AcquireSync(0, 5);

//Draw D2D content
m_pD2DRenderTarget->BeginDraw();

//Clear D2D Background
m_pD2DRenderTarget->Clear(D2D1::ColorF(0.0f, 0.0f, 0.0f, 0.0f));

//Create our string
std::wstring printText = L"Hello World";

//Set the Font Color
D2D1_COLOR_F FontColor = D2D1::ColorF(1.0f, 1.0f, 1.0f, 1.0f);

//Set the brush color D2D will use to draw with
m_pColorBrush->SetColor(FontColor);

//Create the D2D Render Area
D2D1_RECT_F layoutRect = D2D1::RectF(0, 0, m_dwRenderWidth, m_dwRenderHeight);

//Draw the Text
m_pD2DRenderTarget->DrawText(
printText.c_str(),
wcslen(printText.c_str()),
m_pTextFormat,
layoutRect,
m_pColorBrush
);

m_pD2DRenderTarget->EndDraw();

//Release the D3D10.1 Device
hr = m_pKeyedMutex10->ReleaseSync(1);

//Use the D3D11 Device
hr = m_pKeyedMutex11->AcquireSync(1, 5);

//Use the shader resource representing the direct2d render target
//to texture a square which is rendered in screen space so it
//overlays on top of our entire scene. We use alpha blending so
//that the entire background of the D2D render target is "invisible",
//And only the stuff we draw with D2D will be visible (the text)

//Set Vertex and Pixel Shaders
DX11Engine::GetInstance()->GetDeviceContext()->VSSetShader(m_pVertexShader, 0, 0);
DX11Engine::GetInstance()->GetDeviceContext()->PSSetShader(m_PixelShader, 0, 0);

//TO AVOID CRASHING DRIVERS SINCE I HAVE NOT SET THIS BY DEFAULT
DX11Engine::GetInstance()->GetDeviceContext()->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_POINTLIST);

//Set the blend state for D2D render target texture objects
DX11Engine::GetInstance()->GetDeviceContext()->OMSetBlendState(m_pTransparency, NULL, 0xffffffff);

//Set the D2D Index buffer
DX11Engine::GetInstance()->GetDeviceContext()->IASetIndexBuffer( m_pD2DIndexBuffer, DXGI_FORMAT_R32_UINT, 0);

//Set the D2D vertex buffer
UINT stride = sizeof( Vertex );
UINT offset = 0;
DX11Engine::GetInstance()->GetDeviceContext()->IASetVertexBuffers( 0, 1, &m_pD2DVertexBuffer, &stride, &offset );

//Set the Input Layout
DX11Engine::GetInstance()->GetDeviceContext()->IASetInputLayout( m_pVertexLayout );

D3DXMATRIX WVP;
D3DXMatrixIdentity(&WVP);
D3DXMatrixTranspose(&WVP, &WVP);

ConstantBufferObject cbObj;
cbObj.WorldViewProjection = WVP;

DX11Engine::GetInstance()->GetDeviceContext()->UpdateSubresource( m_pConstantBuffer, 0, NULL, &cbObj, 0, 0 );
DX11Engine::GetInstance()->GetDeviceContext()->VSSetConstantBuffers( 0, 1, &m_pConstantBuffer );
DX11Engine::GetInstance()->GetDeviceContext()->PSSetShaderResources( 0, 1, &m_pD2DTexture );
DX11Engine::GetInstance()->GetDeviceContext()->PSSetSamplers( 0, 1, &m_pCubesTexSamplerState );

DX11Engine::GetInstance()->GetDeviceContext()->RSSetState(m_pCWcullMode);

DX11Engine::GetInstance()->GetDeviceContext()->DrawIndexed( 6, 0, 0 );
}

[s]
[/s]

This topic is closed to new replies.

Advertisement