4

詳細に入る前に、問題の概要を説明します。

RWStructuredBuffers を使用して、計算シェーダー (CS) の出力を格納します。頂点シェーダーとピクセル シェーダーは RWStructuredBuffers から読み取ることができないため、StructuredBuffer を同じスロット (u0/t0) と (u4/t4) にマップします。

cbuffer cbWorld : register (b1) 
{
    float4x4 worldViewProj;
    int dummy;
}   

struct VS_IN
{
    float4 pos : POSITION;
    float4 col : COLOR;
};

struct PS_IN
{

    float4 pos : SV_POSITION;
    float4 col : COLOR;
};

RWStructuredBuffer<float4> colorOutputTable : register (u0);    // 2D color data
StructuredBuffer<float4> output2 :            register (t0);    // same as u0
RWStructuredBuffer<int> counterTable :        register (u1);    // depth data for z values
RWStructuredBuffer<VS_IN>vertexTable :        register (u4);    // triangle list
StructuredBuffer<VS_IN>vertexTable2 :         register (t4);    // same as u4

ShaderRecourceView を使用して、ピクセルおよび/または頂点シェーダーにバッファーへのアクセスを許可します。この概念は私のピクセル シェーダーではうまく機能しますが、頂点シェーダーは 0 値しか読み取らないようです (バッファーへのインデックスとして SV_VertexID を使用します)。

PS_IN VS_3DA ( uint vid : SV_VertexID ) 
{           
    PS_IN output = (PS_IN)0; 
    PS_IN input = vertexTable2[vid];
    output.pos = mul(input.pos, worldViewProj); 
    output.col = input.col; 
    return output;
}

hlsl コンパイラからのエラー メッセージや警告はなく、renderloop は (vsync を使用して) 60 fps で実行されますが、画面は黒いままです。Draw(..) が呼び出される前に Color.White で画面を空白にしているため、レンダリング パイプラインがアクティブになっているようです。

GPU から UAView を介して三角形のデータ コンテンツを「vertArray」に読み込み、それを頂点バッファーにフィードバックすると、すべてが機能します。

プログラム:

    let vertices = Buffer.Create(device, BindFlags.VertexBuffer, vertArray)
    context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertices, Utilities.SizeOf<Vector4>() * 2, 0))

HLSL:

PS_IN VS_3D (VS_IN input )
{
    PS_IN output = (PS_IN)0;    
    output.pos = mul(input.pos, worldViewProj);
    output.col = input.col; 
    return output;
}

ここで 2D の定義 - 頂点 / ピクセルシェーダー。PS_2D はスロット t0 のバッファー「output2」にアクセスすることに注意してください。これはまさに、3D 頂点シェーダー「VS_3DA」で複製したい「トリック」です。

float4 PS_2D ( float4 input : SV_Position) : SV_Target
{        
    uint2 pixel =  uint2(input.x, input.y);         
    return output2[ pixel.y * width + pixel.x]; 
}

float4 VS_2D ( uint vid : SV_VertexID ) : SV_POSITION
{
if (vid == 0)
    return float4(-1, -1, 0, 1);
if (vid == 1)
    return float4( 1, -1, 0, 1);
if (vid == 2)
    return float4(-1,  1, 0, 1);    

return float4( 1,  1, 0, 1);    
}

3日間、私は検索して実験しましたが、役に立ちませんでした. 私が収集したすべての情報は、SV_VertexID を使用した私のアプローチが機能することを確認しているようです。

誰でもアドバイスできますか?私の投稿を読んでくれてありがとう!

================================================== ===================

詳細:

私は DirectX 11 コンピューティング シェーダーのコンセプトがとても好きで、代数計算に採用したいと考えています。テスト ケースとして、フラクタル (マンデルブロ集合) を 3D でレンダリングします。壁の最後のレンガが 1 つ欠けていることを除いて、すべてが期待どおりに機能します。

