Como posso alimentar os resultados do shader de computação no shader de vértice sem usar um buffer de vértice?

Antes de entrar em detalhes, quero descrever o problema:

Eu uso RWStructuredBuffers para armazenar a saída dos meus computados shaders (CS). Como os sombreadores de vértice e pixel não conseguem ler de RWStructuredBuffers, mapeio um StructuredBuffer no mesmo slot (u0 / t0) e (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

Eu uso um ShaderRecourceView para conceder acesso de pixel e / ou shader de vértice para os buffers. Este conceito funciona bem para o meu pixel shader, o vertex shader, no entanto, parece ler apenas 0 valores (eu uso SV_VertexID como índice para os buffers):

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

Nenhuma mensagem de erro ou aviso do compilador hlsl, o renderloop é executado com 60 fps (usando vsync), mas a tela permanece preta. Como anulo a tela com Color.White antes do Draw (..) ser chamado, o pipeline de renderização parece estar ativo.

Quando eu leio o conteúdo dos dados do triângulo por meio de um UAView da GPU em “vertArray” e o coloco de volta em um buffer de vértice, tudo funciona no entanto:

Programa:

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

Aqui a definição do 2D - Vertex / Pixelshaders. Por favor note que PS_2D acessa o buffer "output2" no slot t0 - e é exatamente esse o "truque" que eu quero replicar para o 3D shader de vértice "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);    
}

Por três dias eu procurei e experimentei sem sucesso. Todas as informações que reuni parecem confirmar que minha abordagem usando SV_VertexID deve funcionar.

Alguém pode dar conselhos? Obrigado por ler meu post!

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

DETALHES:

Eu gosto muito do conceito de shaders de computação DirectX 11 e quero empregá-lo para computação algébrica. Como um caso de teste, eu faço fractais (conjuntos Mandelbrot) em 3D. Tudo funciona como esperado - exceto um último tijolo na parede está faltando.

O cálculo segue os seguintes passos:

Usando um CS para calcular uma textura 2D (a saída é "counterTable" e "colorOutbutTable" (funciona)

Opcionalmente, renderize essa textura para a tela (funciona)

Usando outro CS para gerar uma malha (lista de triângulos). Este CS obtém os valores x, y e color do passo 1, calcula a coordenada ze finalmente cria um quad para cada pixel. O resultado é armazenado em “vertexTable”. (trabalho)

Alimentando a lista de triângulos para o shader de vértice (problema !!!)

Renderizar para tela (funciona - usando um buffer de vértice).

Para programação eu uso F # 3.0 e SharpDX como wrapper .NET. O ShaderRessourceView para ambos os shaders (pixel e vértice) é configurado com os mesmos parâmetros (exceto os parâmetros de tamanho):

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

Nada de especial aqui. Criação de buffer 2D (liga-se ao buffer "output2" no slot t0):

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

Criação de buffer 3D (liga-se a "vertexTable2" no slot t4):

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

Definindo recursos para 2D:

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

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

Definindo recursos para 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)

render 3D (não funciona - tela preta como resultado de saída)

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

Finalmente os números dos slots:

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