early-access version 1491

main
pineappleEA 2021-03-01 03:52:01 +01:00
parent ae5276503a
commit dff35d290d
3 changed files with 80 additions and 10 deletions

View File

@ -1,7 +1,7 @@
yuzu emulator early access yuzu emulator early access
============= =============
This is the source code for early-access 1490. This is the source code for early-access 1491.
## Legal Notice ## Legal Notice

View File

@ -79,6 +79,11 @@ const float fswzadd_modifiers_a[] = float[4](-1.0f, 1.0f, -1.0f, 0.0f );
const float fswzadd_modifiers_b[] = float[4](-1.0f, -1.0f, 1.0f, -1.0f ); const float fswzadd_modifiers_b[] = float[4](-1.0f, -1.0f, 1.0f, -1.0f );
)"; )";
enum class HelperFunction {
SignedAtomic = 0,
Total,
};
class ShaderWriter final { class ShaderWriter final {
public: public:
void AddExpression(std::string_view text) { void AddExpression(std::string_view text) {
@ -434,6 +439,7 @@ public:
DeclareInternalFlags(); DeclareInternalFlags();
DeclareCustomVariables(); DeclareCustomVariables();
DeclarePhysicalAttributeReader(); DeclarePhysicalAttributeReader();
DeclareHelpersForward();
const auto& subfunctions = ir.GetSubFunctions(); const auto& subfunctions = ir.GetSubFunctions();
auto it = subfunctions.rbegin(); auto it = subfunctions.rbegin();
@ -471,6 +477,9 @@ public:
--code.scope; --code.scope;
code.AddLine("}}"); code.AddLine("}}");
code.AddNewLine();
DeclareHelpers();
} }
std::string GetResult() { std::string GetResult() {
@ -620,7 +629,7 @@ private:
size = limit; size = limit;
} }
code.AddLine("shared uint smem[{}];", size / 4); code.AddLine("shared uint {}[{}];", GetSharedMemory(), size / 4);
code.AddNewLine(); code.AddNewLine();
} }
code.AddLine("layout (local_size_x = {}, local_size_y = {}, local_size_z = {}) in;", code.AddLine("layout (local_size_x = {}, local_size_y = {}, local_size_z = {}) in;",
@ -1004,6 +1013,27 @@ private:
} }
} }
void DeclareHelpersForward() {
code.AddLine("int Helpers_AtomicShared(uint offset, int value, bool is_min);");
code.AddNewLine();
}
void DeclareHelpers() {
if (IsHelperEnabled(HelperFunction::SignedAtomic)) {
code.AddLine(
R"(int Helpers_AtomicShared(uint offset, int value, bool is_min) {{
uint oldValue, newValue;
do {{
oldValue = {}[offset];
newValue = is_min ? uint(min(int(oldValue), value)) : uint(max(int(oldValue), value));
}} while (atomicCompSwap({}[offset], newValue, oldValue) != oldValue);
return int(oldValue);
}})",
GetSharedMemory(), GetSharedMemory());
code.AddNewLine();
}
}
void VisitBlock(const NodeBlock& bb) { void VisitBlock(const NodeBlock& bb) {
for (const auto& node : bb) { for (const auto& node : bb) {
Visit(node).CheckVoid(); Visit(node).CheckVoid();
@ -1130,7 +1160,9 @@ private:
} }
if (const auto smem = std::get_if<SmemNode>(&*node)) { if (const auto smem = std::get_if<SmemNode>(&*node)) {
return {fmt::format("smem[{} >> 2]", Visit(smem->GetAddress()).AsUint()), Type::Uint}; return {
fmt::format("{}[{} >> 2]", GetSharedMemory(), Visit(smem->GetAddress()).AsUint()),
Type::Uint};
} }
if (const auto internal_flag = std::get_if<InternalFlagNode>(&*node)) { if (const auto internal_flag = std::get_if<InternalFlagNode>(&*node)) {
@ -1624,7 +1656,9 @@ private:
Type::Uint}; Type::Uint};
} else if (const auto smem = std::get_if<SmemNode>(&*dest)) { } else if (const auto smem = std::get_if<SmemNode>(&*dest)) {
ASSERT(stage == ShaderType::Compute); ASSERT(stage == ShaderType::Compute);
target = {fmt::format("smem[{} >> 2]", Visit(smem->GetAddress()).AsUint()), Type::Uint}; target = {
fmt::format("{}[{} >> 2]", GetSharedMemory(), Visit(smem->GetAddress()).AsUint()),
Type::Uint};
} else if (const auto gmem = std::get_if<GmemNode>(&*dest)) { } else if (const auto gmem = std::get_if<GmemNode>(&*dest)) {
const std::string real = Visit(gmem->GetRealAddress()).AsUint(); const std::string real = Visit(gmem->GetRealAddress()).AsUint();
const std::string base = Visit(gmem->GetBaseAddress()).AsUint(); const std::string base = Visit(gmem->GetBaseAddress()).AsUint();
@ -2141,7 +2175,14 @@ private:
UNIMPLEMENTED_IF(meta->sampler.is_array); UNIMPLEMENTED_IF(meta->sampler.is_array);
const std::size_t count = operation.GetOperandsCount(); const std::size_t count = operation.GetOperandsCount();
std::string expr = "texelFetch("; std::string expr = "texelFetch";
if (!meta->aoffi.empty()) {
expr += "Offset";
}
expr += '(';
expr += GetSampler(meta->sampler); expr += GetSampler(meta->sampler);
expr += ", "; expr += ", ";
@ -2163,6 +2204,20 @@ private:
expr += ", "; expr += ", ";
expr += Visit(meta->lod).AsInt(); expr += Visit(meta->lod).AsInt();
} }
if (!meta->aoffi.empty()) {
expr += ", ";
expr += constructors.at(meta->aoffi.size() - 1);
expr += '(';
for (size_t i = 0; i < meta->aoffi.size(); ++i) {
if (i > 0) {
expr += ", ";
}
expr += Visit(meta->aoffi[i]).AsInt();
}
expr += ')';
}
expr += ')'; expr += ')';
expr += GetSwizzle(meta->element); expr += GetSwizzle(meta->element);
@ -2209,8 +2264,11 @@ private:
template <const std::string_view& opname, Type type> template <const std::string_view& opname, Type type>
Expression Atomic(Operation operation) { Expression Atomic(Operation operation) {
if ((opname == Func::Min || opname == Func::Max) && type == Type::Int) { if ((opname == Func::Min || opname == Func::Max) && type == Type::Int) {
UNIMPLEMENTED_MSG("Unimplemented Min & Max for atomic operations"); // Use a helper as a workaround due to memory being uint
return {}; SetHelperEnabled(HelperFunction::SignedAtomic, true);
return {fmt::format("Helpers_AtomicShared({}, {}, {})", Visit(operation[0]).AsInt(),
Visit(operation[1]).AsInt(), opname == Func::Min),
Type::Int};
} }
return {fmt::format("atomic{}({}, {})", opname, Visit(operation[0]).GetCode(), return {fmt::format("atomic{}({}, {})", opname, Visit(operation[0]).GetCode(),
Visit(operation[1]).AsUint()), Visit(operation[1]).AsUint()),
@ -2737,6 +2795,10 @@ private:
} }
} }
constexpr std::string_view GetSharedMemory() const {
return "shared_mem";
}
std::string GetInternalFlag(InternalFlag flag) const { std::string GetInternalFlag(InternalFlag flag) const {
constexpr std::array InternalFlagNames = {"zero_flag", "sign_flag", "carry_flag", constexpr std::array InternalFlagNames = {"zero_flag", "sign_flag", "carry_flag",
"overflow_flag"}; "overflow_flag"};
@ -2778,6 +2840,14 @@ private:
return std::min<u32>(device.GetMaxVaryings(), Maxwell::NumVaryings); return std::min<u32>(device.GetMaxVaryings(), Maxwell::NumVaryings);
} }
void SetHelperEnabled(HelperFunction hf, bool enabled) {
helper_functions_enabled[static_cast<size_t>(hf)] = enabled;
}
bool IsHelperEnabled(HelperFunction hf) const {
return helper_functions_enabled[static_cast<size_t>(hf)];
}
const Device& device; const Device& device;
const ShaderIR& ir; const ShaderIR& ir;
const Registry& registry; const Registry& registry;
@ -2792,6 +2862,8 @@ private:
ShaderWriter code; ShaderWriter code;
std::optional<u32> max_input_vertices; std::optional<u32> max_input_vertices;
std::array<bool, static_cast<size_t>(HelperFunction::Total)> helper_functions_enabled{};
}; };
std::string GetFlowVariable(u32 index) { std::string GetFlowVariable(u32 index) {

View File

@ -339,8 +339,6 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
const TextureType texture_type{instr.tlds.GetTextureType()}; const TextureType texture_type{instr.tlds.GetTextureType()};
const bool is_array{instr.tlds.IsArrayTexture()}; const bool is_array{instr.tlds.IsArrayTexture()};
UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(TextureMiscMode::AOFFI),
"AOFFI is not implemented");
UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(TextureMiscMode::MZ), "MZ is not implemented"); UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(TextureMiscMode::MZ), "MZ is not implemented");
const Node4 components = GetTldsCode(instr, texture_type, is_array); const Node4 components = GetTldsCode(instr, texture_type, is_array);
@ -822,7 +820,7 @@ Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is
for (std::size_t i = 0; i < type_coord_count; ++i) { for (std::size_t i = 0; i < type_coord_count; ++i) {
const bool last = (i == (type_coord_count - 1)) && (type_coord_count > 1); const bool last = (i == (type_coord_count - 1)) && (type_coord_count > 1);
coords.push_back( coords.push_back(
GetRegister(last && !aoffi_enabled ? last_coord_register : coord_register + i)); GetRegister(last && !aoffi_enabled ? last_coord_register : (coord_register + i)));
} }
const Node array = is_array ? GetRegister(array_register) : nullptr; const Node array = is_array ? GetRegister(array_register) : nullptr;