ShaderGen: Pass host config to shader generation functions

Also moves the host config checks to common.
This commit is contained in:
Stenzek 2017-07-20 17:10:02 +10:00
parent d01b0bf60f
commit 3ea9d86faa
27 changed files with 231 additions and 219 deletions

View File

@ -164,8 +164,7 @@ void GeometryShaderCache::Init()
void GeometryShaderCache::LoadShaderCache()
{
GeometryShaderCacheInserter inserter;
g_gs_disk_cache.OpenAndRead(g_ActiveConfig.GetDiskCacheFileName(APIType::D3D, "GS", true, true),
inserter);
g_gs_disk_cache.OpenAndRead(GetDiskShaderCacheFileName(APIType::D3D, "GS", true, true), inserter);
}
void GeometryShaderCache::Reload()
@ -237,7 +236,8 @@ bool GeometryShaderCache::SetShader(u32 primitive_type)
}
// Need to compile a new shader
ShaderCode code = GenerateGeometryShaderCode(APIType::D3D, uid.GetUidData());
ShaderCode code =
GenerateGeometryShaderCode(APIType::D3D, ShaderHostConfig::GetCurrent(), uid.GetUidData());
D3DBlob* pbytecode;
if (!D3D::CompileGeometryShader(code.GetBuffer(), &pbytecode))

View File

@ -504,8 +504,7 @@ void PixelShaderCache::Init()
void PixelShaderCache::LoadShaderCache()
{
PixelShaderCacheInserter inserter;
g_ps_disk_cache.OpenAndRead(g_ActiveConfig.GetDiskCacheFileName(APIType::D3D, "PS", true, true),
inserter);
g_ps_disk_cache.OpenAndRead(GetDiskShaderCacheFileName(APIType::D3D, "PS", true, true), inserter);
}
void PixelShaderCache::Reload()
@ -590,7 +589,8 @@ bool PixelShaderCache::SetShader()
}
// Need to compile a new shader
ShaderCode code = GeneratePixelShaderCode(APIType::D3D, uid.GetUidData());
ShaderCode code =
GeneratePixelShaderCode(APIType::D3D, ShaderHostConfig::GetCurrent(), uid.GetUidData());
D3DBlob* pbytecode;
if (!D3D::CompilePixelShader(code.GetBuffer(), &pbytecode))

View File

@ -242,7 +242,6 @@ Renderer::Renderer() : ::Renderer(D3D::GetBackBufferWidth(), D3D::GetBackBufferH
s_last_stereo_mode = g_ActiveConfig.iStereoMode > 0;
s_last_xfb_mode = g_ActiveConfig.bUseRealXFB;
s_last_fullscreen_mode = D3D::GetFullscreenState();
m_last_host_config_bits = g_ActiveConfig.GetHostConfigBits();
g_framebuffer_manager = std::make_unique<FramebufferManager>(m_target_width, m_target_height);
SetupDeviceObjects();
@ -895,14 +894,11 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
D3D11_CLEAR_DEPTH, 0.f, 0);
}
u32 new_host_config_bits = g_ActiveConfig.GetHostConfigBits();
if (new_host_config_bits != m_last_host_config_bits)
if (CheckForHostConfigChanges())
{
OSD::AddMessage("Video config changed, reloading shaders.", OSD::Duration::NORMAL);
VertexShaderCache::Reload();
GeometryShaderCache::Reload();
PixelShaderCache::Reload();
m_last_host_config_bits = new_host_config_bits;
}
// begin next frame

View File

@ -64,7 +64,5 @@ public:
private:
void BlitScreen(TargetRectangle src, TargetRectangle dst, D3DTexture2D* src_texture,
u32 src_width, u32 src_height, float Gamma);
u32 m_last_host_config_bits = 0;
};
}

View File

@ -165,8 +165,7 @@ void VertexShaderCache::Init()
void VertexShaderCache::LoadShaderCache()
{
VertexShaderCacheInserter inserter;
g_vs_disk_cache.OpenAndRead(g_ActiveConfig.GetDiskCacheFileName(APIType::D3D, "VS", true, true),
inserter);
g_vs_disk_cache.OpenAndRead(GetDiskShaderCacheFileName(APIType::D3D, "VS", true, true), inserter);
}
void VertexShaderCache::Reload()
@ -229,7 +228,8 @@ bool VertexShaderCache::SetShader()
return (entry.shader != nullptr);
}
ShaderCode code = GenerateVertexShaderCode(APIType::D3D, uid.GetUidData());
ShaderCode code =
GenerateVertexShaderCode(APIType::D3D, ShaderHostConfig::GetCurrent(), uid.GetUidData());
D3DBlob* pbytecode = nullptr;
D3D::CompileVertexShader(code.GetBuffer(), &pbytecode);

View File

@ -46,7 +46,7 @@ protected:
}
ShaderCode GenerateCode(APIType api_type, VertexShaderUid uid) override
{
return GenerateVertexShaderCode(api_type, uid.GetUidData());
return GenerateVertexShaderCode(api_type, ShaderHostConfig::GetCurrent(), uid.GetUidData());
}
};
@ -62,7 +62,7 @@ protected:
}
ShaderCode GenerateCode(APIType api_type, GeometryShaderUid uid) override
{
return GenerateGeometryShaderCode(api_type, uid.GetUidData());
return GenerateGeometryShaderCode(api_type, ShaderHostConfig::GetCurrent(), uid.GetUidData());
}
};
@ -78,7 +78,7 @@ protected:
}
ShaderCode GenerateCode(APIType api_type, PixelShaderUid uid) override
{
return GeneratePixelShaderCode(api_type, uid.GetUidData());
return GeneratePixelShaderCode(api_type, ShaderHostConfig::GetCurrent(), uid.GetUidData());
}
};

