2013-07-16 28 views
0

我正在尋找一個perona malik各向異性過濾器,它看起來像我需要利用gpu的性能原因。長話短說,我想知道如何在xna中使用HLSL來完成GPGPU任務。在XNA中使用HLSL

我正在尋找一些代碼片段來將一些數據移動到GPU上,逐幀處理它,然後返回它,以便我可以用它來做其他事情。

從我讀過,我需要使用 「ping-ponging

編輯

這是我迄今爲止

C#

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

using Microsoft.Xna.Framework; 
using Microsoft.Xna.Framework.Graphics; 
using Microsoft.Xna.Framework.Input; 
using Microsoft.Xna.Framework.Content.Pipeline; 
using Microsoft.Xna.Framework.Content.Pipeline.Graphics; 
using Microsoft.Xna.Framework.Content.Pipeline.Processors; 

namespace HotplateTest 
{ 
    public class XNAClass : Microsoft.Xna.Framework.Game 
    { 
     GraphicsDeviceManager graphics; 
     RenderTarget2D Target; 
     RenderTarget2D Output; 
     Effect physicsEffect; 

     Vector4[] positions; 

     public XNAClass() 
     { 
      graphics = new GraphicsDeviceManager(this); 
     } 

     protected override void Initialize() 
     { 
      Target = new RenderTarget2D(graphics.GraphicsDevice, 10, 10, false, SurfaceFormat.Vector4, DepthFormat.None); 
      Output = new RenderTarget2D(graphics.GraphicsDevice, 10, 10, false, SurfaceFormat.Vector4, DepthFormat.None); 

      positions = new Vector4[100]; 
      for (int i = 0; i < positions.Length; i++) 
      { 
       positions[i] = new Vector4(i); 
      } 

      Target.SetData<Vector4>(positions); 

      base.Initialize(); 
     } 

     protected override void LoadContent() 
     { 
      base.LoadContent(); 
      physicsEffect = Content.Load<Effect>("shader"); 
     } 

     protected override void Update(GameTime gameTime) 
     { 
      base.Update(gameTime); 
     } 

     protected override void Draw(GameTime gameTime) 
     { 

      GraphicsDevice.SetRenderTarget(Target); 
      GraphicsDevice.Clear(Color.Black); 
      physicsEffect.Techniques[0].Passes[0].Apply(); 
      physicsEffect.Parameters["oldPositionTexture"].SetValue(Output); 
      physicsEffect.CurrentTechnique.Passes[0].Apply(); 

      GraphicsDevice.SetRenderTarget(null); 
      Target.GetData<Vector4>(positions); 


      base.Draw(gameTime); 
     } 
    } 
} 

HLSL

texture oldPositionTexture; 

sampler oldPositionSampler = sampler_state 
{ 
    Texture = <oldPositionTexture>; 

    MipFilter = POINT; 
    MinFilter = POINT; 
    MagFilter = POINT; 
    ADDRESSU = CLAMP; 
    ADDRESSV = CLAMP; 
}; 

struct VertexShaderInput 
{ 
    float4 Position : POSITION; 
    float2 Tex : TEXCOORD0; 
}; 

struct VertexShaderOutput 
{ 
    float4 Position : POSITION; 
    float2 Tex : TEXCOORD0; 
}; 

// input texture dimensions 
static const float w = 10; 
static const float h = 10; 

static const float2 pixel = float2(1.0/w, 1.0/h); 
static const float2 halfPixel = float2(pixel.x/2, pixel.y/2); 

VertexShaderOutput VS(VertexShaderInput input) 
{ 
    VertexShaderOutput output = (VertexShaderOutput)0; 

    output.Tex = input.Tex; 

    return output; 
} 

float4 PS1(VertexShaderOutput input) : COLOR0 
{ 
    float2 myV = input.Tex; 
    float myPosAndMass = tex2D(oldPositionSampler, myV); 

    return float4(myPosAndMass, myPosAndMass, myPosAndMass, myPosAndMass); 
} 

technique Technique1 
{ 
    pass Pass0 
    { 
     VertexShader = compile vs_2_0 VS(); 
     PixelShader = compile ps_2_0 PS1(); 
    } 
} 

我得到一個錯誤信息

類型的未處理的異常 'System.ArgumentException' 發生在 Microsoft.Xna.Framework.Graphics.dll

其他信息:類型你正在使用此方法的T爲 此資源的大小無效。

有趣的是,當我在C#代碼中使用Single而不是Vector4時,錯誤消息不會發生。當然,這意味着在位置變量中計算的結果現在是無用的,因爲當它們真的是vector4時它們被解釋爲單一的。

+0

我覺得我失去了着色器是如何工作的一些概念的理解。 – sav

+0

我已經成功地得到這個在[遊戲開發] [1] [1]固定在:http://gamedev.stackexchange.com/questions/59619/gpgpu-programming-using-hlsl-和XNA/59671#59671 – sav

回答

0

C#

using System; 
using System.Collections.Generic; 
using System.Linq; 
using Microsoft.Xna.Framework; 
using Microsoft.Xna.Framework.Audio; 
using Microsoft.Xna.Framework.Content; 
using Microsoft.Xna.Framework.GamerServices; 
using Microsoft.Xna.Framework.Graphics; 
using Microsoft.Xna.Framework.Input; 
using Microsoft.Xna.Framework.Media; 
using Emgu.Util; 
using Emgu.CV; 
using Emgu.CV.Structure; 

namespace HLSLTest 
{ 
    public delegate void Disp(); 

    /// <summary> 
    /// This is the main type for your game 
    /// </summary> 
    public class Game1 : Microsoft.Xna.Framework.Game 
    { 
     Capture cap = new Capture("output.avi"); 
     GraphicsDeviceManager graphics; 
     SpriteBatch spriteBatch; 

     RenderTarget2D renOutput; 

     Vector4[] gpuStore = new Vector4[1920 * 1080]; 

     Effect effect; 
     QuadRender quad; 
     public Game1() 
     { 
      graphics = new GraphicsDeviceManager(this); 
      Content.RootDirectory = "Content"; 
     } 

     /// <summary> 
     /// Allows the game to perform any initialization it needs to before starting to run. 
     /// This is where it can query for any required services and load any non-graphic 
     /// related content. Calling base.Initialize will enumerate through any components 
     /// and initialize them as well. 
     /// </summary> 
     protected override void Initialize() 
     { 
      // TODO: Add your initialization logic here 

      base.Initialize(); 
     } 

     /// <summary> 
     /// LoadContent will be called once per game and is the place to load 
     /// all of your content. 
     /// </summary> 
     protected override void LoadContent() 
     { 
      // Create a new SpriteBatch, which can be used to draw textures. 
      spriteBatch = new SpriteBatch(GraphicsDevice); 
      quad = new QuadRender(GraphicsDevice); 

      renOutput = new RenderTarget2D(GraphicsDevice, 1920, 1080, false, SurfaceFormat.Vector4, DepthFormat.Depth24); 

      effect = Content.Load<Effect>("Shader"); 

      base.LoadContent(); 

      // TODO: use this.Content to load your game content here 
     } 

     /// <summary> 
     /// UnloadContent will be called once per game and is the place to unload 
     /// all content. 
     /// </summary> 
     protected override void UnloadContent() 
     { 
      // TODO: Unload any non ContentManager content here 
     } 

     /// <summary> 
     /// Allows the game to run logic such as updating the world, 
     /// checking for collisions, gathering input, and playing audio. 
     /// </summary> 
     /// <param name="gameTime">Provides a snapshot of timing values.</param> 
     protected override void Update(GameTime gameTime) 
     { 
      // Allows the game to exit 
      if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) 
       this.Exit(); 

      // TODO: Add your update logic here 

      base.Update(gameTime); 
     } 

     /// <summary> 
     /// This is called when the game should draw itself. 
     /// </summary> 
     /// <param name="gameTime">Provides a snapshot of timing values.</param> 
     protected override void Draw(GameTime gameTime) 
     { 
      Image<Bgr, Byte> video = cap.QueryFrame(); 
      using (Image<Bgra, float> vid2 = video.Convert<Bgra, float>()) 
      { 

       Texture2D t = new Texture2D(GraphicsDevice, video.Width, video.Height, false, SurfaceFormat.Vector4); 
       t.SetData<byte>(vid2.Bytes); 

       GraphicsDevice.SetRenderTarget(renOutput); 
       effect.Parameters["Input0"].SetValue(t); 
       quad.RenderFullScreenQuad(effect); 
       for (int i = 0; i < effect.Techniques.Count; i++) 
       { 
        for (int j = 0; j < effect.Techniques[i].Passes.Count; j++) 
        { 
         effect.Techniques[i].Passes[j].Apply(); 
        } 
       } 

       GraphicsDevice.SetRenderTarget(null); 
       renOutput.GetData<Vector4>(gpuStore); 
      } 

      base.Draw(gameTime); 
     } 
    } 
} 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using Microsoft.Xna.Framework; 
using Microsoft.Xna.Framework.Audio; 
using Microsoft.Xna.Framework.Content; 
using Microsoft.Xna.Framework.GamerServices; 
using Microsoft.Xna.Framework.Graphics; 
using Microsoft.Xna.Framework.Input; 
using Microsoft.Xna.Framework.Media; 

namespace HLSLTest 
{ 
    internal sealed class QuadRender 
    { 
     private VertexPositionTexture[] verts; 
     private GraphicsDevice myDevice; 
     private short[] ib = null; 

