diff --git a/CodeWalker.Shaders/CodeWalker.Shaders.vcxproj b/CodeWalker.Shaders/CodeWalker.Shaders.vcxproj index 5dc55ff..2af5424 100644 --- a/CodeWalker.Shaders/CodeWalker.Shaders.vcxproj +++ b/CodeWalker.Shaders/CodeWalker.Shaders.vcxproj @@ -392,6 +392,16 @@ Pixel 4.0 + + Pixel + 4.1 + Pixel + 4.1 + Pixel + 4.1 + Pixel + 4.1 + Vertex 4.0 @@ -434,6 +444,16 @@ Vertex 4.0 + + Pixel + 4.1 + Pixel + 4.1 + Pixel + 4.1 + Pixel + 4.1 + Pixel 4.0 diff --git a/CodeWalker.Shaders/CodeWalker.Shaders.vcxproj.filters b/CodeWalker.Shaders/CodeWalker.Shaders.vcxproj.filters index 424bf17..b6bf4d5 100644 --- a/CodeWalker.Shaders/CodeWalker.Shaders.vcxproj.filters +++ b/CodeWalker.Shaders/CodeWalker.Shaders.vcxproj.filters @@ -262,6 +262,12 @@ Lights + + Lights + + + Lights + diff --git a/CodeWalker.Shaders/DirLightPS_MS.hlsl b/CodeWalker.Shaders/DirLightPS_MS.hlsl new file mode 100644 index 0000000..1beb390 --- /dev/null +++ b/CodeWalker.Shaders/DirLightPS_MS.hlsl @@ -0,0 +1,66 @@ +#include "LightPS.hlsli" + + +Texture2DMS DepthTex : register(t0); +Texture2DMS DiffuseTex : register(t2); +Texture2DMS NormalTex : register(t3); +Texture2DMS SpecularTex : register(t4); +Texture2DMS IrradianceTex : register(t5); + +struct VS_Output +{ + float4 Pos : SV_POSITION; + float4 Screen : TEXCOORD0; +}; + +PS_OUTPUT main(VS_Output input) +{ + + //switch (RenderMode) + //{ + // case 5: c += diffuse.rgb; break; + // case 6: c += normal.rgb; break; + // case 7: c += specular.rgb; break; + //} + + uint2 ssloc = uint2(input.Pos.xy); //pixel location + float2 spos = float2(input.Screen.xy / input.Screen.w); + float3 c = 0; + float d = 0; + float a = 0; + int sc = min(SampleCount, 8); + + [unroll] + for (int i = 0; i < sc; i++) + { + float depth = DepthTex.Load(ssloc, i); + if (depth == 0) continue; //no existing subpixel rendered here + + float4 diffuse = DiffuseTex.Load(ssloc, i); + float4 normal = NormalTex.Load(ssloc, i); + float4 specular = SpecularTex.Load(ssloc, i); + float4 irradiance = IrradianceTex.Load(ssloc, i); + + float4 cpos = mul(float4(spos, depth, 1), ViewProjInv); + float3 camRel = cpos.xyz * (1 / cpos.w); + float3 norm = normal.xyz * 2 - 1; + + float3 colour = DeferredDirectionalLight(camRel, norm, diffuse, specular, irradiance); + + c += colour; + d += depth; + a += 1; + } + + c *= SampleMult; + d *= SampleMult; + a *= SampleMult; + + if (d <= 0) discard; + + PS_OUTPUT output; + output.Colour = float4(c, a); + output.Depth = d; + return output; +} + diff --git a/CodeWalker.Shaders/LightPS.hlsli b/CodeWalker.Shaders/LightPS.hlsli index 1336438..7bb7002 100644 --- a/CodeWalker.Shaders/LightPS.hlsli +++ b/CodeWalker.Shaders/LightPS.hlsli @@ -18,8 +18,8 @@ cbuffer PSLightVars : register(b0) uint RenderSamplerCoord; uint LightType; //0=directional, 1=Point, 2=Spot, 4=Capsule uint IsLOD; //useful or not? - uint Pad0; - uint Pad1; + uint SampleCount;//for MSAA + float SampleMult;//for MSAA } diff --git a/CodeWalker.Shaders/LodLightsPS_MS.hlsl b/CodeWalker.Shaders/LodLightsPS_MS.hlsl new file mode 100644 index 0000000..cb7d0f8 --- /dev/null +++ b/CodeWalker.Shaders/LodLightsPS_MS.hlsl @@ -0,0 +1,53 @@ +#include "LightPS.hlsli" + + +Texture2DMS DepthTex : register(t0); +Texture2DMS DiffuseTex : register(t2); +Texture2DMS NormalTex : register(t3); +Texture2DMS SpecularTex : register(t4); +Texture2DMS IrradianceTex : register(t5); + +struct VS_Output +{ + float4 Pos : SV_POSITION; + float4 Screen : TEXCOORD0; + uint IID : SV_INSTANCEID; +}; + +float4 main(VS_Output input) : SV_TARGET +{ + uint2 ssloc = uint2(input.Pos.xy); //pixel location + float2 spos = float2(input.Screen.xy / input.Screen.w); + float4 c = 0; + float d = 0; + int sc = min(SampleCount, 8); + + [unroll] + for (int i = 0; i < sc; i++) + { + float depth = DepthTex.Load(ssloc, i); + if (depth == 0) continue; //no existing subpixel rendered here + + float4 diffuse = DiffuseTex.Load(ssloc, i); + float4 normal = NormalTex.Load(ssloc, i); + float4 specular = SpecularTex.Load(ssloc, i); + float4 irradiance = IrradianceTex.Load(ssloc, i); + + float4 cpos = mul(float4(spos, depth, 1), ViewProjInv); + float3 camRel = cpos.xyz * (1 / cpos.w); + float3 norm = normal.xyz * 2 - 1; + + float4 colour = DeferredLODLight(camRel, norm, diffuse, specular, irradiance, input.IID); + + c += colour; + d += depth; + } + + c *= SampleMult; + d *= SampleMult; + + if (d <= 0) discard; + + return c; +} + diff --git a/Rendering/DirectX/DXManager.cs b/Rendering/DirectX/DXManager.cs index bc099af..b3ca953 100644 --- a/Rendering/DirectX/DXManager.cs +++ b/Rendering/DirectX/DXManager.cs @@ -63,7 +63,7 @@ namespace CodeWalker.Rendering Usage = Usage.RenderTargetOutput }; - FeatureLevel[] levels = new FeatureLevel[] { FeatureLevel.Level_10_0 }; + FeatureLevel[] levels = new FeatureLevel[] { FeatureLevel.Level_11_0, FeatureLevel.Level_10_1, FeatureLevel.Level_10_0 }; DeviceCreationFlags flags = DeviceCreationFlags.None; //#if DEBUG diff --git a/Rendering/DirectX/DXUtility.cs b/Rendering/DirectX/DXUtility.cs index 0b4dec7..7480147 100644 --- a/Rendering/DirectX/DXUtility.cs +++ b/Rendering/DirectX/DXUtility.cs @@ -132,6 +132,10 @@ namespace CodeWalker.Rendering srvd.Texture3D.MipLevels = mipLevels; srvd.Texture3D.MostDetailedMip = mostDetailedMip; break; + case ShaderResourceViewDimension.Texture2DMultisampled: + case ShaderResourceViewDimension.Texture2DMultisampledArray: + //nothing to do here + break; default: throw new Exception(); //not implemented.... } diff --git a/Rendering/Shaders/DeferredScene.cs b/Rendering/Shaders/DeferredScene.cs index 48574ba..92b8b3e 100644 --- a/Rendering/Shaders/DeferredScene.cs +++ b/Rendering/Shaders/DeferredScene.cs @@ -37,8 +37,8 @@ namespace CodeWalker.Rendering public uint RenderSamplerCoord; //which texcoord to use in single texture mode public uint LightType; //0=directional, 1=Point, 2=Spot, 4=Capsule public uint IsLOD; //useful or not? - public uint Pad0; - public uint Pad1; + public uint SampleCount;//for MSAA + public float SampleMult;//for MSAA } public struct DeferredSSAAPSVars @@ -66,8 +66,10 @@ namespace CodeWalker.Rendering VertexShader DirLightVS; PixelShader DirLightPS; + PixelShader DirLightMSPS; VertexShader LodLightVS; PixelShader LodLightPS; + PixelShader LodLightMSPS; UnitCone LightCone; UnitSphere LightSphere; UnitCapsule LightCapsule; @@ -86,6 +88,11 @@ namespace CodeWalker.Rendering public int SSAASampleCount = 1; + public int MSAASampleCount = 4; + + + + public long VramUsage { get @@ -102,8 +109,10 @@ namespace CodeWalker.Rendering byte[] bDirLightVS = File.ReadAllBytes("Shaders\\DirLightVS.cso"); byte[] bDirLightPS = File.ReadAllBytes("Shaders\\DirLightPS.cso"); + byte[] bDirLightMSPS = File.ReadAllBytes("Shaders\\DirLightPS_MS.cso"); byte[] bLodLightVS = File.ReadAllBytes("Shaders\\LodLightsVS.cso"); byte[] bLodLightPS = File.ReadAllBytes("Shaders\\LodLightsPS.cso"); + byte[] bLodLightMSPS = File.ReadAllBytes("Shaders\\LodLightsPS_MS.cso"); byte[] bFinalVS = File.ReadAllBytes("Shaders\\PPFinalPassVS.cso"); byte[] bSSAAPS = File.ReadAllBytes("Shaders\\PPSSAAPS.cso"); @@ -111,6 +120,19 @@ namespace CodeWalker.Rendering DirLightPS = new PixelShader(device, bDirLightPS); LodLightVS = new VertexShader(device, bLodLightVS); LodLightPS = new PixelShader(device, bLodLightPS); + + try + { + //error could happen here if the device isn't supporting feature level 10.1 + DirLightMSPS = new PixelShader(device, bDirLightMSPS); + LodLightMSPS = new PixelShader(device, bLodLightMSPS); + } + catch + { + MSAASampleCount = 1; //can't do MSAA without at least 10.1 support + } + + LightCone = new UnitCone(device, bLodLightVS, 4, false); LightSphere = new UnitSphere(device, bLodLightVS, 4, true); LightCapsule = new UnitCapsule(device, bLodLightVS, 4, false); @@ -198,6 +220,11 @@ namespace CodeWalker.Rendering DirLightPS.Dispose(); DirLightPS = null; } + if (DirLightMSPS != null) + { + DirLightMSPS.Dispose(); + DirLightMSPS = null; + } if (DirLightVS != null) { DirLightVS.Dispose(); @@ -208,6 +235,11 @@ namespace CodeWalker.Rendering LodLightPS.Dispose(); LodLightPS = null; } + if (LodLightMSPS != null) + { + LodLightMSPS.Dispose(); + LodLightMSPS = null; + } if (LodLightVS != null) { LodLightVS.Dispose(); @@ -249,7 +281,7 @@ namespace CodeWalker.Rendering Viewport.Y = 0.0f; - GBuffers = new GpuMultiTexture(device, uw, uh, 4, Format.R8G8B8A8_UNorm, true, Format.D32_Float); + GBuffers = new GpuMultiTexture(device, uw, uh, 4, Format.R8G8B8A8_UNorm, true, Format.D32_Float, MSAASampleCount); WindowSizeVramUsage += GBuffers.VramUsage; SceneColour = new GpuTexture(device, uw, uh, Format.R32G32B32A32_Float, 1, 0, true, Format.D32_Float); @@ -293,18 +325,18 @@ namespace CodeWalker.Rendering public void RenderLights(DeviceContext context, Camera camera, Shadowmap globalShadows, ShaderGlobalLights globalLights) { - uint rendermode = 0; - uint rendermodeind = 1; //first full-screen directional light pass, for sun/moon //discard pixels where scene depth is 0, since nothing was rendered there //blend mode: overwrite - context.VertexShader.Set(DirLightVS); - context.PixelShader.Set(DirLightPS); + var ps = (MSAASampleCount > 1) ? DirLightMSPS : DirLightPS; - LightVSVars.Vars.ViewProj = Matrix.Identity; //Matrix.Transpose(camera.ViewProjMatrix); - LightVSVars.Vars.CameraPos = Vector4.Zero; //new Vector4(camera.Position, 0.0f); + context.VertexShader.Set(DirLightVS); + context.PixelShader.Set(ps); + + LightVSVars.Vars.ViewProj = Matrix.Identity; + LightVSVars.Vars.CameraPos = Vector4.Zero; LightVSVars.Vars.LightType = 0; LightVSVars.Vars.IsLOD = 0; LightVSVars.Vars.Pad0 = 0; @@ -314,15 +346,15 @@ namespace CodeWalker.Rendering LightPSVars.Vars.GlobalLights = globalLights.Params; LightPSVars.Vars.ViewProjInv = Matrix.Transpose(camera.ViewProjInvMatrix); - LightPSVars.Vars.CameraPos = Vector4.Zero; //new Vector4(camera.Position, 0.0f); + LightPSVars.Vars.CameraPos = Vector4.Zero; LightPSVars.Vars.EnableShadows = (globalShadows != null) ? 1u : 0u; - LightPSVars.Vars.RenderMode = rendermode; - LightPSVars.Vars.RenderModeIndex = rendermodeind; - LightPSVars.Vars.RenderSamplerCoord = 0;// (uint)RenderTextureSamplerCoord; + LightPSVars.Vars.RenderMode = 0; + LightPSVars.Vars.RenderModeIndex = 1; + LightPSVars.Vars.RenderSamplerCoord = 0; LightPSVars.Vars.LightType = 0; LightPSVars.Vars.IsLOD = 0; - LightPSVars.Vars.Pad0 = 0; - LightPSVars.Vars.Pad1 = 0; + LightPSVars.Vars.SampleCount = (uint)MSAASampleCount; + LightPSVars.Vars.SampleMult = 1.0f / MSAASampleCount; LightPSVars.Update(context); LightPSVars.SetPSCBuffer(context, 0); @@ -350,9 +382,10 @@ namespace CodeWalker.Rendering //instanced rendering of all other lights, using appropriate shapes //blend mode: additive + var ps = (MSAASampleCount > 1) ? LodLightMSPS : LodLightPS; context.VertexShader.Set(LodLightVS); - context.PixelShader.Set(LodLightPS); + context.PixelShader.Set(ps); LightVSVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix); LightVSVars.Vars.CameraPos = new Vector4(camera.Position, 0.0f); @@ -361,26 +394,20 @@ namespace CodeWalker.Rendering LightVSVars.Vars.Pad0 = 0; LightVSVars.Vars.Pad1 = 0; - //LightPSVars.Vars.GlobalLights = globalLights.Params; LightPSVars.Vars.ViewProjInv = Matrix.Transpose(camera.ViewProjInvMatrix); LightPSVars.Vars.CameraPos = new Vector4(camera.Position, 0.0f); - LightPSVars.Vars.EnableShadows = 0;// (globalShadows != null) ? 1u : 0u; - LightPSVars.Vars.RenderMode = 0;// rendermode; - LightPSVars.Vars.RenderModeIndex = 1;// rendermodeind; - LightPSVars.Vars.RenderSamplerCoord = 0;// (uint)RenderTextureSamplerCoord; + LightPSVars.Vars.EnableShadows = 0; + LightPSVars.Vars.RenderMode = 0; + LightPSVars.Vars.RenderModeIndex = 1; + LightPSVars.Vars.RenderSamplerCoord = 0; LightPSVars.Vars.LightType = 0; LightPSVars.Vars.IsLOD = 0; - LightPSVars.Vars.Pad0 = 0; - LightPSVars.Vars.Pad1 = 0; + LightPSVars.Vars.SampleCount = (uint)MSAASampleCount; + LightPSVars.Vars.SampleMult = 1.0f / MSAASampleCount; context.PixelShader.SetShaderResources(0, GBuffers.DepthSRV); context.PixelShader.SetShaderResources(2, GBuffers.SRVs); - //if (globalShadows != null) - //{ - // globalShadows.SetFinalRenderResources(context); - //} - foreach (var rll in lodlights) { @@ -427,10 +454,6 @@ namespace CodeWalker.Rendering context.PixelShader.Set(null); context.PixelShader.SetShaderResources(0, null, null, null); context.PixelShader.SetSamplers(0, null, null); - - - - } diff --git a/Rendering/Utils/GpuBuffers.cs b/Rendering/Utils/GpuBuffers.cs index d67cf32..6f3b462 100644 --- a/Rendering/Utils/GpuBuffers.cs +++ b/Rendering/Utils/GpuBuffers.cs @@ -293,13 +293,13 @@ namespace CodeWalker.Rendering TextureMS = DXUtility.CreateTexture2D(device, w, h, 1, 1, f, sc, sq, u, b, 0, 0); MSRTV = DXUtility.CreateRenderTargetView(device, TextureMS, f, rtvd, 0, 0, 0); - VramUsage += (wh * fs); + VramUsage += (wh * fs) * sc; if (depth) { DepthMS = DXUtility.CreateTexture2D(device, w, h, 1, 1, df, sc, sq, u, db, 0, 0); MSDSV = DXUtility.CreateDepthStencilView(device, DepthMS, df, dsvd); - VramUsage += (wh * DXUtility.ElementSize(df)); + VramUsage += (wh * DXUtility.ElementSize(df)) * sc; } } else @@ -432,31 +432,42 @@ namespace CodeWalker.Rendering public int VramUsage; public bool UseDepth; public int Count; + public bool Multisampled; + public int MultisampleCount; - public void Init(Device device, int w, int h, int count, Format f, bool depth, Format df) + public void Init(Device device, int w, int h, int count, Format f, bool depth, Format df, int multisamplecount) { Count = count; VramUsage = 0; UseDepth = depth; + MultisampleCount = multisamplecount; + Multisampled = (multisamplecount > 1); ResourceUsage u = ResourceUsage.Default; BindFlags b = BindFlags.RenderTarget | BindFlags.ShaderResource; - RenderTargetViewDimension rtvd = RenderTargetViewDimension.Texture2D; - ShaderResourceViewDimension srvd = ShaderResourceViewDimension.Texture2D;// D3D11_SRV_DIMENSION_TEXTURE2D; int fs = DXUtility.ElementSize(f); int wh = w * h; BindFlags db = BindFlags.DepthStencil | BindFlags.ShaderResource;// D3D11_BIND_DEPTH_STENCIL; + RenderTargetViewDimension rtvd = RenderTargetViewDimension.Texture2D; + ShaderResourceViewDimension srvd = ShaderResourceViewDimension.Texture2D;// D3D11_SRV_DIMENSION_TEXTURE2D; DepthStencilViewDimension dsvd = DepthStencilViewDimension.Texture2D; + if (Multisampled) + { + rtvd = RenderTargetViewDimension.Texture2DMultisampled; + srvd = ShaderResourceViewDimension.Texture2DMultisampled; + dsvd = DepthStencilViewDimension.Texture2DMultisampled; + } + Textures = new Texture2D[count]; RTVs = new RenderTargetView[count]; SRVs = new ShaderResourceView[count]; for (int i = 0; i < count; i++) { - Textures[i] = DXUtility.CreateTexture2D(device, w, h, 1, 1, f, 1, 0, u, b, 0, 0); + Textures[i] = DXUtility.CreateTexture2D(device, w, h, 1, 1, f, multisamplecount, 0, u, b, 0, 0); RTVs[i] = DXUtility.CreateRenderTargetView(device, Textures[i], f, rtvd, 0, 0, 0); SRVs[i] = DXUtility.CreateShaderResourceView(device, Textures[i], f, srvd, 1, 0, 0, 0); - VramUsage += (wh * fs); + VramUsage += (wh * fs) * multisamplecount; } if (depth) { @@ -482,10 +493,10 @@ namespace CodeWalker.Rendering break; } - Depth = DXUtility.CreateTexture2D(device, w, h, 1, 1, dtexf, 1, 0, u, db, 0, 0); + Depth = DXUtility.CreateTexture2D(device, w, h, 1, 1, dtexf, multisamplecount, 0, u, db, 0, 0); DSV = DXUtility.CreateDepthStencilView(device, Depth, df, dsvd); DepthSRV = DXUtility.CreateShaderResourceView(device, Depth, dsrvf, srvd, 1, 0, 0, 0); - VramUsage += (wh * DXUtility.ElementSize(df)); + VramUsage += (wh * DXUtility.ElementSize(df)) * multisamplecount; } } public void Dispose() @@ -516,13 +527,13 @@ namespace CodeWalker.Rendering Depth = null; } } - public GpuMultiTexture(Device device, int w, int h, int count, Format f, bool depth, Format df) + public GpuMultiTexture(Device device, int w, int h, int count, Format f, bool depth, Format df, int msc = 1) { - Init(device, w, h, count, f, depth, df); + Init(device, w, h, count, f, depth, df, msc); } - public GpuMultiTexture(Device device, int w, int h, int count, Format f) + public GpuMultiTexture(Device device, int w, int h, int count, Format f, int msc = 1) { - Init(device, w, h, count, f, false, Format.Unknown); + Init(device, w, h, count, f, false, Format.Unknown, msc); } public void Clear(DeviceContext context, Color4 colour) diff --git a/Shaders/DirLightPS.cso b/Shaders/DirLightPS.cso index ff652f9..4706947 100644 Binary files a/Shaders/DirLightPS.cso and b/Shaders/DirLightPS.cso differ diff --git a/Shaders/DirLightPS_MS.cso b/Shaders/DirLightPS_MS.cso new file mode 100644 index 0000000..240b300 Binary files /dev/null and b/Shaders/DirLightPS_MS.cso differ diff --git a/Shaders/LightPS.cso b/Shaders/LightPS.cso index 2a4eb4a..b92ff1a 100644 Binary files a/Shaders/LightPS.cso and b/Shaders/LightPS.cso differ diff --git a/Shaders/LodLightsPS.cso b/Shaders/LodLightsPS.cso index 905872e..b95822b 100644 Binary files a/Shaders/LodLightsPS.cso and b/Shaders/LodLightsPS.cso differ diff --git a/Shaders/LodLightsPS_MS.cso b/Shaders/LodLightsPS_MS.cso new file mode 100644 index 0000000..5e54009 Binary files /dev/null and b/Shaders/LodLightsPS_MS.cso differ