View File

@ -217,12 +217,13 @@ SHADER* ProgramShaderCache::SetShader(u32 primitive_type)
last_entry = &newentry;
newentry.in_cache = 0;
ShaderCode vcode = GenerateVertexShaderCode(APIType::OpenGL, uid.vuid.GetUidData());
ShaderCode pcode = GeneratePixelShaderCode(APIType::OpenGL, uid.puid.GetUidData());
ShaderHostConfig host_config = ShaderHostConfig::GetCurrent();
ShaderCode vcode = GenerateVertexShaderCode(APIType::OpenGL, host_config, uid.vuid.GetUidData());
ShaderCode pcode = GeneratePixelShaderCode(APIType::OpenGL, host_config, uid.puid.GetUidData());
ShaderCode gcode;
if (g_ActiveConfig.backend_info.bSupportsGeometryShaders &&
!uid.guid.GetUidData()->IsPassthrough())
gcode = GenerateGeometryShaderCode(APIType::OpenGL, uid.guid.GetUidData());
gcode = GenerateGeometryShaderCode(APIType::OpenGL, host_config, uid.guid.GetUidData());
#if defined(_DEBUG) || defined(DEBUGFAST)
if (g_ActiveConfig.iLog & CONF_SAVESHADERS)
@ -553,7 +554,7 @@ void ProgramShaderCache::LoadProgramBinaries()
else
{
std::string cache_filename =
g_ActiveConfig.GetDiskCacheFileName(APIType::OpenGL, "ProgramBinaries", true, true);
GetDiskShaderCacheFileName(APIType::OpenGL, "ProgramBinaries", true, true);
ProgramShaderCacheInserter inserter;
g_program_disk_cache.OpenAndRead(cache_filename, inserter);
}

View File

@ -43,6 +43,7 @@
#include "VideoCommon/PixelEngine.h"
#include "VideoCommon/PixelShaderManager.h"
#include "VideoCommon/RenderState.h"
#include "VideoCommon/ShaderGenCommon.h"
#include "VideoCommon/VertexShaderManager.h"
#include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoConfig.h"
@ -664,6 +665,9 @@ Renderer::Renderer()
g_Config.VerifyValidity();
UpdateActiveConfig();
// Since we modify the config here, we need to update the last host bits, it may have changed.
m_last_host_config_bits = ShaderHostConfig::GetCurrent().bits;
OSD::AddMessage(StringFromFormat("Video Info: %s, %s, %s", g_ogl_config.gl_vendor,
g_ogl_config.gl_renderer, g_ogl_config.gl_version),
5000);
@ -688,7 +692,6 @@ Renderer::Renderer()
s_last_stereo_mode = g_ActiveConfig.iStereoMode > 0;
s_last_xfb_mode = g_ActiveConfig.bUseRealXFB;
m_last_host_config_bits = g_ActiveConfig.GetHostConfigBits();
// Handle VSync on/off
s_vsync = g_ActiveConfig.IsVSync();
@ -1471,13 +1474,8 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
g_texture_cache->OnConfigChanged(g_ActiveConfig);
// Invalidate shader cache when the host config changes.
u32 new_host_config_bits = g_ActiveConfig.GetHostConfigBits();
if (new_host_config_bits != m_last_host_config_bits)
{
OSD::AddMessage("Video config changed, reloading shaders.", OSD::Duration::NORMAL);
if (CheckForHostConfigChanges())
ProgramShaderCache::Reload();
m_last_host_config_bits = new_host_config_bits;
}
// For testing zbuffer targets.
// Renderer::SetZBufferRender();

View File

@ -148,8 +148,5 @@ private:
std::array<int, 2> m_last_frame_height = {};
bool m_last_frame_exported = false;
AVIDump::Frame m_last_frame_state;
// last host config state
u32 m_last_host_config_bits = 0;
};
}

View File

