DirectX 11 - 计算着色器:写入输出资源 [英] DirectX 11 - Compute shader: Writing to an output resource

查看:1070
本文介绍了DirectX 11 - 计算着色器:写入输出资源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚开始在DirectX 11中使用Compute着色器阶段,并且在写入Compute着色器中的输出资源时遇到一些不必要的行为。我似乎只得到零作为输出,据我的理解,意味着在计算着色器中执行了超出界限的读取。 (超出范围写入导致无操作)

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. 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. (Out-of-bound writes results in no-ops)

输入资源

首先,我为输入数据创建一个 ID3D11Buffer * 当创建用于输入到Compute着色器级的SRV时,将作为资源传递。如果输入数据从不改变,我们可以在创建SRV之后释放 ID3D11Buffer * 对象,因为SRV将作为资源的句柄。

First I create an ID3D11Buffer* for input data. This is passed as a resource when creating the SRV used for input to the Compute shader stage. 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.

但是,我想更新每帧的输入数据,所以我只是为了映射缓冲区。

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






使用新创建的缓冲区作为资源创建SRV


Creating the SRV using the newly created buffer as resource

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






输出资源 / p>

现在我需要为Compute着色器创建一个资源来写入。我还将创建一个系统内存版本的缓冲区来读取。我将使用 ID3D11DeviceContext :: CopyResource方法将数据从连接到UAV的Compute着色器输出缓冲区复制到系统内存版本以执行映射并将其内容保存回系统内存。

Now I need to create a resource for the Compute shader to write to. 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.

创建计算着色器可以写入

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






为计算着色器创建UAV以写入结果




Create UAV for compute shader to write results

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

很抱歉这个问题的内容量。

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.

传递给着色器的元素数量为32个。

Number of elements passed to shader is 32.

有关我的问题的任何建议吗?谢谢!

Any suggestions on my problem? Thank you!

推荐答案

您的来源和目的地在您致电CopyResource时出错。

You have source and destination the wrong way round in your call to CopyResource.

这篇关于DirectX 11 - 计算着色器:写入输出资源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