├── .gitignore
├── .gitmodules
├── .vs
└── config
│ └── applicationhost.config
├── Application
├── Application.vcxproj
├── Application.vcxproj.filters
├── Game.cpp
├── Game.h
└── WinMain.cpp
├── DX11Application.png
├── DX11Base.sln
├── DX11Base
├── DX11Base.vcxproj
├── DX11Base.vcxproj.filters
├── Dx11Device.cpp
├── Dx11Device.h
├── DxMath.h
├── WindowHelper.cpp
├── WindowHelper.h
└── WindowInput.h
├── LICENSE.md
├── README.md
└── Resources
├── ColoredTriangles.hlsl
├── Common.hlsl
├── PostProcess.hlsl
└── ToyShader.hlsl
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files
2 | *.slo
3 | *.lo
4 | *.o
5 | *.obj
6 |
7 | # Precompiled Headers
8 | *.gch
9 | *.pch
10 |
11 | # Compiled Dynamic libraries
12 | *.so
13 | *.dylib
14 | *.dll
15 |
16 | # Fortran module files
17 | *.mod
18 | *.smod
19 |
20 | # Compiled Static libraries
21 | *.lai
22 | *.la
23 | *.a
24 | *.lib
25 |
26 | # Executables
27 | *.exe
28 | *.out
29 | *.app
30 |
31 | # Build folder
32 | x64
33 |
34 | # Visual Studio
35 | *.opendb
36 | *.db
37 |
38 | # RenderDoc
39 | *.cap
40 |
41 | # Imgui
42 | imgui.ini
43 |
44 | # Visual studio new
45 | *.ipch
46 | *.db-shm
47 | *.db-wal
48 |
49 |
50 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "imgui"]
2 | path = imgui
3 | url = https://github.com/ocornut/imgui
4 |
--------------------------------------------------------------------------------
/.vs/config/applicationhost.config:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
22 |
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 |
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 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 |
647 |
648 |
649 |
650 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 |
666 |
667 |
668 |
669 |
670 |
671 |
672 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
720 |
721 |
722 |
723 |
724 |
725 |
726 |
727 |
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 |
736 |
737 |
738 |
739 |
740 |
741 |
742 |
743 |
744 |
745 |
746 |
747 |
748 |
749 |
750 |
751 |
752 |
753 |
754 |
755 |
756 |
757 |
758 |
759 |
760 |
761 |
762 |
763 |
764 |
765 |
766 |
767 |
768 |
769 |
770 |
771 |
772 |
773 |
774 |
775 |
776 |
777 |
778 |
779 |
780 |
781 |
782 |
783 |
784 |
785 |
786 |
787 |
788 |
789 |
790 |
791 |
792 |
793 |
794 |
795 |
796 |
797 |
798 |
799 |
800 |
801 |
802 |
803 |
804 |
805 |
806 |
807 |
808 |
809 |
810 |
811 |
812 |
813 |
814 |
815 |
816 |
817 |
818 |
819 |
820 |
821 |
822 |
823 |
824 |
825 |
826 |
827 |
828 |
829 |
830 |
831 |
832 |
833 |
834 |
835 |
836 |
837 |
838 |
839 |
840 |
841 |
842 |
843 |
844 |
845 |
846 |
847 |
848 |
849 |
850 |
851 |
852 |
853 |
854 |
855 |
856 |
857 |
858 |
859 |
860 |
861 |
862 |
863 |
864 |
865 |
866 |
867 |
868 |
869 |
870 |
871 |
872 |
873 |
874 |
875 |
876 |
877 |
878 |
879 |
880 |
881 |
882 |
883 |
884 |
885 |
886 |
887 |
888 |
889 |
890 |
891 |
892 |
893 |
894 |
895 |
896 |
897 |
898 |
899 |
900 |
901 |
902 |
903 |
904 |
905 |
906 |
907 |
908 |
909 |
910 |
911 |
912 |
913 |
914 |
915 |
916 |
917 |
918 |
919 |
920 |
921 |
922 |
923 |
924 |
925 |
926 |
927 |
928 |
929 |
930 |
931 |
932 |
933 |
934 |
935 |
936 |
937 |
938 |
939 |
940 |
941 |
942 |
943 |
944 |
945 |
946 |
947 |
948 |
949 |
950 |
951 |
952 |
953 |
954 |
955 |
956 |
957 |
958 |
959 |
960 |
961 |
962 |
963 |
964 |
965 |
966 |
967 |
968 |
969 |
970 |
971 |
972 |
973 |
974 |
975 |
976 |
977 |
978 |
979 |
980 |
981 |
982 |
983 |
984 |
985 |
986 |
987 |
988 |
989 |
990 |
991 |
992 |
993 |
994 |
995 |
996 |
997 |
998 |
999 |
1000 |
1001 |
1002 |
1003 |
1004 |
1005 |
1006 |
1007 |
1008 |
1009 |
1010 |
1011 |
1012 |
1013 |
1014 |
1015 |
1016 |
1017 |
1018 |
1019 |
1020 |
1021 |
1022 |
1023 |
--------------------------------------------------------------------------------
/Application/Application.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | {2CA77969-0EC4-4607-93CC-C63915A2C01F}
23 | Win32Proj
24 | Application
25 | 10.0.17134.0
26 |
27 |
28 |
29 | Application
30 | true
31 | v141
32 | Unicode
33 |
34 |
35 | Application
36 | false
37 | v141
38 | true
39 | Unicode
40 |
41 |
42 | Application
43 | true
44 | v141
45 | Unicode
46 |
47 |
48 | Application
49 | false
50 | v141
51 | true
52 | Unicode
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | true
74 |
75 |
76 | true
77 | $(ProjectDir)..\$(Platform)\$(Configuration)\$(ProjectName)\
78 |
79 |
80 | false
81 |
82 |
83 | true
84 | $(ProjectDir)..\$(Platform)\$(Configuration)\$(ProjectName)\
85 |
86 |
87 |
88 |
89 |
90 | Level3
91 | Disabled
92 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)
93 | true
94 |
95 |
96 | Windows
97 | true
98 |
99 |
100 |
101 |
102 |
103 |
104 | Level3
105 | Disabled
106 | _DEBUG;_WINDOWS;%(PreprocessorDefinitions);IMGUI_DISABLE_OBSOLETE_FUNCTIONS
107 | true
108 | $(SolutionDir)imgui;$(SolutionDir);%(AdditionalIncludeDirectories)
109 |
110 |
111 | Windows
112 | true
113 | dx11Base.lib;D3DCompiler.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
114 | $(TargetDir)
115 |
116 |
117 |
118 |
119 | Level3
120 |
121 |
122 | MaxSpeed
123 | true
124 | true
125 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)
126 | true
127 |
128 |
129 | Windows
130 | true
131 | true
132 | true
133 |
134 |
135 |
136 |
137 | Level3
138 |
139 |
140 | Full
141 | true
142 | true
143 | NDEBUG;_WINDOWS;%(PreprocessorDefinitions);IMGUI_DISABLE_OBSOLETE_FUNCTIONS
144 | true
145 | $(IntDir)
146 | $(IntDir)
147 | $(IntDir)
148 | $(IntDir)
149 | $(SolutionDir)imgui;$(SolutionDir);%(AdditionalIncludeDirectories)
150 |
151 |
152 | Windows
153 | true
154 | true
155 | DebugFastLink
156 | dx11Base.lib;D3DCompiler.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
157 | $(TargetDir)
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 | true
184 | true
185 |
186 |
187 | true
188 | true
189 |
190 |
191 | true
192 | true
193 | true
194 | true
195 |
196 |
197 | true
198 | true
199 |
200 |
201 |
202 |
203 |
204 |
--------------------------------------------------------------------------------
/Application/Application.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
10 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
11 |
12 |
13 | {26774f3f-a03e-4f83-9f4c-7164cccca514}
14 |
15 |
16 | {186851fc-d34f-4cc2-8b98-48bef49025e6}
17 |
18 |
19 |
20 |
21 | Source Files
22 |
23 |
24 | Source Files
25 |
26 |
27 | Imgui
28 |
29 |
30 | Imgui
31 |
32 |
33 | Imgui
34 |
35 |
36 | Imgui
37 |
38 |
39 | Imgui
40 |
41 |
42 | Imgui
43 |
44 |
45 |
46 |
47 | Source Files
48 |
49 |
50 | Imgui
51 |
52 |
53 | Imgui
54 |
55 |
56 | Imgui
57 |
58 |
59 | Imgui
60 |
61 |
62 | Imgui
63 |
64 |
65 | Imgui
66 |
67 |
68 | Imgui
69 |
70 |
71 | Imgui
72 |
73 |
74 |
75 |
76 | HLSL
77 |
78 |
79 | HLSL
80 |
81 |
82 | HLSL
83 |
84 |
85 | HLSL
86 |
87 |
88 |
--------------------------------------------------------------------------------
/Application/Game.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "Game.h"
3 |
4 | #include "windows.h"
5 |
6 | #include
7 |
8 |
9 | Game::Game()
10 | {
11 | }
12 |
13 |
14 | Game::~Game()
15 | {
16 | }
17 |
18 |
19 | void Game::loadShaders(bool firstTimeLoadShaders)
20 | {
21 | bool success = true;
22 |
23 | auto reloadShader = [&](auto** previousShader, const TCHAR* filename, const char* entryFunction, bool firstTimeLoadShaders, const Macros* macros = NULL, bool lazyCompilation = false)
24 | {
25 | if (firstTimeLoadShaders)
26 | {
27 | // The first time we want to compile the shader and make sure we fail if not succesful
28 | return reload(previousShader, filename, entryFunction, true, macros, lazyCompilation);
29 | }
30 | else
31 | {
32 | // other time we only want to make the shader dirty to schedule compilation when used
33 | (*previousShader)->markDirty();
34 | return true;
35 | }
36 | };
37 |
38 | const bool lazyCompilation = true;
39 | success &= reloadShader(&mVertexShader, L"Resources\\Common.hlsl", "DefaultVertexShader", firstTimeLoadShaders, nullptr, false); // No lazy compilation because it is used to create a layout
40 | success &= reloadShader(&mScreenVertexShader, L"Resources\\Common.hlsl", "ScreenTriangleVertexShader", firstTimeLoadShaders, nullptr, false); // No lazy compilation because it is used to create a layout
41 | success &= reload(&mColoredTrianglesShader, L"Resources\\ColoredTriangles.hlsl", "ColoredTrianglesPixelShader", firstTimeLoadShaders, nullptr, lazyCompilation);
42 | success &= reload(&mToyShader, L"Resources\\ToyShader.hlsl", "ToyShaderCS", firstTimeLoadShaders, nullptr, lazyCompilation);
43 | success &= reload(&mPostProcessShader, L"Resources\\PostProcess.hlsl", "PostProcessPS", firstTimeLoadShaders, nullptr, lazyCompilation);
44 |
45 | InputLayoutDesc inputLayout;
46 | appendSimpleVertexDataToInputLayout(inputLayout, "POSITION", DXGI_FORMAT_R32G32B32_FLOAT);
47 | resetComPtr(&mLayout);
48 | mVertexShader->createInputLayout(inputLayout, &mLayout); // Have a layout object with vertex stride in it
49 | }
50 |
51 | void Game::releaseShaders()
52 | {
53 | resetComPtr(&mLayout);
54 |
55 | resetPtr(&mVertexShader);
56 | resetPtr(&mScreenVertexShader);
57 |
58 | resetPtr(&mColoredTrianglesShader);
59 | resetPtr(&mToyShader);
60 | resetPtr(&mPostProcessShader);
61 | }
62 |
63 |
64 | void Game::initialise()
65 | {
66 | ////////// Load and compile shaders
67 |
68 | loadShaders(true);
69 |
70 | ////////// Create other resources
71 |
72 | D3dDevice* device = g_dx11Device->getDevice();
73 | const D3dViewport& viewport = g_dx11Device->getBackBufferViewport();
74 | allocateResolutionIndependentResources();
75 | allocateResolutionDependentResources(uint32(viewport.Width), uint32(viewport.Height));
76 | }
77 |
78 | void Game::reallocateResolutionDependent(uint32 newWidth, uint32 newHeight)
79 | {
80 | releaseResolutionDependentResources();
81 | allocateResolutionDependentResources(newWidth, newHeight);
82 | }
83 |
84 |
85 | void Game::allocateResolutionIndependentResources()
86 | {
87 | D3dDevice* device = g_dx11Device->getDevice();
88 |
89 | // Simple triangle geometry
90 | VertexType vertices[3];
91 | vertices[0] = { { 0.0f, 0.0f, 0.0f } };
92 | vertices[1] = { { 0.0f, 0.5f, 0.0f } };
93 | vertices[2] = { { 0.5f, 0.0f, 0.0f } };
94 | uint32 indices[3];
95 | indices[0] = 0;
96 | indices[1] = 1;
97 | indices[2] = 2;
98 | vertexBuffer = new RenderBuffer(RenderBuffer::initVertexBufferDesc_default(sizeof(vertices)), vertices);
99 | indexBuffer = new RenderBuffer(RenderBuffer::initIndexBufferDesc_default(sizeof(indices)), indices);
100 |
101 | mConstantBuffer = new CommonConstantBuffer();
102 |
103 | uint32 bufferElementSize = (sizeof(float) * 4);
104 | uint32 bufferElementCount = 1024;
105 | D3dBufferDesc someBufferDesc = { bufferElementCount * bufferElementSize , D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS, 0, 0, 0 };
106 | mSomeBuffer = new RenderBuffer(someBufferDesc);
107 |
108 | D3dUnorderedAccessViewDesc someBufferUavViewDesc;
109 | someBufferUavViewDesc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT;
110 | someBufferUavViewDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
111 | someBufferUavViewDesc.Buffer.FirstElement = 0;
112 | someBufferUavViewDesc.Buffer.NumElements = bufferElementCount;
113 | someBufferUavViewDesc.Buffer.Flags = 0; // D3D11_BUFFER_UAV_FLAG_RAW
114 | HRESULT hr = device->CreateUnorderedAccessView(mSomeBuffer->mBuffer, &someBufferUavViewDesc, &mSomeBufferUavView);
115 | ATLASSERT(hr == S_OK);
116 |
117 | mDefaultDepthStencilState = new DepthStencilState(DepthStencilState::initDefaultDepthOnStencilOff());
118 | mDefaultRasterizerState = new RasterizerState(RasterizerState::initDefaultState());
119 | mDefaultBlendState = new BlendState(BlendState::initDisabledState());
120 | }
121 |
122 | void Game::releaseResolutionIndependentResources()
123 | {
124 | resetPtr(&mConstantBuffer);
125 | resetPtr(&indexBuffer);
126 | resetPtr(&vertexBuffer);
127 |
128 | resetComPtr(&mSomeBufferUavView);
129 | resetPtr(&mSomeBuffer);
130 |
131 | resetPtr(&mDefaultDepthStencilState);
132 | resetPtr(&mDefaultBlendState);
133 | resetPtr(&mDefaultRasterizerState);
134 | }
135 |
136 | void Game::allocateResolutionDependentResources(uint32 newWidth, uint32 newHeight)
137 | {
138 | mBackBufferDepth = new Texture2D(Texture2D::initDepthStencilBuffer(newWidth, newHeight, false));
139 | mBackBufferHdr = new Texture2D(Texture2D::initDefault(DXGI_FORMAT_R32G32B32A32_FLOAT, newWidth, newHeight, true, true));
140 | }
141 |
142 | void Game::releaseResolutionDependentResources()
143 | {
144 | resetPtr(&mBackBufferHdr);
145 | resetPtr(&mBackBufferDepth);
146 | }
147 |
148 | void Game::shutdown()
149 | {
150 | ////////// Release resources
151 |
152 | releaseResolutionIndependentResources();
153 | releaseResolutionDependentResources();
154 |
155 | ////////// Release shaders
156 |
157 | releaseShaders();
158 | }
159 |
160 | void Game::update(const WindowInputData& inputData)
161 | {
162 | for (auto& event : inputData.mInputEvents)
163 | {
164 | // Process events
165 | }
166 |
167 | // Listen to CTRL+S for shader live update in a very simple fashion (from http://www.lofibucket.com/articles/64k_intro.html)
168 | static ULONGLONG lastLoadTime = GetTickCount64();
169 | if (GetAsyncKeyState(VK_CONTROL) && GetAsyncKeyState('S'))
170 | {
171 | const ULONGLONG tickCount = GetTickCount64();
172 | if (tickCount - lastLoadTime > 200)
173 | {
174 | Sleep(100); // Wait for a while to let the file system finish the file write.
175 | loadShaders(false); // Reload (all) the shaders
176 | }
177 | lastLoadTime = tickCount;
178 | }
179 | }
180 |
181 |
182 | void Game::render()
183 | {
184 | GPU_SCOPED_TIMEREVENT(GameRender, 75, 75, 75);
185 |
186 | const D3dViewport& backBufferViewport = g_dx11Device->getBackBufferViewport();
187 | D3dRenderContext* context = g_dx11Device->getDeviceContext();
188 | D3dRenderTargetView* backBuffer = g_dx11Device->getBackBufferRT();
189 |
190 | // Constant buffer update
191 | {
192 | XMMATRIX viewMatrix = XMMatrixIdentity();
193 | XMMATRIX projMatrix = XMMatrixOrthographicLH(1.0, 1.0, -1.0, 1.0);
194 | XMMATRIX mViewProjMat = XMMatrixMultiply(viewMatrix, projMatrix);
195 |
196 | CommonConstantBufferStructure cb;
197 | cb.gViewProjMat = mViewProjMat;
198 | cb.gColor = { 0.0, 1.0, 1.0, 1.0 };
199 | cb.gResolution[0] = uint32(backBufferViewport.Width);
200 | cb.gResolution[1] = uint32(backBufferViewport.Height);
201 | mConstantBuffer->update(cb);
202 | }
203 |
204 | // Set default state
205 | {
206 | context->OMSetDepthStencilState(mDefaultDepthStencilState->mState, 0);
207 | context->OMSetBlendState(mDefaultBlendState->mState, nullptr, 0xffffffff);
208 | context->RSSetState(mDefaultRasterizerState->mState);
209 | context->RSSetViewports(1, &backBufferViewport);
210 | }
211 |
212 | // Clear the HDR back buffer
213 | {
214 | GPU_SCOPED_TIMER(Clear, 34, 177, 76);
215 |
216 | D3DCOLORVALUE clearColor = { 0.1f, 0.2f, 0.4f, 1.0f };
217 | context->ClearRenderTargetView(mBackBufferHdr->mRenderTargetView, &clearColor.r);
218 | context->ClearDepthStencilView(mBackBufferDepth->mDepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);;
219 | }
220 |
221 | // Render a shader toy using compute
222 | {
223 | GPU_SCOPED_TIMEREVENT(ShaderToy, 34, 177, 76);
224 |
225 | mToyShader->setShader(*context);
226 | context->CSSetConstantBuffers(0, 1, &mConstantBuffer->mBuffer);
227 | context->CSSetUnorderedAccessViews(0, 1, &mBackBufferHdr->mUnorderedAccessView, nullptr);
228 |
229 | int32 sX = divRoundUp(uint32(backBufferViewport.Width), 8);
230 | int32 sY = divRoundUp(uint32(backBufferViewport.Height), 8);
231 |
232 | context->Dispatch(sX, sY, 1);
233 | g_dx11Device->setNullCsResources(context);
234 | g_dx11Device->setNullCsUnorderedAccessViews(context);
235 | }
236 |
237 | context->OMSetRenderTargetsAndUnorderedAccessViews(1, &mBackBufferHdr->mRenderTargetView, mBackBufferDepth->mDepthStencilView, 0, 0, nullptr, nullptr);
238 |
239 | // Render some triangles using the rasterizer
240 | {
241 | GPU_SCOPED_TIMEREVENT(Triangles, 34, 177, 76);
242 |
243 | // Set vertex buffer stride and offset.
244 | uint32 stride = sizeof(VertexType);
245 | uint32 offset = 0;
246 | context->IASetVertexBuffers(0, 1, &vertexBuffer->mBuffer, &stride, &offset);
247 | context->IASetIndexBuffer(indexBuffer->mBuffer, DXGI_FORMAT_R32_UINT, 0);
248 | context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
249 | // Set the vertex input layout.
250 | context->IASetInputLayout(mLayout);
251 |
252 | // Final view
253 | mVertexShader->setShader(*context);
254 | mColoredTrianglesShader->setShader(*context);
255 | context->VSSetConstantBuffers(0, 1, &mConstantBuffer->mBuffer);
256 | context->PSSetConstantBuffers(0, 1, &mConstantBuffer->mBuffer);
257 |
258 | context->DrawIndexed(3, 0, 0);
259 | }
260 |
261 | // Post process into the back buffer using a pixel shader
262 | {
263 | GPU_SCOPED_TIMEREVENT(Post, 34, 177, 76);
264 |
265 | const uint32* initialCount = 0;
266 | context->OMSetRenderTargetsAndUnorderedAccessViews(1, &backBuffer, nullptr, 1, 1, &mSomeBufferUavView, initialCount);
267 |
268 | // Set null input assembly and layout
269 | context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
270 | context->IASetInputLayout(nullptr);
271 |
272 | // Final view
273 | mScreenVertexShader->setShader(*context);
274 | mPostProcessShader->setShader(*context);
275 | context->VSSetConstantBuffers(0, 1, &mConstantBuffer->mBuffer);
276 | context->PSSetConstantBuffers(0, 1, &mConstantBuffer->mBuffer);
277 |
278 | context->PSSetShaderResources(0, 1, &mBackBufferHdr->mShaderResourceView);
279 |
280 | context->Draw(3, 0);
281 | g_dx11Device->setNullPsResources(context);
282 | }
283 | }
284 |
285 |
286 |
287 |
--------------------------------------------------------------------------------
/Application/Game.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Dx11Base/WindowInput.h"
4 | #include "Dx11Base/Dx11Device.h"
5 |
6 |
7 |
8 | class Game
9 | {
10 | public:
11 | Game();
12 | ~Game();
13 |
14 | void initialise();
15 | void reallocateResolutionDependent(uint32 newWidth, uint32 newHeight);
16 | void shutdown();
17 |
18 | void update(const WindowInputData& inputData);
19 | void render();
20 |
21 | private:
22 |
23 | /// Load/reload all shaders if compilation is succesful.
24 | /// @firstTimeLoadShaders: calls exit(0) if any of the reload/compilation failed.
25 | void loadShaders(bool firstTimeLoadShaders);
26 | /// release all shaders
27 | void releaseShaders();
28 |
29 | void allocateResolutionIndependentResources();
30 | void releaseResolutionIndependentResources();
31 | void allocateResolutionDependentResources(uint32 newWidth, uint32 newHeight);
32 | void releaseResolutionDependentResources();
33 |
34 | // Test vertex buffer
35 | struct VertexType
36 | {
37 | float position[3];
38 | };
39 | RenderBuffer* vertexBuffer;
40 | RenderBuffer* indexBuffer;
41 |
42 | //
43 | // Testing some GPU buffers and shaders
44 | //
45 |
46 | struct CommonConstantBufferStructure
47 | {
48 | float4x4 gViewProjMat;
49 |
50 | float4 gColor;
51 |
52 | unsigned int gResolution[2];
53 | unsigned int pad;
54 | };
55 | typedef ConstantBuffer CommonConstantBuffer;
56 | CommonConstantBuffer* mConstantBuffer;
57 |
58 | RenderBuffer* mSomeBuffer;
59 | D3dUnorderedAccessView* mSomeBufferUavView;
60 |
61 | DepthStencilState* mDefaultDepthStencilState;
62 | BlendState* mDefaultBlendState;
63 | RasterizerState* mDefaultRasterizerState;
64 |
65 | VertexShader* mVertexShader;
66 | VertexShader* mScreenVertexShader;
67 | PixelShader* mColoredTrianglesShader;
68 | ComputeShader*mToyShader;
69 | PixelShader* mPostProcessShader;
70 |
71 | D3dInputLayout* mLayout;
72 |
73 | Texture2D* mBackBufferHdr;
74 | Texture2D* mBackBufferDepth;
75 |
76 | };
77 |
78 |
79 |
--------------------------------------------------------------------------------
/Application/WinMain.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "Dx11Base/WindowHelper.h"
3 | #include "Dx11Base/Dx11Device.h"
4 |
5 | #include "Game.h"
6 |
7 | #include
8 | #include "imgui\examples\imgui_impl_dx11.h"
9 | #include "imgui\examples\imgui_impl_win32.h"
10 |
11 | // Declaration of a Imgui function we need (see imgui_impl_win32.h)
12 | IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
13 |
14 |
15 | // the entry point for any Windows program
16 | int WINAPI WinMain(HINSTANCE hInstance,
17 | HINSTANCE hPrevInstance,
18 | LPSTR lpCmdLine,
19 | int nCmdShow)
20 | {
21 | static bool sVSyncEnable = true;
22 | static float sTimerGraphWidth = 16.7f; // 60FPS
23 |
24 | // Get a window size that matches the desired client size
25 | const unsigned int desiredPosX = 20;
26 | const unsigned int desiredPosY = 20;
27 | const unsigned int desiredClientWidth = 1280;
28 | const unsigned int desiredClientHeight = 720;
29 | RECT clientRect;
30 | clientRect.left = desiredPosX;
31 | clientRect.right = desiredPosX + desiredClientWidth;
32 | clientRect.bottom = desiredPosY + desiredClientHeight;
33 | clientRect.top = desiredPosY;
34 |
35 | // Create the window
36 | WindowHelper win(hInstance, clientRect, nCmdShow, L"D3D11 Application");
37 | win.showWindow();
38 |
39 | // Create the d3d device (a singleton since we only consider a single window)
40 | Dx11Device::initialise(win.getHwnd());
41 | DxGpuPerformance::initialise();
42 |
43 | // Initialise imgui
44 | ImGuiContext* imguiContext = ImGui::CreateContext();
45 | ImGui::SetCurrentContext(imguiContext);
46 | ImGui_ImplWin32_Init(win.getHwnd());
47 | ImGui_ImplDX11_Init(g_dx11Device->getDevice(), g_dx11Device->getDeviceContext());
48 | // Setup style
49 | ImGui::StyleColorsDark();
50 | //ImGui::StyleColorsClassic();
51 |
52 | // Create the game
53 | Game game;
54 | game.initialise();
55 |
56 |
57 | auto windowResizedCallback = [&](LPARAM lParam)
58 | {
59 | // No threading mechanism so safe to do update call from here.
60 |
61 | uint32 newWidth = LOWORD(lParam);
62 | uint32 newHeight = HIWORD(lParam);
63 |
64 | ImGui_ImplDX11_InvalidateDeviceObjects();
65 | g_dx11Device->updateSwapChain(newWidth, newHeight);
66 | ImGui_ImplDX11_CreateDeviceObjects();
67 |
68 | game.reallocateResolutionDependent(newWidth, newHeight);
69 | };
70 | win.setWindowResizedCallback(windowResizedCallback);
71 |
72 |
73 | MSG msg = { 0 };
74 | while (true)
75 | {
76 | bool msgValid = win.translateSingleMessage(msg);
77 |
78 | if (msgValid)
79 | {
80 | // Update imgui
81 | ImGui_ImplWin32_WndProcHandler(msg.hwnd, msg.message, msg.wParam, msg.lParam);
82 | ImGuiIO& io = ImGui::GetIO();
83 | if (!(io.WantCaptureMouse || io.WantCaptureKeyboard))
84 | {
85 | if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE)
86 | break;// process escape key
87 |
88 | if (msg.message == WM_QUIT)
89 | break; // time to quit
90 |
91 | // A message has been processed and not consumed by imgui. Send the message to the WindowProc function.
92 | DispatchMessage(&msg);
93 | }
94 | }
95 | else
96 | {
97 | DxGpuPerformance::startFrame();
98 | const char* frameGpuTimerName = "Frame";
99 | DxGpuPerformance::startGpuTimer(frameGpuTimerName, 150, 150, 150);
100 |
101 | ImGui_ImplWin32_NewFrame();
102 | ImGui_ImplDX11_NewFrame();
103 | ImGui::NewFrame();
104 |
105 | // Game update
106 | game.update(win.getInputData());
107 |
108 | // Game render
109 | game.render();
110 |
111 | // Render UI
112 | {
113 | //ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver); // Normally user code doesn't need/want to call it because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly!
114 | //ImGui::ShowTestWindow();
115 |
116 | // Gpu performance timer graph debug print
117 | const DxGpuPerformance::TimerGraphNode* timerGraphRootNode = DxGpuPerformance::getLastUpdatedTimerGraphRootNode();
118 | if(timerGraphRootNode)
119 | {
120 | ImGui::SetNextWindowSize(ImVec2(400.0f, 400.0f), ImGuiCond_FirstUseEver);
121 | ImGui::Begin("GPU performance");
122 |
123 | //////////////////////////////////////////////////////////////
124 |
125 | ImGui::Checkbox("VSync", &sVSyncEnable);
126 | ImGui::SliderFloat("TimerGraphWidth (ms)", &sTimerGraphWidth, 1.0, 60.0);
127 |
128 | // Lambda function parsing the timer graph and displaying it using horizontal bars
129 | static bool(*imguiPrintTimerGraphRecurse)(const DxGpuPerformance::TimerGraphNode*, int, int)
130 | = [](const DxGpuPerformance::TimerGraphNode* node, int level, int targetLevel) -> bool
131 | {
132 | const float maxWith = ImGui::GetWindowWidth();
133 | const float msToPixel = maxWith / sTimerGraphWidth;
134 |
135 | bool printDone = false;
136 | if (level == targetLevel)
137 | {
138 | ImU32 color = ImColor(node->r, node->g, node->b);
139 | ImGui::PushStyleColor(ImGuiCol_Button, color);
140 | ImGui::PushStyleColor(ImGuiCol_ButtonHovered, color);
141 | ImGui::PushStyleColor(ImGuiCol_ButtonActive, color);
142 | if (node->mLastDurationMs > 0.0f)
143 | {
144 | // Set cursor to the correct position and size according to when things started this day
145 | ImGui::SetCursorPosX(node->mBeginMs * msToPixel);
146 | ImGui::PushItemWidth(node->mLastDurationMs * msToPixel);
147 |
148 | char debugStr[128];
149 | sprintf_s(debugStr, 128, "%s %.3f ms\n", node->name.c_str(), node->mLastDurationMs);
150 | ImGui::Button(debugStr, ImVec2(node->mLastDurationMs * msToPixel, 0.0f));
151 | if (ImGui::IsItemHovered())
152 | {
153 | ImGui::SetTooltip(debugStr);
154 | }
155 | ImGui::SameLine();
156 | ImGui::PopItemWidth();
157 | }
158 | printDone = true;
159 | ImGui::PopStyleColor(3);
160 | }
161 |
162 | if (level >= targetLevel)
163 | return printDone;
164 |
165 | for (auto& node : node->subGraph)
166 | {
167 | printDone |= imguiPrintTimerGraphRecurse(node, level + 1, targetLevel);
168 | }
169 |
170 | return printDone;
171 | };
172 |
173 | ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
174 | ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 2.0f));
175 | ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
176 | ImGui::BeginChild("Timer graph", ImVec2(0, 150), true, ImGuiWindowFlags_HorizontalScrollbar);
177 | for (int targetLevel = 0; targetLevel < 16; ++targetLevel)
178 | {
179 | bool printDone = false;
180 | for (auto& node : timerGraphRootNode->subGraph)
181 | {
182 | printDone |= imguiPrintTimerGraphRecurse(node, 0, targetLevel);
183 | }
184 | if(printDone)
185 | ImGui::NewLine(); // start a new line if anything has been printed
186 | }
187 | ImGui::EndChild();
188 | ImGui::PopStyleVar(3);
189 |
190 | //////////////////////////////////////////////////////////////
191 |
192 | // Lambda function parsing the timer graph and displaying it as text
193 | static void(*textPrintTimerGraphRecurse)(const DxGpuPerformance::TimerGraphNode*, int)
194 | = [](const DxGpuPerformance::TimerGraphNode* node, int level) -> void
195 | {
196 | char* levelOffset = "---------------"; // 16 chars
197 | unsigned int levelShift = 16 - 2 * level - 1;
198 | char* levelOffsetPtr = levelOffset + (levelShift<0 ? 0 : levelShift); // cheap way to add shifting to a printf
199 |
200 | char debugStr[128];
201 | sprintf_s(debugStr, 128, "%s%s %.3f ms\n", levelOffsetPtr, node->name.c_str(), node->mLastDurationMs);
202 | #if 0
203 | OutputDebugStringA(debugStr);
204 | #else
205 | ImGui::TextColored(ImVec4(node->r, node->g, node->b, 1.0f), debugStr);
206 | #endif
207 |
208 | for (auto& node : node->subGraph)
209 | {
210 | textPrintTimerGraphRecurse(node, level + 1);
211 | }
212 | };
213 | for (auto& node : timerGraphRootNode->subGraph)
214 | {
215 | textPrintTimerGraphRecurse(node, 0);
216 | }
217 |
218 | //////////////////////////////////////////////////////////////
219 |
220 | ImGui::End();
221 | }
222 |
223 | GPU_SCOPED_TIMEREVENT(Imgui, 0, 162, 232);
224 | ImGui::Render();
225 | ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
226 | }
227 |
228 | // Swap the back buffer
229 | g_dx11Device->swap(sVSyncEnable);
230 | DxGpuPerformance::endGpuTimer(frameGpuTimerName);
231 | DxGpuPerformance::endFrame();
232 |
233 | // Events have all been processed in this path by the game
234 | win.clearInputEvents();
235 | }
236 | }
237 |
238 | ImGui_ImplDX11_Shutdown();
239 | ImGui_ImplWin32_Shutdown();
240 | ImGui::DestroyContext(imguiContext);
241 |
242 | game.shutdown();
243 | DxGpuPerformance::shutdown();
244 | Dx11Device::shutdown();
245 |
246 | // End of application
247 | return (int)msg.wParam;
248 | }
249 |
250 |
251 |
--------------------------------------------------------------------------------
/DX11Application.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sebh/Dx11Base/497ba82ded6c6beb169446ce03df328b984b6751/DX11Application.png
--------------------------------------------------------------------------------
/DX11Base.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dx11Base", "DX11Base\dx11Base.vcxproj", "{9412077D-D368-4DBD-AACB-6DBA3618CF12}"
7 | EndProject
8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Application", "Application\Application.vcxproj", "{2CA77969-0EC4-4607-93CC-C63915A2C01F}"
9 | ProjectSection(ProjectDependencies) = postProject
10 | {9412077D-D368-4DBD-AACB-6DBA3618CF12} = {9412077D-D368-4DBD-AACB-6DBA3618CF12}
11 | EndProjectSection
12 | EndProject
13 | Global
14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
15 | Debug|x64 = Debug|x64
16 | Debug|x86 = Debug|x86
17 | Release|x64 = Release|x64
18 | Release|x86 = Release|x86
19 | EndGlobalSection
20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
21 | {9412077D-D368-4DBD-AACB-6DBA3618CF12}.Debug|x64.ActiveCfg = Debug|x64
22 | {9412077D-D368-4DBD-AACB-6DBA3618CF12}.Debug|x64.Build.0 = Debug|x64
23 | {9412077D-D368-4DBD-AACB-6DBA3618CF12}.Debug|x64.Deploy.0 = Debug|x64
24 | {9412077D-D368-4DBD-AACB-6DBA3618CF12}.Debug|x86.ActiveCfg = Debug|Win32
25 | {9412077D-D368-4DBD-AACB-6DBA3618CF12}.Debug|x86.Build.0 = Debug|Win32
26 | {9412077D-D368-4DBD-AACB-6DBA3618CF12}.Release|x64.ActiveCfg = Release|x64
27 | {9412077D-D368-4DBD-AACB-6DBA3618CF12}.Release|x64.Build.0 = Release|x64
28 | {9412077D-D368-4DBD-AACB-6DBA3618CF12}.Release|x86.ActiveCfg = Release|Win32
29 | {9412077D-D368-4DBD-AACB-6DBA3618CF12}.Release|x86.Build.0 = Release|Win32
30 | {2CA77969-0EC4-4607-93CC-C63915A2C01F}.Debug|x64.ActiveCfg = Debug|x64
31 | {2CA77969-0EC4-4607-93CC-C63915A2C01F}.Debug|x64.Build.0 = Debug|x64
32 | {2CA77969-0EC4-4607-93CC-C63915A2C01F}.Debug|x86.ActiveCfg = Debug|Win32
33 | {2CA77969-0EC4-4607-93CC-C63915A2C01F}.Debug|x86.Build.0 = Debug|Win32
34 | {2CA77969-0EC4-4607-93CC-C63915A2C01F}.Release|x64.ActiveCfg = Release|x64
35 | {2CA77969-0EC4-4607-93CC-C63915A2C01F}.Release|x64.Build.0 = Release|x64
36 | {2CA77969-0EC4-4607-93CC-C63915A2C01F}.Release|x86.ActiveCfg = Release|Win32
37 | {2CA77969-0EC4-4607-93CC-C63915A2C01F}.Release|x86.Build.0 = Release|Win32
38 | EndGlobalSection
39 | GlobalSection(SolutionProperties) = preSolution
40 | HideSolutionNode = FALSE
41 | EndGlobalSection
42 | EndGlobal
43 |
--------------------------------------------------------------------------------
/DX11Base/DX11Base.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | {9412077D-D368-4DBD-AACB-6DBA3618CF12}
23 | Win32Proj
24 | DX11Base
25 | 10.0.17134.0
26 |
27 |
28 |
29 | Application
30 | true
31 | v141
32 | Unicode
33 |
34 |
35 | Application
36 | false
37 | v141
38 | true
39 | Unicode
40 |
41 |
42 | StaticLibrary
43 | true
44 | v141
45 | Unicode
46 |
47 |
48 | StaticLibrary
49 | false
50 | v141
51 | true
52 | Unicode
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | true
74 |
75 |
76 | true
77 | $(ProjectDir)..\$(Platform)\$(Configuration)\$(ProjectName)\
78 |
79 |
80 | false
81 |
82 |
83 | true
84 | $(ProjectDir)..\$(Platform)\$(Configuration)\$(ProjectName)\
85 |
86 |
87 |
88 |
89 |
90 | Level3
91 | Disabled
92 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)
93 | true
94 |
95 |
96 | Windows
97 | true
98 |
99 |
100 |
101 |
102 |
103 |
104 | Level3
105 | Disabled
106 | _DEBUG;_WINDOWS;%(PreprocessorDefinitions)
107 | true
108 |
109 |
110 | Windows
111 | true
112 | D3DCompiler.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
113 |
114 |
115 |
116 |
117 | Level3
118 |
119 |
120 | MaxSpeed
121 | true
122 | true
123 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)
124 | true
125 |
126 |
127 | Windows
128 | true
129 | true
130 | true
131 |
132 |
133 |
134 |
135 | Level3
136 |
137 |
138 | Full
139 | true
140 | true
141 | NDEBUG;_WINDOWS;%(PreprocessorDefinitions)
142 | true
143 | $(IntDir)
144 | $(IntDir)
145 | $(IntDir)
146 | $(IntDir)
147 |
148 |
149 | Windows
150 | true
151 | true
152 | DebugFastLink
153 | D3DCompiler.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
--------------------------------------------------------------------------------
/DX11Base/DX11Base.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
10 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
11 |
12 |
13 |
14 |
15 | Source Files
16 |
17 |
18 | Source Files
19 |
20 |
21 |
22 |
23 | Source Files
24 |
25 |
26 | Source Files
27 |
28 |
29 | Source Files
30 |
31 |
32 | Source Files
33 |
34 |
35 |
--------------------------------------------------------------------------------
/DX11Base/Dx11Device.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "Dx11Device.h"
3 | #include "D3Dcompiler.h"
4 | #include "Strsafe.h"
5 | #include // _com_error
6 | #include
7 |
8 | // Good dx tutorial: http://www.directxtutorial.com/Lesson.aspx?lessonid=11-4-2
9 | // Dx debug API http://seanmiddleditch.com/direct3d-11-debug-api-tricks/, also https://msdn.microsoft.com/en-us/library/windows/desktop/ff476881(v=vs.85).aspx#Debug
10 |
11 |
12 | Dx11Device* g_dx11Device = nullptr;
13 |
14 | Dx11Device::Dx11Device()
15 | {
16 | }
17 |
18 | Dx11Device::~Dx11Device()
19 | {
20 | internalShutdown();
21 | }
22 |
23 | void Dx11Device::initialise(const HWND& hWnd)
24 | {
25 | Dx11Device::shutdown();
26 |
27 | g_dx11Device = new Dx11Device();
28 | g_dx11Device->internalInitialise(hWnd);
29 | }
30 |
31 | void Dx11Device::shutdown()
32 | {
33 | delete g_dx11Device;
34 | g_dx11Device = nullptr;
35 | }
36 |
37 | void Dx11Device::internalInitialise(const HWND& hWnd)
38 | {
39 | HRESULT hr;
40 |
41 | // create a struct to hold information about the swap chain
42 | DXGI_SWAP_CHAIN_DESC scd;
43 | ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
44 |
45 | // fill the swap chain description struct
46 | scd.BufferCount = 1; // one back buffer
47 | scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // use 32-bit color
48 | scd.BufferDesc.RefreshRate.Numerator = 1; // 60fps target
49 | scd.BufferDesc.RefreshRate.Denominator = 60; // 60fps target
50 | scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // how swap chain is to be used
51 | scd.OutputWindow = hWnd; // the window to be used
52 | scd.SampleDesc.Count = 1; // multisample
53 | scd.Windowed = TRUE; // windowed/full-screen mode
54 |
55 | const uint32 requestedFeatureLevelsCount = 3;
56 | const D3D_FEATURE_LEVEL requestedFeatureLevels[requestedFeatureLevelsCount] =
57 | {
58 | D3D_FEATURE_LEVEL_12_1, // Always ask for 12.1 feature level if available
59 | // other fallbacks
60 | D3D_FEATURE_LEVEL_12_0,
61 | D3D_FEATURE_LEVEL_11_1, // Always ask for 11.1 (or higher) if available
62 | };
63 |
64 | // create a device, device context and swap chain using the information in the scd struct
65 | hr = D3D11CreateDeviceAndSwapChain(NULL,
66 | D3D_DRIVER_TYPE_HARDWARE,
67 | NULL,
68 | DX_DEBUG_EVENT|DX_DEBUG_RESOURCE_NAME ? D3D11_CREATE_DEVICE_DEBUG : NULL,
69 | requestedFeatureLevels,
70 | requestedFeatureLevelsCount,
71 | D3D11_SDK_VERSION,
72 | &scd,
73 | &mSwapchain,
74 | &mDev,
75 | NULL,
76 | &mDevcon);
77 | ATLASSERT(hr == S_OK);
78 |
79 | #if DX_DEBUG_EVENT
80 | // Could do more https://blogs.msdn.microsoft.com/chuckw/2012/11/30/direct3d-sdk-debug-layer-tricks/
81 | // If this fails, make sure you have the graphic tools installed. (Apps/Manage optional features windows settings)
82 | hr = mDevcon->QueryInterface(__uuidof(mUserDefinedAnnotation), reinterpret_cast(&mUserDefinedAnnotation));
83 | ATLASSERT( hr == S_OK );
84 | #endif // DX_DEBUG_EVENT
85 |
86 | updateSwapChain(0, 0);
87 |
88 | // By default, set the back buffer as current render target and viewport (no state tracking for now...)
89 | mDevcon->OMSetRenderTargets(1, &mBackBufferRT, NULL);
90 | mDevcon->RSSetViewports(1, &mBackBufferViewport);
91 |
92 | D3D_FEATURE_LEVEL deviceFeatureLevel = mDev->GetFeatureLevel();
93 | OutputDebugStringA("\n\nSelected D3D feature level: ");
94 | switch (deviceFeatureLevel)
95 | {
96 | case D3D_FEATURE_LEVEL_12_1:
97 | OutputDebugStringA("D3D_FEATURE_LEVEL_12_1\n\n");
98 | break;
99 | case D3D_FEATURE_LEVEL_12_0:
100 | OutputDebugStringA("D3D_FEATURE_LEVEL_12_0\n\n");
101 | break;
102 | case D3D_FEATURE_LEVEL_11_1:
103 | OutputDebugStringA("D3D_FEATURE_LEVEL_11_1\n\n");
104 | break;
105 | default:
106 | ATLASSERT(false); // unhandled level string
107 | }
108 |
109 | /*D3D11_FEATURE_DATA_D3D11_OPTIONS2 featuretest;
110 | hr = mDev->CheckFeatureSupport(
111 | D3D11_FEATURE_D3D11_OPTIONS2,
112 | &featuretest,
113 | sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS2));
114 | ATLASSERT(hr == S_OK);*/
115 |
116 | /*D3D11_FEATURE_DATA_DOUBLES dataDouble;
117 | hr = mDev->CheckFeatureSupport(D3D11_FEATURE_DOUBLES, &dataDouble, sizeof(dataDouble));
118 | ATLASSERT(hr == S_OK);
119 | if (!dataDouble.DoublePrecisionFloatShaderOps)
120 | {
121 | printf("No hardware support for double-precision.\n");
122 | }*/
123 | }
124 |
125 | void Dx11Device::internalShutdown()
126 | {
127 | // close and release all existing COM objects
128 | resetComPtr(&mBackBufferRT);
129 | resetComPtr(&mSwapchain);
130 | resetComPtr(&mDev);
131 | resetComPtr(&mDevcon);
132 | }
133 |
134 | void Dx11Device::updateSwapChain(uint32 newWidth, uint32 newHeight)
135 | {
136 | resetComPtr(&mBackBufferRT);
137 |
138 | if (newWidth > 0 && newHeight > 0)
139 | {
140 | mSwapchain->ResizeBuffers(0, newWidth, newHeight, DXGI_FORMAT_UNKNOWN, 0);
141 |
142 | // Update the back buffer RT
143 | ID3D11Texture2D* backBufferTexture;// back buffer texture
144 | mSwapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBufferTexture);
145 | mDev->CreateRenderTargetView(backBufferTexture, NULL, &mBackBufferRT);
146 | resetComPtr(&backBufferTexture); // This does not delete the object. Just release the ref we just got.
147 |
148 | mBackBufferViewport.Width = (float)newWidth;
149 | mBackBufferViewport.Height = (float)newHeight;
150 | }
151 | else
152 | {
153 | // We get here when creating a Dx11Device
154 | ID3D11Texture2D* backBufferTexture;// back buffer texture
155 | mSwapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBufferTexture);
156 | mDev->CreateRenderTargetView(backBufferTexture, NULL, &mBackBufferRT);
157 |
158 | D3dTexture2dDesc texDesc;
159 | backBufferTexture->GetDesc(&texDesc);
160 | mBackBufferViewport.TopLeftX = 0.0f;
161 | mBackBufferViewport.TopLeftY = 0.0f;
162 | mBackBufferViewport.Width = (float)texDesc.Width;
163 | mBackBufferViewport.Height = (float)texDesc.Height;
164 | mBackBufferViewport.MinDepth = 0.0f;
165 | mBackBufferViewport.MaxDepth = 1.0f;
166 |
167 | resetComPtr(&backBufferTexture); // See description above.
168 | }
169 | }
170 |
171 | void Dx11Device::swap(bool vsyncEnabled)
172 | {
173 | mSwapchain->Present(vsyncEnabled ? 1 : 0, 0);
174 | }
175 |
176 | ////////////////////////////////////////////////////////////////////////////////////////////////////
177 | ////////////////////////////////////////////////////////////////////////////////////////////////////
178 | ////////////////////////////////////////////////////////////////////////////////////////////////////
179 |
180 |
181 | RenderBuffer::RenderBuffer(D3dBufferDesc& bufferDesc, void* initialData) :
182 | mDesc(bufferDesc)
183 | {
184 | ID3D11Device* device = g_dx11Device->getDevice();
185 |
186 | D3dSubResourceData data;
187 | data.pSysMem = initialData;
188 | data.SysMemPitch = 0;
189 | data.SysMemSlicePitch = 0;
190 |
191 | HRESULT hr = device->CreateBuffer( &mDesc, initialData ? &data : nullptr, &mBuffer);
192 | ATLASSERT(hr == S_OK);
193 | }
194 |
195 | RenderBuffer::~RenderBuffer()
196 | {
197 | resetComPtr(&mBuffer);
198 | }
199 |
200 | void RenderBuffer::map(D3D11_MAP map, ScopedMappedRenderbuffer& mappedBuffer)
201 | {
202 | // Check some state
203 | ATLASSERT( mDesc.Usage == D3D11_USAGE_DYNAMIC && (mDesc.CPUAccessFlags&D3D11_CPU_ACCESS_WRITE)!=0 );
204 |
205 | // Reset to 0
206 | ZeroMemory(&mappedBuffer.mMappedResource, sizeof(D3D11_MAPPED_SUBRESOURCE));
207 |
208 | D3dRenderContext* context = g_dx11Device->getDeviceContext();
209 | context->Map(mBuffer, 0, map, 0, &mappedBuffer.mMappedResource);
210 | mappedBuffer.mMappedBuffer = mBuffer;
211 | }
212 |
213 | void RenderBuffer::unmap(ScopedMappedRenderbuffer& mappedBuffer)
214 | {
215 | if (mappedBuffer.mMappedBuffer)
216 | {
217 | D3dRenderContext* context = g_dx11Device->getDeviceContext();
218 | context->Unmap(mappedBuffer.mMappedBuffer, 0);
219 | mappedBuffer.mMappedBuffer = nullptr;
220 | }
221 | }
222 |
223 | D3dBufferDesc RenderBuffer::initConstantBufferDesc_dynamic(uint32 byteSize)
224 | {
225 | D3dBufferDesc desc = { byteSize , D3D11_USAGE_DYNAMIC, D3D11_BIND_CONSTANT_BUFFER, D3D11_CPU_ACCESS_WRITE, 0, 0 };
226 | return desc;
227 | }
228 | D3dBufferDesc RenderBuffer::initVertexBufferDesc_default(uint32 byteSize)
229 | {
230 | D3dBufferDesc desc = { byteSize , D3D11_USAGE_DEFAULT, D3D11_BIND_VERTEX_BUFFER, 0, 0, 0 };
231 | return desc;
232 | }
233 | D3dBufferDesc RenderBuffer::initIndexBufferDesc_default(uint32 byteSize)
234 | {
235 | D3dBufferDesc desc = { byteSize , D3D11_USAGE_DEFAULT, D3D11_BIND_INDEX_BUFFER, 0, 0, 0 };
236 | return desc;
237 | }
238 | D3dBufferDesc RenderBuffer::initBufferDesc_default(uint32 byteSize)
239 | {
240 | D3dBufferDesc desc = { byteSize , D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, 0 };
241 | return desc;
242 | }
243 | D3dBufferDesc RenderBuffer::initBufferDesc_uav(uint32 byteSize)
244 | {
245 | D3dBufferDesc desc = { byteSize , D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS, 0, 0, 0 };
246 | return desc;
247 | }
248 |
249 |
250 | ////////////////////////////////////////////////////////////////////////////////////////////////////
251 | ////////////////////////////////////////////////////////////////////////////////////////////////////
252 | ////////////////////////////////////////////////////////////////////////////////////////////////////
253 |
254 | DXGI_FORMAT getDepthStencilViewFormatFromTypeless(DXGI_FORMAT format)
255 | {
256 | switch (format)
257 | {
258 | case DXGI_FORMAT_R16_TYPELESS:
259 | return DXGI_FORMAT_D16_UNORM;
260 | break;
261 | case DXGI_FORMAT_R24G8_TYPELESS:
262 | return DXGI_FORMAT_D24_UNORM_S8_UINT;
263 | break;
264 | case DXGI_FORMAT_R32_TYPELESS:
265 | return DXGI_FORMAT_D32_FLOAT;
266 | break;
267 | }
268 | ATLASSERT(false); // unknown format
269 | return DXGI_FORMAT_UNKNOWN;
270 | }
271 | DXGI_FORMAT getDepthShaderResourceFormatFromTypeless(DXGI_FORMAT format)
272 | {
273 | switch (format)
274 | {
275 | case DXGI_FORMAT_R16_TYPELESS:
276 | return DXGI_FORMAT_R16_UNORM;
277 | break;
278 | case DXGI_FORMAT_R24G8_TYPELESS:
279 | return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
280 | break;
281 | case DXGI_FORMAT_R32_TYPELESS:
282 | return DXGI_FORMAT_D32_FLOAT;
283 | break;
284 | }
285 | ATLASSERT(false); // unknown format
286 | return DXGI_FORMAT_UNKNOWN;
287 | }
288 |
289 | bool isFormatTypeless(DXGI_FORMAT format)
290 | {
291 | switch (format)
292 | {
293 | case DXGI_FORMAT_R32G32B32A32_TYPELESS:
294 | case DXGI_FORMAT_R32G32B32_TYPELESS:
295 | case DXGI_FORMAT_R16G16B16A16_TYPELESS:
296 | case DXGI_FORMAT_R32G32_TYPELESS:
297 | case DXGI_FORMAT_R32G8X24_TYPELESS:
298 | case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
299 | case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
300 | case DXGI_FORMAT_R10G10B10A2_TYPELESS:
301 | case DXGI_FORMAT_R8G8B8A8_TYPELESS:
302 | case DXGI_FORMAT_R16G16_TYPELESS:
303 | case DXGI_FORMAT_R32_TYPELESS:
304 | case DXGI_FORMAT_R24G8_TYPELESS:
305 | //case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
306 | //case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
307 | case DXGI_FORMAT_R8G8_TYPELESS:
308 | case DXGI_FORMAT_R16_TYPELESS:
309 | case DXGI_FORMAT_R8_TYPELESS:
310 | case DXGI_FORMAT_BC1_TYPELESS:
311 | case DXGI_FORMAT_BC2_TYPELESS:
312 | case DXGI_FORMAT_BC3_TYPELESS:
313 | case DXGI_FORMAT_BC4_TYPELESS:
314 | case DXGI_FORMAT_BC5_TYPELESS:
315 | case DXGI_FORMAT_B8G8R8A8_TYPELESS:
316 | case DXGI_FORMAT_B8G8R8X8_TYPELESS:
317 | case DXGI_FORMAT_BC6H_TYPELESS:
318 | case DXGI_FORMAT_BC7_TYPELESS:
319 | return true;
320 | }
321 | return false;
322 | }
323 |
324 | Texture2D::Texture2D(D3dTexture2dDesc& desc, D3dSubResourceData* initialData) :
325 | mDesc(desc)
326 | {
327 | ID3D11Device* device = g_dx11Device->getDevice();
328 | HRESULT hr = device->CreateTexture2D(&mDesc, initialData, &mTexture);
329 | ATLASSERT(hr == S_OK);
330 |
331 | DXGI_FORMAT format = desc.Format;
332 | if (mDesc.BindFlags & D3D11_BIND_DEPTH_STENCIL)
333 | {
334 | CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D);
335 | depthStencilViewDesc.Format = getDepthStencilViewFormatFromTypeless(format);
336 | HRESULT hr = device->CreateDepthStencilView(mTexture, &depthStencilViewDesc, &mDepthStencilView);
337 | ATLASSERT(hr == S_OK);
338 |
339 | format = getDepthShaderResourceFormatFromTypeless(format);
340 | }
341 |
342 | ATLASSERT(!isFormatTypeless(format));
343 |
344 | if (mDesc.BindFlags & D3D11_BIND_SHADER_RESOURCE)
345 | {
346 | CD3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc(D3D11_SRV_DIMENSION_TEXTURE2D);
347 | shaderResourceViewDesc.Format = format;
348 | HRESULT hr = device->CreateShaderResourceView(mTexture, &shaderResourceViewDesc, &mShaderResourceView);
349 | ATLASSERT(hr == S_OK);
350 | }
351 | if (mDesc.BindFlags & D3D11_BIND_UNORDERED_ACCESS)
352 | {
353 | CD3D11_UNORDERED_ACCESS_VIEW_DESC unorderedAccessViewDesc(D3D11_UAV_DIMENSION_TEXTURE2D);
354 | unorderedAccessViewDesc.Format = format;
355 | HRESULT hr = device->CreateUnorderedAccessView(mTexture, &unorderedAccessViewDesc, &mUnorderedAccessView);
356 | ATLASSERT(hr == S_OK);
357 | }
358 | if (mDesc.BindFlags & D3D11_BIND_RENDER_TARGET)
359 | {
360 | CD3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc(D3D11_RTV_DIMENSION_TEXTURE2D);
361 | renderTargetViewDesc.Format = format;
362 | HRESULT hr = device->CreateRenderTargetView(mTexture, &renderTargetViewDesc, &mRenderTargetView);
363 | ATLASSERT(hr == S_OK);
364 | }
365 | }
366 | Texture2D::~Texture2D()
367 | {
368 | if (mDesc.BindFlags & D3D11_BIND_DEPTH_STENCIL)
369 | {
370 | resetComPtr(&mDepthStencilView);
371 | }
372 | if (mDesc.BindFlags & D3D11_BIND_SHADER_RESOURCE)
373 | {
374 | resetComPtr(&mShaderResourceView);
375 | }
376 | if (mDesc.BindFlags & D3D11_BIND_UNORDERED_ACCESS)
377 | {
378 | resetComPtr(&mUnorderedAccessView);
379 | }
380 | if (mDesc.BindFlags & D3D11_BIND_RENDER_TARGET)
381 | {
382 | resetComPtr(&mRenderTargetView);
383 | }
384 | resetComPtr(&mTexture);
385 | }
386 | D3dTexture2dDesc Texture2D::initDepthStencilBuffer(uint32 width, uint32 height, bool uav)
387 | {
388 | D3dTexture2dDesc desc = { 0 };
389 | desc.Width = width;
390 | desc.Height = height;
391 | desc.MipLevels = 1;
392 | desc.ArraySize = 1;
393 | desc.Format = DXGI_FORMAT_R24G8_TYPELESS; // DXGI_FORMAT_D24_UNORM_S8_UINT;
394 | desc.SampleDesc.Count = 1;
395 | desc.SampleDesc.Quality = 0;
396 | desc.Usage = D3D11_USAGE_DEFAULT;
397 | desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL | (uav ? D3D11_BIND_UNORDERED_ACCESS : 0); // cannot be D3D11_BIND_SHADER_RESOURCE
398 | desc.CPUAccessFlags = 0;
399 | desc.MiscFlags = 0;
400 | return desc;
401 | }
402 |
403 | D3dTexture2dDesc Texture2D::initDefault(DXGI_FORMAT format, uint32 width, uint32 height, bool renderTarget, bool uav)
404 | {
405 | D3dTexture2dDesc desc = { 0 };
406 | desc.Width = width;
407 | desc.Height = height;
408 | desc.MipLevels = 1;
409 | desc.ArraySize = 1;
410 | desc.Format = format;
411 | desc.SampleDesc.Count = 1;
412 | desc.SampleDesc.Quality = 0;
413 | desc.Usage = D3D11_USAGE_DEFAULT;
414 | desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | (renderTarget ? D3D11_BIND_RENDER_TARGET : 0) | (uav ? D3D11_BIND_UNORDERED_ACCESS : 0);
415 | desc.CPUAccessFlags = 0;
416 | desc.MiscFlags = 0;
417 | return desc;
418 | }
419 |
420 |
421 |
422 |
423 |
424 | Texture3D::Texture3D(D3dTexture3dDesc& desc, D3dSubResourceData* initialData) :
425 | mDesc(desc)
426 | {
427 | ID3D11Device* device = g_dx11Device->getDevice();
428 | HRESULT hr = device->CreateTexture3D(&mDesc, initialData, &mTexture);
429 | ATLASSERT(hr == S_OK);
430 |
431 | if (mDesc.BindFlags & D3D11_BIND_SHADER_RESOURCE)
432 | {
433 | CD3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc(D3D11_SRV_DIMENSION_TEXTURE3D);
434 | shaderResourceViewDesc.Format = desc.Format;
435 | HRESULT hr = device->CreateShaderResourceView(mTexture, &shaderResourceViewDesc, &mShaderResourceView);
436 | ATLASSERT(hr == S_OK);
437 | if (desc.MipLevels > 1)
438 | {
439 | for (uint32 l = 0; l < desc.MipLevels; ++l)
440 | {
441 | shaderResourceViewDesc.Texture3D.MostDetailedMip = l;
442 | shaderResourceViewDesc.Texture3D.MipLevels = 1;
443 |
444 | ID3D11ShaderResourceView* mipShaderResourceView;
445 | hr = device->CreateShaderResourceView(mTexture, &shaderResourceViewDesc, &mipShaderResourceView);
446 | ATLASSERT(hr == S_OK);
447 | mShaderResourceViewMips.push_back(mipShaderResourceView);
448 | }
449 | }
450 | }
451 | if (mDesc.BindFlags & D3D11_BIND_UNORDERED_ACCESS)
452 | {
453 | CD3D11_UNORDERED_ACCESS_VIEW_DESC unorderedAccessViewDesc(D3D11_UAV_DIMENSION_TEXTURE3D);
454 | unorderedAccessViewDesc.Format = desc.Format;
455 | HRESULT hr = device->CreateUnorderedAccessView(mTexture, &unorderedAccessViewDesc, &mUnorderedAccessView);
456 | ATLASSERT(hr == S_OK);
457 | if (desc.MipLevels > 1)
458 | {
459 | for (uint32 l = 0; l < desc.MipLevels; ++l)
460 | {
461 | unorderedAccessViewDesc.Texture3D.MipSlice = l;
462 |
463 | ID3D11UnorderedAccessView* mipUnorderedAccessView;
464 | hr = device->CreateUnorderedAccessView(mTexture, &unorderedAccessViewDesc, &mipUnorderedAccessView);
465 | ATLASSERT(hr == S_OK);
466 | mUnorderedAccessViewMips.push_back(mipUnorderedAccessView);
467 | }
468 | }
469 | }
470 | if (mDesc.BindFlags & D3D11_BIND_RENDER_TARGET)
471 | {
472 | CD3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc(D3D11_RTV_DIMENSION_TEXTURE3D);
473 | renderTargetViewDesc.Format = desc.Format;
474 | renderTargetViewDesc.Texture3D.MipSlice = 0;
475 | renderTargetViewDesc.Texture3D.FirstWSlice = 0;
476 | renderTargetViewDesc.Texture3D.WSize = desc.Depth;
477 | HRESULT hr = device->CreateRenderTargetView(mTexture, &renderTargetViewDesc, &mRenderTargetView);
478 | ATLASSERT(hr == S_OK);
479 | }
480 | }
481 | Texture3D::~Texture3D()
482 | {
483 | if (mDesc.BindFlags & D3D11_BIND_SHADER_RESOURCE)
484 | {
485 | resetComPtr(&mShaderResourceView);
486 | for (auto view : mShaderResourceViewMips)
487 | {
488 | resetComPtr(&view);
489 | }
490 | mShaderResourceViewMips.clear();
491 | }
492 | if (mDesc.BindFlags & D3D11_BIND_UNORDERED_ACCESS)
493 | {
494 | resetComPtr(&mUnorderedAccessView);
495 | for (auto view : mUnorderedAccessViewMips)
496 | {
497 | resetComPtr(&view);
498 | }
499 | mUnorderedAccessViewMips.clear();
500 | }
501 | resetComPtr(&mTexture);
502 | if (mDesc.BindFlags & D3D11_BIND_RENDER_TARGET)
503 | {
504 | resetComPtr(&mRenderTargetView);
505 | }
506 | }
507 | D3dTexture3dDesc Texture3D::initDefault(DXGI_FORMAT format, uint32 width, uint32 height, uint32 depth, bool renderTarget, bool uav)
508 | {
509 | D3dTexture3dDesc desc = { 0 };
510 | desc.Width = width;
511 | desc.Height = height;
512 | desc.Depth = depth;
513 | desc.MipLevels = 1;
514 | desc.Format = format;
515 | desc.Usage = D3D11_USAGE_DEFAULT;
516 | desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | (renderTarget ? D3D11_BIND_RENDER_TARGET : 0) | (uav ? D3D11_BIND_UNORDERED_ACCESS : 0);
517 | desc.CPUAccessFlags = 0;
518 | desc.MiscFlags = 0;
519 | return desc;
520 | }
521 |
522 |
523 |
524 | SamplerState::SamplerState(D3dSamplerDesc& desc)
525 | {
526 | ID3D11Device* device = g_dx11Device->getDevice();
527 | HRESULT hr = device->CreateSamplerState(&desc, &mSampler);
528 | ATLASSERT(hr == S_OK);
529 | }
530 | SamplerState::~SamplerState()
531 | {
532 | resetComPtr(&mSampler);
533 | }
534 | D3dSamplerDesc SamplerState::initLinearClamp()
535 | {
536 | D3dSamplerDesc desc = { 0 };
537 | desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
538 | desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
539 | desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
540 | desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
541 | desc.MipLODBias = 0.0f;
542 | desc.MaxAnisotropy = 1;
543 | desc.ComparisonFunc = D3D11_COMPARISON_NEVER;
544 | desc.BorderColor[0] = desc.BorderColor[1] = desc.BorderColor[2] = desc.BorderColor[3] = 1.0f;
545 | desc.MinLOD = -FLT_MAX;
546 | desc.MaxLOD = FLT_MAX;
547 | return desc;
548 | }
549 | D3dSamplerDesc SamplerState::initPointClamp()
550 | {
551 | D3dSamplerDesc desc = { 0 };
552 | desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
553 | desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
554 | desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
555 | desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
556 | desc.MipLODBias = 0.0f;
557 | desc.MaxAnisotropy = 1;
558 | desc.ComparisonFunc = D3D11_COMPARISON_NEVER;
559 | desc.BorderColor[0] = desc.BorderColor[1] = desc.BorderColor[2] = desc.BorderColor[3] = 1.0f;
560 | desc.MinLOD = -FLT_MAX;
561 | desc.MaxLOD = FLT_MAX;
562 | return desc;
563 | }
564 | D3dSamplerDesc SamplerState::initShadowCmpClamp()
565 | {
566 | D3dSamplerDesc desc = { 0 };
567 | desc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT;
568 | desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
569 | desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
570 | desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
571 | desc.MipLODBias = 0.0f;
572 | desc.MaxAnisotropy = 1;
573 | desc.ComparisonFunc = D3D11_COMPARISON_LESS;
574 | desc.BorderColor[0] = desc.BorderColor[1] = desc.BorderColor[2] = desc.BorderColor[3] = 1.0f;
575 | desc.MinLOD = -FLT_MAX;
576 | desc.MaxLOD = FLT_MAX;
577 | return desc;
578 | }
579 |
580 |
581 | ////////////////////////////////////////////////////////////////////////////////////////////////////
582 | ////////////////////////////////////////////////////////////////////////////////////////////////////
583 | ////////////////////////////////////////////////////////////////////////////////////////////////////
584 |
585 |
586 | DepthStencilState::DepthStencilState(D3dDepthStencilDesc& desc)
587 | {
588 | ID3D11Device* device = g_dx11Device->getDevice();
589 | HRESULT hr = device->CreateDepthStencilState(&desc, &mState);
590 | ATLASSERT(hr == S_OK);
591 | }
592 | DepthStencilState::~DepthStencilState()
593 | {
594 | resetComPtr(&mState);
595 | }
596 | D3dDepthStencilDesc DepthStencilState::initDefaultDepthOnStencilOff()
597 | {
598 | D3dDepthStencilDesc desc = { 0 };
599 | // Depth test parameters
600 | desc.DepthEnable = true;
601 | desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
602 | desc.DepthFunc = D3D11_COMPARISON_LESS;
603 | // Stencil test parameters
604 | desc.StencilEnable = false;
605 | desc.StencilReadMask = 0xFF;
606 | desc.StencilWriteMask = 0xFF;
607 | // Stencil operations if pixel is front-facing
608 | desc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
609 | desc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
610 | desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
611 | desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
612 | // Stencil operations if pixel is back-facing
613 | desc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
614 | desc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
615 | desc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
616 | desc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
617 | return desc;
618 | }
619 | D3dDepthStencilDesc DepthStencilState::initDepthNoWriteStencilOff()
620 | {
621 | D3dDepthStencilDesc desc = { 0 };
622 | // Depth test parameters
623 | desc.DepthEnable = true;
624 | desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
625 | desc.DepthFunc = D3D11_COMPARISON_LESS;
626 | // Stencil test parameters
627 | desc.StencilEnable = false;
628 | desc.StencilReadMask = 0xFF;
629 | desc.StencilWriteMask = 0xFF;
630 | // Stencil operations if pixel is front-facing
631 | desc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
632 | desc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
633 | desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
634 | desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
635 | // Stencil operations if pixel is back-facing
636 | desc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
637 | desc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
638 | desc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
639 | desc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
640 | return desc;
641 | }
642 |
643 | RasterizerState::RasterizerState(D3dRasterizerDesc& desc)
644 | {
645 | ID3D11Device* device = g_dx11Device->getDevice();
646 | HRESULT hr = device->CreateRasterizerState(&desc, &mState);
647 | ATLASSERT(hr == S_OK);
648 | }
649 | RasterizerState::~RasterizerState()
650 | {
651 | resetComPtr(&mState);
652 | }
653 | D3dRasterizerDesc RasterizerState::initDefaultState()
654 | {
655 | D3dRasterizerDesc desc = { 0 };
656 | ZeroMemory(&desc, sizeof(D3dRasterizerDesc));
657 | desc.AntialiasedLineEnable = FALSE;
658 | desc.CullMode = D3D11_CULL_BACK;
659 | desc.DepthBias = 0;
660 | desc.DepthBiasClamp = 0.0f;
661 | desc.DepthClipEnable = TRUE;
662 | desc.FillMode = D3D11_FILL_SOLID;
663 | desc.FrontCounterClockwise = FALSE;
664 | desc.MultisampleEnable = FALSE;
665 | desc.ScissorEnable = FALSE;
666 | desc.SlopeScaledDepthBias = 0.0f;
667 | return desc;
668 | }
669 |
670 |
671 | BlendState::BlendState(D3dBlendDesc & desc)
672 | {
673 | ID3D11Device* device = g_dx11Device->getDevice();
674 | HRESULT hr = device->CreateBlendState(&desc, &mState);
675 | ATLASSERT(hr == S_OK);
676 | }
677 | BlendState::~BlendState()
678 | {
679 | resetComPtr(&mState);
680 | }
681 | D3dBlendDesc BlendState::initDisabledState()
682 | {
683 | D3dBlendDesc desc = { 0 };
684 | desc.AlphaToCoverageEnable = false;
685 | desc.IndependentBlendEnable = false;
686 | desc.RenderTarget[0].BlendEnable = false;
687 | desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
688 | desc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
689 | desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
690 | desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
691 | desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
692 | desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
693 | desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
694 | return desc;
695 | }
696 | D3dBlendDesc BlendState::initPreMultBlendState()
697 | {
698 | D3dBlendDesc desc = { 0 };
699 | desc.AlphaToCoverageEnable = false;
700 | desc.IndependentBlendEnable = false;
701 | desc.RenderTarget[0].BlendEnable = true;
702 | desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
703 | desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
704 | desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; // src*1 + dst*(1.0 - srcA)
705 | desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
706 | desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
707 | desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; // src*0 + dst * (1.0 - srcA)
708 | desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
709 | return desc;
710 | }
711 | D3dBlendDesc BlendState::initPreMultDualBlendState()
712 | {
713 | D3dBlendDesc desc = { 0 };
714 | desc.AlphaToCoverageEnable = false;
715 | desc.IndependentBlendEnable = false;
716 | desc.RenderTarget[0].BlendEnable = true;
717 | desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
718 | desc.RenderTarget[0].DestBlend = D3D11_BLEND_SRC1_COLOR;
719 | desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; // src0*1 + dst*src1 , colored transmittance + color
720 | desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
721 | desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE;
722 | desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; // src*0 + dst*1 , keep alpha intact
723 | desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
724 | return desc;
725 | }
726 | D3dBlendDesc BlendState::initAdditiveState()
727 | {
728 | D3dBlendDesc desc = { 0 };
729 | desc.AlphaToCoverageEnable = false;
730 | desc.IndependentBlendEnable = false;
731 | desc.RenderTarget[0].BlendEnable = true;
732 | desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
733 | desc.RenderTarget[0].DestBlend = D3D11_BLEND_ONE;
734 | desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
735 | desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
736 | desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE;
737 | desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
738 | desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
739 | return desc;
740 | }
741 |
742 |
743 | ////////////////////////////////////////////////////////////////////////////////////////////////////
744 | ////////////////////////////////////////////////////////////////////////////////////////////////////
745 | ////////////////////////////////////////////////////////////////////////////////////////////////////
746 |
747 |
748 | void appendSimpleVertexDataToInputLayout(InputLayoutDesc& inputLayout, const char* semanticName, DXGI_FORMAT format)
749 | {
750 | D3dInputElementDesc desc;
751 |
752 | desc.SemanticName = semanticName;
753 | desc.SemanticIndex = 0;
754 | desc.Format = format;
755 | desc.InputSlot = 0;
756 | desc.AlignedByteOffset = inputLayout.empty() ? 0 : D3D11_APPEND_ALIGNED_ELEMENT;
757 | desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
758 | desc.InstanceDataStepRate = 0;
759 |
760 | inputLayout.push_back(desc);
761 | }
762 |
763 |
764 | ////////////////////////////////////////////////////////////////////////////////////////////////////
765 | ////////////////////////////////////////////////////////////////////////////////////////////////////
766 | ////////////////////////////////////////////////////////////////////////////////////////////////////
767 |
768 | static ID3D10Blob* compileShader(const TCHAR* filename, const char* entryFunction, const char* profile, const Macros* macros = NULL)
769 | {
770 | ID3D10Blob* shaderBuffer = NULL;
771 | ID3DBlob * errorbuffer = NULL;
772 | const uint32 defaultFlags = 0;
773 |
774 | #define MAX_SHADER_MACRO 64
775 | D3D_SHADER_MACRO shaderMacros[MAX_SHADER_MACRO];
776 | shaderMacros[0] = { NULL, NULL }; // in case there is no macros
777 | if (macros != NULL)
778 | {
779 | size_t macrosCount = macros->size();
780 | bool validMacroCount = macros->size() <= MAX_SHADER_MACRO-1; // -1 to handle the null end of list macro
781 | ATLASSERT(validMacroCount);
782 | if (!validMacroCount)
783 | {
784 | OutputDebugStringA("\nNumber of macro is too high for shader ");
785 | OutputDebugStringW(filename);
786 | OutputDebugStringA("\n");
787 | return NULL;
788 | }
789 | for (int32 m = 0; m < macrosCount; ++m)
790 | {
791 | const ShaderMacro& sm = macros->at(m);
792 | shaderMacros[m] = { sm.Name.c_str() , sm.Definition.c_str() };
793 | }
794 | shaderMacros[macrosCount] = { NULL, NULL };
795 | }
796 |
797 | HRESULT hr = D3DCompileFromFile(
798 | filename, // filename
799 | shaderMacros, // defines
800 | D3D_COMPILE_STANDARD_FILE_INCLUDE, // default include handler (includes relative to the compiled file)
801 | entryFunction, // function name
802 | profile, // target profile
803 | defaultFlags, // flag1
804 | defaultFlags, // flag2
805 | &shaderBuffer, // ouput
806 | &errorbuffer); // errors
807 |
808 | if (FAILED(hr))
809 | {
810 | OutputDebugStringA("\n===> Failed to compile shader: function=");
811 | OutputDebugStringA(entryFunction);
812 | OutputDebugStringA(", profile=");
813 | OutputDebugStringA(profile);
814 | OutputDebugStringA(", file=");
815 | OutputDebugStringW(filename);
816 | OutputDebugStringA(" :\n");
817 | OutputDebugStringA(" HResult = ");
818 | _com_error err(hr);
819 | OutputDebugStringW(err.ErrorMessage());
820 | OutputDebugStringA("\n");
821 | if (errorbuffer)
822 | {
823 | OutputDebugStringA((char*)errorbuffer->GetBufferPointer());
824 | resetComPtr(&errorbuffer);
825 | }
826 | resetComPtr(&shaderBuffer);
827 | OutputDebugStringA("\n\n");
828 | return NULL;
829 | }
830 | return shaderBuffer;
831 | }
832 |
833 | ShaderBase::ShaderBase(const TCHAR* filename, const char* entryFunction, const char* profile, const Macros* macros, bool lazyCompilation)
834 | : mShaderBuffer(nullptr)
835 | , mFilename(filename)
836 | , mEntryFunction(entryFunction)
837 | , mProfile(profile)
838 | {
839 | if(macros)
840 | mMacros = *macros;
841 | if(!lazyCompilation)
842 | mShaderBuffer = compileShader(mFilename, mEntryFunction, mProfile, macros);
843 | }
844 |
845 | ShaderBase::~ShaderBase()
846 | {
847 | resetComPtr(&mShaderBuffer);
848 | }
849 |
850 | bool ShaderBase::recompileShaderIfNeeded()
851 | {
852 | ID3D10Blob* compiledShaderBuffer;
853 | bool newShaderBinaryAvailable = false;
854 | if (mDirty && (compiledShaderBuffer = compileShader(mFilename, mEntryFunction, mProfile, &mMacros)))
855 | {
856 | resetComPtr(&mShaderBuffer);
857 | mShaderBuffer = compiledShaderBuffer;
858 | newShaderBinaryAvailable = true;
859 | }
860 | mDirty = false; // we always remove dirtiness to avoid try to recompile each frame.
861 | return newShaderBinaryAvailable;
862 | }
863 |
864 | VertexShader::VertexShader(const TCHAR* filename, const char* entryFunction, const Macros* macros, bool lazyCompilation)
865 | : ShaderBase(filename, entryFunction, "vs_5_0", macros, lazyCompilation)
866 | {
867 | if (!compilationSuccessful()) return; // failed compilation
868 | ID3D11Device* device = g_dx11Device->getDevice();
869 | HRESULT hr = device->CreateVertexShader(mShaderBuffer->GetBufferPointer(), mShaderBuffer->GetBufferSize(), NULL, &mVertexShader);
870 | ATLASSERT(hr == S_OK);
871 | mDirty = false;
872 | }
873 | VertexShader::~VertexShader()
874 | {
875 | resetComPtr(&mVertexShader);
876 | }
877 |
878 | void VertexShader::createInputLayout(InputLayoutDesc inputLayout, D3dInputLayout** layout)
879 | {
880 | ID3D11Device* device = g_dx11Device->getDevice();
881 | HRESULT hr = device->CreateInputLayout(inputLayout.data(), uint32(inputLayout.size()), mShaderBuffer->GetBufferPointer(), mShaderBuffer->GetBufferSize(), layout);
882 | ATLASSERT(hr == S_OK);
883 | }
884 |
885 | void VertexShader::setShader(D3dRenderContext& context)
886 | {
887 | if (recompileShaderIfNeeded())
888 | {
889 | resetComPtr(&mVertexShader);
890 | ID3D11Device* device = g_dx11Device->getDevice();
891 | HRESULT hr = device->CreateVertexShader(mShaderBuffer->GetBufferPointer(), mShaderBuffer->GetBufferSize(), NULL, &mVertexShader);
892 | ATLASSERT(hr == S_OK);
893 | }
894 | context.VSSetShader(mVertexShader, nullptr, 0);
895 | }
896 |
897 | PixelShader::PixelShader(const TCHAR* filename, const char* entryFunction, const Macros* macros, bool lazyCompilation)
898 | : ShaderBase(filename, entryFunction, "ps_5_0", macros, lazyCompilation)
899 | {
900 | if (!compilationSuccessful()) return; // failed compilation
901 | ID3D11Device* device = g_dx11Device->getDevice();
902 | HRESULT hr = device->CreatePixelShader(mShaderBuffer->GetBufferPointer(), mShaderBuffer->GetBufferSize(), NULL, &mPixelShader);
903 | ATLASSERT(hr == S_OK);
904 | mDirty = false;
905 | }
906 | PixelShader::~PixelShader()
907 | {
908 | resetComPtr(&mPixelShader);
909 | }
910 | void PixelShader::setShader(D3dRenderContext& context)
911 | {
912 | if (recompileShaderIfNeeded())
913 | {
914 | resetComPtr(&mPixelShader);
915 | ID3D11Device* device = g_dx11Device->getDevice();
916 | HRESULT hr = device->CreatePixelShader(mShaderBuffer->GetBufferPointer(), mShaderBuffer->GetBufferSize(), NULL, &mPixelShader);
917 | ATLASSERT(hr == S_OK);
918 | }
919 | context.PSSetShader(mPixelShader, nullptr, 0);
920 | }
921 |
922 | HullShader::HullShader(const TCHAR* filename, const char* entryFunction, const Macros* macros, bool lazyCompilation)
923 | : ShaderBase(filename, entryFunction, "hs_5_0", macros, lazyCompilation)
924 | {
925 | if (!compilationSuccessful()) return; // failed compilation
926 | ID3D11Device* device = g_dx11Device->getDevice();
927 | HRESULT hr = device->CreateHullShader(mShaderBuffer->GetBufferPointer(), mShaderBuffer->GetBufferSize(), NULL, &mHullShader);
928 | ATLASSERT(hr == S_OK);
929 | mDirty = false;
930 | }
931 | HullShader::~HullShader()
932 | {
933 | resetComPtr(&mHullShader);
934 | }
935 | void HullShader::setShader(D3dRenderContext& context)
936 | {
937 | if (recompileShaderIfNeeded())
938 | {
939 | resetComPtr(&mHullShader);
940 | ID3D11Device* device = g_dx11Device->getDevice();
941 | HRESULT hr = device->CreateHullShader(mShaderBuffer->GetBufferPointer(), mShaderBuffer->GetBufferSize(), NULL, &mHullShader);
942 | ATLASSERT(hr == S_OK);
943 | }
944 | context.HSSetShader(mHullShader, nullptr, 0);
945 | }
946 |
947 | DomainShader::DomainShader(const TCHAR* filename, const char* entryFunction, const Macros* macros, bool lazyCompilation)
948 | : ShaderBase(filename, entryFunction, "ds_5_0", macros, lazyCompilation)
949 | {
950 | if (!compilationSuccessful()) return; // failed compilation
951 | ID3D11Device* device = g_dx11Device->getDevice();
952 | HRESULT hr = device->CreateDomainShader(mShaderBuffer->GetBufferPointer(), mShaderBuffer->GetBufferSize(), NULL, &mDomainShader);
953 | ATLASSERT(hr == S_OK);
954 | mDirty = false;
955 | }
956 | DomainShader::~DomainShader()
957 | {
958 | resetComPtr(&mDomainShader);
959 | }
960 | void DomainShader::setShader(D3dRenderContext& context)
961 | {
962 | if (recompileShaderIfNeeded())
963 | {
964 | resetComPtr(&mDomainShader);
965 | ID3D11Device* device = g_dx11Device->getDevice();
966 | HRESULT hr = device->CreateDomainShader(mShaderBuffer->GetBufferPointer(), mShaderBuffer->GetBufferSize(), NULL, &mDomainShader);
967 | ATLASSERT(hr == S_OK);
968 | }
969 | context.DSSetShader(mDomainShader, nullptr, 0);
970 | }
971 |
972 | GeometryShader::GeometryShader(const TCHAR* filename, const char* entryFunction, const Macros* macros, bool lazyCompilation)
973 | : ShaderBase(filename, entryFunction, "gs_5_0", macros, lazyCompilation)
974 | {
975 | if (!compilationSuccessful()) return; // failed compilation
976 | ID3D11Device* device = g_dx11Device->getDevice();
977 | HRESULT hr = device->CreateGeometryShader(mShaderBuffer->GetBufferPointer(), mShaderBuffer->GetBufferSize(), NULL, &mGeometryShader);
978 | ATLASSERT(hr == S_OK);
979 | mDirty = false;
980 | }
981 | GeometryShader::~GeometryShader()
982 | {
983 | resetComPtr(&mGeometryShader);
984 | }
985 | void GeometryShader::setShader(D3dRenderContext& context)
986 | {
987 | if (recompileShaderIfNeeded())
988 | {
989 | resetComPtr(&mGeometryShader);
990 | ID3D11Device* device = g_dx11Device->getDevice();
991 | HRESULT hr = device->CreateGeometryShader(mShaderBuffer->GetBufferPointer(), mShaderBuffer->GetBufferSize(), NULL, &mGeometryShader);
992 | ATLASSERT(hr == S_OK);
993 | }
994 | context.GSSetShader(mGeometryShader, nullptr, 0);
995 | }
996 |
997 | ComputeShader::ComputeShader(const TCHAR* filename, const char* entryFunction, const Macros* macros, bool lazyCompilation)
998 | : ShaderBase(filename, entryFunction, "cs_5_0", macros, lazyCompilation)
999 | {
1000 | if (!compilationSuccessful()) return; // failed compilation
1001 | ID3D11Device* device = g_dx11Device->getDevice();
1002 | HRESULT hr = device->CreateComputeShader(mShaderBuffer->GetBufferPointer(), mShaderBuffer->GetBufferSize(), NULL, &mComputeShader);
1003 | ATLASSERT(hr == S_OK);
1004 | mDirty = false;
1005 | }
1006 | ComputeShader::~ComputeShader()
1007 | {
1008 | resetComPtr(&mComputeShader);
1009 | }
1010 | void ComputeShader::setShader(D3dRenderContext& context)
1011 | {
1012 | if (recompileShaderIfNeeded())
1013 | {
1014 | resetComPtr(&mComputeShader);
1015 | ID3D11Device* device = g_dx11Device->getDevice();
1016 | HRESULT hr = device->CreateComputeShader(mShaderBuffer->GetBufferPointer(), mShaderBuffer->GetBufferSize(), NULL, &mComputeShader);
1017 | ATLASSERT(hr == S_OK);
1018 | }
1019 | context.CSSetShader(mComputeShader, nullptr, 0);
1020 | }
1021 |
1022 |
1023 | ////////////////////////////////////////////////////////////////////////////////////////////////////
1024 | ////////////////////////////////////////////////////////////////////////////////////////////////////
1025 | ////////////////////////////////////////////////////////////////////////////////////////////////////
1026 |
1027 | // static members
1028 | DxGpuPerformance::GpuTimerMap DxGpuPerformance::mTimers;
1029 | int32 DxGpuPerformance::mMeasureTimerFrameId;
1030 | int32 DxGpuPerformance::mReadTimerFrameId;
1031 | int32 DxGpuPerformance::mLastReadTimerFrameId;
1032 |
1033 | DxGpuPerformance::DxGpuTimer DxGpuPerformance::mTimerArray[V_TIMER_MAX_COUNT];
1034 | int32 DxGpuPerformance::mAllocatedTimers;
1035 |
1036 | DxGpuPerformance::TimerGraphNode DxGpuPerformance::mTimerGraphNodeArray[V_GPU_TIMER_FRAMECOUNT][V_TIMER_MAX_COUNT];
1037 | int32 DxGpuPerformance::mAllocatedTimerGraphNodes[V_GPU_TIMER_FRAMECOUNT];
1038 |
1039 | DxGpuPerformance::GpuTimerGraph DxGpuPerformance::mTimerGraphs[V_GPU_TIMER_FRAMECOUNT];
1040 | DxGpuPerformance::TimerGraphNode* DxGpuPerformance::mCurrentTimeGraph = nullptr;
1041 |
1042 | void DxGpuPerformance::initialise()
1043 | {
1044 | mTimers.clear();
1045 | mAllocatedTimers = 0;
1046 |
1047 | mMeasureTimerFrameId = 0; // first frame
1048 | mReadTimerFrameId = -V_GPU_TIMER_FRAMECOUNT+1; // invalid
1049 | mLastReadTimerFrameId = -V_GPU_TIMER_FRAMECOUNT-1; // invalid
1050 | }
1051 | void DxGpuPerformance::shutdown()
1052 | {
1053 | for (int32 i = 0; i < mAllocatedTimers; ++i)
1054 | mTimerArray[i].release();
1055 | mTimers.clear();
1056 | }
1057 |
1058 | void DxGpuPerformance::startFrame()
1059 | {
1060 | // Clear the frame we are going to measure and append root timer node
1061 | for (int32 i = 0, cnt = mAllocatedTimerGraphNodes[mMeasureTimerFrameId]; i < cnt; ++i)
1062 | mTimerGraphNodeArray[mMeasureTimerFrameId][i].subGraph.clear();
1063 | mAllocatedTimerGraphNodes[mMeasureTimerFrameId] = 0; // reset the counter
1064 | TimerGraphNode* root = &mTimerGraphNodeArray [mMeasureTimerFrameId] [mAllocatedTimerGraphNodes[mMeasureTimerFrameId]++];
1065 | root->name = "root";
1066 | root->r = root->g = root->b = 127;
1067 | mTimerGraphs[mMeasureTimerFrameId].clear();
1068 |
1069 | mTimerGraphs[mMeasureTimerFrameId].push_back(root);
1070 | mCurrentTimeGraph = (*mTimerGraphs[mMeasureTimerFrameId].begin());
1071 | }
1072 |
1073 | void DxGpuPerformance::startGpuTimer(const char* name, unsigned char r, unsigned char g, unsigned char b)
1074 | {
1075 | GpuTimerMap::iterator it = mTimers.find(name);
1076 | DxGpuTimer* timer = nullptr;
1077 | if (it == mTimers.end())
1078 | {
1079 | // Allocate a timer and insert into the map
1080 | ATLASSERT(mAllocatedTimers<(V_TIMER_MAX_COUNT-1));
1081 | timer = &mTimerArray[mAllocatedTimers++];
1082 | mTimers[name] = timer;
1083 | timer->initialize();
1084 | }
1085 | else
1086 | {
1087 | ATLASSERT(!(*it).second->mUsedThisFrame); // a timer can only be used once a frame
1088 | timer = (*it).second;
1089 | }
1090 |
1091 | D3dRenderContext* context = g_dx11Device->getDeviceContext();
1092 | context->Begin(timer->mDisjointQueries[mMeasureTimerFrameId]);
1093 | context->End(timer->mBeginQueries[mMeasureTimerFrameId]);
1094 |
1095 | // Make sure we do not add the timer twice per frame
1096 | ATLASSERT(!timer->mUsedThisFrame);
1097 | timer->mUsedThisFrame = true;
1098 |
1099 | // Push the timer node we just started
1100 | ATLASSERT(mAllocatedTimerGraphNodes[mMeasureTimerFrameId]<(V_TIMER_MAX_COUNT - 1));
1101 | TimerGraphNode* node = &mTimerGraphNodeArray[mMeasureTimerFrameId][mAllocatedTimerGraphNodes[mMeasureTimerFrameId]++];
1102 | node->name = name;
1103 | node->r = float(r) / 255.0f;
1104 | node->g = float(g) / 255.0f;
1105 | node->b = float(b) / 255.0f;
1106 | node->timer = timer;
1107 | node->parent = mCurrentTimeGraph;
1108 | mCurrentTimeGraph->subGraph.push_back(node);
1109 | mCurrentTimeGraph = (*mCurrentTimeGraph->subGraph.rbegin());
1110 | timer->mNode[mMeasureTimerFrameId] = mCurrentTimeGraph;
1111 | // TO SOLVE: have static array of node
1112 | }
1113 |
1114 | void DxGpuPerformance::endGpuTimer(const char* name)
1115 | {
1116 | DxGpuTimer* timer = mTimers[name];
1117 |
1118 | D3dRenderContext* context = g_dx11Device->getDeviceContext();
1119 | context->End(timer->mDisjointQueries[mMeasureTimerFrameId]);
1120 | context->End(timer->mEndQueries[mMeasureTimerFrameId]);
1121 | timer->mEnded = true;
1122 |
1123 | // Pop to the parent of the timer node that has just ended
1124 | mCurrentTimeGraph = mCurrentTimeGraph->parent;
1125 | ATLASSERT(mCurrentTimeGraph!=nullptr);
1126 | }
1127 |
1128 | void DxGpuPerformance::endFrame()
1129 | {
1130 | // Fetch data from ready timer
1131 | if (mReadTimerFrameId >= 0)
1132 | {
1133 | int32 localReadTimerFrameId = mReadTimerFrameId%V_GPU_TIMER_FRAMECOUNT;
1134 |
1135 | D3dRenderContext* context = g_dx11Device->getDeviceContext();
1136 | DxGpuPerformance::GpuTimerMap::iterator it;
1137 |
1138 | // Get all the data first
1139 | for (it = mTimers.begin(); it != mTimers.end(); it++)
1140 | {
1141 | DxGpuPerformance::DxGpuTimer* timer = (*it).second;
1142 | if (!timer->mUsedThisFrame) // we should test usePreviousFrame but that will be enough for now
1143 | continue;
1144 | ATLASSERT(timer->mEnded); // the timer must have been ended this frame
1145 |
1146 | TimerGraphNode* node = timer->mNode[localReadTimerFrameId];
1147 | if (!node)
1148 | continue; // This can happen when a timer is registered later when some features are enabled.
1149 |
1150 | while (context->GetData(timer->mBeginQueries[localReadTimerFrameId], &node->mBeginTick, sizeof(UINT64), 0) != S_OK);
1151 | while (context->GetData(timer->mEndQueries[localReadTimerFrameId], &node->mEndTick, sizeof(UINT64), 0) != S_OK);
1152 | while (context->GetData(timer->mDisjointQueries[localReadTimerFrameId], &node->disjointData, sizeof(D3D11_QUERY_DATA_TIMESTAMP_DISJOINT), 0) != S_OK);
1153 | }
1154 |
1155 | // Get the begining of the frame measurement
1156 | UINT64 minBeginTime = 0xFFFFFFFFFFFFFFFF;
1157 | for (it = mTimers.begin(); it != mTimers.end(); it++)
1158 | {
1159 | DxGpuPerformance::DxGpuTimer* timer = (*it).second;
1160 | if (!timer->mUsedThisFrame) // we should test usePreviousFrame but that will be enough for now
1161 | continue;
1162 |
1163 | TimerGraphNode* node = timer->mNode[localReadTimerFrameId];
1164 | if (!node)
1165 | continue; // This can happen when a timer is registered later when some features are enabled.
1166 |
1167 | minBeginTime = min(minBeginTime, node->mBeginTick);
1168 | }
1169 |
1170 |
1171 | for (it = mTimers.begin(); it != mTimers.end(); it++)
1172 | {
1173 | DxGpuPerformance::DxGpuTimer* timer = (*it).second;
1174 |
1175 | if (!timer->mUsedThisFrame) // we should test usePreviousFrame but that will be enough for now
1176 | continue;
1177 |
1178 | // Reset the safety checks
1179 | timer->mUsedThisFrame = false;
1180 | timer->mEnded = false;
1181 |
1182 | TimerGraphNode* node = timer->mNode[localReadTimerFrameId];
1183 | if (!node)
1184 | continue; // This can happen when a timer is registered later when some features are enabled.
1185 |
1186 | float beginMs = 0.0f;
1187 | float endMs = 0.0f;
1188 | float lastDurationMs = 0.0f;
1189 | if (node->disjointData.Disjoint == FALSE)
1190 | {
1191 | float factor = 1000.0f / float(node->disjointData.Frequency);
1192 | beginMs = (node->mBeginTick - minBeginTime) * factor;
1193 | endMs = (node->mEndTick - minBeginTime) * factor;
1194 | lastDurationMs = (node->mEndTick - node->mBeginTick) * factor;
1195 | }
1196 | node->mBeginMs = beginMs;
1197 | node->mEndMs = endMs;
1198 | node->mLastDurationMs = lastDurationMs;
1199 | }
1200 | }
1201 | else
1202 | {
1203 | // At least reset timers safety checks
1204 | DxGpuPerformance::GpuTimerMap::iterator it;
1205 | for (it = mTimers.begin(); it != mTimers.end(); it++)
1206 | {
1207 | DxGpuPerformance::DxGpuTimer* timer = (*it).second;
1208 | timer->mUsedThisFrame = false;
1209 | timer->mEnded = false;
1210 | }
1211 | }
1212 |
1213 | // Move onto next frame
1214 | mReadTimerFrameId++;
1215 | mMeasureTimerFrameId = (mMeasureTimerFrameId + 1) % V_GPU_TIMER_FRAMECOUNT;
1216 | mLastReadTimerFrameId++;
1217 | }
1218 |
1219 | const DxGpuPerformance::TimerGraphNode* DxGpuPerformance::getLastUpdatedTimerGraphRootNode()
1220 | {
1221 | if (mLastReadTimerFrameId >= 0)
1222 | {
1223 | return *mTimerGraphs[mLastReadTimerFrameId%V_GPU_TIMER_FRAMECOUNT].begin();
1224 | }
1225 | return nullptr;
1226 | }
1227 |
1228 | DxGpuPerformance::DxGpuTimer::DxGpuTimer()
1229 | {
1230 | }
1231 |
1232 | DxGpuPerformance::DxGpuTimer::~DxGpuTimer()
1233 | {
1234 | }
1235 |
1236 | void DxGpuPerformance::DxGpuTimer::initialize()
1237 | {
1238 | ID3D11Device* device = g_dx11Device->getDevice();
1239 | D3D11_QUERY_DESC queryDesc;
1240 | queryDesc.Query = D3D11_QUERY_TIMESTAMP;
1241 | queryDesc.MiscFlags = 0;
1242 | D3D11_QUERY_DESC disjointQueryDesc;
1243 | disjointQueryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
1244 | disjointQueryDesc.MiscFlags = 0;
1245 | for (int32 i = 0; i < V_GPU_TIMER_FRAMECOUNT; ++i)
1246 | {
1247 | device->CreateQuery(&disjointQueryDesc, &mDisjointQueries[i]);
1248 | device->CreateQuery(&queryDesc, &mBeginQueries[i]);
1249 | device->CreateQuery(&queryDesc, &mEndQueries[i]);
1250 | }
1251 | }
1252 | void DxGpuPerformance::DxGpuTimer::release()
1253 | {
1254 | ID3D11Device* device = g_dx11Device->getDevice();
1255 | for (int32 i = 0; i < V_GPU_TIMER_FRAMECOUNT; ++i)
1256 | {
1257 | resetComPtr(&mDisjointQueries[i]);
1258 | resetComPtr(&mBeginQueries[i]);
1259 | resetComPtr(&mEndQueries[i]);
1260 | }
1261 | }
1262 |
1263 |
1264 | ////////////////////////////////////////////////////////////////////////////////////////////////////
1265 | ////////////////////////////////////////////////////////////////////////////////////////////////////
1266 | ////////////////////////////////////////////////////////////////////////////////////////////////////
1267 |
1268 |
1269 |
1270 | int32 divRoundUp(int32 numer, int32 denum)
1271 | {
1272 | return (numer + denum - 1) / denum;
1273 | }
1274 |
1275 |
1276 |
1277 | ////////////////////////////////////////////////////////////////////////////////////////////////////
1278 | ////////////////////////////////////////////////////////////////////////////////////////////////////
1279 | ////////////////////////////////////////////////////////////////////////////////////////////////////
1280 |
1281 |
1282 | //buffer, constant, view, render target and shader creation
1283 | // http://www.rastertek.com/dx11tut04.html
1284 | // https://msdn.microsoft.com/en-us/library/windows/desktop/dn508285(v=vs.85).aspx
1285 |
1286 |
1287 |
1288 |
1289 |
1290 |
1291 |
1292 |
1293 |
1294 |
--------------------------------------------------------------------------------
/DX11Base/Dx11Device.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #define DX_DEBUG_EVENT 1
4 | #define DX_DEBUG_RESOURCE_NAME 1
5 |
6 | // Windows and Dx11 includes
7 | #include