DirectX12 计算着色器什么都不做?

如何解决DirectX12 计算着色器什么都不做?

我正在尝试在 DirectX12 中编写最简单的计算着色器,以便我可以有一个真正项目的起点。但是,似乎无论我做什么,我都无法让我的 GPU 处理“1+1”并查看输出。由于几乎没有关于计算着色器的文档,我想我现在唯一的选择是查询 StackOverflow。

我使用 D3D12nBodyGravity 项目编写了以下代码。首先,我尽可能逐字逐句地复制了尽可能多的代码,修复了“小”的东西,然后一旦一切正常,我就开始将代码精简到基础。我使用的是 Visual Studio 2019。

myClass.cpp:

#include "pch.h"
#include "myClass.h"
#include <d3dcompiler.h> // D3DReadFileToBlob
#include "Common\DirectXHelper.h" // NAME_D3D12_OBJECT

#include "Common\Device.h"
#include <iostream>

// InterlockedCompareExchange returns the object's value if the 
// comparison fails.  If it is already 0,then its value won't 
// change and 0 will be returned.
#define InterlockedGetValue(object) InterlockedCompareExchange(object,0)

myClass::myClass() 
: m_frameIndex(0),m_UavDescriptorSize(0),m_renderContextFenceValue(0),m_frameFenceValues{} {
    std::cout << "Initializing myClass" << std::endl;
    
    m_FenceValue = 0;
    //std::cout << "Calling DXGIDeclareAdapterRemovalSupport()" << std::endl;
    //DX::ThrowIfFailed(DXGIDeclareAdapterRemovalSupport());



    // Identify the device
    std::cout << "Identifying the device" << std::endl;
    auto m_device = Device::Get().GetDevice();

    std::cout << "Leading the rendering pipeline dependencies" << std::endl;
    // Load the rendering pipeline dependencies.
    {
        std::cout << "   Creating the root signatures" << std::endl;
        // Create the root signatures.
        {
            CD3DX12_ROOT_PARAMETER rootParameter;
            rootParameter.InitAsUnorderedAccessView(0);

            Microsoft::WRL::ComPtr<ID3DBlob> signature;
            Microsoft::WRL::ComPtr<ID3DBlob> error;
            
            CD3DX12_ROOT_SIGNATURE_DESC computeRootSignatureDesc(1,&rootParameter,nullptr);
            DX::ThrowIfFailed(D3D12SerializeRootSignature(&computeRootSignatureDesc,D3D_ROOT_SIGNATURE_VERSION_1,&signature,&error));
            
            DX::ThrowIfFailed(m_device->CreateRootSignature(0,signature->GetBufferPointer(),signature->GetBufferSize(),IID_PPV_ARGS(&m_computeRootSignature)));
        }


        // Describe and create the command queue.
        std::cout << "   Describing and creating the command queue" << std::endl;
        D3D12_COMMAND_QUEUE_DESC queueDesc = {};
        queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
        queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;

        DX::ThrowIfFailed(m_device->CreateCommandQueue(&queueDesc,IID_PPV_ARGS(&m_commandQueue)));
        NAME_D3D12_OBJECT(m_commandQueue);

        std::cout << "   Creating descriptor heaps" << std::endl;
        // Create descriptor heaps.
        {
            // Describe and create a shader resource view (SRV) and unordered
            // access view (UAV) descriptor heap.
            D3D12_DESCRIPTOR_HEAP_DESC UavHeapDesc = {};
            UavHeapDesc.NumDescriptors = DescriptorCount;
            UavHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
            UavHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
            DX::ThrowIfFailed(m_device->CreateDescriptorHeap(&UavHeapDesc,IID_PPV_ARGS(&m_UavHeap)));
            NAME_D3D12_OBJECT(m_UavHeap);

            m_UavDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
        }

        std::cout << "   Creating a command allocator for each frame" << std::endl;
        // Create a command allocator for each frame.
        for (UINT n = 0; n < FrameCount; n++) {
            DX::ThrowIfFailed(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT,IID_PPV_ARGS(&m_commandAllocators[n])));
        }
    } // Load the rendering pipeline dependencies.


    std::cout << "Loading the sample assets" << std::endl;
    // Load the sample assets.
    {
        std::cout << "   Creating the pipeline states,including compiling and loading shaders" << std::endl;
        // Create the pipeline states,which includes compiling and loading shaders.
        {
            Microsoft::WRL::ComPtr<ID3DBlob> computeShader;

#if defined(_DEBUG)
            // Enable better shader debugging with the graphics debugging tools.
            UINT compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
#else
            UINT compileFlags = 0;
#endif

            // Load and compile the compute shader.
            DX::ThrowIfFailed(D3DReadFileToBlob(L"ComputeShader.cso",&computeShader));
            auto convert_blob_to_byte = [](Microsoft::WRL::ComPtr<ID3DBlob> blob) {
                auto* p = reinterpret_cast<unsigned char*>(blob->GetBufferPointer());
                auto n = blob->GetBufferSize();
                std::vector<unsigned char> buff;
                buff.reserve(n);
                std::copy(p,p + n,std::back_inserter(buff));
                return buff;
            };
            std::vector<BYTE> m_computeShader = convert_blob_to_byte(computeShader);

            // Describe and create the compute pipeline state object (PSO).
            D3D12_COMPUTE_PIPELINE_STATE_DESC computePsoDesc = {};
            computePsoDesc.pRootSignature = m_computeRootSignature.Get();
            computePsoDesc.CS = CD3DX12_SHADER_BYTECODE(computeShader.Get());

            DX::ThrowIfFailed(m_device->CreateComputePipelineState(&computePsoDesc,IID_PPV_ARGS(&m_computeState)));
            NAME_D3D12_OBJECT(m_computeState);
        }

        std::cout << "   Creating the command list" << std::endl;
        // Create the command list.
        DX::ThrowIfFailed(m_device->CreateCommandList(0,D3D12_COMMAND_LIST_TYPE_DIRECT,m_commandAllocators[m_frameIndex].Get(),m_computeState.Get(),IID_PPV_ARGS(&m_commandList)));
        NAME_D3D12_OBJECT(m_commandList);

        std::cout << "   Initializing the data in the buffers" << std::endl;
        // Initialize the data in the buffers.
        {
            data.resize(2);
            for (unsigned int i = 0; i < data.size(); i++) {
                data[i] = 0.0f;
            }
            const UINT dataSize = data.size() * sizeof(data[0]);

            D3D12_HEAP_PROPERTIES defaultHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);
            D3D12_HEAP_PROPERTIES uploadHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);
            D3D12_HEAP_PROPERTIES readbackHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_READBACK);
            D3D12_RESOURCE_DESC bufferDesc = CD3DX12_RESOURCE_DESC::Buffer(dataSize,D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS);
            D3D12_RESOURCE_DESC uploadBufferDesc = CD3DX12_RESOURCE_DESC::Buffer(dataSize);
            readbackBufferDesc = CD3DX12_RESOURCE_DESC::Buffer(dataSize);


            DX::ThrowIfFailed(m_device->CreateCommittedResource(
                &defaultHeapProperties,D3D12_HEAP_FLAG_NONE,&bufferDesc,D3D12_RESOURCE_STATE_COPY_DEST,nullptr,IID_PPV_ARGS(&m_dataBuffer)));
            m_dataBuffer.Get()->SetName(L"m_dataBuffer");
                
            DX::ThrowIfFailed(m_device->CreateCommittedResource(
                &uploadHeapProperties,&uploadBufferDesc,D3D12_RESOURCE_STATE_GENERIC_READ,IID_PPV_ARGS(&m_dataBufferUpload)));
            m_dataBufferUpload.Get()->SetName(L"m_dataBufferUpload");
                
            DX::ThrowIfFailed(m_device->CreateCommittedResource(
                &readbackHeapProperties,&readbackBufferDesc,IID_PPV_ARGS(&m_dataBufferReadback)));
            m_dataBufferReadback.Get()->SetName(L"m_dataBufferReadback");
                
            NAME_D3D12_OBJECT(m_dataBuffer);

            dataSubResource = {};
            dataSubResource.pData = &data[0];
            dataSubResource.RowPitch = dataSize;
            dataSubResource.SlicePitch = dataSubResource.RowPitch;

            UpdateSubresources<1>(m_commandList.Get(),m_dataBuffer.Get(),m_dataBufferUpload.Get(),1,&dataSubResource);
            m_commandList->ResourceBarrier(1,&CD3DX12_RESOURCE_BARRIER::Transition(m_dataBuffer.Get(),D3D12_RESOURCE_STATE_COMMON));

            m_commandList->CopyResource(m_dataBufferReadback.Get(),m_dataBufferUpload.Get());

            D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
            uavDesc.Format = DXGI_FORMAT_UNKNOWN;
            uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
            uavDesc.Buffer.FirstElement = 0;
            uavDesc.Buffer.NumElements = 1;
            uavDesc.Buffer.StructureByteStride = sizeof(data[0]);
            uavDesc.Buffer.CounterOffsetInBytes = 0;
            uavDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE;

            CD3DX12_CPU_DESCRIPTOR_HANDLE uavHandle0(m_UavHeap->GetCPUDescriptorHandleForHeapStart(),Uav,m_UavDescriptorSize);
            m_device->CreateUnorderedAccessView(m_dataBuffer.Get(),&uavDesc,uavHandle0);
        } // Initialize the data in the buffers.

        std::cout << "   Closing the command list and executing it to begind the initial GPU setup" << std::endl;
        // Close the command list and execute it to begin the initial GPU setup.
        DX::ThrowIfFailed(m_commandList->Close());
        ID3D12CommandList* ppCommandLists[] = { m_commandList.Get() };
        m_commandQueue->ExecuteCommandLists(_countof(ppCommandLists),ppCommandLists);

        std::cout << "   Creating synchronization objects and wait until assets have been uploaded to the GPU" << std::endl;
        // Create synchronization objects and wait until assets have been uploaded to the GPU.
        {
            DX::ThrowIfFailed(m_device->CreateFence(m_renderContextFenceValue,D3D12_FENCE_FLAG_NONE,IID_PPV_ARGS(&m_renderContextFence)));
            m_renderContextFenceValue++;

            m_renderContextFenceEvent = CreateEvent(nullptr,FALSE,nullptr);
            if (m_renderContextFenceEvent == nullptr) {
                DX::ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError()));
            }

            // Add a signal command to the queue.
            DX::ThrowIfFailed(m_commandQueue->Signal(m_renderContextFence.Get(),m_renderContextFenceValue));

            // Instruct the fence to set the event object when the signal command completes.
            DX::ThrowIfFailed(m_renderContextFence->SetEventOnCompletion(m_renderContextFenceValue,m_renderContextFenceEvent));
            m_renderContextFenceValue++;

            // Wait until the signal command has been processed.
            WaitForSingleObject(m_renderContextFenceEvent,INFINITE);
        }
    } // Load the sample assets.

    std::cout << "Creating compute resources" << std::endl;
    {
        // Create compute resources.
        D3D12_COMMAND_QUEUE_DESC queueDesc = { D3D12_COMMAND_LIST_TYPE_COMPUTE,D3D12_COMMAND_QUEUE_FLAG_NONE };
        DX::ThrowIfFailed(m_device->CreateCommandQueue(&queueDesc,IID_PPV_ARGS(&m_computeCommandQueue)));
        DX::ThrowIfFailed(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_COMPUTE,IID_PPV_ARGS(&m_computeAllocator)));
        DX::ThrowIfFailed(m_device->CreateCommandList(0,D3D12_COMMAND_LIST_TYPE_COMPUTE,m_computeAllocator.Get(),IID_PPV_ARGS(&m_computeCommandList)));
        DX::ThrowIfFailed(m_device->CreateFence(0,D3D12_FENCE_FLAG_SHARED,IID_PPV_ARGS(&m_Fence)));

        m_FenceEvent = CreateEvent(nullptr,nullptr);
        if (m_FenceEvent == nullptr) {
            DX::ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError()));
        }
    }

    std::cout << "Calculating" << std::endl;
    Calculate();
    std::cout << "Finished" << std::endl;
}


