• Advertisement

DX11 Sharing surface with ID2D1DCRenderTarget created by CreateDCRenderTarget

Recommended Posts

I have found an example here:
about sharing surfaces/textures created by DX11 into the ID2D1DCRenderTarget, however the above example is based on SwapChain bound to a window (hwnd)
What I need is to draw a shared texture into GDI as this is the only plugin interface in an old software I have. Any ideas ?
Here is what I do.

	//Initialize the ID2D1Factory object
	D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory);
	//D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, &pD2DFactory);
	//initialize the ID2D1DCRenderTarget
	D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
	HRESULT hr = pD2DFactory->CreateDCRenderTarget(&props, &pRT);

	DWORD createDeviceFlags = 0;
	createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;

	ID3D11DeviceContext* context;

	ZeroMemory( &sd, sizeof( sd ) );
	sd.BufferCount = 1;
	sd.BufferDesc.Width = width;
	sd.BufferDesc.Height = height;
	sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
	sd.BufferDesc.RefreshRate.Numerator = 60;
	sd.BufferDesc.RefreshRate.Denominator = 1;
	sd.OutputWindow = 0; // g_hWnd;
	sd.SampleDesc.Count = 1;
	sd.SampleDesc.Quality = 0;
	sd.Windowed = FALSE, // TRUE;		

	hr = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE,
		nullptr, createDeviceFlags, nullptr,
		0, D3D11_SDK_VERSION, &sd, &pSwapChain, &mDevice, &fl, &context);

	hr = m_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));		


