D3D11和D3D12共享资源

这篇具有很好参考价值的文章主要介绍了D3D11和D3D12共享资源。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

最近碰到个伪需求: 游戏串流。 游戏引擎用D3D12渲染, 再把游戏画面做视频编码, 通过网络发送到远端做解码显示。

第一反应就是走全GPU的流程, 不要用CPU把显存里的数据拷来拷去。 所以先获取渲染完的D3D12的frame buffer, 然后送给Intel MediaSDK去做编码。 查了一下MediaSDK文档, 只支持D3D11的输入buffer, 需要想办法把D3D12 Resource转换成D3D11 Texture2D。 可以试试D3D11/D3D12的Texture2D资源共享。查了一下网上的讨论的帖子 Sharing ID3D11Buffer and ID3D12Resource,微软自家的DirectX不同版本间可以用CreateSharedHandle/OpenSharedResource来互相访问。

DX12我不熟,先找个最简单的DX12 Texture的例子。我选了微软官方的例子 https://github.com/microsoft/DirectX-Graphics-Samples/tree/master/Samples/Desktop/D3D12HelloWorld/src/HelloTexture

有关的Texture2D的初始化代码在这里,m_texture就是一块黑白棋盘格样式的Texture2D,所有的初始化和像素填充都是基于D3D12的API来完成。 然后在主循环里在WM_PAINT消息OnRender()函数里把m_texture贴到一个三角形上并显示

//创建m_texture, 一块256x256 R8G8B8A8的texture2D的资源, GPU访问
        // Describe and create a Texture2D.
        D3D12_RESOURCE_DESC textureDesc = {};
        textureDesc.MipLevels = 1;
        textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
        textureDesc.Width = TextureWidth;
        textureDesc.Height = TextureHeight;
        textureDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
        textureDesc.DepthOrArraySize = 1;
        textureDesc.SampleDesc.Count = 1;
        textureDesc.SampleDesc.Quality = 0;
        textureDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;

        ThrowIfFailed(m_device->CreateCommittedResource(
            &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
            D3D12_HEAP_FLAG_NONE,
            &textureDesc,
            D3D12_RESOURCE_STATE_COPY_DEST,
            nullptr,
            IID_PPV_ARGS(&m_texture)));




        const UINT64 uploadBufferSize = GetRequiredIntermediateSize(m_texture.Get(), 0, 1);

//创建textureUploadHeap, 一块CPU可以读写的staging buffer
        // Create the GPU upload buffer.
        ThrowIfFailed(m_device->CreateCommittedResource(
            &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
            D3D12_HEAP_FLAG_NONE,
            &CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize),
            D3D12_RESOURCE_STATE_GENERIC_READ,
            nullptr,
            IID_PPV_ARGS(&textureUploadHeap)));

//生成一块黑白相间的棋盘格样式的图像
        // Copy data to the intermediate upload heap and then schedule a copy 
        // from the upload heap to the Texture2D.
        std::vector<UINT8> texture = GenerateTextureData();

        D3D12_SUBRESOURCE_DATA textureData = {};
        textureData.pData = &texture[0];
        textureData.RowPitch = TextureWidth * TexturePixelSize;
        textureData.SlicePitch = textureData.RowPitch * TextureHeight;

//将棋盘格式的图像填充进textureUploadHeap里,再拷贝进m_texture内
        UpdateSubresources(m_commandList.Get(), m_texture.Get(), textureUploadHeap.Get(), 0, 0, 1, &textureData);
        m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_texture.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE));

运行的输出, 可以看到三角形上贴的纹理是黑白棋盘格

D3D11和D3D12共享资源,Direct3D,DirectX11,DirectX12

接下来要做的是按照Sharing ID3D11Buffer and ID3D12Resource的流程在m_texture初始化后做一个和D3D11 Texture2D的共享,并且通过D3D11的API函数修改这个m_texture的像素纹理

1. 修改创建mtexture的参数,设为可共享

  • 这里需要修改D3D12_RESOURCE_DESC的Flags属性为D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS
  • 同时ID3D12Device::CreateCommittedResource()的HeapFlags参数设为D3D12_HEAP_FLAG_SHARED
		// Describe and create a Texture2D.
		D3D12_RESOURCE_DESC textureDesc = {};
		textureDesc.MipLevels = 1;
		textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
		textureDesc.Width = TextureWidth;
		textureDesc.Height = TextureHeight;
		textureDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS;
		textureDesc.DepthOrArraySize = 1;
		textureDesc.SampleDesc.Count = 1;
		textureDesc.SampleDesc.Quality = 0;
		textureDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;

		ThrowIfFailed(m_device->CreateCommittedResource(
			&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
			D3D12_HEAP_FLAG_SHARED,
			&textureDesc,
			D3D12_RESOURCE_STATE_COPY_DEST, // D3D12_RESOURCE_STATE_COPY_DEST,
			nullptr,
			IID_PPV_ARGS(&m_texture)));

2. 为m_texture创建一个共享句柄m_sharedTextureHandle

		HRESULT hr;
		HANDLE m_sharedTextureHandle;
		ThrowIfFailed(hr = m_device->CreateSharedHandle(
			m_texture.Get(),
			nullptr,
			GENERIC_ALL,
			nullptr,
			&m_sharedTextureHandle));

