Merge pull request #64 from brenwill/master

Support MSL-specific functions
This commit is contained in:
Hans-Kristian Arntzen 2016-10-28 09:09:35 +02:00 committed by GitHub
commit 8199986c0e
3 changed files with 134 additions and 18 deletions

View File

@ -136,6 +136,8 @@ protected:
// Virtualize methods which need to be overridden by subclass targets like C++ and such. // Virtualize methods which need to be overridden by subclass targets like C++ and such.
virtual void emit_function_prototype(SPIRFunction &func, uint64_t return_flags); virtual void emit_function_prototype(SPIRFunction &func, uint64_t return_flags);
virtual void emit_instruction(const Instruction &instr);
virtual void emit_glsl_op(uint32_t result_type, uint32_t result_id, uint32_t op, const uint32_t *args, uint32_t count);
virtual void emit_header(); virtual void emit_header();
virtual void emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id); virtual void emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id);
virtual void emit_texture_op(const Instruction &i); virtual void emit_texture_op(const Instruction &i);
@ -236,8 +238,6 @@ protected:
} backend; } backend;
void emit_struct(SPIRType &type); void emit_struct(SPIRType &type);
void emit_instruction(const Instruction &instr);
void emit_resources(); void emit_resources();
void emit_buffer_block(const SPIRVariable &type); void emit_buffer_block(const SPIRVariable &type);
void emit_push_constant_block(const SPIRVariable &var); void emit_push_constant_block(const SPIRVariable &var);
@ -261,7 +261,6 @@ protected:
bool should_forward(uint32_t id); bool should_forward(uint32_t id);
void emit_mix_op(uint32_t result_type, uint32_t id, uint32_t left, uint32_t right, uint32_t lerp); void emit_mix_op(uint32_t result_type, uint32_t id, uint32_t left, uint32_t right, uint32_t lerp);
bool to_trivial_mix_op(const SPIRType &type, std::string &op, uint32_t left, uint32_t right, uint32_t lerp); bool to_trivial_mix_op(const SPIRType &type, std::string &op, uint32_t left, uint32_t right, uint32_t lerp);
void emit_glsl_op(uint32_t result_type, uint32_t result_id, uint32_t op, const uint32_t *args, uint32_t count);
void emit_quaternary_func_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, uint32_t op2, void emit_quaternary_func_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, uint32_t op2,
uint32_t op3, const char *op); uint32_t op3, const char *op);
void emit_trinary_func_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, uint32_t op2, void emit_trinary_func_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, uint32_t op2,

View File

