2015-06-19 6 views
3

Я работаю над прототипом, который объединяет WPF, Direct3D9 (с использованием класса D3DImage WPF от Microsoft) и CUDA (мне нужно иметь возможность генерировать текстуру для D3DImage на графическом процессоре).Обновите текстуру D3D9 от CUDA

Проблема в том, что CUDA не обновляет мою текстуру. Коды ошибок не возвращаются, текстура остается неизменной. Даже если я прочитаю после своей собственной записи, я не вижу никаких изменений. Как обновить текстуру D3D9?

Я даже не запускаю ядра CUDA для целей отладки. Я использую только cuMemcpy2D API для записи CUDA-памяти путем копирования некоторых поддельных данных из CPU.

Вот код, это C#, но я поставил родной API, в комментариях:

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(); 
    } 
} 
+0

Вы пробовали разные CUGraphicsRegisterFlags, такие как WriteDiscard или SurfaceLDST, чтобы явно указать cuda, что вы напишете текстуру? И CudaDirectXInteropResource должен создаваться только один раз в жизни вашей текстуры DirectX (для регистрации ресурсов стоит дорого) – kunzmi

+0

@kunzmi спасибо, вторая часть вашего комментария (где вы сказали о том, что вы думаете, это просто проблема производительности с моим кодом), была действительно полезно. – Soonts

ответ

3

Как намекают комментатора, я попытался создать один экземпляр CudaDirectXInteropResource вместе с D3D текстурой. Это сработало.

Это контр-интуитивно понятный и недокументированный, но похоже, что cuGraphicsUnregisterResource уничтожает вновь записанные данные. По крайней мере, на моей машине с GeForce GTX 960, Cuda 7.0 и Windows 8.1 x64.

Итак, решение - вызовите cuGraphicsD3D9RegisterResource один раз для каждой текстуры и используйте cuGraphicsMapResources/cuGraphicsUnmapResources API, чтобы позволить CUDA получать доступ к данным текстуры.

Смежные вопросы