# Copy directX 12 texture to GpuMat

**URL:** <https://forum.opencv.org/t/copy-directx-12-texture-to-gpumat/15514>\
**Category:** C++\
**Tags:** gpumat\
**Created:** [November 14, 2023, 3:00pm UTC](https://forum.opencv.org/t/copy-directx-12-texture-to-gpumat/15514 "2023-11-14T15:00:21Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![roy\_c](https://avatars.discourse-cdn.com/v4/letter/r/54ee81/32.png) [@roy\_c](https://forum.opencv.org/u/roy_c)\
**Post date:** [November 14, 2023, 3:00pm UTC](https://forum.opencv.org/t/copy-directx-12-texture-to-gpumat/15514/1 "2023-11-14T15:00:21Z")

</div>

Hello,

I’m trying to copy a directx 12 texture to GpuMat with pure gpu memory transfert.  
In opencv documentation I haven’t see any reference to directx 12 just 10 or 11.  
So I copy the texture in cuda memory and set this memory to a GpuMat.

```auto
void getExternalMemory(DX12Texture& d3d12Texture)
{
	cudaExternalMemoryHandleDesc memDesc{};
	memset(&memDesc, 0, sizeof(memDesc));

	memDesc.type = cudaExternalMemoryHandleTypeD3D12Resource;
	memDesc.handle.win32.handle = d3d12Texture.handle;
	memDesc.size = d3d12Texture.memSize;
	memDesc.flags = cudaExternalMemoryDedicated;

	cudaError_t cudaError = cudaImportExternalMemory(&m_externalMemory, &memDesc);
	
}

void mapMemory(cv::cuda::GpuMat& mat, DX12Texture& d3d12Texture)
{
	void* pData = nullptr;
	cudaExternalMemoryBufferDesc buffDesc{};
	memset(&buffDesc, 0, sizeof(buffDesc));

	buffDesc.offset = 0;
	buffDesc.size = d3d12Texture.memSize;

	cudaExternalMemoryGetMappedBuffer(&pData, m_externalMemory, &buffDesc);
	//auto format = cv::directx::getTypeFromDXGI_FORMAT(d3d12Texture.resource->GetDesc().Format);
	auto format = cv::directx::getTypeFromDXGI_FORMAT(31);//D3DFMT_A2B10G10R10 is the same as DXGI_FORMAT_R10G10B10A2_UNORM

	cv::cuda::GpuMat(static_cast<int>(d3d12Texture.resource->GetDesc().Height),
		static_cast<int>(d3d12Texture.resource->GetDesc().Width),
		format, pData).copyTo(mat);
		
	cudaFree(pData);
}

```

My result is :

 ![Test_screenshot](https://us1.discourse-cdn.com/flex020/uploads/opencv/original/2X/b/b2eeee441e6b8673913ba80e11ea097334b90a7f.jpeg)  
I didn’t know what I missed.  
Do you have an idea ?  
Thanks.  
sorry for my english.

For information the description of directx12 texture is:  
alignment = 65536  
width = 1936  
height = 1066  
depth = 1  
mip level = 1  
format = DXGI\_FORMAT\_R10G10B10A2\_UNORM

---

<div class="post-metadata">

**Author:** ![berak](https://avatars.discourse-cdn.com/v4/letter/b/85f322/32.png) [@berak](https://forum.opencv.org/u/berak)\
**Post date:** [November 14, 2023, 3:10pm UTC](https://forum.opencv.org/t/copy-directx-12-texture-to-gpumat/15514/2 "2023-11-14T15:10:50Z")

</div>

> [@roy\_c](#):
>
> I haven’t see any reference to directx 12 just 10 or 11.

true ;(

how did you get that image ?

> [@roy\_c](#):
>
> `D3DFMT_A2B10G10R10`

is that your only choice ? (it does not fit any known opencv format)

also, i’d think, that you’d need an opencv enum for the ‘type’ param, like CV\_8UC3, not the dx ‘format’

---

<div class="post-metadata">

**Author:** ![roy\_c](https://avatars.discourse-cdn.com/v4/letter/r/54ee81/32.png) [@roy\_c](https://forum.opencv.org/u/roy_c)\
**Post date:** [November 14, 2023, 3:30pm UTC](https://forum.opencv.org/t/copy-directx-12-texture-to-gpumat/15514/3 "2023-11-14T15:30:59Z")

</div>

The texture come from Unreal backbuffer and the format is  
DXGI\_FORMAT\_R10G10B10A2\_UNORM

I see in a other [forum](https://stackoverflow.com/questions/36337804/direct3d9-convert-a-a2r10g10b10-image-to-a-a8r8g8b8-image) DXGI\_FORMAT\_R10G10B10A2\_UNORM is equivalent to D3DFMT\_A2B10G10R10 wich seem supported by opencv.  
For the type I use getTypeFromDXGI\_FORMAT to convert in opencv format.

---

<div class="post-metadata">

**Author:** ![berak](https://avatars.discourse-cdn.com/v4/letter/b/85f322/32.png) [@berak](https://forum.opencv.org/u/berak)\
**Post date:** [November 14, 2023, 4:02pm UTC](https://forum.opencv.org/t/copy-directx-12-texture-to-gpumat/15514/5 "2023-11-14T16:02:14Z")

</div>

ok, so the type resolves to CV\_8UC4 (directx.cpp:103) [solved, sorry i didn’t get it earlier]…

imo, that would mean, opencv still expects B8G8R8X8 bit layout or similar  
(your memory does not align channels to bytes)

any chance, you can get a more ‘opencv friendly’ layout from unreal ?

---

<div class="post-metadata">

**Author:** ![roy\_c](https://avatars.discourse-cdn.com/v4/letter/r/54ee81/32.png) [@roy\_c](https://forum.opencv.org/u/roy_c)\
**Post date:** [November 16, 2023, 8:31am UTC](https://forum.opencv.org/t/copy-directx-12-texture-to-gpumat/15514/6 "2023-11-16T08:31:53Z")

</div>

I change unreal configuration; now the output format is better understand by openCV.  
Now The colors are correct but image is still “blurred”

 ![Test_screenshot](https://us1.discourse-cdn.com/flex020/uploads/opencv/original/2X/6/623e942dc6b286b4af1ecaac7278b42cc19c8ccb.jpeg)

I saw an example opencv / unreal but they use cvMat. I would avoid cpu memory.

Sorry for my english.

---

<div class="post-metadata">

**Author:** ![crackwitz](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/crackwitz/32/14_2.png) [@crackwitz](https://forum.opencv.org/u/crackwitz)\
**Post date:** [November 16, 2023, 8:56am UTC](https://forum.opencv.org/t/copy-directx-12-texture-to-gpumat/15514/7 "2023-11-16T08:56:01Z")

</div>

strides/steps/whatever don’t seem to match. mess around with that.

perhaps simplify first. I see indications that you’re trying to work with _ **10-bit data** _

make this work with the usual 8-bit per channel formats. when that works, you can figure out how those special formats work.

---

<div class="post-metadata">

**Author:** ![roy\_c](https://avatars.discourse-cdn.com/v4/letter/r/54ee81/32.png) [@roy\_c](https://forum.opencv.org/u/roy_c)\
**Post date:** [November 16, 2023, 12:12pm UTC](https://forum.opencv.org/t/copy-directx-12-texture-to-gpumat/15514/8 "2023-11-16T12:12:36Z")

</div>

> strides/steps/whatever don’t seem to match. mess around with that.

Agreed, but in the last picture GpuMat type is CV\_8UC4 and the directx texture source is DXGI\_FORMAT\_B8G8R8A8\_UNORM  
(CV\_8UC4 = getTypeFromDXGI\_FORMAT(DXGI\_FORMAT\_B8G8R8A8\_UNORM ))

---

<div class="post-metadata">

**Author:** ![cudawarped](https://avatars.discourse-cdn.com/v4/letter/c/9dc877/32.png) [@cudawarped](https://forum.opencv.org/u/cudawarped)\
**Post date:** [November 16, 2023, 12:28pm UTC](https://forum.opencv.org/t/copy-directx-12-texture-to-gpumat/15514/9 "2023-11-16T12:28:12Z")

</div>

@roy_c, @crackwitz is talking about the stride, it looks like you are using the default `size_t step = Mat::AUTO_STEP` but you mentioned directx12 texture has an alignement of alignment = 65536?

---

<div class="post-metadata">

**Author:** ![roy\_c](https://avatars.discourse-cdn.com/v4/letter/r/54ee81/32.png) [@roy\_c](https://forum.opencv.org/u/roy_c)\
**Post date:** [November 16, 2023, 12:52pm UTC](https://forum.opencv.org/t/copy-directx-12-texture-to-gpumat/15514/10 "2023-11-16T12:52:04Z")

</div>

I don’t set the step when I create gpumat so step has the default value `Mat::AUTO_STEP`  
alignment = 65536 is a part of the directx texture description retrieved by  
TextureResource-\>GetDesc() but microsoft documentation is very minimal and says

> Specifies the alignment

---

<div class="post-metadata">

**Author:** ![cudawarped](https://avatars.discourse-cdn.com/v4/letter/c/9dc877/32.png) [@cudawarped](https://forum.opencv.org/u/cudawarped)\
**Post date:** [November 16, 2023, 1:24pm UTC](https://forum.opencv.org/t/copy-directx-12-texture-to-gpumat/15514/11 "2023-11-16T13:24:01Z")

</div>

> [@roy\_c](#):
>
> alignment = 65536 is a part of the directx texture description retrieved by  
> TextureResource-\>GetDesc() but microsoft documentation is very minimal and says

I don’t know anything about DirectX but I would guess if you have a 2D texture there is a row alignment parameter meaning that each row is pitched with a step size \>= width. If you are directly mapping the memory and pitch != width then you need to find out what it is and pass it to the GpuMat.

---

<div class="post-metadata">

**Author:** ![roy\_c](https://avatars.discourse-cdn.com/v4/letter/r/54ee81/32.png) [@roy\_c](https://forum.opencv.org/u/roy_c)\
**Post date:** [November 22, 2023, 7:51pm UTC](https://forum.opencv.org/t/copy-directx-12-texture-to-gpumat/15514/12 "2023-11-22T19:51:53Z")

</div>

I found a solution:  
Make Directx texture with ROW\_MAJOR as layout  
then find the good row pitch  
(very weird with direct X:  
with texture 1936 \* 1066 in R8G8B8A8 =\> pitch is 1936 \* 4 + 128 = 7808 bytes  
with texture 1920 \* 1080 =\> pitch is 1920 \* 4 = 7680 bytes)
