You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DirectX12计算着色器管线输出全0问题求助及修复示例

DirectX12计算着色器输出全0问题排查及修复示例

我是DirectX12新手,在网上未找到可用的C++计算着色器简单示例。我编写了一段代码,流程为创建UAV缓冲区、通过计算着色器为其赋值、将UAV缓冲区数据拷贝到暂存缓冲区,最后读取并打印数据,但所有输出值均为0,恳请帮忙排查问题。

更新: 已修复代码,以下是可运行的最小计算着色器应用示例:

#define NOMINMAX

#include <wil/resource.h>

#include <iostream>

#include <d3dx12.h>
#include <dxgi1_4.h>
#define IID_GRAPHICS_PPV_ARGS IID_PPV_ARGS

#include <d3dcompiler.h>

using Microsoft::WRL::ComPtr;

const char* shaderSource = R"(
    RWBuffer<float> uavBuffer : register(u0);  // UAV (writable buffer)

    [numthreads(1, 1, 1)]
    void main(uint3 DTid : SV_DispatchThreadID) {
        // Write some data to the buffer
        uavBuffer[DTid.x] = sqrt((float)DTid.x);
    }
)";

int main()
{
    const UINT numElements = 16;

    ComPtr<ID3D12Device> device;
    ComPtr<ID3D12CommandQueue> commandQueue;
    ComPtr<ID3D12CommandAllocator> commandAllocator;
    ComPtr<ID3D12GraphicsCommandList> commandList;

    UINT64 fenceValue = 0;
    ComPtr<ID3D12Fence> fence;
    HANDLE eventHandle;

    ComPtr<ID3D12RootSignature> rootSignature;
    ComPtr<ID3D12PipelineState> computePSO;
    ComPtr<ID3DBlob> shaderBlob;
    ComPtr<ID3D12DescriptorHeap> uavHeap;
    ComPtr<ID3D12Resource> stagingBuffer;
    ComPtr<ID3D12Resource> uavBuffer;

    // Create the device
    THROW_IF_FAILED(D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_12_0, IID_PPV_ARGS(&device)));

    // Create a command queue
    D3D12_COMMAND_QUEUE_DESC queueDesc = {};
    queueDesc.Type = D3D12_COMMAND_LIST_TYPE_COMPUTE;
    queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
    THROW_IF_FAILED(device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&commandQueue)));

    // Create command list
    THROW_IF_FAILED(device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_COMPUTE, IID_PPV_ARGS(&commandAllocator)));
    THROW_IF_FAILED(device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_COMPUTE, commandAllocator.Get(), nullptr, IID_PPV_ARGS(&commandList)));

    // Create fence
    THROW_IF_FAILED(device->CreateFence(fenceValue, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence)));
    eventHandle = CreateEvent(nullptr, FALSE, FALSE, nullptr);

    // Create a buffer to be used as a UAV
    D3D12_HEAP_PROPERTIES heapProps = {};
    heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
    heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
    heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;

    D3D12_RESOURCE_DESC bufferDesc = {};
    bufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
    bufferDesc.Width = numElements * sizeof(float); // Total size of the buffer
    bufferDesc.Height = 1;
    bufferDesc.DepthOrArraySize = 1;
    bufferDesc.MipLevels = 1;
    bufferDesc.Format = DXGI_FORMAT_UNKNOWN;
    bufferDesc.SampleDesc.Count = 1;
    bufferDesc.SampleDesc.Quality = 0;
    bufferDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
    bufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;

    THROW_IF_FAILED(device->CreateCommittedResource(
        &heapProps,
        D3D12_HEAP_FLAG_NONE,
        &bufferDesc,
        D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
        nullptr, 
        IID_PPV_ARGS(&uavBuffer)));

    // Create staging buffer
    D3D12_RESOURCE_DESC stagingBufferDesc = {};
    stagingBufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
    stagingBufferDesc.Width = sizeof(float) * numElements; // The size of the buffer.
    stagingBufferDesc.Height = 1;
    stagingBufferDesc.DepthOrArraySize = 1;
    stagingBufferDesc.MipLevels = 1;
    stagingBufferDesc.Format = DXGI_FORMAT_UNKNOWN;
    stagingBufferDesc.SampleDesc.Count = 1;
    stagingBufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;

    D3D12_HEAP_PROPERTIES stagingHeapProps = {};
    stagingHeapProps.Type = D3D12_HEAP_TYPE_READBACK; // This is a readback buffer.
    stagingHeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
    stagingHeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;

    THROW_IF_FAILED(device->CreateCommittedResource(
        &stagingHeapProps,
        D3D12_HEAP_FLAG_NONE,
        &stagingBufferDesc,
        D3D12_RESOURCE_STATE_COPY_DEST, // Initial state for copying
        nullptr,
        IID_PPV_ARGS(&stagingBuffer)));

    D3D12_DESCRIPTOR_HEAP_DESC uavHeapDesc = {};
    uavHeapDesc.NumDescriptors = 1; // We are creating one UAV
    uavHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
    uavHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; // Must be visible to shaders

    THROW_IF_FAILED(device->CreateDescriptorHeap(&uavHeapDesc, IID_PPV_ARGS(&uavHeap)));

    D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
    uavDesc.Format = DXGI_FORMAT_UNKNOWN; // Buffer format
    uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
    uavDesc.Buffer.FirstElement = 0;
    uavDesc.Buffer.NumElements = numElements;
    uavDesc.Buffer.StructureByteStride = sizeof(float);
    uavDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE;

    CD3DX12_CPU_DESCRIPTOR_HANDLE uavHandle(uavHeap->GetCPUDescriptorHandleForHeapStart());
    device->CreateUnorderedAccessView(uavBuffer.Get(), nullptr, &uavDesc, uavHandle);

    THROW_IF_FAILED(D3DCompile(shaderSource, strlen(shaderSource), nullptr, nullptr, nullptr, "main", "cs_5_0", 0, 0, &shaderBlob, nullptr));

    D3D12_ROOT_PARAMETER rootParams[1] = {};

    D3D12_DESCRIPTOR_RANGE descRange = {};
    descRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
    descRange.NumDescriptors = 1;
    descRange.BaseShaderRegister = 0; // u0

    rootParams[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
    rootParams[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
    rootParams[0].DescriptorTable.NumDescriptorRanges = 1;
    rootParams[0].DescriptorTable.pDescriptorRanges = &descRange;

    D3D12_ROOT_SIGNATURE_DESC rootSigDesc = {};
    rootSigDesc.NumParameters = 1;
    rootSigDesc.pParameters = rootParams;
    rootSigDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE;

    ComPtr<ID3DBlob> rootSignatureBlob;
    THROW_IF_FAILED(D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1, &rootSignatureBlob, nullptr));
    THROW_IF_FAILED(device->CreateRootSignature(0, rootSignatureBlob->GetBufferPointer(), rootSignatureBlob->GetBufferSize(), IID_PPV_ARGS(&rootSignature)));

    D3D12_COMPUTE_PIPELINE_STATE_DESC psoDesc = {};
    psoDesc.pRootSignature = rootSignature.Get();
    psoDesc.CS = { shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize() };

    THROW_IF_FAILED(device->CreateComputePipelineState(&psoDesc, IID_PPV_ARGS(&computePSO)));

    ID3D12DescriptorHeap* heaps[] = { uavHeap.Get() };
    commandList->SetDescriptorHeaps(1, heaps);
    commandList->SetPipelineState(computePSO.Get());
    commandList->SetComputeRootSignature(rootSignature.Get());
    commandList->SetComputeRootDescriptorTable(0, uavHeap->GetGPUDescriptorHandleForHeapStart());

    commandList->Dispatch(numElements, 1, 1);

    commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(uavBuffer.Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE));
    commandList->CopyResource(stagingBuffer.Get(), uavBuffer.Get());
    commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(uavBuffer.Get(), D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS));

    commandList->Close();

    ID3D12CommandList* commandLists[] = { commandList.Get() };
    commandQueue->ExecuteCommandLists(ARRAYSIZE(commandLists), commandLists);

    commandQueue->Signal(fence.Get(), ++fenceValue);

    // Wait for the fence to reach the signal value before proceeding
    fence->SetEventOnCompletion(fenceValue, eventHandle);
    WaitForSingleObject(eventHandle, INFINITE);

    // Map the staging buffer and read the data
    float* data = nullptr;
    stagingBuffer->Map(0, nullptr, reinterpret_cast<void**>(&data));
    for (size_t i = 0; i < numElements; ++i) {
        std::cout << "data[" << i << "] = " << data[i] << std::endl;
    }
    stagingBuffer->Unmap(0, nullptr);

    CloseHandle(eventHandle);

    return 0;
}

内容的提问来源于stack exchange,提问作者Yuriy Solovyov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 16:55:54