void myClass::Calculate() {
    m_computeCommandList.Get()->ResourceBarrier(1,D3D12_RESOURCE_STATE_COMMON,D3D12_RESOURCE_STATE_UNORDERED_ACCESS));

    m_computeCommandList.Get()->SetPipelineState(m_computeState.Get());
    m_computeCommandList.Get()->SetComputeRootSignature(m_computeRootSignature.Get());

    ID3D12DescriptorHeap* ppHeaps[] = { m_UavHeap.Get() };
    m_computeCommandList.Get()->SetDescriptorHeaps(_countof(ppHeaps),ppHeaps);

    CD3DX12_GPU_DESCRIPTOR_HANDLE uavHandle(m_UavHeap->GetGPUDescriptorHandleForHeapStart(),m_UavDescriptorSize);
    
    m_computeCommandList.Get()->SetComputeRootUnorderedAccessView(ComputeRootUAVTable,m_dataBuffer->GetGPUVirtualAddress());

    m_computeCommandList.Get()->Dispatch(1,1);
    
    m_computeCommandList.Get()->ResourceBarrier(1,D3D12_RESOURCE_STATE_UNORDERED_ACCESS,D3D12_RESOURCE_STATE_COMMON));


    // Close and execute the command list.
    DX::ThrowIfFailed(m_computeCommandList.Get()->Close());
    ID3D12CommandList* commandLists[] = { m_computeCommandList.Get() };
    m_computeCommandQueue->ExecuteCommandLists(1,commandLists);

    // Wait for the compute shader to complete the calculation.
    UINT64 FenceValue = InterlockedIncrement(&m_FenceValue);
    DX::ThrowIfFailed(m_computeCommandQueue.Get()->Signal(m_Fence.Get(),FenceValue));
    DX::ThrowIfFailed(m_Fence.Get()->SetEventOnCompletion(FenceValue,m_FenceEvent));
    WaitForSingleObject(m_FenceEvent,INFINITE);

    std::cout << "FenceValue = " << FenceValue << " " << m_FenceValue << " " << m_Fence.Get()->GetCompletedValue() << std::endl;

    // Check the output!
    float* dataptr = nullptr;
    D3D12_RANGE range = { 0,readbackBufferDesc.Width };
    DX::ThrowIfFailed(m_dataBufferReadback->Map(0,&range,(void**)&dataptr));
    for (int i = 0; i < readbackBufferDesc.Width / sizeof(data[0]); i++)
        printf("uav[%d] = %.2f\n",i,dataptr[i]);
    m_dataBufferReadback->Unmap(0,nullptr);
    for (unsigned int i = 0; i < data.size(); i++) {
        std::cout << "data[" << i << "] = " << data[i] << std::endl;
    }
    
}

