forked from suyu/suyu
rasterizer: Implement combiner buffer input.
This commit is contained in:
parent
44927f0306
commit
a806b420a6
2 changed files with 53 additions and 4 deletions
|
@ -226,7 +226,8 @@ struct Regs {
|
|||
Texture1 = 0x4,
|
||||
Texture2 = 0x5,
|
||||
Texture3 = 0x6,
|
||||
// 0x7-0xc = primary color??
|
||||
|
||||
PreviousBuffer = 0xd,
|
||||
Constant = 0xe,
|
||||
Previous = 0xf,
|
||||
};
|
||||
|
@ -309,11 +310,36 @@ struct Regs {
|
|||
TevStageConfig tev_stage2;
|
||||
INSERT_PADDING_WORDS(0x3);
|
||||
TevStageConfig tev_stage3;
|
||||
INSERT_PADDING_WORDS(0x13);
|
||||
INSERT_PADDING_WORDS(0x3);
|
||||
|
||||
union {
|
||||
// Tev stages 0-3 write their output to the combiner buffer if the corresponding bit in
|
||||
// these masks are set
|
||||
BitField< 8, 4, u32> update_mask_rgb;
|
||||
BitField<12, 4, u32> update_mask_a;
|
||||
|
||||
bool TevStageUpdatesCombinerBufferColor(unsigned stage_index) const {
|
||||
return (stage_index < 4) && (update_mask_rgb & (1 << stage_index));
|
||||
}
|
||||
|
||||
bool TevStageUpdatesCombinerBufferAlpha(unsigned stage_index) const {
|
||||
return (stage_index < 4) && (update_mask_a & (1 << stage_index));
|
||||
}
|
||||
} tev_combiner_buffer_input;
|
||||
|
||||
INSERT_PADDING_WORDS(0xf);
|
||||
TevStageConfig tev_stage4;
|
||||
INSERT_PADDING_WORDS(0x3);
|
||||
TevStageConfig tev_stage5;
|
||||
INSERT_PADDING_WORDS(0x3);
|
||||
|
||||
union {
|
||||
BitField< 0, 8, u32> r;
|
||||
BitField< 8, 8, u32> g;
|
||||
BitField<16, 8, u32> b;
|
||||
BitField<24, 8, u32> a;
|
||||
} tev_combiner_buffer_color;
|
||||
|
||||
INSERT_PADDING_WORDS(0x2);
|
||||
|
||||
const std::array<Regs::TevStageConfig,6> GetTevStages() const {
|
||||
return { tev_stage0, tev_stage1,
|
||||
|
@ -784,8 +810,10 @@ struct Regs {
|
|||
ADD_FIELD(tev_stage1);
|
||||
ADD_FIELD(tev_stage2);
|
||||
ADD_FIELD(tev_stage3);
|
||||
ADD_FIELD(tev_combiner_buffer_input);
|
||||
ADD_FIELD(tev_stage4);
|
||||
ADD_FIELD(tev_stage5);
|
||||
ADD_FIELD(tev_combiner_buffer_color);
|
||||
ADD_FIELD(output_merger);
|
||||
ADD_FIELD(framebuffer);
|
||||
ADD_FIELD(vertex_attributes);
|
||||
|
@ -859,8 +887,10 @@ ASSERT_REG_POSITION(tev_stage0, 0xc0);
|
|||
ASSERT_REG_POSITION(tev_stage1, 0xc8);
|
||||
ASSERT_REG_POSITION(tev_stage2, 0xd0);
|
||||
ASSERT_REG_POSITION(tev_stage3, 0xd8);
|
||||
ASSERT_REG_POSITION(tev_combiner_buffer_input, 0xe0);
|
||||
ASSERT_REG_POSITION(tev_stage4, 0xf0);
|
||||
ASSERT_REG_POSITION(tev_stage5, 0xf8);
|
||||
ASSERT_REG_POSITION(tev_combiner_buffer_color, 0xfd);
|
||||
ASSERT_REG_POSITION(output_merger, 0x100);
|
||||
ASSERT_REG_POSITION(framebuffer, 0x110);
|
||||
ASSERT_REG_POSITION(vertex_attributes, 0x200);
|
||||
|
|
|
@ -376,7 +376,13 @@ static void ProcessTriangleInternal(const VertexShader::OutputVertex& v0,
|
|||
// with some basic arithmetic. Alpha combiners can be configured separately but work
|
||||
// analogously.
|
||||
Math::Vec4<u8> combiner_output;
|
||||
for (const auto& tev_stage : tev_stages) {
|
||||
Math::Vec4<u8> combiner_buffer = {
|
||||
registers.tev_combiner_buffer_color.r, registers.tev_combiner_buffer_color.g,
|
||||
registers.tev_combiner_buffer_color.b, registers.tev_combiner_buffer_color.a
|
||||
};
|
||||
|
||||
for (unsigned tev_stage_index = 0; tev_stage_index < tev_stages.size(); ++tev_stage_index) {
|
||||
const auto& tev_stage = tev_stages[tev_stage_index];
|
||||
using Source = Regs::TevStageConfig::Source;
|
||||
using ColorModifier = Regs::TevStageConfig::ColorModifier;
|
||||
using AlphaModifier = Regs::TevStageConfig::AlphaModifier;
|
||||
|
@ -398,6 +404,9 @@ static void ProcessTriangleInternal(const VertexShader::OutputVertex& v0,
|
|||
case Source::Texture2:
|
||||
return texture_color[2];
|
||||
|
||||
case Source::PreviousBuffer:
|
||||
return combiner_buffer;
|
||||
|
||||
case Source::Constant:
|
||||
return {tev_stage.const_r, tev_stage.const_g, tev_stage.const_b, tev_stage.const_a};
|
||||
|
||||
|
@ -579,6 +588,16 @@ static void ProcessTriangleInternal(const VertexShader::OutputVertex& v0,
|
|||
auto alpha_output = AlphaCombine(tev_stage.alpha_op, alpha_result);
|
||||
|
||||
combiner_output = Math::MakeVec(color_output, alpha_output);
|
||||
|
||||
if (registers.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferColor(tev_stage_index)) {
|
||||
combiner_buffer.r() = combiner_output.r();
|
||||
combiner_buffer.g() = combiner_output.g();
|
||||
combiner_buffer.b() = combiner_output.b();
|
||||
}
|
||||
|
||||
if (registers.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferAlpha(tev_stage_index)) {
|
||||
combiner_buffer.a() = combiner_output.a();
|
||||
}
|
||||
}
|
||||
|
||||
if (registers.output_merger.alpha_test.enable) {
|
||||
|
|
Loading…
Reference in a new issue