Merge upstream.
Add explicit test for uniform var storage class (changed from test of storage class of var type).
This commit is contained in:
Коммит
14f4339b1c
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
for file in spirv_*.{cpp,hpp} include/spirv_cross/*.{hpp,h} samples/cpp/*.cpp
|
||||
for file in spirv_*.{cpp,hpp} include/spirv_cross/*.{hpp,h} samples/cpp/*.cpp main.cpp
|
||||
do
|
||||
echo "Formatting file: $file ..."
|
||||
clang-format -style=file -i $file
|
||||
|
|
792
main.cpp
792
main.cpp
|
@ -16,13 +16,14 @@
|
|||
|
||||
#include "spirv_cpp.hpp"
|
||||
#include "spirv_msl.hpp"
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <unordered_map>
|
||||
#include <cstring>
|
||||
#include <unordered_set>
|
||||
|
||||
using namespace spv;
|
||||
|
@ -32,182 +33,185 @@ using namespace std;
|
|||
struct CLIParser;
|
||||
struct CLICallbacks
|
||||
{
|
||||
void add(const char *cli, const function<void (CLIParser&)> &func)
|
||||
{
|
||||
callbacks[cli] = func;
|
||||
}
|
||||
unordered_map<string, function<void (CLIParser&)>> callbacks;
|
||||
function<void ()> error_handler;
|
||||
function<void (const char*)> default_handler;
|
||||
void add(const char *cli, const function<void(CLIParser &)> &func)
|
||||
{
|
||||
callbacks[cli] = func;
|
||||
}
|
||||
unordered_map<string, function<void(CLIParser &)>> callbacks;
|
||||
function<void()> error_handler;
|
||||
function<void(const char *)> default_handler;
|
||||
};
|
||||
|
||||
struct CLIParser
|
||||
{
|
||||
CLIParser(CLICallbacks cbs_, int argc_, char *argv_[])
|
||||
: cbs(move(cbs_)), argc(argc_), argv(argv_)
|
||||
{}
|
||||
CLIParser(CLICallbacks cbs_, int argc_, char *argv_[])
|
||||
: cbs(move(cbs_))
|
||||
, argc(argc_)
|
||||
, argv(argv_)
|
||||
{
|
||||
}
|
||||
|
||||
bool parse()
|
||||
{
|
||||
try
|
||||
{
|
||||
while (argc && !ended_state)
|
||||
{
|
||||
const char *next = *argv++;
|
||||
argc--;
|
||||
bool parse()
|
||||
{
|
||||
try
|
||||
{
|
||||
while (argc && !ended_state)
|
||||
{
|
||||
const char *next = *argv++;
|
||||
argc--;
|
||||
|
||||
if (*next != '-' && cbs.default_handler)
|
||||
{
|
||||
cbs.default_handler(next);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto itr = cbs.callbacks.find(next);
|
||||
if (itr == ::end(cbs.callbacks))
|
||||
{
|
||||
throw logic_error("Invalid argument.\n");
|
||||
}
|
||||
if (*next != '-' && cbs.default_handler)
|
||||
{
|
||||
cbs.default_handler(next);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto itr = cbs.callbacks.find(next);
|
||||
if (itr == ::end(cbs.callbacks))
|
||||
{
|
||||
throw logic_error("Invalid argument.\n");
|
||||
}
|
||||
|
||||
itr->second(*this);
|
||||
}
|
||||
}
|
||||
itr->second(*this);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
if (cbs.error_handler)
|
||||
{
|
||||
cbs.error_handler();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
if (cbs.error_handler)
|
||||
{
|
||||
cbs.error_handler();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void end()
|
||||
{
|
||||
ended_state = true;
|
||||
}
|
||||
void end()
|
||||
{
|
||||
ended_state = true;
|
||||
}
|
||||
|
||||
uint32_t next_uint()
|
||||
{
|
||||
if (!argc)
|
||||
{
|
||||
throw logic_error("Tried to parse uint, but nothing left in arguments.\n");
|
||||
}
|
||||
uint32_t next_uint()
|
||||
{
|
||||
if (!argc)
|
||||
{
|
||||
throw logic_error("Tried to parse uint, but nothing left in arguments.\n");
|
||||
}
|
||||
|
||||
uint32_t val = stoul(*argv);
|
||||
if (val > numeric_limits<uint32_t>::max())
|
||||
{
|
||||
throw out_of_range("next_uint() out of range.\n");
|
||||
}
|
||||
uint32_t val = stoul(*argv);
|
||||
if (val > numeric_limits<uint32_t>::max())
|
||||
{
|
||||
throw out_of_range("next_uint() out of range.\n");
|
||||
}
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
return val;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
double next_double()
|
||||
{
|
||||
if (!argc)
|
||||
{
|
||||
throw logic_error("Tried to parse double, but nothing left in arguments.\n");
|
||||
}
|
||||
double next_double()
|
||||
{
|
||||
if (!argc)
|
||||
{
|
||||
throw logic_error("Tried to parse double, but nothing left in arguments.\n");
|
||||
}
|
||||
|
||||
double val = stod(*argv);
|
||||
double val = stod(*argv);
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
return val;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
const char *next_string()
|
||||
{
|
||||
if (!argc)
|
||||
{
|
||||
throw logic_error("Tried to parse string, but nothing left in arguments.\n");
|
||||
}
|
||||
const char *next_string()
|
||||
{
|
||||
if (!argc)
|
||||
{
|
||||
throw logic_error("Tried to parse string, but nothing left in arguments.\n");
|
||||
}
|
||||
|
||||
const char *ret = *argv;
|
||||
argc--;
|
||||
argv++;
|
||||
return ret;
|
||||
}
|
||||
const char *ret = *argv;
|
||||
argc--;
|
||||
argv++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
CLICallbacks cbs;
|
||||
int argc;
|
||||
char **argv;
|
||||
bool ended_state = false;
|
||||
CLICallbacks cbs;
|
||||
int argc;
|
||||
char **argv;
|
||||
bool ended_state = false;
|
||||
};
|
||||
|
||||
static vector<uint32_t> read_spirv_file(const char *path)
|
||||
{
|
||||
FILE *file = fopen(path, "rb");
|
||||
if (!file)
|
||||
{
|
||||
fprintf(stderr, "Failed to open SPIRV file: %s\n", path);
|
||||
return {};
|
||||
}
|
||||
FILE *file = fopen(path, "rb");
|
||||
if (!file)
|
||||
{
|
||||
fprintf(stderr, "Failed to open SPIRV file: %s\n", path);
|
||||
return {};
|
||||
}
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
long len = ftell(file) / sizeof(uint32_t);
|
||||
rewind(file);
|
||||
fseek(file, 0, SEEK_END);
|
||||
long len = ftell(file) / sizeof(uint32_t);
|
||||
rewind(file);
|
||||
|
||||
vector<uint32_t> spirv(len);
|
||||
if (fread(spirv.data(), sizeof(uint32_t), len, file) != size_t(len))
|
||||
spirv.clear();
|
||||
vector<uint32_t> spirv(len);
|
||||
if (fread(spirv.data(), sizeof(uint32_t), len, file) != size_t(len))
|
||||
spirv.clear();
|
||||
|
||||
fclose(file);
|
||||
return spirv;
|
||||
fclose(file);
|
||||
return spirv;
|
||||
}
|
||||
|
||||
static bool write_string_to_file(const char *path, const char *string)
|
||||
{
|
||||
FILE *file = fopen(path, "w");
|
||||
if (!file)
|
||||
{
|
||||
fprintf(file, "Failed to write file: %s\n", path);
|
||||
return false;
|
||||
}
|
||||
FILE *file = fopen(path, "w");
|
||||
if (!file)
|
||||
{
|
||||
fprintf(file, "Failed to write file: %s\n", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
fprintf(file, "%s", string);
|
||||
fclose(file);
|
||||
return true;
|
||||
fprintf(file, "%s", string);
|
||||
fclose(file);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void print_resources(const Compiler &compiler, const char *tag, const vector<Resource> &resources)
|
||||
{
|
||||
fprintf(stderr, "%s\n", tag);
|
||||
fprintf(stderr, "=============\n\n");
|
||||
for (auto &res : resources)
|
||||
{
|
||||
auto &type = compiler.get_type(res.type_id);
|
||||
auto mask = compiler.get_decoration_mask(res.id);
|
||||
fprintf(stderr, "%s\n", tag);
|
||||
fprintf(stderr, "=============\n\n");
|
||||
for (auto &res : resources)
|
||||
{
|
||||
auto &type = compiler.get_type(res.type_id);
|
||||
auto mask = compiler.get_decoration_mask(res.id);
|
||||
|
||||
// If we don't have a name, use the fallback for the type instead of the variable
|
||||
// for SSBOs and UBOs since those are the only meaningful names to use externally.
|
||||
// Push constant blocks are still accessed by name and not block name, even though they are technically Blocks.
|
||||
bool is_push_constant = compiler.get_storage_class(res.id) == StorageClassPushConstant;
|
||||
bool is_block = (compiler.get_decoration_mask(type.self) &
|
||||
((1ull << DecorationBlock) | (1ull << DecorationBufferBlock))) != 0;
|
||||
uint32_t fallback_id = !is_push_constant && is_block ? res.type_id : res.id;
|
||||
// If we don't have a name, use the fallback for the type instead of the variable
|
||||
// for SSBOs and UBOs since those are the only meaningful names to use externally.
|
||||
// Push constant blocks are still accessed by name and not block name, even though they are technically Blocks.
|
||||
bool is_push_constant = compiler.get_storage_class(res.id) == StorageClassPushConstant;
|
||||
bool is_block = (compiler.get_decoration_mask(type.self) &
|
||||
((1ull << DecorationBlock) | (1ull << DecorationBufferBlock))) != 0;
|
||||
uint32_t fallback_id = !is_push_constant && is_block ? res.type_id : res.id;
|
||||
|
||||
fprintf(stderr, " ID %03u : %s", res.id,
|
||||
!res.name.empty() ? res.name.c_str() : compiler.get_fallback_name(fallback_id).c_str());
|
||||
fprintf(stderr, " ID %03u : %s", res.id,
|
||||
!res.name.empty() ? res.name.c_str() : compiler.get_fallback_name(fallback_id).c_str());
|
||||
|
||||
if (mask & (1ull << DecorationLocation))
|
||||
fprintf(stderr, " (Location : %u)", compiler.get_decoration(res.id, DecorationLocation));
|
||||
if (mask & (1ull << DecorationDescriptorSet))
|
||||
fprintf(stderr, " (Set : %u)", compiler.get_decoration(res.id, DecorationDescriptorSet));
|
||||
if (mask & (1ull << DecorationBinding))
|
||||
fprintf(stderr, " (Binding : %u)", compiler.get_decoration(res.id, DecorationBinding));
|
||||
if (mask & (1ull << DecorationInputAttachmentIndex))
|
||||
fprintf(stderr, " (Attachment : %u)", compiler.get_decoration(res.id, DecorationInputAttachmentIndex));
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
fprintf(stderr, "=============\n\n");
|
||||
if (mask & (1ull << DecorationLocation))
|
||||
fprintf(stderr, " (Location : %u)", compiler.get_decoration(res.id, DecorationLocation));
|
||||
if (mask & (1ull << DecorationDescriptorSet))
|
||||
fprintf(stderr, " (Set : %u)", compiler.get_decoration(res.id, DecorationDescriptorSet));
|
||||
if (mask & (1ull << DecorationBinding))
|
||||
fprintf(stderr, " (Binding : %u)", compiler.get_decoration(res.id, DecorationBinding));
|
||||
if (mask & (1ull << DecorationInputAttachmentIndex))
|
||||
fprintf(stderr, " (Attachment : %u)", compiler.get_decoration(res.id, DecorationInputAttachmentIndex));
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
fprintf(stderr, "=============\n\n");
|
||||
}
|
||||
|
||||
static void print_resources(const Compiler &compiler, const ShaderResources &res)
|
||||
|
@ -227,278 +231,354 @@ static void print_resources(const Compiler &compiler, const ShaderResources &res
|
|||
|
||||
switch (static_cast<ExecutionMode>(i))
|
||||
{
|
||||
case ExecutionModeInvocations:
|
||||
fprintf(stderr, " Invocations: %u\n", arg0);
|
||||
break;
|
||||
case ExecutionModeInvocations:
|
||||
fprintf(stderr, " Invocations: %u\n", arg0);
|
||||
break;
|
||||
|
||||
case ExecutionModeLocalSize:
|
||||
fprintf(stderr, " LocalSize: (%u, %u, %u)\n", arg0, arg1, arg2);
|
||||
break;
|
||||
case ExecutionModeLocalSize:
|
||||
fprintf(stderr, " LocalSize: (%u, %u, %u)\n", arg0, arg1, arg2);
|
||||
break;
|
||||
|
||||
case ExecutionModeOutputVertices:
|
||||
fprintf(stderr, " OutputVertices: %u\n", arg0);
|
||||
break;
|
||||
case ExecutionModeOutputVertices:
|
||||
fprintf(stderr, " OutputVertices: %u\n", arg0);
|
||||
break;
|
||||
|
||||
#define CHECK_MODE(m) case ExecutionMode##m: fprintf(stderr, " %s\n", #m); break
|
||||
CHECK_MODE(SpacingEqual);
|
||||
CHECK_MODE(SpacingFractionalEven);
|
||||
CHECK_MODE(SpacingFractionalOdd);
|
||||
CHECK_MODE(VertexOrderCw);
|
||||
CHECK_MODE(VertexOrderCcw);
|
||||
CHECK_MODE(PixelCenterInteger);
|
||||
CHECK_MODE(OriginUpperLeft);
|
||||
CHECK_MODE(OriginLowerLeft);
|
||||
CHECK_MODE(EarlyFragmentTests);
|
||||
CHECK_MODE(PointMode);
|
||||
CHECK_MODE(Xfb);
|
||||
CHECK_MODE(DepthReplacing);
|
||||
CHECK_MODE(DepthGreater);
|
||||
CHECK_MODE(DepthLess);
|
||||
CHECK_MODE(DepthUnchanged);
|
||||
CHECK_MODE(LocalSizeHint);
|
||||
CHECK_MODE(InputPoints);
|
||||
CHECK_MODE(InputLines);
|
||||
CHECK_MODE(InputLinesAdjacency);
|
||||
CHECK_MODE(Triangles);
|
||||
CHECK_MODE(InputTrianglesAdjacency);
|
||||
CHECK_MODE(Quads);
|
||||
CHECK_MODE(Isolines);
|
||||
CHECK_MODE(OutputPoints);
|
||||
CHECK_MODE(OutputLineStrip);
|
||||
CHECK_MODE(OutputTriangleStrip);
|
||||
CHECK_MODE(VecTypeHint);
|
||||
CHECK_MODE(ContractionOff);
|
||||
#define CHECK_MODE(m) \
|
||||
case ExecutionMode##m: \
|
||||
fprintf(stderr, " %s\n", #m); \
|
||||
break
|
||||
CHECK_MODE(SpacingEqual);
|
||||
CHECK_MODE(SpacingFractionalEven);
|
||||
CHECK_MODE(SpacingFractionalOdd);
|
||||
CHECK_MODE(VertexOrderCw);
|
||||
CHECK_MODE(VertexOrderCcw);
|
||||
CHECK_MODE(PixelCenterInteger);
|
||||
CHECK_MODE(OriginUpperLeft);
|
||||
CHECK_MODE(OriginLowerLeft);
|
||||
CHECK_MODE(EarlyFragmentTests);
|
||||
CHECK_MODE(PointMode);
|
||||
CHECK_MODE(Xfb);
|
||||
CHECK_MODE(DepthReplacing);
|
||||
CHECK_MODE(DepthGreater);
|
||||
CHECK_MODE(DepthLess);
|
||||
CHECK_MODE(DepthUnchanged);
|
||||
CHECK_MODE(LocalSizeHint);
|
||||
CHECK_MODE(InputPoints);
|
||||
CHECK_MODE(InputLines);
|
||||
CHECK_MODE(InputLinesAdjacency);
|
||||
CHECK_MODE(Triangles);
|
||||
CHECK_MODE(InputTrianglesAdjacency);
|
||||
CHECK_MODE(Quads);
|
||||
CHECK_MODE(Isolines);
|
||||
CHECK_MODE(OutputPoints);
|
||||
CHECK_MODE(OutputLineStrip);
|
||||
CHECK_MODE(OutputTriangleStrip);
|
||||
CHECK_MODE(VecTypeHint);
|
||||
CHECK_MODE(ContractionOff);
|
||||
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
print_resources(compiler, "subpass inputs", res.subpass_inputs);
|
||||
print_resources(compiler, "inputs", res.stage_inputs);
|
||||
print_resources(compiler, "outputs", res.stage_outputs);
|
||||
print_resources(compiler, "textures", res.sampled_images);
|
||||
print_resources(compiler, "images", res.storage_images);
|
||||
print_resources(compiler, "ssbos", res.storage_buffers);
|
||||
print_resources(compiler, "ubos", res.uniform_buffers);
|
||||
print_resources(compiler, "push", res.push_constant_buffers);
|
||||
print_resources(compiler, "counters", res.atomic_counters);
|
||||
print_resources(compiler, "subpass inputs", res.subpass_inputs);
|
||||
print_resources(compiler, "inputs", res.stage_inputs);
|
||||
print_resources(compiler, "outputs", res.stage_outputs);
|
||||
print_resources(compiler, "textures", res.sampled_images);
|
||||
print_resources(compiler, "images", res.storage_images);
|
||||
print_resources(compiler, "ssbos", res.storage_buffers);
|
||||
print_resources(compiler, "ubos", res.uniform_buffers);
|
||||
print_resources(compiler, "push", res.push_constant_buffers);
|
||||
print_resources(compiler, "counters", res.atomic_counters);
|
||||
}
|
||||
|
||||
static void print_push_constant_resources(const Compiler &compiler, const vector<Resource> &res)
|
||||
{
|
||||
for (auto &block : res)
|
||||
{
|
||||
auto ranges = compiler.get_active_buffer_ranges(block.id);
|
||||
fprintf(stderr, "Active members in buffer: %s\n",
|
||||
!block.name.empty() ? block.name.c_str() : compiler.get_fallback_name(block.id).c_str());
|
||||
for (auto &block : res)
|
||||
{
|
||||
auto ranges = compiler.get_active_buffer_ranges(block.id);
|
||||
fprintf(stderr, "Active members in buffer: %s\n",
|
||||
!block.name.empty() ? block.name.c_str() : compiler.get_fallback_name(block.id).c_str());
|
||||
|
||||
fprintf(stderr, "==================\n\n");
|
||||
for (auto &range : ranges)
|
||||
{
|
||||
const auto &name = compiler.get_member_name(block.type_id, range.index);
|
||||
fprintf(stderr, "==================\n\n");
|
||||
for (auto &range : ranges)
|
||||
{
|
||||
const auto &name = compiler.get_member_name(block.type_id, range.index);
|
||||
|
||||
fprintf(stderr, "Member #%3u (%s): Offset: %4u, Range: %4u\n",
|
||||
range.index, !name.empty() ? name.c_str() : compiler.get_fallback_member_name(range.index).c_str(),
|
||||
unsigned(range.offset), unsigned(range.range));
|
||||
}
|
||||
fprintf(stderr, "==================\n\n");
|
||||
}
|
||||
fprintf(stderr, "Member #%3u (%s): Offset: %4u, Range: %4u\n", range.index,
|
||||
!name.empty() ? name.c_str() : compiler.get_fallback_member_name(range.index).c_str(),
|
||||
unsigned(range.offset), unsigned(range.range));
|
||||
}
|
||||
fprintf(stderr, "==================\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
struct PLSArg
|
||||
{
|
||||
PlsFormat format;
|
||||
string name;
|
||||
PlsFormat format;
|
||||
string name;
|
||||
};
|
||||
|
||||
struct Remap
|
||||
{
|
||||
string src_name;
|
||||
string dst_name;
|
||||
unsigned components;
|
||||
};
|
||||
|
||||
struct CLIArguments
|
||||
{
|
||||
const char *input = nullptr;
|
||||
const char *output = nullptr;
|
||||
const char *cpp_interface_name = nullptr;
|
||||
uint32_t version = 0;
|
||||
bool es = false;
|
||||
bool set_version = false;
|
||||
bool set_es = false;
|
||||
bool dump_resources = false;
|
||||
bool force_temporary = false;
|
||||
bool flatten_ubo = false;
|
||||
bool fixup = false;
|
||||
vector<PLSArg> pls_in;
|
||||
vector<PLSArg> pls_out;
|
||||
const char *input = nullptr;
|
||||
const char *output = nullptr;
|
||||
const char *cpp_interface_name = nullptr;
|
||||
uint32_t version = 0;
|
||||
bool es = false;
|
||||
bool set_version = false;
|
||||
bool set_es = false;
|
||||
bool dump_resources = false;
|
||||
bool force_temporary = false;
|
||||
bool flatten_ubo = false;
|
||||
bool fixup = false;
|
||||
vector<PLSArg> pls_in;
|
||||
vector<PLSArg> pls_out;
|
||||
vector<Remap> remaps;
|
||||
vector<string> extensions;
|
||||
|
||||
uint32_t iterations = 1;
|
||||
bool cpp = false;
|
||||
bool metal = false;
|
||||
bool vulkan_semantics = false;
|
||||
uint32_t iterations = 1;
|
||||
bool cpp = false;
|
||||
bool metal = false;
|
||||
bool vulkan_semantics = 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] [--cpp-interface-name <name>] [--metal] [--vulkan-semantics] [--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] [--cpp-interface-name <name>] "
|
||||
"[--metal] [--vulkan-semantics] [--flatten-ubo] [--fixup-clipspace] [--iterations iter] [--pls-in "
|
||||
"format input-name] [--pls-out format output-name] [--remap source_name target_name components] "
|
||||
"[--extension ext]\n");
|
||||
}
|
||||
|
||||
static vector<PlsRemap> remap_pls(const vector<PLSArg> &pls_variables, const vector<Resource> &resources, const vector<Resource> *secondary_resources)
|
||||
static bool remap_generic(Compiler &compiler, const vector<Resource> &resources, const Remap &remap)
|
||||
{
|
||||
vector<PlsRemap> ret;
|
||||
auto itr =
|
||||
find_if(begin(resources), end(resources), [&remap](const Resource &res) { return res.name == remap.src_name; });
|
||||
|
||||
for (auto &pls : pls_variables)
|
||||
{
|
||||
bool found = false;
|
||||
for (auto &res : resources)
|
||||
{
|
||||
if (res.name == pls.name)
|
||||
{
|
||||
ret.push_back({ res.id, pls.format });
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (itr != end(resources))
|
||||
{
|
||||
compiler.set_remapped_variable_state(itr->id, true);
|
||||
compiler.set_name(itr->id, remap.dst_name);
|
||||
compiler.set_subpass_input_remapped_components(itr->id, remap.components);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!found && secondary_resources)
|
||||
{
|
||||
for (auto &res : *secondary_resources)
|
||||
{
|
||||
if (res.name == pls.name)
|
||||
{
|
||||
ret.push_back({ res.id, pls.format });
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
static vector<PlsRemap> remap_pls(const vector<PLSArg> &pls_variables, const vector<Resource> &resources,
|
||||
const vector<Resource> *secondary_resources)
|
||||
{
|
||||
vector<PlsRemap> ret;
|
||||
|
||||
if (!found)
|
||||
fprintf(stderr, "Did not find stage input/output/target with name \"%s\".\n",
|
||||
pls.name.c_str());
|
||||
}
|
||||
for (auto &pls : pls_variables)
|
||||
{
|
||||
bool found = false;
|
||||
for (auto &res : resources)
|
||||
{
|
||||
if (res.name == pls.name)
|
||||
{
|
||||
ret.push_back({ res.id, pls.format });
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
if (!found && secondary_resources)
|
||||
{
|
||||
for (auto &res : *secondary_resources)
|
||||
{
|
||||
if (res.name == pls.name)
|
||||
{
|
||||
ret.push_back({ res.id, pls.format });
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
fprintf(stderr, "Did not find stage input/output/target with name \"%s\".\n", pls.name.c_str());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PlsFormat pls_format(const char *str)
|
||||
{
|
||||
if (!strcmp(str, "r11f_g11f_b10f")) return PlsR11FG11FB10F;
|
||||
else if (!strcmp(str, "r32f")) return PlsR32F;
|
||||
else if (!strcmp(str, "rg16f")) return PlsRG16F;
|
||||
else if (!strcmp(str, "rg16")) return PlsRG16;
|
||||
else if (!strcmp(str, "rgb10_a2")) return PlsRGB10A2;
|
||||
else if (!strcmp(str, "rgba8")) return PlsRGBA8;
|
||||
else if (!strcmp(str, "rgba8i")) return PlsRGBA8I;
|
||||
else if (!strcmp(str, "rgba8ui")) return PlsRGBA8UI;
|
||||
else if (!strcmp(str, "rg16i")) return PlsRG16I;
|
||||
else if (!strcmp(str, "rgb10_a2ui")) return PlsRGB10A2UI;
|
||||
else if (!strcmp(str, "rg16ui")) return PlsRG16UI;
|
||||
else if (!strcmp(str, "r32ui")) return PlsR32UI;
|
||||
else return PlsNone;
|
||||
if (!strcmp(str, "r11f_g11f_b10f"))
|
||||
return PlsR11FG11FB10F;
|
||||
else if (!strcmp(str, "r32f"))
|
||||
return PlsR32F;
|
||||
else if (!strcmp(str, "rg16f"))
|
||||
return PlsRG16F;
|
||||
else if (!strcmp(str, "rg16"))
|
||||
return PlsRG16;
|
||||
else if (!strcmp(str, "rgb10_a2"))
|
||||
return PlsRGB10A2;
|
||||
else if (!strcmp(str, "rgba8"))
|
||||
return PlsRGBA8;
|
||||
else if (!strcmp(str, "rgba8i"))
|
||||
return PlsRGBA8I;
|
||||
else if (!strcmp(str, "rgba8ui"))
|
||||
return PlsRGBA8UI;
|
||||
else if (!strcmp(str, "rg16i"))
|
||||
return PlsRG16I;
|
||||
else if (!strcmp(str, "rgb10_a2ui"))
|
||||
return PlsRGB10A2UI;
|
||||
else if (!strcmp(str, "rg16ui"))
|
||||
return PlsRG16UI;
|
||||
else if (!strcmp(str, "r32ui"))
|
||||
return PlsR32UI;
|
||||
else
|
||||
return PlsNone;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
CLIArguments args;
|
||||
CLICallbacks cbs;
|
||||
CLIArguments args;
|
||||
CLICallbacks cbs;
|
||||
|
||||
cbs.add("--help", [](CLIParser &parser) { print_help(); parser.end(); });
|
||||
cbs.add("--output", [&args](CLIParser &parser) { args.output = parser.next_string(); });
|
||||
cbs.add("--es", [&args](CLIParser &) { args.es = true; args.set_es = true; });
|
||||
cbs.add("--no-es", [&args](CLIParser &) { args.es = false; args.set_es = true; });
|
||||
cbs.add("--version", [&args](CLIParser &parser) { args.version = parser.next_uint(); args.set_version = true; });
|
||||
cbs.add("--dump-resources", [&args](CLIParser &) { args.dump_resources = true; });
|
||||
cbs.add("--force-temporary", [&args](CLIParser &) { args.force_temporary = true; });
|
||||
cbs.add("--flatten-ubo", [&args](CLIParser &) { args.flatten_ubo = true; });
|
||||
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("--cpp-interface-name", [&args](CLIParser &parser) { args.cpp_interface_name = parser.next_string(); });
|
||||
cbs.add("--metal", [&args](CLIParser &) { args.metal = true; });
|
||||
cbs.add("--vulkan-semantics", [&args](CLIParser &) { args.vulkan_semantics = true; });
|
||||
cbs.add("--help", [](CLIParser &parser) {
|
||||
print_help();
|
||||
parser.end();
|
||||
});
|
||||
cbs.add("--output", [&args](CLIParser &parser) { args.output = parser.next_string(); });
|
||||
cbs.add("--es", [&args](CLIParser &) {
|
||||
args.es = true;
|
||||
args.set_es = true;
|
||||
});
|
||||
cbs.add("--no-es", [&args](CLIParser &) {
|
||||
args.es = false;
|
||||
args.set_es = true;
|
||||
});
|
||||
cbs.add("--version", [&args](CLIParser &parser) {
|
||||
args.version = parser.next_uint();
|
||||
args.set_version = true;
|
||||
});
|
||||
cbs.add("--dump-resources", [&args](CLIParser &) { args.dump_resources = true; });
|
||||
cbs.add("--force-temporary", [&args](CLIParser &) { args.force_temporary = true; });
|
||||
cbs.add("--flatten-ubo", [&args](CLIParser &) { args.flatten_ubo = true; });
|
||||
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("--cpp-interface-name", [&args](CLIParser &parser) { args.cpp_interface_name = parser.next_string(); });
|
||||
cbs.add("--metal", [&args](CLIParser &) { args.metal = true; });
|
||||
cbs.add("--vulkan-semantics", [&args](CLIParser &) { args.vulkan_semantics = true; });
|
||||
cbs.add("--extension", [&args](CLIParser &parser) { args.extensions.push_back(parser.next_string()); });
|
||||
cbs.add("--remap", [&args](CLIParser &parser) {
|
||||
string src = parser.next_string();
|
||||
string dst = parser.next_string();
|
||||
uint32_t components = parser.next_uint();
|
||||
args.remaps.push_back({ move(src), move(dst), components });
|
||||
});
|
||||
|
||||
cbs.add("--pls-in", [&args](CLIParser &parser) {
|
||||
auto fmt = pls_format(parser.next_string());
|
||||
auto name = parser.next_string();
|
||||
args.pls_in.push_back({ move(fmt), move(name) });
|
||||
});
|
||||
cbs.add("--pls-out", [&args](CLIParser &parser) {
|
||||
auto fmt = pls_format(parser.next_string());
|
||||
auto name = parser.next_string();
|
||||
args.pls_out.push_back({ move(fmt), move(name) });
|
||||
});
|
||||
cbs.add("--pls-in", [&args](CLIParser &parser) {
|
||||
auto fmt = pls_format(parser.next_string());
|
||||
auto name = parser.next_string();
|
||||
args.pls_in.push_back({ move(fmt), move(name) });
|
||||
});
|
||||
cbs.add("--pls-out", [&args](CLIParser &parser) {
|
||||
auto fmt = pls_format(parser.next_string());
|
||||
auto name = parser.next_string();
|
||||
args.pls_out.push_back({ move(fmt), move(name) });
|
||||
});
|
||||
|
||||
cbs.default_handler = [&args](const char *value) { args.input = value; };
|
||||
cbs.error_handler = []{ print_help(); };
|
||||
cbs.default_handler = [&args](const char *value) { args.input = value; };
|
||||
cbs.error_handler = [] { print_help(); };
|
||||
|
||||
CLIParser parser{move(cbs), argc - 1, argv + 1};
|
||||
if (!parser.parse())
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else if (parser.ended_state)
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
CLIParser parser{ move(cbs), argc - 1, argv + 1 };
|
||||
if (!parser.parse())
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else if (parser.ended_state)
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (!args.input)
|
||||
{
|
||||
fprintf(stderr, "Didn't specify input file.\n");
|
||||
print_help();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (!args.input)
|
||||
{
|
||||
fprintf(stderr, "Didn't specify input file.\n");
|
||||
print_help();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
unique_ptr<CompilerGLSL> compiler;
|
||||
unique_ptr<CompilerGLSL> compiler;
|
||||
|
||||
if (args.cpp)
|
||||
{
|
||||
compiler = unique_ptr<CompilerGLSL>(new CompilerCPP(read_spirv_file(args.input)));
|
||||
if (args.cpp_interface_name)
|
||||
static_cast<CompilerCPP *>(compiler.get())->set_interface_name(args.cpp_interface_name);
|
||||
}
|
||||
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)));
|
||||
if (args.cpp)
|
||||
{
|
||||
compiler = unique_ptr<CompilerGLSL>(new CompilerCPP(read_spirv_file(args.input)));
|
||||
if (args.cpp_interface_name)
|
||||
static_cast<CompilerCPP *>(compiler.get())->set_interface_name(args.cpp_interface_name);
|
||||
}
|
||||
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)));
|
||||
|
||||
if (!args.set_version && !compiler->get_options().version)
|
||||
{
|
||||
fprintf(stderr, "Didn't specify GLSL version and SPIR-V did not specify language.\n");
|
||||
print_help();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (!args.set_version && !compiler->get_options().version)
|
||||
{
|
||||
fprintf(stderr, "Didn't specify GLSL version and SPIR-V did not specify language.\n");
|
||||
print_help();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
CompilerGLSL::Options opts = compiler->get_options();
|
||||
if (args.set_version)
|
||||
opts.version = args.version;
|
||||
if (args.set_es)
|
||||
opts.es = args.es;
|
||||
opts.force_temporary = args.force_temporary;
|
||||
opts.vulkan_semantics = args.vulkan_semantics;
|
||||
opts.vertex.fixup_clipspace = args.fixup;
|
||||
compiler->set_options(opts);
|
||||
CompilerGLSL::Options opts = compiler->get_options();
|
||||
if (args.set_version)
|
||||
opts.version = args.version;
|
||||
if (args.set_es)
|
||||
opts.es = args.es;
|
||||
opts.force_temporary = args.force_temporary;
|
||||
opts.vulkan_semantics = args.vulkan_semantics;
|
||||
opts.vertex.fixup_clipspace = args.fixup;
|
||||
compiler->set_options(opts);
|
||||
|
||||
auto res = compiler->get_shader_resources();
|
||||
auto res = compiler->get_shader_resources();
|
||||
|
||||
if (args.flatten_ubo)
|
||||
for (auto &ubo : res.uniform_buffers)
|
||||
compiler->flatten_interface_block(ubo.id);
|
||||
if (args.flatten_ubo)
|
||||
for (auto &ubo : res.uniform_buffers)
|
||||
compiler->flatten_interface_block(ubo.id);
|
||||
|
||||
auto pls_inputs = remap_pls(args.pls_in, res.stage_inputs, &res.subpass_inputs);
|
||||
auto pls_outputs = remap_pls(args.pls_out, res.stage_outputs, nullptr);
|
||||
compiler->remap_pixel_local_storage(move(pls_inputs), move(pls_outputs));
|
||||
auto pls_inputs = remap_pls(args.pls_in, res.stage_inputs, &res.subpass_inputs);
|
||||
auto pls_outputs = remap_pls(args.pls_out, res.stage_outputs, nullptr);
|
||||
compiler->remap_pixel_local_storage(move(pls_inputs), move(pls_outputs));
|
||||
|
||||
if (args.dump_resources)
|
||||
{
|
||||
print_resources(*compiler, res);
|
||||
print_push_constant_resources(*compiler, res.push_constant_buffers);
|
||||
}
|
||||
for (auto &ext : args.extensions)
|
||||
compiler->require_extension(ext);
|
||||
|
||||
string glsl;
|
||||
for (uint32_t i = 0; i < args.iterations; i++)
|
||||
glsl = compiler->compile();
|
||||
for (auto &remap : args.remaps)
|
||||
{
|
||||
if (remap_generic(*compiler, res.stage_inputs, remap))
|
||||
continue;
|
||||
if (remap_generic(*compiler, res.stage_outputs, remap))
|
||||
continue;
|
||||
if (remap_generic(*compiler, res.subpass_inputs, remap))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (args.output)
|
||||
write_string_to_file(args.output, glsl.c_str());
|
||||
else
|
||||
printf("%s", glsl.c_str());
|
||||
if (args.dump_resources)
|
||||
{
|
||||
print_resources(*compiler, res);
|
||||
print_push_constant_resources(*compiler, res.push_constant_buffers);
|
||||
}
|
||||
|
||||
string glsl;
|
||||
for (uint32_t i = 0; i < args.iterations; i++)
|
||||
glsl = compiler->compile();
|
||||
|
||||
if (args.output)
|
||||
write_string_to_file(args.output, glsl.c_str());
|
||||
else
|
||||
printf("%s", glsl.c_str());
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
precision mediump float;
|
||||
precision highp int;
|
||||
|
||||
layout(binding = 0) uniform sampler2DMS uSampler;
|
||||
layout(binding = 0) uniform mediump sampler2DMS uSampler;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
void main()
|
||||
|
|
|
@ -467,6 +467,7 @@ struct SPIRVariable : IVariant
|
|||
bool deferred_declaration = false;
|
||||
bool phi_variable = false;
|
||||
bool remapped_variable = false;
|
||||
uint32_t remapped_components = 0;
|
||||
|
||||
SPIRFunction::Parameter *parameter = nullptr;
|
||||
};
|
||||
|
|
|
@ -163,9 +163,9 @@ void CompilerCPP::emit_resources()
|
|||
auto &var = id.get<SPIRVariable>();
|
||||
auto &type = get<SPIRType>(var.basetype);
|
||||
|
||||
if (type.pointer && type.storage == StorageClassUniform && !is_builtin_variable(var) &&
|
||||
(meta[type.self].decoration.decoration_flags &
|
||||
((1ull << DecorationBlock) | (1ull << DecorationBufferBlock))))
|
||||
if (var.storage != StorageClassFunction && type.pointer && type.storage == StorageClassUniform &&
|
||||
!is_builtin_variable(var) && (meta[type.self].decoration.decoration_flags &
|
||||
((1ull << DecorationBlock) | (1ull << DecorationBufferBlock))))
|
||||
{
|
||||
emit_buffer_block(var);
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ void CompilerCPP::emit_resources()
|
|||
{
|
||||
auto &var = id.get<SPIRVariable>();
|
||||
auto &type = get<SPIRType>(var.basetype);
|
||||
if (type.pointer && type.storage == StorageClassPushConstant)
|
||||
if (var.storage != StorageClassFunction && type.pointer && type.storage == StorageClassPushConstant)
|
||||
emit_push_constant_block(var);
|
||||
}
|
||||
}
|
||||
|
@ -192,8 +192,8 @@ void CompilerCPP::emit_resources()
|
|||
auto &var = id.get<SPIRVariable>();
|
||||
auto &type = get<SPIRType>(var.basetype);
|
||||
|
||||
if (!is_builtin_variable(var) && !var.remapped_variable && type.pointer &&
|
||||
(var.storage == StorageClassInput || var.storage == StorageClassOutput))
|
||||
if (var.storage != StorageClassFunction && !is_builtin_variable(var) && !var.remapped_variable &&
|
||||
type.pointer && (var.storage == StorageClassInput || var.storage == StorageClassOutput))
|
||||
{
|
||||
emit_interface_block(var);
|
||||
}
|
||||
|
@ -208,7 +208,8 @@ void CompilerCPP::emit_resources()
|
|||
auto &var = id.get<SPIRVariable>();
|
||||
auto &type = get<SPIRType>(var.basetype);
|
||||
|
||||
if (!is_builtin_variable(var) && !var.remapped_variable && type.pointer &&
|
||||
if (var.storage != StorageClassFunction && !is_builtin_variable(var) && !var.remapped_variable &&
|
||||
type.pointer &&
|
||||
(type.storage == StorageClassUniformConstant || type.storage == StorageClassAtomicCounter))
|
||||
{
|
||||
emit_uniform(var);
|
||||
|
|
|
@ -411,7 +411,9 @@ ShaderResources Compiler::get_shader_resources() const
|
|||
auto &var = id.get<SPIRVariable>();
|
||||
auto &type = get<SPIRType>(var.basetype);
|
||||
|
||||
if (!type.pointer || is_builtin_variable(var))
|
||||
// It is possible for uniform storage classes to be passed as function parameters, so detect
|
||||
// that. To detect function parameters, check of StorageClass of variable is function scope.
|
||||
if (var.storage == StorageClassFunction || !type.pointer || is_builtin_variable(var))
|
||||
continue;
|
||||
|
||||
// Input
|
||||
|
@ -620,7 +622,7 @@ void Compiler::set_name(uint32_t id, const std::string &name)
|
|||
if (name.empty())
|
||||
return;
|
||||
// Reserved for temporaries.
|
||||
if (name[0] == '_')
|
||||
if (name[0] == '_' && name.size() >= 2 && isdigit(name[1]))
|
||||
return;
|
||||
|
||||
// Functions in glslangValidator are mangled with name(<mangled> stuff.
|
||||
|
@ -1998,3 +2000,23 @@ ExecutionModel Compiler::get_execution_model() const
|
|||
{
|
||||
return execution.model;
|
||||
}
|
||||
|
||||
void Compiler::set_remapped_variable_state(uint32_t id, bool remap_enable)
|
||||
{
|
||||
get<SPIRVariable>(id).remapped_variable = remap_enable;
|
||||
}
|
||||
|
||||
bool Compiler::get_remapped_variable_state(uint32_t id) const
|
||||
{
|
||||
return get<SPIRVariable>(id).remapped_variable;
|
||||
}
|
||||
|
||||
void Compiler::set_subpass_input_remapped_components(uint32_t id, uint32_t components)
|
||||
{
|
||||
get<SPIRVariable>(id).remapped_components = components;
|
||||
}
|
||||
|
||||
uint32_t Compiler::get_subpass_input_remapped_components(uint32_t id) const
|
||||
{
|
||||
return get<SPIRVariable>(id).remapped_components;
|
||||
}
|
||||
|
|
|
@ -171,6 +171,18 @@ public:
|
|||
// Query shader resources, use ids with reflection interface to modify or query binding points, etc.
|
||||
ShaderResources get_shader_resources() const;
|
||||
|
||||
// Remapped variables are considered built-in variables and a backend will
|
||||
// not emit a declaration for this variable.
|
||||
// This is mostly useful for making use of builtins which are dependent on extensions.
|
||||
void set_remapped_variable_state(uint32_t id, bool remap_enable);
|
||||
bool get_remapped_variable_state(uint32_t id) const;
|
||||
|
||||
// For subpassInput variables which are remapped to plain variables,
|
||||
// the number of components in the remapped
|
||||
// variable must be specified as the backing type of subpass inputs are opaque.
|
||||
void set_subpass_input_remapped_components(uint32_t id, uint32_t components);
|
||||
uint32_t get_subpass_input_remapped_components(uint32_t id) const;
|
||||
|
||||
// Query and modify OpExecutionMode.
|
||||
uint64_t get_execution_mode_mask() const;
|
||||
void unset_execution_mode(spv::ExecutionMode mode);
|
||||
|
|
|
@ -204,6 +204,9 @@ void CompilerGLSL::emit_header()
|
|||
{
|
||||
statement("#version ", options.version, options.es && options.version > 100 ? " es" : "");
|
||||
|
||||
for (auto &header : header_lines)
|
||||
statement(header);
|
||||
|
||||
// Needed for binding = # on UBOs, etc.
|
||||
if (!options.es && options.version < 420)
|
||||
{
|
||||
|
@ -1018,9 +1021,9 @@ void CompilerGLSL::emit_resources()
|
|||
auto &var = id.get<SPIRVariable>();
|
||||
auto &type = get<SPIRType>(var.basetype);
|
||||
|
||||
if (type.pointer && type.storage == StorageClassUniform && !is_builtin_variable(var) &&
|
||||
(meta[type.self].decoration.decoration_flags &
|
||||
((1ull << DecorationBlock) | (1ull << DecorationBufferBlock))))
|
||||
if (var.storage != StorageClassFunction && type.pointer && type.storage == StorageClassUniform &&
|
||||
!is_builtin_variable(var) && (meta[type.self].decoration.decoration_flags &
|
||||
((1ull << DecorationBlock) | (1ull << DecorationBufferBlock))))
|
||||
{
|
||||
emit_buffer_block(var);
|
||||
}
|
||||
|
@ -1034,7 +1037,7 @@ void CompilerGLSL::emit_resources()
|
|||
{
|
||||
auto &var = id.get<SPIRVariable>();
|
||||
auto &type = get<SPIRType>(var.basetype);
|
||||
if (type.pointer && type.storage == StorageClassPushConstant)
|
||||
if (var.storage != StorageClassFunction && type.pointer && type.storage == StorageClassPushConstant)
|
||||
emit_push_constant_block(var);
|
||||
}
|
||||
}
|
||||
|
@ -1049,7 +1052,8 @@ void CompilerGLSL::emit_resources()
|
|||
auto &var = id.get<SPIRVariable>();
|
||||
auto &type = get<SPIRType>(var.basetype);
|
||||
|
||||
if (!is_builtin_variable(var) && !var.remapped_variable && type.pointer &&
|
||||
if (var.storage != StorageClassFunction && !is_builtin_variable(var) && !var.remapped_variable &&
|
||||
type.pointer &&
|
||||
(type.storage == StorageClassUniformConstant || type.storage == StorageClassAtomicCounter))
|
||||
{
|
||||
emit_uniform(var);
|
||||
|
@ -1070,8 +1074,8 @@ void CompilerGLSL::emit_resources()
|
|||
auto &var = id.get<SPIRVariable>();
|
||||
auto &type = get<SPIRType>(var.basetype);
|
||||
|
||||
if (!is_builtin_variable(var) && !var.remapped_variable && type.pointer &&
|
||||
(var.storage == StorageClassInput || var.storage == StorageClassOutput))
|
||||
if (var.storage != StorageClassFunction && !is_builtin_variable(var) && !var.remapped_variable &&
|
||||
type.pointer && (var.storage == StorageClassInput || var.storage == StorageClassOutput))
|
||||
{
|
||||
emit_interface_block(var);
|
||||
emitted = true;
|
||||
|
@ -2694,6 +2698,9 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
|
|||
funexpr += static_func_args(callee, length);
|
||||
funexpr += ")";
|
||||
|
||||
// Check for function call constraints.
|
||||
check_function_call_constraints(arg, length);
|
||||
|
||||
if (get<SPIRType>(result_type).basetype != SPIRType::Void)
|
||||
{
|
||||
// If the function actually writes to an out variable,
|
||||
|
@ -3532,18 +3539,26 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
|
|||
string imgexpr;
|
||||
auto &type = expression_type(ops[2]);
|
||||
|
||||
if (var && var->remapped_variable) // PLS input, just read as-is without any op-code
|
||||
if (var && var->remapped_variable) // Remapped input, just read as-is without any op-code
|
||||
{
|
||||
// PLS input could have different number of components than what the SPIR expects, swizzle to
|
||||
// the appropriate vector size.
|
||||
auto itr =
|
||||
find_if(begin(pls_inputs), end(pls_inputs), [var](const PlsRemap &pls) { return pls.id == var->self; });
|
||||
|
||||
if (itr == end(pls_inputs))
|
||||
throw CompilerError("Found PLS remap for OpImageRead, but ID is not a PLS input ...");
|
||||
|
||||
uint32_t components = pls_format_to_components(itr->format);
|
||||
imgexpr = remap_swizzle(result_type, components, ops[2]);
|
||||
{
|
||||
// For non-PLS inputs, we rely on subpass type remapping information to get it right
|
||||
// since ImageRead always returns 4-component vectors and the backing type is opaque.
|
||||
if (!var->remapped_components)
|
||||
throw CompilerError("subpassInput was remapped, but remap_components is not set correctly.");
|
||||
imgexpr = remap_swizzle(result_type, var->remapped_components, ops[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// PLS input could have different number of components than what the SPIR expects, swizzle to
|
||||
// the appropriate vector size.
|
||||
uint32_t components = pls_format_to_components(itr->format);
|
||||
imgexpr = remap_swizzle(result_type, components, ops[2]);
|
||||
}
|
||||
pure = true;
|
||||
}
|
||||
else if (type.image.dim == DimSubpassData)
|
||||
|
@ -4107,6 +4122,11 @@ void CompilerGLSL::add_resource_name(uint32_t id)
|
|||
add_variable(resource_names, id);
|
||||
}
|
||||
|
||||
void CompilerGLSL::add_header_line(const std::string &line)
|
||||
{
|
||||
header_lines.push_back(line);
|
||||
}
|
||||
|
||||
void CompilerGLSL::require_extension(const string &ext)
|
||||
{
|
||||
if (forced_extensions.find(ext) == end(forced_extensions))
|
||||
|
@ -4805,3 +4825,26 @@ void CompilerGLSL::end_scope_decl(const string &decl)
|
|||
indent--;
|
||||
statement("} ", decl, ";");
|
||||
}
|
||||
|
||||
void CompilerGLSL::check_function_call_constraints(const uint32_t *args, uint32_t length)
|
||||
{
|
||||
// If our variable is remapped, and we rely on type-remapping information as
|
||||
// well, then we cannot pass the variable as a function parameter.
|
||||
// Fixing this is non-trivial without stamping out variants of the same function,
|
||||
// so for now warn about this and suggest workarounds instead.
|
||||
for (uint32_t i = 0; i < length; i++)
|
||||
{
|
||||
auto *var = maybe_get<SPIRVariable>(args[i]);
|
||||
if (!var || !var->remapped_variable)
|
||||
continue;
|
||||
|
||||
auto &type = get<SPIRType>(var->basetype);
|
||||
if (type.basetype == SPIRType::Image && type.image.dim == DimSubpassData)
|
||||
{
|
||||
throw CompilerError("Tried passing a remapped subpassInput variable to a function. "
|
||||
"This will not work correctly because type-remapping information is lost. "
|
||||
"To workaround, please consider not passing the subpass input as a function parameter, "
|
||||
"or use in/out variables instead which do not need type remapping information.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,6 +114,22 @@ public:
|
|||
}
|
||||
std::string compile() override;
|
||||
|
||||
// Adds a line to be added right after #version in GLSL backend.
|
||||
// This is useful for enabling custom extensions which are outside the scope of SPIRV-Cross.
|
||||
// This can be combined with variable remapping.
|
||||
// A new-line will be added.
|
||||
//
|
||||
// While add_header_line() is a more generic way of adding arbitrary text to the header
|
||||
// of a GLSL file, require_extension() should be used when adding extensions since it will
|
||||
// avoid creating collisions with SPIRV-Cross generated extensions.
|
||||
//
|
||||
// Code added via add_header_line() is typically backend-specific.
|
||||
void add_header_line(const std::string &str);
|
||||
|
||||
// Adds an extension which is required to run this shader, e.g.
|
||||
// require_extension("GL_KHR_my_extension");
|
||||
void require_extension(const std::string &ext);
|
||||
|
||||
protected:
|
||||
void reset();
|
||||
void emit_function(SPIRFunction &func, uint64_t return_flags);
|
||||
|
@ -289,7 +305,6 @@ protected:
|
|||
// Can modify flags to remote readonly/writeonly if image type
|
||||
// and force recompile.
|
||||
bool check_atomic_image(uint32_t id);
|
||||
void require_extension(const std::string &ext);
|
||||
|
||||
void replace_fragment_output(SPIRVariable &var);
|
||||
void replace_fragment_outputs();
|
||||
|
@ -307,6 +322,7 @@ protected:
|
|||
void track_expression_read(uint32_t id);
|
||||
|
||||
std::unordered_set<std::string> forced_extensions;
|
||||
std::vector<std::string> header_lines;
|
||||
|
||||
uint32_t statement_count;
|
||||
|
||||
|
@ -328,6 +344,8 @@ protected:
|
|||
void remap_pls_variables();
|
||||
|
||||
void add_variable(std::unordered_set<std::string> &variables, uint32_t id);
|
||||
|
||||
void check_function_call_constraints(const uint32_t *args, uint32_t length);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -531,10 +531,13 @@ void CompilerMSL::emit_resources()
|
|||
auto &var = id.get<SPIRVariable>();
|
||||
auto &type = get<SPIRType>(var.basetype);
|
||||
|
||||
if (type.pointer && (var.storage == StorageClassUniform || var.storage == StorageClassUniformConstant ||
|
||||
var.storage == StorageClassPushConstant) &&
|
||||
!is_builtin_variable(var) && (meta[type.self].decoration.decoration_flags &
|
||||
((1ull << DecorationBlock) | (1ull << DecorationBufferBlock))))
|
||||
if (type.pointer &&
|
||||
!is_builtin_variable(var) &&
|
||||
(var.storage == StorageClassUniform ||
|
||||
var.storage == StorageClassUniformConstant ||
|
||||
var.storage == StorageClassPushConstant) &&
|
||||
(meta[type.self].decoration.decoration_flags &
|
||||
((1ull << DecorationBlock) | (1ull << DecorationBufferBlock))))
|
||||
{
|
||||
emit_struct(type);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче