在 Direct3D12 中使用 Stream Output

本文详细介绍了在Direct3D12中使用Stream Output功能进行Skining Animation的优化,通过对比D3D11和D3D12的差异,分析了在D3D12中创建Graphics Pipeline State时遇到的错误,并提供了解决方案,强调了Shader输出Semantic的一致性和无Geometry Shader时的处理方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一. 引子

从 DirectX10 开始 Direct3D 引入了 Stream Output 功能(下称 SO ),它能利用 GPU 进行一些模型操作,其中利用 SO 受益最大的就是 Skinning Animation。在没有 SO 之前蒙皮动画要不就是由 CPU 完成,要不就是每次渲染的时候都需要重新做一次蒙皮,这在多光源光照渲染 Shadow Map 中是非常耗时的,引入 SO 之后只要进行一次蒙皮动画所得到的 Vertex Buffer 可以重用,这样既节省了 CPU 又获得了 GPU 加速。

二.一切从 CreateGeometryShaderWithStreamOutput 说起

1. D3D11 / D3D10 与 Stream Output

D3D10 和 D3D11 使用 SO 的时候需要调用 CreateGeometryShaderWithStreamOutput 函数。虽然看函数名这个函数是要创建一个 Geometry Shader(下称 GS ),但是在实际使用的时候并不一定需要给出 GS 的 Binary Code。像 Skinning 这种操作实际上只需要在 Vertex Shader(下称 VS ) 中就能完成,根本不需要 GS。在调用 CreateGeometryShaderWithStreamOutput 的时候 pShaderBytecode 参数给的是 VS 的 Binary Code,创建好的 ID3D11GeometryShader 对象其实并没有实际代码,只是用来对应 SO 之后数据输出的信息。
把 VB / IB / VS / GS 设置进渲染管

首先,您需要了解以下几个概念: - `ID3D11VideoDevice`:Direct3D 11视频设备接口,用于创建视频编解码器和视频处理器。 - `ID3D11VideoProcessor`:Direct3D 11视频处理器接口,用于对视频进行处理,如缩放、旋转、色彩空间转换等。 - `ID3D11VideoProcessorEnumerator`:Direct3D 11视频处理器枚举接口,用于枚举支持的视频处理器和视频处理器特性。 - `DXVAHD_VPCAPS`:视频处理器能力结构体,用于描述视频处理器的特性。 接下来是 `GetVideoProcessBltState` 的示例代码: ```c++ // 获得 D3D 设备和设备上下文 ID3D11Device* pD3DDevice = ...; ID3D11DeviceContext* pD3DDeviceContext = ...; // 创建视频设备 ID3D11VideoDevice* pVideoDevice = nullptr; HRESULT hr = pD3DDevice->QueryInterface(__uuidof(ID3D11VideoDevice), (void**)&pVideoDevice); if (FAILED(hr)) { // 处理错误 } // 创建视频处理器枚举器 ID3D11VideoProcessorEnumerator* pVideoProcessorEnumerator = nullptr; DXVAHDDDI_CONTENT_DESC contentDesc = {}; contentDesc.InputFrameFormat = DXVAHDDDI_FRAME_FORMAT_PROGRESSIVE; contentDesc.InputWidth = 1920; contentDesc.InputHeight = 1080; contentDesc.OutputFrameRate.Numerator = 1; contentDesc.OutputFrameRate.Denominator = 1; contentDesc.OutputWidth = 1920; contentDesc.OutputHeight = 1080; contentDesc.Usage = DXVAHDDDI_FILTER_BRIGHTNESS | DXVAHDDDI_FILTER_CONTRAST | DXVAHDDDI_FILTER_HUE | DXVAHDDDI_FILTER_SATURATION; hr = pVideoDevice->CreateVideoProcessorEnumerator(&contentDesc, &pVideoProcessorEnumerator); if (FAILED(hr)) { // 处理错误 } // 创建视频处理器 ID3D11VideoProcessor* pVideoProcessor = nullptr; DXVAHD_STREAM_STATE_STREAM_DATA streamData = {}; streamData.Enable = TRUE; streamData.OutputIndex = 0; streamData.Transform.AffineMatrix.e11 = 1.0f; streamData.Transform.AffineMatrix.e22 = 1.0f; streamData.Transform.AffineMatrix.e33 = 1.0f; streamData.Transform.AffineMatrix.e44 = 1.0f; hr = pVideoDevice->CreateVideoProcessor(pVideoProcessorEnumerator, 0, &pVideoProcessor); if (FAILED(hr)) { // 处理错误 } // 获取视频处理器能力 DXVAHD_VPCAPS videoProcessorCaps = {}; hr = pVideoProcessorEnumerator->GetVideoProcessorCaps(&videoProcessorCaps); if (FAILED(hr)) { // 处理错误 } // 获取视频处理器状态 DXVAHD_STREAM_STATE_BRIGHTNESS stateBrightness = {}; DXVAHD_STREAM_STATE_CONTRAST stateContrast = {}; DXVAHD_STREAM_STATE_HUE stateHue = {}; DXVAHD_STREAM_STATE_SATURATION stateSaturation = {}; UINT numData = 4; DXVAHD_STREAM_DATA streamDataArray[4] = { { &stateBrightness, sizeof(stateBrightness), 0 }, { &stateContrast, sizeof(stateContrast), 0 }, { &stateHue, sizeof(stateHue), 0 }, { &stateSaturation, sizeof(stateSaturation), 0 } }; hr = pVideoProcessor->GetVideoProcessBltState(DXVAHD_STREAM_STATE_BRIGHTNESS | DXVAHD_STREAM_STATE_CONTRAST | DXVAHD_STREAM_STATE_HUE | DXVAHD_STREAM_STATE_SATURATION, numData, streamDataArray); if (FAILED(hr)) { // 处理错误 } // 释放资源 pVideoProcessor->Release(); pVideoProcessorEnumerator->Release(); pVideoDevice->Release(); ``` 在这段代码中,我们首先创建了一个视频设备 `ID3D11VideoDevice`,然后创建了一个视频处理器枚举器 `ID3D11VideoProcessorEnumerator`,用于枚举支持的视频处理器和视频处理器特性。接着,我们创建一个视频处理器 `ID3D11VideoProcessor`,并使用 `GetVideoProcessorCaps` 获取视频处理器能力结构体 `DXVAHD_VPCAPS`。最后,我们通过 `GetVideoProcessBltState` 获取视频处理器状态,包括亮度、对比度、色调和饱和度等。 需要注意的是,这段示例代码中省略了一些错误处理代码,实际使用时需要根据需要添加。另外,这里使用的是 DirectX 11 中的视频处理接口,如果您使用的是其他版本的 DirectX,可能需要做一些调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值