DirectX 11 - Compute-Shader: In eine Ausgaberessource schreiben

Ich habe gerade mit der Verwendung der Compute-Shader-Stufe in DirectX 11 begonnen und beim Schreiben in eine Ausgaberessource im Compute-Shader ein unerwünschtes Verhalten festgestellt. Ich erhalte anscheinend nur Nullen als Ausgabe, was meines Erachtens bedeutet, dass im Compute-Shader Out-of-Bound-Lesevorgänge durchgeführt wurden. (Out-of-Bound-Schreibvorgänge führen zu No-Ops)

Erstellen der Compute-Shader-Komponenten

Eingaberessourcen

Zunächst erstelle ich einID3D11Buffer* für Eingabedaten. Dies wird als Ressource übergeben, wenn das SRV erstellt wird, das für die Eingabe in die Compute-Shader-Stufe verwendet wird. Wenn sich die Eingabedaten nie ändern, können wir das @ freigebeID3D11Buffer* -Objekt nach dem Erstellen des SRV, da der SRV als Handle für die Ressource fungiert.

Ich möchte jedoch die Eingabedaten für jeden Frame aktualisieren, damit ich nur den Puffer für die Zuordnung zur Verfügung habe.

// Create a buffer to be bound as Compute Shader input (D3D11_BIND_SHADER_RESOURCE).
D3D11_BUFFER_DESC constantDataDesc;
constantDataDesc.Usage                  = D3D11_USAGE_DYNAMIC;
constantDataDesc.ByteWidth              = sizeof(ParticleConstantData) * NUM_PARTICLES;
constantDataDesc.BindFlags              = D3D11_BIND_SHADER_RESOURCE;
constantDataDesc.CPUAccessFlags         = D3D11_CPU_ACCESS_WRITE;
constantDataDesc.StructureByteStride    = sizeof(ParticleConstantData);
constantDataDesc.MiscFlags              = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;

hr =  device->CreateBuffer ( &constantDataDesc, 0, &mInputBuffer );

Erstellen des SRV unter Verwendung des neu erstellten Puffers als Ressource

D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
srvDesc.Format                  = DXGI_FORMAT_UNKNOWN;
srvDesc.ViewDimension           = D3D11_SRV_DIMENSION_BUFFEREX;
srvDesc.BufferEx.FirstElement   = 0;
srvDesc.BufferEx.Flags          = 0;
srvDesc.BufferEx.NumElements    = NUM_PARTICLES;

hr = device->CreateShaderResourceView( mInputBuffer, &srvDesc, &mInputView );

Ausgaberessourcen

Nun muss ich eine Ressource erstellen, in die der Compute-Shader schreiben kann. Ich werde auch eine Systemspeicherversion des Puffers erstellen, aus dem gelesen werden kann. Ich werde das @ verwend ID3D11DeviceContext :: CopyResource-Methode, um Daten aus dem Compute-Shader-Ausgabepuffer, der mit dem UAV verbunden ist, in die Systemspeicherversion zu kopieren, um das Mapping durchzuführen, und ihren Inhalt wieder im Systemspeicher zu speichern.

Erstellen Sie einen Lese- / Schreibpuffer, in den der Compute-Shader schreiben kann

(D3D11_BIND_UNORDERED_ACCESS).
D3D11_BUFFER_DESC outputDesc;
outputDesc.Usage                = D3D11_USAGE_DEFAULT;
outputDesc.ByteWidth            = sizeof(ParticleData) * NUM_PARTICLES;
outputDesc.BindFlags            = D3D11_BIND_UNORDERED_ACCESS;
outputDesc.CPUAccessFlags       = 0;
outputDesc.StructureByteStride  = sizeof(ParticleData);
outputDesc.MiscFlags            = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;

hr = ( device->CreateBuffer( &outputDesc, 0, &mOutputBuffer ) );

Erstellen Sie eine Systemspeicherversion des Puffers, um die Ergebnisse von @ zurückzulese

outputDesc.Usage            = D3D11_USAGE_STAGING;
outputDesc.BindFlags        = 0;
outputDesc.CPUAccessFlags   = D3D11_CPU_ACCESS_READ;

hr = ( device->CreateBuffer( &outputDesc, 0, &mOutputResultBuffer ) );

Create UAV for Compute Shader, um Ergebnisse zu schreiben

D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
uavDesc.Buffer.FirstElement     = 0;
uavDesc.Buffer.Flags            = 0;
uavDesc.Buffer.NumElements      = NUM_PARTICLES;
uavDesc.Format                  = DXGI_FORMAT_UNKNOWN;
uavDesc.ViewDimension           = D3D11_UAV_DIMENSION_BUFFER;

hr = device->CreateUnorderedAccessView( mOutputBuffer, &uavDesc, &mOutputUAV );
Executing Compute Shader (jeder Frame)

C ++

mParticleSystem.FillConstantDataBuffer( mDeviceContext, mInputBuffer );


// Enable Compute Shader
mDeviceContext->CSSetShader( mComputeShader, nullptr, 0 );

mDeviceContext->CSSetShaderResources( 0, 1, &mInputView );
mDeviceContext->CSSetUnorderedAccessViews( 0, 1, &mOutputUAV, 0 );


// Dispatch
mDeviceContext->Dispatch( 1, 1, 1 );

// Unbind the input textures from the CS for good housekeeping
ID3D11ShaderResourceView* nullSRV[] = { NULL };
mDeviceContext->CSSetShaderResources( 0, 1, nullSRV );

// Unbind output from compute shader
ID3D11UnorderedAccessView* nullUAV[] = { NULL };
mDeviceContext->CSSetUnorderedAccessViews( 0, 1, nullUAV, 0 );

// Disable Compute Shader
mDeviceContext->CSSetShader( nullptr, nullptr, 0 );


// Copy result
mDeviceContext->CopyResource( mOutputBuffer, mOutputResultBuffer );


// Update particle system data with output from Compute Shader
D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT hr = mDeviceContext->Map( mOutputResultBuffer, 0, D3D11_MAP_READ, 0, &mappedResource );

if( SUCCEEDED( hr ) )
{   
    ParticleData* dataView = reinterpret_cast<ParticleData*>(mappedResource.pData);

    // Update particle positions and velocities
    mParticleSystem.UpdatePositionAndVelocity( dataView );

    mDeviceContext->Unmap( mOutputResultBuffer, 0 );
}

HLSL

struct ConstantParticleData
{
    float3 position;
    float3 velocity;
    float3 initialVelocity;
};

struct ParticleData
{
    float3 position;
    float3 velocity;
};

StructuredBuffer<ConstantParticleData>  inputConstantParticleData   : register( t0 ); 
RWStructuredBuffer<ParticleData>        outputParticleData          : register( u0 );


[numthreads(32, 1, 1)]
void CS_main( int3 dispatchThreadID : SV_DispatchThreadID )
{
    outputParticleData[dispatchThreadID.x].position = inputConstantParticleData[dispatchThreadID.x].position;
}

Es tut mir leid für die Menge an Inhalten in dieser Frage. Ich habe es sorgfältig strukturiert, damit Sie sich einen besseren Überblick verschaffen können.

Anzahl der an Shader übergebenen Elemente ist 32.

Irgendwelche Vorschläge zu meinem Problem? Vielen Dank

Antworten auf die Frage(2)

Ihre Antwort auf die Frage