diff options
| author | Marco Foco <[email protected]> | 2016-03-07 15:47:07 +0100 |
|---|---|---|
| committer | Marco Foco <[email protected]> | 2016-03-08 16:04:19 +0100 |
| commit | cd6e0492903f8a9eb5efa14263d7d9ab092517de (patch) | |
| tree | 05c010b75bf777335565819dcceb140886c5a7e9 /samples/d3d11/shader.cpp | |
| download | faceworks-cd6e0492903f8a9eb5efa14263d7d9ab092517de.tar.xz faceworks-cd6e0492903f8a9eb5efa14263d7d9ab092517de.zip | |
FaceWorks 1.0
Diffstat (limited to 'samples/d3d11/shader.cpp')
| -rw-r--r-- | samples/d3d11/shader.cpp | 861 |
1 files changed, 861 insertions, 0 deletions
diff --git a/samples/d3d11/shader.cpp b/samples/d3d11/shader.cpp new file mode 100644 index 0000000..8ef262f --- /dev/null +++ b/samples/d3d11/shader.cpp @@ -0,0 +1,861 @@ +//---------------------------------------------------------------------------------- +// File: FaceWorks/samples/sample_d3d11/shader.cpp +// SDK Version: v1.0 +// Email: [email protected] +// Site: http://developer.nvidia.com/ +// +// Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//---------------------------------------------------------------------------------- + + +#include "shader.h" +#include "util.h" +#include "shaders/resources.h" + +#include <GFSDK_FaceWorks.h> + +// These headers are generated by the build process, and contain precompiled bytecode +// for all of the fixed shaders (not generated dynamically using feature flags) +#include "copy_ps.h" +#include "create_vsm_ps.h" +#include "curvature_vs.h" +#include "curvature_ps.h" +#include "gaussian_ps.h" +#include "hair_ps.h" +#include "screen_vs.h" +#include "shadow_vs.h" +#include "skybox_vs.h" +#include "skybox_ps.h" +#include "tess_vs.h" +#include "tess_hs.h" +#include "tess_ds.h" +#include "thickness_ps.h" +#include "world_vs.h" + + + +// Constant buffer size must be a multiple of 16 bytes +inline unsigned int align16(unsigned int size) +{ + return ((size + 15) / 16) * 16; +} + + + +// CShaderManager implementation + +CShaderManager g_shdmgr; + +CShaderManager::CShaderManager() +: m_pPsCopy(nullptr), + m_pPsCreateVSM(nullptr), + m_pVsCurvature(nullptr), + m_pPsCurvature(nullptr), + m_pPsThickness(nullptr), + m_pPsGaussian(nullptr), + m_pPsHair(nullptr), + m_pVsScreen(nullptr), + m_pVsShadow(nullptr), + m_pVsSkybox(nullptr), + m_pPsSkybox(nullptr), + m_pVsTess(nullptr), + m_pHsTess(nullptr), + m_pDsTess(nullptr), + m_pVsWorld(nullptr), + m_pSsPointClamp(nullptr), + m_pSsBilinearClamp(nullptr), + m_pSsTrilinearRepeat(nullptr), + m_pSsTrilinearRepeatAniso(nullptr), + m_pSsPCF(nullptr), + m_pInputLayout(nullptr), + m_pCbufDebug(nullptr), + m_pCbufFrame(nullptr), + m_pCbufShader(nullptr), + m_mapSkinFeaturesToShader(), + m_mapEyeFeaturesToShader() +{ +} + +HRESULT CShaderManager::Init(ID3D11Device * pDevice) +{ + HRESULT hr; + + // Initialize all the fixed shaders from bytecode + V_RETURN(pDevice->CreatePixelShader(copy_ps_bytecode, dim(copy_ps_bytecode), nullptr, &m_pPsCopy)); + V_RETURN(pDevice->CreatePixelShader(create_vsm_ps_bytecode, dim(create_vsm_ps_bytecode), nullptr, &m_pPsCreateVSM)); + V_RETURN(pDevice->CreateVertexShader(curvature_vs_bytecode, dim(curvature_vs_bytecode), nullptr, &m_pVsCurvature)); + V_RETURN(pDevice->CreatePixelShader(curvature_ps_bytecode, dim(curvature_ps_bytecode), nullptr, &m_pPsCurvature)); + V_RETURN(pDevice->CreatePixelShader(gaussian_ps_bytecode, dim(gaussian_ps_bytecode), nullptr, &m_pPsGaussian)); + V_RETURN(pDevice->CreatePixelShader(hair_ps_bytecode, dim(hair_ps_bytecode), nullptr, &m_pPsHair)); + V_RETURN(pDevice->CreateVertexShader(screen_vs_bytecode, dim(screen_vs_bytecode), nullptr, &m_pVsScreen)); + V_RETURN(pDevice->CreateVertexShader(shadow_vs_bytecode, dim(shadow_vs_bytecode), nullptr, &m_pVsShadow)); + V_RETURN(pDevice->CreateVertexShader(skybox_vs_bytecode, dim(skybox_vs_bytecode), nullptr, &m_pVsSkybox)); + V_RETURN(pDevice->CreatePixelShader(skybox_ps_bytecode, dim(skybox_ps_bytecode), nullptr, &m_pPsSkybox)); + V_RETURN(pDevice->CreateVertexShader(tess_vs_bytecode, dim(tess_vs_bytecode), nullptr, &m_pVsTess)); + V_RETURN(pDevice->CreateHullShader(tess_hs_bytecode, dim(tess_hs_bytecode), nullptr, &m_pHsTess)); + V_RETURN(pDevice->CreateDomainShader(tess_ds_bytecode, dim(tess_ds_bytecode), nullptr, &m_pDsTess)); + V_RETURN(pDevice->CreatePixelShader(thickness_ps_bytecode, dim(thickness_ps_bytecode), nullptr, &m_pPsThickness)); + V_RETURN(pDevice->CreateVertexShader(world_vs_bytecode, dim(world_vs_bytecode), nullptr, &m_pVsWorld)); + + // Initialize the sampler states + + D3D11_SAMPLER_DESC sampDesc = + { + D3D11_FILTER_MIN_MAG_MIP_POINT, + D3D11_TEXTURE_ADDRESS_CLAMP, + D3D11_TEXTURE_ADDRESS_CLAMP, + D3D11_TEXTURE_ADDRESS_CLAMP, + 0.0f, + 1, + D3D11_COMPARISON_FUNC(0), + { 0.0f, 0.0f, 0.0f, 0.0f }, + 0.0f, + FLT_MAX, + }; + V_RETURN(pDevice->CreateSamplerState(&sampDesc, &m_pSsPointClamp)); + + sampDesc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; + V_RETURN(pDevice->CreateSamplerState(&sampDesc, &m_pSsBilinearClamp)); + + sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + V_RETURN(pDevice->CreateSamplerState(&sampDesc, &m_pSsTrilinearRepeat)); + + sampDesc.Filter = D3D11_FILTER_ANISOTROPIC; + sampDesc.MaxAnisotropy = 16; + V_RETURN(pDevice->CreateSamplerState(&sampDesc, &m_pSsTrilinearRepeatAniso)); + + sampDesc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT; + sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_BORDER; + sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_BORDER; + sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_BORDER; + sampDesc.MaxAnisotropy = 1; + sampDesc.ComparisonFunc = D3D11_COMPARISON_LESS_EQUAL; + sampDesc.BorderColor[0] = 1.0f; + sampDesc.BorderColor[1] = 1.0f; + sampDesc.BorderColor[2] = 1.0f; + sampDesc.BorderColor[3] = 1.0f; + V_RETURN(pDevice->CreateSamplerState(&sampDesc, &m_pSsPCF)); + + // Initialize the input layout, and validate it against all the vertex shaders + + D3D11_INPUT_ELEMENT_DESC aInputDescs[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, UINT(offsetof(Vertex, m_pos)), D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, UINT(offsetof(Vertex, m_normal)), D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "UV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, UINT(offsetof(Vertex, m_uv)), D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, UINT(offsetof(Vertex, m_tangent)), D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "CURVATURE", 0, DXGI_FORMAT_R32_FLOAT, 0, UINT(offsetof(Vertex, m_curvature)), D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + V_RETURN(pDevice->CreateInputLayout( + aInputDescs, dim(aInputDescs), + curvature_vs_bytecode, dim(curvature_vs_bytecode), + &m_pInputLayout)); + + // Note: calling CreateInputLayout with nullptr for the 5th parameter will crash + // the VS2012 graphics debugger. Turn on this define if you need to graphics-debug. + // Bug filed with MS at https://connect.microsoft.com/VisualStudio/feedback/details/790030/ + // Supposed to be fixed in VS2013. +#define VS_GRAPHICS_DEBUG 0 +#if !VS_GRAPHICS_DEBUG + V_RETURN(pDevice->CreateInputLayout( + aInputDescs, dim(aInputDescs), + screen_vs_bytecode, dim(screen_vs_bytecode), + nullptr)); + V_RETURN(pDevice->CreateInputLayout( + aInputDescs, dim(aInputDescs), + shadow_vs_bytecode, dim(shadow_vs_bytecode), + nullptr)); + V_RETURN(pDevice->CreateInputLayout( + aInputDescs, dim(aInputDescs), + skybox_vs_bytecode, dim(skybox_vs_bytecode), + nullptr)); + V_RETURN(pDevice->CreateInputLayout( + aInputDescs, dim(aInputDescs), + tess_vs_bytecode, dim(tess_vs_bytecode), + nullptr)); + V_RETURN(pDevice->CreateInputLayout( + aInputDescs, dim(aInputDescs), + world_vs_bytecode, dim(world_vs_bytecode), + nullptr)); +#endif // !VS_GRAPHICS_DEBUG + + // Initialize the constant buffers + + D3D11_BUFFER_DESC bufDesc = + { + align16(sizeof(CbufDebug)), + D3D11_USAGE_DYNAMIC, + D3D11_BIND_CONSTANT_BUFFER, + D3D11_CPU_ACCESS_WRITE, + }; + + V_RETURN(pDevice->CreateBuffer(&bufDesc, nullptr, &m_pCbufDebug)); + + bufDesc.ByteWidth = align16(sizeof(CbufFrame)); + V_RETURN(pDevice->CreateBuffer(&bufDesc, nullptr, &m_pCbufFrame)); + + bufDesc.ByteWidth = align16(sizeof_field(Material, m_constants)); + V_RETURN(pDevice->CreateBuffer(&bufDesc, nullptr, &m_pCbufShader)); + + return S_OK; +} + +void CShaderManager::InitFrame( + ID3D11DeviceContext * pCtx, + const CbufDebug * pCbufDebug, + const CbufFrame * pCbufFrame, + ID3D11ShaderResourceView * pSrvCubeDiffuse, + ID3D11ShaderResourceView * pSrvCubeSpec, + ID3D11ShaderResourceView * pSrvCurvatureLUT, + ID3D11ShaderResourceView * pSrvShadowLUT) +{ + HRESULT hr; + + // Set all the samplers + pCtx->PSSetSamplers(SAMP_POINT_CLAMP, 1, &m_pSsPointClamp); + pCtx->PSSetSamplers(SAMP_BILINEAR_CLAMP, 1, &m_pSsBilinearClamp); + pCtx->PSSetSamplers(SAMP_TRILINEAR_REPEAT, 1, &m_pSsTrilinearRepeat); + pCtx->PSSetSamplers(SAMP_TRILINEAR_REPEAT_ANISO, 1, &m_pSsTrilinearRepeatAniso); + pCtx->PSSetSamplers(SAMP_PCF, 1, &m_pSsPCF); + + // Set the input assembler state + pCtx->IASetInputLayout(m_pInputLayout); + pCtx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + // Update the constant buffers + + D3D11_MAPPED_SUBRESOURCE map = {}; + V(pCtx->Map(m_pCbufDebug, 0, D3D11_MAP_WRITE_DISCARD, 0, &map)); + memcpy(map.pData, pCbufDebug, sizeof(CbufDebug)); + pCtx->Unmap(m_pCbufDebug, 0); + + V(pCtx->Map(m_pCbufFrame, 0, D3D11_MAP_WRITE_DISCARD, 0, &map)); + memcpy(map.pData, pCbufFrame, sizeof(CbufFrame)); + pCtx->Unmap(m_pCbufFrame, 0); + + // Set the constant buffers to all shader stages + pCtx->VSSetConstantBuffers(CB_DEBUG, 1, &m_pCbufDebug); + pCtx->HSSetConstantBuffers(CB_DEBUG, 1, &m_pCbufDebug); + pCtx->DSSetConstantBuffers(CB_DEBUG, 1, &m_pCbufDebug); + pCtx->PSSetConstantBuffers(CB_DEBUG, 1, &m_pCbufDebug); + pCtx->VSSetConstantBuffers(CB_FRAME, 1, &m_pCbufFrame); + pCtx->HSSetConstantBuffers(CB_FRAME, 1, &m_pCbufFrame); + pCtx->DSSetConstantBuffers(CB_FRAME, 1, &m_pCbufFrame); + pCtx->PSSetConstantBuffers(CB_FRAME, 1, &m_pCbufFrame); + pCtx->VSSetConstantBuffers(CB_SHADER, 1, &m_pCbufShader); + pCtx->HSSetConstantBuffers(CB_SHADER, 1, &m_pCbufShader); + pCtx->DSSetConstantBuffers(CB_SHADER, 1, &m_pCbufShader); + pCtx->PSSetConstantBuffers(CB_SHADER, 1, &m_pCbufShader); + + // Set the textures that are kept for the whole frame + pCtx->PSSetShaderResources(TEX_CUBE_DIFFUSE, 1, &pSrvCubeDiffuse); + pCtx->PSSetShaderResources(TEX_CUBE_SPEC, 1, &pSrvCubeSpec); + pCtx->PSSetShaderResources(TEX_CURVATURE_LUT, 1, &pSrvCurvatureLUT); + pCtx->PSSetShaderResources(TEX_SHADOW_LUT, 1, &pSrvShadowLUT); +} + +void CShaderManager::BindShadowTextures( + ID3D11DeviceContext * pCtx, + ID3D11ShaderResourceView * pSrvShadowMap, + ID3D11ShaderResourceView * pSrvVSM) +{ + pCtx->PSSetShaderResources(TEX_SHADOW_MAP, 1, &pSrvShadowMap); + pCtx->PSSetShaderResources(TEX_VSM, 1, &pSrvVSM); +} + + + +// Include helper class for D3DCompile API +struct IncludeHelper : public ID3DInclude +{ + virtual ~IncludeHelper() + { + } + + std::wstring m_dirsToTry[2]; + std::vector<std::vector<char> > m_openFiles; + + IncludeHelper() + { + // Get the path to the .exe is located + HMODULE hModule = GetModuleHandleW(nullptr); + wchar_t path[MAX_PATH]; + GetModuleFileNameW(hModule, path, MAX_PATH); + + // Trim off the .exe filename, leaving just the directory + wchar_t * pBasename = wcsrchr(path, L'\\'); + if (pBasename) + ++pBasename; + else + pBasename = path; + *pBasename = 0; + + // Assemble paths to try for includes, relative to the .exe directory + m_dirsToTry[0] = path; + m_dirsToTry[0] += L"..\\..\\d3d11\\shaders\\"; + m_dirsToTry[1] = path; + m_dirsToTry[1] += L"..\\..\\..\\include\\"; + } + + virtual HRESULT __stdcall Open( + D3D_INCLUDE_TYPE /*IncludeType*/, + LPCSTR pFileName, + LPCVOID /*pParentData*/, + LPCVOID * ppDataOut, + UINT * pBytesOut) override + { + assert(pFileName); + assert(ppDataOut); + assert(pBytesOut); + + m_openFiles.push_back(std::vector<char>()); + + // Try to find the include in each possible directory + for (int i = 0; i < dim(m_dirsToTry); ++i) + { + wchar_t path[MAX_PATH]; + swprintf_s(path, L"%s%hs", m_dirsToTry[i].c_str(), pFileName); + if (SUCCEEDED(LoadFile(path, &m_openFiles.back()))) + { + *ppDataOut = &m_openFiles.back()[0]; + *pBytesOut = UINT(m_openFiles.back().size()); + DebugPrintf(L"Loaded include file: %hs\n", pFileName); + return S_OK; + } + } + + m_openFiles.pop_back(); + + return E_FAIL; + } + + virtual HRESULT __stdcall Close(LPCVOID pData) override + { + assert(pData); + + for (int i = 0, n = int(m_openFiles.size()); i < n; ++i) + { + if (!m_openFiles[i].empty() && + pData == &m_openFiles[i][0]) + { + m_openFiles[i].clear(); + return S_OK; + } + } + + assert(false); + return E_FAIL; + } +}; + +bool CShaderManager::CompileShader( + ID3D11Device * pDevice, + const char * source, + ID3D11PixelShader ** ppPsOut) +{ + // Compile the source + + UINT flags = 0; +#if defined(_DEBUG) + flags |= D3DCOMPILE_SKIP_OPTIMIZATION | D3DCOMPILE_DEBUG | D3DCOMPILE_PREFER_FLOW_CONTROL; +#endif + + ID3DBlob * pBlobCode = nullptr; + ID3DBlob * pBlobErrors = nullptr; + + IncludeHelper includeHelper; + HRESULT hr = D3DCompile( + source, strlen(source), "generated_ps", + nullptr, &includeHelper, + "main", "ps_5_0", + flags, 0, + &pBlobCode, &pBlobErrors); + if (pBlobErrors) + { + MessageBoxA( + DXUTGetHWND(), + static_cast<char *>(pBlobErrors->GetBufferPointer()), + "Shader Compile Error", MB_OK); + if (pBlobCode) + pBlobCode->Release(); + pBlobErrors->Release(); + return false; + } + if (FAILED(hr) || !pBlobCode) + { + MessageBox( + DXUTGetHWND(), + L"Shader failed to compile, but no error messages were generated.", + L"Shader Compile Error", MB_OK); + if (pBlobCode) + pBlobCode->Release(); + return false; + } + + // Create the shader on the device + if (FAILED(pDevice->CreatePixelShader( + pBlobCode->GetBufferPointer(), pBlobCode->GetBufferSize(), + nullptr, ppPsOut))) + { + MessageBox( + DXUTGetHWND(), + L"Couldn't create pixel shader on device.", + L"Shader Compile Error", MB_OK); + pBlobCode->Release(); + return false; + } + + pBlobCode->Release(); + return true; +} + +void CShaderManager::CreateSkinShader(ID3D11Device * pDevice, SHDFEATURES features) +{ + DebugPrintf(L"Generating skin shader with feature mask %d\n", features); + + assert((features & SHDFEAT_PSMask) == features); + + // Create source code for the shader + char source[512]; + sprintf_s( + source, + "#include \"skin.hlsli\"\n" + "void main(\n" + " in Vertex i_vtx,\n" + " in float3 i_vecCamera : CAMERA,\n" + " in float4 i_uvzwShadow : UVZW_SHADOW,\n" + " out float3 o_rgbLit : SV_Target)\n" + "{\n" + " SkinMegashader(i_vtx, i_vecCamera, i_uvzwShadow, o_rgbLit, %s, %s);\n" + "}\n", + (features & SHDFEAT_SSS) ? "true" : "false", + (features & SHDFEAT_DeepScatter) ? "true" : "false" + ); + + // Compile it + ID3D11PixelShader * pPs = nullptr; + if (!CompileShader(pDevice, source, &pPs)) + return; + + // Store it in the map for future reference + assert(pPs); + m_mapSkinFeaturesToShader[features] = pPs; +} + +void CShaderManager::CreateEyeShader(ID3D11Device * pDevice, SHDFEATURES features) +{ + DebugPrintf(L"Generating eye shader with feature mask %d\n", features); + + assert((features & SHDFEAT_PSMask) == features); + + // Create source code for the shader + char source[512]; + sprintf_s( + source, + "#include \"eye.hlsli\"\n" + "void main(\n" + " in Vertex i_vtx,\n" + " in float3 i_vecCamera : CAMERA,\n" + " in float4 i_uvzwShadow : UVZW_SHADOW,\n" + " out float3 o_rgbLit : SV_Target)\n" + "{\n" + " EyeMegashader(i_vtx, i_vecCamera, i_uvzwShadow, o_rgbLit, %s, %s);\n" + "}\n", + (features & SHDFEAT_SSS) ? "true" : "false", + (features & SHDFEAT_DeepScatter) ? "true" : "false" + ); + + // Compile it + ID3D11PixelShader * pPs = nullptr; + if (!CompileShader(pDevice, source, &pPs)) + return; + + // Store it in the map for future reference + assert(pPs); + m_mapEyeFeaturesToShader[features] = pPs; +} + +ID3D11PixelShader * CShaderManager::GetSkinShader(ID3D11Device * pDevice, SHDFEATURES features) +{ + features &= SHDFEAT_PSMask; + + std::unordered_map<SHDFEATURES, ID3D11PixelShader *>::iterator i = + m_mapSkinFeaturesToShader.find(features); + + if (i != m_mapSkinFeaturesToShader.end()) + { + return i->second; + } + + CreateSkinShader(pDevice, features); + return m_mapSkinFeaturesToShader[features]; +} + +ID3D11PixelShader * CShaderManager::GetEyeShader(ID3D11Device * pDevice, SHDFEATURES features) +{ + features &= SHDFEAT_PSMask; + + std::unordered_map<SHDFEATURES, ID3D11PixelShader *>::iterator i = + m_mapEyeFeaturesToShader.find(features); + + if (i != m_mapEyeFeaturesToShader.end()) + { + return i->second; + } + + CreateEyeShader(pDevice, features); + return m_mapEyeFeaturesToShader[features]; +} + + + +void CShaderManager::BindCopy( + ID3D11DeviceContext * pCtx, + ID3D11ShaderResourceView * pSrvSrc, + const DirectX::XMFLOAT4X4 & matTransformColor) +{ + pCtx->VSSetShader(m_pVsScreen, nullptr, 0); + pCtx->PSSetShader(m_pPsCopy, nullptr, 0); + pCtx->PSSetShaderResources(TEX_SOURCE, 1, &pSrvSrc); + + // Update constant buffer + HRESULT hr; + D3D11_MAPPED_SUBRESOURCE map = {}; + V(pCtx->Map(m_pCbufShader, 0, D3D11_MAP_WRITE_DISCARD, 0, &map)); + memcpy(map.pData, &matTransformColor, sizeof(matTransformColor)); + pCtx->Unmap(m_pCbufShader, 0); +} + +void CShaderManager::BindCreateVSM( + ID3D11DeviceContext * pCtx, + ID3D11ShaderResourceView * pSrvSrc) +{ + pCtx->VSSetShader(m_pVsScreen, nullptr, 0); + pCtx->PSSetShader(m_pPsCreateVSM, nullptr, 0); + pCtx->PSSetShaderResources(TEX_SOURCE, 1, &pSrvSrc); +} + +void CShaderManager::BindCurvature( + ID3D11DeviceContext * pCtx, + float curvatureScale, + float curvatureBias) +{ + pCtx->VSSetShader(m_pVsCurvature, nullptr, 0); + pCtx->PSSetShader(m_pPsCurvature, nullptr, 0); + + // Update constant buffer + HRESULT hr; + D3D11_MAPPED_SUBRESOURCE map = {}; + V(pCtx->Map(m_pCbufShader, 0, D3D11_MAP_WRITE_DISCARD, 0, &map)); + static_cast<float *>(map.pData)[0] = curvatureScale; + static_cast<float *>(map.pData)[1] = curvatureBias; + pCtx->Unmap(m_pCbufShader, 0); +} + +void CShaderManager::BindThickness( + ID3D11DeviceContext * pCtx, + GFSDK_FaceWorks_CBData * pFaceWorksCBData) +{ + pCtx->VSSetShader(m_pVsWorld, nullptr, 0); + pCtx->PSSetShader(m_pPsThickness, nullptr, 0); + + // Update constant buffer + HRESULT hr; + D3D11_MAPPED_SUBRESOURCE map = {}; + V(pCtx->Map(m_pCbufShader, 0, D3D11_MAP_WRITE_DISCARD, 0, &map)); + memcpy(map.pData, pFaceWorksCBData, sizeof(GFSDK_FaceWorks_CBData)); + pCtx->Unmap(m_pCbufShader, 0); +} + +void CShaderManager::BindGaussian( + ID3D11DeviceContext * pCtx, + ID3D11ShaderResourceView * pSrvSrc, + float blurX, + float blurY) +{ + pCtx->VSSetShader(m_pVsScreen, nullptr, 0); + pCtx->PSSetShader(m_pPsGaussian, nullptr, 0); + pCtx->PSSetShaderResources(TEX_SOURCE, 1, &pSrvSrc); + + // Update constant buffer + HRESULT hr; + D3D11_MAPPED_SUBRESOURCE map = {}; + V(pCtx->Map(m_pCbufShader, 0, D3D11_MAP_WRITE_DISCARD, 0, &map)); + static_cast<float *>(map.pData)[0] = blurX; + static_cast<float *>(map.pData)[1] = blurY; + pCtx->Unmap(m_pCbufShader, 0); +} + +void CShaderManager::BindShadow( + ID3D11DeviceContext * pCtx, + const DirectX::XMFLOAT4X4 & matWorldToClipShadow) +{ + pCtx->VSSetShader(m_pVsShadow, nullptr, 0); + pCtx->PSSetShader(nullptr, nullptr, 0); + + // Update constant buffer + HRESULT hr; + D3D11_MAPPED_SUBRESOURCE map = {}; + V(pCtx->Map(m_pCbufShader, 0, D3D11_MAP_WRITE_DISCARD, 0, &map)); + memcpy(map.pData, &matWorldToClipShadow, sizeof(matWorldToClipShadow)); + pCtx->Unmap(m_pCbufShader, 0); +} + +void CShaderManager::BindSkybox( + ID3D11DeviceContext * pCtx, + ID3D11ShaderResourceView * pSrvSkybox, + const DirectX::XMFLOAT4X4 & matClipToWorldAxes) +{ + pCtx->VSSetShader(m_pVsSkybox, nullptr, 0); + pCtx->PSSetShader(m_pPsSkybox, nullptr, 0); + pCtx->PSSetShaderResources(TEX_SOURCE, 1, &pSrvSkybox); + + // Update constant buffer + HRESULT hr; + D3D11_MAPPED_SUBRESOURCE map = {}; + V(pCtx->Map(m_pCbufShader, 0, D3D11_MAP_WRITE_DISCARD, 0, &map)); + memcpy(map.pData, &matClipToWorldAxes, sizeof(matClipToWorldAxes)); + pCtx->Unmap(m_pCbufShader, 0); +} + +void CShaderManager::BindMaterial( + ID3D11DeviceContext * pCtx, + SHDFEATURES features, + const Material * pMtl) +{ + ID3D11Device * pDevice; + pCtx->GetDevice(&pDevice); + + // Determine which pixel shader to use + ID3D11PixelShader * pPs; + switch (pMtl->m_shader) + { + case SHADER_Skin: pPs = GetSkinShader(pDevice, features); break; + case SHADER_Eye: pPs = GetEyeShader(pDevice, features); break; + case SHADER_Hair: pPs = m_pPsHair; break; + default: + assert(false); + return; + } + + pDevice->Release(); + assert(pPs); + + pCtx->PSSetShader(pPs, nullptr, 0); + + // Determine which vertex/tess shaders to use + if (features & SHDFEAT_Tessellation) + { + pCtx->VSSetShader(m_pVsTess, nullptr, 0); + pCtx->HSSetShader(m_pHsTess, nullptr, 0); + pCtx->DSSetShader(m_pDsTess, nullptr, 0); + pCtx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST); + } + else + { + pCtx->VSSetShader(m_pVsWorld, nullptr, 0); + } + + // Bind textures + for (int i = 0; i < dim(pMtl->m_aSrv); ++i) + { + if (pMtl->m_aSrv[i]) + pCtx->PSSetShaderResources(pMtl->m_textureSlots[i], 1, &pMtl->m_aSrv[i]); + } + + // Update constant buffer + HRESULT hr; + D3D11_MAPPED_SUBRESOURCE map = {}; + V(pCtx->Map(m_pCbufShader, 0, D3D11_MAP_WRITE_DISCARD, 0, &map)); + memcpy(map.pData, pMtl->m_constants, sizeof(pMtl->m_constants)); + pCtx->Unmap(m_pCbufShader, 0); +} + +void CShaderManager::UnbindTess(ID3D11DeviceContext * pCtx) +{ + pCtx->HSSetShader(nullptr, nullptr, 0); + pCtx->DSSetShader(nullptr, nullptr, 0); + pCtx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); +} + + +void CShaderManager::DiscardRuntimeCompiledShaders() +{ + for (std::unordered_map<SHDFEATURES, ID3D11PixelShader *>::iterator + i = m_mapSkinFeaturesToShader.begin(), end = m_mapSkinFeaturesToShader.end(); + i != end; + ++i) + { + if (i->second) + i->second->Release(); + } + m_mapSkinFeaturesToShader.clear(); + + for (std::unordered_map<SHDFEATURES, ID3D11PixelShader *>::iterator + i = m_mapEyeFeaturesToShader.begin(), end = m_mapEyeFeaturesToShader.end(); + i != end; + ++i) + { + if (i->second) + i->second->Release(); + } + m_mapEyeFeaturesToShader.clear(); +} + +void CShaderManager::Release() +{ + if (m_pPsCopy) + { + m_pPsCopy->Release(); + m_pPsCopy = nullptr; + } + if (m_pPsCreateVSM) + { + m_pPsCreateVSM->Release(); + m_pPsCreateVSM = nullptr; + } + if (m_pVsCurvature) + { + m_pVsCurvature->Release(); + m_pVsCurvature = nullptr; + } + if (m_pPsCurvature) + { + m_pPsCurvature->Release(); + m_pPsCurvature = nullptr; + } + if (m_pPsThickness) + { + m_pPsThickness->Release(); + m_pPsThickness = nullptr; + } + if (m_pPsGaussian) + { + m_pPsGaussian->Release(); + m_pPsGaussian = nullptr; + } + if (m_pPsHair) + { + m_pPsHair->Release(); + m_pPsHair = nullptr; + } + if (m_pVsScreen) + { + m_pVsScreen->Release(); + m_pVsScreen = nullptr; + } + if (m_pVsShadow) + { + m_pVsShadow->Release(); + m_pVsShadow = nullptr; + } + if (m_pVsSkybox) + { + m_pVsSkybox->Release(); + m_pVsSkybox = nullptr; + } + if (m_pPsSkybox) + { + m_pPsSkybox->Release(); + m_pPsSkybox = nullptr; + } + if (m_pVsTess) + { + m_pVsTess->Release(); + m_pVsTess = nullptr; + } + if (m_pHsTess) + { + m_pHsTess->Release(); + m_pHsTess = nullptr; + } + if (m_pDsTess) + { + m_pDsTess->Release(); + m_pDsTess = nullptr; + } + if (m_pVsWorld) + { + m_pVsWorld->Release(); + m_pVsWorld = nullptr; + } + + if (m_pSsPointClamp) + { + m_pSsPointClamp->Release(); + m_pSsPointClamp = nullptr; + } + if (m_pSsBilinearClamp) + { + m_pSsBilinearClamp->Release(); + m_pSsBilinearClamp = nullptr; + } + if (m_pSsTrilinearRepeat) + { + m_pSsTrilinearRepeat->Release(); + m_pSsTrilinearRepeat = nullptr; + } + if (m_pSsTrilinearRepeatAniso) + { + m_pSsTrilinearRepeatAniso->Release(); + m_pSsTrilinearRepeatAniso = nullptr; + } + if (m_pSsPCF) + { + m_pSsPCF->Release(); + m_pSsPCF = nullptr; + } + + if (m_pInputLayout) + { + m_pInputLayout->Release(); + m_pInputLayout = nullptr; + } + + if (m_pCbufDebug) + { + m_pCbufDebug->Release(); + m_pCbufDebug = nullptr; + } + if (m_pCbufFrame) + { + m_pCbufFrame->Release(); + m_pCbufFrame = nullptr; + } + if (m_pCbufShader) + { + m_pCbufShader->Release(); + m_pCbufShader = nullptr; + } + + DiscardRuntimeCompiledShaders(); +} |