145 lines
5.2 KiB
C++
145 lines
5.2 KiB
C++
// Copyright 2015 Citra Emulator Project
|
|
// Licensed under GPLv2 or any later version
|
|
// Refer to the license.txt file included.
|
|
|
|
#pragma once
|
|
|
|
#include <array>
|
|
#include <cstring>
|
|
#include <functional>
|
|
#include <string>
|
|
#include <type_traits>
|
|
#include "video_core/regs.h"
|
|
|
|
namespace GLShader {
|
|
|
|
enum Attributes {
|
|
ATTRIBUTE_POSITION,
|
|
ATTRIBUTE_COLOR,
|
|
ATTRIBUTE_TEXCOORD0,
|
|
ATTRIBUTE_TEXCOORD1,
|
|
ATTRIBUTE_TEXCOORD2,
|
|
ATTRIBUTE_TEXCOORD0_W,
|
|
ATTRIBUTE_NORMQUAT,
|
|
ATTRIBUTE_VIEW,
|
|
};
|
|
|
|
/**
|
|
* 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
|
|
*/
|
|
std::string GenerateVertexShader();
|
|
|
|
/**
|
|
* Generates the GLSL fragment shader program source code for the current Pica state
|
|
* @param config ShaderCacheKey object generated for the current Pica state, used for the shader
|
|
* configuration (NOTE: Use state in this struct only, not the Pica registers!)
|
|
* @returns String of the shader source code
|
|
*/
|
|
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
|