Jak mogę przesłać wyniki modułu cieniującego do modułu cieniującego wierzchołków bez użycia bufora wierzchołków?

Zanim przejdę do szczegółów, chcę opisać problem:

Używam RWStructuredBuffers do przechowywania danych wyjściowych moich shaderów obliczeniowych (CS). Ponieważ shadery wierzchołków i pikseli nie mogą czytać z RWStructuredBuffers, mapuję StructuredBuffer na to samo gniazdo (u0 / t0) i (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

Używam ShaderRecourceView, aby nadać pikselom i / lub werteksom dostęp do buforów. Ta koncepcja działa dobrze dla mojego pixel shadera, ale vertex shader zdaje się jednak odczytywać tylko 0 wartości (używam SV_VertexID jako indeksu buforów):

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

Brak komunikatów o błędach i ostrzeżeń z kompilatora hlsl, renderloop działa z 60 fps (używając vsync), ale ekran pozostaje czarny. Ponieważ pusto ekran za pomocą Color.White przed wywołaniem Draw (..), potok renderowania wydaje się być aktywny.

Kiedy czytam zawartość danych trójkąta za pośrednictwem UAView z GPU do „vertArray” i przekazuję go z powrotem do bufora wierzchołków, wszystko działa jednak:

Program:

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

Oto definicja 2D - Vertex / Pixelshaders. Należy pamiętać, że PS_2D uzyskuje dostęp do bufora „output2” w gnieździe t0 - i to jest dokładnie „sztuczka”, którą chcę zreplikować dla cieniowania wierzchołków 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);    
}

Przez trzy dni bezskutecznie poszukiwałem i eksperymentowałem. Wszystkie informacje, które zebrałem, wydają się potwierdzać, że moje podejście przy użyciu SV_VertexID powinno działać.

Czy ktoś może udzielić porady? Dzięki za przeczytanie mojego posta!

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

DETALE:

Podoba mi się koncepcja obliczania shaderów DirectX 11 i chcę je wykorzystać do obliczeń algebraicznych. Jako przypadek testowy renderuję fraktale (zestawy Mandelbrota) w 3D. Wszystko działa zgodnie z oczekiwaniami - z wyjątkiem jednej ostatniej cegły w ścianie.

Obliczenie wykonuje następujące kroki:

Używanie CS do obliczenia tekstury 2D (wyjście jest „counterTable” i „colorOutbutTable” (działa)

Opcjonalnie renderuj tę teksturę na ekranie (działa)

Użycie innego CS do wygenerowania siatki (lista trójkątów). Ten CS pobiera wartości x, y i koloru z kroku 1, oblicza współrzędną z i ostatecznie tworzy quad dla każdego piksela. Wynik jest przechowywany w „vertexTable”. (Prace)

Podawanie listy trójkątów do modułu cieniującego wierzchołka (problem !!!)

Renderuj do ekranu (działa - używając bufora wierzchołków).

Do programowania używam F # 3.0 i SharpDX jako opakowania .NET. ShaderRessourceView dla obu shaderów (piksel i wierzchołek) jest ustawiany z tymi samymi parametrami (z wyjątkiem parametrów rozmiaru):

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

Nic specjalnego tutaj. Tworzenie bufora 2D (wiąże się z buforem „output2” w gnieździe t0):

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

Tworzenie bufora 3D (wiąże się z „vertexTable2” w gnieździe t4):

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

Ustawianie zasobów dla 2D:

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

renderuj 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)            

Ustawianie zasobów dla 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)

renderuj 3D (nie działa - czarny ekran jako wynik wyjściowy)

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

Wreszcie numery slotów:

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

questionAnswers(2)

yourAnswerToTheQuestion