summaryrefslogtreecommitdiffstats
path: root/Projects/Asteroids/src/asteroids_d3d12.h
blob: fb2297b61f19dbfa29e46869d4d6624292afd61f (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
174
175
176
177
178
179
180
181
182
183
// Copyright 2014 Intel Corporation All Rights Reserved
//
// Intel makes no representations about the suitability of this software for any purpose.  
// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES,
// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES,
// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY
// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
// Intel does not assume any responsibility for any errors which may appear in this software
// nor any responsibility to update it.

#pragma once

#include <d3d11.h>
#include <d3d12.h>
#include <dxgi1_4.h>
#include <directxmath.h>
#include <deque>
#include <random>
#include <map>

#include "camera.h"
#include "settings.h"
#include "simulation.h"
#include "subset_d3d12.h"
#include "descriptor.h"
#include "upload_heap.h"
#include "util.h"
#include "gui.h"

namespace AsteroidsD3D12 {

CBUFFER_ALIGN struct DrawConstantBuffer {
    DirectX::XMFLOAT4X4 mWorld;
    DirectX::XMFLOAT4X4 mViewProjection;
    DirectX::XMFLOAT3 mSurfaceColor;
    float unused0;
    DirectX::XMFLOAT3 mDeepColor;
    float unused1;
    UINT mTextureIndex;
    UINT unused2[3];
};

CBUFFER_ALIGN struct SkyboxConstantBuffer {
    DirectX::XMFLOAT4X4 mViewProjection;
};

struct ExecuteIndirectArgs {
    D3D12_GPU_VIRTUAL_ADDRESS mConstantBuffer;
    D3D12_DRAW_INDEXED_ARGUMENTS mDrawIndexed;
};

struct DynamicUploadHeap {
    DrawConstantBuffer mDrawConstantBuffers[NUM_ASTEROIDS];
    SkyboxConstantBuffer mSkyboxConstants;
    ExecuteIndirectArgs mIndirectArgs[NUM_ASTEROIDS];
    SpriteVertex mSpriteVertices[MAX_SPRITE_VERTICES_PER_FRAME];
};

class Asteroids {
public:
    Asteroids(AsteroidsSimulation* asteroids, GUI *gui, UINT minCmdLsts, IDXGIAdapter* adapter);
    ~Asteroids();

    void WaitForReadyToRender();
    void Render(float frameTime, const OrbitCamera& camera, const Settings& settings);

    void ReleaseSwapChain();
    void ResizeSwapChain(IDXGIFactory2* dxgiFactory, HWND outputWindow, unsigned int width, unsigned int height);

    void GetPerfCounters(float &UpdateTime, float &RenderTime);

private:
    void WaitForAll();

    void RenderSubset(
        D3D12_CPU_DESCRIPTOR_HANDLE renderTargetView,
        size_t frameIndex, float frameTime,
        SubsetD3D12* subset, UINT subsetIdx,
        DirectX::XMVECTOR cameraEye, DirectX::XMMATRIX viewProjection,
        const Settings& settings);

    void CreatePSOs();

    void CreateSubsets(UINT numHeapsPerFrame);
    void ReleaseSubsets();

    void CreateMeshes();
    void CreateGUIResources();

    struct Frame {
        std::vector<SubsetD3D12*>   mSubsets;
        ID3D12CommandAllocator*     mCmdAlloc = nullptr;

        UploadHeapT<DynamicUploadHeap>* mDynamicUpload = nullptr;
        D3D12_VERTEX_BUFFER_VIEW    mSpriteVertexBufferView;
        D3D12_GPU_VIRTUAL_ADDRESS   mDrawConstantBuffersGPUVA;

        // Descriptor heap and associated GPU handles
        SRVDescriptorList*          mSRVDescs = nullptr;
        D3D12_GPU_VIRTUAL_ADDRESS   mSkyboxConstants;
        D3D12_GPU_DESCRIPTOR_HANDLE mSkyboxTexture;
        UINT                        mSRVDescsDynamicStart = 0;

        UINT64                      mFrameCompleteFence = 0;
    } mFrame[NUM_FRAMES_TO_BUFFER];

    // Swap chain resources
    struct SwapChainBuffer {
        ID3D12Resource*             mRenderTarget = nullptr;
        D3D12_CPU_DESCRIPTOR_HANDLE mRenderTargetView;
    } mSwapChainBuffer[NUM_SWAP_CHAIN_BUFFERS];

    // Swap chain stuff
    IDXGISwapChain3*            mSwapChain = nullptr;
    DXGI_FORMAT                 mRTVFormat;
    D3D12_VIEWPORT              mViewPort;
    D3D11_RECT                  mScissorRect;

    // Fences and synchronization
    size_t                      mCurrentFrameIndex = 0;
    ID3D12Fence*                mFence = nullptr;
    HANDLE                      mFenceEventHandle = NULL;
    UINT64                      mCurrentFence = 0;
    
    // Device
    ID3D12Device*               mDevice = nullptr;
    ID3D12CommandQueue*         mCommandQueue = nullptr;

    // Root signature, descriptors and binding
    ID3D12RootSignature*        mGenericRootSignature = nullptr;
    ID3D12RootSignature*        mAsteroidsRootSignature = nullptr;
    ID3D12CommandSignature*     mCommandSignature = nullptr;
    RTVDescriptorList*          mRTVDescs = nullptr;
    DSVDescriptorList*          mDSVDescs = nullptr;
    SRVDescriptorList*          mSRVDescs = nullptr;
    SMPDescriptorList*          mSMPDescs = nullptr;
    D3D12_CPU_DESCRIPTOR_HANDLE mDepthStencilView;
    D3D12_GPU_DESCRIPTOR_HANDLE mSampler;
    D3D12_VERTEX_BUFFER_VIEW    mSkyboxVertexBufferView;
    D3D12_INDEX_BUFFER_VIEW     mAsteroidIndexBufferView;
    D3D12_VERTEX_BUFFER_VIEW    mAsteroidVertexBufferView;
    
    // Command lists
    ID3D12GraphicsCommandList*  mPreCmdLst = nullptr;
    ID3D12GraphicsCommandList*  mPostCmdLst = nullptr;

    DXGI_FORMAT                 mDSVFormat;
    ID3D12Resource*             mDepthStencil = nullptr;

    AsteroidsSimulation*        mAsteroids = nullptr;
    ID3D12Resource*             mAsteroidTextures[NUM_UNIQUE_TEXTURES];

    // Mesh
    UploadHeap*                 mMeshUpload = nullptr;
    UINT                        mIndexOffsets[MESH_MAX_SUBDIV_LEVELS + 2]; // inclusive
    UINT                        mNumVerticesPerMesh = 0;
    
    ID3D12PipelineState*        mAsteroidPSO = nullptr;
    
    ID3D12PipelineState*        mSkyboxPSO = nullptr;
    ID3D12Resource*             mSkybox = nullptr;

    ID3D12PipelineState*        mFontPSO = nullptr;
    ID3D12Resource*             mFontTexture = nullptr;

    ID3D12PipelineState*        mSpritePSO = nullptr;
    std::map<std::string, ID3D12Resource*> mSpriteTextures;
        
    GUI*                        mGUI = nullptr;
    
    // Transient, just here to avoid allocations each frame
    std::vector<ID3D12GraphicsCommandList*> mCmdListsToSubmit;

    UINT                        mSubsetCount = 0;
    UINT                        mDrawsPerSubset = 0;

    GUISprite*                  mD3D12Sprite = nullptr;
    
    UINT64 mPerfCounterFreq = 0;
    volatile LONG64 mTotalUpdateTicks = 0, mTotalRenderTicks = 0;
};

} // namespace AsteroidsD3D12