spirv: Initial SPIR-V support
This commit is contained in:
parent
6dafb08f52
commit
2930dccecc
|
@ -1 +1 @@
|
||||||
Subproject commit eefca56afd49379bdebc97ded8b480839f930881
|
Subproject commit 1f7b70730d610cfbd5099ab93dd38ec8a78e7e35
|
|
@ -1,5 +1,16 @@
|
||||||
add_executable(shader_recompiler
|
add_executable(shader_recompiler
|
||||||
|
backend/spirv/emit_spirv.cpp
|
||||||
backend/spirv/emit_spirv.h
|
backend/spirv/emit_spirv.h
|
||||||
|
backend/spirv/emit_spirv_bitwise_conversion.cpp
|
||||||
|
backend/spirv/emit_spirv_composite.cpp
|
||||||
|
backend/spirv/emit_spirv_context_get_set.cpp
|
||||||
|
backend/spirv/emit_spirv_control_flow.cpp
|
||||||
|
backend/spirv/emit_spirv_floating_point.cpp
|
||||||
|
backend/spirv/emit_spirv_integer.cpp
|
||||||
|
backend/spirv/emit_spirv_logical.cpp
|
||||||
|
backend/spirv/emit_spirv_memory.cpp
|
||||||
|
backend/spirv/emit_spirv_select.cpp
|
||||||
|
backend/spirv/emit_spirv_undefined.cpp
|
||||||
environment.h
|
environment.h
|
||||||
exception.h
|
exception.h
|
||||||
file_environment.cpp
|
file_environment.cpp
|
||||||
|
@ -72,7 +83,9 @@ add_executable(shader_recompiler
|
||||||
main.cpp
|
main.cpp
|
||||||
object_pool.h
|
object_pool.h
|
||||||
)
|
)
|
||||||
target_link_libraries(shader_recompiler PRIVATE fmt::fmt)
|
|
||||||
|
target_include_directories(video_core PRIVATE sirit)
|
||||||
|
target_link_libraries(shader_recompiler PRIVATE fmt::fmt sirit)
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
target_compile_options(shader_recompiler PRIVATE
|
target_compile_options(shader_recompiler PRIVATE
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
// Copyright 2021 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <numeric>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include "shader_recompiler/backend/spirv/emit_spirv.h"
|
||||||
|
#include "shader_recompiler/frontend/ir/basic_block.h"
|
||||||
|
#include "shader_recompiler/frontend/ir/function.h"
|
||||||
|
#include "shader_recompiler/frontend/ir/microinstruction.h"
|
||||||
|
#include "shader_recompiler/frontend/ir/program.h"
|
||||||
|
|
||||||
|
namespace Shader::Backend::SPIRV {
|
||||||
|
|
||||||
|
EmitContext::EmitContext(IR::Program& program) {
|
||||||
|
AddCapability(spv::Capability::Shader);
|
||||||
|
AddCapability(spv::Capability::Float16);
|
||||||
|
AddCapability(spv::Capability::Float64);
|
||||||
|
void_id = TypeVoid();
|
||||||
|
|
||||||
|
u1 = Name(TypeBool(), "u1");
|
||||||
|
f32.Define(*this, TypeFloat(32), "f32");
|
||||||
|
u32.Define(*this, TypeInt(32, false), "u32");
|
||||||
|
f16.Define(*this, TypeFloat(16), "f16");
|
||||||
|
f64.Define(*this, TypeFloat(64), "f64");
|
||||||
|
|
||||||
|
for (const IR::Function& function : program.functions) {
|
||||||
|
for (IR::Block* const block : function.blocks) {
|
||||||
|
block_label_map.emplace_back(block, OpLabel());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::ranges::sort(block_label_map, {}, &std::pair<IR::Block*, Id>::first);
|
||||||
|
}
|
||||||
|
|
||||||
|
EmitContext::~EmitContext() = default;
|
||||||
|
|
||||||
|
EmitSPIRV::EmitSPIRV(IR::Program& program) {
|
||||||
|
EmitContext ctx{program};
|
||||||
|
const Id void_function{ctx.TypeFunction(ctx.void_id)};
|
||||||
|
// FIXME: Forward declare functions (needs sirit support)
|
||||||
|
Id func{};
|
||||||
|
for (IR::Function& function : program.functions) {
|
||||||
|
func = ctx.OpFunction(ctx.void_id, spv::FunctionControlMask::MaskNone, void_function);
|
||||||
|
for (IR::Block* const block : function.blocks) {
|
||||||
|
ctx.AddLabel(ctx.BlockLabel(block));
|
||||||
|
for (IR::Inst& inst : block->Instructions()) {
|
||||||
|
EmitInst(ctx, &inst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx.OpFunctionEnd();
|
||||||
|
}
|
||||||
|
ctx.AddEntryPoint(spv::ExecutionModel::GLCompute, func, "main");
|
||||||
|
|
||||||
|
std::vector<u32> result{ctx.Assemble()};
|
||||||
|
std::FILE* file{std::fopen("shader.spv", "wb")};
|
||||||
|
std::fwrite(result.data(), sizeof(u32), result.size(), file);
|
||||||
|
std::fclose(file);
|
||||||
|
std::system("spirv-dis shader.spv");
|
||||||
|
std::system("spirv-val shader.spv");
|
||||||
|
}
|
||||||
|
|
||||||
|
template <auto method>
|
||||||
|
static void Invoke(EmitSPIRV& emit, EmitContext& ctx, IR::Inst* inst) {
|
||||||
|
using M = decltype(method);
|
||||||
|
using std::is_invocable_r_v;
|
||||||
|
if constexpr (is_invocable_r_v<Id, M, EmitSPIRV&, EmitContext&>) {
|
||||||
|
ctx.Define(inst, (emit.*method)(ctx));
|
||||||
|
} else if constexpr (is_invocable_r_v<Id, M, EmitSPIRV&, EmitContext&, Id>) {
|
||||||
|
ctx.Define(inst, (emit.*method)(ctx, ctx.Def(inst->Arg(0))));
|
||||||
|
} else if constexpr (is_invocable_r_v<Id, M, EmitSPIRV&, EmitContext&, Id, Id>) {
|
||||||
|
ctx.Define(inst, (emit.*method)(ctx, ctx.Def(inst->Arg(0)), ctx.Def(inst->Arg(1))));
|
||||||
|
} else if constexpr (is_invocable_r_v<Id, M, EmitSPIRV&, EmitContext&, Id, Id, Id>) {
|
||||||
|
ctx.Define(inst, (emit.*method)(ctx, ctx.Def(inst->Arg(0)), ctx.Def(inst->Arg(1)),
|
||||||
|
ctx.Def(inst->Arg(2))));
|
||||||
|
} else if constexpr (is_invocable_r_v<Id, M, EmitSPIRV&, EmitContext&, IR::Inst*, Id, Id>) {
|
||||||
|
ctx.Define(inst, (emit.*method)(ctx, inst, ctx.Def(inst->Arg(0)), ctx.Def(inst->Arg(1))));
|
||||||
|
} else if constexpr (is_invocable_r_v<Id, M, EmitSPIRV&, EmitContext&, IR::Inst*, Id, Id, Id>) {
|
||||||
|
ctx.Define(inst, (emit.*method)(ctx, inst, ctx.Def(inst->Arg(0)), ctx.Def(inst->Arg(1)),
|
||||||
|
ctx.Def(inst->Arg(2))));
|
||||||
|
} else if constexpr (is_invocable_r_v<Id, M, EmitSPIRV&, EmitContext&, Id, u32>) {
|
||||||
|
ctx.Define(inst, (emit.*method)(ctx, ctx.Def(inst->Arg(0)), inst->Arg(1).U32()));
|
||||||
|
} else if constexpr (is_invocable_r_v<Id, M, EmitSPIRV&, EmitContext&, const IR::Value&>) {
|
||||||
|
ctx.Define(inst, (emit.*method)(ctx, inst->Arg(0)));
|
||||||
|
} else if constexpr (is_invocable_r_v<Id, M, EmitSPIRV&, EmitContext&, const IR::Value&,
|
||||||
|
const IR::Value&>) {
|
||||||
|
ctx.Define(inst, (emit.*method)(ctx, inst->Arg(0), inst->Arg(1)));
|
||||||
|
} else if constexpr (is_invocable_r_v<void, M, EmitSPIRV&, EmitContext&, IR::Inst*>) {
|
||||||
|
(emit.*method)(ctx, inst);
|
||||||
|
} else if constexpr (is_invocable_r_v<void, M, EmitSPIRV&, EmitContext&>) {
|
||||||
|
(emit.*method)(ctx);
|
||||||
|
} else {
|
||||||
|
static_assert(false, "Bad format");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitInst(EmitContext& ctx, IR::Inst* inst) {
|
||||||
|
switch (inst->Opcode()) {
|
||||||
|
#define OPCODE(name, result_type, ...) \
|
||||||
|
case IR::Opcode::name: \
|
||||||
|
return Invoke<&EmitSPIRV::Emit##name>(*this, ctx, inst);
|
||||||
|
#include "shader_recompiler/frontend/ir/opcodes.inc"
|
||||||
|
#undef OPCODE
|
||||||
|
}
|
||||||
|
throw LogicError("Invalid opcode {}", inst->Opcode());
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitPhi(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitVoid(EmitContext&) {}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitIdentity(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitGetZeroFromOp(EmitContext&) {
|
||||||
|
throw LogicError("Unreachable instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitGetSignFromOp(EmitContext&) {
|
||||||
|
throw LogicError("Unreachable instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitGetCarryFromOp(EmitContext&) {
|
||||||
|
throw LogicError("Unreachable instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitGetOverflowFromOp(EmitContext&) {
|
||||||
|
throw LogicError("Unreachable instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Shader::Backend::SPIRV
|
|
@ -4,18 +4,326 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <sirit/sirit.h>
|
||||||
|
|
||||||
|
#include <boost/container/flat_map.hpp>
|
||||||
|
|
||||||
|
#include "common/common_types.h"
|
||||||
#include "shader_recompiler/frontend/ir/microinstruction.h"
|
#include "shader_recompiler/frontend/ir/microinstruction.h"
|
||||||
#include "shader_recompiler/frontend/ir/program.h"
|
#include "shader_recompiler/frontend/ir/program.h"
|
||||||
|
|
||||||
namespace Shader::Backend::SPIRV {
|
namespace Shader::Backend::SPIRV {
|
||||||
|
|
||||||
|
using Sirit::Id;
|
||||||
|
|
||||||
|
class DefMap {
|
||||||
|
public:
|
||||||
|
void Define(IR::Inst* inst, Id def_id) {
|
||||||
|
const InstInfo info{.use_count{inst->UseCount()}, .def_id{def_id}};
|
||||||
|
const auto it{map.insert(map.end(), std::make_pair(inst, info))};
|
||||||
|
if (it == map.end()) {
|
||||||
|
throw LogicError("Defining already defined instruction");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Id Consume(IR::Inst* inst) {
|
||||||
|
const auto it{map.find(inst)};
|
||||||
|
if (it == map.end()) {
|
||||||
|
throw LogicError("Consuming undefined instruction");
|
||||||
|
}
|
||||||
|
const Id def_id{it->second.def_id};
|
||||||
|
if (--it->second.use_count == 0) {
|
||||||
|
map.erase(it);
|
||||||
|
}
|
||||||
|
return def_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct InstInfo {
|
||||||
|
int use_count;
|
||||||
|
Id def_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
boost::container::flat_map<IR::Inst*, InstInfo> map;
|
||||||
|
};
|
||||||
|
|
||||||
|
class VectorTypes {
|
||||||
|
public:
|
||||||
|
void Define(Sirit::Module& sirit_ctx, Id base_type, std::string_view name) {
|
||||||
|
defs[0] = sirit_ctx.Name(base_type, name);
|
||||||
|
|
||||||
|
std::array<char, 6> def_name;
|
||||||
|
for (int i = 1; i < 4; ++i) {
|
||||||
|
const std::string_view def_name_view(
|
||||||
|
def_name.data(),
|
||||||
|
fmt::format_to_n(def_name.data(), def_name.size(), "{}x{}", name, i + 1).size);
|
||||||
|
defs[i] = sirit_ctx.Name(sirit_ctx.TypeVector(base_type, i + 1), def_name_view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Id operator[](size_t size) const noexcept {
|
||||||
|
return defs[size - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::array<Id, 4> defs;
|
||||||
|
};
|
||||||
|
|
||||||
|
class EmitContext final : public Sirit::Module {
|
||||||
|
public:
|
||||||
|
explicit EmitContext(IR::Program& program);
|
||||||
|
~EmitContext();
|
||||||
|
|
||||||
|
[[nodiscard]] Id Def(const IR::Value& value) {
|
||||||
|
if (!value.IsImmediate()) {
|
||||||
|
return def_map.Consume(value.Inst());
|
||||||
|
}
|
||||||
|
switch (value.Type()) {
|
||||||
|
case IR::Type::U32:
|
||||||
|
return Constant(u32[1], value.U32());
|
||||||
|
case IR::Type::F32:
|
||||||
|
return Constant(f32[1], value.F32());
|
||||||
|
default:
|
||||||
|
throw NotImplementedException("Immediate type {}", value.Type());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Define(IR::Inst* inst, Id def_id) {
|
||||||
|
def_map.Define(inst, def_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Id BlockLabel(IR::Block* block) const {
|
||||||
|
const auto it{std::ranges::lower_bound(block_label_map, block, {},
|
||||||
|
&std::pair<IR::Block*, Id>::first)};
|
||||||
|
if (it == block_label_map.end()) {
|
||||||
|
throw LogicError("Undefined block");
|
||||||
|
}
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
Id void_id{};
|
||||||
|
Id u1{};
|
||||||
|
VectorTypes f32;
|
||||||
|
VectorTypes u32;
|
||||||
|
VectorTypes f16;
|
||||||
|
VectorTypes f64;
|
||||||
|
|
||||||
|
Id workgroup_id{};
|
||||||
|
Id local_invocation_id{};
|
||||||
|
|
||||||
|
private:
|
||||||
|
DefMap def_map;
|
||||||
|
std::vector<std::pair<IR::Block*, Id>> block_label_map;
|
||||||
|
};
|
||||||
|
|
||||||
class EmitSPIRV {
|
class EmitSPIRV {
|
||||||
public:
|
public:
|
||||||
|
explicit EmitSPIRV(IR::Program& program);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void EmitInst(EmitContext& ctx, IR::Inst* inst);
|
||||||
|
|
||||||
// Microinstruction emitters
|
// Microinstruction emitters
|
||||||
#define OPCODE(name, result_type, ...) void Emit##name(EmitContext& ctx, IR::Inst* inst);
|
void EmitPhi(EmitContext& ctx);
|
||||||
#include "shader_recompiler/frontend/ir/opcodes.inc"
|
void EmitVoid(EmitContext& ctx);
|
||||||
#undef OPCODE
|
void EmitIdentity(EmitContext& ctx);
|
||||||
|
void EmitBranch(EmitContext& ctx, IR::Inst* inst);
|
||||||
|
void EmitBranchConditional(EmitContext& ctx, IR::Inst* inst);
|
||||||
|
void EmitExit(EmitContext& ctx);
|
||||||
|
void EmitReturn(EmitContext& ctx);
|
||||||
|
void EmitUnreachable(EmitContext& ctx);
|
||||||
|
void EmitGetRegister(EmitContext& ctx);
|
||||||
|
void EmitSetRegister(EmitContext& ctx);
|
||||||
|
void EmitGetPred(EmitContext& ctx);
|
||||||
|
void EmitSetPred(EmitContext& ctx);
|
||||||
|
Id EmitGetCbuf(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset);
|
||||||
|
void EmitGetAttribute(EmitContext& ctx);
|
||||||
|
void EmitSetAttribute(EmitContext& ctx);
|
||||||
|
void EmitGetAttributeIndexed(EmitContext& ctx);
|
||||||
|
void EmitSetAttributeIndexed(EmitContext& ctx);
|
||||||
|
void EmitGetZFlag(EmitContext& ctx);
|
||||||
|
void EmitGetSFlag(EmitContext& ctx);
|
||||||
|
void EmitGetCFlag(EmitContext& ctx);
|
||||||
|
void EmitGetOFlag(EmitContext& ctx);
|
||||||
|
void EmitSetZFlag(EmitContext& ctx);
|
||||||
|
void EmitSetSFlag(EmitContext& ctx);
|
||||||
|
void EmitSetCFlag(EmitContext& ctx);
|
||||||
|
void EmitSetOFlag(EmitContext& ctx);
|
||||||
|
Id EmitWorkgroupId(EmitContext& ctx);
|
||||||
|
Id EmitLocalInvocationId(EmitContext& ctx);
|
||||||
|
void EmitUndef1(EmitContext& ctx);
|
||||||
|
void EmitUndef8(EmitContext& ctx);
|
||||||
|
void EmitUndef16(EmitContext& ctx);
|
||||||
|
void EmitUndef32(EmitContext& ctx);
|
||||||
|
void EmitUndef64(EmitContext& ctx);
|
||||||
|
void EmitLoadGlobalU8(EmitContext& ctx);
|
||||||
|
void EmitLoadGlobalS8(EmitContext& ctx);
|
||||||
|
void EmitLoadGlobalU16(EmitContext& ctx);
|
||||||
|
void EmitLoadGlobalS16(EmitContext& ctx);
|
||||||
|
void EmitLoadGlobal32(EmitContext& ctx);
|
||||||
|
void EmitLoadGlobal64(EmitContext& ctx);
|
||||||
|
void EmitLoadGlobal128(EmitContext& ctx);
|
||||||
|
void EmitWriteGlobalU8(EmitContext& ctx);
|
||||||
|
void EmitWriteGlobalS8(EmitContext& ctx);
|
||||||
|
void EmitWriteGlobalU16(EmitContext& ctx);
|
||||||
|
void EmitWriteGlobalS16(EmitContext& ctx);
|
||||||
|
void EmitWriteGlobal32(EmitContext& ctx);
|
||||||
|
void EmitWriteGlobal64(EmitContext& ctx);
|
||||||
|
void EmitWriteGlobal128(EmitContext& ctx);
|
||||||
|
void EmitLoadStorageU8(EmitContext& ctx);
|
||||||
|
void EmitLoadStorageS8(EmitContext& ctx);
|
||||||
|
void EmitLoadStorageU16(EmitContext& ctx);
|
||||||
|
void EmitLoadStorageS16(EmitContext& ctx);
|
||||||
|
Id EmitLoadStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset);
|
||||||
|
void EmitLoadStorage64(EmitContext& ctx);
|
||||||
|
void EmitLoadStorage128(EmitContext& ctx);
|
||||||
|
void EmitWriteStorageU8(EmitContext& ctx);
|
||||||
|
void EmitWriteStorageS8(EmitContext& ctx);
|
||||||
|
void EmitWriteStorageU16(EmitContext& ctx);
|
||||||
|
void EmitWriteStorageS16(EmitContext& ctx);
|
||||||
|
void EmitWriteStorage32(EmitContext& ctx);
|
||||||
|
void EmitWriteStorage64(EmitContext& ctx);
|
||||||
|
void EmitWriteStorage128(EmitContext& ctx);
|
||||||
|
void EmitCompositeConstructU32x2(EmitContext& ctx);
|
||||||
|
void EmitCompositeConstructU32x3(EmitContext& ctx);
|
||||||
|
void EmitCompositeConstructU32x4(EmitContext& ctx);
|
||||||
|
void EmitCompositeExtractU32x2(EmitContext& ctx);
|
||||||
|
Id EmitCompositeExtractU32x3(EmitContext& ctx, Id vector, u32 index);
|
||||||
|
void EmitCompositeExtractU32x4(EmitContext& ctx);
|
||||||
|
void EmitCompositeConstructF16x2(EmitContext& ctx);
|
||||||
|
void EmitCompositeConstructF16x3(EmitContext& ctx);
|
||||||
|
void EmitCompositeConstructF16x4(EmitContext& ctx);
|
||||||
|
void EmitCompositeExtractF16x2(EmitContext& ctx);
|
||||||
|
void EmitCompositeExtractF16x3(EmitContext& ctx);
|
||||||
|
void EmitCompositeExtractF16x4(EmitContext& ctx);
|
||||||
|
void EmitCompositeConstructF32x2(EmitContext& ctx);
|
||||||
|
void EmitCompositeConstructF32x3(EmitContext& ctx);
|
||||||
|
void EmitCompositeConstructF32x4(EmitContext& ctx);
|
||||||
|
void EmitCompositeExtractF32x2(EmitContext& ctx);
|
||||||
|
void EmitCompositeExtractF32x3(EmitContext& ctx);
|
||||||
|
void EmitCompositeExtractF32x4(EmitContext& ctx);
|
||||||
|
void EmitCompositeConstructF64x2(EmitContext& ctx);
|
||||||
|
void EmitCompositeConstructF64x3(EmitContext& ctx);
|
||||||
|
void EmitCompositeConstructF64x4(EmitContext& ctx);
|
||||||
|
void EmitCompositeExtractF64x2(EmitContext& ctx);
|
||||||
|
void EmitCompositeExtractF64x3(EmitContext& ctx);
|
||||||
|
void EmitCompositeExtractF64x4(EmitContext& ctx);
|
||||||
|
void EmitSelect8(EmitContext& ctx);
|
||||||
|
void EmitSelect16(EmitContext& ctx);
|
||||||
|
void EmitSelect32(EmitContext& ctx);
|
||||||
|
void EmitSelect64(EmitContext& ctx);
|
||||||
|
void EmitBitCastU16F16(EmitContext& ctx);
|
||||||
|
Id EmitBitCastU32F32(EmitContext& ctx, Id value);
|
||||||
|
void EmitBitCastU64F64(EmitContext& ctx);
|
||||||
|
void EmitBitCastF16U16(EmitContext& ctx);
|
||||||
|
Id EmitBitCastF32U32(EmitContext& ctx, Id value);
|
||||||
|
void EmitBitCastF64U64(EmitContext& ctx);
|
||||||
|
void EmitPackUint2x32(EmitContext& ctx);
|
||||||
|
void EmitUnpackUint2x32(EmitContext& ctx);
|
||||||
|
void EmitPackFloat2x16(EmitContext& ctx);
|
||||||
|
void EmitUnpackFloat2x16(EmitContext& ctx);
|
||||||
|
void EmitPackDouble2x32(EmitContext& ctx);
|
||||||
|
void EmitUnpackDouble2x32(EmitContext& ctx);
|
||||||
|
void EmitGetZeroFromOp(EmitContext& ctx);
|
||||||
|
void EmitGetSignFromOp(EmitContext& ctx);
|
||||||
|
void EmitGetCarryFromOp(EmitContext& ctx);
|
||||||
|
void EmitGetOverflowFromOp(EmitContext& ctx);
|
||||||
|
void EmitFPAbs16(EmitContext& ctx);
|
||||||
|
void EmitFPAbs32(EmitContext& ctx);
|
||||||
|
void EmitFPAbs64(EmitContext& ctx);
|
||||||
|
Id EmitFPAdd16(EmitContext& ctx, IR::Inst* inst, Id a, Id b);
|
||||||
|
Id EmitFPAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b);
|
||||||
|
Id EmitFPAdd64(EmitContext& ctx, IR::Inst* inst, Id a, Id b);
|
||||||
|
Id EmitFPFma16(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c);
|
||||||
|
Id EmitFPFma32(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c);
|
||||||
|
Id EmitFPFma64(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c);
|
||||||
|
void EmitFPMax32(EmitContext& ctx);
|
||||||
|
void EmitFPMax64(EmitContext& ctx);
|
||||||
|
void EmitFPMin32(EmitContext& ctx);
|
||||||
|
void EmitFPMin64(EmitContext& ctx);
|
||||||
|
Id EmitFPMul16(EmitContext& ctx, IR::Inst* inst, Id a, Id b);
|
||||||
|
Id EmitFPMul32(EmitContext& ctx, IR::Inst* inst, Id a, Id b);
|
||||||
|
Id EmitFPMul64(EmitContext& ctx, IR::Inst* inst, Id a, Id b);
|
||||||
|
void EmitFPNeg16(EmitContext& ctx);
|
||||||
|
void EmitFPNeg32(EmitContext& ctx);
|
||||||
|
void EmitFPNeg64(EmitContext& ctx);
|
||||||
|
void EmitFPRecip32(EmitContext& ctx);
|
||||||
|
void EmitFPRecip64(EmitContext& ctx);
|
||||||
|
void EmitFPRecipSqrt32(EmitContext& ctx);
|
||||||
|
void EmitFPRecipSqrt64(EmitContext& ctx);
|
||||||
|
void EmitFPSqrt(EmitContext& ctx);
|
||||||
|
void EmitFPSin(EmitContext& ctx);
|
||||||
|
void EmitFPSinNotReduced(EmitContext& ctx);
|
||||||
|
void EmitFPExp2(EmitContext& ctx);
|
||||||
|
void EmitFPExp2NotReduced(EmitContext& ctx);
|
||||||
|
void EmitFPCos(EmitContext& ctx);
|
||||||
|
void EmitFPCosNotReduced(EmitContext& ctx);
|
||||||
|
void EmitFPLog2(EmitContext& ctx);
|
||||||
|
void EmitFPSaturate16(EmitContext& ctx);
|
||||||
|
void EmitFPSaturate32(EmitContext& ctx);
|
||||||
|
void EmitFPSaturate64(EmitContext& ctx);
|
||||||
|
void EmitFPRoundEven16(EmitContext& ctx);
|
||||||
|
void EmitFPRoundEven32(EmitContext& ctx);
|
||||||
|
void EmitFPRoundEven64(EmitContext& ctx);
|
||||||
|
void EmitFPFloor16(EmitContext& ctx);
|
||||||
|
void EmitFPFloor32(EmitContext& ctx);
|
||||||
|
void EmitFPFloor64(EmitContext& ctx);
|
||||||
|
void EmitFPCeil16(EmitContext& ctx);
|
||||||
|
void EmitFPCeil32(EmitContext& ctx);
|
||||||
|
void EmitFPCeil64(EmitContext& ctx);
|
||||||
|
void EmitFPTrunc16(EmitContext& ctx);
|
||||||
|
void EmitFPTrunc32(EmitContext& ctx);
|
||||||
|
void EmitFPTrunc64(EmitContext& ctx);
|
||||||
|
Id EmitIAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b);
|
||||||
|
void EmitIAdd64(EmitContext& ctx);
|
||||||
|
Id EmitISub32(EmitContext& ctx, Id a, Id b);
|
||||||
|
void EmitISub64(EmitContext& ctx);
|
||||||
|
Id EmitIMul32(EmitContext& ctx, Id a, Id b);
|
||||||
|
void EmitINeg32(EmitContext& ctx);
|
||||||
|
void EmitIAbs32(EmitContext& ctx);
|
||||||
|
Id EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift);
|
||||||
|
void EmitShiftRightLogical32(EmitContext& ctx);
|
||||||
|
void EmitShiftRightArithmetic32(EmitContext& ctx);
|
||||||
|
void EmitBitwiseAnd32(EmitContext& ctx);
|
||||||
|
void EmitBitwiseOr32(EmitContext& ctx);
|
||||||
|
void EmitBitwiseXor32(EmitContext& ctx);
|
||||||
|
void EmitBitFieldInsert(EmitContext& ctx);
|
||||||
|
void EmitBitFieldSExtract(EmitContext& ctx);
|
||||||
|
Id EmitBitFieldUExtract(EmitContext& ctx, Id base, Id offset, Id count);
|
||||||
|
void EmitSLessThan(EmitContext& ctx);
|
||||||
|
void EmitULessThan(EmitContext& ctx);
|
||||||
|
void EmitIEqual(EmitContext& ctx);
|
||||||
|
void EmitSLessThanEqual(EmitContext& ctx);
|
||||||
|
void EmitULessThanEqual(EmitContext& ctx);
|
||||||
|
void EmitSGreaterThan(EmitContext& ctx);
|
||||||
|
void EmitUGreaterThan(EmitContext& ctx);
|
||||||
|
void EmitINotEqual(EmitContext& ctx);
|
||||||
|
void EmitSGreaterThanEqual(EmitContext& ctx);
|
||||||
|
Id EmitUGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs);
|
||||||
|
void EmitLogicalOr(EmitContext& ctx);
|
||||||
|
void EmitLogicalAnd(EmitContext& ctx);
|
||||||
|
void EmitLogicalXor(EmitContext& ctx);
|
||||||
|
void EmitLogicalNot(EmitContext& ctx);
|
||||||
|
void EmitConvertS16F16(EmitContext& ctx);
|
||||||
|
void EmitConvertS16F32(EmitContext& ctx);
|
||||||
|
void EmitConvertS16F64(EmitContext& ctx);
|
||||||
|
void EmitConvertS32F16(EmitContext& ctx);
|
||||||
|
void EmitConvertS32F32(EmitContext& ctx);
|
||||||
|
void EmitConvertS32F64(EmitContext& ctx);
|
||||||
|
void EmitConvertS64F16(EmitContext& ctx);
|
||||||
|
void EmitConvertS64F32(EmitContext& ctx);
|
||||||
|
void EmitConvertS64F64(EmitContext& ctx);
|
||||||
|
void EmitConvertU16F16(EmitContext& ctx);
|
||||||
|
void EmitConvertU16F32(EmitContext& ctx);
|
||||||
|
void EmitConvertU16F64(EmitContext& ctx);
|
||||||
|
void EmitConvertU32F16(EmitContext& ctx);
|
||||||
|
void EmitConvertU32F32(EmitContext& ctx);
|
||||||
|
void EmitConvertU32F64(EmitContext& ctx);
|
||||||
|
void EmitConvertU64F16(EmitContext& ctx);
|
||||||
|
void EmitConvertU64F32(EmitContext& ctx);
|
||||||
|
void EmitConvertU64F64(EmitContext& ctx);
|
||||||
|
void EmitConvertU64U32(EmitContext& ctx);
|
||||||
|
void EmitConvertU32U64(EmitContext& ctx);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Shader::Backend::SPIRV
|
} // namespace Shader::Backend::SPIRV
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
// Copyright 2021 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "shader_recompiler/backend/spirv/emit_spirv.h"
|
||||||
|
|
||||||
|
namespace Shader::Backend::SPIRV {
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitBitCastU16F16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
Id EmitSPIRV::EmitBitCastU32F32(EmitContext& ctx, Id value) {
|
||||||
|
return ctx.OpBitcast(ctx.u32[1], value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitBitCastU64F64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitBitCastF16U16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
Id EmitSPIRV::EmitBitCastF32U32(EmitContext& ctx, Id value) {
|
||||||
|
return ctx.OpBitcast(ctx.f32[1], value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitBitCastF64U64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitPackUint2x32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitUnpackUint2x32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitPackFloat2x16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitUnpackFloat2x16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitPackDouble2x32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitUnpackDouble2x32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Shader::Backend::SPIRV
|
|
@ -0,0 +1,105 @@
|
||||||
|
// Copyright 2021 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "shader_recompiler/backend/spirv/emit_spirv.h"
|
||||||
|
|
||||||
|
namespace Shader::Backend::SPIRV {
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitCompositeConstructU32x2(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitCompositeConstructU32x3(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitCompositeConstructU32x4(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitCompositeExtractU32x2(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
Id EmitSPIRV::EmitCompositeExtractU32x3(EmitContext& ctx, Id vector, u32 index) {
|
||||||
|
return ctx.OpCompositeExtract(ctx.u32[1], vector, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitCompositeExtractU32x4(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitCompositeConstructF16x2(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitCompositeConstructF16x3(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitCompositeConstructF16x4(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitCompositeExtractF16x2(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitCompositeExtractF16x3(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitCompositeExtractF16x4(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitCompositeConstructF32x2(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitCompositeConstructF32x3(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitCompositeConstructF32x4(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitCompositeExtractF32x2(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitCompositeExtractF32x3(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitCompositeExtractF32x4(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitCompositeConstructF64x2(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitCompositeConstructF64x3(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitCompositeConstructF64x4(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitCompositeExtractF64x2(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitCompositeExtractF64x3(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitCompositeExtractF64x4(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Shader::Backend::SPIRV
|
|
@ -0,0 +1,102 @@
|
||||||
|
// Copyright 2021 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "shader_recompiler/backend/spirv/emit_spirv.h"
|
||||||
|
|
||||||
|
namespace Shader::Backend::SPIRV {
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitGetRegister(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitSetRegister(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitGetPred(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitSetPred(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
Id EmitSPIRV::EmitGetCbuf(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
|
||||||
|
if (!binding.IsImmediate()) {
|
||||||
|
throw NotImplementedException("Constant buffer indexing");
|
||||||
|
}
|
||||||
|
if (!offset.IsImmediate()) {
|
||||||
|
throw NotImplementedException("Variable constant buffer offset");
|
||||||
|
}
|
||||||
|
return ctx.Name(ctx.OpUndef(ctx.u32[1]), "unimplemented_cbuf");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitGetAttribute(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitSetAttribute(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitGetAttributeIndexed(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitSetAttributeIndexed(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitGetZFlag(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitGetSFlag(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitGetCFlag(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitGetOFlag(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitSetZFlag(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitSetSFlag(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitSetCFlag(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitSetOFlag(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
Id EmitSPIRV::EmitWorkgroupId(EmitContext& ctx) {
|
||||||
|
if (ctx.workgroup_id.value == 0) {
|
||||||
|
ctx.workgroup_id = ctx.AddGlobalVariable(
|
||||||
|
ctx.TypePointer(spv::StorageClass::Input, ctx.u32[3]), spv::StorageClass::Input);
|
||||||
|
ctx.Decorate(ctx.workgroup_id, spv::Decoration::BuiltIn, spv::BuiltIn::WorkgroupId);
|
||||||
|
}
|
||||||
|
return ctx.OpLoad(ctx.u32[3], ctx.workgroup_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Id EmitSPIRV::EmitLocalInvocationId(EmitContext& ctx) {
|
||||||
|
if (ctx.local_invocation_id.value == 0) {
|
||||||
|
ctx.local_invocation_id = ctx.AddGlobalVariable(
|
||||||
|
ctx.TypePointer(spv::StorageClass::Input, ctx.u32[3]), spv::StorageClass::Input);
|
||||||
|
ctx.Decorate(ctx.local_invocation_id, spv::Decoration::BuiltIn,
|
||||||
|
spv::BuiltIn::LocalInvocationId);
|
||||||
|
}
|
||||||
|
return ctx.OpLoad(ctx.u32[3], ctx.local_invocation_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Shader::Backend::SPIRV
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright 2021 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "shader_recompiler/backend/spirv/emit_spirv.h"
|
||||||
|
|
||||||
|
namespace Shader::Backend::SPIRV {
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitBranch(EmitContext& ctx, IR::Inst* inst) {
|
||||||
|
ctx.OpBranch(ctx.BlockLabel(inst->Arg(0).Label()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitBranchConditional(EmitContext& ctx, IR::Inst* inst) {
|
||||||
|
ctx.OpBranchConditional(ctx.Def(inst->Arg(0)), ctx.BlockLabel(inst->Arg(1).Label()),
|
||||||
|
ctx.BlockLabel(inst->Arg(2).Label()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitExit(EmitContext& ctx) {
|
||||||
|
ctx.OpReturn();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitReturn(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitUnreachable(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Shader::Backend::SPIRV
|
|
@ -0,0 +1,220 @@
|
||||||
|
// Copyright 2021 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "shader_recompiler/backend/spirv/emit_spirv.h"
|
||||||
|
#include "shader_recompiler/frontend/ir/modifiers.h"
|
||||||
|
|
||||||
|
namespace Shader::Backend::SPIRV {
|
||||||
|
namespace {
|
||||||
|
Id Decorate(EmitContext& ctx, IR::Inst* inst, Id op) {
|
||||||
|
const auto flags{inst->Flags<IR::FpControl>()};
|
||||||
|
if (flags.no_contraction) {
|
||||||
|
ctx.Decorate(op, spv::Decoration::NoContraction);
|
||||||
|
}
|
||||||
|
switch (flags.rounding) {
|
||||||
|
case IR::FpRounding::RN:
|
||||||
|
break;
|
||||||
|
case IR::FpRounding::RM:
|
||||||
|
ctx.Decorate(op, spv::Decoration::FPRoundingMode, spv::FPRoundingMode::RTN);
|
||||||
|
break;
|
||||||
|
case IR::FpRounding::RP:
|
||||||
|
ctx.Decorate(op, spv::Decoration::FPRoundingMode, spv::FPRoundingMode::RTP);
|
||||||
|
break;
|
||||||
|
case IR::FpRounding::RZ:
|
||||||
|
ctx.Decorate(op, spv::Decoration::FPRoundingMode, spv::FPRoundingMode::RTZ);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (flags.fmz_mode != IR::FmzMode::FTZ) {
|
||||||
|
throw NotImplementedException("Denorm management not implemented");
|
||||||
|
}
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPAbs16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPAbs32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPAbs64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
Id EmitSPIRV::EmitFPAdd16(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
|
||||||
|
return Decorate(ctx, inst, ctx.OpFAdd(ctx.f16[1], a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
Id EmitSPIRV::EmitFPAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
|
||||||
|
return Decorate(ctx, inst, ctx.OpFAdd(ctx.f32[1], a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
Id EmitSPIRV::EmitFPAdd64(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
|
||||||
|
return Decorate(ctx, inst, ctx.OpFAdd(ctx.f64[1], a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
Id EmitSPIRV::EmitFPFma16(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c) {
|
||||||
|
return Decorate(ctx, inst, ctx.OpFma(ctx.f16[1], a, b, c));
|
||||||
|
}
|
||||||
|
|
||||||
|
Id EmitSPIRV::EmitFPFma32(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c) {
|
||||||
|
return Decorate(ctx, inst, ctx.OpFma(ctx.f32[1], a, b, c));
|
||||||
|
}
|
||||||
|
|
||||||
|
Id EmitSPIRV::EmitFPFma64(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c) {
|
||||||
|
return Decorate(ctx, inst, ctx.OpFma(ctx.f64[1], a, b, c));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPMax32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPMax64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPMin32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPMin64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
Id EmitSPIRV::EmitFPMul16(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
|
||||||
|
return Decorate(ctx, inst, ctx.OpFMul(ctx.f16[1], a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
Id EmitSPIRV::EmitFPMul32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
|
||||||
|
return Decorate(ctx, inst, ctx.OpFMul(ctx.f32[1], a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
Id EmitSPIRV::EmitFPMul64(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
|
||||||
|
return Decorate(ctx, inst, ctx.OpFMul(ctx.f64[1], a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPNeg16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPNeg32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPNeg64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPRecip32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPRecip64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPRecipSqrt32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPRecipSqrt64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPSqrt(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPSin(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPSinNotReduced(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPExp2(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPExp2NotReduced(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPCos(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPCosNotReduced(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPLog2(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPSaturate16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPSaturate32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPSaturate64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPRoundEven16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPRoundEven32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPRoundEven64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPFloor16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPFloor32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPFloor64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPCeil16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPCeil32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPCeil64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPTrunc16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPTrunc32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitFPTrunc64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Shader::Backend::SPIRV
|
|
@ -0,0 +1,132 @@
|
||||||
|
// Copyright 2021 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "shader_recompiler/backend/spirv/emit_spirv.h"
|
||||||
|
|
||||||
|
namespace Shader::Backend::SPIRV {
|
||||||
|
|
||||||
|
Id EmitSPIRV::EmitIAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
|
||||||
|
if (inst->HasAssociatedPseudoOperation()) {
|
||||||
|
throw NotImplementedException("Pseudo-operations on IAdd32");
|
||||||
|
}
|
||||||
|
return ctx.OpIAdd(ctx.u32[1], a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitIAdd64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
Id EmitSPIRV::EmitISub32(EmitContext& ctx, Id a, Id b) {
|
||||||
|
return ctx.OpISub(ctx.u32[1], a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitISub64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
Id EmitSPIRV::EmitIMul32(EmitContext& ctx, Id a, Id b) {
|
||||||
|
return ctx.OpIMul(ctx.u32[1], a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitINeg32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitIAbs32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
Id EmitSPIRV::EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift) {
|
||||||
|
return ctx.OpShiftLeftLogical(ctx.u32[1], base, shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitShiftRightLogical32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitShiftRightArithmetic32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitBitwiseAnd32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitBitwiseOr32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitBitwiseXor32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitBitFieldInsert(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitBitFieldSExtract(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
Id EmitSPIRV::EmitBitFieldUExtract(EmitContext& ctx, Id base, Id offset, Id count) {
|
||||||
|
return ctx.OpBitFieldUExtract(ctx.u32[1], base, offset, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitSLessThan(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitULessThan(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitIEqual(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitSLessThanEqual(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitULessThanEqual(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitSGreaterThan(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitUGreaterThan(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitINotEqual(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitSGreaterThanEqual(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
Id EmitSPIRV::EmitUGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs) {
|
||||||
|
return ctx.OpUGreaterThanEqual(ctx.u1, lhs, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitLogicalOr(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitLogicalAnd(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitLogicalXor(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitLogicalNot(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Shader::Backend::SPIRV
|
|
@ -0,0 +1,89 @@
|
||||||
|
// Copyright 2021 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "shader_recompiler/backend/spirv/emit_spirv.h"
|
||||||
|
|
||||||
|
namespace Shader::Backend::SPIRV {
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitConvertS16F16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitConvertS16F32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitConvertS16F64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitConvertS32F16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitConvertS32F32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitConvertS32F64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitConvertS64F16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitConvertS64F32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitConvertS64F64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitConvertU16F16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitConvertU16F32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitConvertU16F64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitConvertU32F16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitConvertU32F32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitConvertU32F64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitConvertU64F16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitConvertU64F32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitConvertU64F64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitConvertU64U32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitConvertU32U64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Shader::Backend::SPIRV
|
|
@ -0,0 +1,125 @@
|
||||||
|
// Copyright 2021 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "shader_recompiler/backend/spirv/emit_spirv.h"
|
||||||
|
|
||||||
|
namespace Shader::Backend::SPIRV {
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitLoadGlobalU8(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitLoadGlobalS8(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitLoadGlobalU16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitLoadGlobalS16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitLoadGlobal32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitLoadGlobal64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitLoadGlobal128(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitWriteGlobalU8(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitWriteGlobalS8(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitWriteGlobalU16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitWriteGlobalS16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitWriteGlobal32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitWriteGlobal64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitWriteGlobal128(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitLoadStorageU8(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitLoadStorageS8(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitLoadStorageU16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitLoadStorageS16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
Id EmitSPIRV::EmitLoadStorage32(EmitContext& ctx, const IR::Value& binding,
|
||||||
|
[[maybe_unused]] const IR::Value& offset) {
|
||||||
|
if (!binding.IsImmediate()) {
|
||||||
|
throw NotImplementedException("Storage buffer indexing");
|
||||||
|
}
|
||||||
|
return ctx.Name(ctx.OpUndef(ctx.u32[1]), "unimplemented_sbuf");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitLoadStorage64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitLoadStorage128(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitWriteStorageU8(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitWriteStorageS8(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitWriteStorageU16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitWriteStorageS16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitWriteStorage32(EmitContext& ctx) {
|
||||||
|
ctx.Name(ctx.OpUndef(ctx.u32[1]), "unimplemented_sbuf_store");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitWriteStorage64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitWriteStorage128(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Shader::Backend::SPIRV
|
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright 2021 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "shader_recompiler/backend/spirv/emit_spirv.h"
|
||||||
|
|
||||||
|
namespace Shader::Backend::SPIRV {
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitSelect8(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitSelect16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitSelect32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitSelect64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Shader::Backend::SPIRV
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright 2021 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "shader_recompiler/backend/spirv/emit_spirv.h"
|
||||||
|
|
||||||
|
namespace Shader::Backend::SPIRV {
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitUndef1(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitUndef8(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitUndef16(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitUndef32(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitSPIRV::EmitUndef64(EmitContext&) {
|
||||||
|
throw NotImplementedException("SPIR-V Instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Shader::Backend::SPIRV
|
|
@ -130,27 +130,27 @@ void IREmitter::SetAttribute(IR::Attribute attribute, const F32& value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
U32 IREmitter::WorkgroupIdX() {
|
U32 IREmitter::WorkgroupIdX() {
|
||||||
return Inst<U32>(Opcode::WorkgroupIdX);
|
return U32{CompositeExtract(Inst(Opcode::WorkgroupId), 0)};
|
||||||
}
|
}
|
||||||
|
|
||||||
U32 IREmitter::WorkgroupIdY() {
|
U32 IREmitter::WorkgroupIdY() {
|
||||||
return Inst<U32>(Opcode::WorkgroupIdY);
|
return U32{CompositeExtract(Inst(Opcode::WorkgroupId), 1)};
|
||||||
}
|
}
|
||||||
|
|
||||||
U32 IREmitter::WorkgroupIdZ() {
|
U32 IREmitter::WorkgroupIdZ() {
|
||||||
return Inst<U32>(Opcode::WorkgroupIdZ);
|
return U32{CompositeExtract(Inst(Opcode::WorkgroupId), 2)};
|
||||||
}
|
}
|
||||||
|
|
||||||
U32 IREmitter::LocalInvocationIdX() {
|
U32 IREmitter::LocalInvocationIdX() {
|
||||||
return Inst<U32>(Opcode::LocalInvocationIdX);
|
return U32{CompositeExtract(Inst(Opcode::LocalInvocationId), 0)};
|
||||||
}
|
}
|
||||||
|
|
||||||
U32 IREmitter::LocalInvocationIdY() {
|
U32 IREmitter::LocalInvocationIdY() {
|
||||||
return Inst<U32>(Opcode::LocalInvocationIdY);
|
return U32{CompositeExtract(Inst(Opcode::LocalInvocationId), 1)};
|
||||||
}
|
}
|
||||||
|
|
||||||
U32 IREmitter::LocalInvocationIdZ() {
|
U32 IREmitter::LocalInvocationIdZ() {
|
||||||
return Inst<U32>(Opcode::LocalInvocationIdZ);
|
return U32{CompositeExtract(Inst(Opcode::LocalInvocationId), 2)};
|
||||||
}
|
}
|
||||||
|
|
||||||
U32 IREmitter::LoadGlobalU8(const U64& address) {
|
U32 IREmitter::LoadGlobalU8(const U64& address) {
|
||||||
|
|
|
@ -21,9 +21,9 @@ OPCODE(GetPred, U1, Pred
|
||||||
OPCODE(SetPred, Void, Pred, U1, )
|
OPCODE(SetPred, Void, Pred, U1, )
|
||||||
OPCODE(GetCbuf, U32, U32, U32, )
|
OPCODE(GetCbuf, U32, U32, U32, )
|
||||||
OPCODE(GetAttribute, U32, Attribute, )
|
OPCODE(GetAttribute, U32, Attribute, )
|
||||||
OPCODE(SetAttribute, U32, Attribute, )
|
OPCODE(SetAttribute, Void, Attribute, U32, )
|
||||||
OPCODE(GetAttributeIndexed, U32, U32, )
|
OPCODE(GetAttributeIndexed, U32, U32, )
|
||||||
OPCODE(SetAttributeIndexed, U32, U32, )
|
OPCODE(SetAttributeIndexed, Void, U32, U32, )
|
||||||
OPCODE(GetZFlag, U1, Void, )
|
OPCODE(GetZFlag, U1, Void, )
|
||||||
OPCODE(GetSFlag, U1, Void, )
|
OPCODE(GetSFlag, U1, Void, )
|
||||||
OPCODE(GetCFlag, U1, Void, )
|
OPCODE(GetCFlag, U1, Void, )
|
||||||
|
@ -32,12 +32,8 @@ OPCODE(SetZFlag, Void, U1,
|
||||||
OPCODE(SetSFlag, Void, U1, )
|
OPCODE(SetSFlag, Void, U1, )
|
||||||
OPCODE(SetCFlag, Void, U1, )
|
OPCODE(SetCFlag, Void, U1, )
|
||||||
OPCODE(SetOFlag, Void, U1, )
|
OPCODE(SetOFlag, Void, U1, )
|
||||||
OPCODE(WorkgroupIdX, U32, )
|
OPCODE(WorkgroupId, U32x3, )
|
||||||
OPCODE(WorkgroupIdY, U32, )
|
OPCODE(LocalInvocationId, U32x3, )
|
||||||
OPCODE(WorkgroupIdZ, U32, )
|
|
||||||
OPCODE(LocalInvocationIdX, U32, )
|
|
||||||
OPCODE(LocalInvocationIdY, U32, )
|
|
||||||
OPCODE(LocalInvocationIdZ, U32, )
|
|
||||||
|
|
||||||
// Undefined
|
// Undefined
|
||||||
OPCODE(Undef1, U1, )
|
OPCODE(Undef1, U1, )
|
||||||
|
|
|
@ -11,15 +11,15 @@
|
||||||
|
|
||||||
namespace Shader::Maxwell {
|
namespace Shader::Maxwell {
|
||||||
|
|
||||||
template <auto visitor_method>
|
template <auto method>
|
||||||
static void Invoke(TranslatorVisitor& visitor, Location pc, u64 insn) {
|
static void Invoke(TranslatorVisitor& visitor, Location pc, u64 insn) {
|
||||||
using MethodType = decltype(visitor_method);
|
using MethodType = decltype(method);
|
||||||
if constexpr (std::is_invocable_r_v<void, MethodType, TranslatorVisitor&, Location, u64>) {
|
if constexpr (std::is_invocable_r_v<void, MethodType, TranslatorVisitor&, Location, u64>) {
|
||||||
(visitor.*visitor_method)(pc, insn);
|
(visitor.*method)(pc, insn);
|
||||||
} else if constexpr (std::is_invocable_r_v<void, MethodType, TranslatorVisitor&, u64>) {
|
} else if constexpr (std::is_invocable_r_v<void, MethodType, TranslatorVisitor&, u64>) {
|
||||||
(visitor.*visitor_method)(insn);
|
(visitor.*method)(insn);
|
||||||
} else {
|
} else {
|
||||||
(visitor.*visitor_method)();
|
(visitor.*method)();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace Shader::Optimization {
|
||||||
void IdentityRemovalPass(IR::Function& function) {
|
void IdentityRemovalPass(IR::Function& function) {
|
||||||
std::vector<IR::Inst*> to_invalidate;
|
std::vector<IR::Inst*> to_invalidate;
|
||||||
|
|
||||||
for (auto& block : function.blocks) {
|
for (IR::Block* const block : function.blocks) {
|
||||||
for (auto inst = block->begin(); inst != block->end();) {
|
for (auto inst = block->begin(); inst != block->end();) {
|
||||||
const size_t num_args{inst->NumArgs()};
|
const size_t num_args{inst->NumArgs()};
|
||||||
for (size_t i = 0; i < num_args; ++i) {
|
for (size_t i = 0; i < num_args; ++i) {
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#include "shader_recompiler/backend/spirv/emit_spirv.h"
|
||||||
#include "shader_recompiler/file_environment.h"
|
#include "shader_recompiler/file_environment.h"
|
||||||
#include "shader_recompiler/frontend/ir/basic_block.h"
|
#include "shader_recompiler/frontend/ir/basic_block.h"
|
||||||
#include "shader_recompiler/frontend/ir/ir_emitter.h"
|
#include "shader_recompiler/frontend/ir/ir_emitter.h"
|
||||||
|
@ -51,18 +52,18 @@ void RunDatabase() {
|
||||||
int main() {
|
int main() {
|
||||||
// RunDatabase();
|
// RunDatabase();
|
||||||
|
|
||||||
// FileEnvironment env{"D:\\Shaders\\Database\\test.bin"};
|
|
||||||
FileEnvironment env{"D:\\Shaders\\Database\\Oninaki\\CS15C2FB1F0B965767.bin"};
|
|
||||||
auto cfg{std::make_unique<Flow::CFG>(env, 0)};
|
|
||||||
// fmt::print(stdout, "{}\n", cfg->Dot());
|
|
||||||
|
|
||||||
auto inst_pool{std::make_unique<ObjectPool<IR::Inst>>()};
|
auto inst_pool{std::make_unique<ObjectPool<IR::Inst>>()};
|
||||||
auto block_pool{std::make_unique<ObjectPool<IR::Block>>()};
|
auto block_pool{std::make_unique<ObjectPool<IR::Block>>()};
|
||||||
|
|
||||||
for (int i = 0; i < 8192 * 4; ++i) {
|
// FileEnvironment env{"D:\\Shaders\\Database\\test.bin"};
|
||||||
void(inst_pool->Create(IR::Opcode::Void, 0));
|
FileEnvironment env{"D:\\Shaders\\Database\\Oninaki\\CS15C2FB1F0B965767.bin"};
|
||||||
|
for (int i = 0; i < 1; ++i) {
|
||||||
|
block_pool->ReleaseContents();
|
||||||
|
inst_pool->ReleaseContents();
|
||||||
|
auto cfg{std::make_unique<Flow::CFG>(env, 0)};
|
||||||
|
// fmt::print(stdout, "{}\n", cfg->Dot());
|
||||||
|
IR::Program program{TranslateProgram(*inst_pool, *block_pool, env, *cfg)};
|
||||||
|
// fmt::print(stdout, "{}\n", IR::DumpProgram(program));
|
||||||
|
Backend::SPIRV::EmitSPIRV spirv{program};
|
||||||
}
|
}
|
||||||
|
|
||||||
IR::Program program{TranslateProgram(*inst_pool, *block_pool, env, *cfg)};
|
|
||||||
fmt::print(stdout, "{}\n", IR::DumpProgram(program));
|
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,99 +0,0 @@
|
||||||
// Copyright 2019 yuzu Emulator Project
|
|
||||||
// Licensed under GPLv2 or any later version
|
|
||||||
// Refer to the license.txt file included.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <set>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "common/common_types.h"
|
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
|
||||||
#include "video_core/engines/shader_type.h"
|
|
||||||
#include "video_core/shader/registry.h"
|
|
||||||
#include "video_core/shader/shader_ir.h"
|
|
||||||
|
|
||||||
namespace Vulkan {
|
|
||||||
|
|
||||||
class Device;
|
|
||||||
|
|
||||||
using Maxwell = Tegra::Engines::Maxwell3D::Regs;
|
|
||||||
using UniformTexelEntry = VideoCommon::Shader::SamplerEntry;
|
|
||||||
using SamplerEntry = VideoCommon::Shader::SamplerEntry;
|
|
||||||
using StorageTexelEntry = VideoCommon::Shader::ImageEntry;
|
|
||||||
using ImageEntry = VideoCommon::Shader::ImageEntry;
|
|
||||||
|
|
||||||
constexpr u32 DESCRIPTOR_SET = 0;
|
|
||||||
|
|
||||||
class ConstBufferEntry : public VideoCommon::Shader::ConstBuffer {
|
|
||||||
public:
|
|
||||||
explicit constexpr ConstBufferEntry(const ConstBuffer& entry_, u32 index_)
|
|
||||||
: ConstBuffer{entry_}, index{index_} {}
|
|
||||||
|
|
||||||
constexpr u32 GetIndex() const {
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
u32 index{};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GlobalBufferEntry {
|
|
||||||
u32 cbuf_index{};
|
|
||||||
u32 cbuf_offset{};
|
|
||||||
bool is_written{};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ShaderEntries {
|
|
||||||
u32 NumBindings() const {
|
|
||||||
return static_cast<u32>(const_buffers.size() + global_buffers.size() +
|
|
||||||
uniform_texels.size() + samplers.size() + storage_texels.size() +
|
|
||||||
images.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<ConstBufferEntry> const_buffers;
|
|
||||||
std::vector<GlobalBufferEntry> global_buffers;
|
|
||||||
std::vector<UniformTexelEntry> uniform_texels;
|
|
||||||
std::vector<SamplerEntry> samplers;
|
|
||||||
std::vector<StorageTexelEntry> storage_texels;
|
|
||||||
std::vector<ImageEntry> images;
|
|
||||||
std::set<u32> attributes;
|
|
||||||
std::array<bool, Maxwell::NumClipDistances> clip_distances{};
|
|
||||||
std::size_t shader_length{};
|
|
||||||
u32 enabled_uniform_buffers{};
|
|
||||||
bool uses_warps{};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Specialization final {
|
|
||||||
u32 base_binding{};
|
|
||||||
|
|
||||||
// Compute specific
|
|
||||||
std::array<u32, 3> workgroup_size{};
|
|
||||||
u32 shared_memory_size{};
|
|
||||||
|
|
||||||
// Graphics specific
|
|
||||||
std::optional<float> point_size;
|
|
||||||
std::bitset<Maxwell::NumVertexAttributes> enabled_attributes;
|
|
||||||
std::array<Maxwell::VertexAttribute::Type, Maxwell::NumVertexAttributes> attribute_types{};
|
|
||||||
bool ndc_minus_one_to_one{};
|
|
||||||
bool early_fragment_tests{};
|
|
||||||
float alpha_test_ref{};
|
|
||||||
Maxwell::ComparisonOp alpha_test_func{};
|
|
||||||
};
|
|
||||||
// Old gcc versions don't consider this trivially copyable.
|
|
||||||
// static_assert(std::is_trivially_copyable_v<Specialization>);
|
|
||||||
|
|
||||||
struct SPIRVShader {
|
|
||||||
std::vector<u32> code;
|
|
||||||
ShaderEntries entries;
|
|
||||||
};
|
|
||||||
|
|
||||||
ShaderEntries GenerateShaderEntries(const VideoCommon::Shader::ShaderIR& ir);
|
|
||||||
|
|
||||||
std::vector<u32> Decompile(const Device& device, const VideoCommon::Shader::ShaderIR& ir,
|
|
||||||
Tegra::Engines::ShaderType stage,
|
|
||||||
const VideoCommon::Shader::Registry& registry,
|
|
||||||
const Specialization& specialization);
|
|
||||||
|
|
||||||
} // namespace Vulkan
|
|
Loading…
Reference in New Issue