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 &param, 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