[英]DirectX 11 - Compute shader: Writing to an output resource
我剛剛開始在DirectX 11中使用Compute shader階段,並且在Compute shader中寫入輸出資源時遇到了一些不需要的行為。 我的輸出似乎只有零,據我所知,這意味着已在Compute着色器中執行了越界讀取。 (越界寫入將導致無操作)
輸入資源
首先,我為輸入數據創建一個ID3D11Buffer*
。 當創建用於輸入到Compute shader階段的SRV時,它將作為資源傳遞。 如果輸入數據永不更改,則可以在創建SRV之后釋放ID3D11Buffer*
對象,因為SRV將充當資源的句柄。
但是,我想每幀更新輸入數據,所以我只需要保留緩沖區即可進行映射。
// 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 );
使用新創建的緩沖區作為資源創建SRV
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 );
輸出資源
現在,我需要為Compute着色器創建要寫入的資源。 我還將創建要讀取的緩沖區的系統內存版本。 我將使用ID3D11DeviceContext :: CopyResource方法將數據從連接到UAV的計算着色器輸出緩沖區復制到系統內存版本,以執行映射,並將其內容保存回系統內存中。
創建計算着色器可以寫入的讀寫緩沖區
(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 ) );
創建緩沖區的系統內存版本以從中讀取結果
outputDesc.Usage = D3D11_USAGE_STAGING;
outputDesc.BindFlags = 0;
outputDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
hr = ( device->CreateBuffer( &outputDesc, 0, &mOutputResultBuffer ) );
創建用於計算着色器的UAV以寫入結果
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 );
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;
}
抱歉,這個問題的內容太多了。 我對它進行了精心構造,因此您可能會更容易獲得概述。
傳遞到着色器的元素數為32。
關於我的問題有什么建議嗎? 謝謝!
您對CopyResource的調用中的源和目標方向錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.