Hardware MSAA support for deferred render

This commit is contained in:
dexy 2019-12-04 20:14:11 +11:00
parent 152d439f89
commit f333e64812
14 changed files with 231 additions and 48 deletions

View File

@ -392,6 +392,16 @@
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Pixel</ShaderType>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">4.0</ShaderModel>
</FxCompile>
<FxCompile Include="DirLightPS_MS.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Pixel</ShaderType>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">4.1</ShaderModel>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Pixel</ShaderType>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">4.1</ShaderModel>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Pixel</ShaderType>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">4.1</ShaderModel>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Pixel</ShaderType>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">4.1</ShaderModel>
</FxCompile>
<FxCompile Include="DirLightVS.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Vertex</ShaderType>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">4.0</ShaderModel>
@ -434,6 +444,16 @@
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Vertex</ShaderType>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">4.0</ShaderModel>
</FxCompile>
<FxCompile Include="LodLightsPS_MS.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Pixel</ShaderType>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">4.1</ShaderModel>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Pixel</ShaderType>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">4.1</ShaderModel>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Pixel</ShaderType>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">4.1</ShaderModel>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Pixel</ShaderType>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">4.1</ShaderModel>
</FxCompile>
<FxCompile Include="LodLightsPS.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Pixel</ShaderType>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">4.0</ShaderModel>

View File

@ -262,6 +262,12 @@
<FxCompile Include="LodLightsPS.hlsl">
<Filter>Lights</Filter>
</FxCompile>
<FxCompile Include="DirLightPS_MS.hlsl">
<Filter>Lights</Filter>
</FxCompile>
<FxCompile Include="LodLightsPS_MS.hlsl">
<Filter>Lights</Filter>
</FxCompile>
</ItemGroup>
<ItemGroup>
<None Include="BasicPS.hlsli">

View File

@ -0,0 +1,66 @@
#include "LightPS.hlsli"
Texture2DMS<float> DepthTex : register(t0);
Texture2DMS<float4> DiffuseTex : register(t2);
Texture2DMS<float4> NormalTex : register(t3);
Texture2DMS<float4> SpecularTex : register(t4);
Texture2DMS<float4> 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;
}

View File

@ -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
}

View File

@ -0,0 +1,53 @@
#include "LightPS.hlsli"
Texture2DMS<float> DepthTex : register(t0);
Texture2DMS<float4> DiffuseTex : register(t2);
Texture2DMS<float4> NormalTex : register(t3);
Texture2DMS<float4> SpecularTex : register(t4);
Texture2DMS<float4> 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;
}

View File

@ -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

View File

@ -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....
}

View File

@ -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);
}

View File

@ -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)

Binary file not shown.

BIN
Shaders/DirLightPS_MS.cso Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Shaders/LodLightsPS_MS.cso Normal file

Binary file not shown.