myClass.h:

#pragma once
#include "Common\Device.h"
#include <iostream>

// We have to write all of this as its own class,otherwise we cannot
// use the "this" pointer when we create compute resources. We need to
// do that because this code tagets multithreading.

class myClass {
public:
    myClass();

private:
    // Two buffers full of data are used. The compute thread alternates 
    // writing to each of them. The render thread renders using the 
    // buffer that is not currently in use by the compute shader.
    //struct Data {
    //  float c;
    //};
    //std::vector<Data> data;
    std::vector<float> data;

    // For the compute pipeline,the CBV is a struct containing some 
    // constants used in the compute shader.
    struct ConstantBufferCS {
        float a;
        float b;
    };

    D3D12_SUBRESOURCE_DATA dataSubResource;

    static const UINT FrameCount = 1;
    //static const UINT ThreadCount = 1;

    UINT m_heightInstances;
    UINT m_widthInstances;

    UINT m_frameIndex;
    Microsoft::WRL::ComPtr<ID3D12RootSignature> m_rootSignature;
    Microsoft::WRL::ComPtr<ID3D12RootSignature> m_computeRootSignature;
    Microsoft::WRL::ComPtr<ID3D12CommandQueue> m_commandQueue;
    Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> m_UavHeap;
    Microsoft::WRL::ComPtr<ID3D12CommandAllocator> m_commandAllocators[FrameCount];
    Microsoft::WRL::ComPtr<ID3D12PipelineState> m_computeState;
    Microsoft::WRL::ComPtr<ID3D12GraphicsCommandList> m_commandList;
    Microsoft::WRL::ComPtr<ID3D12Resource> m_constantBufferCS;
    UINT64 m_renderContextFenceValue;
    HANDLE m_renderContextFenceEvent;
    UINT64 m_frameFenceValues[FrameCount];
    UINT m_UavDescriptorSize;

