简体   繁体   English

DirectX 11-计算着色器:写入输出资源

[英]DirectX 11 - Compute shader: Writing to an output resource

I've just started using the Compute shader stage in DirectX 11 and encountered some unwanted behaviour when writing to an output resource in the Compute shader. 我刚刚开始在DirectX 11中使用Compute shader阶段,并且在Compute shader中写入输出资源时遇到了一些不需要的行为。 I seem to get only zeroes as output which, to my understanding, means that out-of-bound reads has been performed in the Compute shader. 我的输出似乎只有零,据我所知,这意味着已在Compute着色器中执行了越界读取。 (Out-of-bound writes results in no-ops) (越界写入将导致无操作)

Creating the Compute shader components 创建计算着色器组件

Input resources 输入资源

First I create an ID3D11Buffer* for input data. 首先,我为输入数据创建一个ID3D11Buffer* This is passed as a resource when creating the SRV used for input to the Compute shader stage. 当创建用于输入到Compute shader阶段的SRV时,它将作为资源传递。 If the input data never changes then we could release the ID3D11Buffer* object after creating the SRV since the SRV is going to act as a handle to the resource. 如果输入数据永不更改,则可以在创建SRV之后释放ID3D11Buffer*对象,因为SRV将充当资源的句柄。

However, I want to update the input data each frame so I'm just going to keep the buffer at my disposal for mapping. 但是,我想每帧更新输入数据,所以我只需要保留缓冲区即可进行映射。

// 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 );

Creating the SRV using the newly created buffer as resource 使用新创建的缓冲区作为资源创建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 );

Output resources 输出资源

Now I need to create a resource for the Compute shader to write to. 现在,我需要为Compute着色器创建要写入的资源。 I will also create a system memory version of the buffer to read from. 我还将创建要读取的缓冲区的系统内存版本。 I will use the ID3D11DeviceContext::CopyResource method to copy data from the Compute shader output buffer, connected to the UAV, to the system memory version for performing mapping and save its content back into system memory. 我将使用ID3D11DeviceContext :: CopyResource方法将数据从连接到UAV的计算着色器输出缓冲区复制到系统内存版本,以执行映射,并将其内容保存回系统内存中。

Create a read-write buffer the compute shader can write to 创建计算着色器可以写入的读写缓冲区

(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 ) );

Create a system memory version of the buffer to read the results back from 创建缓冲区的系统内存版本以从中读取结果

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 to write results 创建用于计算着色器的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 );

Executing Compute shader (each frame) 执行计算着色器(每帧)

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

I'm sorry for the amount of content in this question. 抱歉,这个问题的内容太多了。 I've structured it with care so you may find it easier to get an overview. 我对它进行了精心构造,因此您可能会更容易获得概述。

Number of elements passed to shader is 32. 传递到着色器的元素数为32。

Any suggestions on my problem? 关于我的问题有什么建议吗? Thank you! 谢谢!

您对CopyResource的调用中的源和目标方向错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM