summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_opengl/gl_shader_gen.h
diff options
context:
space:
mode:
authorYuri Kunde Schlesner <yuriks@yuriks.net>2017-04-17 06:43:58 +0200
committerYuri Kunde Schlesner <yuriks@yuriks.net>2017-04-17 06:49:32 +0200
commita6fd4533f64fde7f7f7079a6758c87c995192a5f (patch)
treef69fa10dfc37b87863009aa5d43f393951f6ef8e /src/video_core/renderer_opengl/gl_shader_gen.h
parentOpenGL: Move Attributes enum to a more appropriate file (diff)
downloadyuzu-a6fd4533f64fde7f7f7079a6758c87c995192a5f.tar
yuzu-a6fd4533f64fde7f7f7079a6758c87c995192a5f.tar.gz
yuzu-a6fd4533f64fde7f7f7079a6758c87c995192a5f.tar.bz2
yuzu-a6fd4533f64fde7f7f7079a6758c87c995192a5f.tar.lz
yuzu-a6fd4533f64fde7f7f7079a6758c87c995192a5f.tar.xz
yuzu-a6fd4533f64fde7f7f7079a6758c87c995192a5f.tar.zst
yuzu-a6fd4533f64fde7f7f7079a6758c87c995192a5f.zip
Diffstat (limited to 'src/video_core/renderer_opengl/gl_shader_gen.h')
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.h111
1 files changed, 109 insertions, 2 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.h b/src/video_core/renderer_opengl/gl_shader_gen.h
index 7ec3bb53f..e01bd34f9 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.h
+++ b/src/video_core/renderer_opengl/gl_shader_gen.h
@@ -4,9 +4,12 @@
#pragma once
+#include <array>
+#include <cstring>
+#include <functional>
#include <string>
-
-union PicaShaderConfig;
+#include <type_traits>
+#include "video_core/regs.h"
namespace GLShader {
@@ -22,6 +25,101 @@ enum Attributes {
};
/**
+ * This struct contains all state used to generate the GLSL shader program that emulates the current
+ * Pica register configuration. This struct is used as a cache key for generated GLSL shader
+ * programs. The functions in gl_shader_gen.cpp should retrieve state from this struct only, not by
+ * directly accessing Pica registers. This should reduce the risk of bugs in shader generation where
+ * Pica state is not being captured in the shader cache key, thereby resulting in (what should be)
+ * two separate shaders sharing the same key.
+ *
+ * We use a union because "implicitly-defined copy/move constructor for a union X copies the object
+ * representation of X." and "implicitly-defined copy assignment operator for a union X copies the
+ * object representation (3.9) of X." = Bytewise copy instead of memberwise copy. This is important
+ * because the padding bytes are included in the hash and comparison between objects.
+ */
+union PicaShaderConfig {
+
+ /// Construct a PicaShaderConfig with the current Pica register configuration.
+ static PicaShaderConfig CurrentConfig();
+
+ bool TevStageUpdatesCombinerBufferColor(unsigned stage_index) const {
+ return (stage_index < 4) && (state.combiner_buffer_input & (1 << stage_index));
+ }
+
+ bool TevStageUpdatesCombinerBufferAlpha(unsigned stage_index) const {
+ return (stage_index < 4) && ((state.combiner_buffer_input >> 4) & (1 << stage_index));
+ }
+
+ bool operator==(const PicaShaderConfig& o) const {
+ return std::memcmp(&state, &o.state, sizeof(PicaShaderConfig::State)) == 0;
+ };
+
+ // NOTE: MSVC15 (Update 2) doesn't think `delete`'d constructors and operators are TC.
+ // This makes BitField not TC when used in a union or struct so we have to resort
+ // to this ugly hack.
+ // Once that bug is fixed we can use Pica::Regs::TevStageConfig here.
+ // Doesn't include const_color because we don't sync it, see comment in CurrentConfig()
+ struct TevStageConfigRaw {
+ u32 sources_raw;
+ u32 modifiers_raw;
+ u32 ops_raw;
+ u32 scales_raw;
+ explicit operator Pica::TexturingRegs::TevStageConfig() const noexcept {
+ Pica::TexturingRegs::TevStageConfig stage;
+ stage.sources_raw = sources_raw;
+ stage.modifiers_raw = modifiers_raw;
+ stage.ops_raw = ops_raw;
+ stage.const_color = 0;
+ stage.scales_raw = scales_raw;
+ return stage;
+ }
+ };
+
+ struct State {
+ Pica::FramebufferRegs::CompareFunc alpha_test_func;
+ Pica::RasterizerRegs::ScissorMode scissor_test_mode;
+ Pica::TexturingRegs::TextureConfig::TextureType texture0_type;
+ std::array<TevStageConfigRaw, 6> tev_stages;
+ u8 combiner_buffer_input;
+
+ Pica::RasterizerRegs::DepthBuffering depthmap_enable;
+ Pica::TexturingRegs::FogMode fog_mode;
+ bool fog_flip;
+
+ struct {
+ struct {
+ unsigned num;
+ bool directional;
+ bool two_sided_diffuse;
+ bool dist_atten_enable;
+ } light[8];
+
+ bool enable;
+ unsigned src_num;
+ Pica::LightingRegs::LightingBumpMode bump_mode;
+ unsigned bump_selector;
+ bool bump_renorm;
+ bool clamp_highlights;
+
+ Pica::LightingRegs::LightingConfig config;
+ Pica::LightingRegs::LightingFresnelSelector fresnel_selector;
+
+ struct {
+ bool enable;
+ bool abs_input;
+ Pica::LightingRegs::LightingLutInput type;
+ float scale;
+ } lut_d0, lut_d1, lut_fr, lut_rr, lut_rg, lut_rb;
+ } lighting;
+
+ } state;
+};
+#if (__GNUC__ >= 5) || defined(__clang__) || defined(_MSC_VER)
+static_assert(std::is_trivially_copyable<PicaShaderConfig::State>::value,
+ "PicaShaderConfig::State must be trivially copyable");
+#endif
+
+/**
* Generates the GLSL vertex shader program source code for the current Pica state
* @returns String of the shader source code
*/
@@ -36,3 +134,12 @@ std::string GenerateVertexShader();
std::string GenerateFragmentShader(const PicaShaderConfig& config);
} // namespace GLShader
+
+namespace std {
+template <>
+struct hash<GLShader::PicaShaderConfig> {
+ size_t operator()(const GLShader::PicaShaderConfig& k) const {
+ return Common::ComputeHash64(&k.state, sizeof(GLShader::PicaShaderConfig::State));
+ }
+};
+} // namespace std