Wie kann ich feed compute shader Ergebnisse in vertex-shader-w/o mit einem vertex-buffer?
Bevor ich in die details gehen möchte ich umreißen das problem:
Benutze ich RWStructuredBuffers zu speichern, die Ausgabe von meinem compute Shader (CS). Da vertex-und pixel-Shader können nicht Lesen RWStructuredBuffers, ich Karte einer StructuredBuffer auf den gleichen Steckplatz (u0/t0) und (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
Verwende ich eine ShaderRecourceView zu gewähren, pixel-und/oder vertex-shader-Zugriff auf die Puffer. Dieses Konzept funktioniert gut für meine pixel-shader, vertex-shader hingegen scheint nur Lesen nur Lesen 0-Werte (ich benutze SV_VertexID als index für den 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 aus der hlsl-compiler, der renderloop läuft mit 60 fps (mit vsync), aber der Bildschirm bleibt schwarz. Da ich einen leeren Bildschirm mit Farbe.Weiß vor dem Draw(..) aufgerufen wird, wird der render-pipeline scheint aktiv zu sein.
Wenn ich lese das Dreieck Daten Inhalt über eine UAView von der GPU in "vertArray" und führen es zurück in ein vertex-buffer, alles funktioniert aber:
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 des 2D - Vertex /Pixelshaders. Bitte beachten Sie, dass PS_2D greift auf die Puffer "output2" in Schlitz t0 - und das ist genau der "trick" was ich will, zu replizieren, für die dann die 3D-vertex-shader "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);
}
Drei Tage lang habe ich danach gesucht und experimentiert, ohne Erfolg. Alle Informationen die ich gesammelt, scheinen zu bestätigen, dass mein Ansatz dann SV_VertexID funktionieren sollte.
Kann jemand Tipps geben? Vielen Dank für das Lesen meiner post!
=====================================================================
DETAILS:
Ich mag das Konzept der DirectX-11-compute-Shader sehr viel, und ich will Sie anwenden algebraischer computing. Als test-Fall, den ich render, Fraktale (apfelmännchen) in 3D. Alles funktioniert wie erwartet – außer einem letzten Stein in der Wand fehlt.
Die Berechnung die folgenden Schritte erfolgt:
-
Verwendung eines CS zur Berechnung einer 2D-textur (Ausgang ist "counterTable" und "colorOutbutTable" (funktioniert)
-
Optional machen diese textur zu Bildschirm (funktioniert)
-
Mit einem anderen CS zu erzeugen, ein mesh (triangle list). Das CS nimmt die x -, y-und color-Werte aus Schritt 1 berechnet die z-Koordinate, und schafft endlich ein quad für jedes pixel. Das Ergebnis wird gespeichert in "vertexTable". (Werke)
-
Fütterung der Dreiecke Liste der vertex-shader (problem!!!!!)
-
Render to screen (Werke - mit einem vertex-buffer).
Zur Programmierung verwende ich F# 3.0 und SharpDX als .NET-wrapper.
Die ShaderRessourceView für beide Shader (pixel - & Eckpunkt) mit gleichen Parametern (außer der Größe-Parameter):
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
Hier nichts besonderes.
Erstellung von 2D-Puffer (bindet an Puffer "output2" in Schlitz t0):
outputBuffer2D <- new Buffer(device, descr)
outputView2D <- new UnorderedAccessView (device, outputBuffer2D)
shaderResourceView2D <- new ShaderResourceView (device, outputBuffer2D)
Erstellung von 3D-Puffer (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)
Rendern 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)
Festlegen von Ressourcen für 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)
Rendern 3D (funktioniert nicht – schwarzer Bildschirm als Ausgabe-Ergebnis)
context.ClearDepthStencilView(depthView3D, DepthStencilClearFlags.Depth, 1.0f, 0uy)
context.Draw(dataXsize * dataYsize * 6, 0)
swapChain.Present(1, PresentFlags.None)
Schließlich die slot-Nummern:
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
InformationsquelleAutor Siegfried Stephan | 2013-11-11
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ok, erste, was ich vorschlagen würde, ist, um auf debug-Ebene (Verwendung von Debug-flag beim erstellen Ihres Geräts), dann gehen Sie zu Projekteigenschaften, Registerkarte "Debuggen", und kreuzen Sie "Enable unmanaged code debugging" oder "Enable native code debugging".
Wenn Sie beginnen, Debuggen Sie das Programm von der runtime geben Sie mögliche Warnungen, wenn etwas falsch mit pipeline-Zustand.
Ein mögliches Problem (das sieht wohl einer aus, was du gepostet hast):
Stellen Sie sicher, zu reinigen Sie Ihren compute shader UAV-slots nach dem Versand. Wenn Sie versuchen zu binden vertexTable2 zu Ihrem vertex-shader, aber die Ressource ist Sie immer noch gebunden sind als compute-shader die Ausgabe, die Laufzeit wird automatisch gesetzt, Ihre ShaderView auf null (was wiederum 0 zurück, wenn Sie versuchen, es zu Lesen).
Reinigen Sie Ihre Compute-Shader, rufen Sie dieses auf Ihrem Gerät Zusammenhang du fertig bist mit Versand:
Bitte beachten Sie auch, dass die PixelShader zugreifen können RWStructuredBuffer (technisch gesehen kann man das verwenden RWStructuredBuffer für jeden shader-Typ, wenn Sie feature-level 11.1, das bedeutet, dass neuere ATI-Grafikkarte und Windows 8+).
Derzeit nutze ich VS Express for Web 2012 (da F# 3.0 ist im Lieferumfang enthalten); debug-Optionen, die Sie beschreiben, existiert nicht auf meine debug-Eigenschaften-Registerkarte (nur "enable VS-hosting-Prozess"). Ich glaube, ich habe eine Vollversion von VS, um zu bekommen, DirectX Debuggen (wenn ich die swapchain mit der debug-option, wird eine Ausnahme geworfen wird). So habe ich keine chance auf low-level-debugging im moment. Wenn Sie wissen, eine web-Ressource, die erklärt, wie Sie zum aktivieren von DirectX-debugging in Visual Studio, ich würde mich freuen, Sie zu empfangen.
SharpDX verwendet verschiedene Bibliotheken für jedes DirectX-level, also bleibe ich mit 11.0 abwärtskompatibel mit ein paar Freunden.
Normalerweise so lange, wie haben Sie das DirectX-SDK (Juni 2010) installiert haben, erstellen Sie ein Gerät mit debug-flags funktionieren sollte. Zum erfassen von Warnungen Sie können auch verwenden Sie windbg, sollte glücklich diejenigen erfassen (sofern debug-flag eingeschaltet ist natürlich).
InformationsquelleAutor catflier
Anstelle der Verwendung von strukturierten Puffer (lassen Sie sich nicht von Ihnen binden, als einen vb -), ich würde in raw-Puffer. Es erfordert casting im shader, sondern ermöglicht Ihnen die Verwendung des gleichen Puffers in dein cs und vs
Beim erstellen der Puffer nicht:
Könnte man sich dann binden, wie ein shader Ressource:
oder Unordered Access View:
In die shader, die Sie verwenden würden, so etwas wie dieses:
Beispielcode oben wurde aus der BasicCompute11 Probe aus dem DirectX June 2010 SDK. Es veranschaulicht die Verwendung von sowohl strukturierte als Puffer-und raw-Puffer.
InformationsquelleAutor boni