1 /******************************************************************************
2 Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 ******************************************************************************/
17
18 #pragma once
19
20 #include <util/AlignedNew.hpp>
21 #include <util/windows/win-version.h>
22
23 #include <vector>
24 #include <string>
25 #include <memory>
26
27 #include <windows.h>
28 #include <dxgi1_5.h>
29 #include <d3d11_1.h>
30 #include <d3dcompiler.h>
31
32 #include <util/base.h>
33 #include <graphics/matrix4.h>
34 #include <graphics/graphics.h>
35 #include <graphics/device-exports.h>
36 #include <util/windows/ComPtr.hpp>
37 #include <util/windows/HRError.hpp>
38
39 // #define DISASSEMBLE_SHADERS
40
41 struct shader_var;
42 struct shader_sampler;
43 struct gs_vertex_shader;
44
45 using namespace std;
46
47 /*
48 * Just to clarify, all structs, and all public. These are exporting only
49 * via encapsulated C bindings, not C++ bindings, so the whole concept of
50 * "public" and "private" does not matter at all for this subproject.
51 */
52
GetWinVer()53 static inline uint32_t GetWinVer()
54 {
55 struct win_version_info ver;
56 get_win_ver(&ver);
57
58 return (ver.major << 8) | ver.minor;
59 }
60
ConvertGSTextureFormatResource(gs_color_format format)61 static inline DXGI_FORMAT ConvertGSTextureFormatResource(gs_color_format format)
62 {
63 switch (format) {
64 case GS_UNKNOWN:
65 return DXGI_FORMAT_UNKNOWN;
66 case GS_A8:
67 return DXGI_FORMAT_A8_UNORM;
68 case GS_R8:
69 return DXGI_FORMAT_R8_UNORM;
70 case GS_RGBA:
71 return DXGI_FORMAT_R8G8B8A8_TYPELESS;
72 case GS_BGRX:
73 return DXGI_FORMAT_B8G8R8X8_TYPELESS;
74 case GS_BGRA:
75 return DXGI_FORMAT_B8G8R8A8_TYPELESS;
76 case GS_R10G10B10A2:
77 return DXGI_FORMAT_R10G10B10A2_UNORM;
78 case GS_RGBA16:
79 return DXGI_FORMAT_R16G16B16A16_UNORM;
80 case GS_R16:
81 return DXGI_FORMAT_R16_UNORM;
82 case GS_RGBA16F:
83 return DXGI_FORMAT_R16G16B16A16_FLOAT;
84 case GS_RGBA32F:
85 return DXGI_FORMAT_R32G32B32A32_FLOAT;
86 case GS_RG16F:
87 return DXGI_FORMAT_R16G16_FLOAT;
88 case GS_RG32F:
89 return DXGI_FORMAT_R32G32_FLOAT;
90 case GS_R16F:
91 return DXGI_FORMAT_R16_FLOAT;
92 case GS_R32F:
93 return DXGI_FORMAT_R32_FLOAT;
94 case GS_DXT1:
95 return DXGI_FORMAT_BC1_UNORM;
96 case GS_DXT3:
97 return DXGI_FORMAT_BC2_UNORM;
98 case GS_DXT5:
99 return DXGI_FORMAT_BC3_UNORM;
100 case GS_R8G8:
101 return DXGI_FORMAT_R8G8_UNORM;
102 case GS_RGBA_UNORM:
103 return DXGI_FORMAT_R8G8B8A8_UNORM;
104 case GS_BGRX_UNORM:
105 return DXGI_FORMAT_B8G8R8X8_UNORM;
106 case GS_BGRA_UNORM:
107 return DXGI_FORMAT_B8G8R8A8_UNORM;
108 }
109
110 return DXGI_FORMAT_UNKNOWN;
111 }
112
ConvertGSTextureFormatView(gs_color_format format)113 static inline DXGI_FORMAT ConvertGSTextureFormatView(gs_color_format format)
114 {
115 switch (format) {
116 case GS_RGBA:
117 return DXGI_FORMAT_R8G8B8A8_UNORM;
118 case GS_BGRX:
119 return DXGI_FORMAT_B8G8R8X8_UNORM;
120 case GS_BGRA:
121 return DXGI_FORMAT_B8G8R8A8_UNORM;
122 default:
123 return ConvertGSTextureFormatResource(format);
124 }
125 }
126
127 static inline DXGI_FORMAT
ConvertGSTextureFormatViewLinear(gs_color_format format)128 ConvertGSTextureFormatViewLinear(gs_color_format format)
129 {
130 switch (format) {
131 case GS_RGBA:
132 return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
133 case GS_BGRX:
134 return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB;
135 case GS_BGRA:
136 return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
137 default:
138 return ConvertGSTextureFormatResource(format);
139 }
140 }
141
ConvertDXGITextureFormat(DXGI_FORMAT format)142 static inline gs_color_format ConvertDXGITextureFormat(DXGI_FORMAT format)
143 {
144 switch ((unsigned long)format) {
145 case DXGI_FORMAT_A8_UNORM:
146 return GS_A8;
147 case DXGI_FORMAT_R8_UNORM:
148 return GS_R8;
149 case DXGI_FORMAT_R8G8_UNORM:
150 return GS_R8G8;
151 case DXGI_FORMAT_R8G8B8A8_TYPELESS:
152 return GS_RGBA;
153 case DXGI_FORMAT_B8G8R8X8_TYPELESS:
154 return GS_BGRX;
155 case DXGI_FORMAT_B8G8R8A8_TYPELESS:
156 return GS_BGRA;
157 case DXGI_FORMAT_R10G10B10A2_UNORM:
158 return GS_R10G10B10A2;
159 case DXGI_FORMAT_R16G16B16A16_UNORM:
160 return GS_RGBA16;
161 case DXGI_FORMAT_R16_UNORM:
162 return GS_R16;
163 case DXGI_FORMAT_R16G16B16A16_FLOAT:
164 return GS_RGBA16F;
165 case DXGI_FORMAT_R32G32B32A32_FLOAT:
166 return GS_RGBA32F;
167 case DXGI_FORMAT_R16G16_FLOAT:
168 return GS_RG16F;
169 case DXGI_FORMAT_R32G32_FLOAT:
170 return GS_RG32F;
171 case DXGI_FORMAT_R16_FLOAT:
172 return GS_R16F;
173 case DXGI_FORMAT_R32_FLOAT:
174 return GS_R32F;
175 case DXGI_FORMAT_BC1_UNORM:
176 return GS_DXT1;
177 case DXGI_FORMAT_BC2_UNORM:
178 return GS_DXT3;
179 case DXGI_FORMAT_BC3_UNORM:
180 return GS_DXT5;
181 case DXGI_FORMAT_R8G8B8A8_UNORM:
182 return GS_RGBA_UNORM;
183 case DXGI_FORMAT_B8G8R8X8_UNORM:
184 return GS_BGRX_UNORM;
185 case DXGI_FORMAT_B8G8R8A8_UNORM:
186 return GS_BGRA_UNORM;
187 }
188
189 return GS_UNKNOWN;
190 }
191
ConvertGSZStencilFormat(gs_zstencil_format format)192 static inline DXGI_FORMAT ConvertGSZStencilFormat(gs_zstencil_format format)
193 {
194 switch (format) {
195 case GS_ZS_NONE:
196 return DXGI_FORMAT_UNKNOWN;
197 case GS_Z16:
198 return DXGI_FORMAT_D16_UNORM;
199 case GS_Z24_S8:
200 return DXGI_FORMAT_D24_UNORM_S8_UINT;
201 case GS_Z32F:
202 return DXGI_FORMAT_D32_FLOAT;
203 case GS_Z32F_S8X24:
204 return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
205 }
206
207 return DXGI_FORMAT_UNKNOWN;
208 }
209
ConvertGSDepthTest(gs_depth_test test)210 static inline D3D11_COMPARISON_FUNC ConvertGSDepthTest(gs_depth_test test)
211 {
212 switch (test) {
213 case GS_NEVER:
214 return D3D11_COMPARISON_NEVER;
215 case GS_LESS:
216 return D3D11_COMPARISON_LESS;
217 case GS_LEQUAL:
218 return D3D11_COMPARISON_LESS_EQUAL;
219 case GS_EQUAL:
220 return D3D11_COMPARISON_EQUAL;
221 case GS_GEQUAL:
222 return D3D11_COMPARISON_GREATER_EQUAL;
223 case GS_GREATER:
224 return D3D11_COMPARISON_GREATER;
225 case GS_NOTEQUAL:
226 return D3D11_COMPARISON_NOT_EQUAL;
227 case GS_ALWAYS:
228 return D3D11_COMPARISON_ALWAYS;
229 }
230
231 return D3D11_COMPARISON_NEVER;
232 }
233
ConvertGSStencilOp(gs_stencil_op_type op)234 static inline D3D11_STENCIL_OP ConvertGSStencilOp(gs_stencil_op_type op)
235 {
236 switch (op) {
237 case GS_KEEP:
238 return D3D11_STENCIL_OP_KEEP;
239 case GS_ZERO:
240 return D3D11_STENCIL_OP_ZERO;
241 case GS_REPLACE:
242 return D3D11_STENCIL_OP_REPLACE;
243 case GS_INCR:
244 return D3D11_STENCIL_OP_INCR;
245 case GS_DECR:
246 return D3D11_STENCIL_OP_DECR;
247 case GS_INVERT:
248 return D3D11_STENCIL_OP_INVERT;
249 }
250
251 return D3D11_STENCIL_OP_KEEP;
252 }
253
ConvertGSBlendType(gs_blend_type type)254 static inline D3D11_BLEND ConvertGSBlendType(gs_blend_type type)
255 {
256 switch (type) {
257 case GS_BLEND_ZERO:
258 return D3D11_BLEND_ZERO;
259 case GS_BLEND_ONE:
260 return D3D11_BLEND_ONE;
261 case GS_BLEND_SRCCOLOR:
262 return D3D11_BLEND_SRC_COLOR;
263 case GS_BLEND_INVSRCCOLOR:
264 return D3D11_BLEND_INV_SRC_COLOR;
265 case GS_BLEND_SRCALPHA:
266 return D3D11_BLEND_SRC_ALPHA;
267 case GS_BLEND_INVSRCALPHA:
268 return D3D11_BLEND_INV_SRC_ALPHA;
269 case GS_BLEND_DSTCOLOR:
270 return D3D11_BLEND_DEST_COLOR;
271 case GS_BLEND_INVDSTCOLOR:
272 return D3D11_BLEND_INV_DEST_COLOR;
273 case GS_BLEND_DSTALPHA:
274 return D3D11_BLEND_DEST_ALPHA;
275 case GS_BLEND_INVDSTALPHA:
276 return D3D11_BLEND_INV_DEST_ALPHA;
277 case GS_BLEND_SRCALPHASAT:
278 return D3D11_BLEND_SRC_ALPHA_SAT;
279 }
280
281 return D3D11_BLEND_ONE;
282 }
283
ConvertGSCullMode(gs_cull_mode mode)284 static inline D3D11_CULL_MODE ConvertGSCullMode(gs_cull_mode mode)
285 {
286 switch (mode) {
287 case GS_BACK:
288 return D3D11_CULL_BACK;
289 case GS_FRONT:
290 return D3D11_CULL_FRONT;
291 case GS_NEITHER:
292 return D3D11_CULL_NONE;
293 }
294
295 return D3D11_CULL_BACK;
296 }
297
ConvertGSTopology(gs_draw_mode mode)298 static inline D3D11_PRIMITIVE_TOPOLOGY ConvertGSTopology(gs_draw_mode mode)
299 {
300 switch (mode) {
301 case GS_POINTS:
302 return D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
303 case GS_LINES:
304 return D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
305 case GS_LINESTRIP:
306 return D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP;
307 case GS_TRIS:
308 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
309 case GS_TRISTRIP:
310 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
311 }
312
313 return D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
314 }
315
316 /* exception-safe RAII wrapper for vertex buffer data (NOTE: not copy-safe) */
317 struct VBDataPtr {
318 gs_vb_data *data;
319
VBDataPtrVBDataPtr320 inline VBDataPtr(gs_vb_data *data) : data(data) {}
~VBDataPtrVBDataPtr321 inline ~VBDataPtr() { gs_vbdata_destroy(data); }
322 };
323
324 enum class gs_type {
325 gs_vertex_buffer,
326 gs_index_buffer,
327 gs_texture_2d,
328 gs_zstencil_buffer,
329 gs_stage_surface,
330 gs_sampler_state,
331 gs_vertex_shader,
332 gs_pixel_shader,
333 gs_duplicator,
334 gs_swap_chain,
335 gs_timer,
336 gs_timer_range,
337 gs_texture_3d,
338 };
339
340 struct gs_obj {
341 gs_device_t *device;
342 gs_type obj_type;
343 gs_obj *next;
344 gs_obj **prev_next;
345
gs_objgs_obj346 inline gs_obj() : device(nullptr), next(nullptr), prev_next(nullptr) {}
347
348 gs_obj(gs_device_t *device, gs_type type);
349 virtual ~gs_obj();
350 };
351
352 struct gs_vertex_buffer : gs_obj {
353 ComPtr<ID3D11Buffer> vertexBuffer;
354 ComPtr<ID3D11Buffer> normalBuffer;
355 ComPtr<ID3D11Buffer> colorBuffer;
356 ComPtr<ID3D11Buffer> tangentBuffer;
357 vector<ComPtr<ID3D11Buffer>> uvBuffers;
358
359 bool dynamic;
360 VBDataPtr vbd;
361 size_t numVerts;
362 vector<size_t> uvSizes;
363
364 void FlushBuffer(ID3D11Buffer *buffer, void *array, size_t elementSize);
365
366 UINT MakeBufferList(gs_vertex_shader *shader, ID3D11Buffer **buffers,
367 uint32_t *strides);
368
369 void InitBuffer(const size_t elementSize, const size_t numVerts,
370 void *array, ID3D11Buffer **buffer);
371
372 void BuildBuffers();
373
Releasegs_vertex_buffer374 inline void Release()
375 {
376 vertexBuffer.Release();
377 normalBuffer.Release();
378 colorBuffer.Release();
379 tangentBuffer.Release();
380 uvBuffers.clear();
381 }
382
383 void Rebuild();
384
385 gs_vertex_buffer(gs_device_t *device, struct gs_vb_data *data,
386 uint32_t flags);
387 };
388
389 /* exception-safe RAII wrapper for index buffer data (NOTE: not copy-safe) */
390 struct DataPtr {
391 void *data;
392
DataPtrDataPtr393 inline DataPtr(void *data) : data(data) {}
~DataPtrDataPtr394 inline ~DataPtr() { bfree(data); }
395 };
396
397 struct gs_index_buffer : gs_obj {
398 ComPtr<ID3D11Buffer> indexBuffer;
399 bool dynamic;
400 gs_index_type type;
401 size_t indexSize;
402 size_t num;
403 DataPtr indices;
404
405 D3D11_BUFFER_DESC bd = {};
406 D3D11_SUBRESOURCE_DATA srd = {};
407
408 void InitBuffer();
409
410 void Rebuild(ID3D11Device *dev);
411
Releasegs_index_buffer412 inline void Release() { indexBuffer.Release(); }
413
414 gs_index_buffer(gs_device_t *device, enum gs_index_type type,
415 void *indices, size_t num, uint32_t flags);
416 };
417
418 struct gs_timer : gs_obj {
419 ComPtr<ID3D11Query> query_begin;
420 ComPtr<ID3D11Query> query_end;
421
422 void Rebuild(ID3D11Device *dev);
423
Releasegs_timer424 inline void Release()
425 {
426 query_begin.Release();
427 query_end.Release();
428 }
429
430 gs_timer(gs_device_t *device);
431 };
432
433 struct gs_timer_range : gs_obj {
434 ComPtr<ID3D11Query> query_disjoint;
435
436 void Rebuild(ID3D11Device *dev);
437
Releasegs_timer_range438 inline void Release() { query_disjoint.Release(); }
439
440 gs_timer_range(gs_device_t *device);
441 };
442
443 struct gs_texture : gs_obj {
444 gs_texture_type type;
445 uint32_t levels;
446 gs_color_format format;
447
448 ComPtr<ID3D11ShaderResourceView> shaderRes;
449 ComPtr<ID3D11ShaderResourceView> shaderResLinear;
450 D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc{};
451 D3D11_SHADER_RESOURCE_VIEW_DESC viewDescLinear{};
452
453 void Rebuild(ID3D11Device *dev);
454
gs_texturegs_texture455 inline gs_texture(gs_texture_type type, uint32_t levels,
456 gs_color_format format)
457 : type(type), levels(levels), format(format)
458 {
459 }
460
gs_texturegs_texture461 inline gs_texture(gs_device *device, gs_type obj_type,
462 gs_texture_type type)
463 : gs_obj(device, obj_type), type(type)
464 {
465 }
466
gs_texturegs_texture467 inline gs_texture(gs_device *device, gs_type obj_type,
468 gs_texture_type type, uint32_t levels,
469 gs_color_format format)
470 : gs_obj(device, obj_type),
471 type(type),
472 levels(levels),
473 format(format)
474 {
475 }
476 };
477
478 struct gs_texture_2d : gs_texture {
479 ComPtr<ID3D11Texture2D> texture;
480 ComPtr<ID3D11RenderTargetView> renderTarget[6];
481 ComPtr<ID3D11RenderTargetView> renderTargetLinear[6];
482 ComPtr<IDXGISurface1> gdiSurface;
483
484 uint32_t width = 0, height = 0;
485 uint32_t flags = 0;
486 DXGI_FORMAT dxgiFormatResource = DXGI_FORMAT_UNKNOWN;
487 DXGI_FORMAT dxgiFormatView = DXGI_FORMAT_UNKNOWN;
488 DXGI_FORMAT dxgiFormatViewLinear = DXGI_FORMAT_UNKNOWN;
489 bool isRenderTarget = false;
490 bool isGDICompatible = false;
491 bool isDynamic = false;
492 bool isShared = false;
493 bool genMipmaps = false;
494 uint32_t sharedHandle = GS_INVALID_HANDLE;
495
496 gs_texture_2d *pairedNV12texture = nullptr;
497 bool nv12 = false;
498 bool chroma = false;
499 bool acquired = false;
500
501 vector<vector<uint8_t>> data;
502 vector<D3D11_SUBRESOURCE_DATA> srd;
503 D3D11_TEXTURE2D_DESC td = {};
504
505 void InitSRD(vector<D3D11_SUBRESOURCE_DATA> &srd);
506 void InitTexture(const uint8_t *const *data);
507 void InitResourceView();
508 void InitRenderTargets();
509 void BackupTexture(const uint8_t *const *data);
510 void GetSharedHandle(IDXGIResource *dxgi_res);
511
512 void RebuildSharedTextureFallback();
513 void Rebuild(ID3D11Device *dev);
514 void RebuildNV12_Y(ID3D11Device *dev);
515 void RebuildNV12_UV(ID3D11Device *dev);
516
Releasegs_texture_2d517 inline void Release()
518 {
519 texture.Release();
520 for (ComPtr<ID3D11RenderTargetView> &rt : renderTarget)
521 rt.Release();
522 for (ComPtr<ID3D11RenderTargetView> &rt : renderTargetLinear)
523 rt.Release();
524 gdiSurface.Release();
525 shaderRes.Release();
526 shaderResLinear.Release();
527 }
528
gs_texture_2dgs_texture_2d529 inline gs_texture_2d() : gs_texture(GS_TEXTURE_2D, 0, GS_UNKNOWN) {}
530
531 gs_texture_2d(gs_device_t *device, uint32_t width, uint32_t height,
532 gs_color_format colorFormat, uint32_t levels,
533 const uint8_t *const *data, uint32_t flags,
534 gs_texture_type type, bool gdiCompatible,
535 bool nv12 = false);
536
537 gs_texture_2d(gs_device_t *device, ID3D11Texture2D *nv12,
538 uint32_t flags);
539 gs_texture_2d(gs_device_t *device, uint32_t handle);
540 gs_texture_2d(gs_device_t *device, ID3D11Texture2D *obj);
541 };
542
543 struct gs_texture_3d : gs_texture {
544 ComPtr<ID3D11Texture3D> texture;
545
546 uint32_t width = 0, height = 0, depth = 0;
547 uint32_t flags = 0;
548 DXGI_FORMAT dxgiFormatResource = DXGI_FORMAT_UNKNOWN;
549 DXGI_FORMAT dxgiFormatView = DXGI_FORMAT_UNKNOWN;
550 DXGI_FORMAT dxgiFormatViewLinear = DXGI_FORMAT_UNKNOWN;
551 bool isDynamic = false;
552 bool isShared = false;
553 bool genMipmaps = false;
554 uint32_t sharedHandle = GS_INVALID_HANDLE;
555
556 bool chroma = false;
557 bool acquired = false;
558
559 vector<vector<uint8_t>> data;
560 vector<D3D11_SUBRESOURCE_DATA> srd;
561 D3D11_TEXTURE3D_DESC td = {};
562
563 void InitSRD(vector<D3D11_SUBRESOURCE_DATA> &srd);
564 void InitTexture(const uint8_t *const *data);
565 void InitResourceView();
566 void BackupTexture(const uint8_t *const *data);
567 void GetSharedHandle(IDXGIResource *dxgi_res);
568
569 void RebuildSharedTextureFallback();
570 void Rebuild(ID3D11Device *dev);
571 void RebuildNV12_Y(ID3D11Device *dev);
572 void RebuildNV12_UV(ID3D11Device *dev);
573
Releasegs_texture_3d574 inline void Release()
575 {
576 texture.Release();
577 shaderRes.Release();
578 }
579
gs_texture_3dgs_texture_3d580 inline gs_texture_3d() : gs_texture(GS_TEXTURE_3D, 0, GS_UNKNOWN) {}
581
582 gs_texture_3d(gs_device_t *device, uint32_t width, uint32_t height,
583 uint32_t depth, gs_color_format colorFormat,
584 uint32_t levels, const uint8_t *const *data,
585 uint32_t flags);
586
587 gs_texture_3d(gs_device_t *device, uint32_t handle);
588 };
589
590 struct gs_zstencil_buffer : gs_obj {
591 ComPtr<ID3D11Texture2D> texture;
592 ComPtr<ID3D11DepthStencilView> view;
593
594 uint32_t width, height;
595 gs_zstencil_format format;
596 DXGI_FORMAT dxgiFormat;
597
598 D3D11_TEXTURE2D_DESC td = {};
599 D3D11_DEPTH_STENCIL_VIEW_DESC dsvd = {};
600
601 void InitBuffer();
602
603 void Rebuild(ID3D11Device *dev);
604
Releasegs_zstencil_buffer605 inline void Release()
606 {
607 texture.Release();
608 view.Release();
609 }
610
gs_zstencil_buffergs_zstencil_buffer611 inline gs_zstencil_buffer()
612 : width(0), height(0), dxgiFormat(DXGI_FORMAT_UNKNOWN)
613 {
614 }
615
616 gs_zstencil_buffer(gs_device_t *device, uint32_t width, uint32_t height,
617 gs_zstencil_format format);
618 };
619
620 struct gs_stage_surface : gs_obj {
621 ComPtr<ID3D11Texture2D> texture;
622 D3D11_TEXTURE2D_DESC td = {};
623
624 uint32_t width, height;
625 gs_color_format format;
626 DXGI_FORMAT dxgiFormat;
627
628 void Rebuild(ID3D11Device *dev);
629
Releasegs_stage_surface630 inline void Release() { texture.Release(); }
631
632 gs_stage_surface(gs_device_t *device, uint32_t width, uint32_t height,
633 gs_color_format colorFormat);
634 gs_stage_surface(gs_device_t *device, uint32_t width, uint32_t height);
635 };
636
637 struct gs_sampler_state : gs_obj {
638 ComPtr<ID3D11SamplerState> state;
639 D3D11_SAMPLER_DESC sd = {};
640 gs_sampler_info info;
641
642 void Rebuild(ID3D11Device *dev);
643
Releasegs_sampler_state644 inline void Release() { state.Release(); }
645
646 gs_sampler_state(gs_device_t *device, const gs_sampler_info *info);
647 };
648
649 struct gs_shader_param {
650 string name;
651 gs_shader_param_type type;
652
653 uint32_t textureID;
654 struct gs_sampler_state *nextSampler = nullptr;
655
656 int arrayCount;
657
658 size_t pos;
659
660 vector<uint8_t> curValue;
661 vector<uint8_t> defaultValue;
662 bool changed;
663
664 gs_shader_param(shader_var &var, uint32_t &texCounter);
665 };
666
667 struct ShaderError {
668 ComPtr<ID3D10Blob> errors;
669 HRESULT hr;
670
ShaderErrorShaderError671 inline ShaderError(const ComPtr<ID3D10Blob> &errors, HRESULT hr)
672 : errors(errors), hr(hr)
673 {
674 }
675 };
676
677 struct gs_shader : gs_obj {
678 gs_shader_type type;
679 vector<gs_shader_param> params;
680 ComPtr<ID3D11Buffer> constants;
681 size_t constantSize;
682
683 D3D11_BUFFER_DESC bd = {};
684 vector<uint8_t> data;
685
686 inline void UpdateParam(vector<uint8_t> &constData,
687 gs_shader_param ¶m, bool &upload);
688 void UploadParams();
689
690 void BuildConstantBuffer();
691 void Compile(const char *shaderStr, const char *file,
692 const char *target, ID3D10Blob **shader);
693
gs_shadergs_shader694 inline gs_shader(gs_device_t *device, gs_type obj_type,
695 gs_shader_type type)
696 : gs_obj(device, obj_type), type(type), constantSize(0)
697 {
698 }
699
~gs_shadergs_shader700 virtual ~gs_shader() {}
701 };
702
703 struct ShaderSampler {
704 string name;
705 gs_sampler_state sampler;
706
ShaderSamplerShaderSampler707 inline ShaderSampler(const char *name, gs_device_t *device,
708 gs_sampler_info *info)
709 : name(name), sampler(device, info)
710 {
711 }
712 };
713
714 struct gs_vertex_shader : gs_shader {
715 ComPtr<ID3D11VertexShader> shader;
716 ComPtr<ID3D11InputLayout> layout;
717
718 gs_shader_param *world, *viewProj;
719
720 vector<D3D11_INPUT_ELEMENT_DESC> layoutData;
721
722 bool hasNormals;
723 bool hasColors;
724 bool hasTangents;
725 uint32_t nTexUnits;
726
727 void Rebuild(ID3D11Device *dev);
728
Releasegs_vertex_shader729 inline void Release()
730 {
731 shader.Release();
732 layout.Release();
733 constants.Release();
734 }
735
NumBuffersExpectedgs_vertex_shader736 inline uint32_t NumBuffersExpected() const
737 {
738 uint32_t count = nTexUnits + 1;
739 if (hasNormals)
740 count++;
741 if (hasColors)
742 count++;
743 if (hasTangents)
744 count++;
745
746 return count;
747 }
748
749 void GetBuffersExpected(const vector<D3D11_INPUT_ELEMENT_DESC> &inputs);
750
751 gs_vertex_shader(gs_device_t *device, const char *file,
752 const char *shaderString);
753 };
754
755 struct gs_duplicator : gs_obj {
756 ComPtr<IDXGIOutputDuplication> duplicator;
757 gs_texture_2d *texture;
758 int idx;
759 long refs;
760 bool updated;
761
762 void Start();
763
Releasegs_duplicator764 inline void Release() { duplicator.Release(); }
765
766 gs_duplicator(gs_device_t *device, int monitor_idx);
767 ~gs_duplicator();
768 };
769
770 struct gs_pixel_shader : gs_shader {
771 ComPtr<ID3D11PixelShader> shader;
772 vector<unique_ptr<ShaderSampler>> samplers;
773
774 void Rebuild(ID3D11Device *dev);
775
Releasegs_pixel_shader776 inline void Release()
777 {
778 shader.Release();
779 constants.Release();
780 }
781
GetSamplerStatesgs_pixel_shader782 inline void GetSamplerStates(ID3D11SamplerState **states)
783 {
784 size_t i;
785 for (i = 0; i < samplers.size(); i++)
786 states[i] = samplers[i]->sampler.state;
787 for (; i < GS_MAX_TEXTURES; i++)
788 states[i] = NULL;
789 }
790
791 gs_pixel_shader(gs_device_t *device, const char *file,
792 const char *shaderString);
793 };
794
795 struct gs_swap_chain : gs_obj {
796 HWND hwnd;
797 gs_init_data initData;
798 DXGI_SWAP_CHAIN_DESC swapDesc = {};
799 UINT presentFlags = 0;
800
801 gs_texture_2d target;
802 gs_zstencil_buffer zs;
803 ComPtr<IDXGISwapChain> swap;
804 HANDLE hWaitable = NULL;
805
806 void InitTarget(uint32_t cx, uint32_t cy);
807 void InitZStencilBuffer(uint32_t cx, uint32_t cy);
808 void Resize(uint32_t cx, uint32_t cy);
809 void Init();
810
811 void Rebuild(ID3D11Device *dev);
812
Releasegs_swap_chain813 inline void Release()
814 {
815 target.Release();
816 zs.Release();
817 if (hWaitable) {
818 CloseHandle(hWaitable);
819 hWaitable = NULL;
820 }
821 swap.Clear();
822 }
823
824 gs_swap_chain(gs_device *device, const gs_init_data *data);
825 virtual ~gs_swap_chain();
826 };
827
828 struct BlendState {
829 bool blendEnabled;
830 gs_blend_type srcFactorC;
831 gs_blend_type destFactorC;
832 gs_blend_type srcFactorA;
833 gs_blend_type destFactorA;
834
835 bool redEnabled;
836 bool greenEnabled;
837 bool blueEnabled;
838 bool alphaEnabled;
839
BlendStateBlendState840 inline BlendState()
841 : blendEnabled(true),
842 srcFactorC(GS_BLEND_SRCALPHA),
843 destFactorC(GS_BLEND_INVSRCALPHA),
844 srcFactorA(GS_BLEND_ONE),
845 destFactorA(GS_BLEND_INVSRCALPHA),
846 redEnabled(true),
847 greenEnabled(true),
848 blueEnabled(true),
849 alphaEnabled(true)
850 {
851 }
852
BlendStateBlendState853 inline BlendState(const BlendState &state)
854 {
855 memcpy(this, &state, sizeof(BlendState));
856 }
857 };
858
859 struct SavedBlendState : BlendState {
860 ComPtr<ID3D11BlendState> state;
861 D3D11_BLEND_DESC bd;
862
863 void Rebuild(ID3D11Device *dev);
864
ReleaseSavedBlendState865 inline void Release() { state.Release(); }
866
SavedBlendStateSavedBlendState867 inline SavedBlendState(const BlendState &val, D3D11_BLEND_DESC &desc)
868 : BlendState(val), bd(desc)
869 {
870 }
871 };
872
873 struct StencilSide {
874 gs_depth_test test;
875 gs_stencil_op_type fail;
876 gs_stencil_op_type zfail;
877 gs_stencil_op_type zpass;
878
StencilSideStencilSide879 inline StencilSide()
880 : test(GS_ALWAYS), fail(GS_KEEP), zfail(GS_KEEP), zpass(GS_KEEP)
881 {
882 }
883 };
884
885 struct ZStencilState {
886 bool depthEnabled;
887 bool depthWriteEnabled;
888 gs_depth_test depthFunc;
889
890 bool stencilEnabled;
891 bool stencilWriteEnabled;
892 StencilSide stencilFront;
893 StencilSide stencilBack;
894
ZStencilStateZStencilState895 inline ZStencilState()
896 : depthEnabled(true),
897 depthWriteEnabled(true),
898 depthFunc(GS_LESS),
899 stencilEnabled(false),
900 stencilWriteEnabled(true)
901 {
902 }
903
ZStencilStateZStencilState904 inline ZStencilState(const ZStencilState &state)
905 {
906 memcpy(this, &state, sizeof(ZStencilState));
907 }
908 };
909
910 struct SavedZStencilState : ZStencilState {
911 ComPtr<ID3D11DepthStencilState> state;
912 D3D11_DEPTH_STENCIL_DESC dsd;
913
914 void Rebuild(ID3D11Device *dev);
915
ReleaseSavedZStencilState916 inline void Release() { state.Release(); }
917
SavedZStencilStateSavedZStencilState918 inline SavedZStencilState(const ZStencilState &val,
919 D3D11_DEPTH_STENCIL_DESC desc)
920 : ZStencilState(val), dsd(desc)
921 {
922 }
923 };
924
925 struct RasterState {
926 gs_cull_mode cullMode;
927 bool scissorEnabled;
928
RasterStateRasterState929 inline RasterState() : cullMode(GS_BACK), scissorEnabled(false) {}
930
RasterStateRasterState931 inline RasterState(const RasterState &state)
932 {
933 memcpy(this, &state, sizeof(RasterState));
934 }
935 };
936
937 struct SavedRasterState : RasterState {
938 ComPtr<ID3D11RasterizerState> state;
939 D3D11_RASTERIZER_DESC rd;
940
941 void Rebuild(ID3D11Device *dev);
942
ReleaseSavedRasterState943 inline void Release() { state.Release(); }
944
SavedRasterStateSavedRasterState945 inline SavedRasterState(const RasterState &val,
946 D3D11_RASTERIZER_DESC &desc)
947 : RasterState(val), rd(desc)
948 {
949 }
950 };
951
952 struct mat4float {
953 float mat[16];
954 };
955
956 struct gs_device {
957 ComPtr<IDXGIFactory1> factory;
958 ComPtr<IDXGIAdapter1> adapter;
959 ComPtr<ID3D11Device> device;
960 ComPtr<ID3D11DeviceContext> context;
961 uint32_t adpIdx = 0;
962 bool nv12Supported = false;
963
964 gs_texture_2d *curRenderTarget = nullptr;
965 gs_zstencil_buffer *curZStencilBuffer = nullptr;
966 int curRenderSide = 0;
967 bool curFramebufferSrgb = false;
968 bool curFramebufferInvalidate = false;
969 gs_texture *curTextures[GS_MAX_TEXTURES];
970 gs_sampler_state *curSamplers[GS_MAX_TEXTURES];
971 gs_vertex_buffer *curVertexBuffer = nullptr;
972 gs_index_buffer *curIndexBuffer = nullptr;
973 gs_vertex_shader *curVertexShader = nullptr;
974 gs_pixel_shader *curPixelShader = nullptr;
975 gs_swap_chain *curSwapChain = nullptr;
976
977 gs_vertex_buffer *lastVertexBuffer = nullptr;
978 gs_vertex_shader *lastVertexShader = nullptr;
979
980 bool zstencilStateChanged = true;
981 bool rasterStateChanged = true;
982 bool blendStateChanged = true;
983 ZStencilState zstencilState;
984 RasterState rasterState;
985 BlendState blendState;
986 vector<SavedZStencilState> zstencilStates;
987 vector<SavedRasterState> rasterStates;
988 vector<SavedBlendState> blendStates;
989 ID3D11DepthStencilState *curDepthStencilState = nullptr;
990 ID3D11RasterizerState *curRasterState = nullptr;
991 ID3D11BlendState *curBlendState = nullptr;
992 D3D11_PRIMITIVE_TOPOLOGY curToplogy;
993
994 pD3DCompile d3dCompile = nullptr;
995 #ifdef DISASSEMBLE_SHADERS
996 pD3DDisassemble d3dDisassemble = nullptr;
997 #endif
998
999 gs_rect viewport;
1000
1001 vector<mat4float> projStack;
1002
1003 matrix4 curProjMatrix;
1004 matrix4 curViewMatrix;
1005 matrix4 curViewProjMatrix;
1006
1007 vector<gs_device_loss> loss_callbacks;
1008 gs_obj *first_obj = nullptr;
1009
1010 void InitCompiler();
1011 void InitFactory();
1012 void ReorderAdapters(uint32_t &adapterIdx);
1013 void InitAdapter(uint32_t adapterIdx);
1014 void InitDevice(uint32_t adapterIdx);
1015
1016 ID3D11DepthStencilState *AddZStencilState();
1017 ID3D11RasterizerState *AddRasterState();
1018 ID3D11BlendState *AddBlendState();
1019 void UpdateZStencilState();
1020 void UpdateRasterState();
1021 void UpdateBlendState();
1022
1023 void LoadVertexBufferData();
1024
1025 inline void CopyTex(ID3D11Texture2D *dst, uint32_t dst_x,
1026 uint32_t dst_y, gs_texture_t *src, uint32_t src_x,
1027 uint32_t src_y, uint32_t src_w, uint32_t src_h);
1028
1029 void UpdateViewProjMatrix();
1030
1031 void FlushOutputViews();
1032
1033 void RebuildDevice();
1034
1035 bool HasBadNV12Output();
1036
1037 gs_device(uint32_t adapterIdx);
1038 ~gs_device();
1039 };
1040
1041 extern "C" EXPORT int device_texture_acquire_sync(gs_texture_t *tex,
1042 uint64_t key, uint32_t ms);
1043