aboutsummaryrefslogtreecommitdiff
path: root/dxg/src/dxcommon.c
blob: ecc9a8833e827086e0b57d644ed18bc27e55debe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#include <dxg/dxcommon.h>

// Required so that D3D12.dll can find and load D3D12Core.dll and other DLLs
// from the Agility SDK. The macro comes from CMakeLists.txt.
__declspec(dllexport) extern const UINT  D3D12SDKVersion = AGILITY_SDK_VERSION;
__declspec(dllexport) extern const char* D3D12SDKPath    = AGILITY_SDK_INSTALL;
D3D12_RESOURCE_BARRIER CD3DX12_RESOURCE_BARRIER_Transition(
    ID3D12Resource*       pResource,
    D3D12_RESOURCE_STATES stateBefore,
    D3D12_RESOURCE_STATES stateAfter) {
    return (D3D12_RESOURCE_BARRIER){
        .Type                   = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
        .Flags                  = D3D12_RESOURCE_BARRIER_FLAG_NONE,
        .Transition.pResource   = pResource,
        .Transition.StateBefore = stateBefore,
        .Transition.StateAfter  = stateAfter,
        .Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES};
}

D3D12_RASTERIZER_DESC CD3DX12_RASTERIZER_DESC_DEFAULT() {
    return (D3D12_RASTERIZER_DESC){
        .FillMode              = D3D12_FILL_MODE_SOLID,
        .CullMode              = D3D12_CULL_MODE_BACK,
        .FrontCounterClockwise = FALSE,
        .DepthBias             = D3D12_DEFAULT_DEPTH_BIAS,
        .DepthBiasClamp        = D3D12_DEFAULT_DEPTH_BIAS_CLAMP,
        .SlopeScaledDepthBias  = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS,
        .DepthClipEnable       = TRUE,
        .MultisampleEnable     = FALSE,
        .AntialiasedLineEnable = FALSE,
        .ForcedSampleCount     = 0,
        .ConservativeRaster    = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF};
}

D3D12_BLEND_DESC CD3DX12_BLEND_DESC_DEFAULT() {
    const D3D12_RENDER_TARGET_BLEND_DESC defaultRenderTargetBlendDesc = {
        FALSE, FALSE,
        D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,
        D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,
        D3D12_LOGIC_OP_NOOP,
        D3D12_COLOR_WRITE_ENABLE_ALL,
    };
    D3D12_BLEND_DESC desc = {
        .AlphaToCoverageEnable  = FALSE,
        .IndependentBlendEnable = FALSE,
    };
    for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) {
        desc.RenderTarget[i] = defaultRenderTargetBlendDesc;
    }
    return desc;
}

void dxg_wait(ID3D12Fence* pFence, HANDLE fenceEvent, UINT64 fenceValue) {
    assert(pFence);
    // Wait for commands to finish execution.
    // It is possible that execution has already finished by the time we
    // get here, so first check the fence's completed value.
    if (pFence->lpVtbl->GetCompletedValue(pFence) < fenceValue) {
        // GPU Signal still pending. Configure a Windows event and wait for it.
        // The event fires when the GPU signals.
        //
        // Indicate that the fence event is to be fired when the fence reaches
        // the given fence value.
        TrapIfFailed(pFence->lpVtbl->SetEventOnCompletion(pFence, fenceValue, fenceEvent));
        // Will wake up when the fence takes on the given fence value.
        WaitForSingleObject(fenceEvent, INFINITE);
    }
}

// -----------------------------------------------------------------------------
// Command Recorder
// -----------------------------------------------------------------------------

HRESULT dxg_cmdrec_init(CommandRecorder* pRec, ID3D12Device* pDevice) {
    assert(pRec);
    assert(pDevice);

    HRESULT result = S_OK;

    const D3D12_COMMAND_LIST_TYPE type = D3D12_COMMAND_LIST_TYPE_DIRECT;

    if ((result = pDevice->lpVtbl->CreateCommandAllocator(
        pDevice, type, &IID_ID3D12CommandAllocator, &pRec->pCmdAllocator)) != S_OK) {
        return result;
    }

    if ((result = pDevice->lpVtbl->CreateCommandList(
        pDevice, 0, type, pRec->pCmdAllocator, NULL, &IID_ID3D12CommandList, &pRec->pCmdList)) != S_OK) {
        return result;
    }

    // Command lists start open. Close it for API convenience.
    if ((result = pRec->pCmdList->lpVtbl->Close(pRec->pCmdList)) != S_OK) {
        return result;
    }

    return result;
}

void dxg_cmdrec_destroy(CommandRecorder* pRec) {
    assert(pRec);
    SafeRelease(pRec->pCmdList);
    SafeRelease(pRec->pCmdAllocator);
}

HRESULT dxg_cmdrec_reset(CommandRecorder* pRec) {
    assert(pRec);
    assert(pRec->pCmdAllocator);
    assert(pRec->pCmdList);
    HRESULT result = S_OK;
    if ((result = pRec->pCmdAllocator->lpVtbl->Reset(pRec->pCmdAllocator)) != S_OK) {
        return result;
    }
    if ((result = pRec->pCmdList->lpVtbl->Reset(pRec->pCmdList, pRec->pCmdAllocator, NULL)) != S_OK) {
        return result;
    }
    return result;
}

// -----------------------------------------------------------------------------
// Upload Buffer
// -----------------------------------------------------------------------------

void dxg_upload_buffer_init(UploadBuffer* pBuf, ID3D12Device* pDevice, size_t size) {
    assert(pBuf);
    assert(pDevice);

    pBuf->size = size;

    const D3D12_HEAP_PROPERTIES props = {
        .Type                 = D3D12_HEAP_TYPE_UPLOAD,
        .CPUPageProperty      = D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE,
        .MemoryPoolPreference = D3D12_MEMORY_POOL_L0,
        .CreationNodeMask     = 0,
        .VisibleNodeMask      = 0
    };
    // Constant buffers need to be aligned to 256 bytes. Other types of buffers
    // do not have this requirement. To make the upload buffer general, use the
    // worst-case alignment.
    const D3D12_RESOURCE_DESC desc = {
        .Dimension        = D3D12_RESOURCE_DIMENSION_BUFFER,
        .Alignment        = 256,
        .Width            = size,
        .Height           = 0,
        .DepthOrArraySize = 0,
        .MipLevels        = 0,
        .Format           = DXGI_FORMAT_UNKNOWN,
        .SampleDesc       = (DXGI_SAMPLE_DESC){0},
        .Layout           = D3D12_TEXTURE_LAYOUT_UNKNOWN,
        .Flags            = D3D12_RESOURCE_FLAG_NONE
    };
    TrapIfFailed(pDevice->lpVtbl->CreateCommittedResource(
        pDevice,
        &props,
        D3D12_HEAP_FLAG_NONE,
        &desc,
        D3D12_RESOURCE_STATE_COPY_SOURCE,
        NULL,
        &IID_ID3D12Resource,
        &pBuf->pUploadBuffer));
}

void dxg_upload_buffer_destroy(UploadBuffer* pBuf, ID3D12Device* pDevice) {
    assert(pDevice);
    assert(pBuf);
    SafeRelease(pBuf->pUploadBuffer);
}

void dxg_upload_buffer_load(UploadBuffer* pBuf, const void* pData, size_t bytes, ID3D12Resource* pDstBuffer) {
    assert(pBuf);
    assert(pData);
    assert(pDstBuffer);
}