2010-04-25 00:31:27 +00:00
/*
2010-01-28 13:07:06 +00:00
* Copyright ( C ) 2007 - 2009 Gabest
* http : //www.gabest.org
*
* This Program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 , or ( at your option )
* any later version .
2010-04-25 00:31:27 +00:00
*
2010-01-28 13:07:06 +00:00
* This Program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
2010-04-25 00:31:27 +00:00
*
2010-01-28 13:07:06 +00:00
* You should have received a copy of the GNU General Public License
* along with GNU Make ; see the file COPYING . If not , write to
2012-09-09 18:16:11 +00:00
* the Free Software Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA USA .
2010-01-28 13:07:06 +00:00
* http : //www.gnu.org/copyleft/gpl.html
*
*/
# include "stdafx.h"
# include "GSdx.h"
# include "GSDevice11.h"
2010-05-07 14:19:54 +00:00
# include "GSUtil.h"
2010-01-28 13:07:06 +00:00
# include "resource.h"
2015-08-29 15:53:29 +00:00
# include <fstream>
2019-01-25 17:06:08 +00:00
# include <VersionHelpers.h>
HMODULE GSDevice11 : : s_d3d_compiler_dll = nullptr ;
decltype ( & D3DCompile ) GSDevice11 : : s_pD3DCompile = nullptr ;
bool GSDevice11 : : s_old_d3d_compiler_dll ;
2010-01-28 13:07:06 +00:00
GSDevice11 : : GSDevice11 ( )
{
memset ( & m_state , 0 , sizeof ( m_state ) ) ;
memset ( & m_vs_cb_cache , 0 , sizeof ( m_vs_cb_cache ) ) ;
2017-03-03 21:18:49 +00:00
memset ( & m_gs_cb_cache , 0 , sizeof ( m_gs_cb_cache ) ) ;
2010-01-28 13:07:06 +00:00
memset ( & m_ps_cb_cache , 0 , sizeof ( m_ps_cb_cache ) ) ;
2014-02-02 17:50:32 +00:00
FXAA_Compiled = false ;
ExShader_Compiled = false ;
2017-03-03 21:18:49 +00:00
2010-01-28 13:07:06 +00:00
m_state . topology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED ;
m_state . bf = - 1 ;
2017-03-03 21:18:49 +00:00
2018-09-20 17:14:59 +00:00
m_mipmap = theApp . GetConfigI ( " mipmap " ) ;
2019-01-25 17:06:08 +00:00
m_upscale_multiplier = theApp . GetConfigI ( " upscale_multiplier " ) ;
2020-01-18 20:25:08 +00:00
const BiFiltering nearest_filter = static_cast < BiFiltering > ( theApp . GetConfigI ( " filter " ) ) ;
const int aniso_level = theApp . GetConfigI ( " MaxAnisotropy " ) ;
if ( ( nearest_filter ! = BiFiltering : : Nearest & & ! theApp . GetConfigB ( " paltex " ) & & aniso_level ) )
m_aniso_filter = aniso_level ;
else
m_aniso_filter = 0 ;
2010-01-28 13:07:06 +00:00
}
2019-01-25 17:06:08 +00:00
bool GSDevice11 : : LoadD3DCompiler ( )
2010-01-28 13:07:06 +00:00
{
2019-01-25 17:06:08 +00:00
// Windows 8.1 and later come with the latest d3dcompiler_47.dll, but
// Windows 7 devs might also have the dll available for use (which will
// have to be placed in the application directory)
s_d3d_compiler_dll = LoadLibraryEx ( D3DCOMPILER_DLL , nullptr , LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32 ) ;
// Windows Vista and 7 can use the older version. If the previous LoadLibrary
// call fails on Windows 8.1 and later, then the user's system is likely
// broken.
if ( s_d3d_compiler_dll )
{
s_old_d3d_compiler_dll = false ;
}
else
{
if ( ! IsWindows8Point1OrGreater ( ) )
// Use LoadLibrary instead of LoadLibraryEx, some Windows 7 systems
// have issues with it.
s_d3d_compiler_dll = LoadLibrary ( " D3DCompiler_43.dll " ) ;
if ( s_d3d_compiler_dll = = nullptr )
return false ;
s_old_d3d_compiler_dll = true ;
}
s_pD3DCompile = reinterpret_cast < decltype ( & D3DCompile ) > ( GetProcAddress ( s_d3d_compiler_dll , " D3DCompile " ) ) ;
if ( s_pD3DCompile )
return true ;
FreeLibrary ( s_d3d_compiler_dll ) ;
s_d3d_compiler_dll = nullptr ;
return false ;
}
void GSDevice11 : : FreeD3DCompiler ( )
{
s_pD3DCompile = nullptr ;
if ( s_d3d_compiler_dll )
FreeLibrary ( s_d3d_compiler_dll ) ;
s_d3d_compiler_dll = nullptr ;
}
bool GSDevice11 : : SetFeatureLevel ( D3D_FEATURE_LEVEL level , bool compat_mode )
{
m_shader . level = level ;
switch ( level )
{
case D3D_FEATURE_LEVEL_10_0 :
m_shader . model = " 0x400 " ;
m_shader . vs = " vs_4_0 " ;
m_shader . gs = " gs_4_0 " ;
m_shader . ps = " ps_4_0 " ;
m_shader . cs = " cs_4_0 " ;
break ;
case D3D_FEATURE_LEVEL_10_1 :
m_shader . model = " 0x401 " ;
m_shader . vs = " vs_4_1 " ;
m_shader . gs = " gs_4_1 " ;
m_shader . ps = " ps_4_1 " ;
m_shader . cs = " cs_4_1 " ;
break ;
case D3D_FEATURE_LEVEL_11_0 :
m_shader . model = " 0x500 " ;
m_shader . vs = " vs_5_0 " ;
m_shader . gs = " gs_5_0 " ;
m_shader . ps = " ps_5_0 " ;
m_shader . cs = " cs_5_0 " ;
break ;
default :
ASSERT ( 0 ) ;
return false ;
}
return true ;
2010-01-28 13:07:06 +00:00
}
2017-02-22 21:02:34 +00:00
bool GSDevice11 : : Create ( const std : : shared_ptr < GSWnd > & wnd )
2010-01-28 13:07:06 +00:00
{
2019-06-16 14:13:16 +00:00
bool nvidia_vendor = false ;
2010-01-28 13:07:06 +00:00
if ( ! __super : : Create ( wnd ) )
{
return false ;
}
HRESULT hr = E_FAIL ;
DXGI_SWAP_CHAIN_DESC scd ;
D3D11_BUFFER_DESC bd ;
D3D11_SAMPLER_DESC sd ;
D3D11_DEPTH_STENCIL_DESC dsd ;
2011-02-24 23:46:26 +00:00
D3D11_RASTERIZER_DESC rd ;
2010-01-28 13:07:06 +00:00
D3D11_BLEND_DESC bsd ;
2012-08-06 05:26:44 +00:00
CComPtr < IDXGIAdapter1 > adapter ;
D3D_DRIVER_TYPE driver_type = D3D_DRIVER_TYPE_HARDWARE ;
2016-05-24 19:52:06 +00:00
std : : string adapter_id = theApp . GetConfigS ( " Adapter " ) ;
2012-08-06 05:26:44 +00:00
2019-06-16 14:13:16 +00:00
if ( adapter_id = = " ref " )
2012-08-06 05:26:44 +00:00
{
driver_type = D3D_DRIVER_TYPE_REFERENCE ;
}
else
{
CComPtr < IDXGIFactory1 > dxgi_factory ;
CreateDXGIFactory1 ( __uuidof ( IDXGIFactory1 ) , ( void * * ) & dxgi_factory ) ;
if ( dxgi_factory )
for ( int i = 0 ; ; i + + )
{
CComPtr < IDXGIAdapter1 > enum_adapter ;
if ( S_OK ! = dxgi_factory - > EnumAdapters1 ( i , & enum_adapter ) )
break ;
DXGI_ADAPTER_DESC1 desc ;
hr = enum_adapter - > GetDesc1 ( & desc ) ;
2019-06-16 14:13:16 +00:00
if ( S_OK = = hr & & ( GSAdapter ( desc ) = = adapter_id | | adapter_id = = " default " ) )
2012-08-06 05:26:44 +00:00
{
2019-06-16 14:13:16 +00:00
if ( desc . VendorId = = 0x10DE )
nvidia_vendor = true ;
2012-08-06 05:26:44 +00:00
adapter = enum_adapter ;
driver_type = D3D_DRIVER_TYPE_UNKNOWN ;
break ;
}
}
}
2010-01-28 13:07:06 +00:00
memset ( & scd , 0 , sizeof ( scd ) ) ;
scd . BufferCount = 2 ;
scd . BufferDesc . Width = 1 ;
scd . BufferDesc . Height = 1 ;
scd . BufferDesc . Format = DXGI_FORMAT_R8G8B8A8_UNORM ;
//scd.BufferDesc.RefreshRate.Numerator = 60;
//scd.BufferDesc.RefreshRate.Denominator = 1;
scd . BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT ;
2011-02-19 03:36:30 +00:00
scd . OutputWindow = ( HWND ) m_wnd - > GetHandle ( ) ;
2010-01-28 13:07:06 +00:00
scd . SampleDesc . Count = 1 ;
scd . SampleDesc . Quality = 0 ;
2010-03-19 20:27:06 +00:00
// Always start in Windowed mode. According to MS, DXGI just "prefers" this, and it's more or less
// required if we want to add support for dual displays later on. The fullscreen/exclusive flip
// will be issued after all other initializations are complete.
2010-01-28 13:07:06 +00:00
scd . Windowed = TRUE ;
2010-03-19 20:27:06 +00:00
// NOTE : D3D11_CREATE_DEVICE_SINGLETHREADED
// This flag is safe as long as the DXGI's internal message pump is disabled or is on the
// same thread as the GS window (which the emulator makes sure of, if it utilizes a
// multithreaded GS). Setting the flag is a nice and easy 5% speedup on GS-intensive scenes.
2010-01-28 13:07:06 +00:00
uint32 flags = D3D11_CREATE_DEVICE_SINGLETHREADED ;
# ifdef DEBUG
flags | = D3D11_CREATE_DEVICE_DEBUG ;
# endif
D3D_FEATURE_LEVEL level ;
2011-02-20 16:09:46 +00:00
const D3D_FEATURE_LEVEL levels [ ] =
{
D3D_FEATURE_LEVEL_11_0 ,
D3D_FEATURE_LEVEL_10_1 ,
D3D_FEATURE_LEVEL_10_0 ,
} ;
2012-08-06 05:26:44 +00:00
hr = D3D11CreateDeviceAndSwapChain ( adapter , driver_type , NULL , flags , levels , countof ( levels ) , D3D11_SDK_VERSION , & scd , & m_swapchain , & m_dev , & level , & m_ctx ) ;
2010-01-28 13:07:06 +00:00
if ( FAILED ( hr ) ) return false ;
if ( ! SetFeatureLevel ( level , true ) )
{
return false ;
}
2019-08-18 21:16:04 +00:00
// Set maximum texture size limit based on supported feature level.
if ( level > = D3D_FEATURE_LEVEL_11_0 )
m_d3d_texsize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION ;
else
m_d3d_texsize = D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION ;
2018-09-20 00:13:26 +00:00
{ // HACK: check nVIDIA
2019-06-18 20:06:35 +00:00
// Note: It can cause issues on several games such as SOTC, Fatal Frame, plus it adds border offset.
2019-06-18 20:34:17 +00:00
bool disable_safe_features = theApp . GetConfigB ( " UserHacks " ) & & theApp . GetConfigB ( " UserHacks_Disable_Safe_Features " ) ;
m_hack_topleft_offset = ( m_upscale_multiplier ! = 1 & & nvidia_vendor & & ! disable_safe_features ) ? - 0.01f : 0.0f ;
2018-09-20 00:13:26 +00:00
}
2019-01-29 23:08:30 +00:00
// debug
# ifdef _DEBUG
CComPtr < ID3D11Debug > debug ;
hr = m_dev - > QueryInterface < ID3D11Debug > ( & debug ) ;
if ( SUCCEEDED ( hr ) )
{
CComPtr < ID3D11InfoQueue > info_queue ;
hr = debug - > QueryInterface < ID3D11InfoQueue > ( & info_queue ) ;
if ( SUCCEEDED ( hr ) )
{
int break_on = theApp . GetConfigI ( " dx_break_on_severity " ) ;
info_queue - > SetBreakOnSeverity ( D3D11_MESSAGE_SEVERITY_CORRUPTION , break_on & ( 1 < < 0 ) ) ;
info_queue - > SetBreakOnSeverity ( D3D11_MESSAGE_SEVERITY_ERROR , break_on & ( 1 < < 1 ) ) ;
info_queue - > SetBreakOnSeverity ( D3D11_MESSAGE_SEVERITY_WARNING , break_on & ( 1 < < 2 ) ) ;
info_queue - > SetBreakOnSeverity ( D3D11_MESSAGE_SEVERITY_INFO , break_on & ( 1 < < 3 ) ) ;
}
}
# endif
2010-01-28 13:07:06 +00:00
// convert
D3D11_INPUT_ELEMENT_DESC il_convert [ ] =
{
{ " POSITION " , 0 , DXGI_FORMAT_R32G32B32A32_FLOAT , 0 , 0 , D3D11_INPUT_PER_VERTEX_DATA , 0 } ,
{ " TEXCOORD " , 0 , DXGI_FORMAT_R32G32_FLOAT , 0 , 16 , D3D11_INPUT_PER_VERTEX_DATA , 0 } ,
2018-12-14 11:59:00 +00:00
{ " COLOR " , 0 , DXGI_FORMAT_R8G8B8A8_UNORM , 0 , 28 , D3D11_INPUT_PER_VERTEX_DATA , 0 } ,
2010-01-28 13:07:06 +00:00
} ;
2019-06-14 18:24:37 +00:00
ShaderMacro sm_model ( m_shader . model ) ;
2017-04-08 15:54:27 +00:00
std : : vector < char > shader ;
2015-08-29 15:53:29 +00:00
theApp . LoadResource ( IDR_CONVERT_FX , shader ) ;
2019-06-14 18:24:37 +00:00
CreateShader ( shader , " convert.fx " , nullptr , " vs_main " , sm_model . GetPtr ( ) , & m_convert . vs , il_convert , countof ( il_convert ) , & m_convert . il ) ;
2010-01-28 13:07:06 +00:00
2019-06-14 18:24:37 +00:00
ShaderMacro sm_convert ( m_shader . model ) ;
sm_convert . AddMacro ( " PS_SCALE_FACTOR " , std : : max ( 1 , m_upscale_multiplier ) ) ;
2018-10-12 06:06:17 +00:00
2019-06-14 18:24:37 +00:00
D3D_SHADER_MACRO * sm_convert_ptr = sm_convert . GetPtr ( ) ;
2018-10-12 06:06:17 +00:00
2013-06-29 12:02:03 +00:00
for ( size_t i = 0 ; i < countof ( m_convert . ps ) ; i + + )
2010-01-28 13:07:06 +00:00
{
2019-06-14 18:24:37 +00:00
CreateShader ( shader , " convert.fx " , nullptr , format ( " ps_main%d " , i ) . c_str ( ) , sm_convert_ptr , & m_convert . ps [ i ] ) ;
2010-01-28 13:07:06 +00:00
}
memset ( & dsd , 0 , sizeof ( dsd ) ) ;
hr = m_dev - > CreateDepthStencilState ( & dsd , & m_convert . dss ) ;
2018-12-03 17:04:18 +00:00
dsd . DepthEnable = true ;
dsd . DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL ;
dsd . DepthFunc = D3D11_COMPARISON_ALWAYS ;
hr = m_dev - > CreateDepthStencilState ( & dsd , & m_convert . dss_write ) ;
2010-01-28 13:07:06 +00:00
memset ( & bsd , 0 , sizeof ( bsd ) ) ;
bsd . RenderTarget [ 0 ] . RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL ;
hr = m_dev - > CreateBlendState ( & bsd , & m_convert . bs ) ;
// merge
memset ( & bd , 0 , sizeof ( bd ) ) ;
2011-02-24 23:46:26 +00:00
bd . ByteWidth = sizeof ( MergeConstantBuffer ) ;
bd . Usage = D3D11_USAGE_DEFAULT ;
bd . BindFlags = D3D11_BIND_CONSTANT_BUFFER ;
2010-01-28 13:07:06 +00:00
2011-02-24 23:46:26 +00:00
hr = m_dev - > CreateBuffer ( & bd , NULL , & m_merge . cb ) ;
2010-01-28 13:07:06 +00:00
2015-08-29 15:53:29 +00:00
theApp . LoadResource ( IDR_MERGE_FX , shader ) ;
2013-06-29 12:02:03 +00:00
for ( size_t i = 0 ; i < countof ( m_merge . ps ) ; i + + )
2010-01-28 13:07:06 +00:00
{
2019-06-14 18:24:37 +00:00
CreateShader ( shader , " merge.fx " , nullptr , format ( " ps_main%d " , i ) . c_str ( ) , sm_model . GetPtr ( ) , & m_merge . ps [ i ] ) ;
2010-01-28 13:07:06 +00:00
}
memset ( & bsd , 0 , sizeof ( bsd ) ) ;
bsd . RenderTarget [ 0 ] . BlendEnable = true ;
bsd . RenderTarget [ 0 ] . BlendOp = D3D11_BLEND_OP_ADD ;
bsd . RenderTarget [ 0 ] . SrcBlend = D3D11_BLEND_SRC_ALPHA ;
bsd . RenderTarget [ 0 ] . DestBlend = D3D11_BLEND_INV_SRC_ALPHA ;
bsd . RenderTarget [ 0 ] . BlendOpAlpha = D3D11_BLEND_OP_ADD ;
bsd . RenderTarget [ 0 ] . SrcBlendAlpha = D3D11_BLEND_ONE ;
bsd . RenderTarget [ 0 ] . DestBlendAlpha = D3D11_BLEND_ZERO ;
bsd . RenderTarget [ 0 ] . RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL ;
hr = m_dev - > CreateBlendState ( & bsd , & m_merge . bs ) ;
// interlace
memset ( & bd , 0 , sizeof ( bd ) ) ;
2011-02-24 23:46:26 +00:00
bd . ByteWidth = sizeof ( InterlaceConstantBuffer ) ;
bd . Usage = D3D11_USAGE_DEFAULT ;
bd . BindFlags = D3D11_BIND_CONSTANT_BUFFER ;
2010-01-28 13:07:06 +00:00
2011-02-24 23:46:26 +00:00
hr = m_dev - > CreateBuffer ( & bd , NULL , & m_interlace . cb ) ;
2010-01-28 13:07:06 +00:00
2015-08-29 15:53:29 +00:00
theApp . LoadResource ( IDR_INTERLACE_FX , shader ) ;
2013-06-29 12:02:03 +00:00
for ( size_t i = 0 ; i < countof ( m_interlace . ps ) ; i + + )
2010-01-28 13:07:06 +00:00
{
2019-06-14 18:24:37 +00:00
CreateShader ( shader , " interlace.fx " , nullptr , format ( " ps_main%d " , i ) . c_str ( ) , sm_model . GetPtr ( ) , & m_interlace . ps [ i ] ) ;
2010-01-28 13:07:06 +00:00
}
2019-06-14 18:24:37 +00:00
// Shade Boost
2016-05-24 19:52:06 +00:00
2019-06-14 18:24:37 +00:00
ShaderMacro sm_sboost ( m_shader . model ) ;
2016-05-24 19:52:06 +00:00
2019-07-16 23:16:46 +00:00
sm_sboost . AddMacro ( " SB_SATURATION " , std : : max ( 0 , std : : min ( theApp . GetConfigI ( " ShadeBoost_Saturation " ) , 100 ) ) ) ;
sm_sboost . AddMacro ( " SB_BRIGHTNESS " , std : : max ( 0 , std : : min ( theApp . GetConfigI ( " ShadeBoost_Brightness " ) , 100 ) ) ) ;
sm_sboost . AddMacro ( " SB_CONTRAST " , std : : max ( 0 , std : : min ( theApp . GetConfigI ( " ShadeBoost_Contrast " ) , 100 ) ) ) ;
2012-02-29 00:29:29 +00:00
memset ( & bd , 0 , sizeof ( bd ) ) ;
bd . ByteWidth = sizeof ( ShadeBoostConstantBuffer ) ;
bd . Usage = D3D11_USAGE_DEFAULT ;
bd . BindFlags = D3D11_BIND_CONSTANT_BUFFER ;
hr = m_dev - > CreateBuffer ( & bd , NULL , & m_shadeboost . cb ) ;
2015-08-29 15:53:29 +00:00
theApp . LoadResource ( IDR_SHADEBOOST_FX , shader ) ;
2019-06-14 18:24:37 +00:00
CreateShader ( shader , " shadeboost.fx " , nullptr , " ps_main " , sm_sboost . GetPtr ( ) , & m_shadeboost . ps ) ;
2012-02-29 00:29:29 +00:00
2014-01-17 10:17:24 +00:00
// External fx shader
memset ( & bd , 0 , sizeof ( bd ) ) ;
bd . ByteWidth = sizeof ( ExternalFXConstantBuffer ) ;
bd . Usage = D3D11_USAGE_DEFAULT ;
bd . BindFlags = D3D11_BIND_CONSTANT_BUFFER ;
hr = m_dev - > CreateBuffer ( & bd , NULL , & m_shaderfx . cb ) ;
// Fxaa
2011-07-25 11:16:01 +00:00
memset ( & bd , 0 , sizeof ( bd ) ) ;
bd . ByteWidth = sizeof ( FXAAConstantBuffer ) ;
bd . Usage = D3D11_USAGE_DEFAULT ;
bd . BindFlags = D3D11_BIND_CONSTANT_BUFFER ;
hr = m_dev - > CreateBuffer ( & bd , NULL , & m_fxaa . cb ) ;
2014-02-02 17:50:32 +00:00
//
2010-01-28 13:07:06 +00:00
memset ( & rd , 0 , sizeof ( rd ) ) ;
rd . FillMode = D3D11_FILL_SOLID ;
rd . CullMode = D3D11_CULL_NONE ;
rd . FrontCounterClockwise = false ;
rd . DepthBias = false ;
rd . DepthBiasClamp = 0 ;
rd . SlopeScaledDepthBias = 0 ;
rd . DepthClipEnable = false ; // ???
rd . ScissorEnable = true ;
rd . MultisampleEnable = true ;
rd . AntialiasedLineEnable = false ;
hr = m_dev - > CreateRasterizerState ( & rd , & m_rs ) ;
m_ctx - > RSSetState ( m_rs ) ;
//
memset ( & sd , 0 , sizeof ( sd ) ) ;
2020-01-18 20:25:08 +00:00
sd . Filter = m_aniso_filter ? D3D11_FILTER_ANISOTROPIC : D3D11_FILTER_MIN_MAG_MIP_LINEAR ;
2010-01-28 13:07:06 +00:00
sd . AddressU = D3D11_TEXTURE_ADDRESS_CLAMP ;
sd . AddressV = D3D11_TEXTURE_ADDRESS_CLAMP ;
sd . AddressW = D3D11_TEXTURE_ADDRESS_CLAMP ;
2014-02-04 21:42:43 +00:00
sd . MinLOD = - FLT_MAX ;
2010-01-28 13:07:06 +00:00
sd . MaxLOD = FLT_MAX ;
2020-01-18 20:25:08 +00:00
sd . MaxAnisotropy = m_aniso_filter ;
2010-01-28 13:07:06 +00:00
sd . ComparisonFunc = D3D11_COMPARISON_NEVER ;
hr = m_dev - > CreateSamplerState ( & sd , & m_convert . ln ) ;
2020-01-18 20:25:08 +00:00
sd . Filter = m_aniso_filter ? D3D11_FILTER_ANISOTROPIC : D3D11_FILTER_MIN_MAG_MIP_POINT ;
2010-01-28 13:07:06 +00:00
hr = m_dev - > CreateSamplerState ( & sd , & m_convert . pt ) ;
//
Reset ( 1 , 1 ) ;
//
CreateTextureFX ( ) ;
2010-04-25 00:31:27 +00:00
2010-01-28 13:07:06 +00:00
//
memset ( & dsd , 0 , sizeof ( dsd ) ) ;
dsd . DepthEnable = false ;
dsd . StencilEnable = true ;
dsd . StencilReadMask = 1 ;
dsd . StencilWriteMask = 1 ;
dsd . FrontFace . StencilFunc = D3D11_COMPARISON_ALWAYS ;
dsd . FrontFace . StencilPassOp = D3D11_STENCIL_OP_REPLACE ;
dsd . FrontFace . StencilFailOp = D3D11_STENCIL_OP_KEEP ;
dsd . FrontFace . StencilDepthFailOp = D3D11_STENCIL_OP_KEEP ;
dsd . BackFace . StencilFunc = D3D11_COMPARISON_ALWAYS ;
dsd . BackFace . StencilPassOp = D3D11_STENCIL_OP_REPLACE ;
dsd . BackFace . StencilFailOp = D3D11_STENCIL_OP_KEEP ;
dsd . BackFace . StencilDepthFailOp = D3D11_STENCIL_OP_KEEP ;
m_dev - > CreateDepthStencilState ( & dsd , & m_date . dss ) ;
D3D11_BLEND_DESC blend ;
memset ( & blend , 0 , sizeof ( blend ) ) ;
m_dev - > CreateBlendState ( & blend , & m_date . bs ) ;
2010-03-19 20:27:06 +00:00
// Exclusive/Fullscreen flip, issued for legacy (managed) windows only. GSopen2 style
// emulators will issue the flip themselves later on.
2010-01-28 13:07:06 +00:00
if ( m_wnd - > IsManaged ( ) )
{
2016-05-24 19:52:06 +00:00
SetExclusive ( ! theApp . GetConfigB ( " windowed " ) ) ;
2010-01-28 13:07:06 +00:00
}
2018-12-14 15:45:42 +00:00
GSVector2i tex_font = m_osd . get_texture_font_size ( ) ;
2018-12-14 22:53:28 +00:00
m_font = std : : unique_ptr < GSTexture > (
2019-01-14 21:28:23 +00:00
CreateSurface ( GSTexture : : Texture , tex_font . x , tex_font . y , DXGI_FORMAT_R8_UNORM )
2018-12-14 22:53:28 +00:00
) ;
2018-12-14 15:45:42 +00:00
2010-01-28 13:07:06 +00:00
return true ;
}
bool GSDevice11 : : Reset ( int w , int h )
{
if ( ! __super : : Reset ( w , h ) )
return false ;
if ( m_swapchain )
{
DXGI_SWAP_CHAIN_DESC scd ;
2011-02-22 23:39:02 +00:00
2010-01-28 13:07:06 +00:00
memset ( & scd , 0 , sizeof ( scd ) ) ;
2011-02-07 01:59:05 +00:00
2010-01-28 13:07:06 +00:00
m_swapchain - > GetDesc ( & scd ) ;
m_swapchain - > ResizeBuffers ( scd . BufferCount , w , h , scd . BufferDesc . Format , 0 ) ;
2010-04-25 00:31:27 +00:00
2010-01-28 13:07:06 +00:00
CComPtr < ID3D11Texture2D > backbuffer ;
2011-02-07 01:59:05 +00:00
2010-01-28 13:25:18 +00:00
if ( FAILED ( m_swapchain - > GetBuffer ( 0 , __uuidof ( ID3D11Texture2D ) , ( void * * ) & backbuffer ) ) )
2010-01-28 13:07:06 +00:00
{
2010-01-28 13:25:18 +00:00
return false ;
2010-01-28 13:07:06 +00:00
}
2010-01-28 13:25:18 +00:00
m_backbuffer = new GSTexture11 ( backbuffer ) ;
2010-01-28 13:07:06 +00:00
}
return true ;
}
void GSDevice11 : : SetExclusive ( bool isExcl )
{
if ( ! m_swapchain ) return ;
2010-04-25 00:31:27 +00:00
2010-01-28 13:07:06 +00:00
// TODO : Support for alternative display modes, by finishing this code below:
// Video mode info should be pulled form config/ini.
/*DXGI_MODE_DESC desc;
memset ( & desc , 0 , sizeof ( desc ) ) ;
desc . RefreshRate = 0 ; // must be zero for best results.
m_swapchain - > ResizeTarget ( & desc ) ;
*/
2010-04-25 00:31:27 +00:00
2011-02-07 01:59:05 +00:00
HRESULT hr = m_swapchain - > SetFullscreenState ( isExcl , NULL ) ;
2010-01-28 13:07:06 +00:00
if ( hr = = DXGI_ERROR_NOT_CURRENTLY_AVAILABLE )
2011-02-07 01:59:05 +00:00
{
2010-01-28 13:07:06 +00:00
fprintf ( stderr , " (GSdx10) SetExclusive(%s) failed; request unavailable. " , isExcl ? " true " : " false " ) ;
2011-02-07 01:59:05 +00:00
}
2010-04-25 00:31:27 +00:00
}
2010-01-28 13:07:06 +00:00
2017-08-23 18:55:42 +00:00
void GSDevice11 : : SetVSync ( int vsync )
{
m_vsync = vsync ? 1 : 0 ;
}
2010-01-28 13:07:06 +00:00
void GSDevice11 : : Flip ( )
{
m_swapchain - > Present ( m_vsync , 0 ) ;
}
2019-01-25 06:50:40 +00:00
void GSDevice11 : : BeforeDraw ( )
2012-01-05 02:40:24 +00:00
{
2018-12-16 02:09:12 +00:00
// DX can't read from the FB
2019-01-25 06:50:40 +00:00
// So let's copy it and send that to the shader instead
2019-01-20 06:09:47 +00:00
2019-01-25 06:50:40 +00:00
auto bits = m_state . ps_sr_bitfield ;
m_state . ps_sr_bitfield = 0 ;
2019-01-20 06:09:47 +00:00
2019-01-25 06:50:40 +00:00
unsigned long i ;
while ( _BitScanForward ( & i , bits ) )
{
GSTexture11 * tex = m_state . ps_sr_texture [ i ] ;
2018-12-16 02:09:12 +00:00
2019-01-25 06:50:40 +00:00
if ( tex - > Equal ( m_state . rt_texture ) | | tex - > Equal ( m_state . rt_ds ) )
{
# ifdef _DEBUG
OutputDebugString ( format ( " WARNING: FB read detected on slot %i, copying... " , i ) . c_str ( ) ) ;
# endif
GSTexture * cp = nullptr ;
2018-12-16 02:09:12 +00:00
2019-01-25 06:50:40 +00:00
CloneTexture ( tex , & cp ) ;
2018-12-16 02:09:12 +00:00
2019-01-25 06:50:40 +00:00
PSSetShaderResource ( i , cp ) ;
}
2018-12-16 02:09:12 +00:00
2019-01-25 06:50:40 +00:00
bits ^ = 1u < < i ;
2018-12-16 02:09:12 +00:00
}
2019-01-25 06:50:40 +00:00
PSUpdateShaderState ( ) ;
}
void GSDevice11 : : AfterDraw ( )
{
unsigned long i ;
while ( _BitScanForward ( & i , m_state . ps_sr_bitfield ) )
2018-12-16 02:09:12 +00:00
{
2019-01-25 06:50:40 +00:00
# ifdef _DEBUG
OutputDebugString ( format ( " WARNING: Cleaning up copied texture on slot %i " , i ) . c_str ( ) ) ;
# endif
Recycle ( m_state . ps_sr_texture [ i ] ) ;
PSSetShaderResource ( i , NULL ) ;
2018-12-16 02:09:12 +00:00
}
2010-01-28 13:07:06 +00:00
}
2019-01-25 06:50:40 +00:00
void GSDevice11 : : DrawPrimitive ( )
{
BeforeDraw ( ) ;
m_ctx - > Draw ( m_vertex . count , m_vertex . start ) ;
AfterDraw ( ) ;
}
void GSDevice11 : : DrawIndexedPrimitive ( )
{
BeforeDraw ( ) ;
m_ctx - > DrawIndexed ( m_index . count , m_index . start , m_vertex . start ) ;
AfterDraw ( ) ;
}
2012-01-27 11:56:49 +00:00
void GSDevice11 : : DrawIndexedPrimitive ( int offset , int count )
{
2017-08-04 17:41:16 +00:00
ASSERT ( offset + count < = ( int ) m_index . count ) ;
2012-01-27 11:56:49 +00:00
2019-01-25 06:50:40 +00:00
BeforeDraw ( ) ;
2012-01-27 11:56:49 +00:00
m_ctx - > DrawIndexed ( count , m_index . start + offset , m_vertex . start ) ;
2019-01-25 06:50:40 +00:00
AfterDraw ( ) ;
2012-01-27 11:56:49 +00:00
}
2012-01-13 18:10:05 +00:00
void GSDevice11 : : Dispatch ( uint32 x , uint32 y , uint32 z )
{
m_ctx - > Dispatch ( x , y , z ) ;
}
2010-01-28 13:07:06 +00:00
void GSDevice11 : : ClearRenderTarget ( GSTexture * t , const GSVector4 & c )
{
2015-08-04 17:26:17 +00:00
if ( ! t ) return ;
2010-01-28 13:07:06 +00:00
m_ctx - > ClearRenderTargetView ( * ( GSTexture11 * ) t , c . v ) ;
}
void GSDevice11 : : ClearRenderTarget ( GSTexture * t , uint32 c )
{
2015-08-04 17:26:17 +00:00
if ( ! t ) return ;
2011-04-04 11:05:54 +00:00
GSVector4 color = GSVector4 : : rgba32 ( c ) * ( 1.0f / 255 ) ;
2010-01-28 13:07:06 +00:00
m_ctx - > ClearRenderTargetView ( * ( GSTexture11 * ) t , color . v ) ;
}
2016-07-27 21:22:46 +00:00
void GSDevice11 : : ClearDepth ( GSTexture * t )
2010-01-28 13:07:06 +00:00
{
2015-08-04 17:26:17 +00:00
if ( ! t ) return ;
2016-07-27 21:22:46 +00:00
m_ctx - > ClearDepthStencilView ( * ( GSTexture11 * ) t , D3D11_CLEAR_DEPTH , 0.0f , 0 ) ;
2010-01-28 13:07:06 +00:00
}
void GSDevice11 : : ClearStencil ( GSTexture * t , uint8 c )
{
2015-08-04 17:26:17 +00:00
if ( ! t ) return ;
2010-01-28 13:07:06 +00:00
m_ctx - > ClearDepthStencilView ( * ( GSTexture11 * ) t , D3D11_CLEAR_STENCIL , 0 , c ) ;
}
2019-01-14 21:28:23 +00:00
GSTexture * GSDevice11 : : CreateSurface ( int type , int w , int h , int format )
2010-01-28 13:07:06 +00:00
{
HRESULT hr ;
D3D11_TEXTURE2D_DESC desc ;
memset ( & desc , 0 , sizeof ( desc ) ) ;
2019-08-18 21:16:04 +00:00
// Texture limit for D3D10/11 min 1, max 8192 D3D10, max 16384 D3D11.
desc . Width = std : : max ( 1 , std : : min ( w , m_d3d_texsize ) ) ;
desc . Height = std : : max ( 1 , std : : min ( h , m_d3d_texsize ) ) ;
2010-01-28 13:07:06 +00:00
desc . Format = ( DXGI_FORMAT ) format ;
desc . MipLevels = 1 ;
desc . ArraySize = 1 ;
desc . SampleDesc . Count = 1 ;
desc . SampleDesc . Quality = 0 ;
desc . Usage = D3D11_USAGE_DEFAULT ;
2018-09-20 17:14:59 +00:00
// mipmap = m_mipmap > 1 || m_filter != TriFiltering::None;
bool mipmap = m_mipmap > 1 ;
int layers = mipmap & & format = = DXGI_FORMAT_R8G8B8A8_UNORM ? ( int ) log2 ( std : : max ( w , h ) ) : 1 ;
2010-01-28 13:07:06 +00:00
switch ( type )
{
case GSTexture : : RenderTarget :
desc . BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE ;
break ;
case GSTexture : : DepthStencil :
2018-12-04 05:20:41 +00:00
desc . BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE ;
2010-01-28 13:07:06 +00:00
break ;
case GSTexture : : Texture :
desc . BindFlags = D3D11_BIND_SHADER_RESOURCE ;
2018-09-20 17:14:59 +00:00
desc . MipLevels = layers ;
2010-01-28 13:07:06 +00:00
break ;
case GSTexture : : Offscreen :
desc . Usage = D3D11_USAGE_STAGING ;
desc . CPUAccessFlags | = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE ;
break ;
}
GSTexture11 * t = NULL ;
CComPtr < ID3D11Texture2D > texture ;
hr = m_dev - > CreateTexture2D ( & desc , NULL , & texture ) ;
if ( SUCCEEDED ( hr ) )
{
t = new GSTexture11 ( texture ) ;
switch ( type )
{
case GSTexture : : RenderTarget :
ClearRenderTarget ( t , 0 ) ;
break ;
case GSTexture : : DepthStencil :
2016-07-27 21:22:46 +00:00
ClearDepth ( t ) ;
2010-01-28 13:07:06 +00:00
break ;
}
}
2016-10-13 18:44:59 +00:00
else
{
throw std : : bad_alloc ( ) ;
}
2010-01-28 13:07:06 +00:00
return t ;
}
2019-01-25 17:06:08 +00:00
GSTexture * GSDevice11 : : FetchSurface ( int type , int w , int h , int format )
{
2019-01-30 12:10:34 +00:00
if ( format = = 0 )
2019-02-07 11:08:44 +00:00
format = ( type = = GSTexture : : DepthStencil | | type = = GSTexture : : SparseDepthStencil ) ? DXGI_FORMAT_R32G8X24_TYPELESS : DXGI_FORMAT_R8G8B8A8_UNORM ;
2019-01-25 17:06:08 +00:00
2019-01-30 12:10:34 +00:00
return __super : : FetchSurface ( type , w , h , format ) ;
2010-01-28 13:07:06 +00:00
}
2015-05-19 10:42:14 +00:00
GSTexture * GSDevice11 : : CopyOffscreen ( GSTexture * src , const GSVector4 & sRect , int w , int h , int format , int ps_shader )
2010-01-28 13:07:06 +00:00
{
GSTexture * dst = NULL ;
if ( format = = 0 )
{
format = DXGI_FORMAT_R8G8B8A8_UNORM ;
}
2018-12-04 05:20:41 +00:00
ASSERT ( format = = DXGI_FORMAT_R8G8B8A8_UNORM | | format = = DXGI_FORMAT_R16_UINT | | format = = DXGI_FORMAT_R32_UINT ) ;
2010-01-28 13:07:06 +00:00
2019-01-14 21:28:23 +00:00
if ( GSTexture * rt = CreateRenderTarget ( w , h , format ) )
2010-01-28 13:07:06 +00:00
{
2015-05-15 18:49:25 +00:00
GSVector4 dRect ( 0 , 0 , w , h ) ;
2010-01-28 13:07:06 +00:00
2019-01-14 21:28:23 +00:00
StretchRect ( src , sRect , rt , dRect , m_convert . ps [ ps_shader ] , NULL ) ;
2010-01-28 13:07:06 +00:00
dst = CreateOffscreen ( w , h , format ) ;
if ( dst )
{
m_ctx - > CopyResource ( * ( GSTexture11 * ) dst , * ( GSTexture11 * ) rt ) ;
}
Recycle ( rt ) ;
}
return dst ;
}
2015-05-15 18:45:31 +00:00
void GSDevice11 : : CopyRect ( GSTexture * sTex , GSTexture * dTex , const GSVector4i & r )
2010-01-28 13:07:06 +00:00
{
2019-01-20 06:09:47 +00:00
if ( ! sTex | | ! dTex )
2011-09-01 13:25:08 +00:00
{
ASSERT ( 0 ) ;
return ;
}
2019-01-20 06:09:47 +00:00
D3D11_BOX box = { ( UINT ) r . left , ( UINT ) r . top , 0U , ( UINT ) r . right , ( UINT ) r . bottom , 1U } ;
2010-01-28 13:07:06 +00:00
2019-01-20 06:09:47 +00:00
// DX api isn't happy if we pass a box for depth copy
// It complains that depth/multisample must be a full copy
// and asks us to use a NULL for the box
bool depth = ( sTex - > GetType ( ) = = GSTexture : : DepthStencil ) ;
auto pBox = depth ? nullptr : & box ;
m_ctx - > CopySubresourceRegion ( * ( GSTexture11 * ) dTex , 0 , 0 , 0 , 0 , * ( GSTexture11 * ) sTex , 0 , pBox ) ;
2010-01-28 13:07:06 +00:00
}
2019-01-20 06:09:47 +00:00
void GSDevice11 : : CloneTexture ( GSTexture * src , GSTexture * * dest )
2018-12-16 02:06:11 +00:00
{
2019-01-20 06:09:47 +00:00
if ( ! src | | ! ( src - > GetType ( ) = = GSTexture : : DepthStencil | | src - > GetType ( ) = = GSTexture : : RenderTarget ) )
{
ASSERT ( 0 ) ;
return ;
}
2018-12-16 02:06:11 +00:00
int w = src - > GetWidth ( ) ;
int h = src - > GetHeight ( ) ;
2019-01-20 06:09:47 +00:00
if ( src - > GetType ( ) = = GSTexture : : DepthStencil )
* dest = CreateDepthStencil ( w , h , src - > GetFormat ( ) ) ;
else
* dest = CreateRenderTarget ( w , h , src - > GetFormat ( ) ) ;
2018-12-16 02:06:11 +00:00
2019-01-20 06:09:47 +00:00
CopyRect ( src , * dest , GSVector4i ( 0 , 0 , w , h ) ) ;
2018-12-16 02:06:11 +00:00
}
2015-05-15 18:49:25 +00:00
void GSDevice11 : : StretchRect ( GSTexture * sTex , const GSVector4 & sRect , GSTexture * dTex , const GSVector4 & dRect , int shader , bool linear )
2010-01-28 13:07:06 +00:00
{
2015-05-15 18:49:25 +00:00
StretchRect ( sTex , sRect , dTex , dRect , m_convert . ps [ shader ] , NULL , linear ) ;
2010-01-28 13:07:06 +00:00
}
2015-05-15 18:49:25 +00:00
void GSDevice11 : : StretchRect ( GSTexture * sTex , const GSVector4 & sRect , GSTexture * dTex , const GSVector4 & dRect , ID3D11PixelShader * ps , ID3D11Buffer * ps_cb , bool linear )
2010-01-28 13:07:06 +00:00
{
2015-05-15 18:49:25 +00:00
StretchRect ( sTex , sRect , dTex , dRect , ps , ps_cb , m_convert . bs , linear ) ;
2010-01-28 13:07:06 +00:00
}
2019-06-19 14:47:57 +00:00
void GSDevice11 : : StretchRect ( GSTexture * sTex , const GSVector4 & sRect , GSTexture * dTex , const GSVector4 & dRect , bool red , bool green , bool blue , bool alpha )
{
D3D11_BLEND_DESC bd = { } ;
CComPtr < ID3D11BlendState > bs ;
uint8 write_mask = 0 ;
if ( red ) write_mask | = D3D11_COLOR_WRITE_ENABLE_RED ;
if ( green ) write_mask | = D3D11_COLOR_WRITE_ENABLE_GREEN ;
if ( blue ) write_mask | = D3D11_COLOR_WRITE_ENABLE_BLUE ;
if ( alpha ) write_mask | = D3D11_COLOR_WRITE_ENABLE_ALPHA ;
bd . RenderTarget [ 0 ] . RenderTargetWriteMask = write_mask ;
m_dev - > CreateBlendState ( & bd , & bs ) ;
StretchRect ( sTex , sRect , dTex , dRect , m_convert . ps [ ShaderConvert_COPY ] , nullptr , bs , false ) ;
}
void GSDevice11 : : StretchRect ( GSTexture * sTex , const GSVector4 & sRect , GSTexture * dTex , const GSVector4 & dRect , ID3D11PixelShader * ps , ID3D11Buffer * ps_cb , ID3D11BlendState * bs , bool linear )
2010-01-28 13:07:06 +00:00
{
2015-05-15 18:45:31 +00:00
if ( ! sTex | | ! dTex )
2011-09-01 13:25:08 +00:00
{
ASSERT ( 0 ) ;
return ;
}
2018-12-03 17:04:18 +00:00
bool draw_in_depth = ( ps = = m_convert . ps [ ShaderConvert_RGBA8_TO_FLOAT32 ] | | ps = = m_convert . ps [ ShaderConvert_RGBA8_TO_FLOAT24 ] | |
ps = = m_convert . ps [ ShaderConvert_RGBA8_TO_FLOAT16 ] | | ps = = m_convert . ps [ ShaderConvert_RGB5A1_TO_FLOAT16 ] ) ;
2010-01-28 13:07:06 +00:00
BeginScene ( ) ;
2015-05-15 18:43:57 +00:00
GSVector2i ds = dTex - > GetSize ( ) ;
2010-01-28 13:07:06 +00:00
// om
2018-12-03 17:04:18 +00:00
if ( draw_in_depth )
OMSetDepthStencilState ( m_convert . dss_write , 0 ) ;
else
OMSetDepthStencilState ( m_convert . dss , 0 ) ;
2010-01-28 13:07:06 +00:00
OMSetBlendState ( bs , 0 ) ;
2018-12-03 17:04:18 +00:00
if ( draw_in_depth )
OMSetRenderTargets ( NULL , dTex ) ;
else
OMSetRenderTargets ( dTex , NULL ) ;
2010-01-28 13:07:06 +00:00
// ia
2015-05-15 18:49:25 +00:00
float left = dRect . x * 2 / ds . x - 1.0f ;
float top = 1.0f - dRect . y * 2 / ds . y ;
float right = dRect . z * 2 / ds . x - 1.0f ;
float bottom = 1.0f - dRect . w * 2 / ds . y ;
2010-01-28 13:07:06 +00:00
GSVertexPT1 vertices [ ] =
{
2015-05-15 18:47:14 +00:00
{ GSVector4 ( left , top , 0.5f , 1.0f ) , GSVector2 ( sRect . x , sRect . y ) } ,
{ GSVector4 ( right , top , 0.5f , 1.0f ) , GSVector2 ( sRect . z , sRect . y ) } ,
{ GSVector4 ( left , bottom , 0.5f , 1.0f ) , GSVector2 ( sRect . x , sRect . w ) } ,
{ GSVector4 ( right , bottom , 0.5f , 1.0f ) , GSVector2 ( sRect . z , sRect . w ) } ,
2010-01-28 13:07:06 +00:00
} ;
2015-05-28 20:41:02 +00:00
2010-01-28 13:07:06 +00:00
IASetVertexBuffer ( vertices , sizeof ( vertices [ 0 ] ) , countof ( vertices ) ) ;
IASetInputLayout ( m_convert . il ) ;
IASetPrimitiveTopology ( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP ) ;
// vs
VSSetShader ( m_convert . vs , NULL ) ;
2015-05-28 20:41:02 +00:00
2010-01-28 13:07:06 +00:00
// gs
2015-05-28 20:41:02 +00:00
/* NVIDIA HACK!!!!
Not sure why , but having the Geometry shader disabled causes the strange stretching in recent drivers */
GSSelector sel ;
2015-08-19 22:01:39 +00:00
//Don't use shading for stretching, we're just passing through - Note: With Win10 it seems to cause other bugs when shading is off if any of the coords is greater than 0
//I really don't know whats going on there, but this seems to resolve it mostly (if not all, not tester a lot of games, only BIOS, FFXII and VP2)
2018-09-20 17:14:59 +00:00
//sel.iip = (sRect.y > 0.0f || sRect.w > 0.0f) ? 1 : 0;
2015-08-20 22:45:00 +00:00
//sel.prim = 2; //Triangle Strip
//SetupGS(sel);
2010-01-28 13:07:06 +00:00
2017-03-03 21:18:49 +00:00
GSSetShader ( NULL , NULL ) ;
2015-05-28 20:41:02 +00:00
/*END OF HACK*/
2018-09-20 17:14:59 +00:00
2015-05-28 20:41:02 +00:00
//
2010-01-28 13:07:06 +00:00
// ps
2015-05-15 18:45:31 +00:00
PSSetShaderResources ( sTex , NULL ) ;
2010-05-14 14:05:39 +00:00
PSSetSamplerState ( linear ? m_convert . ln : m_convert . pt , NULL ) ;
PSSetShader ( ps , ps_cb ) ;
2010-01-28 13:07:06 +00:00
//
DrawPrimitive ( ) ;
//
EndScene ( ) ;
PSSetShaderResources ( NULL , NULL ) ;
}
2018-12-14 15:45:42 +00:00
void GSDevice11 : : RenderOsd ( GSTexture * dt )
{
BeginScene ( ) ;
// om
OMSetDepthStencilState ( m_convert . dss , 0 ) ;
OMSetBlendState ( m_merge . bs , 0 ) ;
OMSetRenderTargets ( dt , NULL ) ;
if ( m_osd . m_texture_dirty ) {
2018-12-14 22:53:28 +00:00
m_osd . upload_texture_atlas ( m_font . get ( ) ) ;
2018-12-14 15:45:42 +00:00
}
// ps
2018-12-14 22:53:28 +00:00
PSSetShaderResource ( 0 , m_font . get ( ) ) ;
2018-12-14 15:45:42 +00:00
PSSetSamplerState ( m_convert . pt , NULL ) ;
PSSetShader ( m_convert . ps [ ShaderConvert_OSD ] , NULL ) ;
// ia
IASetInputLayout ( m_convert . il ) ;
IASetPrimitiveTopology ( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST ) ;
// Note scaling could also be done in shader (require gl3/dx10)
size_t count = m_osd . Size ( ) ;
void * dst = NULL ;
IAMapVertexBuffer ( & dst , sizeof ( GSVertexPT1 ) , count ) ;
count = m_osd . GeneratePrimitives ( ( GSVertexPT1 * ) dst , count ) ;
IAUnmapVertexBuffer ( ) ;
// vs
VSSetShader ( m_convert . vs , NULL ) ;
// gs
GSSetShader ( NULL , NULL ) ;
DrawPrimitive ( ) ;
EndScene ( ) ;
}
2016-10-09 11:20:31 +00:00
void GSDevice11 : : DoMerge ( GSTexture * sTex [ 3 ] , GSVector4 * sRect , GSTexture * dTex , GSVector4 * dRect , const GSRegPMODE & PMODE , const GSRegEXTBUF & EXTBUF , const GSVector4 & c )
2010-01-28 13:07:06 +00:00
{
2016-10-09 11:20:31 +00:00
bool slbg = PMODE . SLBG ;
bool mmod = PMODE . MMOD ;
2015-05-15 18:43:57 +00:00
ClearRenderTarget ( dTex , c ) ;
2010-01-28 13:07:06 +00:00
2015-05-15 18:45:31 +00:00
if ( sTex [ 1 ] & & ! slbg )
2010-01-28 13:07:06 +00:00
{
2015-05-15 18:49:25 +00:00
StretchRect ( sTex [ 1 ] , sRect [ 1 ] , dTex , dRect [ 1 ] , m_merge . ps [ 0 ] , NULL , true ) ;
2010-01-28 13:07:06 +00:00
}
2015-05-15 18:45:31 +00:00
if ( sTex [ 0 ] )
2010-01-28 13:07:06 +00:00
{
m_ctx - > UpdateSubresource ( m_merge . cb , 0 , NULL , & c , 0 , 0 ) ;
2015-05-15 18:49:25 +00:00
StretchRect ( sTex [ 0 ] , sRect [ 0 ] , dTex , dRect [ 0 ] , m_merge . ps [ mmod ? 1 : 0 ] , m_merge . cb , m_merge . bs , true ) ;
2010-01-28 13:07:06 +00:00
}
}
2015-05-15 18:45:31 +00:00
void GSDevice11 : : DoInterlace ( GSTexture * sTex , GSTexture * dTex , int shader , bool linear , float yoffset )
2010-01-28 13:07:06 +00:00
{
2015-05-15 18:43:57 +00:00
GSVector4 s = GSVector4 ( dTex - > GetSize ( ) ) ;
2010-01-28 13:07:06 +00:00
2015-05-15 18:47:14 +00:00
GSVector4 sRect ( 0 , 0 , 1 , 1 ) ;
2015-05-15 18:49:25 +00:00
GSVector4 dRect ( 0.0f , yoffset , s . x , s . y + yoffset ) ;
2010-01-28 13:07:06 +00:00
InterlaceConstantBuffer cb ;
cb . ZrH = GSVector2 ( 0 , 1.0f / s . y ) ;
cb . hH = s . y / 2 ;
m_ctx - > UpdateSubresource ( m_interlace . cb , 0 , NULL , & cb , 0 , 0 ) ;
2015-05-15 18:49:25 +00:00
StretchRect ( sTex , sRect , dTex , dRect , m_interlace . ps [ shader ] , m_interlace . cb , linear ) ;
2010-01-28 13:07:06 +00:00
}
2014-01-17 10:17:24 +00:00
//Included an init function for this also. Just to be safe.
void GSDevice11 : : InitExternalFX ( )
{
if ( ! ExShader_Compiled )
{
try {
2016-05-24 19:52:06 +00:00
std : : string config_name ( theApp . GetConfigS ( " shaderfx_conf " ) ) ;
2015-08-29 16:50:10 +00:00
std : : ifstream fconfig ( config_name ) ;
std : : stringstream shader ;
if ( fconfig . good ( ) )
shader < < fconfig . rdbuf ( ) < < " \n " ;
else
fprintf ( stderr , " GSdx: External shader config '%s' not loaded. \n " , config_name . c_str ( ) ) ;
2016-05-24 19:52:06 +00:00
std : : string shader_name ( theApp . GetConfigS ( " shaderfx_glsl " ) ) ;
2015-08-29 16:50:10 +00:00
std : : ifstream fshader ( shader_name ) ;
2015-08-29 15:53:29 +00:00
if ( fshader . good ( ) )
{
shader < < fshader . rdbuf ( ) ;
2018-12-19 19:28:05 +00:00
const std : : string & s = shader . str ( ) ;
std : : vector < char > buff ( s . begin ( ) , s . end ( ) ) ;
2019-06-14 18:24:37 +00:00
ShaderMacro sm ( m_shader . model ) ;
CreateShader ( buff , shader_name . c_str ( ) , D3D_COMPILE_STANDARD_FILE_INCLUDE , " ps_main " , sm . GetPtr ( ) , & m_shaderfx . ps ) ;
2015-08-29 15:53:29 +00:00
}
else
{
2015-08-29 16:50:10 +00:00
fprintf ( stderr , " GSdx: External shader '%s' not loaded and will be disabled! \n " , shader_name . c_str ( ) ) ;
2015-08-29 15:53:29 +00:00
}
2014-01-17 10:17:24 +00:00
}
catch ( GSDXRecoverableError ) {
2014-02-09 01:01:41 +00:00
printf ( " GSdx: failed to compile external post-processing shader. \n " ) ;
2014-01-17 10:17:24 +00:00
}
ExShader_Compiled = true ;
}
}
2015-05-15 18:45:31 +00:00
void GSDevice11 : : DoExternalFX ( GSTexture * sTex , GSTexture * dTex )
2014-01-17 10:17:24 +00:00
{
2015-05-15 18:43:57 +00:00
GSVector2i s = dTex - > GetSize ( ) ;
2014-01-17 10:17:24 +00:00
2015-05-15 18:47:14 +00:00
GSVector4 sRect ( 0 , 0 , 1 , 1 ) ;
2015-05-15 18:49:25 +00:00
GSVector4 dRect ( 0 , 0 , s . x , s . y ) ;
2014-01-17 10:17:24 +00:00
ExternalFXConstantBuffer cb ;
InitExternalFX ( ) ;
2016-04-14 10:00:58 +00:00
cb . xyFrame = GSVector2 ( ( float ) s . x , ( float ) s . y ) ;
cb . rcpFrame = GSVector4 ( 1.0f / ( float ) s . x , 1.0f / ( float ) s . y , 0.0f , 0.0f ) ;
2014-01-17 10:17:24 +00:00
cb . rcpFrameOpt = GSVector4 : : zero ( ) ;
m_ctx - > UpdateSubresource ( m_shaderfx . cb , 0 , NULL , & cb , 0 , 0 ) ;
2015-05-15 18:49:25 +00:00
StretchRect ( sTex , sRect , dTex , dRect , m_shaderfx . ps , m_shaderfx . cb , true ) ;
2014-01-17 10:17:24 +00:00
}
2014-01-09 21:51:42 +00:00
// This shouldn't be necessary, we have some bug corrupting memory
// and for some reason isolating this code makes the plugin not crash
void GSDevice11 : : InitFXAA ( )
2011-07-25 11:16:01 +00:00
{
2014-02-02 17:50:32 +00:00
if ( ! FXAA_Compiled )
2014-01-07 23:53:30 +00:00
{
2014-01-17 10:17:24 +00:00
try {
2017-04-08 15:54:27 +00:00
std : : vector < char > shader ;
2015-08-29 15:53:29 +00:00
theApp . LoadResource ( IDR_FXAA_FX , shader ) ;
2019-06-14 18:24:37 +00:00
ShaderMacro sm ( m_shader . model ) ;
CreateShader ( shader , " fxaa.fx " , nullptr , " ps_main " , sm . GetPtr ( ) , & m_fxaa . ps ) ;
2014-01-17 10:17:24 +00:00
}
catch ( GSDXRecoverableError ) {
2014-02-09 01:01:41 +00:00
printf ( " GSdx: failed to compile fxaa shader. \n " ) ;
2014-01-17 10:17:24 +00:00
}
2014-02-02 17:50:32 +00:00
FXAA_Compiled = true ;
2014-01-07 23:53:30 +00:00
}
2014-01-09 21:51:42 +00:00
}
2015-05-15 18:45:31 +00:00
void GSDevice11 : : DoFXAA ( GSTexture * sTex , GSTexture * dTex )
2014-01-09 21:51:42 +00:00
{
2015-05-15 18:43:57 +00:00
GSVector2i s = dTex - > GetSize ( ) ;
2014-01-09 21:51:42 +00:00
2015-05-15 18:47:14 +00:00
GSVector4 sRect ( 0 , 0 , 1 , 1 ) ;
2015-05-15 18:49:25 +00:00
GSVector4 dRect ( 0 , 0 , s . x , s . y ) ;
2014-01-09 21:51:42 +00:00
FXAAConstantBuffer cb ;
InitFXAA ( ) ;
2014-01-17 10:17:24 +00:00
2011-07-25 11:16:01 +00:00
cb . rcpFrame = GSVector4 ( 1.0f / s . x , 1.0f / s . y , 0.0f , 0.0f ) ;
cb . rcpFrameOpt = GSVector4 : : zero ( ) ;
m_ctx - > UpdateSubresource ( m_fxaa . cb , 0 , NULL , & cb , 0 , 0 ) ;
2015-05-15 18:49:25 +00:00
StretchRect ( sTex , sRect , dTex , dRect , m_fxaa . ps , m_fxaa . cb , true ) ;
2011-07-25 11:16:01 +00:00
2015-05-15 18:45:31 +00:00
//sTex->Save("c:\\temp1\\1.bmp");
2015-05-15 18:43:57 +00:00
//dTex->Save("c:\\temp1\\2.bmp");
2011-07-25 11:16:01 +00:00
}
2015-05-15 18:45:31 +00:00
void GSDevice11 : : DoShadeBoost ( GSTexture * sTex , GSTexture * dTex )
2012-02-29 00:29:29 +00:00
{
2015-05-15 18:43:57 +00:00
GSVector2i s = dTex - > GetSize ( ) ;
2012-02-29 00:29:29 +00:00
2015-05-15 18:47:14 +00:00
GSVector4 sRect ( 0 , 0 , 1 , 1 ) ;
2015-05-15 18:49:25 +00:00
GSVector4 dRect ( 0 , 0 , s . x , s . y ) ;
2012-02-29 00:29:29 +00:00
ShadeBoostConstantBuffer cb ;
cb . rcpFrame = GSVector4 ( 1.0f / s . x , 1.0f / s . y , 0.0f , 0.0f ) ;
cb . rcpFrameOpt = GSVector4 : : zero ( ) ;
m_ctx - > UpdateSubresource ( m_shadeboost . cb , 0 , NULL , & cb , 0 , 0 ) ;
2015-05-15 18:49:25 +00:00
StretchRect ( sTex , sRect , dTex , dRect , m_shadeboost . ps , m_shadeboost . cb , true ) ;
2012-02-29 00:29:29 +00:00
}
2011-02-18 03:50:12 +00:00
void GSDevice11 : : SetupDATE ( GSTexture * rt , GSTexture * ds , const GSVertexPT1 * vertices , bool datm )
2010-01-28 13:07:06 +00:00
{
2012-07-23 22:55:06 +00:00
// sfex3 (after the capcom logo), vf4 (first menu fading in), ffxii shadows, rumble roses shadows, persona4 shadows
2010-01-28 13:07:06 +00:00
2012-07-23 22:55:06 +00:00
BeginScene ( ) ;
2010-01-28 13:07:06 +00:00
2012-07-23 22:55:06 +00:00
ClearStencil ( ds , 0 ) ;
2010-01-28 13:07:06 +00:00
2012-07-23 22:55:06 +00:00
// om
2010-01-28 13:07:06 +00:00
2012-07-23 22:55:06 +00:00
OMSetDepthStencilState ( m_date . dss , 1 ) ;
OMSetBlendState ( m_date . bs , 0 ) ;
OMSetRenderTargets ( NULL , ds ) ;
2010-01-28 13:07:06 +00:00
2012-07-23 22:55:06 +00:00
// ia
2010-01-28 13:07:06 +00:00
2012-07-23 22:55:06 +00:00
IASetVertexBuffer ( vertices , sizeof ( vertices [ 0 ] ) , 4 ) ;
IASetInputLayout ( m_convert . il ) ;
IASetPrimitiveTopology ( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP ) ;
2010-01-28 13:07:06 +00:00
2012-07-23 22:55:06 +00:00
// vs
2010-01-28 13:07:06 +00:00
2012-07-23 22:55:06 +00:00
VSSetShader ( m_convert . vs , NULL ) ;
2010-01-28 13:07:06 +00:00
2012-07-23 22:55:06 +00:00
// gs
2010-01-28 13:07:06 +00:00
2017-03-03 21:18:49 +00:00
GSSetShader ( NULL , NULL ) ;
2010-01-28 13:07:06 +00:00
2012-07-23 22:55:06 +00:00
// ps
2019-01-14 21:28:23 +00:00
PSSetShaderResources ( rt , NULL ) ;
2012-07-23 22:55:06 +00:00
PSSetSamplerState ( m_convert . pt , NULL ) ;
2018-10-20 19:12:16 +00:00
PSSetShader ( m_convert . ps [ datm ? ShaderConvert_DATM_1 : ShaderConvert_DATM_0 ] , NULL ) ;
2010-01-28 13:07:06 +00:00
2012-07-23 22:55:06 +00:00
//
2010-01-28 13:07:06 +00:00
2012-07-23 22:55:06 +00:00
DrawPrimitive ( ) ;
2010-01-28 13:07:06 +00:00
2012-07-23 22:55:06 +00:00
//
2010-01-28 13:07:06 +00:00
2012-07-23 22:55:06 +00:00
EndScene ( ) ;
2010-01-28 13:07:06 +00:00
}
2012-01-05 02:40:24 +00:00
void GSDevice11 : : IASetVertexBuffer ( const void * vertex , size_t stride , size_t count )
2012-01-19 04:53:36 +00:00
{
void * ptr = NULL ;
if ( IAMapVertexBuffer ( & ptr , stride , count ) )
{
GSVector4i : : storent ( ptr , vertex , count * stride ) ;
IAUnmapVertexBuffer ( ) ;
}
}
bool GSDevice11 : : IAMapVertexBuffer ( void * * vertex , size_t stride , size_t count )
2010-01-28 13:07:06 +00:00
{
2012-01-05 02:40:24 +00:00
ASSERT ( m_vertex . count = = 0 ) ;
2010-01-28 13:07:06 +00:00
2012-01-05 02:40:24 +00:00
if ( count * stride > m_vertex . limit * m_vertex . stride )
2010-01-28 13:07:06 +00:00
{
m_vb_old = m_vb ;
m_vb = NULL ;
2012-01-05 02:40:24 +00:00
m_vertex . start = 0 ;
m_vertex . limit = std : : max < int > ( count * 3 / 2 , 11000 ) ;
2010-01-28 13:07:06 +00:00
}
if ( m_vb = = NULL )
{
D3D11_BUFFER_DESC bd ;
memset ( & bd , 0 , sizeof ( bd ) ) ;
bd . Usage = D3D11_USAGE_DYNAMIC ;
2012-01-05 02:40:24 +00:00
bd . ByteWidth = m_vertex . limit * stride ;
2010-01-28 13:07:06 +00:00
bd . BindFlags = D3D11_BIND_VERTEX_BUFFER ;
bd . CPUAccessFlags = D3D11_CPU_ACCESS_WRITE ;
HRESULT hr ;
2010-04-25 00:31:27 +00:00
2010-01-28 13:07:06 +00:00
hr = m_dev - > CreateBuffer ( & bd , NULL , & m_vb ) ;
2012-01-19 04:53:36 +00:00
if ( FAILED ( hr ) ) return false ;
2010-01-28 13:07:06 +00:00
}
D3D11_MAP type = D3D11_MAP_WRITE_NO_OVERWRITE ;
2012-01-05 02:40:24 +00:00
if ( m_vertex . start + count > m_vertex . limit | | stride ! = m_vertex . stride )
2010-01-28 13:07:06 +00:00
{
2012-01-05 02:40:24 +00:00
m_vertex . start = 0 ;
2010-01-28 13:07:06 +00:00
type = D3D11_MAP_WRITE_DISCARD ;
}
D3D11_MAPPED_SUBRESOURCE m ;
2012-01-19 04:53:36 +00:00
if ( FAILED ( m_ctx - > Map ( m_vb , 0 , type , 0 , & m ) ) )
2010-01-28 13:07:06 +00:00
{
2012-01-19 04:53:36 +00:00
return false ;
2010-01-28 13:07:06 +00:00
}
2012-01-19 04:53:36 +00:00
* vertex = ( uint8 * ) m . pData + m_vertex . start * stride ;
2012-01-05 02:40:24 +00:00
m_vertex . count = count ;
m_vertex . stride = stride ;
2010-01-28 13:07:06 +00:00
2012-01-19 04:53:36 +00:00
return true ;
}
void GSDevice11 : : IAUnmapVertexBuffer ( )
{
m_ctx - > Unmap ( m_vb , 0 ) ;
IASetVertexBuffer ( m_vb , m_vertex . stride ) ;
2010-01-28 13:07:06 +00:00
}
void GSDevice11 : : IASetVertexBuffer ( ID3D11Buffer * vb , size_t stride )
{
if ( m_state . vb ! = vb | | m_state . vb_stride ! = stride )
{
m_state . vb = vb ;
m_state . vb_stride = stride ;
2011-02-12 21:45:16 +00:00
uint32 stride2 = stride ;
2010-01-28 13:07:06 +00:00
uint32 offset = 0 ;
2011-02-12 21:45:16 +00:00
m_ctx - > IASetVertexBuffers ( 0 , 1 , & vb , & stride2 , & offset ) ;
2010-01-28 13:07:06 +00:00
}
}
2012-01-05 02:40:24 +00:00
void GSDevice11 : : IASetIndexBuffer ( const void * index , size_t count )
{
ASSERT ( m_index . count = = 0 ) ;
if ( count > m_index . limit )
{
m_ib_old = m_ib ;
m_ib = NULL ;
2012-01-18 11:47:31 +00:00
m_index . start = 0 ;
2012-01-05 02:40:24 +00:00
m_index . limit = std : : max < int > ( count * 3 / 2 , 11000 ) ;
}
if ( m_ib = = NULL )
{
D3D11_BUFFER_DESC bd ;
memset ( & bd , 0 , sizeof ( bd ) ) ;
bd . Usage = D3D11_USAGE_DYNAMIC ;
bd . ByteWidth = m_index . limit * sizeof ( uint32 ) ;
bd . BindFlags = D3D11_BIND_INDEX_BUFFER ;
bd . CPUAccessFlags = D3D11_CPU_ACCESS_WRITE ;
HRESULT hr ;
hr = m_dev - > CreateBuffer ( & bd , NULL , & m_ib ) ;
if ( FAILED ( hr ) ) return ;
}
D3D11_MAP type = D3D11_MAP_WRITE_NO_OVERWRITE ;
if ( m_index . start + count > m_index . limit )
{
m_index . start = 0 ;
type = D3D11_MAP_WRITE_DISCARD ;
}
D3D11_MAPPED_SUBRESOURCE m ;
if ( SUCCEEDED ( m_ctx - > Map ( m_ib , 0 , type , 0 , & m ) ) )
{
memcpy ( ( uint8 * ) m . pData + m_index . start * sizeof ( uint32 ) , index , count * sizeof ( uint32 ) ) ;
m_ctx - > Unmap ( m_ib , 0 ) ;
}
m_index . count = count ;
IASetIndexBuffer ( m_ib ) ;
}
void GSDevice11 : : IASetIndexBuffer ( ID3D11Buffer * ib )
{
if ( m_state . ib ! = ib )
{
m_state . ib = ib ;
m_ctx - > IASetIndexBuffer ( ib , DXGI_FORMAT_R32_UINT , 0 ) ;
}
}
2010-01-28 13:07:06 +00:00
void GSDevice11 : : IASetInputLayout ( ID3D11InputLayout * layout )
{
if ( m_state . layout ! = layout )
{
m_state . layout = layout ;
m_ctx - > IASetInputLayout ( layout ) ;
}
}
void GSDevice11 : : IASetPrimitiveTopology ( D3D11_PRIMITIVE_TOPOLOGY topology )
{
if ( m_state . topology ! = topology )
{
m_state . topology = topology ;
m_ctx - > IASetPrimitiveTopology ( topology ) ;
}
}
void GSDevice11 : : VSSetShader ( ID3D11VertexShader * vs , ID3D11Buffer * vs_cb )
{
if ( m_state . vs ! = vs )
{
m_state . vs = vs ;
m_ctx - > VSSetShader ( vs , NULL , 0 ) ;
}
2010-04-25 00:31:27 +00:00
2010-01-28 13:07:06 +00:00
if ( m_state . vs_cb ! = vs_cb )
{
m_state . vs_cb = vs_cb ;
m_ctx - > VSSetConstantBuffers ( 0 , 1 , & vs_cb ) ;
}
}
2017-03-03 21:18:49 +00:00
void GSDevice11 : : GSSetShader ( ID3D11GeometryShader * gs , ID3D11Buffer * gs_cb )
2010-01-28 13:07:06 +00:00
{
if ( m_state . gs ! = gs )
{
m_state . gs = gs ;
m_ctx - > GSSetShader ( gs , NULL , 0 ) ;
}
2017-03-03 21:18:49 +00:00
if ( m_state . gs_cb ! = gs_cb )
{
m_state . gs_cb = gs_cb ;
m_ctx - > GSSetConstantBuffers ( 0 , 1 , & gs_cb ) ;
}
2010-01-28 13:07:06 +00:00
}
void GSDevice11 : : PSSetShaderResources ( GSTexture * sr0 , GSTexture * sr1 )
{
2010-05-14 14:05:39 +00:00
PSSetShaderResource ( 0 , sr0 ) ;
PSSetShaderResource ( 1 , sr1 ) ;
2012-01-18 11:47:31 +00:00
2018-12-15 18:44:45 +00:00
for ( size_t i = 2 ; i < m_state . ps_sr_views . size ( ) ; i + + )
2012-01-18 11:47:31 +00:00
{
PSSetShaderResource ( i , NULL ) ;
}
2010-05-14 14:05:39 +00:00
}
2015-05-21 07:48:15 +00:00
void GSDevice11 : : PSSetShaderResource ( int i , GSTexture * sr )
2010-05-14 14:05:39 +00:00
{
ID3D11ShaderResourceView * srv = NULL ;
2010-04-25 00:31:27 +00:00
2015-05-21 07:48:15 +00:00
if ( sr ) srv = * ( GSTexture11 * ) sr ;
2011-02-07 01:59:05 +00:00
2018-12-15 18:44:45 +00:00
PSSetShaderResourceView ( i , srv , sr ) ;
2012-01-18 11:47:31 +00:00
}
2018-12-15 18:44:45 +00:00
void GSDevice11 : : PSSetShaderResourceView ( int i , ID3D11ShaderResourceView * srv , GSTexture * sr )
2012-01-18 11:47:31 +00:00
{
2018-12-17 14:52:15 +00:00
ASSERT ( i < ( int ) m_state . ps_sr_views . size ( ) ) ;
2012-01-18 11:47:31 +00:00
2018-12-15 18:44:45 +00:00
if ( m_state . ps_sr_views [ i ] ! = srv )
2011-02-07 01:59:05 +00:00
{
2018-12-15 18:44:45 +00:00
m_state . ps_sr_views [ i ] = srv ;
m_state . ps_sr_texture [ i ] = ( GSTexture11 * ) sr ;
2019-01-25 06:50:40 +00:00
srv ? m_state . ps_sr_bitfield | = 1u < < i : m_state . ps_sr_bitfield & = ~ ( 1u < < i ) ;
2010-05-14 14:05:39 +00:00
}
}
2010-01-28 13:07:06 +00:00
2018-12-20 00:19:36 +00:00
void GSDevice11 : : PSSetSamplerState ( ID3D11SamplerState * ss0 , ID3D11SamplerState * ss1 )
2010-05-14 14:05:39 +00:00
{
2018-12-20 00:19:36 +00:00
if ( m_state . ps_ss [ 0 ] ! = ss0 | | m_state . ps_ss [ 1 ] ! = ss1 )
2010-01-28 13:07:06 +00:00
{
2010-05-14 14:05:39 +00:00
m_state . ps_ss [ 0 ] = ss0 ;
m_state . ps_ss [ 1 ] = ss1 ;
2010-01-28 13:07:06 +00:00
}
}
void GSDevice11 : : PSSetShader ( ID3D11PixelShader * ps , ID3D11Buffer * ps_cb )
{
if ( m_state . ps ! = ps )
{
m_state . ps = ps ;
m_ctx - > PSSetShader ( ps , NULL , 0 ) ;
}
2010-04-25 00:31:27 +00:00
2010-05-14 14:05:39 +00:00
if ( m_state . ps_cb ! = ps_cb )
2010-01-28 13:07:06 +00:00
{
2010-05-14 14:05:39 +00:00
m_state . ps_cb = ps_cb ;
2010-01-28 13:07:06 +00:00
2010-05-14 14:05:39 +00:00
m_ctx - > PSSetConstantBuffers ( 0 , 1 , & ps_cb ) ;
2010-01-28 13:07:06 +00:00
}
2018-12-16 08:51:00 +00:00
}
void GSDevice11 : : PSUpdateShaderState ( )
{
m_ctx - > PSSetShaderResources ( 0 , m_state . ps_sr_views . size ( ) , m_state . ps_sr_views . data ( ) ) ;
m_ctx - > PSSetSamplers ( 0 , countof ( m_state . ps_ss ) , m_state . ps_ss ) ;
2010-01-28 13:07:06 +00:00
}
void GSDevice11 : : OMSetDepthStencilState ( ID3D11DepthStencilState * dss , uint8 sref )
{
if ( m_state . dss ! = dss | | m_state . sref ! = sref )
{
m_state . dss = dss ;
m_state . sref = sref ;
m_ctx - > OMSetDepthStencilState ( dss , sref ) ;
}
}
void GSDevice11 : : OMSetBlendState ( ID3D11BlendState * bs , float bf )
{
if ( m_state . bs ! = bs | | m_state . bf ! = bf )
{
m_state . bs = bs ;
m_state . bf = bf ;
float BlendFactor [ ] = { bf , bf , bf , 0 } ;
m_ctx - > OMSetBlendState ( bs , BlendFactor , 0xffffffff ) ;
}
}
void GSDevice11 : : OMSetRenderTargets ( GSTexture * rt , GSTexture * ds , const GSVector4i * scissor )
{
ID3D11RenderTargetView * rtv = NULL ;
ID3D11DepthStencilView * dsv = NULL ;
2012-07-23 22:55:06 +00:00
if ( ! rt & & ! ds )
throw GSDXRecoverableError ( ) ;
2010-01-28 13:07:06 +00:00
if ( rt ) rtv = * ( GSTexture11 * ) rt ;
if ( ds ) dsv = * ( GSTexture11 * ) ds ;
2018-12-15 18:42:58 +00:00
if ( m_state . rt_view ! = rtv | | m_state . dsv ! = dsv )
2010-01-28 13:07:06 +00:00
{
2018-12-15 18:42:58 +00:00
m_state . rt_view = rtv ;
2019-01-20 06:04:07 +00:00
m_state . rt_texture = static_cast < GSTexture11 * > ( rt ) ;
2010-01-28 13:07:06 +00:00
m_state . dsv = dsv ;
2019-01-20 06:04:07 +00:00
m_state . rt_ds = static_cast < GSTexture11 * > ( ds ) ;
2010-01-28 13:07:06 +00:00
m_ctx - > OMSetRenderTargets ( 1 , & rtv , dsv ) ;
}
2012-07-23 22:55:06 +00:00
GSVector2i size = rt ? rt - > GetSize ( ) : ds - > GetSize ( ) ;
if ( m_state . viewport ! = size )
2010-01-28 13:07:06 +00:00
{
2012-07-23 22:55:06 +00:00
m_state . viewport = size ;
2010-01-28 13:07:06 +00:00
D3D11_VIEWPORT vp ;
memset ( & vp , 0 , sizeof ( vp ) ) ;
2010-04-25 00:31:27 +00:00
2018-09-20 00:13:26 +00:00
vp . TopLeftX = m_hack_topleft_offset ;
vp . TopLeftY = m_hack_topleft_offset ;
2012-07-23 22:55:06 +00:00
vp . Width = ( float ) size . x ;
vp . Height = ( float ) size . y ;
2010-01-28 13:07:06 +00:00
vp . MinDepth = 0.0f ;
vp . MaxDepth = 1.0f ;
m_ctx - > RSSetViewports ( 1 , & vp ) ;
}
2012-07-23 22:55:06 +00:00
GSVector4i r = scissor ? * scissor : GSVector4i ( size ) . zwxy ( ) ;
2010-01-28 13:07:06 +00:00
2012-01-18 11:47:31 +00:00
if ( ! m_state . scissor . eq ( r ) )
{
m_state . scissor = r ;
m_ctx - > RSSetScissorRects ( 1 , r ) ;
}
}
2019-06-14 18:24:37 +00:00
GSDevice11 : : ShaderMacro : : ShaderMacro ( std : : string & smodel )
{
mlist . emplace_back ( " SHADER_MODEL " , smodel ) ;
}
void GSDevice11 : : ShaderMacro : : AddMacro ( const char * n , int d )
{
mlist . emplace_back ( n , std : : to_string ( d ) ) ;
}
D3D_SHADER_MACRO * GSDevice11 : : ShaderMacro : : GetPtr ( void )
{
mout . clear ( ) ;
for ( auto & i : mlist )
mout . emplace_back ( i . name . c_str ( ) , i . def . c_str ( ) ) ;
mout . emplace_back ( nullptr , nullptr ) ;
return ( D3D_SHADER_MACRO * ) mout . data ( ) ;
}
2018-12-19 19:28:05 +00:00
void GSDevice11 : : CreateShader ( std : : vector < char > source , const char * fn , ID3DInclude * include , const char * entry , D3D_SHADER_MACRO * macro , ID3D11VertexShader * * vs , D3D11_INPUT_ELEMENT_DESC * layout , int count , ID3D11InputLayout * * il )
2010-01-28 13:07:06 +00:00
{
HRESULT hr ;
2018-12-19 19:28:05 +00:00
CComPtr < ID3DBlob > shader ;
2010-01-28 13:07:06 +00:00
2018-12-19 19:28:05 +00:00
CompileShader ( source , fn , include , entry , macro , & shader , m_shader . vs ) ;
2010-01-28 13:07:06 +00:00
hr = m_dev - > CreateVertexShader ( ( void * ) shader - > GetBufferPointer ( ) , shader - > GetBufferSize ( ) , NULL , vs ) ;
if ( FAILED ( hr ) )
{
2012-06-11 02:31:44 +00:00
throw GSDXRecoverableError ( ) ;
2010-01-28 13:07:06 +00:00
}
hr = m_dev - > CreateInputLayout ( layout , count , shader - > GetBufferPointer ( ) , shader - > GetBufferSize ( ) , il ) ;
if ( FAILED ( hr ) )
{
2012-06-11 02:31:44 +00:00
throw GSDXRecoverableError ( ) ;
2010-01-28 13:07:06 +00:00
}
}
2018-12-19 19:28:05 +00:00
void GSDevice11 : : CreateShader ( std : : vector < char > source , const char * fn , ID3DInclude * include , const char * entry , D3D_SHADER_MACRO * macro , ID3D11GeometryShader * * gs )
2010-01-28 13:07:06 +00:00
{
HRESULT hr ;
2018-12-19 19:28:05 +00:00
CComPtr < ID3DBlob > shader ;
2010-01-28 13:07:06 +00:00
2018-12-19 19:28:05 +00:00
CompileShader ( source , fn , include , entry , macro , & shader , m_shader . gs ) ;
2010-01-28 13:07:06 +00:00
hr = m_dev - > CreateGeometryShader ( ( void * ) shader - > GetBufferPointer ( ) , shader - > GetBufferSize ( ) , NULL , gs ) ;
if ( FAILED ( hr ) )
{
2012-06-11 02:31:44 +00:00
throw GSDXRecoverableError ( ) ;
2010-01-28 13:07:06 +00:00
}
}
2018-12-19 19:28:05 +00:00
void GSDevice11 : : CreateShader ( std : : vector < char > source , const char * fn , ID3DInclude * include , const char * entry , D3D_SHADER_MACRO * macro , ID3D11PixelShader * * ps )
{
HRESULT hr ;
CComPtr < ID3DBlob > shader ;
CompileShader ( source , fn , include , entry , macro , & shader , m_shader . ps ) ;
hr = m_dev - > CreatePixelShader ( ( void * ) shader - > GetBufferPointer ( ) , shader - > GetBufferSize ( ) , NULL , ps ) ;
2012-01-18 11:47:31 +00:00
if ( FAILED ( hr ) )
{
2012-06-11 02:31:44 +00:00
throw GSDXRecoverableError ( ) ;
2012-01-18 11:47:31 +00:00
}
}
2018-12-19 19:28:05 +00:00
void GSDevice11 : : CompileShader ( std : : vector < char > source , const char * fn , ID3DInclude * include , const char * entry , D3D_SHADER_MACRO * macro , ID3DBlob * * shader , std : : string shader_model )
2012-01-13 18:10:05 +00:00
{
HRESULT hr ;
2018-12-19 19:28:05 +00:00
CComPtr < ID3DBlob > error ;
2012-01-13 18:10:05 +00:00
2018-12-19 19:28:05 +00:00
UINT flags = 0 ;
2012-01-13 18:10:05 +00:00
2018-12-19 19:28:05 +00:00
# ifdef _DEBUG
flags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION | D3DCOMPILE_AVOID_FLOW_CONTROL ;
# endif
2012-01-13 18:10:05 +00:00
2019-06-14 18:24:37 +00:00
hr = s_pD3DCompile ( source . data ( ) , source . size ( ) , fn , macro , include , entry , shader_model . c_str ( ) , flags , 0 , shader , & error ) ;
2018-12-19 19:28:05 +00:00
if ( error )
2012-01-13 18:10:05 +00:00
{
2019-01-04 00:00:10 +00:00
fprintf ( stderr , " %s \n " , ( const char * ) error - > GetBufferPointer ( ) ) ;
2012-01-13 18:10:05 +00:00
}
if ( FAILED ( hr ) )
{
2012-06-11 02:31:44 +00:00
throw GSDXRecoverableError ( ) ;
2012-01-13 18:10:05 +00:00
}
2019-01-25 17:06:08 +00:00
}
2019-06-06 14:21:32 +00:00
uint16 GSDevice11 : : ConvertBlendEnum ( uint16 generic )
2019-01-25 17:06:08 +00:00
{
2019-06-06 14:21:32 +00:00
switch ( generic )
{
case SRC_COLOR : return D3D11_BLEND_SRC_COLOR ;
case INV_SRC_COLOR : return D3D11_BLEND_INV_SRC_COLOR ;
case DST_COLOR : return D3D11_BLEND_DEST_COLOR ;
case INV_DST_COLOR : return D3D11_BLEND_INV_DEST_COLOR ;
case SRC1_COLOR : return D3D11_BLEND_SRC1_COLOR ;
case INV_SRC1_COLOR : return D3D11_BLEND_INV_SRC1_COLOR ;
case SRC_ALPHA : return D3D11_BLEND_SRC_ALPHA ;
case INV_SRC_ALPHA : return D3D11_BLEND_INV_SRC_ALPHA ;
case DST_ALPHA : return D3D11_BLEND_DEST_ALPHA ;
case INV_DST_ALPHA : return D3D11_BLEND_INV_DEST_ALPHA ;
case SRC1_ALPHA : return D3D11_BLEND_SRC1_ALPHA ;
case INV_SRC1_ALPHA : return D3D11_BLEND_INV_SRC1_ALPHA ;
case CONST_COLOR : return D3D11_BLEND_BLEND_FACTOR ;
case INV_CONST_COLOR : return D3D11_BLEND_INV_BLEND_FACTOR ;
case CONST_ONE : return D3D11_BLEND_ONE ;
case CONST_ZERO : return D3D11_BLEND_ZERO ;
case OP_ADD : return D3D11_BLEND_OP_ADD ;
case OP_SUBTRACT : return D3D11_BLEND_OP_SUBTRACT ;
case OP_REV_SUBTRACT : return D3D11_BLEND_OP_REV_SUBTRACT ;
default : ASSERT ( 0 ) ; return 0 ;
}
}