shader: Add partial rasterizer integration
This commit is contained in:
parent
72990df7ba
commit
260743f371
54 changed files with 1929 additions and 568 deletions
|
@ -1,15 +0,0 @@
|
|||
// Copyright 2021 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "shader_recompiler/exception.h"
|
||||
#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
|
||||
|
||||
namespace Shader::Maxwell {
|
||||
|
||||
void TranslatorVisitor::EXIT(u64) {
|
||||
ir.Exit();
|
||||
}
|
||||
|
||||
} // namespace Shader::Maxwell
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright 2021 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "shader_recompiler/exception.h"
|
||||
#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
|
||||
|
||||
namespace Shader::Maxwell {
|
||||
namespace {
|
||||
void ExitFragment(TranslatorVisitor& v) {
|
||||
const ProgramHeader sph{v.env.SPH()};
|
||||
IR::Reg src_reg{IR::Reg::R0};
|
||||
for (u32 render_target = 0; render_target < 8; ++render_target) {
|
||||
const std::array<bool, 4> mask{sph.ps.EnabledOutputComponents(render_target)};
|
||||
for (u32 component = 0; component < 4; ++component) {
|
||||
if (!mask[component]) {
|
||||
continue;
|
||||
}
|
||||
v.ir.SetFragColor(render_target, component, v.F(src_reg));
|
||||
++src_reg;
|
||||
}
|
||||
}
|
||||
if (sph.ps.omap.sample_mask != 0) {
|
||||
throw NotImplementedException("Sample mask");
|
||||
}
|
||||
if (sph.ps.omap.depth != 0) {
|
||||
throw NotImplementedException("Fragment depth");
|
||||
}
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
void TranslatorVisitor::EXIT() {
|
||||
switch (env.ShaderStage()) {
|
||||
case Stage::Fragment:
|
||||
ExitFragment(*this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Shader::Maxwell
|
|
@ -108,7 +108,7 @@ public:
|
|||
void DSETP_reg(u64 insn);
|
||||
void DSETP_cbuf(u64 insn);
|
||||
void DSETP_imm(u64 insn);
|
||||
void EXIT(u64 insn);
|
||||
void EXIT();
|
||||
void F2F_reg(u64 insn);
|
||||
void F2F_cbuf(u64 insn);
|
||||
void F2F_imm(u64 insn);
|
||||
|
@ -220,7 +220,7 @@ public:
|
|||
void JCAL(u64 insn);
|
||||
void JMP(u64 insn);
|
||||
void JMX(u64 insn);
|
||||
void KIL(u64 insn);
|
||||
void KIL();
|
||||
void LD(u64 insn);
|
||||
void LDC(u64 insn);
|
||||
void LDG(u64 insn);
|
||||
|
|
|
@ -11,6 +11,13 @@
|
|||
|
||||
namespace Shader::Maxwell {
|
||||
namespace {
|
||||
enum class Size : u64 {
|
||||
B32,
|
||||
B64,
|
||||
B96,
|
||||
B128,
|
||||
};
|
||||
|
||||
enum class InterpolationMode : u64 {
|
||||
Pass,
|
||||
Multiply,
|
||||
|
@ -23,8 +30,85 @@ enum class SampleMode : u64 {
|
|||
Centroid,
|
||||
Offset,
|
||||
};
|
||||
|
||||
int NumElements(Size size) {
|
||||
switch (size) {
|
||||
case Size::B32:
|
||||
return 1;
|
||||
case Size::B64:
|
||||
return 2;
|
||||
case Size::B96:
|
||||
return 3;
|
||||
case Size::B128:
|
||||
return 4;
|
||||
}
|
||||
throw InvalidArgument("Invalid size {}", size);
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
void TranslatorVisitor::ALD(u64 insn) {
|
||||
union {
|
||||
u64 raw;
|
||||
BitField<0, 8, IR::Reg> dest_reg;
|
||||
BitField<8, 8, IR::Reg> index_reg;
|
||||
BitField<20, 10, u64> absolute_offset;
|
||||
BitField<20, 11, s64> relative_offset;
|
||||
BitField<39, 8, IR::Reg> stream_reg;
|
||||
BitField<32, 1, u64> o;
|
||||
BitField<31, 1, u64> patch;
|
||||
BitField<47, 2, Size> size;
|
||||
} const ald{insn};
|
||||
|
||||
if (ald.o != 0) {
|
||||
throw NotImplementedException("O");
|
||||
}
|
||||
if (ald.patch != 0) {
|
||||
throw NotImplementedException("P");
|
||||
}
|
||||
if (ald.index_reg != IR::Reg::RZ) {
|
||||
throw NotImplementedException("Indexed");
|
||||
}
|
||||
const u64 offset{ald.absolute_offset.Value()};
|
||||
if (offset % 4 != 0) {
|
||||
throw NotImplementedException("Unaligned absolute offset {}", offset);
|
||||
}
|
||||
const int num_elements{NumElements(ald.size)};
|
||||
for (int element = 0; element < num_elements; ++element) {
|
||||
F(ald.dest_reg + element, ir.GetAttribute(IR::Attribute{offset / 4 + element}));
|
||||
}
|
||||
}
|
||||
|
||||
void TranslatorVisitor::AST(u64 insn) {
|
||||
union {
|
||||
u64 raw;
|
||||
BitField<0, 8, IR::Reg> src_reg;
|
||||
BitField<8, 8, IR::Reg> index_reg;
|
||||
BitField<20, 10, u64> absolute_offset;
|
||||
BitField<20, 11, s64> relative_offset;
|
||||
BitField<31, 1, u64> patch;
|
||||
BitField<39, 8, IR::Reg> stream_reg;
|
||||
BitField<47, 2, Size> size;
|
||||
} const ast{insn};
|
||||
|
||||
if (ast.patch != 0) {
|
||||
throw NotImplementedException("P");
|
||||
}
|
||||
if (ast.stream_reg != IR::Reg::RZ) {
|
||||
throw NotImplementedException("Stream store");
|
||||
}
|
||||
if (ast.index_reg != IR::Reg::RZ) {
|
||||
throw NotImplementedException("Indexed store");
|
||||
}
|
||||
const u64 offset{ast.absolute_offset.Value()};
|
||||
if (offset % 4 != 0) {
|
||||
throw NotImplementedException("Unaligned absolute offset {}", offset);
|
||||
}
|
||||
const int num_elements{NumElements(ast.size)};
|
||||
for (int element = 0; element < num_elements; ++element) {
|
||||
ir.SetAttribute(IR::Attribute{offset / 4 + element}, F(ast.src_reg + element));
|
||||
}
|
||||
}
|
||||
|
||||
void TranslatorVisitor::IPA(u64 insn) {
|
||||
// IPA is the instruction used to read varyings from a fragment shader.
|
||||
// gl_FragCoord is mapped to the gl_Position attribute.
|
||||
|
@ -51,7 +135,7 @@ void TranslatorVisitor::IPA(u64 insn) {
|
|||
// }
|
||||
const bool is_indexed{ipa.idx != 0 && ipa.index_reg != IR::Reg::RZ};
|
||||
if (is_indexed) {
|
||||
throw NotImplementedException("IPA.IDX");
|
||||
throw NotImplementedException("IDX");
|
||||
}
|
||||
|
||||
const IR::Attribute attribute{ipa.attribute};
|
||||
|
|
|
@ -17,14 +17,6 @@ void TranslatorVisitor::AL2P(u64) {
|
|||
ThrowNotImplemented(Opcode::AL2P);
|
||||
}
|
||||
|
||||
void TranslatorVisitor::ALD(u64) {
|
||||
ThrowNotImplemented(Opcode::ALD);
|
||||
}
|
||||
|
||||
void TranslatorVisitor::AST(u64) {
|
||||
ThrowNotImplemented(Opcode::AST);
|
||||
}
|
||||
|
||||
void TranslatorVisitor::ATOM_cas(u64) {
|
||||
ThrowNotImplemented(Opcode::ATOM_cas);
|
||||
}
|
||||
|
@ -153,10 +145,6 @@ void TranslatorVisitor::DSETP_imm(u64) {
|
|||
ThrowNotImplemented(Opcode::DSETP_imm);
|
||||
}
|
||||
|
||||
void TranslatorVisitor::EXIT(u64) {
|
||||
throw LogicError("Visting EXIT instruction");
|
||||
}
|
||||
|
||||
void TranslatorVisitor::F2F_reg(u64) {
|
||||
ThrowNotImplemented(Opcode::F2F_reg);
|
||||
}
|
||||
|
@ -345,8 +333,8 @@ void TranslatorVisitor::JMX(u64) {
|
|||
ThrowNotImplemented(Opcode::JMX);
|
||||
}
|
||||
|
||||
void TranslatorVisitor::KIL(u64) {
|
||||
ThrowNotImplemented(Opcode::KIL);
|
||||
void TranslatorVisitor::KIL() {
|
||||
// KIL is a no-op
|
||||
}
|
||||
|
||||
void TranslatorVisitor::LD(u64) {
|
||||
|
|
|
@ -215,7 +215,7 @@ void TranslatorVisitor::TEX(u64 insn) {
|
|||
BitField<36, 13, u64> cbuf_offset;
|
||||
} const tex{insn};
|
||||
|
||||
Impl(*this, insn, tex.aoffi != 0, tex.blod, tex.lc != 0, static_cast<u32>(tex.cbuf_offset));
|
||||
Impl(*this, insn, tex.aoffi != 0, tex.blod, tex.lc != 0, static_cast<u32>(tex.cbuf_offset * 4));
|
||||
}
|
||||
|
||||
void TranslatorVisitor::TEX_b(u64 insn) {
|
||||
|
|
|
@ -70,7 +70,7 @@ IR::F32 ReadArray(TranslatorVisitor& v, const IR::U32& value) {
|
|||
|
||||
IR::Value Sample(TranslatorVisitor& v, u64 insn) {
|
||||
const Encoding texs{insn};
|
||||
const IR::U32 handle{v.ir.Imm32(static_cast<u32>(texs.cbuf_offset))};
|
||||
const IR::U32 handle{v.ir.Imm32(static_cast<u32>(texs.cbuf_offset * 4))};
|
||||
const IR::F32 zero{v.ir.Imm32(0.0f)};
|
||||
const IR::Reg reg_a{texs.src_reg_a};
|
||||
const IR::Reg reg_b{texs.src_reg_b};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue