Use input/output structs for HLSL

This commit is contained in:
Robert Konrad 2016-08-14 17:58:56 +02:00
parent 45270f618f
commit 02fd8e92ab
2 changed files with 155 additions and 1 deletions

View File

@ -20,6 +20,158 @@ using namespace spv;
using namespace spirv_cross;
using namespace std;
void CompilerHLSL::emit_header()
{
auto &execution = get_entry_point();
for (auto &header : header_lines)
statement(header);
statement("");
}
void CompilerHLSL::emit_interface_block(const SPIRVariable &var, uint32_t &binding_number)
{
auto &execution = get_entry_point();
auto &type = get<SPIRType>(var.basetype);
const char* binding = "TEXCOORD";
if (is_builtin_variable(var) || var.remapped_variable)
{
binding = "COLOR";
}
add_resource_name(var.self);
statement(layout_for_variable(var), variable_decl(var), " : ", binding, binding_number, ";");
if (!is_builtin_variable(var) && !var.remapped_variable)
{
++binding_number;
}
}
void CompilerHLSL::emit_resources()
{
auto &execution = get_entry_point();
// Emit PLS blocks if we have such variables.
if (!pls_inputs.empty() || !pls_outputs.empty())
emit_pls();
// Output all basic struct types which are not Block or BufferBlock as these are declared inplace
// when such variables are instantiated.
for (auto &id : ids)
{
if (id.get_type() == TypeType)
{
auto &type = id.get<SPIRType>();
if (type.basetype == SPIRType::Struct && type.array.empty() && !type.pointer &&
(meta[type.self].decoration.decoration_flags &
((1ull << DecorationBlock) | (1ull << DecorationBufferBlock))) == 0)
{
emit_struct(type);
}
}
}
bool emitted = false;
// Output Uniform Constants (values, samplers, images, etc).
for (auto &id : ids)
{
if (id.get_type() == TypeVariable)
{
auto &var = id.get<SPIRVariable>();
auto &type = get<SPIRType>(var.basetype);
if (var.storage != StorageClassFunction && !is_builtin_variable(var) && !var.remapped_variable &&
type.pointer &&
(type.storage == StorageClassUniformConstant || type.storage == StorageClassAtomicCounter))
{
emit_uniform(var);
emitted = true;
}
}
}
if (emitted)
statement("");
emitted = false;
if (execution.model == ExecutionModelVertex)
{
statement("struct InputVert");
}
else
{
statement("struct InputFrag");
}
begin_scope();
uint32_t binding_number = 0;
for (auto &id : ids)
{
if (id.get_type() == TypeVariable)
{
auto &var = id.get<SPIRVariable>();
auto &type = get<SPIRType>(var.basetype);
if (var.storage != StorageClassFunction && !var.remapped_variable &&
type.pointer && var.storage == StorageClassInput &&
interface_variable_exists_in_entry_point(var.self))
{
emit_interface_block(var, binding_number);
emitted = true;
}
}
}
end_scope_decl();
statement("");
if (execution.model == ExecutionModelVertex)
{
statement("struct OutputVert");
}
else
{
statement("struct OutputFrag");
}
begin_scope();
binding_number = 0;
for (auto &id : ids)
{
if (id.get_type() == TypeVariable)
{
auto &var = id.get<SPIRVariable>();
auto &type = get<SPIRType>(var.basetype);
if (var.storage != StorageClassFunction && !var.remapped_variable &&
type.pointer && var.storage == StorageClassOutput &&
interface_variable_exists_in_entry_point(var.self))
{
emit_interface_block(var, binding_number);
emitted = true;
}
}
}
end_scope_decl();
statement("");
// Global variables.
for (auto global : global_variables)
{
auto &var = get<SPIRVariable>(global);
if (var.storage != StorageClassOutput)
{
add_resource_name(var.self);
statement("static ", variable_decl(var), ";");
emitted = true;
}
}
if (emitted)
statement("");
}
string CompilerHLSL::compile()
{
// Do not deal with ES-isms like precision, older extensions and such.

View File

@ -33,7 +33,9 @@ namespace spirv_cross
std::string compile() override;
private:
void emit_header() override;
void emit_resources();
void emit_interface_block(const SPIRVariable &type, uint32_t &binding_number);
};
}