Merge pull request #1690 from JayFoxRox/tex-type-3

Pica: Implement texture type 3 (Projection2D)
This commit is contained in:
bunnei 2016-05-11 21:47:08 -04:00
commit f6eb62d062
7 changed files with 106 additions and 38 deletions

View file

@ -138,6 +138,15 @@ struct Regs {
INSERT_PADDING_WORDS(0x12); INSERT_PADDING_WORDS(0x12);
struct TextureConfig { struct TextureConfig {
enum TextureType : u32 {
Texture2D = 0,
TextureCube = 1,
Shadow2D = 2,
Projection2D = 3,
ShadowCube = 4,
Disabled = 5,
};
enum WrapMode : u32 { enum WrapMode : u32 {
ClampToEdge = 0, ClampToEdge = 0,
ClampToBorder = 1, ClampToBorder = 1,
@ -168,6 +177,7 @@ struct Regs {
BitField< 2, 1, TextureFilter> min_filter; BitField< 2, 1, TextureFilter> min_filter;
BitField< 8, 2, WrapMode> wrap_t; BitField< 8, 2, WrapMode> wrap_t;
BitField<12, 2, WrapMode> wrap_s; BitField<12, 2, WrapMode> wrap_s;
BitField<28, 2, TextureType> type; ///< @note Only valid for texture 0 according to 3DBrew.
}; };
INSERT_PADDING_WORDS(0x1); INSERT_PADDING_WORDS(0x1);

View file

@ -442,8 +442,33 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0,
DEBUG_ASSERT(0 != texture.config.address); DEBUG_ASSERT(0 != texture.config.address);
int s = (int)(uv[i].u() * float24::FromFloat32(static_cast<float>(texture.config.width))).ToFloat32(); float24 u = uv[i].u();
int t = (int)(uv[i].v() * float24::FromFloat32(static_cast<float>(texture.config.height))).ToFloat32(); float24 v = uv[i].v();
// Only unit 0 respects the texturing type (according to 3DBrew)
// TODO: Refactor so cubemaps and shadowmaps can be handled
if (i == 0) {
switch(texture.config.type) {
case Regs::TextureConfig::Texture2D:
break;
case Regs::TextureConfig::Projection2D: {
auto tc0_w = GetInterpolatedAttribute(v0.tc0_w, v1.tc0_w, v2.tc0_w);
u /= tc0_w;
v /= tc0_w;
break;
}
default:
// TODO: Change to LOG_ERROR when more types are handled.
LOG_DEBUG(HW_GPU, "Unhandled texture type %x", (int)texture.config.type);
UNIMPLEMENTED();
break;
}
}
int s = (int)(u * float24::FromFloat32(static_cast<float>(texture.config.width))).ToFloat32();
int t = (int)(v * float24::FromFloat32(static_cast<float>(texture.config.height))).ToFloat32();
static auto GetWrappedTexCoord = [](Regs::TextureConfig::WrapMode mode, int val, unsigned size) { static auto GetWrappedTexCoord = [](Regs::TextureConfig::WrapMode mode, int val, unsigned size) {
switch (mode) { switch (mode) {
case Regs::TextureConfig::ClampToEdge: case Regs::TextureConfig::ClampToEdge:

View file

@ -76,6 +76,9 @@ RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true) {
glEnableVertexAttribArray(GLShader::ATTRIBUTE_TEXCOORD1); glEnableVertexAttribArray(GLShader::ATTRIBUTE_TEXCOORD1);
glEnableVertexAttribArray(GLShader::ATTRIBUTE_TEXCOORD2); glEnableVertexAttribArray(GLShader::ATTRIBUTE_TEXCOORD2);
glVertexAttribPointer(GLShader::ATTRIBUTE_TEXCOORD0_W, 1, GL_FLOAT, GL_FALSE, sizeof(HardwareVertex), (GLvoid*)offsetof(HardwareVertex, tex_coord0_w));
glEnableVertexAttribArray(GLShader::ATTRIBUTE_TEXCOORD0_W);
glVertexAttribPointer(GLShader::ATTRIBUTE_NORMQUAT, 4, GL_FLOAT, GL_FALSE, sizeof(HardwareVertex), (GLvoid*)offsetof(HardwareVertex, normquat)); glVertexAttribPointer(GLShader::ATTRIBUTE_NORMQUAT, 4, GL_FLOAT, GL_FALSE, sizeof(HardwareVertex), (GLvoid*)offsetof(HardwareVertex, normquat));
glEnableVertexAttribArray(GLShader::ATTRIBUTE_NORMQUAT); glEnableVertexAttribArray(GLShader::ATTRIBUTE_NORMQUAT);
@ -319,6 +322,11 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
SyncLogicOp(); SyncLogicOp();
break; break;
// Texture 0 type
case PICA_REG_INDEX(texture0.type):
shader_dirty = true;
break;
// TEV stages // TEV stages
case PICA_REG_INDEX(tev_stage0.color_source1): case PICA_REG_INDEX(tev_stage0.color_source1):
case PICA_REG_INDEX(tev_stage0.color_modifier1): case PICA_REG_INDEX(tev_stage0.color_modifier1):

View file

@ -61,6 +61,8 @@ union PicaShaderConfig {
state.alpha_test_func = regs.output_merger.alpha_test.enable ? state.alpha_test_func = regs.output_merger.alpha_test.enable ?
regs.output_merger.alpha_test.func.Value() : Pica::Regs::CompareFunc::Always; regs.output_merger.alpha_test.func.Value() : Pica::Regs::CompareFunc::Always;
state.texture0_type = regs.texture0.type;
// Copy relevant tev stages fields. // Copy relevant tev stages fields.
// We don't sync const_color here because of the high variance, it is a // We don't sync const_color here because of the high variance, it is a
// shader uniform instead. // shader uniform instead.
@ -170,6 +172,7 @@ union PicaShaderConfig {
struct State { struct State {
Pica::Regs::CompareFunc alpha_test_func; Pica::Regs::CompareFunc alpha_test_func;
Pica::Regs::TextureConfig::TextureType texture0_type;
std::array<TevStageConfigRaw, 6> tev_stages; std::array<TevStageConfigRaw, 6> tev_stages;
u8 combiner_buffer_input; u8 combiner_buffer_input;
@ -281,6 +284,7 @@ private:
tex_coord1[1] = v.tc1.y.ToFloat32(); tex_coord1[1] = v.tc1.y.ToFloat32();
tex_coord2[0] = v.tc2.x.ToFloat32(); tex_coord2[0] = v.tc2.x.ToFloat32();
tex_coord2[1] = v.tc2.y.ToFloat32(); tex_coord2[1] = v.tc2.y.ToFloat32();
tex_coord0_w = v.tc0_w.ToFloat32();
normquat[0] = v.quat.x.ToFloat32(); normquat[0] = v.quat.x.ToFloat32();
normquat[1] = v.quat.y.ToFloat32(); normquat[1] = v.quat.y.ToFloat32();
normquat[2] = v.quat.z.ToFloat32(); normquat[2] = v.quat.z.ToFloat32();
@ -301,6 +305,7 @@ private:
GLfloat tex_coord0[2]; GLfloat tex_coord0[2];
GLfloat tex_coord1[2]; GLfloat tex_coord1[2];
GLfloat tex_coord2[2]; GLfloat tex_coord2[2];
GLfloat tex_coord0_w;
GLfloat normquat[4]; GLfloat normquat[4];
GLfloat view[3]; GLfloat view[3];
}; };

View file

@ -32,8 +32,9 @@ static bool IsPassThroughTevStage(const TevStageConfig& stage) {
} }
/// Writes the specified TEV stage source component(s) /// Writes the specified TEV stage source component(s)
static void AppendSource(std::string& out, TevStageConfig::Source source, static void AppendSource(std::string& out, const PicaShaderConfig& config, TevStageConfig::Source source,
const std::string& index_name) { const std::string& index_name) {
const auto& state = config.state;
using Source = TevStageConfig::Source; using Source = TevStageConfig::Source;
switch (source) { switch (source) {
case Source::PrimaryColor: case Source::PrimaryColor:
@ -46,7 +47,20 @@ static void AppendSource(std::string& out, TevStageConfig::Source source,
out += "secondary_fragment_color"; out += "secondary_fragment_color";
break; break;
case Source::Texture0: case Source::Texture0:
out += "texture(tex[0], texcoord[0])"; // Only unit 0 respects the texturing type (according to 3DBrew)
switch(state.texture0_type) {
case Pica::Regs::TextureConfig::Texture2D:
out += "texture(tex[0], texcoord[0])";
break;
case Pica::Regs::TextureConfig::Projection2D:
out += "textureProj(tex[0], vec3(texcoord[0], texcoord0_w))";
break;
default:
out += "texture(tex[0], texcoord[0])";
LOG_CRITICAL(HW_GPU, "Unhandled texture type %x", static_cast<int>(state.texture0_type));
UNIMPLEMENTED();
break;
}
break; break;
case Source::Texture1: case Source::Texture1:
out += "texture(tex[1], texcoord[1])"; out += "texture(tex[1], texcoord[1])";
@ -71,53 +85,53 @@ static void AppendSource(std::string& out, TevStageConfig::Source source,
} }
/// Writes the color components to use for the specified TEV stage color modifier /// Writes the color components to use for the specified TEV stage color modifier
static void AppendColorModifier(std::string& out, TevStageConfig::ColorModifier modifier, static void AppendColorModifier(std::string& out, const PicaShaderConfig& config, TevStageConfig::ColorModifier modifier,
TevStageConfig::Source source, const std::string& index_name) { TevStageConfig::Source source, const std::string& index_name) {
using ColorModifier = TevStageConfig::ColorModifier; using ColorModifier = TevStageConfig::ColorModifier;
switch (modifier) { switch (modifier) {
case ColorModifier::SourceColor: case ColorModifier::SourceColor:
AppendSource(out, source, index_name); AppendSource(out, config, source, index_name);
out += ".rgb"; out += ".rgb";
break; break;
case ColorModifier::OneMinusSourceColor: case ColorModifier::OneMinusSourceColor:
out += "vec3(1.0) - "; out += "vec3(1.0) - ";
AppendSource(out, source, index_name); AppendSource(out, config, source, index_name);
out += ".rgb"; out += ".rgb";
break; break;
case ColorModifier::SourceAlpha: case ColorModifier::SourceAlpha:
AppendSource(out, source, index_name); AppendSource(out, config, source, index_name);
out += ".aaa"; out += ".aaa";
break; break;
case ColorModifier::OneMinusSourceAlpha: case ColorModifier::OneMinusSourceAlpha:
out += "vec3(1.0) - "; out += "vec3(1.0) - ";
AppendSource(out, source, index_name); AppendSource(out, config, source, index_name);
out += ".aaa"; out += ".aaa";
break; break;
case ColorModifier::SourceRed: case ColorModifier::SourceRed:
AppendSource(out, source, index_name); AppendSource(out, config, source, index_name);
out += ".rrr"; out += ".rrr";
break; break;
case ColorModifier::OneMinusSourceRed: case ColorModifier::OneMinusSourceRed:
out += "vec3(1.0) - "; out += "vec3(1.0) - ";
AppendSource(out, source, index_name); AppendSource(out, config, source, index_name);
out += ".rrr"; out += ".rrr";
break; break;
case ColorModifier::SourceGreen: case ColorModifier::SourceGreen:
AppendSource(out, source, index_name); AppendSource(out, config, source, index_name);
out += ".ggg"; out += ".ggg";
break; break;
case ColorModifier::OneMinusSourceGreen: case ColorModifier::OneMinusSourceGreen:
out += "vec3(1.0) - "; out += "vec3(1.0) - ";
AppendSource(out, source, index_name); AppendSource(out, config, source, index_name);
out += ".ggg"; out += ".ggg";
break; break;
case ColorModifier::SourceBlue: case ColorModifier::SourceBlue:
AppendSource(out, source, index_name); AppendSource(out, config, source, index_name);
out += ".bbb"; out += ".bbb";
break; break;
case ColorModifier::OneMinusSourceBlue: case ColorModifier::OneMinusSourceBlue:
out += "vec3(1.0) - "; out += "vec3(1.0) - ";
AppendSource(out, source, index_name); AppendSource(out, config, source, index_name);
out += ".bbb"; out += ".bbb";
break; break;
default: default:
@ -128,44 +142,44 @@ static void AppendColorModifier(std::string& out, TevStageConfig::ColorModifier
} }
/// Writes the alpha component to use for the specified TEV stage alpha modifier /// Writes the alpha component to use for the specified TEV stage alpha modifier
static void AppendAlphaModifier(std::string& out, TevStageConfig::AlphaModifier modifier, static void AppendAlphaModifier(std::string& out, const PicaShaderConfig& config, TevStageConfig::AlphaModifier modifier,
TevStageConfig::Source source, const std::string& index_name) { TevStageConfig::Source source, const std::string& index_name) {
using AlphaModifier = TevStageConfig::AlphaModifier; using AlphaModifier = TevStageConfig::AlphaModifier;
switch (modifier) { switch (modifier) {
case AlphaModifier::SourceAlpha: case AlphaModifier::SourceAlpha:
AppendSource(out, source, index_name); AppendSource(out, config, source, index_name);
out += ".a"; out += ".a";
break; break;
case AlphaModifier::OneMinusSourceAlpha: case AlphaModifier::OneMinusSourceAlpha:
out += "1.0 - "; out += "1.0 - ";
AppendSource(out, source, index_name); AppendSource(out, config, source, index_name);
out += ".a"; out += ".a";
break; break;
case AlphaModifier::SourceRed: case AlphaModifier::SourceRed:
AppendSource(out, source, index_name); AppendSource(out, config, source, index_name);
out += ".r"; out += ".r";
break; break;
case AlphaModifier::OneMinusSourceRed: case AlphaModifier::OneMinusSourceRed:
out += "1.0 - "; out += "1.0 - ";
AppendSource(out, source, index_name); AppendSource(out, config, source, index_name);
out += ".r"; out += ".r";
break; break;
case AlphaModifier::SourceGreen: case AlphaModifier::SourceGreen:
AppendSource(out, source, index_name); AppendSource(out, config, source, index_name);
out += ".g"; out += ".g";
break; break;
case AlphaModifier::OneMinusSourceGreen: case AlphaModifier::OneMinusSourceGreen:
out += "1.0 - "; out += "1.0 - ";
AppendSource(out, source, index_name); AppendSource(out, config, source, index_name);
out += ".g"; out += ".g";
break; break;
case AlphaModifier::SourceBlue: case AlphaModifier::SourceBlue:
AppendSource(out, source, index_name); AppendSource(out, config, source, index_name);
out += ".b"; out += ".b";
break; break;
case AlphaModifier::OneMinusSourceBlue: case AlphaModifier::OneMinusSourceBlue:
out += "1.0 - "; out += "1.0 - ";
AppendSource(out, source, index_name); AppendSource(out, config, source, index_name);
out += ".b"; out += ".b";
break; break;
default: default:
@ -292,11 +306,11 @@ static void WriteTevStage(std::string& out, const PicaShaderConfig& config, unsi
std::string index_name = std::to_string(index); std::string index_name = std::to_string(index);
out += "vec3 color_results_" + index_name + "[3] = vec3[3]("; out += "vec3 color_results_" + index_name + "[3] = vec3[3](";
AppendColorModifier(out, stage.color_modifier1, stage.color_source1, index_name); AppendColorModifier(out, config, stage.color_modifier1, stage.color_source1, index_name);
out += ", "; out += ", ";
AppendColorModifier(out, stage.color_modifier2, stage.color_source2, index_name); AppendColorModifier(out, config, stage.color_modifier2, stage.color_source2, index_name);
out += ", "; out += ", ";
AppendColorModifier(out, stage.color_modifier3, stage.color_source3, index_name); AppendColorModifier(out, config, stage.color_modifier3, stage.color_source3, index_name);
out += ");\n"; out += ");\n";
out += "vec3 color_output_" + index_name + " = "; out += "vec3 color_output_" + index_name + " = ";
@ -304,11 +318,11 @@ static void WriteTevStage(std::string& out, const PicaShaderConfig& config, unsi
out += ";\n"; out += ";\n";
out += "float alpha_results_" + index_name + "[3] = float[3]("; out += "float alpha_results_" + index_name + "[3] = float[3](";
AppendAlphaModifier(out, stage.alpha_modifier1, stage.alpha_source1, index_name); AppendAlphaModifier(out, config, stage.alpha_modifier1, stage.alpha_source1, index_name);
out += ", "; out += ", ";
AppendAlphaModifier(out, stage.alpha_modifier2, stage.alpha_source2, index_name); AppendAlphaModifier(out, config, stage.alpha_modifier2, stage.alpha_source2, index_name);
out += ", "; out += ", ";
AppendAlphaModifier(out, stage.alpha_modifier3, stage.alpha_source3, index_name); AppendAlphaModifier(out, config, stage.alpha_modifier3, stage.alpha_source3, index_name);
out += ");\n"; out += ");\n";
out += "float alpha_output_" + index_name + " = "; out += "float alpha_output_" + index_name + " = ";
@ -523,6 +537,7 @@ std::string GenerateFragmentShader(const PicaShaderConfig& config) {
in vec4 primary_color; in vec4 primary_color;
in vec2 texcoord[3]; in vec2 texcoord[3];
in float texcoord0_w;
in vec4 normquat; in vec4 normquat;
in vec3 view; in vec3 view;
@ -598,17 +613,19 @@ vec4 secondary_fragment_color = vec4(0.0);
std::string GenerateVertexShader() { std::string GenerateVertexShader() {
std::string out = "#version 330 core\n"; std::string out = "#version 330 core\n";
out += "layout(location = " + std::to_string((int)ATTRIBUTE_POSITION) + ") in vec4 vert_position;\n"; out += "layout(location = " + std::to_string((int)ATTRIBUTE_POSITION) + ") in vec4 vert_position;\n";
out += "layout(location = " + std::to_string((int)ATTRIBUTE_COLOR) + ") in vec4 vert_color;\n"; out += "layout(location = " + std::to_string((int)ATTRIBUTE_COLOR) + ") in vec4 vert_color;\n";
out += "layout(location = " + std::to_string((int)ATTRIBUTE_TEXCOORD0) + ") in vec2 vert_texcoord0;\n"; out += "layout(location = " + std::to_string((int)ATTRIBUTE_TEXCOORD0) + ") in vec2 vert_texcoord0;\n";
out += "layout(location = " + std::to_string((int)ATTRIBUTE_TEXCOORD1) + ") in vec2 vert_texcoord1;\n"; out += "layout(location = " + std::to_string((int)ATTRIBUTE_TEXCOORD1) + ") in vec2 vert_texcoord1;\n";
out += "layout(location = " + std::to_string((int)ATTRIBUTE_TEXCOORD2) + ") in vec2 vert_texcoord2;\n"; out += "layout(location = " + std::to_string((int)ATTRIBUTE_TEXCOORD2) + ") in vec2 vert_texcoord2;\n";
out += "layout(location = " + std::to_string((int)ATTRIBUTE_NORMQUAT) + ") in vec4 vert_normquat;\n"; out += "layout(location = " + std::to_string((int)ATTRIBUTE_TEXCOORD0_W) + ") in float vert_texcoord0_w;\n";
out += "layout(location = " + std::to_string((int)ATTRIBUTE_VIEW) + ") in vec3 vert_view;\n"; out += "layout(location = " + std::to_string((int)ATTRIBUTE_NORMQUAT) + ") in vec4 vert_normquat;\n";
out += "layout(location = " + std::to_string((int)ATTRIBUTE_VIEW) + ") in vec3 vert_view;\n";
out += R"( out += R"(
out vec4 primary_color; out vec4 primary_color;
out vec2 texcoord[3]; out vec2 texcoord[3];
out float texcoord0_w;
out vec4 normquat; out vec4 normquat;
out vec3 view; out vec3 view;
@ -617,6 +634,7 @@ void main() {
texcoord[0] = vert_texcoord0; texcoord[0] = vert_texcoord0;
texcoord[1] = vert_texcoord1; texcoord[1] = vert_texcoord1;
texcoord[2] = vert_texcoord2; texcoord[2] = vert_texcoord2;
texcoord0_w = vert_texcoord0_w;
normquat = vert_normquat; normquat = vert_normquat;
view = vert_view; view = vert_view;
gl_Position = vec4(vert_position.x, vert_position.y, -vert_position.z, vert_position.w); gl_Position = vec4(vert_position.x, vert_position.y, -vert_position.z, vert_position.w);

View file

@ -14,6 +14,7 @@ enum Attributes {
ATTRIBUTE_TEXCOORD0, ATTRIBUTE_TEXCOORD0,
ATTRIBUTE_TEXCOORD1, ATTRIBUTE_TEXCOORD1,
ATTRIBUTE_TEXCOORD2, ATTRIBUTE_TEXCOORD2,
ATTRIBUTE_TEXCOORD0_W,
ATTRIBUTE_NORMQUAT, ATTRIBUTE_NORMQUAT,
ATTRIBUTE_VIEW, ATTRIBUTE_VIEW,
}; };

View file

@ -43,7 +43,8 @@ struct OutputVertex {
Math::Vec4<float24> color; Math::Vec4<float24> color;
Math::Vec2<float24> tc0; Math::Vec2<float24> tc0;
Math::Vec2<float24> tc1; Math::Vec2<float24> tc1;
INSERT_PADDING_WORDS(2); float24 tc0_w;
INSERT_PADDING_WORDS(1);
Math::Vec3<float24> view; Math::Vec3<float24> view;
INSERT_PADDING_WORDS(1); INSERT_PADDING_WORDS(1);
Math::Vec2<float24> tc2; Math::Vec2<float24> tc2;