2016-03-26 10 views
1

Şu anda bir CUDA programından bir çıktı biçimini, oluşturmada kullanmak üzere GL_TEXTURE_2D'a bağlamaya çalışıyorum. CUDA'nın çıkış türünden endişe duymuyorum (ister bir dizi ister yüzey olsun, programı buna göre uyarlayabilirim).ManagedCUDA içinde CUDA çıkış dizisini/yüzeyini GL yapısına bağlama

Soru şu ki, bunu nasıl yaparım? (şu anki kodum çıkış dizisini sistem belleğine kopyalar ve GL.TexImage2D ile tekrar GPU'ya yükler, ki bu da son derece verimsizdir - bu iki kod parçasını devre dışı bıraktığımda, saniyede yaklaşık 300 çekirdek yürütme sayısı 400)

... zaten en azından CUDA bir GL doku bağlamak için test kod biraz var, ama ben bile ondan aygıt işaretçisi almanız mümkün değilim

ctx = CudaContext.CreateOpenGLContext(CudaContext.GetMaxGflopsDeviceId(), CUCtxFlags.SchedAuto); 

uint textureID = (uint)GL.GenTexture(); //create a texture in GL 
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); 
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); 
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Rgba, PixelType.UnsignedByte, null); //allocate memory for the texture in GL 

CudaOpenGLImageInteropResource resultImage = new CudaOpenGLImageInteropResource(textureID, CUGraphicsRegisterFlags.WriteDiscard, CudaOpenGLImageInteropResource.OpenGLImageTarget.GL_TEXTURE_2D, CUGraphicsMapResourceFlags.WriteDiscard); //using writediscard because the CUDA kernel will only write to this texture 

//then, as far as I understood the ManagedCuda example, I have to do the following when I call my kernel 
//(done without a CudaGraphicsInteropResourceCollection because I only have one item) 
resultImage.Map(); 
var ptr = resultImage.GetMappedPointer(); //this crashes 
kernelSample.Run(ptr); //pass the pointer to the kernel so it knows where to write 
resultImage.UnMap(); 

Aşağıdaki özel durum işaretçisini almaya çalışırken atılır:

ErrorNotMappedAsPointer: This indicates that a mapped resource is not available for access as a pointer. 

Bunu düzeltmek için ne yapmam gerekiyor?

Bu istisna çözülse bile, sorumun diğer bölümünü nasıl çözebilirim; Yani, çekirdeğimde edinilen işaretçi ile nasıl çalışırım? Bunun için bir yüzey kullanabilir miyim? Bir keyfi dizi (işaretçi aritmetik) olarak erişin?

Düzenleme: Örnek, this örneğiyle, görünüşe göre, her çekirdeği çağıran ve eşleme işlevini çağırdığımda kaynağı eşlemeye gerek duymuyorum. Ama bu nasıl ManangedCUDA'ya çevrilir?

cevap

0

Bulduğum örnek sayesinde, bunu ManagedCUDA'ya çevirebildim (kaynak koduna göz atarak ve etrafta dolaştıktan sonra), ve bunun gerçekten benim 300 saniyeden başlayarak örneklemlerimi gerçekten geliştirdiğini duyurmaktan mutluluk duyuyorum. 400 :)

Görünüşe göre 3 boyutlu bir dizi kullanmak gerekiyor (2B dizileri kullanarak ManagedCUDA'da aşırı yüklenme görmedim) ama bu gerçekten önemli değil - Ben tam olarak bir 3D dizi/doku kullanıyorum 1 derin.

id = GL.GenTexture(); 
GL.BindTexture(TextureTarget.Texture3D, id); 
GL.TexParameter(TextureTarget.Texture3D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); 
GL.TexParameter(TextureTarget.Texture3D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); 
GL.TexImage3D(TextureTarget.Texture3D, 0, PixelInternalFormat.Rgba, width, height, 1, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero); //allocate memory for the texture but do not upload anything 

CudaOpenGLImageInteropResource resultImage = new CudaOpenGLImageInteropResource((uint)id, CUGraphicsRegisterFlags.SurfaceLDST, CudaOpenGLImageInteropResource.OpenGLImageTarget.GL_TEXTURE_3D, CUGraphicsMapResourceFlags.WriteDiscard); 
resultImage.Map(); 
CudaArray3D mappedArray = resultImage.GetMappedArray3D(0, 0); 
resultImage.UnMap(); 

CudaSurface surfaceResult = new CudaSurface(kernelSample, "outputSurface", CUSurfRefSetFlags.None, mappedArray); //nothing needs to be done anymore - this call connects the 3D array from the GL texture to a surface reference in the kernel 

Çekirdek kodu: yüzey outputSurface;

__global__ void Sample() { 
    ... 
    surf3Dwrite(output, outputSurface, pixelX, pixelY, 0); 
}