@ -472,8 +472,7 @@ bool ObjectCache::CreatePipelineCache()
// Vulkan pipeline caches can be shared between games for shader compile time reduction.
// This assumes that drivers don't create all pipelines in the cache on load time, only
// when a lookup occurs that matches a pipeline (or pipeline data) in the cache.
m_pipeline_cache_filename =
g_ActiveConfig.GetDiskCacheFileName(APIType::Vulkan, "Pipeline", false, true);
m_pipeline_cache_filename = GetDiskShaderCacheFileName(APIType::Vulkan, "Pipeline", false, true);
VkPipelineCacheCreateInfo info = {
VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType
@ -496,8 +495,7 @@ bool ObjectCache::LoadPipelineCache()
{
// We have to keep the pipeline cache file name around since when we save it
// we delete the old one, by which time the game's unique ID is already cleared.
m_pipeline_cache_filename =
g_ActiveConfig.GetDiskCacheFileName(APIType::Vulkan, "Pipeline", false, true);
m_pipeline_cache_filename = GetDiskShaderCacheFileName(APIType::Vulkan, "Pipeline", false, true);
std::vector<u8> disk_data;
LinearDiskCache<u32, u8> disk_cache;
@ -663,18 +661,18 @@ struct ShaderCacheReader : public LinearDiskCacheReader<Uid, u32>
void ObjectCache::LoadShaderCaches()
{
ShaderCacheReader<VertexShaderUid> vs_reader(m_vs_cache.shader_map);
m_vs_cache.disk_cache.OpenAndRead(
g_ActiveConfig.GetDiskCacheFileName(APIType::Vulkan, "VS", true, true), vs_reader);
m_vs_cache.disk_cache.OpenAndRead(GetDiskShaderCacheFileName(APIType::Vulkan, "VS", true, true),
vs_reader);
ShaderCacheReader<PixelShaderUid> ps_reader(m_ps_cache.shader_map);
m_ps_cache.disk_cache.OpenAndRead(
g_ActiveConfig.GetDiskCacheFileName(APIType::Vulkan, "PS", true, true), ps_reader);
m_ps_cache.disk_cache.OpenAndRead(GetDiskShaderCacheFileName(APIType::Vulkan, "PS", true, true),
ps_reader);
if (g_vulkan_context->SupportsGeometryShaders())
{
ShaderCacheReader<GeometryShaderUid> gs_reader(m_gs_cache.shader_map);
m_gs_cache.disk_cache.OpenAndRead(
g_ActiveConfig.GetDiskCacheFileName(APIType::Vulkan, "GS", true, true), gs_reader);
m_gs_cache.disk_cache.OpenAndRead(GetDiskShaderCacheFileName(APIType::Vulkan, "GS", true, true),
gs_reader);
}
SETSTAT(stats.numPixelShadersCreated, static_cast<int>(m_ps_cache.shader_map.size()));
@ -719,7 +717,8 @@ VkShaderModule ObjectCache::GetVertexShaderForUid(const VertexShaderUid& uid)
// Not in the cache, so compile the shader.
ShaderCompiler::SPIRVCodeVector spv;
VkShaderModule module = VK_NULL_HANDLE;
ShaderCode source_code = GenerateVertexShaderCode(APIType::Vulkan, uid.GetUidData());
ShaderCode source_code =
GenerateVertexShaderCode(APIType::Vulkan, ShaderHostConfig::GetCurrent(), uid.GetUidData());
if (ShaderCompiler::CompileVertexShader(&spv, source_code.GetBuffer().c_str(),
source_code.GetBuffer().length()))
{
@ -749,7 +748,8 @@ VkShaderModule ObjectCache::GetGeometryShaderForUid(const GeometryShaderUid& uid
// Not in the cache, so compile the shader.
ShaderCompiler::SPIRVCodeVector spv;
VkShaderModule module = VK_NULL_HANDLE;
ShaderCode source_code = GenerateGeometryShaderCode(APIType::Vulkan, uid.GetUidData());
ShaderCode source_code =
GenerateGeometryShaderCode(APIType::Vulkan, ShaderHostConfig::GetCurrent(), uid.GetUidData());
if (ShaderCompiler::CompileGeometryShader(&spv, source_code.GetBuffer().c_str(),
source_code.GetBuffer().length()))
{
@ -774,7 +774,8 @@ VkShaderModule ObjectCache::GetPixelShaderForUid(const PixelShaderUid& uid)
// Not in the cache, so compile the shader.
ShaderCompiler::SPIRVCodeVector spv;
VkShaderModule module = VK_NULL_HANDLE;
ShaderCode source_code = GeneratePixelShaderCode(APIType::Vulkan, uid.GetUidData());
ShaderCode source_code =
GeneratePixelShaderCode(APIType::Vulkan, ShaderHostConfig::GetCurrent(), uid.GetUidData());
if (ShaderCompiler::CompileFragmentShader(&spv, source_code.GetBuffer().c_str(),
source_code.GetBuffer().length()))
{

View File

@ -1126,7 +1126,6 @@ void Renderer::CheckForSurfaceChange()
void Renderer::CheckForConfigChanges()
{
// Save the video config so we can compare against to determine which settings have changed.
u32 old_host_bits = g_ActiveConfig.GetHostConfigBits();
int old_anisotropy = g_ActiveConfig.iMaxAnisotropy;
int old_aspect_ratio = g_ActiveConfig.iAspectRatio;
int old_efb_scale = g_ActiveConfig.iEFBScale;
@ -1140,7 +1139,6 @@ void Renderer::CheckForConfigChanges()
UpdateActiveConfig();
// Determine which (if any) settings have changed.
bool host_bits_changed = old_host_bits != g_ActiveConfig.GetHostConfigBits();
bool anisotropy_changed = old_anisotropy != g_ActiveConfig.iMaxAnisotropy;
bool force_texture_filtering_changed = old_force_filtering != g_ActiveConfig.bForceFiltering;
bool efb_scale_changed = old_efb_scale != g_ActiveConfig.iEFBScale;
@ -1162,9 +1160,8 @@ void Renderer::CheckForConfigChanges()
// If the stereoscopy mode changed, we need to recreate the buffers as well.
// SSAA changed on/off, we have to recompile shaders.
// Changing stereoscopy from off<->on also requires shaders to be recompiled.
if (host_bits_changed)
if (CheckForHostConfigChanges())
{
OSD::AddMessage("Video config changed, reloading shaders.", OSD::Duration::NORMAL);
g_command_buffer_mgr->WaitForGPUIdle();
FramebufferManager::GetInstance()->RecreateRenderPass();
FramebufferManager::GetInstance()->ResizeEFBTextures();

View File

@ -147,8 +147,7 @@ void StateTracker::ReloadPipelineUIDCache()
m_uid_cache.Close();
// UID caches don't contain any host state, so use a single uid cache per gameid.
std::string filename =
g_ActiveConfig.GetDiskCacheFileName(APIType::Vulkan, "PipelineUID", true, false);
std::string filename = GetDiskShaderCacheFileName(APIType::Vulkan, "PipelineUID", true, false);
if (g_ActiveConfig.bShaderCache)
{
PipelineInserter inserter(this);

View File

@ -29,6 +29,7 @@ set(SRCS
PostProcessing.cpp
RenderBase.cpp
RenderState.cpp
ShaderGenCommon.cpp
Statistics.cpp
TextureCacheBase.cpp
TextureConfig.cpp

View File

@ -37,22 +37,25 @@ GeometryShaderUid GetGeometryShaderUid(u32 primitive_type)
return out;
}
static void EmitVertex(ShaderCode& out, const geometry_shader_uid_data* uid_data,
const char* vertex, APIType ApiType, bool wireframe, bool pixel_lighting,
static void EmitVertex(ShaderCode& out, const ShaderHostConfig& host_config,
const geometry_shader_uid_data* uid_data, const char* vertex,
APIType ApiType, bool wireframe, bool pixel_lighting,
bool first_vertex = false);
static void EndPrimitive(ShaderCode& out, const geometry_shader_uid_data* uid_data, APIType ApiType,
bool wireframe, bool pixel_lighting);
static void EndPrimitive(ShaderCode& out, const ShaderHostConfig& host_config,
const geometry_shader_uid_data* uid_data, APIType ApiType, bool wireframe,
bool pixel_lighting);
ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid_data* uid_data)
ShaderCode GenerateGeometryShaderCode(APIType ApiType, const ShaderHostConfig& host_config,
const geometry_shader_uid_data* uid_data)
{
ShaderCode out;
// Non-uid template parameters will write to the dummy data (=> gets optimized out)
const bool wireframe = g_ActiveConfig.bWireFrame;
const bool wireframe = host_config.wireframe;
const bool pixel_lighting = g_ActiveConfig.bEnablePixelLighting;
const bool msaa = g_ActiveConfig.IsMSAAEnabled();
const bool ssaa = g_ActiveConfig.IsSSAAEnabled();
const bool stereo = g_ActiveConfig.IsStereoEnabled();
const bool msaa = host_config.msaa;
const bool ssaa = host_config.ssaa;
const bool stereo = host_config.stereo;
const unsigned int vertex_in = uid_data->primitive_type + 1;
unsigned int vertex_out = uid_data->primitive_type == PRIMITIVE_TRIANGLES ? 3 : 4;
@ -62,7 +65,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid
if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
{
// Insert layout parameters
if (g_ActiveConfig.backend_info.bSupportsGSInstancing)
if (host_config.backend_gs_instancing)
{
out.Write("layout(%s, invocations = %d) in;\n", primitives_ogl[uid_data->primitive_type],
stereo ? 2 : 1);
@ -96,7 +99,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid
if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
{
if (g_ActiveConfig.backend_info.bSupportsGSInstancing)
if (host_config.backend_gs_instancing)
out.Write("#define InstanceID gl_InvocationID\n");
out.Write("VARYING_LOCATION(0) in VertexData {\n");
@ -125,7 +128,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid
out.Write("};\n");
if (g_ActiveConfig.backend_info.bSupportsGSInstancing)
if (host_config.backend_gs_instancing)
{
out.Write("[maxvertexcount(%d)]\n[instance(%d)]\n", vertex_out, stereo ? 2 : 1);
out.Write("void main(%s VS_OUTPUT o[%d], inout %sStream<VertexData> output, in uint "
@ -197,7 +200,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid
{
// If the GPU supports invocation we don't need a for loop and can simply use the
// invocation identifier to determine which layer we're rendering.
if (g_ActiveConfig.backend_info.bSupportsGSInstancing)
if (host_config.backend_gs_instancing)
out.Write("\tint eye = InstanceID;\n");
else
out.Write("\tfor (int eye = 0; eye < 2; ++eye) {\n");
@ -213,7 +216,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid
out.Write("\tVS_OUTPUT f;\n");
AssignVSOutputMembers(out, "f", "vs[i]", uid_data->numTexGens, pixel_lighting);
if (g_ActiveConfig.backend_info.bSupportsDepthClamp &&
if (host_config.backend_depth_clamp &&
DriverDetails::HasBug(DriverDetails::BUG_BROKEN_CLIP_DISTANCE))
{
// On certain GPUs we have to consume the clip distance from the vertex shader
@ -263,8 +266,8 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid
}
out.Write("\t}\n");
EmitVertex(out, uid_data, "l", ApiType, wireframe, pixel_lighting, true);
EmitVertex(out, uid_data, "r", ApiType, wireframe, pixel_lighting);
EmitVertex(out, host_config, uid_data, "l", ApiType, wireframe, pixel_lighting, true);
EmitVertex(out, host_config, uid_data, "r", ApiType, wireframe, pixel_lighting);
}
else if (uid_data->primitive_type == PRIMITIVE_POINTS)
{
@ -292,21 +295,21 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid
}
out.Write("\t}\n");
EmitVertex(out, uid_data, "ll", ApiType, wireframe, pixel_lighting, true);
EmitVertex(out, uid_data, "lr", ApiType, wireframe, pixel_lighting);
EmitVertex(out, uid_data, "ul", ApiType, wireframe, pixel_lighting);
EmitVertex(out, uid_data, "ur", ApiType, wireframe, pixel_lighting);
EmitVertex(out, host_config, uid_data, "ll", ApiType, wireframe, pixel_lighting, true);
EmitVertex(out, host_config, uid_data, "lr", ApiType, wireframe, pixel_lighting);
EmitVertex(out, host_config, uid_data, "ul", ApiType, wireframe, pixel_lighting);
EmitVertex(out, host_config, uid_data, "ur", ApiType, wireframe, pixel_lighting);
}
else
{
EmitVertex(out, uid_data, "f", ApiType, wireframe, pixel_lighting, true);
EmitVertex(out, host_config, uid_data, "f", ApiType, wireframe, pixel_lighting, true);
}
out.Write("\t}\n");
EndPrimitive(out, uid_data, ApiType, wireframe, pixel_lighting);
EndPrimitive(out, host_config, uid_data, ApiType, wireframe, pixel_lighting);
if (stereo && !g_ActiveConfig.backend_info.bSupportsGSInstancing)
if (stereo && !host_config.backend_gs_instancing)
out.Write("\t}\n");
out.Write("}\n");
@ -314,9 +317,9 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid
return out;
}
static void EmitVertex(ShaderCode& out, const geometry_shader_uid_data* uid_data,
const char* vertex, APIType ApiType, bool wireframe, bool pixel_lighting,
bool first_vertex)
static void EmitVertex(ShaderCode& out, const ShaderHostConfig& host_config,
const geometry_shader_uid_data* uid_data, const char* vertex,
APIType ApiType, bool wireframe, bool pixel_lighting, bool first_vertex)
{
if (wireframe && first_vertex)
out.Write("\tif (i == 0) first = %s;\n", vertex);
@ -324,7 +327,7 @@ static void EmitVertex(ShaderCode& out, const geometry_shader_uid_data* uid_data
if (ApiType == APIType::OpenGL)
{
out.Write("\tgl_Position = %s.pos;\n", vertex);
if (g_ActiveConfig.backend_info.bSupportsDepthClamp)
if (host_config.backend_depth_clamp)
{
out.Write("\tgl_ClipDistance[0] = %s.clipDist0;\n", vertex);
out.Write("\tgl_ClipDistance[1] = %s.clipDist1;\n", vertex);
@ -349,11 +352,12 @@ static void EmitVertex(ShaderCode& out, const geometry_shader_uid_data* uid_data
out.Write("\toutput.Append(ps);\n");
}
static void EndPrimitive(ShaderCode& out, const geometry_shader_uid_data* uid_data, APIType ApiType,
bool wireframe, bool pixel_lighting)
static void EndPrimitive(ShaderCode& out, const ShaderHostConfig& host_config,
const geometry_shader_uid_data* uid_data, APIType ApiType, bool wireframe,
bool pixel_lighting)
{
if (wireframe)
EmitVertex(out, uid_data, "first", ApiType, wireframe, pixel_lighting);
EmitVertex(out, host_config, uid_data, "first", ApiType, wireframe, pixel_lighting);
if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
out.Write("\tEndPrimitive();\n");

View File

@ -25,5 +25,6 @@ struct geometry_shader_uid_data
typedef ShaderUid<geometry_shader_uid_data> GeometryShaderUid;
ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid_data* uid_data);
ShaderCode GenerateGeometryShaderCode(APIType ApiType, const ShaderHostConfig& host_config,
const geometry_shader_uid_data* uid_data);
GeometryShaderUid GetGeometryShaderUid(u32 primitive_type);

View File

@ -345,14 +345,15 @@ static void WriteFog(ShaderCode& out, const pixel_shader_uid_data* uid_data);
static void WriteColor(ShaderCode& out, const pixel_shader_uid_data* uid_data,
bool use_dual_source);
ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data* uid_data)
ShaderCode GeneratePixelShaderCode(APIType ApiType, const ShaderHostConfig& host_config,
const pixel_shader_uid_data* uid_data)
{
ShaderCode out;
const bool per_pixel_lighting = g_ActiveConfig.bEnablePixelLighting;
const bool msaa = g_ActiveConfig.IsMSAAEnabled();
const bool ssaa = g_ActiveConfig.IsSSAAEnabled();
const bool stereo = g_ActiveConfig.IsStereoEnabled();
const bool msaa = host_config.msaa;
const bool ssaa = host_config.ssaa;
const bool stereo = host_config.stereo;
const u32 numStages = uid_data->genMode_numtevstages + 1;
out.Write("//Pixel Shader for TEV stages\n");
@ -501,7 +502,7 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data*
// Only use dual-source blending when required on drivers that don't support it very well.
const bool use_dual_source =
g_ActiveConfig.backend_info.bSupportsDualSourceBlend &&
host_config.backend_dual_source_blend &&
(!DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DUAL_SOURCE_BLENDING) ||
uid_data->useDstAlpha);
@ -529,7 +530,7 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data*
out.Write("#define depth gl_FragDepth\n");
// We need to always use output blocks for Vulkan, but geometry shaders are also optional.
if (g_ActiveConfig.backend_info.bSupportsGeometryShaders || ApiType == APIType::Vulkan)
if (host_config.backend_geometry_shaders || ApiType == APIType::Vulkan)
{
out.Write("VARYING_LOCATION(0) in VertexData {\n");
GenerateVSOutputMembers(out, ApiType, uid_data->genMode_numtexgens, per_pixel_lighting,
@ -560,7 +561,7 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data*
out.Write("void main()\n{\n");
if (g_ActiveConfig.backend_info.bSupportsGeometryShaders || ApiType == APIType::Vulkan)
if (host_config.backend_geometry_shaders || ApiType == APIType::Vulkan)
{
for (unsigned int i = 0; i < uid_data->genMode_numtexgens; ++i)
out.Write("\tfloat3 uv%d = tex%d;\n", i, i);
@ -713,7 +714,7 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data*
out.Write("\tint zCoord = int(" I_ZSLOPE ".z + " I_ZSLOPE ".x * screenpos.x + " I_ZSLOPE
".y * screenpos.y);\n");
}
else if (!g_ActiveConfig.bFastDepthCalc)
else if (!host_config.fast_depth_calc)
{
// FastDepth means to trust the depth generated in perspective division.
// It should be correct, but it seems not to be as accurate as required. TODO: Find out why!

View File

@ -157,5 +157,6 @@ struct pixel_shader_uid_data
typedef ShaderUid<pixel_shader_uid_data> PixelShaderUid;
ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data* uid_data);
ShaderCode GeneratePixelShaderCode(APIType ApiType, const ShaderHostConfig& host_config,
const pixel_shader_uid_data* uid_data);
PixelShaderUid GetPixelShaderUid();

View File

@ -52,6 +52,7 @@
#include "VideoCommon/OnScreenDisplay.h"
#include "VideoCommon/PixelShaderManager.h"
#include "VideoCommon/PostProcessing.h"
#include "VideoCommon/ShaderGenCommon.h"
#include "VideoCommon/Statistics.h"
#include "VideoCommon/TextureCacheBase.h"
#include "VideoCommon/TextureDecoder.h"
@ -96,6 +97,8 @@ Renderer::Renderer(int backbuffer_width, int backbuffer_height)
{
m_aspect_wide = SConfig::GetInstance().m_wii_aspect_ratio != 0;
}
m_last_host_config_bits = ShaderHostConfig::GetCurrent().bits;
}
Renderer::~Renderer()
@ -315,6 +318,17 @@ void Renderer::SaveScreenshot(const std::string& filename, bool wait_for_complet
}
}
bool Renderer::CheckForHostConfigChanges()
{
ShaderHostConfig new_host_config = ShaderHostConfig::GetCurrent();
if (new_host_config.bits == m_last_host_config_bits)
return false;
OSD::AddMessage("Video config changed, reloading shaders.", OSD::Duration::NORMAL);
m_last_host_config_bits = new_host_config.bits;
return true;
}
// Create On-Screen-Messages
void Renderer::DrawDebugText()
{

View File

@ -147,6 +147,8 @@ protected:
std::tuple<int, int> CalculateTargetScale(int x, int y) const;
bool CalculateTargetSize();
bool CheckForHostConfigChanges();
void CheckFifoRecording();
void RecordVideoMemory();
@ -182,6 +184,8 @@ protected:
Common::Event m_surface_changed;
void* m_new_surface_handle = nullptr;
u32 m_last_host_config_bits = 0;
private:
void RunFrameDumps();
void ShutdownFrameDumping();

View File

@ -0,0 +1,75 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "VideoCommon/ShaderGenCommon.h"
#include "Common/CommonPaths.h"
#include "Common/FileUtil.h"
#include "Core/ConfigManager.h"
ShaderHostConfig ShaderHostConfig::GetCurrent()
{
ShaderHostConfig bits = {};
bits.msaa = g_ActiveConfig.iMultisamples > 1;
bits.ssaa = g_ActiveConfig.iMultisamples > 1 && g_ActiveConfig.bSSAA &&
g_ActiveConfig.backend_info.bSupportsSSAA;
bits.stereo = g_ActiveConfig.iStereoMode > 0;
bits.wireframe = g_ActiveConfig.bWireFrame;
bits.per_pixel_lighting = g_ActiveConfig.bEnablePixelLighting;
bits.vertex_rounding = g_ActiveConfig.UseVertexRounding();
bits.fast_depth_calc = g_ActiveConfig.bFastDepthCalc;
bits.bounding_box = g_ActiveConfig.bBBoxEnable;
bits.backend_dual_source_blend = g_ActiveConfig.backend_info.bSupportsDualSourceBlend;
bits.backend_geometry_shaders = g_ActiveConfig.backend_info.bSupportsGeometryShaders;
bits.backend_early_z = g_ActiveConfig.backend_info.bSupportsEarlyZ;
bits.backend_bbox = g_ActiveConfig.backend_info.bSupportsBBox;
bits.backend_gs_instancing = g_ActiveConfig.backend_info.bSupportsGSInstancing;
bits.backend_clip_control = g_ActiveConfig.backend_info.bSupportsClipControl;
bits.backend_ssaa = g_ActiveConfig.backend_info.bSupportsSSAA;
bits.backend_atomics = g_ActiveConfig.backend_info.bSupportsFragmentStoresAndAtomics;
bits.backend_depth_clamp = g_ActiveConfig.backend_info.bSupportsDepthClamp;
bits.backend_reversed_depth_range = g_ActiveConfig.backend_info.bSupportsReversedDepthRange;
return bits;
}
std::string GetDiskShaderCacheFileName(APIType api_type, const char* type, bool include_gameid,
bool include_host_config)
{
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
std::string filename = File::GetUserPath(D_SHADERCACHE_IDX);
switch (api_type)
{
case APIType::D3D:
filename += "D3D";
break;
case APIType::OpenGL:
filename += "OpenGL";
break;
case APIType::Vulkan:
filename += "Vulkan";
break;
default:
break;
}
filename += '-';
filename += type;
if (include_gameid)
{
filename += '-';
filename += SConfig::GetInstance().GetGameID();
}
if (include_host_config)
{
// We're using 18 bits, so 5 hex characters.
ShaderHostConfig host_config = ShaderHostConfig::GetCurrent();
filename += StringFromFormat("-%05X", host_config.bits);
}
filename += ".cache";
return filename;
}

View File

@ -151,6 +151,41 @@ private:
std::vector<bool> constant_usage; // TODO: Is vector<bool> appropriate here?
};
// Host config contains the settings which can influence generated shaders.
union ShaderHostConfig
{
u32 bits;
struct
{
u32 msaa : 1;
u32 ssaa : 1;
u32 stereo : 1;
u32 wireframe : 1;
u32 per_pixel_lighting : 1;
u32 vertex_rounding : 1;
u32 fast_depth_calc : 1;
u32 bounding_box : 1;
u32 backend_dual_source_blend : 1;
u32 backend_geometry_shaders : 1;
u32 backend_early_z : 1;
u32 backend_bbox : 1;
u32 backend_gs_instancing : 1;
u32 backend_clip_control : 1;
u32 backend_ssaa : 1;
u32 backend_atomics : 1;
u32 backend_depth_clamp : 1;
u32 backend_reversed_depth_range : 1;
u32 pad : 14;
};
static ShaderHostConfig GetCurrent();
};
// Gets the filename of the specified type of cache object (e.g. vertex shader, pipeline).
std::string GetDiskShaderCacheFileName(APIType api_type, const char* type, bool include_gameid,
bool include_host_config);
template <class T>
inline void DefineOutputMember(T& object, APIType api_type, const char* qualifier, const char* type,
const char* name, int var_index, const char* semantic = "",

View File

@ -76,14 +76,15 @@ VertexShaderUid GetVertexShaderUid()
return out;
}
ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_data* uid_data)
ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& host_config,
const vertex_shader_uid_data* uid_data)
{
ShaderCode out;
const bool per_pixel_lighting = g_ActiveConfig.bEnablePixelLighting;
const bool msaa = g_ActiveConfig.IsMSAAEnabled();
const bool ssaa = g_ActiveConfig.IsSSAAEnabled();
const bool vertex_rounding = g_ActiveConfig.UseVertexRounding();
const bool msaa = host_config.msaa;
const bool ssaa = host_config.ssaa;
const bool vertex_rounding = host_config.vertex_rounding;
out.Write("%s", s_lighting_struct);
@ -128,7 +129,7 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da
}
// We need to always use output blocks for Vulkan, but geometry shaders are also optional.
if (g_ActiveConfig.backend_info.bSupportsGeometryShaders || api_type == APIType::Vulkan)
if (host_config.backend_geometry_shaders || api_type == APIType::Vulkan)
{
out.Write("VARYING_LOCATION(0) out VertexData {\n");
GenerateVSOutputMembers(out, api_type, uid_data->numTexGens, per_pixel_lighting,
@ -415,7 +416,7 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da
// If we can disable the incorrect depth clipping planes using depth clamping, then we can do
// our own depth clipping and calculate the depth range before the perspective divide if
// necessary.
if (g_ActiveConfig.backend_info.bSupportsDepthClamp)
if (host_config.backend_depth_clamp)
{
// Since we're adjusting z for the depth range before the perspective divide, we have to do our
// own clipping. We want to clip so that -w <= z <= 0, which matches the console -1..0 range.
@ -440,7 +441,7 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da
out.Write("o.pos.z = o.pos.w * " I_PIXELCENTERCORRECTION ".w - "
"o.pos.z * " I_PIXELCENTERCORRECTION ".z;\n");
if (!g_ActiveConfig.backend_info.bSupportsClipControl)
if (!host_config.backend_clip_control)
{
// If the graphics API doesn't support a depth range of 0..1, then we need to map z to
// the -1..1 range. Unfortunately we have to use a substraction, which is a lossy floating-point
@ -485,7 +486,7 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da
if (api_type == APIType::OpenGL || api_type == APIType::Vulkan)
{
if (g_ActiveConfig.backend_info.bSupportsGeometryShaders || api_type == APIType::Vulkan)
if (host_config.backend_geometry_shaders || api_type == APIType::Vulkan)
{
AssignVSOutputMembers(out, "vs", "o", uid_data->numTexGens, per_pixel_lighting);
}
@ -505,7 +506,7 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da
out.Write("colors_1 = o.colors_1;\n");
}
if (g_ActiveConfig.backend_info.bSupportsDepthClamp)
if (host_config.backend_depth_clamp)
{
out.Write("gl_ClipDistance[0] = o.clipDist0;\n");
out.Write("gl_ClipDistance[1] = o.clipDist1;\n");

View File

@ -65,4 +65,5 @@ struct vertex_shader_uid_data
typedef ShaderUid<vertex_shader_uid_data> VertexShaderUid;
VertexShaderUid GetVertexShaderUid();
ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_data* uid_data);
ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& host_config,
const vertex_shader_uid_data* uid_data);

View File

@ -65,6 +65,7 @@
<ClCompile Include="RenderBase.cpp" />
<ClCompile Include="RenderState.cpp" />
<ClCompile Include="LightingShaderGen.cpp" />
<ClCompile Include="ShaderGenCommon.cpp" />
<ClCompile Include="Statistics.cpp" />
<ClCompile Include="GeometryShaderGen.cpp" />
<ClCompile Include="GeometryShaderManager.cpp" />

View File

@ -173,6 +173,9 @@
<ClCompile Include="AbstractTexture.cpp">
<Filter>Base</Filter>
</ClCompile>
<ClCompile Include="ShaderGenCommon.cpp">
<Filter>Shader Generators</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="CommandProcessor.h" />

View File

@ -4,12 +4,9 @@
#include <algorithm>
#include "Common/CommonPaths.h"
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
#include "Common/StringUtil.h"
#include "Core/Config/GraphicsSettings.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/Movie.h"
#include "VideoCommon/OnScreenDisplay.h"
@ -191,109 +188,3 @@ bool VideoConfig::IsVSync()
{
return bVSync && !Core::GetIsThrottlerTempDisabled();
}
bool VideoConfig::IsStereoEnabled() const
{
return iStereoMode > 0;
}
bool VideoConfig::IsMSAAEnabled() const
{
return iMultisamples > 1;
}
bool VideoConfig::IsSSAAEnabled() const
{
return iMultisamples > 1 && bSSAA && backend_info.bSupportsSSAA;
}
union HostConfigBits
{
u32 bits;
struct
{
u32 msaa : 1;
u32 ssaa : 1;
u32 stereo : 1;
u32 wireframe : 1;
u32 per_pixel_lighting : 1;
u32 vertex_rounding : 1;
u32 fast_depth_calc : 1;
u32 bounding_box : 1;
u32 backend_dual_source_blend : 1;
u32 backend_geometry_shaders : 1;
u32 backend_early_z : 1;
u32 backend_bbox : 1;
u32 backend_gs_instancing : 1;
u32 backend_clip_control : 1;
u32 backend_ssaa : 1;
u32 backend_atomics : 1;
u32 backend_depth_clamp : 1;
u32 backend_reversed_depth_range : 1;
u32 pad : 14;
};
};
u32 VideoConfig::GetHostConfigBits() const
{
HostConfigBits bits = {};
bits.msaa = IsMSAAEnabled();
bits.ssaa = IsSSAAEnabled();
bits.stereo = IsStereoEnabled();
bits.wireframe = bWireFrame;
bits.per_pixel_lighting = bEnablePixelLighting;
bits.vertex_rounding = UseVertexRounding();
bits.fast_depth_calc = bFastDepthCalc;
bits.bounding_box = bBBoxEnable;
bits.backend_dual_source_blend = backend_info.bSupportsDualSourceBlend;
bits.backend_geometry_shaders = backend_info.bSupportsGeometryShaders;
bits.backend_early_z = backend_info.bSupportsEarlyZ;
bits.backend_bbox = backend_info.bSupportsBBox;
bits.backend_gs_instancing = backend_info.bSupportsGSInstancing;
bits.backend_clip_control = backend_info.bSupportsClipControl;
bits.backend_ssaa = backend_info.bSupportsSSAA;
bits.backend_atomics = backend_info.bSupportsFragmentStoresAndAtomics;
bits.backend_depth_clamp = backend_info.bSupportsDepthClamp;
bits.backend_reversed_depth_range = backend_info.bSupportsReversedDepthRange;
return bits.bits;
}
std::string VideoConfig::GetDiskCacheFileName(APIType api_type, const char* type,
bool include_gameid, bool include_host_config) const
{
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
std::string filename = File::GetUserPath(D_SHADERCACHE_IDX);
switch (api_type)
{
case APIType::D3D:
filename += "D3D";
break;
case APIType::OpenGL:
filename += "OpenGL";
break;
case APIType::Vulkan:
filename += "Vulkan";
break;
}
filename += '-';
filename += type;
if (include_gameid)
{
filename += '-';
filename += SConfig::GetInstance().GetGameID();
}
if (include_host_config)
{
// We're using 18 bits, so 5 hex characters.
filename += StringFromFormat("-%05X", GetHostConfigBits());
}
filename += ".cache";
return filename;
}

View File

@ -224,14 +224,6 @@ struct VideoConfig final
return backend_info.bSupportsGPUTextureDecoding && bEnableGPUTextureDecoding;
}
bool UseVertexRounding() const { return bVertexRounding && iEFBScale != SCALE_1X; }
bool IsStereoEnabled() const;
bool IsMSAAEnabled() const;
bool IsSSAAEnabled() const;
// Host config contains the settings which can influence generated shaders.
u32 GetHostConfigBits() const;
// Gets the filename of the specified type of cache object (e.g. vertex shader, pipeline).
std::string GetDiskCacheFileName(APIType api_type, const char* type, bool include_gameid,
bool include_host_config) const;
};
extern VideoConfig g_Config;