Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial support for Metal Shading Language. #2

Merged
merged 17 commits into from
May 5, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
103aabf
Initial support for Metal Shading Language.
billhollings Apr 6, 2016
8f30f07
Clarify CompileMSL config parameters and move to compile() function.
billhollings Apr 8, 2016
6ddd80e
Fixes from code review of MSL functionality.
billhollings Apr 8, 2016
f9e5fb3
Fix compiler warnings.
billhollings Apr 11, 2016
5f2d666
Add CLI support for Metal.
billhollings Apr 11, 2016
b2e313e
Support 3 compilation loops for MSL.
billhollings Apr 11, 2016
78b6877
MSL outputs vertex input struct even when vertex attribute configurat…
billhollings Apr 11, 2016
6236cc7
Merge branch 'master' of https://github.com/KhronosGroup/SPIRV-Cross
billhollings Apr 11, 2016
257b10e
Fix MSL reference to instruction stream modified in subclass update.
billhollings Apr 11, 2016
fa46c14
Clean up commented uniform code and replace with TODO statement.
billhollings Apr 11, 2016
d7660fa
Merge branch 'master' of https://github.com/KhronosGroup/SPIRV-Cross
billhollings Apr 19, 2016
2570121
Merge branch 'master' of https://github.com/KhronosGroup/SPIRV-Cross
billhollings Apr 19, 2016
1dbd18d
Add pixel type qualifier to MSL image type names.
billhollings Apr 22, 2016
5aafb28
Track sampler ID in Meta for OpSampledImage objects.
billhollings Apr 24, 2016
762947e
CompilerMSL move Private global variables to entry-point function var…
billhollings Apr 27, 2016
2436f4c
CompilerMSL DimBuffer image type uses 2D MTLTexture.
billhollings Apr 29, 2016
2b1e6a8
Merge branch 'master' of https://github.com/KhronosGroup/SPIRV-Cross
billhollings May 4, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ SPIRV-Cross is a tool designed for parsing and converting SPIR-V to other shader
## Features

- Convert SPIR-V to readable, usable and efficient GLSL
- Convert SPIR-V to readable, usable and efficient Metal Shading Language (MSL) [EXPERIMENTAL]
- Convert SPIR-V to debuggable C++ [EXPERIMENTAL]
- Reflection API to simplify the creation of Vulkan pipeline layouts
- Reflection API to modify and tweak OpDecorations
- Supports "all" of vertex, fragment, tessellation, geometry and compute shaders.

SPIRV-Cross tries hard to emit readable and clean output from the SPIR-V.
The goal is to emit GLSL that looks like it was written by a human and not awkward IR/assembly-like code.
The goal is to emit GLSL or MSL that looks like it was written by a human and not awkward IR/assembly-like code.

NOTE: Individual features are expected to be mostly complete, but it is possible that certain obscure GLSL features are not yet supported.
However, most missing features are expected to be "trivial" improvements at this stage.
Expand Down
7 changes: 6 additions & 1 deletion main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

#include "spirv_cpp.hpp"
#include "spirv_msl.hpp"
#include <cstdio>
#include <stdexcept>
#include <functional>
Expand Down Expand Up @@ -266,11 +267,12 @@ struct CLIArguments

uint32_t iterations = 1;
bool cpp = false;
bool metal = false;
};

static void print_help()
{
fprintf(stderr, "Usage: spirv-cross [--output <output path>] [SPIR-V file] [--es] [--no-es] [--version <GLSL version>] [--dump-resources] [--help] [--force-temporary] [-cpp] [--flatten-ubo] [--fixup-clipspace] [--iterations iter] [--pls-in format input-name] [--pls-out format output-name]\n");
fprintf(stderr, "Usage: spirv-cross [--output <output path>] [SPIR-V file] [--es] [--no-es] [--version <GLSL version>] [--dump-resources] [--help] [--force-temporary] [--cpp] [--metal] [--flatten-ubo] [--fixup-clipspace] [--iterations iter] [--pls-in format input-name] [--pls-out format output-name]\n");
}

static vector<PlsRemap> remap_pls(const vector<PLSArg> &pls_variables, const vector<Resource> &resources, const vector<Resource> *secondary_resources)
Expand Down Expand Up @@ -344,6 +346,7 @@ int main(int argc, char *argv[])
cbs.add("--fixup-clipspace", [&args](CLIParser &) { args.fixup = true; });
cbs.add("--iterations", [&args](CLIParser &parser) { args.iterations = parser.next_uint(); });
cbs.add("--cpp", [&args](CLIParser &) { args.cpp = true; });
cbs.add("--metal", [&args](CLIParser &) { args.metal = true; });

