从 CUDA 更新 D3D9 纹理
Update a D3D9 texture from CUDA
我正在开发一个集成了 WPF、Direct3D9(使用 Microsoft 的 D3DImage WPF class)和 CUDA(我需要能够在 GPU 上为 D3DImage 生成纹理)的原型。
问题是,CUDA 没有更新我的纹理。没有返回错误代码,纹理保持不变。即使我在自己写完后阅读,我也看不到任何变化。如何更新我的 D3D9 纹理?
我什至没有 运行 任何 CUDA 内核,出于调试目的,我只使用 cuMemcpy2D API 通过从 CPU 复制一些虚假数据来写入 CUDA 内存。
这是代码,它是 C# 但我在评论中放置了本机 APIs:
static void updateTexture( Texture tx )
{
var size = tx.getSize();
using( CudaDirectXInteropResource res = new CudaDirectXInteropResource( tx.NativePointer, CUGraphicsRegisterFlags.None, CudaContext.DirectXVersion.D3D9 ) ) // cuGraphicsD3D9RegisterResource
{
res.Map(); // = cuGraphicsMapResources
using( CudaArray2D arr = res.GetMappedArray2D( 0, 0 ) ) // cuGraphicsSubResourceGetMappedArray, cuArrayGetDescriptor. The size is correct here, BTW
{
// Debug code below - don't run any kernels for now, just call cuMemcpy2D to write the GPU memory
uint[] arrWhite = new uint[ size.Width * size.Height ];
for( int i = 0; i < arrWhite.Length; i++ )
arrWhite[ i ] = 0xFF0000FF;
arr.CopyFromHostToThis( arrWhite ); // cuMemcpy2D
uint[] test = new uint[ size.Width * size.Height ];
arr.CopyFromThisToHost( test ); // The values here are correct
}
res.UnMap(); // cuGraphicsUnmapResources
}
tx.AddDirtyRectangle();
// Map again and check what's in the resource
using( CudaDirectXInteropResource res = new CudaDirectXInteropResource( tx.NativePointer, CUGraphicsRegisterFlags.None, CudaContext.DirectXVersion.D3D9 ) )
{
res.Map();
using( CudaArray2D arr = res.GetMappedArray2D( 0, 0 ) )
{
uint[] test = new uint[ size.Width * size.Height ];
arr.CopyFromThisToHost( test ); // All zeros :-(
Debug.WriteLine( "First pixel: {0:X}", test[ 0 ] );
}
res.UnMap();
}
}
正如评论者所暗示的,我已经尝试创建一个 CudaDirectXInteropResource 实例以及 D3D 纹理。
成功了。
这违反直觉且未记录,但看起来 cuGraphicsUnregisterResource 破坏了新写入的数据。
至少在我的机器上有 GeForce GTX 960、Cuda 7.0 和 Windows 8.1 x64.
因此,解决方案 — 每个纹理调用一次 cuGraphicsD3D9RegisterResource,并使用 cuGraphicsMapResources / cuGraphicsUnmapResources API 允许 CUDA 访问纹理数据。
我正在开发一个集成了 WPF、Direct3D9(使用 Microsoft 的 D3DImage WPF class)和 CUDA(我需要能够在 GPU 上为 D3DImage 生成纹理)的原型。
问题是,CUDA 没有更新我的纹理。没有返回错误代码,纹理保持不变。即使我在自己写完后阅读,我也看不到任何变化。如何更新我的 D3D9 纹理?
我什至没有 运行 任何 CUDA 内核,出于调试目的,我只使用 cuMemcpy2D API 通过从 CPU 复制一些虚假数据来写入 CUDA 内存。
这是代码,它是 C# 但我在评论中放置了本机 APIs:
static void updateTexture( Texture tx )
{
var size = tx.getSize();
using( CudaDirectXInteropResource res = new CudaDirectXInteropResource( tx.NativePointer, CUGraphicsRegisterFlags.None, CudaContext.DirectXVersion.D3D9 ) ) // cuGraphicsD3D9RegisterResource
{
res.Map(); // = cuGraphicsMapResources
using( CudaArray2D arr = res.GetMappedArray2D( 0, 0 ) ) // cuGraphicsSubResourceGetMappedArray, cuArrayGetDescriptor. The size is correct here, BTW
{
// Debug code below - don't run any kernels for now, just call cuMemcpy2D to write the GPU memory
uint[] arrWhite = new uint[ size.Width * size.Height ];
for( int i = 0; i < arrWhite.Length; i++ )
arrWhite[ i ] = 0xFF0000FF;
arr.CopyFromHostToThis( arrWhite ); // cuMemcpy2D
uint[] test = new uint[ size.Width * size.Height ];
arr.CopyFromThisToHost( test ); // The values here are correct
}
res.UnMap(); // cuGraphicsUnmapResources
}
tx.AddDirtyRectangle();
// Map again and check what's in the resource
using( CudaDirectXInteropResource res = new CudaDirectXInteropResource( tx.NativePointer, CUGraphicsRegisterFlags.None, CudaContext.DirectXVersion.D3D9 ) )
{
res.Map();
using( CudaArray2D arr = res.GetMappedArray2D( 0, 0 ) )
{
uint[] test = new uint[ size.Width * size.Height ];
arr.CopyFromThisToHost( test ); // All zeros :-(
Debug.WriteLine( "First pixel: {0:X}", test[ 0 ] );
}
res.UnMap();
}
}
正如评论者所暗示的,我已经尝试创建一个 CudaDirectXInteropResource 实例以及 D3D 纹理。 成功了。
这违反直觉且未记录,但看起来 cuGraphicsUnregisterResource 破坏了新写入的数据。 至少在我的机器上有 GeForce GTX 960、Cuda 7.0 和 Windows 8.1 x64.
因此,解决方案 — 每个纹理调用一次 cuGraphicsD3D9RegisterResource,并使用 cuGraphicsMapResources / cuGraphicsUnmapResources API 允许 CUDA 访问纹理数据。