    ConstantBufferCS constantBufferCS;
    Microsoft::WRL::ComPtr<ID3D12Resource> constantBufferCSUpload;

    Microsoft::WRL::ComPtr<ID3D12Fence> m_renderContextFence;

    Microsoft::WRL::ComPtr<ID3D12Resource> m_dataBuffer;
    Microsoft::WRL::ComPtr<ID3D12Resource> m_dataBufferUpload;
    Microsoft::WRL::ComPtr<ID3D12Resource> m_dataBufferReadback;

    // Compute objects.
    Microsoft::WRL::ComPtr<ID3D12CommandAllocator> m_computeAllocator;
    Microsoft::WRL::ComPtr<ID3D12CommandQueue> m_computeCommandQueue;
    Microsoft::WRL::ComPtr<ID3D12GraphicsCommandList> m_computeCommandList;
    Microsoft::WRL::ComPtr<ID3D12Fence> m_Fence;
    volatile HANDLE m_FenceEvent;

    D3D12_RESOURCE_DESC readbackBufferDesc;

    // State
    UINT64 volatile m_FenceValue;
    /*
    struct ThreadData {
        myClass* pContext;
        UINT threadIndex;
    };
    ThreadData m_threadData;
    HANDLE m_threadHandles;
    */
    void Calculate();