cbs.add("--pls-in", [&args](CLIParser &parser) {
auto fmt = pls_format(parser.next_string());
Expand Down Expand Up @@ -380,6 +383,8 @@ int main(int argc, char *argv[])

if (args.cpp)
compiler = unique_ptr<CompilerGLSL>(new CompilerCPP(read_spirv_file(args.input)));
else if (args.metal)
compiler = unique_ptr<CompilerMSL>(new CompilerMSL(read_spirv_file(args.input)));
else
compiler = unique_ptr<CompilerGLSL>(new CompilerGLSL(read_spirv_file(args.input)));

Expand Down
14 changes: 12 additions & 2 deletions spirv_common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,17 @@ namespace spirv_cross
return std::to_string(std::forward<T>(t));
}

// Allow implementations to set a convenient standard precision
#ifndef SPIRV_CROSS_FLT_FMT
# define SPIRV_CROSS_FLT_FMT "%.32g"
#endif

inline std::string convert_to_string(float t)
{
// std::to_string for floating point values is broken.
// Fallback to something more sane.
char buf[64];
sprintf(buf, "%.32g", t);
sprintf(buf, SPIRV_CROSS_FLT_FMT, t);
// Ensure that the literal is float.
if (!strchr(buf, '.') && !strchr(buf, 'e'))
strcat(buf, ".0");
Expand All @@ -89,7 +94,7 @@ namespace spirv_cross
// std::to_string for floating point values is broken.
// Fallback to something more sane.
char buf[64];
sprintf(buf, "%.32g", t);
sprintf(buf, SPIRV_CROSS_FLT_FMT, t);
// Ensure that the literal is float.
if (!strchr(buf, '.') && !strchr(buf, 'e'))
strcat(buf, ".0");
Expand Down Expand Up @@ -144,6 +149,7 @@ namespace spirv_cross
Unknown,
Void,
Bool,
Char,
Int,
UInt,
AtomicCounter,
Expand All @@ -169,6 +175,8 @@ namespace spirv_cross

std::vector<uint32_t> member_types;

bool is_packed = false; // Tightly packed in memory (no alignment padding)

struct Image
{
uint32_t type;
Expand Down Expand Up @@ -632,10 +640,12 @@ namespace spirv_cross
uint32_t array_stride = 0;
uint32_t input_attachment = 0;
bool builtin = false;
bool per_instance = false;
};

Decoration decoration;
std::vector<Decoration> members;
uint32_t sampler = 0;
};
}

Expand Down
27 changes: 27 additions & 0 deletions spirv_cross.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,21 @@ bool Compiler::is_member_builtin(const SPIRType &type, uint32_t index, BuiltIn *
return false;
}

bool Compiler::is_scalar(const SPIRType &type) const
{
return type.vecsize == 1 && type.columns == 1;
}

bool Compiler::is_vector(const SPIRType &type) const
{
return type.vecsize > 1 && type.columns == 1;
}

bool Compiler::is_matrix(const SPIRType &type) const
{
return type.vecsize > 1 && type.columns > 1;
}

ShaderResources Compiler::get_shader_resources() const
{
ShaderResources res;
Expand Down Expand Up @@ -1820,3 +1835,15 @@ std::vector<BufferRange> Compiler::get_active_buffer_ranges(unsigned id) const
return ranges;
}

// Increase the number of IDs by the specified incremental amount.
// Returns the value of the first ID available for use in the expanded bound.
uint32_t Compiler::increase_bound_by(uint32_t incr_amount)
{
uint32_t curr_bound = (uint32_t)ids.size();
uint32_t new_bound = curr_bound + incr_amount;
ids.resize(new_bound);
meta.resize(new_bound);
return curr_bound;
}


12 changes: 10 additions & 2 deletions spirv_cross.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ namespace spirv_cross
// The constructor takes a buffer of SPIR-V words and parses it.
Compiler(std::vector<uint32_t> ir);

virtual ~Compiler() = default;

// After parsing, API users can modify the SPIR-V via reflection and call this
// to disassemble the SPIR-V into the desired langauage.
// Sub-classes actually implement this.
Expand Down Expand Up @@ -157,6 +159,9 @@ namespace spirv_cross
// Returns the effective size of a buffer block.
size_t get_declared_struct_size(const SPIRType &struct_type) const;

// Returns the effective size of a buffer block struct member.
virtual size_t get_declared_struct_member_size(const SPIRType &struct_type, uint32_t index) const;

// Legacy GLSL compatibility method.
// Takes a variable with a block interface and flattens it into a T array[N]; array instead.
// For this to work, all types in the block must not themselves be composites
Expand Down Expand Up @@ -265,6 +270,9 @@ namespace spirv_cross
bool is_builtin_variable(const SPIRVariable &var) const;
bool is_immutable(uint32_t id) const;
bool is_member_builtin(const SPIRType &type, uint32_t index, spv::BuiltIn *builtin) const;
bool is_scalar(const SPIRType &type) const;
bool is_vector(const SPIRType &type) const;
bool is_matrix(const SPIRType &type) const;
const SPIRType& expression_type(uint32_t id) const;
bool expression_is_lvalue(uint32_t id) const;
bool variable_storage_is_aliased(const SPIRVariable &var);
Expand Down Expand Up @@ -317,6 +325,8 @@ namespace spirv_cross

bool block_is_loop_candidate(const SPIRBlock &block, SPIRBlock::Method method) const;

uint32_t increase_bound_by(uint32_t incr_amount);

