summaryrefslogtreecommitdiffstats
path: root/src/d3d11/gpu.h
blob: cbc706ac9026b29af1b6c4159c90b3de653f4e8b (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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
/*
 * This file is part of libplacebo.
 *
 * libplacebo is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * libplacebo is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with libplacebo. If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <stdalign.h>
#include <d3d11_4.h>
#include <dxgi1_6.h>
#include <d3dcompiler.h>
#include <spirv_cross_c.h>

#include "../gpu.h"
#include "../glsl/spirv.h"

#include "common.h"
#include "utils.h"

pl_gpu pl_gpu_create_d3d11(struct d3d11_ctx *ctx);

// --- pl_gpu internal structs and helpers

// Size of one constant in a constant buffer
#define CBUF_ELEM (sizeof(float[4]))

struct d3d_stream_buf {
    UINT bind_flags;
    ID3D11Buffer *buf;
    size_t size;
    size_t used;
    unsigned int align;
};

struct pl_gpu_d3d11 {
    struct pl_gpu_fns impl;
    struct d3d11_ctx *ctx;
    ID3D11Device *dev;
    ID3D11Device1 *dev1;
    ID3D11Device5 *dev5;
    ID3D11DeviceContext *imm;
    ID3D11DeviceContext1 *imm1;
    ID3D11DeviceContext4 *imm4;

    // The Direct3D 11 minor version number
    int minor;

    pl_spirv spirv;

    pD3DCompile D3DCompile;
    struct dll_version d3d_compiler_ver;

    // Device capabilities
    D3D_FEATURE_LEVEL fl;
    bool has_timestamp_queries;
    bool has_monitored_fences;

    int max_srvs;
    int max_uavs;

    // Streaming vertex and index buffers
    struct d3d_stream_buf vbuf;
    struct d3d_stream_buf ibuf;

    // Shared rasterizer state
    ID3D11RasterizerState *rstate;

    // Shared depth-stencil state
    ID3D11DepthStencilState *dsstate;

    // Array of ID3D11SamplerStates for every combination of sample/address modes
    ID3D11SamplerState *samplers[PL_TEX_SAMPLE_MODE_COUNT][PL_TEX_ADDRESS_MODE_COUNT];

    // Resources for finish()
    ID3D11Fence *finish_fence;
    uint64_t finish_value;
    HANDLE finish_event;
    ID3D11Query *finish_query;
    pl_buf finish_buf_src;
    pl_buf finish_buf_dst;
};

void pl_d3d11_setup_formats(struct pl_gpu_t *gpu);

void pl_d3d11_timer_start(pl_gpu gpu, pl_timer timer);
void pl_d3d11_timer_end(pl_gpu gpu, pl_timer timer);

struct pl_buf_d3d11 {
    ID3D11Buffer *buf;
    ID3D11Buffer *staging;
    ID3D11ShaderResourceView *raw_srv;
    ID3D11UnorderedAccessView *raw_uav;
    ID3D11ShaderResourceView *texel_srv;
    ID3D11UnorderedAccessView *texel_uav;

    char *data;
    bool dirty;
};

void pl_d3d11_buf_destroy(pl_gpu gpu, pl_buf buf);
pl_buf pl_d3d11_buf_create(pl_gpu gpu, const struct pl_buf_params *params);
void pl_d3d11_buf_write(pl_gpu gpu, pl_buf buf, size_t offset, const void *data,
                        size_t size);
bool pl_d3d11_buf_read(pl_gpu gpu, pl_buf buf, size_t offset, void *dest,
                       size_t size);
void pl_d3d11_buf_copy(pl_gpu gpu, pl_buf dst, size_t dst_offset, pl_buf src,
                       size_t src_offset, size_t size);

// Ensure a buffer is up-to-date with its system memory mirror before it is used
void pl_d3d11_buf_resolve(pl_gpu gpu, pl_buf buf);

struct pl_tex_d3d11 {
    // res mirrors one of tex1d, tex2d or tex3d for convenience. It does not
    // hold an additional reference to the texture object.
    ID3D11Resource *res;

    ID3D11Texture1D *tex1d;
    ID3D11Texture2D *tex2d;
    ID3D11Texture3D *tex3d;
    int array_slice;

    // Mirrors one of staging1d, staging2d, or staging3d, and doesn't hold a ref
    ID3D11Resource *staging;

    // Staging textures for pl_tex_download
    ID3D11Texture1D *staging1d;
    ID3D11Texture2D *staging2d;
    ID3D11Texture3D *staging3d;

    ID3D11ShaderResourceView *srv;
    ID3D11RenderTargetView *rtv;
    ID3D11UnorderedAccessView *uav;

    // for tex_upload/download fallback code
    pl_fmt texel_fmt;
};

void pl_d3d11_tex_destroy(pl_gpu gpu, pl_tex tex);
pl_tex pl_d3d11_tex_create(pl_gpu gpu, const struct pl_tex_params *params);
void pl_d3d11_tex_invalidate(pl_gpu gpu, pl_tex tex);
void pl_d3d11_tex_clear_ex(pl_gpu gpu, pl_tex tex,
                           const union pl_clear_color color);
void pl_d3d11_tex_blit(pl_gpu gpu, const struct pl_tex_blit_params *params);
bool pl_d3d11_tex_upload(pl_gpu gpu, const struct pl_tex_transfer_params *params);
bool pl_d3d11_tex_download(pl_gpu gpu, const struct pl_tex_transfer_params *params);

// Constant buffer layout used for gl_NumWorkGroups emulation
struct d3d_num_workgroups_buf {
    alignas(CBUF_ELEM) uint32_t num_wgs[3];
};

enum {
    HLSL_BINDING_NOT_USED = -1, // Slot should always be bound as NULL
    HLSL_BINDING_NUM_WORKGROUPS = -2, // Slot used for gl_NumWorkGroups emulation
};

// Represents a specific shader stage in a pl_pass (VS, PS, CS)
struct d3d_pass_stage {
    // Lists for each resource type, to simplify binding in pl_pass_run. Indexes
    // match the index of the arrays passed to the ID3D11DeviceContext methods.
    // Entries are the index of pass->params.descriptors which should be bound
    // in that position, or a HLSL_BINDING_* special value.
    PL_ARRAY(int) cbvs;
    PL_ARRAY(int) srvs;
    PL_ARRAY(int) samplers;
};

struct pl_pass_d3d11 {
    ID3D11PixelShader *ps;
    ID3D11VertexShader *vs;
    ID3D11ComputeShader *cs;
    ID3D11InputLayout *layout;
    ID3D11BlendState *bstate;

    // gl_NumWorkGroups emulation
    struct d3d_num_workgroups_buf last_num_wgs;
    ID3D11Buffer *num_workgroups_buf;
    bool num_workgroups_used;

    // Maximum binding number
    int max_binding;

    struct d3d_pass_stage main; // PS and CS
    struct d3d_pass_stage vertex;

    // List of resources, as in `struct pass_stage`, except UAVs are shared
    // between all shader stages
    PL_ARRAY(int) uavs;

    // Pre-allocated resource arrays to use in pl_pass_run
    ID3D11Buffer **cbv_arr;
    ID3D11ShaderResourceView **srv_arr;
    ID3D11SamplerState **sampler_arr;
    ID3D11UnorderedAccessView **uav_arr;
};

void pl_d3d11_pass_destroy(pl_gpu gpu, pl_pass pass);
const struct pl_pass_t *pl_d3d11_pass_create(pl_gpu gpu,
                                             const struct pl_pass_params *params);
void pl_d3d11_pass_run(pl_gpu gpu, const struct pl_pass_run_params *params);