    // Indices of shader resources in the descriptor heap.
    enum DescriptorHeapIndex : UINT32 {
        Uav = 0,DescriptorCount = 1
    };

    enum ComputeRootParameters : UINT32 {
        //ComputeRootCBV = 0,ComputeRootUAVTable = 0,ComputeRootParametersCount
    };

};

设备.cpp:

#pragma once
#include "pch.h"
#include "Device.h"
#include "DirectXHelper.h"
#include <cassert> // for "assert"
#include <iostream>

static Device* gs_pSingelton = nullptr;

// Constructor
Device::Device(HINSTANCE hInst,bool useWarp)
    : m_hInstance(hInst),m_useWarp(useWarp)
{
}

void Device::Initialize() {
#if defined(_DEBUG)
    // Always enable the debug layer before doing anything DX12 related
    // so all possible errors generated while creating DX12 objects
    // are caught by the debug layer.
    Microsoft::WRL::ComPtr<ID3D12Debug1> debugInterface;
    DX::ThrowIfFailed(D3D12GetDebugInterface(IID_PPV_ARGS(&debugInterface)));
    debugInterface->EnableDebugLayer();
    // Enable these if you want full validation (will slow down rendering a lot).
    //debugInterface->SetEnableGPUBasedValidation(TRUE);
    //debugInterface->SetEnableSynchronizedCommandQueueValidation(TRUE);
#endif
    auto dxgiAdapter = GetAdapter(false);
    if (!dxgiAdapter) { // If no supporting DX12 adapters exist,fall back to WARP
        dxgiAdapter = GetAdapter(true);
    }
    if (dxgiAdapter) {
        m_device = CreateDevice(dxgiAdapter);
    }
    else {
        throw std::exception("DXGI adapter enumeration failed.");
    }
}

void Device::Create(HINSTANCE hInst) {
    if (!gs_pSingelton) {
        gs_pSingelton = new Device(hInst);
        gs_pSingelton->Initialize();
    }
}

Device& Device::Get() {
    assert(gs_pSingelton);
    return *gs_pSingelton;
}

void Device::Destroy() {
    if (gs_pSingelton) {
        delete gs_pSingelton;
        gs_pSingelton = nullptr;
    }
}

// Destructor
Device::~Device() {
}


Microsoft::WRL::ComPtr<ID3D12Device2> Device::CreateDevice(Microsoft::WRL::ComPtr<IDXGIAdapter4> adapter) {
    Microsoft::WRL::ComPtr<ID3D12Device2> d3d12Device2;
    DX::ThrowIfFailed(D3D12CreateDevice(adapter.Get(),D3D_FEATURE_LEVEL_11_0,IID_PPV_ARGS(&d3d12Device2)));

    // Enable debug messages in debug mode.
#if defined(_DEBUG)
    Microsoft::WRL::ComPtr<ID3D12InfoQueue> pInfoQueue;
    if (SUCCEEDED(d3d12Device2.As(&pInfoQueue))) {
        pInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION,TRUE);
        pInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR,TRUE);
        pInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING,TRUE);
        // Suppress whole categories of messages
        //D3D12_MESSAGE_CATEGORY Categories[] = {};

        // Suppress messages based on their severity level
        D3D12_MESSAGE_SEVERITY Severities[] = { D3D12_MESSAGE_SEVERITY_INFO };

        // Suppress individual messages by their ID
        D3D12_MESSAGE_ID DenyIds[] = {
            D3D12_MESSAGE_ID_CLEARRENDERTARGETVIEW_MISMATCHINGCLEARVALUE,// I'm really not sure how to avoid this message.
            D3D12_MESSAGE_ID_MAP_INVALID_NULLRANGE,// This warning occurs when using capture frame while graphics debugging.
            D3D12_MESSAGE_ID_UNMAP_INVALID_NULLRANGE,// This warning occurs when using capture frame while graphics debugging.
        };

        D3D12_INFO_QUEUE_FILTER NewFilter = {};
        //NewFilter.DenyList.NumCategories = _countof(Categories);
        //NewFilter.DenyList.pCategoryList = Categories;
        NewFilter.DenyList.NumSeverities = _countof(Severities);
        NewFilter.DenyList.pSeverityList = Severities;
        NewFilter.DenyList.NumIDs = _countof(DenyIds);
        NewFilter.DenyList.pIDList = DenyIds;

        DX::ThrowIfFailed(pInfoQueue->PushStorageFilter(&NewFilter));
    }
