Skip to content
Permalink
Browse files
Merge pull request #6399 from stenzek/videocommon-shader-cache
VideoCommon Shader (Pipeline) Cache
  • Loading branch information
delroth committed Mar 10, 2018
2 parents 63838c0 + 93ab50c commit a4ef133
Show file tree
Hide file tree
Showing 74 changed files with 1,791 additions and 3,555 deletions.
@@ -11,12 +11,14 @@

std::unique_ptr<cInterfaceBase> GLInterface;

namespace GLUtil
{
void InitInterface()
{
GLInterface = HostGL_CreateGLInterface();
}

GLuint OpenGL_CompileProgram(const std::string& vertexShader, const std::string& fragmentShader)
GLuint CompileProgram(const std::string& vertexShader, const std::string& fragmentShader)
{
// generate objects
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
@@ -100,3 +102,27 @@ GLuint OpenGL_CompileProgram(const std::string& vertexShader, const std::string&

return programID;
}

void EnablePrimitiveRestart()
{
constexpr GLuint PRIMITIVE_RESTART_INDEX = 65535;

if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGLES3)
{
glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
}
else
{
if (GLExtensions::Version() >= 310)
{
glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(PRIMITIVE_RESTART_INDEX);
}
else
{
glEnableClientState(GL_PRIMITIVE_RESTART_NV);
glPrimitiveRestartIndexNV(PRIMITIVE_RESTART_INDEX);
}
}
}
}
@@ -8,12 +8,9 @@

#include "Common/GL/GLExtensions/GLExtensions.h"

#ifndef _WIN32

#include <sys/types.h>

#endif
namespace GLUtil
{
void InitInterface();

// Helpers
GLuint OpenGL_CompileProgram(const std::string& vertexShader, const std::string& fragmentShader);
GLuint CompileProgram(const std::string& vertexShader, const std::string& fragmentShader);
void EnablePrimitiveRestart();
}
@@ -180,13 +180,16 @@ void DolphinAnalytics::MakeBaseBuilder()

static const char* GetUbershaderMode(const VideoConfig& video_config)
{
if (video_config.bDisableSpecializedShaders)
switch (video_config.iUberShaderMode)
{
case UberShaderMode::Exclusive:
return "exclusive";

if (video_config.bBackgroundShaderCompiling)
case UberShaderMode::Hybrid:
return "hybrid";

return "disabled";
case UberShaderMode::Disabled:
default:
return "disabled";
}
}

void DolphinAnalytics::MakePerGameBuilder()
@@ -76,12 +76,10 @@ 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<bool> GFX_WAIT_FOR_SHADERS_BEFORE_STARTING{
{System::GFX, "Settings", "WaitForShadersBeforeStarting"}, false};
const ConfigInfo<int> GFX_UBERSHADER_MODE{{System::GFX, "Settings", "UberShaderMode"},
static_cast<int>(UberShaderMode::Disabled)};
const ConfigInfo<int> GFX_SHADER_COMPILER_THREADS{
{System::GFX, "Settings", "ShaderCompilerThreads"}, 1};
const ConfigInfo<int> GFX_SHADER_PRECOMPILER_THREADS{
@@ -59,9 +59,8 @@ 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<bool> GFX_WAIT_FOR_SHADERS_BEFORE_STARTING;
extern const ConfigInfo<int> GFX_UBERSHADER_MODE;
extern const ConfigInfo<int> GFX_SHADER_COMPILER_THREADS;
extern const ConfigInfo<int> GFX_SHADER_PRECOMPILER_THREADS;

@@ -46,10 +46,8 @@ 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_WAIT_FOR_SHADERS_BEFORE_STARTING.location, Config::GFX_UBERSHADER_MODE.location,
Config::GFX_SHADER_COMPILER_THREADS.location, Config::GFX_SHADER_PRECOMPILER_THREADS.location,

Config::GFX_SW_ZCOMPLOC.location, Config::GFX_SW_ZFREEZE.location,
Config::GFX_SW_DUMP_OBJECTS.location, Config::GFX_SW_DUMP_TEV_STAGES.location,
@@ -63,9 +63,8 @@ void EnhancementsWidget::CreateWidgets()
m_af_combo = new GraphicsChoice({tr("1x"), tr("2x"), tr("4x"), tr("8x"), tr("16x")},
Config::GFX_ENHANCE_MAX_ANISOTROPY);

m_ubershader_combo = new QComboBox;
for (const auto& option : {tr("Disabled"), tr("Hybrid"), tr("Exclusive")})
m_ubershader_combo->addItem(option);
m_ubershader_combo = new GraphicsChoice({tr("Disabled"), tr("Hybrid"), tr("Exclusive")},
Config::GFX_UBERSHADER_MODE);

m_pp_effect = new QComboBox();
m_configure_pp_effect = new QPushButton(tr("Configure"));
@@ -131,9 +130,6 @@ void EnhancementsWidget::ConnectWidgets()
{
connect(m_aa_combo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
[this](int) { SaveSettings(); });
connect(m_ubershader_combo,
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
[this](int) { SaveSettings(); });
connect(m_pp_effect, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
[this](int) { SaveSettings(); });
connect(m_3d_mode, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
@@ -156,13 +152,6 @@ void EnhancementsWidget::LoadSettings()
QString::fromStdString(std::to_string(aa_selection) + "x " + (ssaa ? "SSAA" : "MSAA")));
m_aa_combo->setEnabled(m_aa_combo->count() > 1);

if (Config::GetBase(Config::GFX_DISABLE_SPECIALIZED_SHADERS))
m_ubershader_combo->setCurrentIndex(2);
else if (Config::GetBase(Config::GFX_BACKGROUND_SHADER_COMPILING))
m_ubershader_combo->setCurrentIndex(1);
else
m_ubershader_combo->setCurrentIndex(0);

// Post Processing Shader
std::vector<std::string> shaders =
g_Config.stereo_mode == StereoMode::Anaglyph ?
@@ -220,10 +209,6 @@ void EnhancementsWidget::SaveSettings()

Config::SetBaseOrCurrent(Config::GFX_SSAA, is_ssaa);

int us_value = m_ubershader_combo->currentIndex();
Config::SetBaseOrCurrent(Config::GFX_BACKGROUND_SHADER_COMPILING, us_value == 1);
Config::SetBaseOrCurrent(Config::GFX_DISABLE_SPECIALIZED_SHADERS, us_value == 2);

Config::SetBaseOrCurrent(Config::GFX_ENHANCE_POST_SHADER,
m_pp_effect->currentText().toStdString());

@@ -87,6 +87,8 @@ void GeneralWidget::CreateWidgets()
m_keep_window_top = new QCheckBox(tr("Keep Window on Top"));
m_hide_cursor = new QCheckBox(tr("Hide Mouse Cursor"));
m_render_main_window = new QCheckBox(tr("Render to Main Window"));
m_wait_for_shaders = new GraphicsBool(tr("Immediately Compile Shaders"),
Config::GFX_WAIT_FOR_SHADERS_BEFORE_STARTING);

m_options_box->setLayout(m_options_layout);

@@ -101,6 +103,7 @@ void GeneralWidget::CreateWidgets()

m_options_layout->addWidget(m_hide_cursor, 3, 0);
m_options_layout->addWidget(m_render_main_window, 3, 1);
m_options_layout->addWidget(m_wait_for_shaders, 4, 0);

main_layout->addWidget(m_video_box);
main_layout->addWidget(m_options_box);
@@ -265,6 +268,12 @@ void GeneralWidget::AddDescriptions()
static const char* TR_SHOW_NETPLAY_MESSAGES_DESCRIPTION =
QT_TR_NOOP("When playing on NetPlay, show chat messages, buffer changes and "
"desync alerts.\n\nIf unsure, leave this unchecked.");
static const char* TR_WAIT_FOR_SHADERS_DESCRIPTION = QT_TR_NOOP(
"Waits for all shaders to finish compiling before starting a game. Enabling this "
"option may reduce stuttering or hitching for a short time after the game is "
"started, at the cost of a longer delay before the game starts.\n\nFor systems "
"with two or fewer cores, it is recommended to enable this option, as a large "
"shader queue may reduce frame rates. Otherwise, if unsure, leave this unchecked.");

AddDescription(m_backend_combo, TR_BACKEND_DESCRIPTION);
#ifdef _WIN32
@@ -282,6 +291,7 @@ void GeneralWidget::AddDescriptions()
AddDescription(m_show_messages, TR_SHOW_FPS_DESCRIPTION);
AddDescription(m_keep_window_top, TR_KEEP_WINDOW_ON_TOP_DESCRIPTION);
AddDescription(m_show_messages, TR_SHOW_NETPLAY_MESSAGES_DESCRIPTION);
AddDescription(m_wait_for_shaders, TR_WAIT_FOR_SHADERS_DESCRIPTION);
}
void GeneralWidget::OnBackendChanged(const QString& backend_name)
{
@@ -52,6 +52,7 @@ class GeneralWidget final : public GraphicsWidget
QCheckBox* m_keep_window_top;
QCheckBox* m_hide_cursor;
QCheckBox* m_render_main_window;
QCheckBox* m_wait_for_shaders;

X11Utils::XRRConfiguration* m_xrr_config;
};
@@ -317,6 +317,12 @@ static wxString ubershader_desc =
"stuttering. Balances performance and smoothness.\n\n"
"Exclusive: Ubershaders will always be used. Only recommended for high-end "
"systems.");
static wxString wait_for_shaders_desc =
wxTRANSLATE("Waits for all shaders to finish compiling before starting a game. Enabling this "
"option may reduce stuttering or hitching for a short time after the game is "
"started, at the cost of a longer delay before the game starts.\n\nFor systems "
"with two or fewer cores, it is recommended to enable this option, as a large "
"shader queue may reduce frame rates. Otherwise, if unsure, leave this unchecked.");

VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
: wxDialog(parent, wxID_ANY, wxString::Format(_("Dolphin %s Graphics Configuration"),
@@ -442,6 +448,10 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
wxGetTranslation(backend_multithreading_desc),
Config::GFX_BACKEND_MULTITHREADING));
}

szr_other->Add(CreateCheckBox(page_general, _("Immediately Compile Shaders"),
wxGetTranslation(wait_for_shaders_desc),
Config::GFX_WAIT_FOR_SHADERS_BEFORE_STARTING));
}

wxStaticBoxSizer* const group_basic =
@@ -534,24 +544,13 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
// 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);
szr_enh->Add(CreateChoice(page_enh, Config::GFX_UBERSHADER_MODE,
wxGetTranslation(ubershader_desc), mode_choices.size(),
mode_choices.data()),
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
@@ -1290,13 +1289,3 @@ 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);
}
@@ -139,7 +139,6 @@ class VideoConfigDiag : public wxDialog
void PopulatePostProcessingShaders();
void PopulateAAList();
void OnAAChanged(wxCommandEvent& ev);
void OnUberShaderModeChanged(wxCommandEvent& ev);

wxChoice* choice_backend;
wxChoice* choice_adapter;
@@ -212,6 +212,7 @@ StateCache::~StateCache()

ID3D11SamplerState* StateCache::Get(SamplerState state)
{
std::lock_guard<std::mutex> guard(m_lock);
auto it = m_sampler.find(state.hex);
if (it != m_sampler.end())
return it->second;
@@ -266,6 +267,7 @@ ID3D11SamplerState* StateCache::Get(SamplerState state)

ID3D11BlendState* StateCache::Get(BlendingState state)
{
std::lock_guard<std::mutex> guard(m_lock);
auto it = m_blend.find(state.hex);
if (it != m_blend.end())
return it->second;
@@ -348,6 +350,7 @@ ID3D11BlendState* StateCache::Get(BlendingState state)

ID3D11RasterizerState* StateCache::Get(RasterizationState state)
{
std::lock_guard<std::mutex> guard(m_lock);
auto it = m_raster.find(state.hex);
if (it != m_raster.end())
return it->second;
@@ -372,6 +375,7 @@ ID3D11RasterizerState* StateCache::Get(RasterizationState state)

ID3D11DepthStencilState* StateCache::Get(DepthState state)
{
std::lock_guard<std::mutex> guard(m_lock);
auto it = m_depth.find(state.hex);
if (it != m_depth.end())
return it->second;
@@ -6,6 +6,7 @@

#include <array>
#include <cstddef>
#include <mutex>
#include <unordered_map>

#include "Common/BitField.h"
@@ -35,6 +36,7 @@ class StateCache
std::unordered_map<u32, ID3D11RasterizerState*> m_raster;
std::unordered_map<u32, ID3D11BlendState*> m_blend;
std::unordered_map<SamplerState::StorageType, ID3D11SamplerState*> m_sampler;
std::mutex m_lock;
};

namespace D3D

0 comments on commit a4ef133

Please sign in to comment.