private:
void parse();
void parse(const Instruction &i);
Expand Down Expand Up @@ -347,8 +357,6 @@ namespace spirv_cross

bool traverse_all_reachable_opcodes(const SPIRBlock &block, OpcodeHandler &handler) const;
bool traverse_all_reachable_opcodes(const SPIRFunction &block, OpcodeHandler &handler) const;

size_t get_declared_struct_member_size(const SPIRType &struct_type, uint32_t index) const;
};
}

Expand Down
9 changes: 7 additions & 2 deletions spirv_glsl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1351,6 +1351,11 @@ void CompilerGLSL::emit_mix_op(uint32_t result_type, uint32_t id,
emit_trinary_func_op(result_type, id, left, right, lerp, "mix");
}

void CompilerGLSL::emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id)
{
emit_binary_func_op(result_type, result_id, image_id, samp_id, type_to_glsl(get<SPIRType>(result_type)).c_str());
}

void CompilerGLSL::emit_texture_op(const Instruction &i)
{
auto ops = stream(i);
Expand Down Expand Up @@ -1866,7 +1871,7 @@ string CompilerGLSL::bitcast_glsl(uint32_t result_type, uint32_t argument)
return join(op, "(", to_expression(argument), ")");
}

const char* CompilerGLSL::builtin_to_glsl(BuiltIn builtin)
string CompilerGLSL::builtin_to_glsl(BuiltIn builtin)
{
switch (builtin)
{
Expand Down Expand Up @@ -3049,7 +3054,7 @@ void CompilerGLSL::emit_instruction(const Instruction &i)
{
uint32_t result_type = ops[0];
uint32_t id = ops[1];
emit_binary_func_op(result_type, id, ops[2], ops[3], type_to_glsl(get<SPIRType>(result_type)).c_str());
emit_sampled_image_op(result_type, id, ops[2], ops[3]);
break;
}

Expand Down
19 changes: 10 additions & 9 deletions spirv_glsl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,15 @@ namespace spirv_cross
// 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_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_texture_op(const Instruction &i);
virtual std::string type_to_glsl(const SPIRType &type);
virtual std::string builtin_to_glsl(spv::BuiltIn builtin);
virtual std::string member_decl(const SPIRType &type, const SPIRType &member_type, uint32_t member);
virtual std::string image_type_glsl(const SPIRType &type);
virtual std::string constant_expression(const SPIRConstant &c);
virtual std::string constant_expression_vector(const SPIRConstant &c, uint32_t vector);
virtual void emit_fixup();

std::unique_ptr<std::ostringstream> buffer;

Expand Down Expand Up @@ -165,7 +174,6 @@ namespace spirv_cross

Options options;

std::string type_to_glsl(const SPIRType &type);
std::string type_to_array_glsl(const SPIRType &type);
std::string variable_decl(const SPIRVariable &variable);

Expand All @@ -189,7 +197,7 @@ namespace spirv_cross
void emit_struct(const SPIRType &type);
void emit_instruction(const Instruction &instr);

private:
protected:

void emit_resources();
void emit_buffer_block(const SPIRVariable &type);
Expand All @@ -209,7 +217,6 @@ namespace spirv_cross
void flush_undeclared_variables();

bool should_forward(uint32_t id);
void emit_texture_op(const Instruction &i);
void emit_mix_op(uint32_t result_type, uint32_t id, 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, uint32_t op3, const char *op);
Expand All @@ -229,13 +236,9 @@ namespace spirv_cross
std::string to_member_name(const SPIRType &type, uint32_t index);
std::string type_to_glsl_constructor(const SPIRType &type);
std::string argument_decl(const SPIRFunction::Parameter &arg);
std::string member_decl(const SPIRType &type, const SPIRType &member_type, uint32_t member);
std::string image_type_glsl(const SPIRType &type);
std::string to_qualifiers_glsl(uint32_t id);
const char* to_precision_qualifiers_glsl(uint32_t id);
const char* flags_to_precision_qualifiers_glsl(const SPIRType &type, uint64_t flags);
std::string constant_expression(const SPIRConstant &c);
std::string constant_expression_vector(const SPIRConstant &c, uint32_t vector);
const char* format_to_glsl(spv::ImageFormat format);
std::string layout_for_member(const SPIRType &type, uint32_t index);
uint64_t combined_decoration_for_member(const SPIRType &type, uint32_t index);
Expand All @@ -248,7 +251,6 @@ namespace spirv_cross

std::string bitcast_glsl(uint32_t result_type, uint32_t arg);
std::string bitcast_glsl_op(uint32_t result_type, uint32_t arg);
const char* builtin_to_glsl(spv::BuiltIn builtin);
std::string build_composite_combiner(const uint32_t *elems, uint32_t length);
bool remove_duplicate_swizzle(std::string &op);
bool remove_unity_swizzle(uint32_t base, std::string &op);
Expand All @@ -263,7 +265,6 @@ namespace spirv_cross
std::string legacy_tex_op(const std::string &op, const SPIRType &imgtype);

uint32_t indent = 0;
void emit_fixup();

std::unordered_set<uint32_t> emitted_functions;

Expand Down
Loading