計算には次の手順が必要です。

  1. CS を使用して 2D テクスチャを計算する (出力は「counterTable」と「colorOutbutTable」です (動作)

  2. 必要に応じて、このテクスチャを画面にレンダリングします (動作)

  3. 別の CS を使用してメッシュ (三角形のリスト) を生成します。この CS は、ステップ 1 から x、y、および色の値を取得し、z 座標を計算して、最後に各ピクセルのクワッドを作成します。結果は「頂点テーブル」に格納されます。(作品)

  4. 三角形のリストを頂点シェーダーにフィードする (問題!!!)

  5. 画面にレンダリングします (動作 - 頂点バッファーを使用)。

プログラミングには、F# 3.0 と SharpDX を .NET ラッパーとして使用します。両方のシェーダー (ピクセルと頂点) の ShaderRessourceView は、同じパラメーター (サイズ パラメーターを除く) で設定されます。

let mutable descr = new BufferDescription()     
descr.BindFlags <- BindFlags.UnorderedAccess ||| BindFlags.ShaderResource 
descr.Usage <- ResourceUsage.Default  
descr.CpuAccessFlags <- CpuAccessFlags.None
descr.StructureByteStride <- xxx    / / depends on shader
descr.SizeInBytes <-  yyy       / / depends on shader
descr.OptionFlags <- ResourceOptionFlags.BufferStructured

ここでは特別なことは何もありません。2D バッファの作成 (スロット t0 のバッファ「output2」にバインド):

outputBuffer2D <- new Buffer(device, descr) 
outputView2D <- new UnorderedAccessView (device, outputBuffer2D)  
shaderResourceView2D <- new ShaderResourceView (device, outputBuffer2D)

3D バッファの作成 (スロット t4 の「vertexTable2」にバインド):

vertexBuffer3D <- new Buffer(device, descr) 
shaderResourceView3D <- new ShaderResourceView (device, vertexBuffer3D)
//  UAView not required here

2D のリソースの設定:

context.InputAssembler.PrimitiveTopology <- PrimitiveTopology.TriangleStrip
context.OutputMerger.SetRenderTargets(renderTargetView2D)
context.OutputMerger.SetDepthStencilState(depthStencilState2D)
context.VertexShader.Set (vertexShader2D)
context.PixelShader.Set (pixelShader2D) 

2D をレンダリング:

context.PixelShader.SetShaderResource(COLOR_OUT_SLOT, shaderResourceView2D)
context.PixelShader.SetConstantBuffer(CONSTANT_SLOT_GLOBAL, constantBuffer2D )
context.ClearRenderTargetView (renderTargetView2D, Color.White.ToColor4())         
context.Draw(4,0)                                                
swapChain.Present(1, PresentFlags.None)            

3D のリソースの設定:

context.InputAssembler.PrimitiveTopology <- PrimitiveTopology.TriangleList
context.OutputMerger.SetTargets(depthView3D, renderTargetView2D)
context.VertexShader.SetShaderResource(TRIANGLE_SLOT, shaderResourceView3D )
context.VertexShader.SetConstantBuffer(CONSTANT_SLOT_3D, constantBuffer3D)
context.VertexShader.Set(vertexShader3D)
context.PixelShader.Set(pixelShader3D)

3D をレンダリングします (機能しません – 出力結果として黒い画面が表示されます)

context.ClearDepthStencilView(depthView3D, DepthStencilClearFlags.Depth, 1.0f, 0uy)
context.Draw(dataXsize * dataYsize * 6, 0)
swapChain.Present(1, PresentFlags.None)

最後にスロット番号:

static let CONSTANT_SLOT_GLOBAL = 0
static let CONSTANT_SLOT_3D = 1
static let COLOR_OUT_SLOT = 0
static let COUNTER_SLOT = 1
static let COLOR_SLOT = 2    
static let TRIANGLE_SLOT = 4
4

2 に答える 2

3

最初にお勧めするのは、デバッグ レイヤーをオンにして (デバイスを作成するときにデバッグ フラグを使用する)、プロジェクト プロパティの [デバッグ] タブに移動し、[アンマネージ コードのデバッグを有効にする] または [ネイティブ コードのデバッグを有効にする] にチェックマークを付けることです。

プログラムのデバッグを開始すると、パイプラインの状態に何か問題がある場合、ランタイムが潜在的な警告を表示します。

潜在的な問題の 1 つ (投稿した内容から最も可能性の高い問題のように見えます): ディスパッチ後にコンピューティング シェーダーの UAV スロットを必ずクリーニングしてください。vertexTable2 を頂点シェーダーにバインドしようとしても、リソースがまだ計算シェーダー出力としてバインドされている場合、ランタイムは自動的に ShaderView を null に設定します (これを読み取ろうとすると、0 が返されます)。

コンピュート シェーダーをクリーンアップするには、ディスパッチが完了したデバイス コンテキストでこれを呼び出します。

ComputeShader.SetUnorderedAccessView(TRIANGLE_SLOT, null)

また、PixelShader は RWStructuredBuffer にアクセスできることにも注意してください (技術的には、機能レベル 11.1、つまり最近の ATI カードと Windows 8+ を使用している場合、任意のシェーダー タイプに RWStructuredBuffer を使用できます)。

于 2013-11-11T19:30:04.817 に答える
1

三角形のリストを頂点シェーダーにフィードする (問題!!!)

構造化されたバッファ (vb としてバインドできない) を使用する代わりに、生のバッファの使用を検討します。シェーダーでキャストする必要がありますが、cs と vs.

バッファを作成するときは、次のようにします。

D3D11_BUFFER_DESC desc = {};
desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_VERTEX_BUFFER;
desc.ByteWidth = byteSize;
desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;

その後、シェーダー リソースとしてバインドできます。

D3D11_SHADER_RESOURCE_VIEW_DESC desc = {};
desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
desc.BufferEx.FirstElement = 0;
desc.Format = DXGI_FORMAT_R32_TYPELESS;
desc.BufferEx.Flags = D3D11_BUFFEREX_SRV_FLAG_RAW;
desc.BufferEx.NumElements = descBuf.ByteWidth / 4;

または順不同アクセス ビュー:

D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
desc.Buffer.FirstElement = 0;
desc.Format = DXGI_FORMAT_R32_TYPELESS; // Format must be DXGI_FORMAT_R32_TYPELESS, when creating Raw Unordered Access View
desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
desc.Buffer.NumElements = descBuf.ByteWidth / 4; 

シェーダーでは、次のようなものを使用します。

ByteAddressBuffer Buffer0 : register(t0);
ByteAddressBuffer Buffer1 : register(t1);
RWByteAddressBuffer BufferOut : register(u0);

int i0 = asint( Buffer0.Load( DTid.x*8 ) );
float f0 = asfloat( Buffer0.Load( DTid.x*8+4 ) );
int i1 = asint( Buffer1.Load( DTid.x*8 ) );
float f1 = asfloat( Buffer1.Load( DTid.x*8+4 ) );

BufferOut.Store( DTid.x*8, asuint(i0 + i1) );
BufferOut.Store( DTid.x*8+4, asuint(f0 + f1) );

上記のサンプル コードは、DirectX June 2010 SDK の BasicCompute11 サンプルから取得したものです。構造化バッファと生バッファの両方を使用する方法を示しています。

于 2014-10-16T21:19:51.397 に答える