Wie kann ich Compute-Shader-Ergebnisse ohne Verwendung eines Vertex-Puffers in den Vertex-Shader einspeisen?

Bevor ich ins Detail gehe, möchte ich das Problem skizzieren:

Ich verwende RWStructuredBuffers, um die Ausgabe meiner Compute-Shader (CS) zu speichern. Da Vertex- und Pixel-Shader nicht aus RWStructuredBuffers lesen können, ordne ich einen StructuredBuffer demselben Slot (u0 / t0) und (u4 / t4) zu:

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

Ich verwende ShaderRecourceView, um Pixel- und / oder Vertex-Shader-Zugriff auf die Puffer zu gewähren. Dieses Konzept funktioniert gut für meinen Pixel-Shader, der Vertex-Shader scheint jedoch nur 0 Werte zu lesen (ich verwende SV_VertexID als Index für die Puffer):

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;
}

Keine Fehlermeldungen oder Warnungen vom HLSL-Compiler, der Renderloop läuft mit 60 fps (mit vsync), aber der Bildschirm bleibt schwarz. Da ich den Bildschirm mit Color.White leerlasse, bevor Draw (..) aufgerufen wird, scheint die Render-Pipeline aktiv zu sein.

Wenn ich den Inhalt der Dreiecksdaten über ein UAView von der GPU in "vertArray" lese und in einen Vertex-Puffer zurückspeise, funktioniert alles jedoch:

Programm:

    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;
}

Hier die Definition der 2D - Vertex / Pixelshader. Bitte beachte, dass PS_2D auf den Puffer "output2" in Slot t0 zugreift - und genau das ist der "Trick", den ich für den 3D Vertex Shader "VS_3DA" replizieren möchte:

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);    
}

Seit drei Tagen habe ich erfolglos gesucht und experimentiert. Alle Informationen, die ich gesammelt habe, scheinen zu bestätigen, dass mein Ansatz mit der SV_VertexID funktionieren sollte.

Kann jemand einen Rat geben? Vielen Dank für das Lesen meines Beitrags!

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

EINZELHEITEN:

Ich mag das Konzept der DirectX 11-Computing-Shader sehr und möchte es für algebraisches Computing einsetzen. Als Testfall rendere ich Fraktale (Mandelbrot-Sets) in 3D. Alles funktioniert wie erwartet - außer dass ein letzter Stein in der Wand fehlt.

Die Berechnung umfasst die folgenden Schritte:

Verwenden eines CS zum Berechnen einer 2D-Textur (Ausgabe ist "counterTable" und "colorOutbutTable") (funktioniert)

Optional können Sie diese Textur auf dem Bildschirm rendern (funktioniert)

Verwenden eines anderen CS zum Erzeugen eines Netzes (Dreiecksliste). Diese CS verwendet die Werte für x, y und Farbe aus Schritt 1, berechnet die z-Koordinate und erstellt schließlich für jedes Pixel ein Quad. Das Ergebnis wird in „vertexTable“ gespeichert. (funktioniert)

Die Dreiecksliste an den Vertex-Shader weiterleiten (Problem !!!)

Auf Bildschirm rendern (funktioniert - mit einem Scheitelpunktpuffer).

Zum Programmieren verwende ich F # 3.0 und SharpDX als .NET-Wrapper. Die ShaderRessourceView für beide Shader (Pixel & Vertex) wird mit denselben Parametern (außer den Größenparametern) eingerichtet:

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

Nichts besonderes hier. Erzeugung eines 2D-Puffers (bindet an den Puffer "output2" in Slot t0):

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

Erstellung eines 3D-Puffers (bindet an "vertexTable2" in Slot t4):

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

Festlegen von Ressourcen für 2D:

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

2D rendern:

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)            

Ressourcen für 3D festlegen:

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 rendern (funktioniert nicht - schwarzer Bildschirm als Ausgabeergebnis)

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

Schließlich die Steckplatznummern:

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

Antworten auf die Frage(2)

Ihre Antwort auf die Frage