From 4c1c742d347907881aa56a0c47337d4eeb3a0a39 Mon Sep 17 00:00:00 2001 From: XProger Date: Thu, 18 Apr 2019 04:43:47 +0300 Subject: [PATCH] fix D3D11 shaders and samplers --- src/gapi/d3d11.h | 125 ++++++++++++++++++++------------ src/shaders/common.hlsl | 48 ++++++------ src/shaders/compose_entity.hlsl | 4 +- src/shaders/water_caustics.hlsl | 4 +- src/shaders/water_compose.hlsl | 2 +- src/shaders/water_rays.hlsl | 4 +- 6 files changed, 109 insertions(+), 78 deletions(-) diff --git a/src/gapi/d3d11.h b/src/gapi/d3d11.h index 683911d..bac6aed 100644 --- a/src/gapi/d3d11.h +++ b/src/gapi/d3d11.h @@ -52,6 +52,8 @@ void D3DCHECK(HRESULT res) { #define D3DCHECK(res) res #endif +#define MAX_SAMPLERS 5 + namespace GAPI { using namespace Core; @@ -73,6 +75,8 @@ namespace GAPI { ID3D11RasterizerState *RS[cmMAX]; // [cullMode] ID3D11DepthStencilState *DS[2][2]; // [depthTest][depthWrite] + ID3D11SamplerState *samplers[MAX_SAMPLERS]; + // Shader #include "shaders/d3d11/shaders.h" @@ -272,13 +276,12 @@ namespace GAPI { ID3D11ShaderResourceView *SRV; ID3D11RenderTargetView *RTV; ID3D11DepthStencilView *DSV; - ID3D11SamplerState *sampler; int width, height, depth, origWidth, origHeight, origDepth; TexFormat fmt; uint32 opt; - Texture(int width, int height, int depth, uint32 opt) : tex2D(NULL), tex3D(NULL), SRV(NULL), RTV(NULL), DSV(NULL), sampler(NULL), width(width), height(height), depth(depth), origWidth(width), origHeight(height), origDepth(depth), fmt(FMT_RGBA), opt(opt) {} + Texture(int width, int height, int depth, uint32 opt) : tex2D(NULL), tex3D(NULL), SRV(NULL), RTV(NULL), DSV(NULL), width(width), height(height), depth(depth), origWidth(width), origHeight(height), origDepth(depth), fmt(FMT_RGBA), opt(opt) {} void init(void *data) { ASSERT((opt & OPT_PROXY) == 0); @@ -389,8 +392,6 @@ namespace GAPI { } ASSERT(SRV); - - initSampler(); } void deinit() { @@ -399,48 +400,6 @@ namespace GAPI { SAFE_RELEASE(SRV); SAFE_RELEASE(RTV); SAFE_RELEASE(DSV); - SAFE_RELEASE(sampler); - } - - void initSampler() { - SAFE_RELEASE(sampler); - - D3D11_SAMPLER_DESC desc; - memset(&desc, 0, sizeof(desc)); - - bool mipmaps = (opt & OPT_MIPMAPS) != 0; - bool filter = (opt & OPT_NEAREST) == 0; - - if (mipmaps && (opt & (OPT_VOLUME | OPT_CUBEMAP | OPT_NEAREST)) == 0 && (Core::support.maxAniso > 0)) { - desc.MaxAnisotropy = min(int(Core::support.maxAniso), 8); - } else { - desc.MaxAnisotropy = 1; - } - - if (desc.MaxAnisotropy > 1) { - desc.Filter = D3D11_FILTER_ANISOTROPIC; - } else { - if (filter) { - desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - } else { - desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; - } - } - - if (fmt == FMT_SHADOW) { - desc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT; - desc.ComparisonFunc = D3D11_COMPARISON_LESS; - } else { - desc.ComparisonFunc = D3D11_COMPARISON_NEVER; - } - - desc.AddressU = - desc.AddressV = - desc.AddressW = (opt & OPT_REPEAT) ? D3D11_TEXTURE_ADDRESS_WRAP : D3D11_TEXTURE_ADDRESS_CLAMP; - - desc.MinLOD = 0; - desc.MaxLOD = D3D11_FLOAT32_MAX; - device->CreateSamplerState(&desc, &sampler); } void generateMipMap() { @@ -466,10 +425,8 @@ namespace GAPI { if (opt & OPT_VERTEX) { deviceContext->VSSetShaderResources(sampler, 1, &SRV); - deviceContext->VSSetSamplers(sampler, 1, &this->sampler); } deviceContext->PSSetShaderResources(sampler, 1, &SRV); - deviceContext->PSSetSamplers(sampler, 1, &this->sampler); } } @@ -562,6 +519,66 @@ namespace GAPI { } items[MAX_RENDER_BUFFERS]; } rtCache; + void deinitSamplers() { + for (int i = 0; i < COUNT(samplers); i++) { + SAFE_RELEASE(samplers[i]); + } + } + + ID3D11SamplerState* initSampler(bool filter, bool aniso, bool wrap, bool cmp) { + D3D11_SAMPLER_DESC desc; + memset(&desc, 0, sizeof(desc)); + + if (aniso && (Core::support.maxAniso > 0)) { + desc.MaxAnisotropy = min(int(Core::support.maxAniso), 8); + } else { + desc.MaxAnisotropy = 1; + } + + if (desc.MaxAnisotropy > 1) { + desc.Filter = D3D11_FILTER_ANISOTROPIC; + } else { + if (filter) { + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + } else { + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; + } + } + + if (cmp) { + desc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT; + desc.ComparisonFunc = D3D11_COMPARISON_LESS; + } else { + desc.ComparisonFunc = D3D11_COMPARISON_NEVER; + } + + desc.AddressU = + desc.AddressV = + desc.AddressW = wrap ? D3D11_TEXTURE_ADDRESS_WRAP : D3D11_TEXTURE_ADDRESS_CLAMP; + desc.MinLOD = 0; + desc.MaxLOD = D3D11_FLOAT32_MAX; + + ID3D11SamplerState *sampler; + device->CreateSamplerState(&desc, &sampler); + return sampler; + } + + void initSamplers() { + deinitSamplers(); + /* + 0 - smpDefault + 1 - smpPoint + 2 - smpPointWrap + 3 - smpLinear + 4 - smpCmp + */ + samplers[0] = initSampler(true, true, false, false); // TODO settings dependent + samplers[1] = initSampler(false, false, false, false); + samplers[2] = initSampler(false, false, true, false); + samplers[3] = initSampler(true, false, false, false); + samplers[4] = initSampler(true, false, false, true); + } + void init() { memset(&rtCache, 0, sizeof(rtCache)); @@ -628,6 +645,7 @@ namespace GAPI { #undef BLEND_FUNC } + // init raster state { D3D11_RASTERIZER_DESC desc; memset(&desc, 0, sizeof(desc)); @@ -641,6 +659,7 @@ namespace GAPI { device->CreateRasterizerState(&desc, &RS[cmFront]); } + // init depth stencil states { D3D11_DEPTH_STENCIL_DESC desc; memset(&desc, 0, sizeof(desc)); @@ -656,6 +675,10 @@ namespace GAPI { } } } + + // init samplers + memset(samplers, 0, sizeof(samplers)); + initSamplers(); } void resetDevice() { @@ -666,6 +689,9 @@ namespace GAPI { SAFE_RELEASE(rtCache.items[i].RTV); SAFE_RELEASE(rtCache.items[i].DSV); } + + deinitSamplers(); + rtCache.count = 0; } @@ -747,6 +773,9 @@ namespace GAPI { deviceContext->RSSetState(RS[cmNone]); depthTest = depthWrite = dirtyDepthState = true; colorWrite = dirtyBlendState = true; + + deviceContext->VSGetSamplers(0, COUNT(samplers), samplers); + deviceContext->PSGetSamplers(0, COUNT(samplers), samplers); } void cacheRenderTarget(ID3D11RenderTargetView **RTV, ID3D11DepthStencilView **DSV, int width, int height) { diff --git a/src/shaders/common.hlsl b/src/shaders/common.hlsl index d9cd411..e9bbf6c 100644 --- a/src/shaders/common.hlsl +++ b/src/shaders/common.hlsl @@ -37,11 +37,11 @@ struct VS_INPUT { }; #ifdef _GAPI_D3D11 - SamplerState smpDefault : register(s0); - SamplerState smpPoint : register(s1); - SamplerState smpLinear : register(s2); - SamplerState smpAniso : register(s3); - SamplerComparisonState smpCmp : register(s4); + SamplerState smpDefault : register(s0); + SamplerState smpPoint : register(s1); + SamplerState smpPointWrap : register(s2); + SamplerState smpLinear : register(s3); + SamplerComparisonState smpCmp : register(s4); Texture2D sDiffuse : register(t0); #ifdef NORMAL_AS_3D @@ -54,13 +54,14 @@ struct VS_INPUT { TextureCube sEnvironment : register(t4); Texture2D sMask : register(t5); - #define SAMPLE_2D (T,uv) T.Sample(smpDefault, uv) - #define SAMPLE_2D_POINT (T,uv) T.Sample(smpPoint, uv) - #define SAMPLE_2D_LINEAR (T,uv) T.Sample(smpLinear, uv) - #define SAMPLE_2D_ANISO (T,uv) T.Sample(smpAniso, uv) - #define SAMPLE_2D_CMP (T,uv) T.SampleCmp(smpCmp, uv.xy, uv.z) - #define SAMPLE_3D (T,uv) T.Sample(smpLinear, uv) - #define SAMPLE_CUBE (T,uv) T.Sample(smpLinear, uv) + #define SAMPLE_2D(T,uv) T.Sample(smpDefault, uv) + #define SAMPLE_2D_POINT(T,uv) T.Sample(smpPoint, uv) + #define SAMPLE_2D_POINT_WRAP(T,uv) T.Sample(smpPointWrap, uv) + #define SAMPLE_2D_LINEAR(T,uv) T.Sample(smpLinear, uv) + #define SAMPLE_2D_CMP(T,uv) T.SampleCmp(smpCmp, uv.xy, uv.z) + #define SAMPLE_2D_LOD0(T,uv) T.SampleLevel(smpLinear, uv, 0) + #define SAMPLE_3D(T,uv) T.Sample(smpLinear, uv) + #define SAMPLE_CUBE(T,uv) T.Sample(smpLinear, uv) #else sampler2D sDiffuse : register(s0); sampler2D sNormal : register(s1); @@ -69,13 +70,14 @@ struct VS_INPUT { samplerCUBE sEnvironment : register(s4); sampler2D sMask : register(s5); - #define SAMPLE_2D (T,uv) tex2D(T, uv) - #define SAMPLE_2D_POINT (T,uv) tex2D(T, uv) - #define SAMPLE_2D_LINEAR (T,uv) tex2D(T, uv) - #define SAMPLE_2D_ANISO (T,uv) tex2D(T, uv) - #define SAMPLE_2D_CMP (T,uv) ((tex2Dlod(T, uv.xy) => uv.z) ? 1 : 0) - #define SAMPLE_3D (T,uv) tex3D(T, uv) - #define SAMPLE_CUBE (T,uv) texCUBE(T, uv) + #define SAMPLE_2D(T,uv) tex2D(T, uv) + #define SAMPLE_2D_POINT(T,uv) tex2D(T, uv) + #define SAMPLE_2D_POINT_WRAP(T,uv) tex2D(T, uv) + #define SAMPLE_2D_LINEAR(T,uv) tex2D(T, uv) + #define SAMPLE_2D_LOD0(T,uv) tex2Dlod(T, float4(uv.xy, 0, 0)) + #define SAMPLE_2D_CMP(T,uv) ((tex2D(T, uv.xy) => uv.z) ? 1 : 0) + #define SAMPLE_3D(T,uv) tex3D(T, uv) + #define SAMPLE_CUBE(T,uv) texCUBE(T, uv) #endif float4 uParam : register( c0 ); @@ -143,9 +145,9 @@ float calcCausticsV(float3 coord) { return 0.5 + abs(sin(dot(coord.xyz, 1.0 / 1024.0) + uParam.x)) * 0.75; } -float3 calcNormalF(float2 tcR, float2 tcB, float base) { - float dx = SAMPLE_2D_LINEAR(sNormal, tcR).x - base; - float dz = SAMPLE_2D_LINEAR(sNormal, tcB).x - base; +float3 calcHeightMapNormal(float2 tcR, float2 tcB, float base) { + float dx = SAMPLE_2D_LOD0(sNormal, tcR).x - base; + float dz = SAMPLE_2D_LOD0(sNormal, tcB).x - base; return normalize( float3(dx, 64.0 / (1024.0 * 8.0), dz) ); } @@ -181,7 +183,7 @@ float SHADOW(float2 p) { #elif SHADOW_DEPTH return SAMPLE_2D_POINT(sShadow, float4(p, 0, 0)).x; #else - return unpack(SAMPLE_2D_POINT(sShadow, float4(p, 0, 0))); + return unpack(SAMPLE_2D_POINT(sShadow, p)); #endif } diff --git a/src/shaders/compose_entity.hlsl b/src/shaders/compose_entity.hlsl index 633e308..40aa4bc 100644 --- a/src/shaders/compose_entity.hlsl +++ b/src/shaders/compose_entity.hlsl @@ -43,7 +43,7 @@ VS_OUTPUT main(VS_INPUT In) { if (OPT_AMBIENT) { Out.ambient = calcAmbient(Out.normal.xyz); } else { - Out.ambient = min(uMaterial.yyy, In.aLight); + Out.ambient = min(uMaterial.yyy, In.aLight.xyz); } float4 lum, att, light; @@ -69,7 +69,7 @@ VS_OUTPUT main(VS_INPUT In) { Out.light.xyz += Out.ambient + uLightColor[0].xyz * light.x; } - Out.diffuse = float4(In.aColor * (uMaterial.x * 1.8), 1.0); + Out.diffuse = float4(In.aColor.xyz * (uMaterial.x * 1.8), 1.0); Out.diffuse *= uMaterial.w; diff --git a/src/shaders/water_caustics.hlsl b/src/shaders/water_caustics.hlsl index 34d70fd..ff0ab43 100644 --- a/src/shaders/water_caustics.hlsl +++ b/src/shaders/water_caustics.hlsl @@ -27,8 +27,8 @@ VS_OUTPUT main(VS_INPUT In) { float3 rCoord = float3(coord.x, coord.y, 0.0) * uPosScale[1].xzy; float2 uv = getInvUV(rCoord.xy, uTexParam).xy; - float2 info = SAMPLE_2D_LINEAR(sNormal, float4(uv, 0, 0)).xy; - float3 normal = calcNormalV(uv, info.x).xzy; + float2 info = SAMPLE_2D_LOD0(sNormal, uv).xy; + float3 normal = calcHeightMapNormal(float2(uv.x + uTexParam.x, uv.y), float2(uv.x, uv.y - uTexParam.y), info.x).xzy; float3 light = float3(0.0, 0.0, 1.0); float3 refOld = refract(-light, float3(0.0, 0.0, 1.0), 0.75); diff --git a/src/shaders/water_compose.hlsl b/src/shaders/water_compose.hlsl index b0a4310..1c8cb43 100644 --- a/src/shaders/water_compose.hlsl +++ b/src/shaders/water_compose.hlsl @@ -47,7 +47,7 @@ half4 main(VS_OUTPUT In) : COLOR0 { float3 viewVec = normalize(In.viewVec.xyz); float base = SAMPLE_2D_LINEAR(sNormal, In.texCoord).x; - float3 normal = calcNormalF(In.texCoordR, In.texCoordB, base); + float3 normal = calcHeightMapNormal(In.texCoordR, In.texCoordB, base); float2 dudv = mul(uViewProj, float4(normal.x, 0.0, normal.z, 0.0)).xy * uParam.z; float3 rv = reflect(-viewVec, normal); diff --git a/src/shaders/water_rays.hlsl b/src/shaders/water_rays.hlsl index 4008fc9..da95581 100644 --- a/src/shaders/water_rays.hlsl +++ b/src/shaders/water_rays.hlsl @@ -44,7 +44,7 @@ float4 main(VS_OUTPUT In/*, float2 pixelCoord: VPOS*/) : COLOR0 { float3 p0 = uViewPos.xyz - viewVec * t; float3 p1 = In.coord.xyz; - float dither = SAMPLE_2D_POINT(sMask, float4(pixelCoord * (1.0 / 8.0), 0.0, 0.0)).x; + float dither = SAMPLE_2D_POINT_WRAP(sMask, pixelCoord * (1.0 / 8.0)).x; float3 delta = (p1 - p0) / RAY_STEPS; float3 pos = p0 + delta * dither; @@ -53,7 +53,7 @@ float4 main(VS_OUTPUT In/*, float2 pixelCoord: VPOS*/) : COLOR0 { for (float i = 0.0; i < RAY_STEPS; i++) { float3 wpos = (pos - uPosScale[0].xyz) / uPosScale[1].xyz; float2 tc = wpos.xz * 0.5 + 0.5; - float light = SAMPLE_2D_LINEAR(sReflect, float4(tc, 0, 0)).x; + float light = SAMPLE_2D_LINEAR(sReflect, tc).x; sum += light * (1.0 - (clamp(wpos.y, -1.0, 1.0) * 0.5 + 0.5)); pos += delta; }