#endif
    return d3d12Device2;
}

Microsoft::WRL::ComPtr<IDXGIAdapter4> Device::GetAdapter(bool useWarp) {
    UINT createFactoryFlags = 0;
#if defined(_DEBUG)
    createFactoryFlags = DXGI_CREATE_FACTORY_DEBUG;
#endif

    DX::ThrowIfFailed(CreateDXGIFactory2(createFactoryFlags,IID_PPV_ARGS(&m_factory)));

    Microsoft::WRL::ComPtr<IDXGIAdapter1> dxgiAdapter1;
    Microsoft::WRL::ComPtr<IDXGIAdapter4> dxgiAdapter4;

    if (useWarp) {
        DX::ThrowIfFailed(m_factory->EnumWarpAdapter(IID_PPV_ARGS(&dxgiAdapter1)));
        DX::ThrowIfFailed(dxgiAdapter1.As(&dxgiAdapter4));
    }
    else {
        SIZE_T maxDedicatedVideoMemory = 0;
        for (UINT i = 0; m_factory->EnumAdapters1(i,&dxgiAdapter1) != DXGI_ERROR_NOT_FOUND; ++i) {
            DXGI_ADAPTER_DESC1 dxgiAdapterDesc1;
            dxgiAdapter1->GetDesc1(&dxgiAdapterDesc1);

            // Check to see if the adapter can create a D3D12 device without actually 
            // creating it. The adapter with the largest dedicated video memory
            // is favored.
            if ((dxgiAdapterDesc1.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) == 0 &&
                SUCCEEDED(D3D12CreateDevice(dxgiAdapter1.Get(),__uuidof(ID3D12Device),nullptr)) &&
                dxgiAdapterDesc1.DedicatedVideoMemory > maxDedicatedVideoMemory) {
                maxDedicatedVideoMemory = dxgiAdapterDesc1.DedicatedVideoMemory;
                DX::ThrowIfFailed(dxgiAdapter1.As(&dxgiAdapter4));
            }
        }
    }

    return dxgiAdapter4;
}

设备.h:

#pragma once

#include <dxgi1_6.h> // IDXGIAdapter4

// We require this file because we are unable to pass the device pointer to everywhere we need to.

class Device {
public:
    /**
    * Create the device singleton with the device instance handle.
    */
    static void Create(HINSTANCE hInst);

    /**
    * Destroy the device instance.
    */
    static void Destroy();

    /**
    * Get the device singleton.
    */
    static Device& Get();

    /**
     * Get the Direct3D 12 device
     */
    Microsoft::WRL::ComPtr<ID3D12Device2> GetDevice() const { return m_device; }
    Microsoft::WRL::ComPtr<IDXGIFactory4> GetFactory() const { return m_factory; }

protected:
    // Create a device instance
    Device(HINSTANCE hInst,bool useWarp = false);
    // Destroy the device instance.
    virtual ~Device();

    // Initialize the device instance.
    void Initialize();
    Microsoft::WRL::ComPtr<IDXGIAdapter4> GetAdapter(bool useWarp);
    Microsoft::WRL::ComPtr<ID3D12Device2> CreateDevice(Microsoft::WRL::ComPtr<IDXGIAdapter4> adapter);
private:
    Device(const Device& copy) = delete;
    Device& operator=(const Device& other) = delete;
    HINSTANCE m_hInstance;
    Microsoft::WRL::ComPtr<ID3D12Device2> m_device;
    Microsoft::WRL::ComPtr<IDXGIFactory4> m_factory;
    bool m_useWarp;
};

ComputeShader.hlsl:

RWStructuredBuffer<float> output : register(u0);    // UAV

[numthreads(1,1)]
void main( uint3 DTid : SV_DispatchThreadID ) {
    output[DTid.x] = 1 + 1;
}

如果您能找到我不明白的地方,请告诉我。如果有帮助,我也可以尝试将我的项目上传到 GitHub... SOS :(

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res