3. 创建一个新的d3d11 device和context,

		static D3D_FEATURE_LEVEL FeatureLevels[] = {
			D3D_FEATURE_LEVEL_11_1,
			D3D_FEATURE_LEVEL_11_0,
			D3D_FEATURE_LEVEL_10_1,
			D3D_FEATURE_LEVEL_10_0
		};

		IDXGIFactory2* DxgiFactory;
		IDXGIAdapter* DxgiAdapter;
		DXGI_ADAPTER_DESC DxgiAdapterDesc;
		ID3D11Texture2D* Texture;

		ID3D11Device* D3d11Device;
		D3D_FEATURE_LEVEL FeatureLevel;
		ID3D11DeviceContext* D3d11DeviceContext;

		hr = CreateDXGIFactory2(0, IID_PPV_ARGS(&DxgiFactory));
		hr = DxgiFactory->EnumAdapters(0, &DxgiAdapter);
		hr = DxgiAdapter->GetDesc(&DxgiAdapterDesc);
		hr = D3D11CreateDevice(DxgiAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, D3D11_CREATE_DEVICE_DEBUG, FeatureLevels, 4, D3D11_SDK_VERSION, &D3d11Device, &FeatureLevel, &D3d11DeviceContext);

创建一个和m_texture一样大小的D3D11 Texture2D对象,填充成灰红蓝绿色,等下用ID3D11DeviceContext::CopyResource()来覆盖d3d12的m_texture,用来验证共享的texture2D资源是否成功

//这里需要创建一个和DX12纹理资源相同尺寸的Texture2D
//图省事,没有提取前面DX12的纹理资源的尺寸,直接定义个相同的尺寸
#define SHARED_TEXTURE_WIDTH   256
#define SHARED_TEXTURE_HEIGHT  256

		CD3D11_TEXTURE2D_DESC TextureDesc(DXGI_FORMAT_R8G8B8A8_UNORM, SHARED_TEXTURE_WIDTH, SHARED_TEXTURE_HEIGHT, 1, 1);
		//TextureDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED | D3D11_RESOURCE_MISC_SHARED_NTHANDLE;

		unsigned long texture_data_1[SHARED_TEXTURE_WIDTH * SHARED_TEXTURE_HEIGHT];

		D3D11_SUBRESOURCE_DATA Data = {};
		//将texture的左上,右上,左下,右下分别填充成灰红绿蓝
		for (int i = 0; i < SHARED_TEXTURE_HEIGHT; i++)
		{
			for (int j = 0; j < SHARED_TEXTURE_WIDTH; j++)
			{
				if (i >= SHARED_TEXTURE_HEIGHT / 2)
				{
					if (j >= SHARED_TEXTURE_WIDTH / 2)
					{
						texture_data_1[i * SHARED_TEXTURE_WIDTH + j] = 0xFF00FF00;		//G	Formet:0xAaBbGgRr
					}
					else
					{
						texture_data_1[i * SHARED_TEXTURE_WIDTH + j] = 0xFFFF0000;		//B
					}
				}
				else
				{
					if (j >= SHARED_TEXTURE_WIDTH / 2)
					{
						texture_data_1[i * SHARED_TEXTURE_WIDTH + j] = 0xFF0000FF;		//R
					}
					else
					{
						texture_data_1[i * SHARED_TEXTURE_WIDTH + j] = 0xFF808080;		//Gray
					}
				}
			}
		}
		Data.pSysMem = texture_data_1;
		Data.SysMemPitch = SHARED_TEXTURE_WIDTH * sizeof(unsigned long);		//п
		Data.SysMemSlicePitch = 0;

		hr = D3d11Device->CreateTexture2D(&TextureDesc, &Data, &Texture);

4. 在d3d11下用m_texture的共享句柄创建一个共享设备, 对应的是D3D11Texture2D类型的SharedTexture

		ID3D11Device1* pDevice1;

		hr = D3d11Device->QueryInterface(__uuidof(ID3D11Device1), (void**)&pDevice1);

		ComPtr<ID3D11Texture2D> SharedTexture;
		hr = pDevice1->OpenSharedResource1(m_sharedTextureHandle, IID_PPV_ARGS(SharedTexture.GetAddressOf()));

5. 修改SharedTexture的内容, 对应的D3D12的m_texture的内容也同步变了。

		D3d11DeviceContext->CopyResource(SharedTexture.Get(), Texture);
		D3d11DeviceContext->Flush();

最后运行一下修改过的程序, 可以看到三角形上的纹理变成了我们在D3D11下面创建的灰红蓝绿的纹理,看来共享成功了

D3D11和D3D12共享资源,Direct3D,DirectX11,DirectX12

 搞定收工

最后老规矩,代码奉上,仅供参考

https://gitee.com/tisandman/dx12-hello-texture/tree/master