@ -15,6 +15,7 @@
*/ */
#include "spirv_msl.hpp" #include "spirv_msl.hpp"
#include "GLSL.std.450.h"
#include <algorithm> #include <algorithm>
#include <numeric> #include <numeric>
@ -61,7 +62,7 @@ string CompilerMSL::compile(MSLConfiguration &msl_cfg, vector<MSLVertexAttr> *p_
// Do not deal with ES-isms like precision, older extensions and such. // Do not deal with ES-isms like precision, older extensions and such.
options.es = false; options.es = false;
options.version = 1; options.version = 120;
backend.float_literal_suffix = false; backend.float_literal_suffix = false;
backend.uint32_t_literal_suffix = true; backend.uint32_t_literal_suffix = true;
backend.basic_int_type = "int"; backend.basic_int_type = "int";
@ -516,19 +517,6 @@ void CompilerMSL::emit_header()
statement(""); statement("");
statement("using namespace metal;"); statement("using namespace metal;");
statement(""); statement("");
emit_msl_defines();
}
void CompilerMSL::emit_msl_defines()
{
statement("// Standard GLSL->MSL redefinitions");
statement("#define dFdy dfdy");
statement("#define dFdx dfdy");
statement("#define atan(y,x) atan2((y),(x))");
statement("#define greaterThan(a,b) ((a)>(b))");
statement("inline uint2 imageSize(thread const texture2d<float>& tex) { return uint2(tex.get_width(), "
"tex.get_height()); }");
statement("");
} }
void CompilerMSL::emit_resources() void CompilerMSL::emit_resources()
@ -578,6 +566,134 @@ void CompilerMSL::emit_resources()
// TODO: Consolidate and output loose uniforms into an input struct // TODO: Consolidate and output loose uniforms into an input struct
} }
// Override for MSL-specific syntax instructions
void CompilerMSL::emit_instruction(const Instruction &instruction)
{
#define BOP(op) emit_binary_op(ops[0], ops[1], ops[2], ops[3], #op)
#define BOP_CAST(op, type) emit_binary_op_cast(ops[0], ops[1], ops[2], ops[3], #op, type, opcode_is_sign_invariant(opcode))
#define UOP(op) emit_unary_op(ops[0], ops[1], ops[2], #op)
#define QFOP(op) emit_quaternary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], ops[5], #op)
#define TFOP(op) emit_trinary_func_op(ops[0], ops[1], ops[2], ops[3], ops[4], #op)
#define BFOP(op) emit_binary_func_op(ops[0], ops[1], ops[2], ops[3], #op)
#define BFOP_CAST(op, type) emit_binary_func_op_cast(ops[0], ops[1], ops[2], ops[3], #op, type, opcode_is_sign_invariant(opcode))
#define BFOP(op) emit_binary_func_op(ops[0], ops[1], ops[2], ops[3], #op)
#define UFOP(op) emit_unary_func_op(ops[0], ops[1], ops[2], #op)
auto ops = stream(instruction);
auto opcode = static_cast<Op>(instruction.op);
switch (opcode)
{
// Comparisons
case OpIEqual:
case OpLogicalEqual:
case OpFOrdEqual:
BOP(==);
break;
case OpINotEqual:
case OpLogicalNotEqual:
case OpFOrdNotEqual:
BOP(!=);
break;
case OpUGreaterThan:
case OpSGreaterThan:
case OpFOrdGreaterThan:
BOP(>);
break;
case OpUGreaterThanEqual:
case OpSGreaterThanEqual:
case OpFOrdGreaterThanEqual:
BOP(>=);
break;
case OpULessThan:
case OpSLessThan:
case OpFOrdLessThan:
BOP(<);
break;
case OpULessThanEqual:
case OpSLessThanEqual:
case OpFOrdLessThanEqual:
BOP(<=);
break;
// Derivatives
case OpDPdx:
UFOP(dfdx);
break;
case OpDPdy:
UFOP(dfdy);
break;
case OpImageQuerySize:
{
auto &type = expression_type(ops[2]);
uint32_t result_type = ops[0];
uint32_t id = ops[1];
if (type.basetype == SPIRType::Image)
{
string img_exp = to_expression(ops[2]);
auto &img_type = type.image;
switch (img_type.dim)
{
case Dim1D:
if (img_type.arrayed)
emit_op(result_type, id, join("uint2(", img_exp, ".get_width(), ", img_exp, ".get_array_size())"), false, false);
else
emit_op(result_type, id, join(img_exp, ".get_width()"), true, false);
break;
case Dim2D:
case DimCube:
if (img_type.arrayed)
emit_op(result_type, id, join("uint3(", img_exp, ".get_width(), ", img_exp, ".get_height(), ", img_exp, ".get_array_size())"), false, false);
else
emit_op(result_type, id, join("uint2(", img_exp, ".get_width(), ", img_exp, ".get_height())"), false, false);
break;
case Dim3D:
emit_op(result_type, id, join("uint3(", img_exp, ".get_width(), ", img_exp, ".get_height(), ", img_exp, ".get_depth())"), false, false);
break;
default:
break;
}
}
else
throw CompilerError("Invalid type for OpImageQuerySize.");
break;
}
default:
CompilerGLSL::emit_instruction(instruction);
break;
}
}
// Override for MSL-specific extension syntax instructions
void CompilerMSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop, const uint32_t *args, uint32_t count)
{
GLSLstd450 op = static_cast<GLSLstd450>(eop);
switch (op)
{
case GLSLstd450Atan2:
emit_binary_func_op(result_type, id, args[0], args[1], "atan2");
break;
default:
CompilerGLSL::emit_glsl_op(result_type, id, eop, args, count);
break;
}
}
// Emit a structure declaration for the specified interface variable. // Emit a structure declaration for the specified interface variable.
void CompilerMSL::emit_interface_block(uint32_t ib_var_id) void CompilerMSL::emit_interface_block(uint32_t ib_var_id)
{ {

View File

@ -96,6 +96,8 @@ public:
std::string compile() override; std::string compile() override;
protected: protected:
void emit_instruction(const Instruction &instr) override;
void emit_glsl_op(uint32_t result_type, uint32_t result_id, uint32_t op, const uint32_t *args, uint32_t count) override;
void emit_header() override; void emit_header() override;
void emit_function_prototype(SPIRFunction &func, uint64_t return_flags) override; void emit_function_prototype(SPIRFunction &func, uint64_t return_flags) override;
void emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id) override; void emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id) override;
@ -124,7 +126,6 @@ protected:
void emit_interface_block(uint32_t ib_var_id); void emit_interface_block(uint32_t ib_var_id);
void emit_function_prototype(SPIRFunction &func, bool is_decl); void emit_function_prototype(SPIRFunction &func, bool is_decl);
void emit_function_declarations(); void emit_function_declarations();
void emit_msl_defines();
std::string func_type_decl(SPIRType &type); std::string func_type_decl(SPIRType &type);
std::string clean_func_name(std::string func_name); std::string clean_func_name(std::string func_name);