mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
+31
@@ -274,6 +274,10 @@ public final class SettingsAdapter extends RecyclerView.Adapter<SettingViewHolde
|
||||
{
|
||||
putXfbSetting(which);
|
||||
}
|
||||
else if (scSetting.getKey().equals(SettingsFile.KEY_UBERSHADER_MODE))
|
||||
{
|
||||
putUberShaderModeSetting(which);
|
||||
}
|
||||
else if (scSetting.getKey().equals(SettingsFile.KEY_WIIMOTE_EXTENSION))
|
||||
{
|
||||
putExtensionSetting(which, Character.getNumericValue(scSetting.getSection().charAt(scSetting.getSection().length() - 1)));
|
||||
@@ -437,6 +441,33 @@ public final class SettingsAdapter extends RecyclerView.Adapter<SettingViewHolde
|
||||
mView.putSetting(xfbReal);
|
||||
}
|
||||
|
||||
public void putUberShaderModeSetting(int which)
|
||||
{
|
||||
BooleanSetting disableSpecializedShaders = null;
|
||||
BooleanSetting backgroundShaderCompilation = null;
|
||||
|
||||
switch (which)
|
||||
{
|
||||
case 0:
|
||||
disableSpecializedShaders = new BooleanSetting(SettingsFile.KEY_DISABLE_SPECIALIZED_SHADERS, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, false);
|
||||
backgroundShaderCompilation = new BooleanSetting(SettingsFile.KEY_BACKGROUND_SHADER_COMPILING, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, false);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
disableSpecializedShaders = new BooleanSetting(SettingsFile.KEY_DISABLE_SPECIALIZED_SHADERS, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, true);
|
||||
backgroundShaderCompilation = new BooleanSetting(SettingsFile.KEY_BACKGROUND_SHADER_COMPILING, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, false);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
disableSpecializedShaders = new BooleanSetting(SettingsFile.KEY_DISABLE_SPECIALIZED_SHADERS, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, true);
|
||||
backgroundShaderCompilation = new BooleanSetting(SettingsFile.KEY_BACKGROUND_SHADER_COMPILING, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, true);
|
||||
break;
|
||||
}
|
||||
|
||||
mView.putSetting(disableSpecializedShaders);
|
||||
mView.putSetting(backgroundShaderCompilation);
|
||||
}
|
||||
|
||||
public void putExtensionSetting(int which, int wiimoteNumber)
|
||||
{
|
||||
StringSetting extension = new StringSetting(SettingsFile.KEY_WIIMOTE_EXTENSION, SettingsFile.SECTION_WIIMOTE + wiimoteNumber,
|
||||
|
||||
+27
@@ -276,6 +276,8 @@ public final class SettingsFragmentPresenter
|
||||
|
||||
private void addEnhanceSettings(ArrayList<SettingsItem> sl)
|
||||
{
|
||||
int uberShaderModeValue = getUberShaderModeValue();
|
||||
|
||||
Setting resolution = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_INTERNAL_RES);
|
||||
Setting fsaa = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_FSAA);
|
||||
Setting anisotropic = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_ENHANCEMENTS).getSetting(SettingsFile.KEY_ANISOTROPY);
|
||||
@@ -283,6 +285,7 @@ public final class SettingsFragmentPresenter
|
||||
Setting perPixel = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_PER_PIXEL);
|
||||
Setting forceFilter = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_ENHANCEMENTS).getSetting(SettingsFile.KEY_FORCE_FILTERING);
|
||||
Setting disableFog = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_DISABLE_FOG);
|
||||
IntSetting uberShaderMode = new IntSetting(SettingsFile.KEY_UBERSHADER_MODE, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, uberShaderModeValue);
|
||||
|
||||
sl.add(new SingleChoiceSetting(SettingsFile.KEY_INTERNAL_RES, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, R.string.internal_resolution, R.string.internal_resolution_descrip, R.array.internalResolutionEntries, R.array.internalResolutionValues, 0, resolution));
|
||||
sl.add(new SingleChoiceSetting(SettingsFile.KEY_FSAA, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, R.string.FSAA, R.string.FSAA_descrip, R.array.FSAAEntries, R.array.FSAAValues, 0, fsaa));
|
||||
@@ -296,6 +299,7 @@ public final class SettingsFragmentPresenter
|
||||
sl.add(new CheckBoxSetting(SettingsFile.KEY_PER_PIXEL, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, R.string.per_pixel_lighting, R.string.per_pixel_lighting_descrip, false, perPixel));
|
||||
sl.add(new CheckBoxSetting(SettingsFile.KEY_FORCE_FILTERING, SettingsFile.SECTION_GFX_ENHANCEMENTS, SettingsFile.SETTINGS_GFX, R.string.force_texture_filtering, R.string.force_texture_filtering_descrip, false, forceFilter));
|
||||
sl.add(new CheckBoxSetting(SettingsFile.KEY_DISABLE_FOG, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, R.string.disable_fog, R.string.disable_fog_descrip, false, disableFog));
|
||||
sl.add(new SingleChoiceSetting(SettingsFile.KEY_UBERSHADER_MODE, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, R.string.ubershader_mode, R.string.ubershader_mode_descrip, R.array.uberShaderModeEntries, R.array.uberShaderModeValues, 0, uberShaderMode));
|
||||
|
||||
/*
|
||||
Check if we support stereo
|
||||
@@ -903,6 +907,29 @@ public final class SettingsFragmentPresenter
|
||||
return xfbValue;
|
||||
}
|
||||
|
||||
private int getUberShaderModeValue()
|
||||
{
|
||||
int uberShaderModeValue = 0;
|
||||
|
||||
try
|
||||
{
|
||||
boolean backgroundShaderCompiling = ((BooleanSetting) mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_BACKGROUND_SHADER_COMPILING)).getValue();
|
||||
boolean disableSpecializedShaders = ((BooleanSetting) mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_DISABLE_SPECIALIZED_SHADERS)).getValue();
|
||||
|
||||
if (disableSpecializedShaders)
|
||||
uberShaderModeValue = 2; // Exclusive
|
||||
else if (backgroundShaderCompiling)
|
||||
uberShaderModeValue = 1; // Hybrid
|
||||
else
|
||||
uberShaderModeValue = 0; // Disabled
|
||||
}
|
||||
catch (NullPointerException ex)
|
||||
{
|
||||
}
|
||||
|
||||
return uberShaderModeValue;
|
||||
}
|
||||
|
||||
private int getExtensionValue(int wiimoteNumber)
|
||||
{
|
||||
int extensionValue;
|
||||
|
||||
@@ -79,6 +79,9 @@ public final class SettingsFile
|
||||
public static final String KEY_XFB_REAL = "UseRealXFB";
|
||||
public static final String KEY_FAST_DEPTH = "FastDepthCalc";
|
||||
public static final String KEY_ASPECT_RATIO = "AspectRatio";
|
||||
public static final String KEY_UBERSHADER_MODE = "UberShaderMode";
|
||||
public static final String KEY_DISABLE_SPECIALIZED_SHADERS = "DisableSpecializedShaders";
|
||||
public static final String KEY_BACKGROUND_SHADER_COMPILING = "BackgroundShaderCompiling";
|
||||
|
||||
public static final String KEY_GCPAD_TYPE = "SIDevice";
|
||||
|
||||
|
||||
@@ -89,6 +89,18 @@
|
||||
<item>2</item>
|
||||
</integer-array>
|
||||
|
||||
<!-- Ubershader Mode Preference -->
|
||||
<string-array name="uberShaderModeEntries" translatable="false">
|
||||
<item>Disabled</item>
|
||||
<item>Hybrid</item>
|
||||
<item>Exclusive</item>
|
||||
</string-array>
|
||||
<integer-array name="uberShaderModeValues" translatable="false">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
</integer-array>
|
||||
|
||||
<!-- Internal Resolution Preference -->
|
||||
<string-array name="internalResolutionEntries" translatable="false">
|
||||
<item>1x Native (640x528)</item>
|
||||
|
||||
@@ -179,6 +179,8 @@
|
||||
<string name="fast_depth_calculation_descrip">Uses a less accurate algorithm to calculate depth values.</string>
|
||||
<string name="aspect_ratio">Aspect Ratio</string>
|
||||
<string name="aspect_ratio_descrip">Select what aspect ratio to use when rendering</string>
|
||||
<string name="ubershader_mode">Ubershader Mode</string>
|
||||
<string name="ubershader_mode_descrip">Specifies when to use Ubershaders. Disabled - Never, Hybrid - Use ubershaders while compiling specialized shaders. Exclusive - Use only ubershaders, largest performance impact.</string>
|
||||
|
||||
<!-- Miscellaneous -->
|
||||
<string name="yes">Yes</string>
|
||||
|
||||
@@ -77,6 +77,20 @@ const ConfigInfo<bool> GFX_BACKEND_MULTITHREADING{
|
||||
const ConfigInfo<int> GFX_COMMAND_BUFFER_EXECUTE_INTERVAL{
|
||||
{System::GFX, "Settings", "CommandBufferExecuteInterval"}, 100};
|
||||
const ConfigInfo<bool> GFX_SHADER_CACHE{{System::GFX, "Settings", "ShaderCache"}, true};
|
||||
const ConfigInfo<bool> GFX_BACKGROUND_SHADER_COMPILING{
|
||||
{System::GFX, "Settings", "BackgroundShaderCompiling"}, false};
|
||||
const ConfigInfo<bool> GFX_DISABLE_SPECIALIZED_SHADERS{
|
||||
{System::GFX, "Settings", "DisableSpecializedShaders"}, false};
|
||||
const ConfigInfo<bool> GFX_PRECOMPILE_UBER_SHADERS{
|
||||
{System::GFX, "Settings", "PrecompileUberShaders"}, true};
|
||||
const ConfigInfo<int> GFX_SHADER_COMPILER_THREADS{
|
||||
{System::GFX, "Settings", "ShaderCompilerThreads"}, 1};
|
||||
const ConfigInfo<int> GFX_SHADER_PRECOMPILER_THREADS{
|
||||
{System::GFX, "Settings", "ShaderPrecompilerThreads"}, 1};
|
||||
const ConfigInfo<bool> GFX_FORCE_VERTEX_UBER_SHADERS{
|
||||
{System::GFX, "Settings", "ForceVertexUberShaders"}, false};
|
||||
const ConfigInfo<bool> GFX_FORCE_PIXEL_UBER_SHADERS{
|
||||
{System::GFX, "Settings", "ForcePixelUberShaders"}, false};
|
||||
|
||||
const ConfigInfo<bool> GFX_SW_ZCOMPLOC{{System::GFX, "Settings", "SWZComploc"}, true};
|
||||
const ConfigInfo<bool> GFX_SW_ZFREEZE{{System::GFX, "Settings", "SWZFreeze"}, true};
|
||||
|
||||
@@ -59,6 +59,13 @@ extern const ConfigInfo<bool> GFX_ENABLE_VALIDATION_LAYER;
|
||||
extern const ConfigInfo<bool> GFX_BACKEND_MULTITHREADING;
|
||||
extern const ConfigInfo<int> GFX_COMMAND_BUFFER_EXECUTE_INTERVAL;
|
||||
extern const ConfigInfo<bool> GFX_SHADER_CACHE;
|
||||
extern const ConfigInfo<bool> GFX_BACKGROUND_SHADER_COMPILING;
|
||||
extern const ConfigInfo<bool> GFX_DISABLE_SPECIALIZED_SHADERS;
|
||||
extern const ConfigInfo<bool> GFX_PRECOMPILE_UBER_SHADERS;
|
||||
extern const ConfigInfo<int> GFX_SHADER_COMPILER_THREADS;
|
||||
extern const ConfigInfo<int> GFX_SHADER_PRECOMPILER_THREADS;
|
||||
extern const ConfigInfo<bool> GFX_FORCE_VERTEX_UBER_SHADERS;
|
||||
extern const ConfigInfo<bool> GFX_FORCE_PIXEL_UBER_SHADERS;
|
||||
|
||||
extern const ConfigInfo<bool> GFX_SW_ZCOMPLOC;
|
||||
extern const ConfigInfo<bool> GFX_SW_ZFREEZE;
|
||||
|
||||
@@ -43,6 +43,11 @@ bool IsSettingSaveable(const Config::ConfigLocation& config_location)
|
||||
Config::GFX_DISABLE_FOG.location, Config::GFX_BORDERLESS_FULLSCREEN.location,
|
||||
Config::GFX_ENABLE_VALIDATION_LAYER.location, Config::GFX_BACKEND_MULTITHREADING.location,
|
||||
Config::GFX_COMMAND_BUFFER_EXECUTE_INTERVAL.location, Config::GFX_SHADER_CACHE.location,
|
||||
Config::GFX_BACKGROUND_SHADER_COMPILING.location,
|
||||
Config::GFX_DISABLE_SPECIALIZED_SHADERS.location,
|
||||
Config::GFX_PRECOMPILE_UBER_SHADERS.location, Config::GFX_SHADER_COMPILER_THREADS.location,
|
||||
Config::GFX_SHADER_PRECOMPILER_THREADS.location,
|
||||
Config::GFX_FORCE_VERTEX_UBER_SHADERS.location, Config::GFX_FORCE_PIXEL_UBER_SHADERS.location,
|
||||
|
||||
Config::GFX_SW_ZCOMPLOC.location, Config::GFX_SW_ZFREEZE.location,
|
||||
Config::GFX_SW_DUMP_OBJECTS.location, Config::GFX_SW_DUMP_TEV_STAGES.location,
|
||||
|
||||
@@ -341,6 +341,7 @@ static void CpuThread()
|
||||
{
|
||||
Common::SetCurrentThreadName("CPU-GPU thread");
|
||||
g_video_backend->Video_Prepare();
|
||||
Host_Message(WM_USER_CREATE);
|
||||
}
|
||||
|
||||
// This needs to be delayed until after the video backend is ready.
|
||||
@@ -409,6 +410,7 @@ static void FifoPlayerThread()
|
||||
else
|
||||
{
|
||||
g_video_backend->Video_Prepare();
|
||||
Host_Message(WM_USER_CREATE);
|
||||
Common::SetCurrentThreadName("FIFO-GPU thread");
|
||||
}
|
||||
|
||||
@@ -601,6 +603,7 @@ static void EmuThread(std::unique_ptr<BootParameters> boot)
|
||||
Common::SetCurrentThreadName("Video thread");
|
||||
|
||||
g_video_backend->Video_Prepare();
|
||||
Host_Message(WM_USER_CREATE);
|
||||
|
||||
// Spawn the CPU thread
|
||||
s_cpu_thread = std::thread(cpuThreadFunc);
|
||||
|
||||
@@ -308,6 +308,14 @@ static wxString gpu_texture_decoding_desc =
|
||||
wxTRANSLATE("Enables texture decoding using the GPU instead of the CPU. This may result in "
|
||||
"performance gains in some scenarios, or on systems where the CPU is the "
|
||||
"bottleneck.\n\nIf unsure, leave this unchecked.");
|
||||
static wxString ubershader_desc =
|
||||
wxTRANSLATE("Disabled: Ubershaders are never used. Stuttering will occur during shader "
|
||||
"compilation, but GPU demands are low. Recommended for low-end hardware.\n\n"
|
||||
"Hybrid: Ubershaders will be used to prevent stuttering during shader "
|
||||
"compilation, but traditional shaders will be used when they will not cause "
|
||||
"stuttering. Balances performance and smoothness.\n\n"
|
||||
"Exclusive: Ubershaders will always be used. Only recommended for high-end "
|
||||
"systems.");
|
||||
|
||||
VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
|
||||
: wxDialog(parent, wxID_ANY, wxString::Format(_("Dolphin %s Graphics Configuration"),
|
||||
@@ -561,6 +569,29 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
|
||||
row += 1;
|
||||
}
|
||||
|
||||
// ubershaders
|
||||
{
|
||||
const std::array<wxString, 3> mode_choices = {{_("Disabled"), _("Hybrid"), _("Exclusive")}};
|
||||
|
||||
wxChoice* const choice_mode =
|
||||
new wxChoice(page_enh, wxID_ANY, wxDefaultPosition, wxDefaultSize,
|
||||
static_cast<int>(mode_choices.size()), mode_choices.data());
|
||||
RegisterControl(choice_mode, wxGetTranslation(ubershader_desc));
|
||||
szr_enh->Add(new wxStaticText(page_enh, wxID_ANY, _("Ubershaders:")), wxGBPosition(row, 0),
|
||||
wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
szr_enh->Add(choice_mode, wxGBPosition(row, 1), span2, wxALIGN_CENTER_VERTICAL);
|
||||
row += 1;
|
||||
|
||||
// Determine ubershader mode
|
||||
choice_mode->Bind(wxEVT_CHOICE, &VideoConfigDiag::OnUberShaderModeChanged, this);
|
||||
if (Config::GetBase(Config::GFX_DISABLE_SPECIALIZED_SHADERS))
|
||||
choice_mode->SetSelection(2);
|
||||
else if (Config::GetBase(Config::GFX_BACKGROUND_SHADER_COMPILING))
|
||||
choice_mode->SetSelection(1);
|
||||
else
|
||||
choice_mode->SetSelection(0);
|
||||
}
|
||||
|
||||
// postproc shader
|
||||
if (vconfig.backend_info.bSupportsPostProcessing)
|
||||
{
|
||||
@@ -1326,3 +1357,13 @@ void VideoConfigDiag::OnAAChanged(wxCommandEvent& ev)
|
||||
|
||||
Config::SetBaseOrCurrent(Config::GFX_MSAA, vconfig.backend_info.AAModes[mode]);
|
||||
}
|
||||
|
||||
void VideoConfigDiag::OnUberShaderModeChanged(wxCommandEvent& ev)
|
||||
{
|
||||
// 0: No ubershaders
|
||||
// 1: Hybrid ubershaders
|
||||
// 2: Only ubershaders
|
||||
int mode = ev.GetInt();
|
||||
Config::SetBaseOrCurrent(Config::GFX_BACKGROUND_SHADER_COMPILING, mode == 1);
|
||||
Config::SetBaseOrCurrent(Config::GFX_DISABLE_SPECIALIZED_SHADERS, mode == 2);
|
||||
}
|
||||
|
||||
@@ -140,6 +140,7 @@ protected:
|
||||
void PopulatePostProcessingShaders();
|
||||
void PopulateAAList();
|
||||
void OnAAChanged(wxCommandEvent& ev);
|
||||
void OnUberShaderModeChanged(wxCommandEvent& ev);
|
||||
|
||||
wxChoice* choice_backend;
|
||||
wxChoice* choice_adapter;
|
||||
|
||||
@@ -185,10 +185,9 @@ std::vector<DXGI_SAMPLE_DESC> EnumAAModes(IDXGIAdapter* adapter)
|
||||
ID3D11Device* _device;
|
||||
ID3D11DeviceContext* _context;
|
||||
D3D_FEATURE_LEVEL feat_level;
|
||||
HRESULT hr = PD3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
|
||||
D3D11_CREATE_DEVICE_SINGLETHREADED, supported_feature_levels,
|
||||
NUM_SUPPORTED_FEATURE_LEVELS, D3D11_SDK_VERSION, &_device,
|
||||
&feat_level, &_context);
|
||||
HRESULT hr = PD3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, 0,
|
||||
supported_feature_levels, NUM_SUPPORTED_FEATURE_LEVELS,
|
||||
D3D11_SDK_VERSION, &_device, &feat_level, &_context);
|
||||
if (FAILED(hr) || feat_level == D3D_FEATURE_LEVEL_10_0)
|
||||
{
|
||||
DXGI_SAMPLE_DESC desc;
|
||||
@@ -221,9 +220,9 @@ std::vector<DXGI_SAMPLE_DESC> EnumAAModes(IDXGIAdapter* adapter)
|
||||
D3D_FEATURE_LEVEL GetFeatureLevel(IDXGIAdapter* adapter)
|
||||
{
|
||||
D3D_FEATURE_LEVEL feat_level = D3D_FEATURE_LEVEL_9_1;
|
||||
PD3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, D3D11_CREATE_DEVICE_SINGLETHREADED,
|
||||
supported_feature_levels, NUM_SUPPORTED_FEATURE_LEVELS, D3D11_SDK_VERSION,
|
||||
nullptr, &feat_level, nullptr);
|
||||
PD3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, 0, supported_feature_levels,
|
||||
NUM_SUPPORTED_FEATURE_LEVELS, D3D11_SDK_VERSION, nullptr, &feat_level,
|
||||
nullptr);
|
||||
return feat_level;
|
||||
}
|
||||
|
||||
@@ -311,8 +310,7 @@ HRESULT Create(HWND wnd)
|
||||
// Creating debug devices can sometimes fail if the user doesn't have the correct
|
||||
// version of the DirectX SDK. If it does, simply fallback to a non-debug device.
|
||||
{
|
||||
hr = PD3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
|
||||
D3D11_CREATE_DEVICE_SINGLETHREADED | D3D11_CREATE_DEVICE_DEBUG,
|
||||
hr = PD3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, D3D11_CREATE_DEVICE_DEBUG,
|
||||
supported_feature_levels, NUM_SUPPORTED_FEATURE_LEVELS,
|
||||
D3D11_SDK_VERSION, &device, &featlevel, &context);
|
||||
|
||||
@@ -339,8 +337,7 @@ HRESULT Create(HWND wnd)
|
||||
if (FAILED(hr))
|
||||
#endif
|
||||
{
|
||||
hr = PD3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
|
||||
D3D11_CREATE_DEVICE_SINGLETHREADED, supported_feature_levels,
|
||||
hr = PD3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, 0, supported_feature_levels,
|
||||
NUM_SUPPORTED_FEATURE_LEVELS, D3D11_SDK_VERSION, &device, &featlevel,
|
||||
&context);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace DX11
|
||||
namespace D3D
|
||||
{
|
||||
// bytecode->shader
|
||||
ID3D11VertexShader* CreateVertexShaderFromByteCode(const void* bytecode, unsigned int len)
|
||||
ID3D11VertexShader* CreateVertexShaderFromByteCode(const void* bytecode, size_t len)
|
||||
{
|
||||
ID3D11VertexShader* v_shader;
|
||||
HRESULT hr = D3D::device->CreateVertexShader(bytecode, len, nullptr, &v_shader);
|
||||
@@ -73,7 +73,7 @@ bool CompileVertexShader(const std::string& code, D3DBlob** blob)
|
||||
}
|
||||
|
||||
// bytecode->shader
|
||||
ID3D11GeometryShader* CreateGeometryShaderFromByteCode(const void* bytecode, unsigned int len)
|
||||
ID3D11GeometryShader* CreateGeometryShaderFromByteCode(const void* bytecode, size_t len)
|
||||
{
|
||||
ID3D11GeometryShader* g_shader;
|
||||
HRESULT hr = D3D::device->CreateGeometryShader(bytecode, len, nullptr, &g_shader);
|
||||
@@ -131,7 +131,7 @@ bool CompileGeometryShader(const std::string& code, D3DBlob** blob,
|
||||
}
|
||||
|
||||
// bytecode->shader
|
||||
ID3D11PixelShader* CreatePixelShaderFromByteCode(const void* bytecode, unsigned int len)
|
||||
ID3D11PixelShader* CreatePixelShaderFromByteCode(const void* bytecode, size_t len)
|
||||
{
|
||||
ID3D11PixelShader* p_shader;
|
||||
HRESULT hr = D3D::device->CreatePixelShader(bytecode, len, nullptr, &p_shader);
|
||||
|
||||
@@ -16,9 +16,9 @@ namespace DX11
|
||||
{
|
||||
namespace D3D
|
||||
{
|
||||
ID3D11VertexShader* CreateVertexShaderFromByteCode(const void* bytecode, unsigned int len);
|
||||
ID3D11GeometryShader* CreateGeometryShaderFromByteCode(const void* bytecode, unsigned int len);
|
||||
ID3D11PixelShader* CreatePixelShaderFromByteCode(const void* bytecode, unsigned int len);
|
||||
ID3D11VertexShader* CreateVertexShaderFromByteCode(const void* bytecode, size_t len);
|
||||
ID3D11GeometryShader* CreateGeometryShaderFromByteCode(const void* bytecode, size_t len);
|
||||
ID3D11PixelShader* CreatePixelShaderFromByteCode(const void* bytecode, size_t len);
|
||||
|
||||
// The returned bytecode buffers should be Release()d.
|
||||
bool CompileVertexShader(const std::string& code, D3DBlob** blob);
|
||||
|
||||
@@ -136,7 +136,7 @@ void StateManager::Apply()
|
||||
m_current.pixelConstants[1] != m_pending.pixelConstants[1])
|
||||
{
|
||||
D3D::context->PSSetConstantBuffers(0, m_pending.pixelConstants[1] ? 2 : 1,
|
||||
m_pending.pixelConstants);
|
||||
m_pending.pixelConstants.data());
|
||||
m_current.pixelConstants[0] = m_pending.pixelConstants[0];
|
||||
m_current.pixelConstants[1] = m_pending.pixelConstants[1];
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <stack>
|
||||
#include <unordered_map>
|
||||
@@ -269,9 +270,9 @@ private:
|
||||
|
||||
struct Resources
|
||||
{
|
||||
ID3D11ShaderResourceView* textures[8];
|
||||
ID3D11SamplerState* samplers[8];
|
||||
ID3D11Buffer* pixelConstants[2];
|
||||
std::array<ID3D11ShaderResourceView*, 8> textures;
|
||||
std::array<ID3D11SamplerState*, 8> samplers;
|
||||
std::array<ID3D11Buffer*, 2> pixelConstants;
|
||||
ID3D11Buffer* vertexConstants;
|
||||
ID3D11Buffer* geometryConstants;
|
||||
ID3D11Buffer* vertexBuffer;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoBackends/D3D/D3DShader.h"
|
||||
#include "VideoBackends/D3D/D3DState.h"
|
||||
#include "VideoBackends/D3D/FramebufferManager.h"
|
||||
#include "VideoBackends/D3D/GeometryShaderCache.h"
|
||||
|
||||
@@ -159,6 +160,9 @@ void GeometryShaderCache::Init()
|
||||
|
||||
if (g_ActiveConfig.bShaderCache)
|
||||
LoadShaderCache();
|
||||
|
||||
if (g_ActiveConfig.CanPrecompileUberShaders())
|
||||
PrecompileShaders();
|
||||
}
|
||||
|
||||
void GeometryShaderCache::LoadShaderCache()
|
||||
@@ -175,6 +179,9 @@ void GeometryShaderCache::Reload()
|
||||
|
||||
if (g_ActiveConfig.bShaderCache)
|
||||
LoadShaderCache();
|
||||
|
||||
if (g_ActiveConfig.CanPrecompileUberShaders())
|
||||
PrecompileShaders();
|
||||
}
|
||||
|
||||
// ONLY to be used during shutdown.
|
||||
@@ -203,78 +210,74 @@ void GeometryShaderCache::Shutdown()
|
||||
bool GeometryShaderCache::SetShader(u32 primitive_type)
|
||||
{
|
||||
GeometryShaderUid uid = GetGeometryShaderUid(primitive_type);
|
||||
|
||||
// Check if the shader is already set
|
||||
if (last_entry)
|
||||
if (last_entry && uid == last_uid)
|
||||
{
|
||||
if (uid == last_uid)
|
||||
{
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
|
||||
return true;
|
||||
}
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
|
||||
D3D::stateman->SetGeometryShader(last_entry->shader);
|
||||
return true;
|
||||
}
|
||||
|
||||
last_uid = uid;
|
||||
|
||||
// Check if the shader is a pass-through shader
|
||||
if (uid.GetUidData()->IsPassthrough())
|
||||
{
|
||||
// Return the default pass-through shader
|
||||
last_uid = uid;
|
||||
last_entry = &pass_entry;
|
||||
D3D::stateman->SetGeometryShader(last_entry->shader);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if the shader is already in the cache
|
||||
GSCache::iterator iter;
|
||||
iter = GeometryShaders.find(uid);
|
||||
auto iter = GeometryShaders.find(uid);
|
||||
if (iter != GeometryShaders.end())
|
||||
{
|
||||
const GSCacheEntry& entry = iter->second;
|
||||
last_uid = uid;
|
||||
last_entry = &entry;
|
||||
|
||||
D3D::stateman->SetGeometryShader(last_entry->shader);
|
||||
return (entry.shader != nullptr);
|
||||
}
|
||||
|
||||
// Need to compile a new shader
|
||||
if (CompileShader(uid))
|
||||
return SetShader(primitive_type);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GeometryShaderCache::CompileShader(const GeometryShaderUid& uid)
|
||||
{
|
||||
D3DBlob* bytecode;
|
||||
ShaderCode code =
|
||||
GenerateGeometryShaderCode(APIType::D3D, ShaderHostConfig::GetCurrent(), uid.GetUidData());
|
||||
|
||||
D3DBlob* pbytecode;
|
||||
if (!D3D::CompileGeometryShader(code.GetBuffer(), &pbytecode))
|
||||
if (!D3D::CompileGeometryShader(code.GetBuffer(), &bytecode) ||
|
||||
!InsertByteCode(uid, bytecode->Data(), bytecode->Size()))
|
||||
{
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
|
||||
SAFE_RELEASE(bytecode);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Insert the bytecode into the caches
|
||||
g_gs_disk_cache.Append(uid, pbytecode->Data(), pbytecode->Size());
|
||||
|
||||
bool success = InsertByteCode(uid, pbytecode->Data(), pbytecode->Size());
|
||||
pbytecode->Release();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool GeometryShaderCache::InsertByteCode(const GeometryShaderUid& uid, const void* bytecode,
|
||||
unsigned int bytecodelen)
|
||||
{
|
||||
ID3D11GeometryShader* shader = D3D::CreateGeometryShaderFromByteCode(bytecode, bytecodelen);
|
||||
if (shader == nullptr)
|
||||
return false;
|
||||
|
||||
// TODO: Somehow make the debug name a bit more specific
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)shader, "a pixel shader of GeometryShaderCache");
|
||||
|
||||
// Make an entry in the table
|
||||
GSCacheEntry newentry;
|
||||
newentry.shader = shader;
|
||||
GeometryShaders[uid] = newentry;
|
||||
last_entry = &GeometryShaders[uid];
|
||||
|
||||
if (!shader)
|
||||
return false;
|
||||
|
||||
g_gs_disk_cache.Append(uid, bytecode->Data(), bytecode->Size());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GeometryShaderCache::InsertByteCode(const GeometryShaderUid& uid, const u8* bytecode,
|
||||
size_t len)
|
||||
{
|
||||
GSCacheEntry& newentry = GeometryShaders[uid];
|
||||
newentry.shader = bytecode ? D3D::CreateGeometryShaderFromByteCode(bytecode, len) : nullptr;
|
||||
return newentry.shader != nullptr;
|
||||
}
|
||||
|
||||
void GeometryShaderCache::PrecompileShaders()
|
||||
{
|
||||
EnumerateGeometryShaderUids([](const GeometryShaderUid& uid) {
|
||||
if (GeometryShaders.find(uid) != GeometryShaders.end())
|
||||
return;
|
||||
|
||||
CompileShader(uid);
|
||||
});
|
||||
}
|
||||
|
||||
} // DX11
|
||||
|
||||
@@ -18,14 +18,14 @@ public:
|
||||
static void Reload();
|
||||
static void Clear();
|
||||
static void Shutdown();
|
||||
static bool SetShader(u32 primitive_type); // TODO: Should be renamed to LoadShader
|
||||
static bool InsertByteCode(const GeometryShaderUid& uid, const void* bytecode,
|
||||
unsigned int bytecodelen);
|
||||
static bool SetShader(u32 primitive_type);
|
||||
static bool CompileShader(const GeometryShaderUid& uid);
|
||||
static bool InsertByteCode(const GeometryShaderUid& uid, const u8* bytecode, size_t len);
|
||||
static void PrecompileShaders();
|
||||
|
||||
static ID3D11GeometryShader* GetClearGeometryShader();
|
||||
static ID3D11GeometryShader* GetCopyGeometryShader();
|
||||
|
||||
static ID3D11GeometryShader* GetActiveShader() { return last_entry->shader; }
|
||||
static ID3D11Buffer*& GetConstantBuffer();
|
||||
|
||||
private:
|
||||
|
||||
@@ -13,20 +13,6 @@
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
class D3DVertexFormat : public NativeVertexFormat
|
||||
{
|
||||
public:
|
||||
D3DVertexFormat(const PortableVertexDeclaration& vtx_decl);
|
||||
~D3DVertexFormat() { SAFE_RELEASE(m_layout); }
|
||||
void SetupVertexPointers() override;
|
||||
|
||||
private:
|
||||
std::array<D3D11_INPUT_ELEMENT_DESC, 32> m_elems{};
|
||||
UINT m_num_elems = 0;
|
||||
|
||||
ID3D11InputLayout* m_layout = nullptr;
|
||||
};
|
||||
|
||||
std::unique_ptr<NativeVertexFormat>
|
||||
VertexManager::CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl)
|
||||
{
|
||||
@@ -66,7 +52,6 @@ D3DVertexFormat::D3DVertexFormat(const PortableVertexDeclaration& _vtx_decl)
|
||||
this->vtx_decl = _vtx_decl;
|
||||
|
||||
const AttributeFormat* format = &_vtx_decl.position;
|
||||
|
||||
if (format->enable)
|
||||
{
|
||||
m_elems[m_num_elems].SemanticName = "POSITION";
|
||||
@@ -129,15 +114,18 @@ D3DVertexFormat::D3DVertexFormat(const PortableVertexDeclaration& _vtx_decl)
|
||||
}
|
||||
}
|
||||
|
||||
void D3DVertexFormat::SetupVertexPointers()
|
||||
D3DVertexFormat::~D3DVertexFormat()
|
||||
{
|
||||
SAFE_RELEASE(m_layout);
|
||||
}
|
||||
|
||||
void D3DVertexFormat::SetInputLayout(D3DBlob* vs_bytecode)
|
||||
{
|
||||
if (!m_layout)
|
||||
{
|
||||
// CreateInputLayout requires a shader input, but it only looks at the
|
||||
// signature of the shader, so we don't need to recompute it if the shader
|
||||
// changes.
|
||||
D3DBlob* vs_bytecode = DX11::VertexShaderCache::GetActiveShaderBytecode();
|
||||
|
||||
HRESULT hr = DX11::D3D::device->CreateInputLayout(
|
||||
m_elems.data(), m_num_elems, vs_bytecode->Data(), vs_bytecode->Size(), &m_layout);
|
||||
if (FAILED(hr))
|
||||
|
||||
@@ -8,12 +8,15 @@
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/LinearDiskCache.h"
|
||||
#include "Common/MsgHandler.h"
|
||||
#include "Common/StringUtil.h"
|
||||
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Host.h"
|
||||
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoBackends/D3D/D3DShader.h"
|
||||
#include "VideoBackends/D3D/D3DState.h"
|
||||
#include "VideoBackends/D3D/PixelShaderCache.h"
|
||||
|
||||
#include "VideoCommon/Debugger.h"
|
||||
@@ -25,10 +28,15 @@
|
||||
namespace DX11
|
||||
{
|
||||
PixelShaderCache::PSCache PixelShaderCache::PixelShaders;
|
||||
PixelShaderCache::UberPSCache PixelShaderCache::UberPixelShaders;
|
||||
const PixelShaderCache::PSCacheEntry* PixelShaderCache::last_entry;
|
||||
const PixelShaderCache::PSCacheEntry* PixelShaderCache::last_uber_entry;
|
||||
PixelShaderUid PixelShaderCache::last_uid;
|
||||
UberShader::PixelShaderUid PixelShaderCache::last_uber_uid;
|
||||
|
||||
LinearDiskCache<PixelShaderUid, u8> g_ps_disk_cache;
|
||||
LinearDiskCache<UberShader::PixelShaderUid, u8> g_uber_ps_disk_cache;
|
||||
extern std::unique_ptr<VideoCommon::AsyncShaderCompiler> g_async_compiler;
|
||||
|
||||
ID3D11PixelShader* s_ColorMatrixProgram[2] = {nullptr};
|
||||
ID3D11PixelShader* s_ColorCopyProgram[2] = {nullptr};
|
||||
@@ -429,10 +437,8 @@ ID3D11PixelShader* PixelShaderCache::GetDepthResolveProgram()
|
||||
return s_DepthResolveProgram;
|
||||
}
|
||||
|
||||
ID3D11Buffer*& PixelShaderCache::GetConstantBuffer()
|
||||
static void UpdateConstantBuffers()
|
||||
{
|
||||
// TODO: divide the global variables of the generated shaders into about 5 constant buffers to
|
||||
// speed this up
|
||||
if (PixelShaderManager::dirty)
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
@@ -443,14 +449,20 @@ ID3D11Buffer*& PixelShaderCache::GetConstantBuffer()
|
||||
|
||||
ADDSTAT(stats.thisFrame.bytesUniformStreamed, sizeof(PixelShaderConstants));
|
||||
}
|
||||
}
|
||||
|
||||
ID3D11Buffer* PixelShaderCache::GetConstantBuffer()
|
||||
{
|
||||
UpdateConstantBuffers();
|
||||
return pscbuf;
|
||||
}
|
||||
|
||||
// this class will load the precompiled shaders into our cache
|
||||
class PixelShaderCacheInserter : public LinearDiskCacheReader<PixelShaderUid, u8>
|
||||
template <typename UidType>
|
||||
class PixelShaderCacheInserter : public LinearDiskCacheReader<UidType, u8>
|
||||
{
|
||||
public:
|
||||
void Read(const PixelShaderUid& key, const u8* value, u32 value_size)
|
||||
void Read(const UidType& key, const u8* value, u32 value_size)
|
||||
{
|
||||
PixelShaderCache::InsertByteCode(key, value, value_size);
|
||||
}
|
||||
@@ -499,22 +511,34 @@ void PixelShaderCache::Init()
|
||||
|
||||
if (g_ActiveConfig.bShaderCache)
|
||||
LoadShaderCache();
|
||||
|
||||
if (g_ActiveConfig.CanPrecompileUberShaders())
|
||||
QueueUberShaderCompiles();
|
||||
}
|
||||
|
||||
void PixelShaderCache::LoadShaderCache()
|
||||
{
|
||||
PixelShaderCacheInserter inserter;
|
||||
PixelShaderCacheInserter<PixelShaderUid> inserter;
|
||||
g_ps_disk_cache.OpenAndRead(GetDiskShaderCacheFileName(APIType::D3D, "PS", true, true), inserter);
|
||||
|
||||
PixelShaderCacheInserter<UberShader::PixelShaderUid> uber_inserter;
|
||||
g_uber_ps_disk_cache.OpenAndRead(GetDiskShaderCacheFileName(APIType::D3D, "UberPS", false, true),
|
||||
uber_inserter);
|
||||
}
|
||||
|
||||
void PixelShaderCache::Reload()
|
||||
{
|
||||
g_ps_disk_cache.Sync();
|
||||
g_ps_disk_cache.Close();
|
||||
g_uber_ps_disk_cache.Sync();
|
||||
g_uber_ps_disk_cache.Close();
|
||||
Clear();
|
||||
|
||||
if (g_ActiveConfig.bShaderCache)
|
||||
LoadShaderCache();
|
||||
|
||||
if (g_ActiveConfig.CanPrecompileUberShaders())
|
||||
QueueUberShaderCompiles();
|
||||
}
|
||||
|
||||
// ONLY to be used during shutdown.
|
||||
@@ -522,10 +546,15 @@ void PixelShaderCache::Clear()
|
||||
{
|
||||
for (auto& iter : PixelShaders)
|
||||
iter.second.Destroy();
|
||||
for (auto& iter : UberPixelShaders)
|
||||
iter.second.Destroy();
|
||||
PixelShaders.clear();
|
||||
UberPixelShaders.clear();
|
||||
|
||||
last_entry = nullptr;
|
||||
last_uber_entry = nullptr;
|
||||
last_uid = {};
|
||||
last_uber_uid = {};
|
||||
}
|
||||
|
||||
// Used in Swap() when AA mode has changed
|
||||
@@ -558,82 +587,249 @@ void PixelShaderCache::Shutdown()
|
||||
Clear();
|
||||
g_ps_disk_cache.Sync();
|
||||
g_ps_disk_cache.Close();
|
||||
g_uber_ps_disk_cache.Sync();
|
||||
g_uber_ps_disk_cache.Close();
|
||||
}
|
||||
|
||||
bool PixelShaderCache::SetShader()
|
||||
{
|
||||
PixelShaderUid uid = GetPixelShaderUid();
|
||||
if (g_ActiveConfig.bDisableSpecializedShaders || g_ActiveConfig.bForcePixelUberShaders)
|
||||
return SetUberShader();
|
||||
|
||||
// Check if the shader is already set
|
||||
if (last_entry)
|
||||
PixelShaderUid uid = GetPixelShaderUid();
|
||||
if (last_entry && uid == last_uid)
|
||||
{
|
||||
if (uid == last_uid)
|
||||
{
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
|
||||
return (last_entry->shader != nullptr);
|
||||
}
|
||||
if (last_entry->pending)
|
||||
return SetUberShader();
|
||||
|
||||
if (!last_entry->shader)
|
||||
return false;
|
||||
|
||||
D3D::stateman->SetPixelShader(last_entry->shader);
|
||||
return true;
|
||||
}
|
||||
|
||||
last_uid = uid;
|
||||
|
||||
// Check if the shader is already in the cache
|
||||
PSCache::iterator iter;
|
||||
iter = PixelShaders.find(uid);
|
||||
auto iter = PixelShaders.find(uid);
|
||||
if (iter != PixelShaders.end())
|
||||
{
|
||||
const PSCacheEntry& entry = iter->second;
|
||||
if (entry.pending)
|
||||
return SetUberShader();
|
||||
|
||||
last_uid = uid;
|
||||
last_entry = &entry;
|
||||
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
|
||||
return (entry.shader != nullptr);
|
||||
if (!last_entry->shader)
|
||||
return false;
|
||||
|
||||
D3D::stateman->SetPixelShader(last_entry->shader);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Background compiling?
|
||||
if (g_ActiveConfig.CanBackgroundCompileShaders())
|
||||
{
|
||||
// Create a pending entry
|
||||
PSCacheEntry entry;
|
||||
entry.pending = true;
|
||||
PixelShaders[uid] = entry;
|
||||
|
||||
// Queue normal shader compiling and use ubershader
|
||||
g_async_compiler->QueueWorkItem(
|
||||
g_async_compiler->CreateWorkItem<PixelShaderCompilerWorkItem>(uid));
|
||||
return SetUberShader();
|
||||
}
|
||||
|
||||
// Need to compile a new shader
|
||||
D3DBlob* bytecode = nullptr;
|
||||
ShaderCode code =
|
||||
GeneratePixelShaderCode(APIType::D3D, ShaderHostConfig::GetCurrent(), uid.GetUidData());
|
||||
|
||||
D3DBlob* pbytecode;
|
||||
if (!D3D::CompilePixelShader(code.GetBuffer(), &pbytecode))
|
||||
D3D::CompilePixelShader(code.GetBuffer(), &bytecode);
|
||||
if (!InsertByteCode(uid, bytecode->Data(), bytecode->Size()))
|
||||
{
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
|
||||
SAFE_RELEASE(bytecode);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Insert the bytecode into the caches
|
||||
g_ps_disk_cache.Append(uid, pbytecode->Data(), pbytecode->Size());
|
||||
|
||||
bool success = InsertByteCode(uid, pbytecode->Data(), pbytecode->Size());
|
||||
pbytecode->Release();
|
||||
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
|
||||
return success;
|
||||
g_ps_disk_cache.Append(uid, bytecode->Data(), bytecode->Size());
|
||||
return SetShader();
|
||||
}
|
||||
|
||||
bool PixelShaderCache::InsertByteCode(const PixelShaderUid& uid, const void* bytecode,
|
||||
unsigned int bytecodelen)
|
||||
bool PixelShaderCache::SetUberShader()
|
||||
{
|
||||
ID3D11PixelShader* shader = D3D::CreatePixelShaderFromByteCode(bytecode, bytecodelen);
|
||||
if (shader == nullptr)
|
||||
return false;
|
||||
UberShader::PixelShaderUid uid = UberShader::GetPixelShaderUid();
|
||||
|
||||
// TODO: Somehow make the debug name a bit more specific
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)shader, "a pixel shader of PixelShaderCache");
|
||||
|
||||
// Make an entry in the table
|
||||
PSCacheEntry newentry;
|
||||
newentry.shader = shader;
|
||||
PixelShaders[uid] = newentry;
|
||||
last_entry = &PixelShaders[uid];
|
||||
|
||||
if (!shader)
|
||||
if (last_uber_entry && last_uber_uid == uid)
|
||||
{
|
||||
// INCSTAT(stats.numPixelShadersFailed);
|
||||
if (!last_uber_entry->shader)
|
||||
return false;
|
||||
|
||||
D3D::stateman->SetPixelShader(last_uber_entry->shader);
|
||||
return true;
|
||||
}
|
||||
|
||||
auto iter = UberPixelShaders.find(uid);
|
||||
if (iter != UberPixelShaders.end())
|
||||
{
|
||||
const PSCacheEntry& entry = iter->second;
|
||||
last_uber_uid = uid;
|
||||
last_uber_entry = &entry;
|
||||
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
|
||||
if (!last_uber_entry->shader)
|
||||
return false;
|
||||
|
||||
D3D::stateman->SetPixelShader(last_uber_entry->shader);
|
||||
return true;
|
||||
}
|
||||
|
||||
D3DBlob* bytecode = nullptr;
|
||||
ShaderCode code =
|
||||
UberShader::GenPixelShader(APIType::D3D, ShaderHostConfig::GetCurrent(), uid.GetUidData());
|
||||
D3D::CompilePixelShader(code.GetBuffer(), &bytecode);
|
||||
if (!InsertByteCode(uid, bytecode->Data(), bytecode->Size()))
|
||||
{
|
||||
SAFE_RELEASE(bytecode);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Lookup map again.
|
||||
g_uber_ps_disk_cache.Append(uid, bytecode->Data(), bytecode->Size());
|
||||
bytecode->Release();
|
||||
return SetUberShader();
|
||||
}
|
||||
|
||||
bool PixelShaderCache::InsertByteCode(const PixelShaderUid& uid, const u8* data, size_t len)
|
||||
{
|
||||
ID3D11PixelShader* shader = data ? D3D::CreatePixelShaderFromByteCode(data, len) : nullptr;
|
||||
if (!InsertShader(uid, shader))
|
||||
{
|
||||
SAFE_RELEASE(shader);
|
||||
return false;
|
||||
}
|
||||
|
||||
INCSTAT(stats.numPixelShadersCreated);
|
||||
SETSTAT(stats.numPixelShadersAlive, PixelShaders.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PixelShaderCache::InsertByteCode(const UberShader::PixelShaderUid& uid, const u8* data,
|
||||
size_t len)
|
||||
{
|
||||
ID3D11PixelShader* shader = data ? D3D::CreatePixelShaderFromByteCode(data, len) : nullptr;
|
||||
if (!InsertShader(uid, shader))
|
||||
{
|
||||
SAFE_RELEASE(shader);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PixelShaderCache::InsertShader(const PixelShaderUid& uid, ID3D11PixelShader* shader)
|
||||
{
|
||||
auto iter = PixelShaders.find(uid);
|
||||
if (iter != PixelShaders.end() && !iter->second.pending)
|
||||
return false;
|
||||
|
||||
PSCacheEntry& newentry = PixelShaders[uid];
|
||||
newentry.pending = false;
|
||||
newentry.shader = shader;
|
||||
|
||||
INCSTAT(stats.numPixelShadersCreated);
|
||||
SETSTAT(stats.numPixelShadersAlive, PixelShaders.size());
|
||||
return (shader != nullptr);
|
||||
}
|
||||
|
||||
bool PixelShaderCache::InsertShader(const UberShader::PixelShaderUid& uid,
|
||||
ID3D11PixelShader* shader)
|
||||
{
|
||||
auto iter = UberPixelShaders.find(uid);
|
||||
if (iter != UberPixelShaders.end() && !iter->second.pending)
|
||||
return false;
|
||||
|
||||
PSCacheEntry& newentry = UberPixelShaders[uid];
|
||||
newentry.pending = false;
|
||||
newentry.shader = shader;
|
||||
return (shader != nullptr);
|
||||
}
|
||||
|
||||
void PixelShaderCache::QueueUberShaderCompiles()
|
||||
{
|
||||
UberShader::EnumeratePixelShaderUids([&](const UberShader::PixelShaderUid& uid) {
|
||||
if (UberPixelShaders.find(uid) != UberPixelShaders.end())
|
||||
return;
|
||||
|
||||
g_async_compiler->QueueWorkItem(
|
||||
g_async_compiler->CreateWorkItem<UberPixelShaderCompilerWorkItem>(uid));
|
||||
});
|
||||
|
||||
g_async_compiler->WaitUntilCompletion([](size_t completed, size_t total) {
|
||||
Host_UpdateProgressDialog(GetStringT("Compiling shaders...").c_str(),
|
||||
static_cast<int>(completed), static_cast<int>(total));
|
||||
});
|
||||
g_async_compiler->RetrieveWorkItems();
|
||||
Host_UpdateProgressDialog("", -1, -1);
|
||||
}
|
||||
|
||||
PixelShaderCache::PixelShaderCompilerWorkItem::PixelShaderCompilerWorkItem(
|
||||
const PixelShaderUid& uid)
|
||||
{
|
||||
std::memcpy(&m_uid, &uid, sizeof(uid));
|
||||
}
|
||||
|
||||
PixelShaderCache::PixelShaderCompilerWorkItem::~PixelShaderCompilerWorkItem()
|
||||
{
|
||||
SAFE_RELEASE(m_bytecode);
|
||||
}
|
||||
|
||||
bool PixelShaderCache::PixelShaderCompilerWorkItem::Compile()
|
||||
{
|
||||
ShaderCode code =
|
||||
GeneratePixelShaderCode(APIType::D3D, ShaderHostConfig::GetCurrent(), m_uid.GetUidData());
|
||||
|
||||
if (D3D::CompilePixelShader(code.GetBuffer(), &m_bytecode))
|
||||
m_shader = D3D::CreatePixelShaderFromByteCode(m_bytecode);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PixelShaderCache::PixelShaderCompilerWorkItem::Retrieve()
|
||||
{
|
||||
if (InsertShader(m_uid, m_shader))
|
||||
g_ps_disk_cache.Append(m_uid, m_bytecode->Data(), m_bytecode->Size());
|
||||
else
|
||||
SAFE_RELEASE(m_shader);
|
||||
}
|
||||
|
||||
PixelShaderCache::UberPixelShaderCompilerWorkItem::UberPixelShaderCompilerWorkItem(
|
||||
const UberShader::PixelShaderUid& uid)
|
||||
{
|
||||
std::memcpy(&m_uid, &uid, sizeof(uid));
|
||||
}
|
||||
|
||||
PixelShaderCache::UberPixelShaderCompilerWorkItem::~UberPixelShaderCompilerWorkItem()
|
||||
{
|
||||
SAFE_RELEASE(m_bytecode);
|
||||
}
|
||||
|
||||
bool PixelShaderCache::UberPixelShaderCompilerWorkItem::Compile()
|
||||
{
|
||||
ShaderCode code =
|
||||
UberShader::GenPixelShader(APIType::D3D, ShaderHostConfig::GetCurrent(), m_uid.GetUidData());
|
||||
|
||||
if (D3D::CompilePixelShader(code.GetBuffer(), &m_bytecode))
|
||||
m_shader = D3D::CreatePixelShaderFromByteCode(m_bytecode);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PixelShaderCache::UberPixelShaderCompilerWorkItem::Retrieve()
|
||||
{
|
||||
if (InsertShader(m_uid, m_shader))
|
||||
g_uber_ps_disk_cache.Append(m_uid, m_bytecode->Data(), m_bytecode->Size());
|
||||
else
|
||||
SAFE_RELEASE(m_shader);
|
||||
}
|
||||
|
||||
} // DX11
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user