PS:文章来源地址https://www.toymoban.com/news/detail-759027.html

  • D3D12和D3D11下面的command queue应该是2个独立的queue, 所以操作D3D11的命令一定等D3D12的CommandList执行完了以后再执行,否则会互相影响 (我开始的时候把D3D11的所有操作放到了 D3D12 commandQueue的ExecuteCommandLists()前面了,结果所有的D3D11下的操作先执行,D3D12的操作后执行,导致对D3D11 Texture2D的所有像素改动操作都被覆盖了,查了好久代码)。话说也没有自带个靠谱的同步信号量
  • 微软自家的框架之间的共享真是好弄,毕竟是同一家的东西。
  • D3D12的编程思路一点不像以前版本的DirectX, 反倒是和前面的Vulkan的操作顺序很像...

到了这里,关于D3D11和D3D12共享资源的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • d3d12龙书阅读----数学基础 向量代数、矩阵代数、变换

    d3d12龙书阅读----数学基础 向量代数、矩阵代数、变换 directx 采用左手坐标系 点积与叉积 点积与叉积的正交化 使用点积进行正交化 使用叉积进行正交化 矩阵与矩阵乘法 转置矩阵 单位矩阵 逆矩阵 矩阵行列式 变换 旋转矩阵 坐标变换 利用DirectXMath库进行向量运算、矩阵运算以

    2024年02月19日
    浏览(31)
  • d3d12龙书阅读----Direct3D的初始化

    使用d3d我们可以对gpu进行控制与编程,以硬件加速的方式来完成3d场景的渲染,d3d层与硬件驱动会将相应的代码转换成gpu可以执行的机器指令,与之前的版本相比,d3d12大大减少了cpu的开销,同时也改进了对多线程的支持,但是使用的api也更加复杂。 接下来,我们将先介绍在

    2024年03月12日
    浏览(33)
  • DirectX12(D3D12)基础教程(二十一)—— PBR:IBL 的数学原理(1/5)

      2023年来了,令人闹心伤身的疫情也暂告一段落了。感慨之余,其实我也挺惆怅,这个系列教程还能继续下去吗?或者我自己还能坚持多久,我不知道。因为我也天天徘徊在失业的边缘,年纪大了被人嫌弃,学历低被人嫌弃,身体稍差也被人嫌弃,忽然发现我已不是当初那

    2023年04月08日
    浏览(44)
  • DirectX12(D3D12)基础教程(二十一)—— PBR:IBL 的数学原理(5/5)镜面反射积分项2及光照合成

    3.5.4、根据 Epic 近似假设进一步拆分积分项为两部分之积   通过之前的步骤,实际上以及得到了我们想要的镜面反射项的蒙特卡洛积分重要性采样的形式,并且根据我们的假设认为视方向等于法线方向,实际上以及可以编码实现这个积分计算过程,而且依据假设我们不再需

    2023年04月08日
    浏览(33)
  • 【Samba】win 11 不允许一个用户使用一个以上用户名与服务器或共享资源的多重连接

    之前使用两个用户登录过,没有释放 1、打开cmd命令窗口: net use * /del /y 命令中断开所有连接. 2、重新登录 删除后重启

    2024年02月04日
    浏览(48)
  • nodejs中的共享资源和锁

    在Node.js中,如果你使用锁来同步代码,通常是为了防止多个线程或进程同时访问共享资源,这可能导致数据不一致或其他问题。然而,Node.js本身并不是一个多线程环境,而是单线程的。因此,你通常不会在Node.js中使用锁来同步线程,而是使用锁来同步异步操作。 如果你正在

    2024年01月22日
    浏览(32)
  • 云计算资源供应模型是指云计算所提供的资源供应方式,主要包括共享型资源和专属型资源。

    作者:禅与计算机程序设计艺术 云计算是一种将大数据、机器学习等技术应用到互联网的数据中心中,向用户提供更高级的计算服务的一种服务模式。其特点之一就是利用计算机硬件、网络和软件资源池作为计算基础设施(Infrastructure as a Service, IaaS)或平台服务(Platform as

    2024年02月06日
    浏览(30)
  • 【开源】基于JAVA的教学资源共享平台

    基于JAVA+Vue+SpringBoot+MySQL的教学资源共享平台,包含了课程管理、课程课件、授课中心、作业发布、课程评价、课程质量分析、交流互动模块,还包含系统自带的用户管理、部门管理、角色管理、菜单管理、日志管理、数据字典管理、文件管理、图表展示等基础模块,教学资源

    2024年01月19日
    浏览(42)
  • 进程和线程的区别 && 线程之间共享的资源

    线程和进程都是操作系统中的执行单位,但它们在以下几个方面存在区别: 1.执行环境:线程和进程都有自己的执行上下文,包括程序计数器、寄存器和栈,可以独立执行指令。 2.并发性:线程和进程都可以实现并发执行,提高系统资源利用率。 3.调度:线程和进程都需要操

    2024年02月07日
    浏览(31)
  • HTTP 第六章 跨资源共享(CORS)

    跨源资源共享(CORS,或通俗地译为跨域资源共享)是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其他源(域、协议或端口),使得浏览器允许这些源访问加载自己的资源。跨源资源共享还通过一种机制来检查服务器是否会允许要发送的真实请求,该

    2024年02月22日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包