├── teapot.xls ├── shaders ├── ps_black.hlsl ├── ps_copy.hlsl ├── vs_quad.hlsl ├── vs_raster_test.hlsl └── cs_raster.hlsl ├── README.md ├── ComputeRaster.vcxproj.filters ├── ComputeRaster.sln ├── .gitignore ├── ComputeRaster.vcxproj └── Compute_Raster.cpp /teapot.xls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbarczak/CSRasterization/HEAD/teapot.xls -------------------------------------------------------------------------------- /shaders/ps_black.hlsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | float4 main( ) : SV_Target 5 | { 6 | return float4(0,0,0,1); 7 | } -------------------------------------------------------------------------------- /shaders/ps_copy.hlsl: -------------------------------------------------------------------------------- 1 | 2 | Texture2D tx; 3 | 4 | float4 main( float4 vpos : SV_POSITION ) : SV_TARGET 5 | { 6 | return tx.Load(uint3(vpos.xy,0) ).xxxx; 7 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CSRasterization 2 | 3 | Demo of depth-only rasterizer implemented using sort-last rendering with compute shaders. You need my simpleton library (https://github.com/jbarczak/Simpleton) 4 | -------------------------------------------------------------------------------- /shaders/vs_quad.hlsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | void main( float4 p : POSITION, 4 | float2 uv : TEXCOORD0, 5 | out float4 vPos : SV_POSITION, 6 | out float2 vUV : TEXCOORD0 7 | ) 8 | { 9 | vPos = float4(p.xy,0.5,1); 10 | vUV = uv; 11 | } -------------------------------------------------------------------------------- /shaders/vs_raster_test.hlsl: -------------------------------------------------------------------------------- 1 | 2 | cbuffer cb0 3 | { 4 | row_major float4x4 mViewProj; 5 | } 6 | cbuffer cb1 7 | { 8 | row_major float4x4 mWorld; 9 | } 10 | 11 | float4 main( float4 p : POSITION ) : SV_Position 12 | { 13 | p = mul( p, mWorld ); 14 | return mul( p, mViewProj ); 15 | } -------------------------------------------------------------------------------- /ComputeRaster.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 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {fd1c7243-8b6b-44dd-8777-1df3fde9f313} 18 | 19 | 20 | 21 | 22 | Source Files 23 | 24 | 25 | 26 | 27 | Source Files 28 | 29 | 30 | Source Files 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | Source Files 40 | 41 | 42 | 43 | 44 | shader_headers 45 | 46 | 47 | shader_headers 48 | 49 | 50 | shader_headers 51 | 52 | 53 | shader_headers 54 | 55 | 56 | shader_headers 57 | 58 | 59 | -------------------------------------------------------------------------------- /ComputeRaster.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Express 2013 for Windows Desktop 4 | VisualStudioVersion = 12.0.21005.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ComputeRaster", "ComputeRaster.vcxproj", "{936F427B-5AD0-441E-BFA3-35FA532DB610}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {7D98EF05-AAEB-4A55-8425-28CBBCBE6754} = {7D98EF05-AAEB-4A55-8425-28CBBCBE6754} 9 | {D557A623-7946-446C-B7C9-A5927D850CFF} = {D557A623-7946-446C-B7C9-A5927D850CFF} 10 | EndProjectSection 11 | EndProject 12 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Simpleton", "..\..\Simpleton\build\msvc2013\Simpleton.vcxproj", "{7D98EF05-AAEB-4A55-8425-28CBBCBE6754}" 13 | EndProject 14 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpletonDX11", "..\..\Simpleton\build\msvc2013\SimpletonDX11.vcxproj", "{D557A623-7946-446C-B7C9-A5927D850CFF}" 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Win32 = Debug|Win32 19 | Debug|x64 = Debug|x64 20 | Release|Win32 = Release|Win32 21 | Release|x64 = Release|x64 22 | EndGlobalSection 23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 24 | {936F427B-5AD0-441E-BFA3-35FA532DB610}.Debug|Win32.ActiveCfg = Debug|Win32 25 | {936F427B-5AD0-441E-BFA3-35FA532DB610}.Debug|Win32.Build.0 = Debug|Win32 26 | {936F427B-5AD0-441E-BFA3-35FA532DB610}.Debug|x64.ActiveCfg = Debug|Win32 27 | {936F427B-5AD0-441E-BFA3-35FA532DB610}.Release|Win32.ActiveCfg = Release|Win32 28 | {936F427B-5AD0-441E-BFA3-35FA532DB610}.Release|Win32.Build.0 = Release|Win32 29 | {936F427B-5AD0-441E-BFA3-35FA532DB610}.Release|x64.ActiveCfg = Release|Win32 30 | {7D98EF05-AAEB-4A55-8425-28CBBCBE6754}.Debug|Win32.ActiveCfg = Debug|Win32 31 | {7D98EF05-AAEB-4A55-8425-28CBBCBE6754}.Debug|Win32.Build.0 = Debug|Win32 32 | {7D98EF05-AAEB-4A55-8425-28CBBCBE6754}.Debug|x64.ActiveCfg = Debug|x64 33 | {7D98EF05-AAEB-4A55-8425-28CBBCBE6754}.Debug|x64.Build.0 = Debug|x64 34 | {7D98EF05-AAEB-4A55-8425-28CBBCBE6754}.Release|Win32.ActiveCfg = Release|Win32 35 | {7D98EF05-AAEB-4A55-8425-28CBBCBE6754}.Release|Win32.Build.0 = Release|Win32 36 | {7D98EF05-AAEB-4A55-8425-28CBBCBE6754}.Release|x64.ActiveCfg = Release|x64 37 | {7D98EF05-AAEB-4A55-8425-28CBBCBE6754}.Release|x64.Build.0 = Release|x64 38 | {D557A623-7946-446C-B7C9-A5927D850CFF}.Debug|Win32.ActiveCfg = Debug|Win32 39 | {D557A623-7946-446C-B7C9-A5927D850CFF}.Debug|Win32.Build.0 = Debug|Win32 40 | {D557A623-7946-446C-B7C9-A5927D850CFF}.Debug|x64.ActiveCfg = Debug|x64 41 | {D557A623-7946-446C-B7C9-A5927D850CFF}.Debug|x64.Build.0 = Debug|x64 42 | {D557A623-7946-446C-B7C9-A5927D850CFF}.Release|Win32.ActiveCfg = Release|Win32 43 | {D557A623-7946-446C-B7C9-A5927D850CFF}.Release|Win32.Build.0 = Release|Win32 44 | {D557A623-7946-446C-B7C9-A5927D850CFF}.Release|x64.ActiveCfg = Release|x64 45 | {D557A623-7946-446C-B7C9-A5927D850CFF}.Release|x64.Build.0 = Release|x64 46 | EndGlobalSection 47 | GlobalSection(SolutionProperties) = preSolution 48 | HideSolutionNode = FALSE 49 | EndGlobalSection 50 | EndGlobal 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # Build results 11 | [Dd]ebug/ 12 | [Dd]ebugPublic/ 13 | [Rr]elease/ 14 | [Rr]eleases/ 15 | x64/ 16 | x86/ 17 | build/ 18 | bld/ 19 | [Bb]in/ 20 | [Oo]bj/ 21 | 22 | # Roslyn cache directories 23 | *.ide/ 24 | 25 | # MSTest test Results 26 | [Tt]est[Rr]esult*/ 27 | [Bb]uild[Ll]og.* 28 | 29 | #NUNIT 30 | *.VisualState.xml 31 | TestResult.xml 32 | 33 | # Build Results of an ATL Project 34 | [Dd]ebugPS/ 35 | [Rr]eleasePS/ 36 | dlldata.c 37 | 38 | *_i.c 39 | *_p.c 40 | *_i.h 41 | *.ilk 42 | *.meta 43 | *.obj 44 | *.pch 45 | *.pdb 46 | *.pgc 47 | *.pgd 48 | *.rsp 49 | *.sbr 50 | *.tlb 51 | *.tli 52 | *.tlh 53 | *.tmp 54 | *.tmp_proj 55 | *.log 56 | *.vspscc 57 | *.vssscc 58 | .builds 59 | *.pidb 60 | *.svclog 61 | *.scc 62 | 63 | # Chutzpah Test files 64 | _Chutzpah* 65 | 66 | # Visual C++ cache files 67 | ipch/ 68 | *.aps 69 | *.ncb 70 | *.opensdf 71 | *.sdf 72 | *.cachefile 73 | 74 | # Visual Studio profiler 75 | *.psess 76 | *.vsp 77 | *.vspx 78 | 79 | # TFS 2012 Local Workspace 80 | $tf/ 81 | 82 | # Guidance Automation Toolkit 83 | *.gpState 84 | 85 | # ReSharper is a .NET coding add-in 86 | _ReSharper*/ 87 | *.[Rr]e[Ss]harper 88 | *.DotSettings.user 89 | 90 | # JustCode is a .NET coding addin-in 91 | .JustCode 92 | 93 | # TeamCity is a build add-in 94 | _TeamCity* 95 | 96 | # DotCover is a Code Coverage Tool 97 | *.dotCover 98 | 99 | # NCrunch 100 | _NCrunch_* 101 | .*crunch*.local.xml 102 | 103 | # MightyMoose 104 | *.mm.* 105 | AutoTest.Net/ 106 | 107 | # Web workbench (sass) 108 | .sass-cache/ 109 | 110 | # Installshield output folder 111 | [Ee]xpress/ 112 | 113 | # DocProject is a documentation generator add-in 114 | DocProject/buildhelp/ 115 | DocProject/Help/*.HxT 116 | DocProject/Help/*.HxC 117 | DocProject/Help/*.hhc 118 | DocProject/Help/*.hhk 119 | DocProject/Help/*.hhp 120 | DocProject/Help/Html2 121 | DocProject/Help/html 122 | 123 | # Click-Once directory 124 | publish/ 125 | 126 | # Publish Web Output 127 | *.[Pp]ublish.xml 128 | *.azurePubxml 129 | # TODO: Comment the next line if you want to checkin your web deploy settings 130 | # but database connection strings (with potential passwords) will be unencrypted 131 | *.pubxml 132 | *.publishproj 133 | 134 | # NuGet Packages 135 | *.nupkg 136 | # The packages folder can be ignored because of Package Restore 137 | **/packages/* 138 | # except build/, which is used as an MSBuild target. 139 | !**/packages/build/ 140 | # If using the old MSBuild-Integrated Package Restore, uncomment this: 141 | #!**/packages/repositories.config 142 | 143 | # Windows Azure Build Output 144 | csx/ 145 | *.build.csdef 146 | 147 | # Windows Store app package directory 148 | AppPackages/ 149 | 150 | # Others 151 | sql/ 152 | *.Cache 153 | ClientBin/ 154 | [Ss]tyle[Cc]op.* 155 | ~$* 156 | *~ 157 | *.dbmdl 158 | *.dbproj.schemaview 159 | *.pfx 160 | *.publishsettings 161 | node_modules/ 162 | 163 | # RIA/Silverlight projects 164 | Generated_Code/ 165 | 166 | # Backup & report files from converting an old project file 167 | # to a newer Visual Studio version. Backup files are not needed, 168 | # because we have git ;-) 169 | _UpgradeReport_Files/ 170 | Backup*/ 171 | UpgradeLog*.XML 172 | UpgradeLog*.htm 173 | 174 | # SQL Server files 175 | *.mdf 176 | *.ldf 177 | 178 | # Business Intelligence projects 179 | *.rdl.data 180 | *.bim.layout 181 | *.bim_*.settings 182 | 183 | # Microsoft Fakes 184 | FakesAssemblies/ 185 | 186 | # ========================= 187 | # Operating System Files 188 | # ========================= 189 | 190 | # OSX 191 | # ========================= 192 | 193 | .DS_Store 194 | .AppleDouble 195 | .LSOverride 196 | 197 | # Thumbnails 198 | ._* 199 | 200 | # Files that might appear on external disk 201 | .Spotlight-V100 202 | .Trashes 203 | 204 | # Directories potentially created on remote AFP share 205 | .AppleDB 206 | .AppleDesktop 207 | Network Trash Folder 208 | Temporary Items 209 | .apdisk 210 | 211 | # Windows 212 | # ========================= 213 | 214 | # Windows image file caches 215 | Thumbs.db 216 | ehthumbs.db 217 | 218 | # Folder config file 219 | Desktop.ini 220 | 221 | # Recycle Bin used on file shares 222 | $RECYCLE.BIN/ 223 | 224 | # Windows Installer files 225 | *.cab 226 | *.msi 227 | *.msm 228 | *.msp 229 | 230 | # Windows shortcuts 231 | *.lnk 232 | 233 | #Auto-generated shader headers 234 | shader_headers/* 235 | 236 | # Blog files 237 | post.txt 238 | -------------------------------------------------------------------------------- /shaders/cs_raster.hlsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | #define THREADGROUP_WIDTH 160 // 1 SIMD16 thread per EU 4 | 5 | cbuffer globals 6 | { 7 | row_major float4x4 mViewProj; 8 | float2 g_vResolution; 9 | }; 10 | cbuffer drawcall 11 | { 12 | row_major float4x4 mWorld; 13 | uint g_nTriangles; 14 | }; 15 | 16 | // Public service announcement. Raw buffers are SIGNIFICANTLY more efficient than TBuffers 17 | // Buffer and friends. Because of stupid DX constraint that R32G32B32 views cannot be used on VB/IB 18 | // it is necessary to load single elements from these. 19 | // Using ByteAddressBuffer instead gives me a sizable boost because we can load multiple dwords at once 20 | 21 | ByteAddressBuffer g_Verts; 22 | ByteAddressBuffer g_Indices; 23 | 24 | RWTexture2D g_ZBuffer : register(u0); 25 | 26 | 27 | [numthreads(THREADGROUP_WIDTH,1,1)] 28 | void main( uint3 ThreadID : SV_DispatchThreadID, 29 | uint3 GroupID : SV_GroupID, 30 | uint3 GroupThreadID : SV_GroupThreadID ) 31 | { 32 | uint tid = ThreadID.x; 33 | 34 | [branch] 35 | if( tid < g_nTriangles ) 36 | { 37 | // fetch verts 38 | // NOTE: No Vertex re-use. Possible to add some? 39 | uint3 Indices = g_Indices.Load3( 12*tid ); 40 | float3 P0 = asfloat( g_Verts.Load3( 12*Indices.x ) ); 41 | float3 P1 = asfloat( g_Verts.Load3( 12*Indices.y ) ); 42 | float3 P2 = asfloat( g_Verts.Load3( 12*Indices.z ) ); 43 | 44 | // transform verts 45 | float3 P0w = mul( float4(P0,1), mWorld ).xyz; 46 | float3 P1w = mul( float4(P1,1), mWorld ).xyz; 47 | float3 P2w = mul( float4(P2,1), mWorld ).xyz; 48 | float4 P0p = mul( float4(P0w,1), mViewProj ); 49 | float4 P1p = mul( float4(P1w,1), mViewProj ); 50 | float4 P2p = mul( float4(P2w,1), mViewProj ); 51 | P0p.w = rcp(P0p.w); 52 | P1p.w = rcp(P1p.w); 53 | P2p.w = rcp(P2p.w); 54 | P0p.xyz *= P0p.w; 55 | P1p.xyz *= P1p.w; 56 | P2p.xyz *= P2p.w; 57 | 58 | // clip-space to viewport transform 59 | P0p.xy = g_vResolution*(float2(0.5,-0.5)*P0p.xy + float2(0.5,0.5)); 60 | P1p.xy = g_vResolution*(float2(0.5,-0.5)*P1p.xy + float2(0.5,0.5)); 61 | P2p.xy = g_vResolution*(float2(0.5,-0.5)*P2p.xy + float2(0.5,0.5)); 62 | 63 | // compute AABB 64 | float2 vBBMin = min(P0p.xy,min(P1p.xy,P2p.xy)); 65 | float2 vBBMax = max(P0p.xy,max(P1p.xy,P2p.xy)); 66 | 67 | // clip AABB to screen 68 | vBBMin = max(vBBMin.xy,0); 69 | vBBMax = min(vBBMax.xy,g_vResolution); 70 | 71 | // reject out-of-bounds triangles 72 | [branch] 73 | if( all(vBBMin < vBBMax) ) 74 | { 75 | // back-face test 76 | float2 v01 = P1p.xy-P0p.xy; 77 | float2 v20 = P0p.xy-P2p.xy; 78 | [branch] 79 | if( (v01.x*v20.y - v20.x*v01.y) < 0 ) 80 | { 81 | // Setup Edge functions 82 | float2 N01 = float2(-v01.y,v01.x); 83 | float2 N20 = float2(-v20.y,v20.x); 84 | float3 E01 = float3(N01.xy,-dot(N01,P0p.xy)); 85 | float3 E20 = float3(N20.xy,-dot(N20,P0p.xy)); 86 | E01 *= rcp(dot(E01,float3(P2p.xy,1))); 87 | E20 *= rcp(dot(E20,float3(P1p.xy,1))); 88 | 89 | // Setup interpolation functions for Z and 1/w 90 | float3 ZPlane = float3(P0p.z, P2p.z-P0p.z, P1p.z-P0p.z); 91 | float3 WPlane = float3(P0p.w, P2p.w-P0p.w, P1p.w-P0p.w); 92 | 93 | // Round AABB to pixels 94 | float2 TriMin = floor(vBBMin); 95 | float2 TriMax = ceil(vBBMax); 96 | 97 | // offset to pixel center 98 | TriMin += 0.5f; 99 | TriMax += 0.5f; 100 | 101 | // iterate pixels 102 | 103 | float2 vPos; 104 | for( vPos.y=TriMin.y; vPos.y < TriMax.y; vPos.y++ ) 105 | { 106 | for( vPos.x=TriMin.x; vPos.x < TriMax.x; vPos.x++ ) 107 | { 108 | // TODO: Incremental? 109 | float u = dot( float3(vPos,1), E01 ); 110 | float v = dot( float3(vPos,1), E20 ); 111 | [branch] 112 | if( u>=0 && v>=0 && (u+v)<=1 ) 113 | { 114 | // Interpolate depth 115 | float z = dot( float3(1,u,v),ZPlane ); 116 | float w = dot( float3(1,u,v),WPlane ); 117 | float depth = z/w; 118 | 119 | // Surprisingly, reading the Z-buffer first 120 | // and then skipping redundant Interlocked ops 121 | // results in a massive boost 122 | // 123 | // I'm not so sure whether this is due to depth complexity or 124 | // if we're somehow speeding up the atomics by ensuring 125 | // that the pixels are in cache first 126 | // 127 | uint zb = g_ZBuffer[uint2(vPos.xy)]; 128 | 129 | [branch] 130 | if( zb > asuint(depth) ) 131 | InterlockedMin(g_ZBuffer[uint2(vPos.xy)], asuint(depth) ); 132 | } 133 | } 134 | } 135 | } 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /ComputeRaster.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {936F427B-5AD0-441E-BFA3-35FA532DB610} 15 | ComputeRaster 16 | 17 | 18 | 19 | Application 20 | true 21 | v120 22 | MultiByte 23 | 24 | 25 | Application 26 | false 27 | v120 28 | true 29 | MultiByte 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | Level3 45 | Disabled 46 | true 47 | ../../Simpleton/include 48 | 49 | 50 | true 51 | d3dcompiler.lib;winmm.lib;d3d11.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) 52 | 53 | 54 | %(Filename) 55 | 56 | 57 | shader_headers/%(Filename).h 58 | false 59 | false 60 | 5.0 61 | 62 | 63 | 64 | 65 | Level3 66 | MaxSpeed 67 | true 68 | true 69 | true 70 | ../../Simpleton/include 71 | 72 | 73 | true 74 | true 75 | true 76 | d3d11.lib;winmm.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) 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | Compute 85 | 5.0 86 | Compute 87 | 5.0 88 | 89 | 90 | Pixel 91 | 92 | 93 | Pixel 94 | 5.0 95 | Pixel 96 | 5.0 97 | 98 | 99 | Vertex 100 | 5.0 101 | Vertex 102 | 5.0 103 | 104 | 105 | Vertex 106 | Vertex 107 | 5.0 108 | 109 | 110 | 111 | 112 | {7d98ef05-aaeb-4a55-8425-28cbbcbe6754} 113 | 114 | 115 | {d557a623-7946-446c-b7c9-a5927d850cff} 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /Compute_Raster.cpp: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #include "Simpleton.h" 3 | #include "PlyLoader.h" 4 | #include "DX11/SimpletonDX11.h" 5 | 6 | #include "shader_headers\vs_quad.h" 7 | #include "shader_headers\ps_copy.h" 8 | #include "shader_headers\ps_black.h" 9 | 10 | 11 | #include "shader_headers\vs_raster_test.h" 12 | 13 | #include "shader_headers\cs_raster.h" 14 | 15 | 16 | class CopyQuad 17 | { 18 | public: 19 | 20 | void Init( ID3D11Device* pDev, Simpleton::DX11PipelineStateBuilder& builder ) 21 | { 22 | m_ScreenQuad.InitXYQuad(pDev); 23 | builder.BeginState(pDev); 24 | builder.DisableZAndStencil(); 25 | builder.SetInputLayout( m_ScreenQuad.GetVertexElements(), m_ScreenQuad.GetVertexElementCount() ); 26 | builder.SetPixelShader( ps_copy, sizeof(ps_copy) ); 27 | builder.SetVertexShader( vs_quad, sizeof(vs_quad)); 28 | builder.EndState(&m_PSO); 29 | m_PSO.GetResourceSchema()->CreateResourceSet(&m_PSOResourceSet,pDev); 30 | } 31 | 32 | void Do( ID3D11RenderTargetView* pDest, ID3D11ShaderResourceView* pSrc, ID3D11DeviceContext* pCtx ) 33 | { 34 | pCtx->OMSetRenderTargets(1,&pDest,0); 35 | 36 | m_PSO.Apply(pCtx); 37 | m_PSOResourceSet.BeginUpdate(pCtx); 38 | m_PSOResourceSet.BindSRV( "tx", pSrc ); 39 | m_PSOResourceSet.EndUpdate(pCtx); 40 | m_PSOResourceSet.Apply(pCtx); 41 | m_ScreenQuad.Draw(pCtx); 42 | 43 | } 44 | 45 | private: 46 | 47 | Simpleton::DX11Mesh m_ScreenQuad; 48 | Simpleton::DX11PipelineState m_PSO; 49 | Simpleton::DX11PipelineResourceSet m_PSOResourceSet; 50 | 51 | }; 52 | 53 | class FakeZBuffer 54 | { 55 | public: 56 | 57 | void Init( size_t width, size_t height, ID3D11Device* pDev ) 58 | { 59 | D3D11_TEXTURE2D_DESC td; 60 | td.ArraySize = 1; 61 | td.BindFlags = D3D11_BIND_SHADER_RESOURCE|D3D11_BIND_UNORDERED_ACCESS|D3D11_BIND_RENDER_TARGET; 62 | td.CPUAccessFlags=0; 63 | td.Format = DXGI_FORMAT_R32_TYPELESS; 64 | td.Height = height; 65 | td.Width = width; 66 | td.MipLevels = 1; 67 | td.SampleDesc.Count=1; 68 | td.SampleDesc.Quality=0; 69 | td.MiscFlags=0; 70 | td.Usage = D3D11_USAGE_DEFAULT; 71 | 72 | pDev->CreateTexture2D( &td, 0,m_pFakeZBuffer.Address()); 73 | 74 | D3D11_SHADER_RESOURCE_VIEW_DESC srv; 75 | srv.Format = DXGI_FORMAT_R32_FLOAT; 76 | srv.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; 77 | srv.Texture2D.MipLevels=1; 78 | srv.Texture2D.MostDetailedMip=0; 79 | pDev->CreateShaderResourceView( m_pFakeZBuffer, &srv, m_pSRV.Address()); 80 | 81 | D3D11_UNORDERED_ACCESS_VIEW_DESC uav; 82 | uav.Format = DXGI_FORMAT_R32_UINT; 83 | uav.ViewDimension= D3D11_UAV_DIMENSION_TEXTURE2D; 84 | uav.Texture2D.MipSlice=0; 85 | pDev->CreateUnorderedAccessView( m_pFakeZBuffer, &uav, m_pUAV.Address()); 86 | 87 | D3D11_RENDER_TARGET_VIEW_DESC rtv; 88 | rtv.Format = DXGI_FORMAT_R32_FLOAT; 89 | rtv.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; 90 | rtv.Texture2D.MipSlice=0; 91 | pDev->CreateRenderTargetView( m_pFakeZBuffer, &rtv, m_pRTV.Address() ); 92 | } 93 | 94 | ID3D11ShaderResourceView* GetSRV() { return m_pSRV; } 95 | ID3D11UnorderedAccessView* GetUAV() { return m_pUAV; } 96 | ID3D11RenderTargetView* GetRTV() { return m_pRTV; } 97 | 98 | private: 99 | 100 | Simpleton::ComPtr m_pFakeZBuffer; 101 | Simpleton::ComPtr m_pUAV; 102 | Simpleton::ComPtr m_pSRV; 103 | Simpleton::ComPtr m_pRTV; 104 | }; 105 | 106 | #define ZOOM 2.0f 107 | #define Y_OFFS -0.5f 108 | 109 | class RasterTest : public Simpleton::DX11WindowController 110 | { 111 | public: 112 | 113 | Simpleton::DX11PipelineStateBuilder m_StateBuilder; 114 | Simpleton::DX11PipelineState m_PSO; 115 | Simpleton::DX11PipelineState m_WirePSO; 116 | Simpleton::DX11PipelineResourceSet m_PSOResourceSet; 117 | 118 | Simpleton::DX11ComputeKernel m_CSO; 119 | Simpleton::DX11ComputeResourceSet m_CSOResourceSet; 120 | 121 | 122 | Simpleton::DX11ShadowMap m_SMap; 123 | FakeZBuffer m_FakeZBuffer; 124 | 125 | CopyQuad m_CopyQuad; 126 | 127 | Simpleton::DX11Texture m_VB; 128 | Simpleton::DX11Texture m_IB; 129 | UINT m_nTriangles; 130 | bool m_bCompute; 131 | bool m_bWire; 132 | 133 | virtual bool OnCreate( Simpleton::DX11Window* pWin ) 134 | { 135 | m_bCompute = true; 136 | m_bWire = false; 137 | D3D11_INPUT_ELEMENT_DESC il[] = { 138 | {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0,0,D3D11_INPUT_PER_VERTEX_DATA, 0} 139 | }; 140 | 141 | ID3D11Device* pDevice = pWin->GetDevice(); 142 | m_StateBuilder.BeginState( pWin->GetDevice() ); 143 | m_StateBuilder.SetInputLayout( il, 1 ); 144 | m_StateBuilder.SetPixelShader( 0,0); 145 | m_StateBuilder.SetVertexShader( vs_raster_test, sizeof(vs_raster_test)); 146 | m_StateBuilder.EndState( &m_PSO ); 147 | m_PSO.GetResourceSchema()->CreateResourceSet( &m_PSOResourceSet, pWin->GetDevice() ); 148 | 149 | D3D11_RASTERIZER_DESC rs; 150 | rs.CullMode = D3D11_CULL_BACK; 151 | rs.AntialiasedLineEnable = false; 152 | rs.DepthBias = -1000; 153 | rs.DepthBiasClamp=0; 154 | rs.DepthClipEnable=0; 155 | rs.FillMode = D3D11_FILL_WIREFRAME; 156 | rs.FrontCounterClockwise = false; 157 | rs.MultisampleEnable = false; 158 | rs.ScissorEnable = false; 159 | rs.SlopeScaledDepthBias = 0; 160 | 161 | 162 | D3D11_DEPTH_STENCIL_DESC ds; 163 | memset(&ds,0,sizeof(ds)); 164 | ds.StencilEnable = false; 165 | ds.DepthFunc = D3D11_COMPARISON_LESS_EQUAL; 166 | ds.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; 167 | ds.DepthEnable= true; 168 | 169 | m_StateBuilder.BeginState( pWin->GetDevice() ); 170 | m_StateBuilder.SetInputLayout( il, 1 ); 171 | m_StateBuilder.SetPixelShader( ps_black, sizeof(ps_black)); 172 | m_StateBuilder.SetVertexShader( vs_raster_test, sizeof(vs_raster_test)); 173 | m_StateBuilder.SetRasterizerState(rs); 174 | m_StateBuilder.SetDepthStencilState(ds); 175 | m_StateBuilder.EndState( &m_WirePSO ); 176 | 177 | /* 178 | Simpleton::PlyMesh ply; 179 | if( !Simpleton::LoadPly( "dragon_vrip.ply", ply, Simpleton::PF_STANDARDIZE_POSITIONS | 180 | Simpleton::PF_IGNORE_UVS | 181 | Simpleton::PF_IGNORE_NORMALS | 182 | Simpleton::PF_IGNORE_COLORS ) ) 183 | { 184 | printf("DERP\n"); 185 | return false; 186 | } 187 | 188 | 189 | m_VB.InitRawBuffer( pWin->GetDevice(), ply.pPositions, ply.nVertices*3*sizeof(float), D3D11_BIND_VERTEX_BUFFER ); 190 | m_IB.InitRawBuffer( pWin->GetDevice(), ply.pVertexIndices, ply.nTriangles*3*sizeof(uint32), D3D11_BIND_INDEX_BUFFER ); 191 | 192 | m_nTriangles = ply.nTriangles; 193 | 194 | printf("%u tris. %.2f MB", ply.nTriangles, (sizeof(float)*3*ply.nVertices, sizeof(uint32)*3*ply.nTriangles)/(1024.0f*1024.0f) ); 195 | */ 196 | 197 | std::vector vb; 198 | std::vector ib; 199 | 200 | Simpleton::TessellateTeapot( 64, vb, ib ); 201 | 202 | 203 | // slice out all the stuff we dont need 204 | std::vector positions; 205 | positions.resize(vb.size()); 206 | Simpleton::Vec3f* pData = positions.data(); 207 | for( size_t i=0; iGetDevice(), positions.data(), positions.size()*3*sizeof(float), D3D11_BIND_VERTEX_BUFFER ); 218 | m_IB.InitRawBuffer( pWin->GetDevice(), ib.data(), ib.size()*sizeof(uint32), D3D11_BIND_INDEX_BUFFER ); 219 | m_nTriangles = ib.size()/3; 220 | 221 | printf("%u tris. %.2f MB. %ux%u(%u pixels)", m_nTriangles, (sizeof(float)*3*positions.size(), sizeof(uint32)*3*m_nTriangles)/(1024.0f*1024.0f), 222 | pWin->GetViewportWidth(), 223 | pWin->GetViewportHeight(), 224 | pWin->GetViewportHeight()*pWin->GetViewportWidth()); 225 | 226 | 227 | /* 228 | float vb[] = { 229 | -0.1,-0.05,0, 230 | 0,0.1,0, 231 | 0.1,0,0 232 | }; 233 | uint32 ib[3] = {0,1,2}; 234 | 235 | m_VB.InitRawBuffer( pWin->GetDevice(), vb, sizeof(vb), D3D11_BIND_VERTEX_BUFFER ); 236 | m_IB.InitRawBuffer( pWin->GetDevice(), ib, sizeof(ib), D3D11_BIND_INDEX_BUFFER ); 237 | m_nTriangles=1; 238 | 239 | */ 240 | 241 | 242 | m_CSO.Init( cs_raster, sizeof(cs_raster), pDevice ); 243 | m_CSO.GetResourceSchema()->CreateResourceSet( &m_CSOResourceSet, pDevice ); 244 | 245 | m_CopyQuad.Init(pWin->GetDevice(),m_StateBuilder); 246 | 247 | m_FakeZBuffer.Init( pWin->GetViewportWidth(), pWin->GetViewportHeight(), pWin->GetDevice() ); 248 | m_SMap.Init( pWin->GetViewportWidth(), pWin->GetViewportHeight(), 1, true, pWin->GetDevice() ); 249 | return true; 250 | } 251 | 252 | 253 | void DoRasterizer( Simpleton::DX11Window* pWin ) 254 | { 255 | 256 | float aspect = pWin->GetAspectRatio(); 257 | Simpleton::Matrix4f mProj = Simpleton::MatrixOrthoLH(ZOOM,ZOOM/aspect,1,10); 258 | Simpleton::Matrix4f mXLate = Simpleton::MatrixTranslate(0,Y_OFFS,5); 259 | m_PSOResourceSet.BeginUpdate(pWin->GetDeviceContext()); 260 | m_PSOResourceSet.BindConstant("mWorld",&mXLate, sizeof(mXLate)); 261 | m_PSOResourceSet.BindConstant("mViewProj",&mProj, sizeof(mProj)); 262 | m_PSOResourceSet.EndUpdate(pWin->GetDeviceContext()); 263 | 264 | 265 | ID3D11DeviceContext* pCtx = pWin->GetDeviceContext(); 266 | 267 | pCtx->ClearState(); 268 | 269 | auto pBackBuffer = pWin->GetBackbufferRTV(); 270 | auto pZBuffer = m_SMap.GetDSV(); 271 | 272 | 273 | pCtx->ClearDepthStencilView( pZBuffer, D3D11_CLEAR_DEPTH|D3D11_CLEAR_STENCIL, 1, 0 ); 274 | 275 | D3D11_VIEWPORT vp = pWin->BuildViewport(); 276 | D3D11_RECT scissor = pWin->BuildScissorRect(); 277 | 278 | 279 | pCtx->OMSetRenderTargets( 0,0, pZBuffer ); 280 | pCtx->RSSetViewports( 1, &vp); 281 | pCtx->RSSetScissorRects(1,&scissor); 282 | 283 | 284 | UINT stride=12; 285 | UINT offs=0; 286 | ID3D11Buffer* pBuff = (ID3D11Buffer*) m_VB.GetResource(); 287 | pCtx->IASetVertexBuffers( 0, 1, &pBuff, &stride, &offs ); 288 | pCtx->IASetIndexBuffer((ID3D11Buffer*)m_IB.GetResource(),DXGI_FORMAT_R32_UINT, 0 ); 289 | pCtx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); 290 | 291 | 292 | m_PSO.Apply( pWin->GetDeviceContext() ); 293 | m_PSOResourceSet.Apply(pCtx); 294 | pCtx->DrawIndexed( 3*m_nTriangles,0,0); 295 | 296 | m_CopyQuad.Do( pWin->GetBackbufferRTV(), m_SMap.GetSRV(), pWin->GetDeviceContext()); 297 | } 298 | 299 | void DrawWireFrame(Simpleton::DX11Window* pWin ) 300 | { 301 | auto pCtx = pWin->GetDeviceContext(); 302 | auto pBackBuffer = pWin->GetBackbufferRTV(); 303 | auto pZBuffer = pWin->GetBackbufferDSV(); 304 | 305 | 306 | pCtx->ClearState(); 307 | 308 | float aspect = pWin->GetAspectRatio(); 309 | Simpleton::Matrix4f mProj = Simpleton::MatrixOrthoLH(ZOOM,ZOOM/aspect,1,10); 310 | Simpleton::Matrix4f mXLate = Simpleton::MatrixTranslate(0,Y_OFFS,5); 311 | m_PSOResourceSet.BeginUpdate(pWin->GetDeviceContext()); 312 | m_PSOResourceSet.BindConstant("mWorld",&mXLate, sizeof(mXLate)); 313 | m_PSOResourceSet.BindConstant("mViewProj",&mProj, sizeof(mProj)); 314 | m_PSOResourceSet.EndUpdate(pWin->GetDeviceContext()); 315 | 316 | pCtx->ClearDepthStencilView( pZBuffer, D3D11_CLEAR_DEPTH, 1, 0 ); 317 | 318 | D3D11_VIEWPORT vp = pWin->BuildViewport(); 319 | D3D11_RECT scissor = pWin->BuildScissorRect(); 320 | 321 | pCtx->OMSetRenderTargets( 0,0, pZBuffer ); 322 | pCtx->RSSetViewports( 1, &vp); 323 | pCtx->RSSetScissorRects(1,&scissor); 324 | 325 | 326 | UINT stride=12; 327 | UINT offs=0; 328 | ID3D11Buffer* pBuff = (ID3D11Buffer*) m_VB.GetResource(); 329 | pCtx->IASetVertexBuffers( 0, 1, &pBuff, &stride, &offs ); 330 | pCtx->IASetIndexBuffer((ID3D11Buffer*)m_IB.GetResource(),DXGI_FORMAT_R32_UINT, 0 ); 331 | pCtx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); 332 | 333 | 334 | m_PSO.Apply( pWin->GetDeviceContext() ); 335 | m_PSOResourceSet.Apply(pCtx); 336 | pCtx->DrawIndexed( 3*m_nTriangles,0,0); 337 | 338 | 339 | pCtx->OMSetRenderTargets( 1,&pBackBuffer, pZBuffer ); 340 | m_WirePSO.Apply( pWin->GetDeviceContext() ); 341 | pCtx->DrawIndexed( 3*m_nTriangles,0,0); 342 | 343 | 344 | } 345 | 346 | 347 | 348 | 349 | void DoCompute( Simpleton::DX11Window* pWin ) 350 | { 351 | float aspect = pWin->GetAspectRatio(); 352 | Simpleton::Matrix4f mProj = Simpleton::MatrixOrthoLH(ZOOM,ZOOM/aspect,1,10); 353 | Simpleton::Matrix4f mXLate = Simpleton::MatrixTranslate(0,Y_OFFS,5); 354 | float Resolution[2] = { pWin->GetViewportWidth(), pWin->GetViewportHeight() }; 355 | 356 | pWin->GetDeviceContext()->ClearState(); 357 | 358 | m_CSOResourceSet.BeginUpdate(pWin->GetDeviceContext()); 359 | m_CSOResourceSet.BindConstant("mWorld", &mXLate, sizeof(mXLate)); 360 | m_CSOResourceSet.BindConstant("mViewProj",&mProj, sizeof(mProj) ); 361 | m_CSOResourceSet.BindConstant("g_vResolution", Resolution, sizeof(Resolution) ); 362 | m_CSOResourceSet.BindConstant("g_nTriangles", &m_nTriangles, sizeof(m_nTriangles) ); 363 | m_CSOResourceSet.BindSRV("g_Verts", m_VB.GetSRV()); 364 | m_CSOResourceSet.BindSRV("g_Indices", m_IB.GetSRV()); 365 | m_CSOResourceSet.EndUpdate(pWin->GetDeviceContext()); 366 | 367 | 368 | auto pUAV = m_FakeZBuffer.GetUAV(); 369 | ID3D11DeviceContext* pCtx = pWin->GetDeviceContext(); 370 | m_CSO.Bind(pCtx); 371 | m_CSOResourceSet.Apply(pCtx); 372 | pCtx->OMSetRenderTargets(0,0,0); 373 | 374 | pCtx->CSSetUnorderedAccessViews( 0,1,&pUAV, 0 ); 375 | 376 | // 3f800000 -> 1.0f DX11 makes me use hex here 377 | UINT ONE[] = {0x3f800000,0x3f800000,0x3f800000,0x3f800000}; 378 | pCtx->ClearUnorderedAccessViewUint(pUAV,ONE); 379 | 380 | DWORD size = m_CSO.GetThreadGroupDims()[0]; 381 | uint nGroups = m_nTriangles; 382 | if( nGroups%size ) 383 | nGroups += size-(nGroups%size); 384 | nGroups /= size; 385 | 386 | 387 | pCtx->Dispatch(nGroups,1,1); 388 | 389 | 390 | D3D11_VIEWPORT vp = pWin->BuildViewport(); 391 | D3D11_RECT scissor = pWin->BuildScissorRect(); 392 | pCtx->RSSetViewports( 1, &vp); 393 | pCtx->RSSetScissorRects(1,&scissor); 394 | ID3D11UnorderedAccessView* pNULLS[] = {0}; 395 | pCtx->CSSetUnorderedAccessViews(0,1,pNULLS,0); 396 | m_CopyQuad.Do( pWin->GetBackbufferRTV(), m_FakeZBuffer.GetSRV(), pWin->GetDeviceContext()); 397 | } 398 | 399 | 400 | virtual void OnFrame( Simpleton::DX11Window* pWin ) 401 | { 402 | if( !m_bCompute ) 403 | DoRasterizer(pWin); 404 | else 405 | DoCompute(pWin); 406 | 407 | if( m_bWire ) 408 | DrawWireFrame(pWin); 409 | } 410 | 411 | 412 | virtual void OnKeyUp( Simpleton::Window* pWindow, KeyCode eKey ) 413 | { 414 | if( eKey == KEY_SPACE ) 415 | m_bCompute = !m_bCompute; 416 | 417 | if( eKey == KEY_W ) 418 | m_bWire = !m_bWire; 419 | } 420 | 421 | }; 422 | 423 | 424 | 425 | int main() 426 | { 427 | RasterTest app; 428 | 429 | Simpleton::DX11Window* pWin = Simpleton::DX11Window::Create( 1600,900, Simpleton::DX11Window::FPS_TITLE | Simpleton::DX11Window::USE_DEBUG_LAYER, &app ); 430 | while( pWin->DoEvents() ) 431 | pWin->DoFrame(); 432 | 433 | return 0; 434 | } 435 | 436 | --------------------------------------------------------------------------------