     /// 
     /// Loads the quad. 
     /// 
     /// 
     public QuadRender(GraphicsDevice device) 
     { 
      myDevice = device;   
      verts = new VertexPositionTexture[] 
      { 
       new VertexPositionTexture 
       (
        new Vector3(0,0,0), 
        new Vector2(1,1) 
       ), 
       new VertexPositionTexture 
       (
        new Vector3(0,0,0), 
        new Vector2(0,1) 
       ), 
       new VertexPositionTexture 
       (
        new Vector3(0,0,0), 
        new Vector2(0,0) 
       ), 
       new VertexPositionTexture 
       (
        new Vector3(0,0,0), 
        new Vector2(1,0) 
       ) 
      }; 

      ib = new short[] { 0, 1, 2, 2, 3, 0 }; 
     }    

     /// 
     /// Draws the fullscreen quad. 
     /// 
     /// 
     public void RenderFullScreenQuad(Effect effect) 
     { 
      effect.CurrentTechnique.Passes[0].Apply(); 
      RenderQuad(Vector2.One * -1, Vector2.One); 
     } 

     public void RenderQuad(Vector2 v1, Vector2 v2) 
     {   

      verts[0].Position.X = v2.X; 
      verts[0].Position.Y = v1.Y; 

      verts[1].Position.X = v1.X; 
      verts[1].Position.Y = v1.Y; 

      verts[2].Position.X = v1.X; 
      verts[2].Position.Y = v2.Y; 

      verts[3].Position.X = v2.X; 
      verts[3].Position.Y = v2.Y; 

      myDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, verts, 0, 4, ib, 0, 2); 
     } 
    } 
} 

HLSL

texture2D Input0; 
sampler2D Input0Sampler = sampler_state 
{ 
    Texture = <Input0>; 
    MinFilter = Point; 
    MagFilter = Point; 
    MipFilter = Point; 
    AddressU = Clamp; 
    AddressV = Clamp; 
}; 

texture2D Input1; 
sampler2D Input1Sampler = sampler_state 
{ 
    Texture = <Input1>; 
    MinFilter = Point; 
    MagFilter = Point; 
    MipFilter = Point; 
    AddressU = Clamp; 
    AddressV = Clamp; 
}; 

texture2D Input2; 
sampler2D Input2Sampler = sampler_state 
{ 
    Texture = <Input2>; 
    MinFilter = Point; 
    MagFilter = Point; 
    MipFilter = Point; 
    AddressU = Clamp; 
    AddressV = Clamp; 
}; 

texture2D Input3; 
sampler2D Input3Sampler = sampler_state 
{ 
    Texture = <Input3>; 
    MinFilter = Point; 
    MagFilter = Point; 
    MipFilter = Point; 
    AddressU = Clamp; 
    AddressV = Clamp; 
}; 


struct VertexShaderInput 
{ 
    float4 Position : POSITION0; 
    float2 TextureCoordinate : TEXCOORD0; 
}; 

struct VertexShaderOutput 
{ 
    float4 Position : POSITION0; 
    float2 TextureCoordinate : TEXCOORD0; 
}; 

struct PixelShaderOutput 
{ 
    // TODO: Optionally add/remove output indices to match GPUProcessor.numOutputs 
    float4 Index0 : COLOR0; 
}; 

// input texture dimensions 
static const float w = 1920; 
static const float h = 1080; 

static const float2 pixel = float2(1.0/w, 1.0/h); 
static const float2 halfPixel = float2(pixel.x/2, pixel.y/2); 


VertexShaderOutput VertexShaderFunction(VertexShaderInput vsInput) 
{ 
    //VertexShaderOutput output; 

    //output.Position = vsInput.Position; 
    //output.TextureCoordinate = vsInput.TextureCoordinate; 

    VertexShaderOutput output; 
    vsInput.Position.x = vsInput.Position.x - 2*halfPixel.x; 
    vsInput.Position.y = vsInput.Position.y + 2*halfPixel.y; 
    output.Position = vsInput.Position; 
    output.TextureCoordinate = vsInput.TextureCoordinate ; 
    return output; 


    //return output; 
} 

PixelShaderOutput PixelShaderFunction(VertexShaderOutput psInput) 
{ 
    PixelShaderOutput output; 
    // TODO: Optionally add/remove samples to match GPUProcessor.numInputs 
    float4 input0 = tex2D(Input0Sampler, psInput.TextureCoordinate); 
    //float4 input1 = tex2D(Input0Sampler, psInput.TextureCoordinate); 
    //float4 input2 = tex2D(Input0Sampler, psInput.TextureCoordinate); 
    //float4 input3 = tex2D(Input0Sampler, psInput.TextureCoordinate); 

    // your calculations go here 

    // TODO: Optionally add/remove outputs to match GPUProcessor.numOutputs 
    output.Index0 = input0;//float4(100,200,13,24);//input0; 

    return output; 
} 

technique Verlet 
{ 
    pass Go 
    { 
     VertexShader = compile vs_2_0 VertexShaderFunction(); 
     PixelShader = compile ps_2_0 PixelShaderFunction(); 
    } 
}