bool SharedSurface::CreateTexture(ID3D11Device* device, UINT width, UINT height)
	ZeroMemory(&desc, sizeof(desc));
	desc.Width = width;
	desc.Height = height;
	desc.MipLevels = 1;
	desc.ArraySize = 1;
	desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
	desc.SampleDesc.Count = 1;

	desc.Usage = D3D11_USAGE_DEFAULT;
	desc.CPUAccessFlags = 0; // D3D11_CPU_ACCESS_READ; // 0;

	if (device != nullptr)
		mDevice = device;

	hr = mDevice->CreateTexture2D(&desc, NULL, &pTexture);

	IDXGIResource * pDXGIResource = NULL;
	hr = pTexture->QueryInterface(__uuidof(IDXGIResource), (void **)&pDXGIResource);


		hr = pDXGIResource->GetSharedHandle(&sharedHandle);

		if SUCCEEDED(hr)
			hr = pTexture->QueryInterface(__uuidof(IDXGIKeyedMutex),


	hr = pTexture->QueryInterface(__uuidof(IDXGISurface), (void **)&pSurface);

	FLOAT dpiX;
    FLOAT dpiY;
    pD2DFactory->GetDesktopDpi(&dpiX, &dpiY);


	hr = pD2DFactory->CreateDxgiSurfaceRenderTarget(pBackBuffer,&props,	&pBackBufferRT);

	ZeroMemory(&bp, sizeof(bp));
	bp.pixelFormat = D2D1::PixelFormat(sdesc.Format, D2D1_ALPHA_MODE_PREMULTIPLIED);

	hr = pBackBufferRT->CreateSharedBitmap(__uuidof(ID3D11Texture2D), pSurface,&bp, &pBitmap);

	return SUCCEEDED(hr);


void SharedSurface::Draw()

void SharedSurface::BindDC(HDC hdc, int width, int height)
	RECT rct;
	rct.top = 0;
	rct.left = 0;
	rct.right = width;
	rct.bottom = height;
	pRT->BindDC(hdc, &rct);

// HOW TO EXCHANGE between pBackBufferRT and pRT ? 


Share this post

Link to post
Share on other sites

It looks like CreateDxgiSurfaceRenderTarget cannot be used with D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE and CreateSharedBitmap cannot be used with ID2D1DCRenderTarget as it must be used with render target created by CreateDxgiSurfaceRenderTarget , so looks there is no straight way to do it. Any tricks ?

Share this post

Link to post
Share on other sites

I am a bit unclear what you are trying to do. You can do 2 totally seperate things with directx2d in your directx3d program.

1. You can use directx2d to write to the swapchain backbuffer.

2. You can use direct2d to write to a texturebuffer that you use as a SRV in your 3d pipeline. This has nothing to do with the swapchain. For example you might want your pixel shader to use this texture to display some text on the side of an object.

See here for different things you can do  - https://msdn.microsoft.com/en-gb/library/windows/desktop/dd370966(v=vs.85).aspx

Share this post

Link to post
Share on other sites

The scenario is the following.

I have quite old app using dx9 which allows plugin integration. Unfortunately the plugin integration is through GDI, so I receive Paint callback with HDC. What I do is drawing into Texture2D using DX11 in another process and share the texture with GDI plugin. It works fine when I share the texture bits through CPU. Now, I want to use GPU only and use the texture sharing between DX11 and GDI so I tried to create ID2D1DCRenderTarget   but that I cannot link with any shared surface ...

Share this post

Link to post
Share on other sites

You'd need to create a swapchain on the corresponding HWND and Present() to copy the bits, or create a GDI_COMPATIBLE surface and use the IDXGISurface1::GetDC/ReleaseDC methods to get a second DC, and use GDI to do the copy.

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
  • Advertisement
  • Popular Tags

  • Advertisement
  • Popular Now

  • Similar Content

    • By trojanfoe
      I hope this is the right place to ask questions about DirectXTK which aren't really about graphics, if not please let me know a better place.
      Can anyone tell me why I cannot do this:
      DirectX::SimpleMath::Rectangle rectangle = {...}; RECT rect = rectangle; or
      RECT rect = static_cast<RECT>(rectangle); or
      const RECT rect(m_textureRect); despite Rectangle having the following operator RECT:
      operator RECT() { RECT rct; rct.left = x; rct.top = y; rct.right = (x + width); rct.bottom = (y + height); return rct; } VS2017 tells me:
      error C2440: 'initializing': cannot convert from 'const DirectX::SimpleMath::Rectangle' to 'const RECT' Thanks in advance
    • By isu diss
      I'm trying to duplicate vertices using std::map to be used in a vertex buffer. I don't get the correct index buffer(myInds) or vertex buffer(myVerts). I can get the index array from FBX but it differs from what I get in the following std::map code. Any help is much appreciated.
      struct FBXVTX { XMFLOAT3 Position; XMFLOAT2 TextureCoord; XMFLOAT3 Normal; }; std::map< FBXVTX, int > myVertsMap; std::vector<FBXVTX> myVerts; std::vector<int> myInds; HRESULT FBXLoader::Open(HWND hWnd, char* Filename, bool UsePositionOnly) { HRESULT hr = S_OK; if (FBXM) { FBXIOS = FbxIOSettings::Create(FBXM, IOSROOT); FBXM->SetIOSettings(FBXIOS); FBXI = FbxImporter::Create(FBXM, ""); if (!(FBXI->Initialize(Filename, -1, FBXIOS))) { hr = E_FAIL; MessageBox(hWnd, (wchar_t*)FBXI->GetStatus().GetErrorString(), TEXT("ALM"), MB_OK); } FBXS = FbxScene::Create(FBXM, "REALMS"); if (!FBXS) { hr = E_FAIL; MessageBox(hWnd, TEXT("Failed to create the scene"), TEXT("ALM"), MB_OK); } if (!(FBXI->Import(FBXS))) { hr = E_FAIL; MessageBox(hWnd, TEXT("Failed to import fbx file content into the scene"), TEXT("ALM"), MB_OK); } FbxAxisSystem OurAxisSystem = FbxAxisSystem::DirectX; FbxAxisSystem SceneAxisSystem = FBXS->GetGlobalSettings().GetAxisSystem(); if(SceneAxisSystem != OurAxisSystem) { FbxAxisSystem::DirectX.ConvertScene(FBXS); } FbxSystemUnit SceneSystemUnit = FBXS->GetGlobalSettings().GetSystemUnit(); if( SceneSystemUnit.GetScaleFactor() != 1.0 ) { FbxSystemUnit::cm.ConvertScene( FBXS ); } if (FBXI) FBXI->Destroy(); FbxNode* MainNode = FBXS->GetRootNode(); int NumKids = MainNode->GetChildCount(); FbxNode* ChildNode = NULL; for (int i=0; i<NumKids; i++) { ChildNode = MainNode->GetChild(i); FbxNodeAttribute* NodeAttribute = ChildNode->GetNodeAttribute(); if (NodeAttribute->GetAttributeType() == FbxNodeAttribute::eMesh) { FbxMesh* Mesh = ChildNode->GetMesh(); if (UsePositionOnly) { NumVertices = Mesh->GetControlPointsCount();//number of vertices MyV = new XMFLOAT3[NumVertices]; for (DWORD j = 0; j < NumVertices; j++) { FbxVector4 Vertex = Mesh->GetControlPointAt(j);//Gets the control point at the specified index. MyV[j] = XMFLOAT3((float)Vertex.mData[0], (float)Vertex.mData[1], (float)Vertex.mData[2]); } NumIndices = Mesh->GetPolygonVertexCount();//number of indices MyI = (DWORD*)Mesh->GetPolygonVertices();//index array } else { FbxLayerElementArrayTemplate<FbxVector2>* uvVertices = NULL; Mesh->GetTextureUV(&uvVertices); int idx = 0; for (int i = 0; i < Mesh->GetPolygonCount(); i++)//polygon(=mostly triangle) count { for (int j = 0; j < Mesh->GetPolygonSize(i); j++)//retrieves number of vertices in a polygon { FBXVTX myVert; int p_index = 3*i+j; int t_index = Mesh->GetTextureUVIndex(i, j); FbxVector4 Vertex = Mesh->GetControlPointAt(p_index);//Gets the control point at the specified index. myVert.Position = XMFLOAT3((float)Vertex.mData[0], (float)Vertex.mData[1], (float)Vertex.mData[2]); FbxVector4 Normal; Mesh->GetPolygonVertexNormal(i, j, Normal); myVert.Normal = XMFLOAT3((float)Normal.mData[0], (float)Normal.mData[1], (float)Normal.mData[2]); FbxVector2 uv = uvVertices->GetAt(t_index); myVert.TextureCoord = XMFLOAT2((float)uv.mData[0], (float)uv.mData[1]); if ( myVertsMap.find( myVert ) != myVertsMap.end() ) myInds.push_back( myVertsMap[ myVert ]); else { myVertsMap.insert( std::pair<FBXVTX, int> (myVert, idx ) ); myVerts.push_back(myVert); myInds.push_back(idx); idx++; } } } } } } } else { hr = E_FAIL; MessageBox(hWnd, TEXT("Failed to create the FBX Manager"), TEXT("ALM"), MB_OK); } return hr; } bool operator < ( const FBXVTX &lValue, const FBXVTX &rValue) { if (lValue.Position.x != rValue.Position.x) return(lValue.Position.x < rValue.Position.x); if (lValue.Position.y != rValue.Position.y) return(lValue.Position.y < rValue.Position.y); if (lValue.Position.z != rValue.Position.z) return(lValue.Position.z < rValue.Position.z); if (lValue.TextureCoord.x != rValue.TextureCoord.x) return(lValue.TextureCoord.x < rValue.TextureCoord.x); if (lValue.TextureCoord.y != rValue.TextureCoord.y) return(lValue.TextureCoord.y < rValue.TextureCoord.y); if (lValue.Normal.x != rValue.Normal.x) return(lValue.Normal.x < rValue.Normal.x); if (lValue.Normal.y != rValue.Normal.y) return(lValue.Normal.y < rValue.Normal.y); return(lValue.Normal.z < rValue.Normal.z); }  
    • By Karol Plewa
      I am working on a project where I'm trying to use Forward Plus Rendering on point lights. I have a simple reflective scene with many point lights moving around it. I am using effects file (.fx) to keep my shaders in one place. I am having a problem with Compute Shader code. I cannot get it to work properly and calculate the tiles and lighting properly. 
      Is there anyone that is wishing to help me set up my compute shader?
      Thank you in advance for any replies and interest!
    • By turanszkij
      Hi, right now building my engine in visual studio involves a shader compiling step to build hlsl 5.0 shaders. I have a separate project which only includes shader sources and the compiler is the visual studio integrated fxc compiler. I like this method because on any PC that has visual studio installed, I can just download the solution from GitHub and everything just builds without additional dependencies and using the latest version of the compiler. I also like it because the shaders are included in the solution explorer and easy to browse, and double-click to open (opening files can be really a pain in the ass in visual studio run in admin mode). Also it's nice that VS displays the build output/errors in the output window.
      But now I have the HLSL 6 compiler and want to build hlsl 6 shaders as well (and as I understand I can also compile vulkan compatible shaders with it later). Any idea how to do this nicely? I want only a single project containing shader sources, like it is now, but build them for different targets. I guess adding different building projects would be the way to go that reference the shader source project? But how would they differentiate from shader type of the sources (eg. pixel shader, compute shader,etc.)? Now the shader building project contains for each shader the shader type, how can other building projects reference that?
      Anyone with some experience in this?
    • By osiris_dev
      Have a problem with reflection shader for D3D11:
      1>engine_render_d3d11_system.obj : error LNK2001: unresolved external symbol IID_ID3D11ShaderReflection
      I tried to add this:
      #include <D3D11Shader.h>
      #include <D3Dcompiler.h>
      #include <D3DCompiler.inl>
      #pragma comment(lib, "D3DCompiler.lib")
      //#pragma comment(lib, "D3DCompiler_47.lib")
      As MSDN tells me but still no fortune. I think lot of people did that already, what I missing?
      I also find this article http://mattfife.com/?p=470
      where recommend to use SDK headers and libs before Wind SDK, but I am not using DirectX SDK for this project at all, should I?
  • Advertisement