diff options
| author | 2016-05-01 23:28:39 +0200 | |
|---|---|---|
| committer | 2016-05-03 15:06:49 +0200 | |
| commit | f74652d2fe0f1b10ad15066bacd47c9ba00bed09 (patch) | |
| tree | 7daff755ec132058f63df4754daac870210dcbc5 /src | |
| parent | Pica: Add TevStageConfigRaw to PicaShaderConfig (MSVC workaround) (diff) | |
| download | yuzu-f74652d2fe0f1b10ad15066bacd47c9ba00bed09.tar.gz yuzu-f74652d2fe0f1b10ad15066bacd47c9ba00bed09.tar.xz yuzu-f74652d2fe0f1b10ad15066bacd47c9ba00bed09.zip | |
Pica: Use a union for PicaShaderConfig
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 184 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_gen.cpp | 78 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_gen.h | 2 |
3 files changed, 139 insertions, 125 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index cc12a5f62..4f9a032fb 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -39,17 +39,24 @@ struct ScreenInfo; | |||
| 39 | * directly accessing Pica registers. This should reduce the risk of bugs in shader generation where | 39 | * directly accessing Pica registers. This should reduce the risk of bugs in shader generation where |
| 40 | * Pica state is not being captured in the shader cache key, thereby resulting in (what should be) | 40 | * Pica state is not being captured in the shader cache key, thereby resulting in (what should be) |
| 41 | * two separate shaders sharing the same key. | 41 | * two separate shaders sharing the same key. |
| 42 | * | ||
| 43 | * We use a union because "implicitly-defined copy/move constructor for a union X copies the object representation of X." | ||
| 44 | * and "implicitly-defined copy assignment operator for a union X copies the object representation (3.9) of X." | ||
| 45 | * = Bytewise copy instead of memberwise copy. | ||
| 46 | * This is important because the padding bytes are included in the hash and comparison between objects. | ||
| 42 | */ | 47 | */ |
| 43 | struct PicaShaderConfig { | 48 | union PicaShaderConfig { |
| 44 | 49 | ||
| 45 | /// Construct a PicaShaderConfig with the current Pica register configuration. | 50 | /// Construct a PicaShaderConfig with the current Pica register configuration. |
| 46 | static PicaShaderConfig CurrentConfig() { | 51 | static PicaShaderConfig CurrentConfig() { |
| 47 | PicaShaderConfig res; | 52 | PicaShaderConfig res; |
| 48 | std::memset(&res, 0, sizeof(PicaShaderConfig)); | 53 | |
| 54 | auto& state = res.state; | ||
| 55 | std::memset(&state, 0, sizeof(PicaShaderConfig::State)); | ||
| 49 | 56 | ||
| 50 | const auto& regs = Pica::g_state.regs; | 57 | const auto& regs = Pica::g_state.regs; |
| 51 | 58 | ||
| 52 | res.alpha_test_func = regs.output_merger.alpha_test.enable ? | 59 | state.alpha_test_func = regs.output_merger.alpha_test.enable ? |
| 53 | regs.output_merger.alpha_test.func.Value() : Pica::Regs::CompareFunc::Always; | 60 | regs.output_merger.alpha_test.func.Value() : Pica::Regs::CompareFunc::Always; |
| 54 | 61 | ||
| 55 | // Copy relevant tev stages fields. | 62 | // Copy relevant tev stages fields. |
| @@ -59,86 +66,84 @@ struct PicaShaderConfig { | |||
| 59 | DEBUG_ASSERT(res.tev_stages.size() == tev_stages.size()); | 66 | DEBUG_ASSERT(res.tev_stages.size() == tev_stages.size()); |
| 60 | for (size_t i = 0; i < tev_stages.size(); i++) { | 67 | for (size_t i = 0; i < tev_stages.size(); i++) { |
| 61 | const auto& tev_stage = tev_stages[i]; | 68 | const auto& tev_stage = tev_stages[i]; |
| 62 | res.tev_stages[i].sources_raw = tev_stage.sources_raw; | 69 | state.tev_stages[i].sources_raw = tev_stage.sources_raw; |
| 63 | res.tev_stages[i].modifiers_raw = tev_stage.modifiers_raw; | 70 | state.tev_stages[i].modifiers_raw = tev_stage.modifiers_raw; |
| 64 | res.tev_stages[i].ops_raw = tev_stage.ops_raw; | 71 | state.tev_stages[i].ops_raw = tev_stage.ops_raw; |
| 65 | res.tev_stages[i].scales_raw = tev_stage.scales_raw; | 72 | state.tev_stages[i].scales_raw = tev_stage.scales_raw; |
| 66 | } | 73 | } |
| 67 | 74 | ||
| 68 | res.combiner_buffer_input = | 75 | state.combiner_buffer_input = |
| 69 | regs.tev_combiner_buffer_input.update_mask_rgb.Value() | | 76 | regs.tev_combiner_buffer_input.update_mask_rgb.Value() | |
| 70 | regs.tev_combiner_buffer_input.update_mask_a.Value() << 4; | 77 | regs.tev_combiner_buffer_input.update_mask_a.Value() << 4; |
| 71 | 78 | ||
| 72 | // Fragment lighting | 79 | // Fragment lighting |
| 73 | 80 | ||
| 74 | res.lighting.enable = !regs.lighting.disable; | 81 | state.lighting.enable = !regs.lighting.disable; |
| 75 | res.lighting.src_num = regs.lighting.num_lights + 1; | 82 | state.lighting.src_num = regs.lighting.num_lights + 1; |
| 76 | 83 | ||
| 77 | for (unsigned light_index = 0; light_index < res.lighting.src_num; ++light_index) { | 84 | for (unsigned light_index = 0; light_index < state.lighting.src_num; ++light_index) { |
| 78 | unsigned num = regs.lighting.light_enable.GetNum(light_index); | 85 | unsigned num = regs.lighting.light_enable.GetNum(light_index); |
| 79 | const auto& light = regs.lighting.light[num]; | 86 | const auto& light = regs.lighting.light[num]; |
| 80 | res.lighting.light[light_index].num = num; | 87 | state.lighting.light[light_index].num = num; |
| 81 | res.lighting.light[light_index].directional = light.directional != 0; | 88 | state.lighting.light[light_index].directional = light.directional != 0; |
| 82 | res.lighting.light[light_index].two_sided_diffuse = light.two_sided_diffuse != 0; | 89 | state.lighting.light[light_index].two_sided_diffuse = light.two_sided_diffuse != 0; |
| 83 | res.lighting.light[light_index].dist_atten_enable = !regs.lighting.IsDistAttenDisabled(num); | 90 | state.lighting.light[light_index].dist_atten_enable = !regs.lighting.IsDistAttenDisabled(num); |
| 84 | res.lighting.light[light_index].dist_atten_bias = Pica::float20::FromRaw(light.dist_atten_bias).ToFloat32(); | 91 | state.lighting.light[light_index].dist_atten_bias = Pica::float20::FromRaw(light.dist_atten_bias).ToFloat32(); |
| 85 | res.lighting.light[light_index].dist_atten_scale = Pica::float20::FromRaw(light.dist_atten_scale).ToFloat32(); | 92 | state.lighting.light[light_index].dist_atten_scale = Pica::float20::FromRaw(light.dist_atten_scale).ToFloat32(); |
| 86 | } | 93 | } |
| 87 | 94 | ||
| 88 | res.lighting.lut_d0.enable = regs.lighting.disable_lut_d0 == 0; | 95 | state.lighting.lut_d0.enable = regs.lighting.disable_lut_d0 == 0; |
| 89 | res.lighting.lut_d0.abs_input = regs.lighting.abs_lut_input.disable_d0 == 0; | 96 | state.lighting.lut_d0.abs_input = regs.lighting.abs_lut_input.disable_d0 == 0; |
| 90 | res.lighting.lut_d0.type = regs.lighting.lut_input.d0.Value(); | 97 | state.lighting.lut_d0.type = regs.lighting.lut_input.d0.Value(); |
| 91 | res.lighting.lut_d0.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.d0); | 98 | state.lighting.lut_d0.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.d0); |
| 92 | 99 | ||
| 93 | res.lighting.lut_d1.enable = regs.lighting.disable_lut_d1 == 0; | 100 | state.lighting.lut_d1.enable = regs.lighting.disable_lut_d1 == 0; |
| 94 | res.lighting.lut_d1.abs_input = regs.lighting.abs_lut_input.disable_d1 == 0; | 101 | state.lighting.lut_d1.abs_input = regs.lighting.abs_lut_input.disable_d1 == 0; |
| 95 | res.lighting.lut_d1.type = regs.lighting.lut_input.d1.Value(); | 102 | state.lighting.lut_d1.type = regs.lighting.lut_input.d1.Value(); |
| 96 | res.lighting.lut_d1.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.d1); | 103 | state.lighting.lut_d1.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.d1); |
| 97 | 104 | ||
| 98 | res.lighting.lut_fr.enable = regs.lighting.disable_lut_fr == 0; | 105 | state.lighting.lut_fr.enable = regs.lighting.disable_lut_fr == 0; |
| 99 | res.lighting.lut_fr.abs_input = regs.lighting.abs_lut_input.disable_fr == 0; | 106 | state.lighting.lut_fr.abs_input = regs.lighting.abs_lut_input.disable_fr == 0; |
| 100 | res.lighting.lut_fr.type = regs.lighting.lut_input.fr.Value(); | 107 | state.lighting.lut_fr.type = regs.lighting.lut_input.fr.Value(); |
| 101 | res.lighting.lut_fr.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.fr); | 108 | state.lighting.lut_fr.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.fr); |
| 102 | 109 | ||
| 103 | res.lighting.lut_rr.enable = regs.lighting.disable_lut_rr == 0; | 110 | state.lighting.lut_rr.enable = regs.lighting.disable_lut_rr == 0; |
| 104 | res.lighting.lut_rr.abs_input = regs.lighting.abs_lut_input.disable_rr == 0; | 111 | state.lighting.lut_rr.abs_input = regs.lighting.abs_lut_input.disable_rr == 0; |
| 105 | res.lighting.lut_rr.type = regs.lighting.lut_input.rr.Value(); | 112 | state.lighting.lut_rr.type = regs.lighting.lut_input.rr.Value(); |
| 106 | res.lighting.lut_rr.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rr); | 113 | state.lighting.lut_rr.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rr); |
| 107 | 114 | ||
| 108 | res.lighting.lut_rg.enable = regs.lighting.disable_lut_rg == 0; | 115 | state.lighting.lut_rg.enable = regs.lighting.disable_lut_rg == 0; |
| 109 | res.lighting.lut_rg.abs_input = regs.lighting.abs_lut_input.disable_rg == 0; | 116 | state.lighting.lut_rg.abs_input = regs.lighting.abs_lut_input.disable_rg == 0; |
| 110 | res.lighting.lut_rg.type = regs.lighting.lut_input.rg.Value(); | 117 | state.lighting.lut_rg.type = regs.lighting.lut_input.rg.Value(); |
| 111 | res.lighting.lut_rg.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rg); | 118 | state.lighting.lut_rg.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rg); |
| 112 | 119 | ||
| 113 | res.lighting.lut_rb.enable = regs.lighting.disable_lut_rb == 0; | 120 | state.lighting.lut_rb.enable = regs.lighting.disable_lut_rb == 0; |
| 114 | res.lighting.lut_rb.abs_input = regs.lighting.abs_lut_input.disable_rb == 0; | 121 | state.lighting.lut_rb.abs_input = regs.lighting.abs_lut_input.disable_rb == 0; |
| 115 | res.lighting.lut_rb.type = regs.lighting.lut_input.rb.Value(); | 122 | state.lighting.lut_rb.type = regs.lighting.lut_input.rb.Value(); |
| 116 | res.lighting.lut_rb.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rb); | 123 | state.lighting.lut_rb.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rb); |
| 117 | 124 | ||
| 118 | res.lighting.config = regs.lighting.config; | 125 | state.lighting.config = regs.lighting.config; |
| 119 | res.lighting.fresnel_selector = regs.lighting.fresnel_selector; | 126 | state.lighting.fresnel_selector = regs.lighting.fresnel_selector; |
| 120 | res.lighting.bump_mode = regs.lighting.bump_mode; | 127 | state.lighting.bump_mode = regs.lighting.bump_mode; |
| 121 | res.lighting.bump_selector = regs.lighting.bump_selector; | 128 | state.lighting.bump_selector = regs.lighting.bump_selector; |
| 122 | res.lighting.bump_renorm = regs.lighting.disable_bump_renorm == 0; | 129 | state.lighting.bump_renorm = regs.lighting.disable_bump_renorm == 0; |
| 123 | res.lighting.clamp_highlights = regs.lighting.clamp_highlights != 0; | 130 | state.lighting.clamp_highlights = regs.lighting.clamp_highlights != 0; |
| 124 | 131 | ||
| 125 | return res; | 132 | return res; |
| 126 | } | 133 | } |
| 127 | 134 | ||
| 128 | bool TevStageUpdatesCombinerBufferColor(unsigned stage_index) const { | 135 | bool TevStageUpdatesCombinerBufferColor(unsigned stage_index) const { |
| 129 | return (stage_index < 4) && (combiner_buffer_input & (1 << stage_index)); | 136 | return (stage_index < 4) && (state.combiner_buffer_input & (1 << stage_index)); |
| 130 | } | 137 | } |
| 131 | 138 | ||
| 132 | bool TevStageUpdatesCombinerBufferAlpha(unsigned stage_index) const { | 139 | bool TevStageUpdatesCombinerBufferAlpha(unsigned stage_index) const { |
| 133 | return (stage_index < 4) && ((combiner_buffer_input >> 4) & (1 << stage_index)); | 140 | return (stage_index < 4) && ((state.combiner_buffer_input >> 4) & (1 << stage_index)); |
| 134 | } | 141 | } |
| 135 | 142 | ||
| 136 | bool operator ==(const PicaShaderConfig& o) const { | 143 | bool operator ==(const PicaShaderConfig& o) const { |
| 137 | return std::memcmp(this, &o, sizeof(PicaShaderConfig)) == 0; | 144 | return std::memcmp(&state, &o.state, sizeof(PicaShaderConfig::State)) == 0; |
| 138 | }; | 145 | }; |
| 139 | 146 | ||
| 140 | Pica::Regs::CompareFunc alpha_test_func; | ||
| 141 | |||
| 142 | // NOTE: MSVC15 (Update 2) doesn't think `delete`'d constructors and operators are TC. | 147 | // NOTE: MSVC15 (Update 2) doesn't think `delete`'d constructors and operators are TC. |
| 143 | // This makes BitField not TC when used in a union or struct so we have to resort | 148 | // This makes BitField not TC when used in a union or struct so we have to resort |
| 144 | // to this ugly hack. | 149 | // to this ugly hack. |
| @@ -159,40 +164,45 @@ struct PicaShaderConfig { | |||
| 159 | return stage; | 164 | return stage; |
| 160 | } | 165 | } |
| 161 | }; | 166 | }; |
| 162 | std::array<TevStageConfigRaw, 6> tev_stages; | ||
| 163 | u8 combiner_buffer_input; | ||
| 164 | 167 | ||
| 165 | struct { | 168 | struct State { |
| 166 | struct { | 169 | |
| 167 | unsigned num; | 170 | Pica::Regs::CompareFunc alpha_test_func; |
| 168 | bool directional; | 171 | std::array<TevStageConfigRaw, 6> tev_stages; |
| 169 | bool two_sided_diffuse; | 172 | u8 combiner_buffer_input; |
| 170 | bool dist_atten_enable; | ||
| 171 | GLfloat dist_atten_scale; | ||
| 172 | GLfloat dist_atten_bias; | ||
| 173 | } light[8]; | ||
| 174 | |||
| 175 | bool enable; | ||
| 176 | unsigned src_num; | ||
| 177 | Pica::Regs::LightingBumpMode bump_mode; | ||
| 178 | unsigned bump_selector; | ||
| 179 | bool bump_renorm; | ||
| 180 | bool clamp_highlights; | ||
| 181 | |||
| 182 | Pica::Regs::LightingConfig config; | ||
| 183 | Pica::Regs::LightingFresnelSelector fresnel_selector; | ||
| 184 | 173 | ||
| 185 | struct { | 174 | struct { |
| 186 | bool enable; | 175 | struct { |
| 187 | bool abs_input; | 176 | unsigned num; |
| 188 | Pica::Regs::LightingLutInput type; | 177 | bool directional; |
| 189 | float scale; | 178 | bool two_sided_diffuse; |
| 190 | } lut_d0, lut_d1, lut_fr, lut_rr, lut_rg, lut_rb; | 179 | bool dist_atten_enable; |
| 191 | } lighting; | 180 | GLfloat dist_atten_scale; |
| 181 | GLfloat dist_atten_bias; | ||
| 182 | } light[8]; | ||
| 192 | 183 | ||
| 184 | bool enable; | ||
| 185 | unsigned src_num; | ||
| 186 | Pica::Regs::LightingBumpMode bump_mode; | ||
| 187 | unsigned bump_selector; | ||
| 188 | bool bump_renorm; | ||
| 189 | bool clamp_highlights; | ||
| 190 | |||
| 191 | Pica::Regs::LightingConfig config; | ||
| 192 | Pica::Regs::LightingFresnelSelector fresnel_selector; | ||
| 193 | |||
| 194 | struct { | ||
| 195 | bool enable; | ||
| 196 | bool abs_input; | ||
| 197 | Pica::Regs::LightingLutInput type; | ||
| 198 | float scale; | ||
| 199 | } lut_d0, lut_d1, lut_fr, lut_rr, lut_rg, lut_rb; | ||
| 200 | } lighting; | ||
| 201 | |||
| 202 | } state; | ||
| 193 | }; | 203 | }; |
| 194 | #if (__GNUC__ >= 5) || defined(__clang__) || defined(_MSC_VER) | 204 | #if (__GNUC__ >= 5) || defined(__clang__) || defined(_MSC_VER) |
| 195 | static_assert(std::is_trivially_copyable<PicaShaderConfig>::value, "PicaShaderConfig must be trivially copyable"); | 205 | static_assert(std::is_trivially_copyable<PicaShaderConfig::State>::value, "PicaShaderConfig::State must be trivially copyable"); |
| 196 | #endif | 206 | #endif |
| 197 | 207 | ||
| 198 | namespace std { | 208 | namespace std { |
| @@ -200,7 +210,7 @@ namespace std { | |||
| 200 | template <> | 210 | template <> |
| 201 | struct hash<PicaShaderConfig> { | 211 | struct hash<PicaShaderConfig> { |
| 202 | size_t operator()(const PicaShaderConfig& k) const { | 212 | size_t operator()(const PicaShaderConfig& k) const { |
| 203 | return Common::ComputeHash64(&k, sizeof(PicaShaderConfig)); | 213 | return Common::ComputeHash64(&k.state, sizeof(PicaShaderConfig::State)); |
| 204 | } | 214 | } |
| 205 | }; | 215 | }; |
| 206 | 216 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index 51984389c..0890adb12 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp | |||
| @@ -287,7 +287,7 @@ static void AppendAlphaTestCondition(std::string& out, Regs::CompareFunc func) { | |||
| 287 | 287 | ||
| 288 | /// Writes the code to emulate the specified TEV stage | 288 | /// Writes the code to emulate the specified TEV stage |
| 289 | static void WriteTevStage(std::string& out, const PicaShaderConfig& config, unsigned index) { | 289 | static void WriteTevStage(std::string& out, const PicaShaderConfig& config, unsigned index) { |
| 290 | const auto stage = static_cast<const Pica::Regs::TevStageConfig>(config.tev_stages[index]); | 290 | const auto stage = static_cast<const Pica::Regs::TevStageConfig>(config.state.tev_stages[index]); |
| 291 | if (!IsPassThroughTevStage(stage)) { | 291 | if (!IsPassThroughTevStage(stage)) { |
| 292 | std::string index_name = std::to_string(index); | 292 | std::string index_name = std::to_string(index); |
| 293 | 293 | ||
| @@ -331,6 +331,8 @@ static void WriteTevStage(std::string& out, const PicaShaderConfig& config, unsi | |||
| 331 | 331 | ||
| 332 | /// Writes the code to emulate fragment lighting | 332 | /// Writes the code to emulate fragment lighting |
| 333 | static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | 333 | static void WriteLighting(std::string& out, const PicaShaderConfig& config) { |
| 334 | const auto& lighting = config.state.lighting; | ||
| 335 | |||
| 334 | // Define lighting globals | 336 | // Define lighting globals |
| 335 | out += "vec4 diffuse_sum = vec4(0.0, 0.0, 0.0, 1.0);\n" | 337 | out += "vec4 diffuse_sum = vec4(0.0, 0.0, 0.0, 1.0);\n" |
| 336 | "vec4 specular_sum = vec4(0.0, 0.0, 0.0, 1.0);\n" | 338 | "vec4 specular_sum = vec4(0.0, 0.0, 0.0, 1.0);\n" |
| @@ -338,17 +340,17 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 338 | "vec3 refl_value = vec3(0.0);\n"; | 340 | "vec3 refl_value = vec3(0.0);\n"; |
| 339 | 341 | ||
| 340 | // Compute fragment normals | 342 | // Compute fragment normals |
| 341 | if (config.lighting.bump_mode == Pica::Regs::LightingBumpMode::NormalMap) { | 343 | if (lighting.bump_mode == Pica::Regs::LightingBumpMode::NormalMap) { |
| 342 | // Bump mapping is enabled using a normal map, read perturbation vector from the selected texture | 344 | // Bump mapping is enabled using a normal map, read perturbation vector from the selected texture |
| 343 | std::string bump_selector = std::to_string(config.lighting.bump_selector); | 345 | std::string bump_selector = std::to_string(lighting.bump_selector); |
| 344 | out += "vec3 surface_normal = 2.0 * texture(tex[" + bump_selector + "], texcoord[" + bump_selector + "]).rgb - 1.0;\n"; | 346 | out += "vec3 surface_normal = 2.0 * texture(tex[" + bump_selector + "], texcoord[" + bump_selector + "]).rgb - 1.0;\n"; |
| 345 | 347 | ||
| 346 | // Recompute Z-component of perturbation if 'renorm' is enabled, this provides a higher precision result | 348 | // Recompute Z-component of perturbation if 'renorm' is enabled, this provides a higher precision result |
| 347 | if (config.lighting.bump_renorm) { | 349 | if (lighting.bump_renorm) { |
| 348 | std::string val = "(1.0 - (surface_normal.x*surface_normal.x + surface_normal.y*surface_normal.y))"; | 350 | std::string val = "(1.0 - (surface_normal.x*surface_normal.x + surface_normal.y*surface_normal.y))"; |
| 349 | out += "surface_normal.z = sqrt(max(" + val + ", 0.0));\n"; | 351 | out += "surface_normal.z = sqrt(max(" + val + ", 0.0));\n"; |
| 350 | } | 352 | } |
| 351 | } else if (config.lighting.bump_mode == Pica::Regs::LightingBumpMode::TangentMap) { | 353 | } else if (lighting.bump_mode == Pica::Regs::LightingBumpMode::TangentMap) { |
| 352 | // Bump mapping is enabled using a tangent map | 354 | // Bump mapping is enabled using a tangent map |
| 353 | LOG_CRITICAL(HW_GPU, "unimplemented bump mapping mode (tangent mapping)"); | 355 | LOG_CRITICAL(HW_GPU, "unimplemented bump mapping mode (tangent mapping)"); |
| 354 | UNIMPLEMENTED(); | 356 | UNIMPLEMENTED(); |
| @@ -361,7 +363,7 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 361 | out += "vec3 normal = normalize(quaternion_rotate(normquat, surface_normal));\n"; | 363 | out += "vec3 normal = normalize(quaternion_rotate(normquat, surface_normal));\n"; |
| 362 | 364 | ||
| 363 | // Gets the index into the specified lookup table for specular lighting | 365 | // Gets the index into the specified lookup table for specular lighting |
| 364 | auto GetLutIndex = [config](unsigned light_num, Regs::LightingLutInput input, bool abs) { | 366 | auto GetLutIndex = [&lighting](unsigned light_num, Regs::LightingLutInput input, bool abs) { |
| 365 | const std::string half_angle = "normalize(normalize(view) + light_vector)"; | 367 | const std::string half_angle = "normalize(normalize(view) + light_vector)"; |
| 366 | std::string index; | 368 | std::string index; |
| 367 | switch (input) { | 369 | switch (input) { |
| @@ -389,7 +391,7 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 389 | 391 | ||
| 390 | if (abs) { | 392 | if (abs) { |
| 391 | // LUT index is in the range of (0.0, 1.0) | 393 | // LUT index is in the range of (0.0, 1.0) |
| 392 | index = config.lighting.light[light_num].two_sided_diffuse ? "abs(" + index + ")" : "max(" + index + ", 0.f)"; | 394 | index = lighting.light[light_num].two_sided_diffuse ? "abs(" + index + ")" : "max(" + index + ", 0.f)"; |
| 393 | return "(FLOAT_255 * clamp(" + index + ", 0.0, 1.0))"; | 395 | return "(FLOAT_255 * clamp(" + index + ", 0.0, 1.0))"; |
| 394 | } else { | 396 | } else { |
| 395 | // LUT index is in the range of (-1.0, 1.0) | 397 | // LUT index is in the range of (-1.0, 1.0) |
| @@ -407,8 +409,8 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 407 | }; | 409 | }; |
| 408 | 410 | ||
| 409 | // Write the code to emulate each enabled light | 411 | // Write the code to emulate each enabled light |
| 410 | for (unsigned light_index = 0; light_index < config.lighting.src_num; ++light_index) { | 412 | for (unsigned light_index = 0; light_index < lighting.src_num; ++light_index) { |
| 411 | const auto& light_config = config.lighting.light[light_index]; | 413 | const auto& light_config = lighting.light[light_index]; |
| 412 | std::string light_src = "light_src[" + std::to_string(light_config.num) + "]"; | 414 | std::string light_src = "light_src[" + std::to_string(light_config.num) + "]"; |
| 413 | 415 | ||
| 414 | // Compute light vector (directional or positional) | 416 | // Compute light vector (directional or positional) |
| @@ -432,39 +434,39 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 432 | } | 434 | } |
| 433 | 435 | ||
| 434 | // If enabled, clamp specular component if lighting result is negative | 436 | // If enabled, clamp specular component if lighting result is negative |
| 435 | std::string clamp_highlights = config.lighting.clamp_highlights ? "(dot(light_vector, normal) <= 0.0 ? 0.0 : 1.0)" : "1.0"; | 437 | std::string clamp_highlights = lighting.clamp_highlights ? "(dot(light_vector, normal) <= 0.0 ? 0.0 : 1.0)" : "1.0"; |
| 436 | 438 | ||
| 437 | // Specular 0 component | 439 | // Specular 0 component |
| 438 | std::string d0_lut_value = "1.0"; | 440 | std::string d0_lut_value = "1.0"; |
| 439 | if (config.lighting.lut_d0.enable && Pica::Regs::IsLightingSamplerSupported(config.lighting.config, Pica::Regs::LightingSampler::Distribution0)) { | 441 | if (lighting.lut_d0.enable && Pica::Regs::IsLightingSamplerSupported(lighting.config, Pica::Regs::LightingSampler::Distribution0)) { |
| 440 | // Lookup specular "distribution 0" LUT value | 442 | // Lookup specular "distribution 0" LUT value |
| 441 | std::string index = GetLutIndex(light_config.num, config.lighting.lut_d0.type, config.lighting.lut_d0.abs_input); | 443 | std::string index = GetLutIndex(light_config.num, lighting.lut_d0.type, lighting.lut_d0.abs_input); |
| 442 | d0_lut_value = "(" + std::to_string(config.lighting.lut_d0.scale) + " * " + GetLutValue(Regs::LightingSampler::Distribution0, index) + ")"; | 444 | d0_lut_value = "(" + std::to_string(lighting.lut_d0.scale) + " * " + GetLutValue(Regs::LightingSampler::Distribution0, index) + ")"; |
| 443 | } | 445 | } |
| 444 | std::string specular_0 = "(" + d0_lut_value + " * " + light_src + ".specular_0)"; | 446 | std::string specular_0 = "(" + d0_lut_value + " * " + light_src + ".specular_0)"; |
| 445 | 447 | ||
| 446 | // If enabled, lookup ReflectRed value, otherwise, 1.0 is used | 448 | // If enabled, lookup ReflectRed value, otherwise, 1.0 is used |
| 447 | if (config.lighting.lut_rr.enable && Pica::Regs::IsLightingSamplerSupported(config.lighting.config, Pica::Regs::LightingSampler::ReflectRed)) { | 449 | if (lighting.lut_rr.enable && Pica::Regs::IsLightingSamplerSupported(lighting.config, Pica::Regs::LightingSampler::ReflectRed)) { |
| 448 | std::string index = GetLutIndex(light_config.num, config.lighting.lut_rr.type, config.lighting.lut_rr.abs_input); | 450 | std::string index = GetLutIndex(light_config.num, lighting.lut_rr.type, lighting.lut_rr.abs_input); |
| 449 | std::string value = "(" + std::to_string(config.lighting.lut_rr.scale) + " * " + GetLutValue(Regs::LightingSampler::ReflectRed, index) + ")"; | 451 | std::string value = "(" + std::to_string(lighting.lut_rr.scale) + " * " + GetLutValue(Regs::LightingSampler::ReflectRed, index) + ")"; |
| 450 | out += "refl_value.r = " + value + ";\n"; | 452 | out += "refl_value.r = " + value + ";\n"; |
| 451 | } else { | 453 | } else { |
| 452 | out += "refl_value.r = 1.0;\n"; | 454 | out += "refl_value.r = 1.0;\n"; |
| 453 | } | 455 | } |
| 454 | 456 | ||
| 455 | // If enabled, lookup ReflectGreen value, otherwise, ReflectRed value is used | 457 | // If enabled, lookup ReflectGreen value, otherwise, ReflectRed value is used |
| 456 | if (config.lighting.lut_rg.enable && Pica::Regs::IsLightingSamplerSupported(config.lighting.config, Pica::Regs::LightingSampler::ReflectGreen)) { | 458 | if (lighting.lut_rg.enable && Pica::Regs::IsLightingSamplerSupported(lighting.config, Pica::Regs::LightingSampler::ReflectGreen)) { |
| 457 | std::string index = GetLutIndex(light_config.num, config.lighting.lut_rg.type, config.lighting.lut_rg.abs_input); | 459 | std::string index = GetLutIndex(light_config.num, lighting.lut_rg.type, lighting.lut_rg.abs_input); |
| 458 | std::string value = "(" + std::to_string(config.lighting.lut_rg.scale) + " * " + GetLutValue(Regs::LightingSampler::ReflectGreen, index) + ")"; | 460 | std::string value = "(" + std::to_string(lighting.lut_rg.scale) + " * " + GetLutValue(Regs::LightingSampler::ReflectGreen, index) + ")"; |
| 459 | out += "refl_value.g = " + value + ";\n"; | 461 | out += "refl_value.g = " + value + ";\n"; |
| 460 | } else { | 462 | } else { |
| 461 | out += "refl_value.g = refl_value.r;\n"; | 463 | out += "refl_value.g = refl_value.r;\n"; |
| 462 | } | 464 | } |
| 463 | 465 | ||
| 464 | // If enabled, lookup ReflectBlue value, otherwise, ReflectRed value is used | 466 | // If enabled, lookup ReflectBlue value, otherwise, ReflectRed value is used |
| 465 | if (config.lighting.lut_rb.enable && Pica::Regs::IsLightingSamplerSupported(config.lighting.config, Pica::Regs::LightingSampler::ReflectBlue)) { | 467 | if (lighting.lut_rb.enable && Pica::Regs::IsLightingSamplerSupported(lighting.config, Pica::Regs::LightingSampler::ReflectBlue)) { |
| 466 | std::string index = GetLutIndex(light_config.num, config.lighting.lut_rb.type, config.lighting.lut_rb.abs_input); | 468 | std::string index = GetLutIndex(light_config.num, lighting.lut_rb.type, lighting.lut_rb.abs_input); |
| 467 | std::string value = "(" + std::to_string(config.lighting.lut_rb.scale) + " * " + GetLutValue(Regs::LightingSampler::ReflectBlue, index) + ")"; | 469 | std::string value = "(" + std::to_string(lighting.lut_rb.scale) + " * " + GetLutValue(Regs::LightingSampler::ReflectBlue, index) + ")"; |
| 468 | out += "refl_value.b = " + value + ";\n"; | 470 | out += "refl_value.b = " + value + ";\n"; |
| 469 | } else { | 471 | } else { |
| 470 | out += "refl_value.b = refl_value.r;\n"; | 472 | out += "refl_value.b = refl_value.r;\n"; |
| @@ -472,27 +474,27 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 472 | 474 | ||
| 473 | // Specular 1 component | 475 | // Specular 1 component |
| 474 | std::string d1_lut_value = "1.0"; | 476 | std::string d1_lut_value = "1.0"; |
| 475 | if (config.lighting.lut_d1.enable && Pica::Regs::IsLightingSamplerSupported(config.lighting.config, Pica::Regs::LightingSampler::Distribution1)) { | 477 | if (lighting.lut_d1.enable && Pica::Regs::IsLightingSamplerSupported(lighting.config, Pica::Regs::LightingSampler::Distribution1)) { |
| 476 | // Lookup specular "distribution 1" LUT value | 478 | // Lookup specular "distribution 1" LUT value |
| 477 | std::string index = GetLutIndex(light_config.num, config.lighting.lut_d1.type, config.lighting.lut_d1.abs_input); | 479 | std::string index = GetLutIndex(light_config.num, lighting.lut_d1.type, lighting.lut_d1.abs_input); |
| 478 | d1_lut_value = "(" + std::to_string(config.lighting.lut_d1.scale) + " * " + GetLutValue(Regs::LightingSampler::Distribution1, index) + ")"; | 480 | d1_lut_value = "(" + std::to_string(lighting.lut_d1.scale) + " * " + GetLutValue(Regs::LightingSampler::Distribution1, index) + ")"; |
| 479 | } | 481 | } |
| 480 | std::string specular_1 = "(" + d1_lut_value + " * refl_value * " + light_src + ".specular_1)"; | 482 | std::string specular_1 = "(" + d1_lut_value + " * refl_value * " + light_src + ".specular_1)"; |
| 481 | 483 | ||
| 482 | // Fresnel | 484 | // Fresnel |
| 483 | if (config.lighting.lut_fr.enable && Pica::Regs::IsLightingSamplerSupported(config.lighting.config, Pica::Regs::LightingSampler::Fresnel)) { | 485 | if (lighting.lut_fr.enable && Pica::Regs::IsLightingSamplerSupported(lighting.config, Pica::Regs::LightingSampler::Fresnel)) { |
| 484 | // Lookup fresnel LUT value | 486 | // Lookup fresnel LUT value |
| 485 | std::string index = GetLutIndex(light_config.num, config.lighting.lut_fr.type, config.lighting.lut_fr.abs_input); | 487 | std::string index = GetLutIndex(light_config.num, lighting.lut_fr.type, lighting.lut_fr.abs_input); |
| 486 | std::string value = "(" + std::to_string(config.lighting.lut_fr.scale) + " * " + GetLutValue(Regs::LightingSampler::Fresnel, index) + ")"; | 488 | std::string value = "(" + std::to_string(lighting.lut_fr.scale) + " * " + GetLutValue(Regs::LightingSampler::Fresnel, index) + ")"; |
| 487 | 489 | ||
| 488 | // Enabled for difffuse lighting alpha component | 490 | // Enabled for difffuse lighting alpha component |
| 489 | if (config.lighting.fresnel_selector == Pica::Regs::LightingFresnelSelector::PrimaryAlpha || | 491 | if (lighting.fresnel_selector == Pica::Regs::LightingFresnelSelector::PrimaryAlpha || |
| 490 | config.lighting.fresnel_selector == Pica::Regs::LightingFresnelSelector::Both) | 492 | lighting.fresnel_selector == Pica::Regs::LightingFresnelSelector::Both) |
| 491 | out += "diffuse_sum.a *= " + value + ";\n"; | 493 | out += "diffuse_sum.a *= " + value + ";\n"; |
| 492 | 494 | ||
| 493 | // Enabled for the specular lighting alpha component | 495 | // Enabled for the specular lighting alpha component |
| 494 | if (config.lighting.fresnel_selector == Pica::Regs::LightingFresnelSelector::SecondaryAlpha || | 496 | if (lighting.fresnel_selector == Pica::Regs::LightingFresnelSelector::SecondaryAlpha || |
| 495 | config.lighting.fresnel_selector == Pica::Regs::LightingFresnelSelector::Both) | 497 | lighting.fresnel_selector == Pica::Regs::LightingFresnelSelector::Both) |
| 496 | out += "specular_sum.a *= " + value + ";\n"; | 498 | out += "specular_sum.a *= " + value + ";\n"; |
| 497 | } | 499 | } |
| 498 | 500 | ||
| @@ -510,6 +512,8 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 510 | } | 512 | } |
| 511 | 513 | ||
| 512 | std::string GenerateFragmentShader(const PicaShaderConfig& config) { | 514 | std::string GenerateFragmentShader(const PicaShaderConfig& config) { |
| 515 | const auto& state = config.state; | ||
| 516 | |||
| 513 | std::string out = R"( | 517 | std::string out = R"( |
| 514 | #version 330 core | 518 | #version 330 core |
| 515 | #define NUM_TEV_STAGES 6 | 519 | #define NUM_TEV_STAGES 6 |
| @@ -555,24 +559,24 @@ vec4 secondary_fragment_color = vec4(0.0); | |||
| 555 | )"; | 559 | )"; |
| 556 | 560 | ||
| 557 | // Do not do any sort of processing if it's obvious we're not going to pass the alpha test | 561 | // Do not do any sort of processing if it's obvious we're not going to pass the alpha test |
| 558 | if (config.alpha_test_func == Regs::CompareFunc::Never) { | 562 | if (state.alpha_test_func == Regs::CompareFunc::Never) { |
| 559 | out += "discard; }"; | 563 | out += "discard; }"; |
| 560 | return out; | 564 | return out; |
| 561 | } | 565 | } |
| 562 | 566 | ||
| 563 | if (config.lighting.enable) | 567 | if (state.lighting.enable) |
| 564 | WriteLighting(out, config); | 568 | WriteLighting(out, config); |
| 565 | 569 | ||
| 566 | out += "vec4 combiner_buffer = vec4(0.0);\n"; | 570 | out += "vec4 combiner_buffer = vec4(0.0);\n"; |
| 567 | out += "vec4 next_combiner_buffer = tev_combiner_buffer_color;\n"; | 571 | out += "vec4 next_combiner_buffer = tev_combiner_buffer_color;\n"; |
| 568 | out += "vec4 last_tex_env_out = vec4(0.0);\n"; | 572 | out += "vec4 last_tex_env_out = vec4(0.0);\n"; |
| 569 | 573 | ||
| 570 | for (size_t index = 0; index < config.tev_stages.size(); ++index) | 574 | for (size_t index = 0; index < state.tev_stages.size(); ++index) |
| 571 | WriteTevStage(out, config, (unsigned)index); | 575 | WriteTevStage(out, config, (unsigned)index); |
| 572 | 576 | ||
| 573 | if (config.alpha_test_func != Regs::CompareFunc::Always) { | 577 | if (state.alpha_test_func != Regs::CompareFunc::Always) { |
| 574 | out += "if ("; | 578 | out += "if ("; |
| 575 | AppendAlphaTestCondition(out, config.alpha_test_func); | 579 | AppendAlphaTestCondition(out, state.alpha_test_func); |
| 576 | out += ") discard;\n"; | 580 | out += ") discard;\n"; |
| 577 | } | 581 | } |
| 578 | 582 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.h b/src/video_core/renderer_opengl/gl_shader_gen.h index 3eb07d57a..bef3249cf 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.h +++ b/src/video_core/renderer_opengl/gl_shader_gen.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <string> | 7 | #include <string> |
| 8 | 8 | ||
| 9 | struct PicaShaderConfig; | 9 | union PicaShaderConfig; |
| 10 | 10 | ||
| 11 | namespace GLShader { | 11 | namespace GLShader { |
| 12 | 12 | ||