diff --git a/Engine/source/gfx/D3D11/gfxD3D11Device.cpp b/Engine/source/gfx/D3D11/gfxD3D11Device.cpp index 352523f36..476fbac9d 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Device.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Device.cpp @@ -53,6 +53,127 @@ GFXDevice *GFXD3D11Device::createInstance(U32 adapterIndex) return dev; } +class GFXPCD3D11RegisterDevice +{ +public: + GFXPCD3D11RegisterDevice() + { + GFXInit::getRegisterDeviceSignal().notify(&GFXD3D11Device::enumerateAdapters); + } +}; + +static GFXPCD3D11RegisterDevice pPCD3D11RegisterDevice; + +//----------------------------------------------------------------------------- +/// Parse command line arguments for window creation +//----------------------------------------------------------------------------- +static void sgPCD3D11DeviceHandleCommandLine(S32 argc, const char **argv) +{ + // useful to pass parameters by command line for d3d (e.g. -dx9 -dx11) + for (U32 i = 1; i < argc; i++) + { + argv[i]; + } +} + +// Register the command line parsing hook +static ProcessRegisterCommandLine sgCommandLine(sgPCD3D11DeviceHandleCommandLine); + +GFXD3D11Device::GFXD3D11Device(U32 index) +{ + mDeviceSwizzle32 = &Swizzles::bgra; + GFXVertexColor::setSwizzle(mDeviceSwizzle32); + + mDeviceSwizzle24 = &Swizzles::bgr; + + mAdapterIndex = index; + mD3DDevice = NULL; + mVolatileVB = NULL; + + mCurrentPB = NULL; + mDynamicPB = NULL; + + mLastVertShader = NULL; + mLastPixShader = NULL; + + mCanCurrentlyRender = false; + mTextureManager = NULL; + mCurrentStateBlock = NULL; + mResourceListHead = NULL; + + mPixVersion = 0.0; + + mVertexShaderTarget = String::EmptyString; + mPixelShaderTarget = String::EmptyString; + + mDrawInstancesCount = 0; + + mCardProfiler = NULL; + + mDeviceDepthStencil = NULL; + mDeviceBackbuffer = NULL; + mDeviceBackBufferView = NULL; + mDeviceDepthStencilView = NULL; + + mCreateFenceType = -1; // Unknown, test on first allocate + + mCurrentConstBuffer = NULL; + + mOcclusionQuerySupported = false; + + mDebugLayers = false; + + for (U32 i = 0; i < GS_COUNT; ++i) + mModelViewProjSC[i] = NULL; + + // Set up the Enum translation tables + GFXD3D11EnumTranslate::init(); +} + +GFXD3D11Device::~GFXD3D11Device() +{ + // Release our refcount on the current stateblock object + mCurrentStateBlock = NULL; + + releaseDefaultPoolResources(); + + mD3DDeviceContext->ClearState(); + mD3DDeviceContext->Flush(); + + // Free the vertex declarations. + VertexDeclMap::Iterator iter = mVertexDecls.begin(); + for (; iter != mVertexDecls.end(); iter++) + delete iter->value; + + // Forcibly clean up the pools + mVolatileVBList.setSize(0); + mDynamicPB = NULL; + + // And release our D3D resources. + SAFE_RELEASE(mDeviceDepthStencilView); + SAFE_RELEASE(mDeviceBackBufferView); + SAFE_RELEASE(mDeviceDepthStencil); + SAFE_RELEASE(mDeviceBackbuffer); + SAFE_RELEASE(mD3DDeviceContext); + + SAFE_DELETE(mCardProfiler); + SAFE_DELETE(gScreenShot); + +#ifdef TORQUE_DEBUG + if (mDebugLayers) + { + ID3D11Debug *pDebug = NULL; + mD3DDevice->QueryInterface(IID_PPV_ARGS(&pDebug)); + AssertFatal(pDebug, "~GFXD3D11Device- Failed to get debug layer"); + pDebug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL); + SAFE_RELEASE(pDebug); + } +#endif + + SAFE_RELEASE(mSwapChain); + SAFE_RELEASE(mD3DDevice); +} + GFXFormat GFXD3D11Device::selectSupportedFormat(GFXTextureProfile *profile, const Vector &formats, bool texture, bool mustblend, bool mustfilter) { U32 features = 0; @@ -186,10 +307,47 @@ void GFXD3D11Device::enumerateAdapters(Vector &adapterList) toAdd->mAvailableModes.push_back(vmAdd); } + //Check adapater can handle feature level 10 + D3D_FEATURE_LEVEL deviceFeature; + ID3D11Device *pTmpDevice = nullptr; + // Create temp Direct3D11 device. + bool suitable = true; + UINT createDeviceFlags = D3D11_CREATE_DEVICE_SINGLETHREADED | D3D11_CREATE_DEVICE_BGRA_SUPPORT; + hr = D3D11CreateDevice(EnumAdapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, createDeviceFlags, NULL, 0, D3D11_SDK_VERSION, &pTmpDevice, &deviceFeature, NULL); + + if (FAILED(hr)) + suitable = false; + + if (deviceFeature < D3D_FEATURE_LEVEL_10_0) + suitable = false; + + //double check we support required bgra format for LEVEL_10_0 & LEVEL_10_1 + if (deviceFeature == D3D_FEATURE_LEVEL_10_0 || deviceFeature == D3D_FEATURE_LEVEL_10_1) + { + U32 formatSupported = 0; + pTmpDevice->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &formatSupported); + U32 flagsRequired = D3D11_FORMAT_SUPPORT_RENDER_TARGET | D3D11_FORMAT_SUPPORT_DISPLAY; + if (!(formatSupported && flagsRequired)) + { + Con::printf("DXGI adapter: %s does not support BGRA", Description.c_str()); + suitable = false; + } + } + delete[] displayModes; + SAFE_RELEASE(pTmpDevice); SAFE_RELEASE(pOutput); SAFE_RELEASE(EnumAdapter); - adapterList.push_back(toAdd); + + if (suitable) + { + adapterList.push_back(toAdd); + } + else + { + Con::printf("DXGI adapter: %s does not support D3D11 feature level 10 or better", Description.c_str()); + delete toAdd; + } } SAFE_RELEASE(DXGIFactory); @@ -271,7 +429,6 @@ void GFXD3D11Device::init(const GFXVideoMode &mode, PlatformWindow *window) mDebugLayers = true; #endif - D3D_FEATURE_LEVEL deviceFeature; D3D_DRIVER_TYPE driverType = D3D_DRIVER_TYPE_HARDWARE;// use D3D_DRIVER_TYPE_REFERENCE for reference device // create a device & device context HRESULT hres = D3D11CreateDevice(NULL, @@ -282,7 +439,7 @@ void GFXD3D11Device::init(const GFXVideoMode &mode, PlatformWindow *window) 0, D3D11_SDK_VERSION, &mD3DDevice, - &deviceFeature, + &mFeatureLevel, &mD3DDeviceContext); if(FAILED(hres)) @@ -298,7 +455,7 @@ void GFXD3D11Device::init(const GFXVideoMode &mode, PlatformWindow *window) 0, D3D11_SDK_VERSION, &mD3DDevice, - &deviceFeature, + &mFeatureLevel, &mD3DDeviceContext); //if we failed again than we definitely have a problem if (FAILED(hres)) @@ -319,11 +476,27 @@ void GFXD3D11Device::init(const GFXVideoMode &mode, PlatformWindow *window) // Now reacquire all the resources we trashed earlier reacquireDefaultPoolResources(); - //TODO implement feature levels? - if (deviceFeature >= D3D_FEATURE_LEVEL_11_0) + //set vert/pixel shader targets + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + mVertexShaderTarget = "vs_5_0"; + mPixelShaderTarget = "ps_5_0"; mPixVersion = 5.0f; - else - AssertFatal(false, "GFXD3D11Device::init - We don't support anything below feature level 11."); + break; + case D3D_FEATURE_LEVEL_10_1: + mVertexShaderTarget = "vs_4_1"; + mPixelShaderTarget = "ps_4_1"; + mPixVersion = 4.1f; + break; + case D3D_FEATURE_LEVEL_10_0: + mVertexShaderTarget = "vs_4_0"; + mPixelShaderTarget = "ps_4_0"; + mPixVersion = 4.0f; + break; + default: + AssertFatal(false, "GFXD3D11Device::init - We don't support this feature level"); + } D3D11_QUERY_DESC queryDesc; queryDesc.Query = D3D11_QUERY_OCCLUSION; @@ -475,124 +648,6 @@ void GFXD3D11Device::endReset(GFXD3D11WindowTarget *windowTarget) updateStates(true); } -class GFXPCD3D11RegisterDevice -{ -public: - GFXPCD3D11RegisterDevice() - { - GFXInit::getRegisterDeviceSignal().notify(&GFXD3D11Device::enumerateAdapters); - } -}; - -static GFXPCD3D11RegisterDevice pPCD3D11RegisterDevice; - -//----------------------------------------------------------------------------- -/// Parse command line arguments for window creation -//----------------------------------------------------------------------------- -static void sgPCD3D11DeviceHandleCommandLine(S32 argc, const char **argv) -{ - // useful to pass parameters by command line for d3d (e.g. -dx9 -dx11) - for (U32 i = 1; i < argc; i++) - { - argv[i]; - } -} - -// Register the command line parsing hook -static ProcessRegisterCommandLine sgCommandLine( sgPCD3D11DeviceHandleCommandLine ); - -GFXD3D11Device::GFXD3D11Device(U32 index) -{ - mDeviceSwizzle32 = &Swizzles::bgra; - GFXVertexColor::setSwizzle( mDeviceSwizzle32 ); - - mDeviceSwizzle24 = &Swizzles::bgr; - - mAdapterIndex = index; - mD3DDevice = NULL; - mVolatileVB = NULL; - - mCurrentPB = NULL; - mDynamicPB = NULL; - - mLastVertShader = NULL; - mLastPixShader = NULL; - - mCanCurrentlyRender = false; - mTextureManager = NULL; - mCurrentStateBlock = NULL; - mResourceListHead = NULL; - - mPixVersion = 0.0; - - mDrawInstancesCount = 0; - - mCardProfiler = NULL; - - mDeviceDepthStencil = NULL; - mDeviceBackbuffer = NULL; - mDeviceBackBufferView = NULL; - mDeviceDepthStencilView = NULL; - - mCreateFenceType = -1; // Unknown, test on first allocate - - mCurrentConstBuffer = NULL; - - mOcclusionQuerySupported = false; - - mDebugLayers = false; - - for(U32 i = 0; i < GS_COUNT; ++i) - mModelViewProjSC[i] = NULL; - - // Set up the Enum translation tables - GFXD3D11EnumTranslate::init(); -} - -GFXD3D11Device::~GFXD3D11Device() -{ - // Release our refcount on the current stateblock object - mCurrentStateBlock = NULL; - - releaseDefaultPoolResources(); - - mD3DDeviceContext->ClearState(); - mD3DDeviceContext->Flush(); - - // Free the vertex declarations. - VertexDeclMap::Iterator iter = mVertexDecls.begin(); - for ( ; iter != mVertexDecls.end(); iter++ ) - delete iter->value; - - // Forcibly clean up the pools - mVolatileVBList.setSize(0); - mDynamicPB = NULL; - - // And release our D3D resources. - SAFE_RELEASE(mDeviceDepthStencilView); - SAFE_RELEASE(mDeviceBackBufferView); - SAFE_RELEASE(mDeviceDepthStencil); - SAFE_RELEASE(mDeviceBackbuffer); - SAFE_RELEASE(mD3DDeviceContext); - - SAFE_DELETE(mCardProfiler); - SAFE_DELETE(gScreenShot); - -#ifdef TORQUE_DEBUG - if (mDebugLayers) - { - ID3D11Debug *pDebug = NULL; - mD3DDevice->QueryInterface(IID_PPV_ARGS(&pDebug)); - AssertFatal(pDebug, "~GFXD3D11Device- Failed to get debug layer"); - pDebug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL); - SAFE_RELEASE(pDebug); - } -#endif - - SAFE_RELEASE(mSwapChain); - SAFE_RELEASE(mD3DDevice); -} - void GFXD3D11Device::setupGenericShaders(GenericShaderType type) { AssertFatal(type != GSTargetRestore, ""); //not used @@ -600,11 +655,12 @@ void GFXD3D11Device::setupGenericShaders(GenericShaderType type) if(mGenericShader[GSColor] == NULL) { ShaderData *shaderData; - + //shader model 4.0 is enough for the generic shaders + const char* shaderModel = "4.0"; shaderData = new ShaderData(); shaderData->setField("DXVertexShaderFile", "shaders/common/fixedFunction/colorV.hlsl"); shaderData->setField("DXPixelShaderFile", "shaders/common/fixedFunction/colorP.hlsl"); - shaderData->setField("pixVersion", "5.0"); + shaderData->setField("pixVersion", shaderModel); shaderData->registerObject(); mGenericShader[GSColor] = shaderData->getShader(); mGenericShaderBuffer[GSColor] = mGenericShader[GSColor]->allocConstBuffer(); @@ -614,7 +670,7 @@ void GFXD3D11Device::setupGenericShaders(GenericShaderType type) shaderData = new ShaderData(); shaderData->setField("DXVertexShaderFile", "shaders/common/fixedFunction/modColorTextureV.hlsl"); shaderData->setField("DXPixelShaderFile", "shaders/common/fixedFunction/modColorTextureP.hlsl"); - shaderData->setField("pixVersion", "5.0"); + shaderData->setField("pixVersion", shaderModel); shaderData->registerObject(); mGenericShader[GSModColorTexture] = shaderData->getShader(); mGenericShaderBuffer[GSModColorTexture] = mGenericShader[GSModColorTexture]->allocConstBuffer(); @@ -624,7 +680,7 @@ void GFXD3D11Device::setupGenericShaders(GenericShaderType type) shaderData = new ShaderData(); shaderData->setField("DXVertexShaderFile", "shaders/common/fixedFunction/addColorTextureV.hlsl"); shaderData->setField("DXPixelShaderFile", "shaders/common/fixedFunction/addColorTextureP.hlsl"); - shaderData->setField("pixVersion", "5.0"); + shaderData->setField("pixVersion", shaderModel); shaderData->registerObject(); mGenericShader[GSAddColorTexture] = shaderData->getShader(); mGenericShaderBuffer[GSAddColorTexture] = mGenericShader[GSAddColorTexture]->allocConstBuffer(); @@ -634,7 +690,7 @@ void GFXD3D11Device::setupGenericShaders(GenericShaderType type) shaderData = new ShaderData(); shaderData->setField("DXVertexShaderFile", "shaders/common/fixedFunction/textureV.hlsl"); shaderData->setField("DXPixelShaderFile", "shaders/common/fixedFunction/textureP.hlsl"); - shaderData->setField("pixVersion", "5.0"); + shaderData->setField("pixVersion", shaderModel); shaderData->registerObject(); mGenericShader[GSTexture] = shaderData->getShader(); mGenericShaderBuffer[GSTexture] = mGenericShader[GSTexture]->allocConstBuffer(); diff --git a/Engine/source/gfx/D3D11/gfxD3D11Device.h b/Engine/source/gfx/D3D11/gfxD3D11Device.h index 726dce42f..c0024e9d2 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Device.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Device.h @@ -129,6 +129,11 @@ protected: F32 mPixVersion; + D3D_FEATURE_LEVEL mFeatureLevel; + // Shader Model targers + String mVertexShaderTarget; + String mPixelShaderTarget; + bool mDebugLayers; DXGI_SAMPLE_DESC mMultisampleDesc; @@ -196,8 +201,6 @@ public: static void enumerateAdapters( Vector &adapterList ); - GFXTextureObject* createRenderSurface( U32 width, U32 height, GFXFormat format, U32 mipLevel ); - ID3D11DepthStencilView* getDepthStencilView() { return mDeviceDepthStencilView; } ID3D11RenderTargetView* getRenderTargetView() { return mDeviceBackBufferView; } ID3D11Texture2D* getBackBufferTexture() { return mDeviceBackbuffer; } @@ -294,6 +297,12 @@ public: // Default multisample parameters DXGI_SAMPLE_DESC getMultisampleType() const { return mMultisampleDesc; } + + // Get feature level this gfx device supports + D3D_FEATURE_LEVEL getFeatureLevel() const { mFeatureLevel; } + // Shader Model targers + const String &getVertexShaderTarget() const { return mVertexShaderTarget; } + const String &getPixelShaderTarget() const { return mPixelShaderTarget; } }; #endif diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp index 519c4645a..1e132534c 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.cpp @@ -206,7 +206,6 @@ bool GFXD3D11ConstBufferLayout::setMatrix(const ParamDesc& pd, const GFXShaderCo } else if (pd.constType == GFXSCT_Float4x3) { - F32 buffer[4 * 4]; const U32 csize = 48; // Loop through and copy @@ -811,18 +810,21 @@ bool GFXD3D11Shader::_init() mSamplerDescriptions.clear(); mShaderConsts.clear(); + String vertTarget = D3D11->getVertexShaderTarget(); + String pixTarget = D3D11->getPixelShaderTarget(); + if ( !Con::getBoolVariable( "$shaders::forceLoadCSF", false ) ) { - if (!mVertexFile.isEmpty() && !_compileShader( mVertexFile, "vs_5_0", d3dMacros, mVertexConstBufferLayout, mSamplerDescriptions ) ) + if (!mVertexFile.isEmpty() && !_compileShader( mVertexFile, vertTarget, d3dMacros, mVertexConstBufferLayout, mSamplerDescriptions ) ) return false; - if (!mPixelFile.isEmpty() && !_compileShader( mPixelFile, "ps_5_0", d3dMacros, mPixelConstBufferLayout, mSamplerDescriptions ) ) + if (!mPixelFile.isEmpty() && !_compileShader( mPixelFile, pixTarget, d3dMacros, mPixelConstBufferLayout, mSamplerDescriptions ) ) return false; } else { - if ( !_loadCompiledOutput( mVertexFile, "vs_5_0", mVertexConstBufferLayout, mSamplerDescriptions ) ) + if ( !_loadCompiledOutput( mVertexFile, vertTarget, mVertexConstBufferLayout, mSamplerDescriptions ) ) { if ( smLogErrors ) Con::errorf( "GFXD3D11Shader::init - Unable to load precompiled vertex shader for '%s'.", mVertexFile.getFullPath().c_str() ); @@ -830,7 +832,7 @@ bool GFXD3D11Shader::_init() return false; } - if ( !_loadCompiledOutput( mPixelFile, "ps_5_0", mPixelConstBufferLayout, mSamplerDescriptions ) ) + if ( !_loadCompiledOutput( mPixelFile, pixTarget, mPixelConstBufferLayout, mSamplerDescriptions ) ) { if ( smLogErrors ) Con::errorf( "GFXD3D11Shader::init - Unable to load precompiled pixel shader for '%s'.", mPixelFile.getFullPath().c_str() ); @@ -1053,20 +1055,20 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath, return result; } -void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *table, +void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *pTable, GenericConstBufferLayout *bufferLayoutIn, Vector &samplerDescriptions ) { PROFILE_SCOPE( GFXD3D11Shader_GetShaderConstants ); - AssertFatal(table, "NULL constant table not allowed, is this an assembly shader?"); + AssertFatal(pTable, "NULL constant table not allowed, is this an assembly shader?"); GFXD3D11ConstBufferLayout *bufferLayout = (GFXD3D11ConstBufferLayout*)bufferLayoutIn; Vector &subBuffers = bufferLayout->getSubBufferDesc(); subBuffers.clear(); D3D11_SHADER_DESC tableDesc; - HRESULT hr = table->GetDesc(&tableDesc); + HRESULT hr = pTable->GetDesc(&tableDesc); if (FAILED(hr)) { AssertFatal(false, "Shader Reflection table unable to be created"); @@ -1076,7 +1078,7 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *table, U32 bufferOffset = 0; for (U32 i = 0; i < tableDesc.ConstantBuffers; i++) { - ID3D11ShaderReflectionConstantBuffer* constantBuffer = table->GetConstantBufferByIndex(i); + ID3D11ShaderReflectionConstantBuffer* constantBuffer = pTable->GetConstantBufferByIndex(i); D3D11_SHADER_BUFFER_DESC constantBufferDesc; if (constantBuffer->GetDesc(&constantBufferDesc) == S_OK) @@ -1161,7 +1163,7 @@ void GFXD3D11Shader::_getShaderConstants( ID3D11ShaderReflection *table, { GFXShaderConstDesc desc; D3D11_SHADER_INPUT_BIND_DESC bindDesc; - table->GetResourceBindingDesc(i, &bindDesc); + pTable->GetResourceBindingDesc(i, &bindDesc); switch (bindDesc.Type) { diff --git a/Engine/source/gfx/D3D11/gfxD3D11Shader.h b/Engine/source/gfx/D3D11/gfxD3D11Shader.h index 2e4074a8f..fc4cac62c 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Shader.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Shader.h @@ -434,7 +434,7 @@ protected: GenericConstBufferLayout *bufferLayout, Vector &samplerDescriptions ); - void _getShaderConstants( ID3D11ShaderReflection* table, + void _getShaderConstants( ID3D11ShaderReflection* pTable, GenericConstBufferLayout *bufferLayout, Vector &samplerDescriptions );