Begin rewriting how HLSL deals with inputs and outputs.
This commit is contained in:
parent
099f307123
commit
bdea1a444a
@ -4,15 +4,15 @@ static float4 FragColor;
|
||||
static float4 vColor;
|
||||
static float2 vTex;
|
||||
|
||||
struct InputFrag
|
||||
struct SPIRV_Cross_Input
|
||||
{
|
||||
float4 vColor : TEXCOORD0;
|
||||
float2 vTex : TEXCOORD1;
|
||||
};
|
||||
|
||||
struct OutputFrag
|
||||
struct SPIRV_Cross_Output
|
||||
{
|
||||
float4 FragColor : COLOR;
|
||||
float4 FragColor : COLOR0;
|
||||
};
|
||||
|
||||
void frag_main()
|
||||
@ -20,12 +20,12 @@ void frag_main()
|
||||
FragColor = vColor * tex2D(uTex, vTex);
|
||||
}
|
||||
|
||||
OutputFrag main(InputFrag input)
|
||||
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
|
||||
{
|
||||
vColor = input.vColor;
|
||||
vTex = input.vTex;
|
||||
vColor = stage_input.vColor;
|
||||
vTex = stage_input.vTex;
|
||||
frag_main();
|
||||
OutputFrag output;
|
||||
output.FragColor = FragColor;
|
||||
return output;
|
||||
SPIRV_Cross_Output stage_output;
|
||||
stage_output.FragColor = FragColor;
|
||||
return stage_output;
|
||||
}
|
||||
|
@ -14,16 +14,16 @@ static float4 aVertex;
|
||||
static float3 vNormal;
|
||||
static float3 aNormal;
|
||||
|
||||
struct InputVert
|
||||
struct SPIRV_Cross_Input
|
||||
{
|
||||
float3 aNormal : TEXCOORD0;
|
||||
float4 aVertex : TEXCOORD1;
|
||||
};
|
||||
|
||||
struct OutputVert
|
||||
struct SPIRV_Cross_Output
|
||||
{
|
||||
float3 vNormal : TEXCOORD0;
|
||||
float4 gl_Position : POSITION;
|
||||
float3 vNormal : TEXCOORD2;
|
||||
};
|
||||
|
||||
void vert_main()
|
||||
@ -32,15 +32,15 @@ void vert_main()
|
||||
vNormal = aNormal;
|
||||
}
|
||||
|
||||
OutputVert main(InputVert input)
|
||||
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
|
||||
{
|
||||
aVertex = input.aVertex;
|
||||
aNormal = input.aNormal;
|
||||
aVertex = stage_input.aVertex;
|
||||
aNormal = stage_input.aNormal;
|
||||
vert_main();
|
||||
OutputVert output;
|
||||
output.gl_Position = gl_Position;
|
||||
output.vNormal = vNormal;
|
||||
output.gl_Position.x = output.gl_Position.x - gl_HalfPixel.x * output.gl_Position.w;
|
||||
output.gl_Position.y = output.gl_Position.y + gl_HalfPixel.y * output.gl_Position.w;
|
||||
return output;
|
||||
SPIRV_Cross_Output stage_output;
|
||||
stage_output.gl_Position = gl_Position;
|
||||
stage_output.vNormal = vNormal;
|
||||
stage_output.gl_Position.x = stage_output.gl_Position.x - gl_HalfPixel.x * stage_output.gl_Position.w;
|
||||
stage_output.gl_Position.y = stage_output.gl_Position.y + gl_HalfPixel.y * stage_output.gl_Position.w;
|
||||
return stage_output;
|
||||
}
|
||||
|
@ -3124,7 +3124,12 @@ bool Compiler::ActiveBuiltinHandler::handle(spv::Op opcode, const uint32_t *args
|
||||
// Builtins which are part of a block are handled in AccessChain.
|
||||
auto *var = compiler.maybe_get<SPIRVariable>(id);
|
||||
if (var && compiler.meta[id].decoration.builtin)
|
||||
compiler.active_builtins |= 1ull << compiler.meta[id].decoration.builtin_type;
|
||||
{
|
||||
auto &type = compiler.get<SPIRType>(var->basetype);
|
||||
auto &flags =
|
||||
type.storage == StorageClassInput ? compiler.active_input_builtins : compiler.active_output_builtins;
|
||||
flags |= 1ull << compiler.meta[id].decoration.builtin_type;
|
||||
}
|
||||
};
|
||||
|
||||
switch (opcode)
|
||||
@ -3185,6 +3190,8 @@ bool Compiler::ActiveBuiltinHandler::handle(spv::Op opcode, const uint32_t *args
|
||||
type = &compiler.get<SPIRType>(type->parent_type);
|
||||
}
|
||||
|
||||
auto &flags = type->storage == StorageClassInput ? compiler.active_input_builtins : compiler.active_output_builtins;
|
||||
|
||||
uint32_t count = length - 3;
|
||||
args += 3;
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
@ -3203,7 +3210,7 @@ bool Compiler::ActiveBuiltinHandler::handle(spv::Op opcode, const uint32_t *args
|
||||
{
|
||||
auto &decorations = compiler.meta[type->self].members[index];
|
||||
if (decorations.builtin)
|
||||
compiler.active_builtins |= 1ull << decorations.builtin_type;
|
||||
flags |= 1ull << decorations.builtin_type;
|
||||
}
|
||||
|
||||
type = &compiler.get<SPIRType>(type->member_types[index]);
|
||||
@ -3226,7 +3233,8 @@ bool Compiler::ActiveBuiltinHandler::handle(spv::Op opcode, const uint32_t *args
|
||||
|
||||
void Compiler::update_active_builtins()
|
||||
{
|
||||
active_builtins = 0;
|
||||
active_input_builtins = 0;
|
||||
active_output_builtins = 0;
|
||||
ActiveBuiltinHandler handler(*this);
|
||||
traverse_all_reachable_opcodes(get<SPIRFunction>(entry_point), handler);
|
||||
}
|
||||
|
@ -603,7 +603,8 @@ protected:
|
||||
std::unordered_set<uint32_t> forced_temporaries;
|
||||
std::unordered_set<uint32_t> forwarded_temporaries;
|
||||
|
||||
uint64_t active_builtins = 0;
|
||||
uint64_t active_input_builtins = 0;
|
||||
uint64_t active_output_builtins = 0;
|
||||
// Traverses all reachable opcodes and sets active_builtins to a bitmask of all builtin variables which are accessed in the shader.
|
||||
void update_active_builtins();
|
||||
};
|
||||
|
425
spirv_hlsl.cpp
425
spirv_hlsl.cpp
@ -26,17 +26,30 @@ namespace
|
||||
{
|
||||
struct VariableComparator
|
||||
{
|
||||
VariableComparator(const std::vector<Meta> &m)
|
||||
: meta(m)
|
||||
VariableComparator(const CompilerHLSL &compiler_)
|
||||
: compiler(compiler_)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator()(SPIRVariable *var1, SPIRVariable *var2)
|
||||
{
|
||||
return meta[var1->self].decoration.alias.compare(meta[var2->self].decoration.alias) < 0;
|
||||
if (compiler.get_decoration_mask(var1->self) & compiler.get_decoration_mask(var2->self) & (1ull << DecorationLocation))
|
||||
return compiler.get_decoration(var1->self, DecorationLocation) < compiler.get_decoration(var2->self, DecorationLocation);
|
||||
|
||||
auto &name1 = compiler.get_name(var1->self);
|
||||
auto &name2 = compiler.get_name(var2->self);
|
||||
|
||||
if (name1.empty() && name2.empty())
|
||||
return var1->self < var2->self;
|
||||
if (name1.empty())
|
||||
return true;
|
||||
else if (name2.empty())
|
||||
return false;
|
||||
|
||||
return name1.compare(name2) < 0;
|
||||
}
|
||||
|
||||
const std::vector<Meta> &meta;
|
||||
const CompilerHLSL &compiler;
|
||||
};
|
||||
}
|
||||
|
||||
@ -178,71 +191,124 @@ const char *CompilerHLSL::to_storage_qualifiers_glsl(const SPIRVariable &var)
|
||||
return "";
|
||||
}
|
||||
|
||||
void CompilerHLSL::emit_interface_block_in_struct(const SPIRVariable &var, uint32_t &binding_number, bool builtins)
|
||||
void CompilerHLSL::emit_builtin_outputs_in_struct()
|
||||
{
|
||||
bool legacy = options.shader_model <= 30;
|
||||
for (uint32_t i = 0; i < 64; i++)
|
||||
{
|
||||
if (!(active_output_builtins & (1ull << i)))
|
||||
continue;
|
||||
|
||||
const char *type = nullptr;
|
||||
const char *semantic = nullptr;
|
||||
auto builtin = static_cast<BuiltIn>(i);
|
||||
switch (builtin)
|
||||
{
|
||||
case BuiltInPosition:
|
||||
type = "float4";
|
||||
semantic = legacy ? "POSITION" : "SV_Position";
|
||||
break;
|
||||
|
||||
default:
|
||||
SPIRV_CROSS_THROW("Unsupported builtin in HLSL.");
|
||||
break;
|
||||
}
|
||||
|
||||
if (type && semantic)
|
||||
statement(type, " ", builtin_to_glsl(builtin), " : ", semantic, ";");
|
||||
}
|
||||
}
|
||||
|
||||
void CompilerHLSL::emit_builtin_inputs_in_struct()
|
||||
{
|
||||
bool legacy = options.shader_model <= 30;
|
||||
for (uint32_t i = 0; i < 64; i++)
|
||||
{
|
||||
if (!(active_input_builtins & (1ull << i)))
|
||||
continue;
|
||||
|
||||
const char *type = nullptr;
|
||||
const char *semantic = nullptr;
|
||||
auto builtin = static_cast<BuiltIn>(i);
|
||||
switch (builtin)
|
||||
{
|
||||
case BuiltInFragCoord:
|
||||
type = "float4";
|
||||
semantic = legacy ? "POSITION" : "SV_Position";
|
||||
break;
|
||||
|
||||
default:
|
||||
SPIRV_CROSS_THROW("Unsupported builtin in HLSL.");
|
||||
break;
|
||||
}
|
||||
|
||||
if (type && semantic)
|
||||
statement(type, " ", builtin_to_glsl(builtin), " : ", semantic, ";");
|
||||
}
|
||||
}
|
||||
|
||||
void CompilerHLSL::emit_interface_block_in_struct(const SPIRVariable &var, uint32_t &binding_number)
|
||||
{
|
||||
auto &execution = get_entry_point();
|
||||
auto &type = get<SPIRType>(var.basetype);
|
||||
|
||||
const char *binding = "TEXCOORD";
|
||||
string binding = "TEXCOORD";
|
||||
bool use_binding_number = true;
|
||||
bool legacy = options.shader_model <= 30;
|
||||
if (execution.model == ExecutionModelFragment && var.storage == StorageClassOutput)
|
||||
{
|
||||
binding = "COLOR";
|
||||
use_binding_number = false;
|
||||
}
|
||||
else if (execution.model == ExecutionModelVertex && var.storage == StorageClassOutput && is_builtin_variable(var))
|
||||
{
|
||||
if (options.shader_model <= 30)
|
||||
{
|
||||
binding = "POSITION";
|
||||
}
|
||||
else
|
||||
{
|
||||
binding = "SV_POSITION";
|
||||
}
|
||||
binding = join(legacy ? "COLOR" : "SV_Target", get_decoration(var.self, DecorationLocation));
|
||||
use_binding_number = false;
|
||||
}
|
||||
|
||||
bool is_no_builtin = !is_builtin_variable(var) && !var.remapped_variable;
|
||||
|
||||
if ((is_no_builtin && !builtins) || (!is_no_builtin && builtins))
|
||||
auto &m = meta[var.self].decoration;
|
||||
if (use_binding_number)
|
||||
{
|
||||
auto &m = meta[var.self].decoration;
|
||||
if (use_binding_number)
|
||||
if (type.columns > 1)
|
||||
{
|
||||
if (type.vecsize == 4 && type.columns == 4)
|
||||
for (uint32_t i = 0; i < type.columns; i++)
|
||||
{
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
std::stringstream name;
|
||||
name << m.alias << "_" << i;
|
||||
SPIRType newtype = type;
|
||||
newtype.columns = 1;
|
||||
statement(variable_decl(newtype, name.str()), " : ", binding, binding_number++, ";");
|
||||
}
|
||||
--binding_number;
|
||||
}
|
||||
else
|
||||
{
|
||||
statement(variable_decl(type, m.alias), " : ", binding, binding_number, ";");
|
||||
SPIRType newtype = type;
|
||||
newtype.columns = 1;
|
||||
statement(variable_decl(newtype, join(m.alias, "_", i)), " : ", binding, binding_number++, ";");
|
||||
}
|
||||
--binding_number;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (execution.model == ExecutionModelVertex)
|
||||
{
|
||||
statement("float4 gl_Position", " : ", binding, ";");
|
||||
}
|
||||
else
|
||||
{
|
||||
statement(variable_decl(type, m.alias), " : ", binding, ";");
|
||||
}
|
||||
}
|
||||
statement(variable_decl(type, m.alias), " : ", binding, binding_number, ";");
|
||||
}
|
||||
else
|
||||
statement(variable_decl(type, m.alias), " : ", binding, ";");
|
||||
|
||||
if (is_no_builtin)
|
||||
if (use_binding_number)
|
||||
binding_number++;
|
||||
}
|
||||
|
||||
void CompilerHLSL::emit_builtin_variables()
|
||||
{
|
||||
// Emit global variables for the interface variables which are statically used by the shader.
|
||||
for (uint32_t i = 0; i < 64; i++)
|
||||
{
|
||||
++binding_number;
|
||||
if (!((active_input_builtins | active_output_builtins) & (1ull << i)))
|
||||
continue;
|
||||
|
||||
const char *type = nullptr;
|
||||
auto builtin = static_cast<BuiltIn>(i);
|
||||
|
||||
switch (builtin)
|
||||
{
|
||||
case BuiltInFragCoord:
|
||||
case BuiltInPosition:
|
||||
type = "float4";
|
||||
break;
|
||||
|
||||
default:
|
||||
SPIRV_CROSS_THROW(join("Unsupported builtin in HLSL: ", unsigned(builtin)));
|
||||
break;
|
||||
}
|
||||
|
||||
if (type)
|
||||
statement("static ", type, " ", builtin_to_glsl(builtin), ";");
|
||||
}
|
||||
}
|
||||
|
||||
@ -250,10 +316,6 @@ 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)
|
||||
@ -334,6 +396,9 @@ void CompilerHLSL::emit_resources()
|
||||
statement("");
|
||||
emitted = false;
|
||||
|
||||
// Emit builtin input and output variables here.
|
||||
emit_builtin_variables();
|
||||
|
||||
for (auto &id : ids)
|
||||
{
|
||||
if (id.get_type() == TypeVariable)
|
||||
@ -343,8 +408,10 @@ void CompilerHLSL::emit_resources()
|
||||
|
||||
if (var.storage != StorageClassFunction && !var.remapped_variable && type.pointer &&
|
||||
(var.storage == StorageClassInput || var.storage == StorageClassOutput) &&
|
||||
!is_builtin_variable(var) &&
|
||||
interface_variable_exists_in_entry_point(var.self))
|
||||
{
|
||||
// Only emit non-builtins here. Builtin variables are handled separately.
|
||||
emit_interface_block_globally(var);
|
||||
emitted = true;
|
||||
}
|
||||
@ -355,17 +422,9 @@ void CompilerHLSL::emit_resources()
|
||||
statement("");
|
||||
emitted = false;
|
||||
|
||||
if (execution.model == ExecutionModelVertex)
|
||||
{
|
||||
statement("struct InputVert");
|
||||
}
|
||||
else
|
||||
{
|
||||
statement("struct InputFrag");
|
||||
}
|
||||
begin_scope();
|
||||
uint32_t binding_number = 0;
|
||||
std::vector<SPIRVariable *> variables;
|
||||
vector<SPIRVariable *> input_variables;
|
||||
vector<SPIRVariable *> output_variables;
|
||||
for (auto &id : ids)
|
||||
{
|
||||
if (id.get_type() == TypeVariable)
|
||||
@ -373,63 +432,52 @@ void CompilerHLSL::emit_resources()
|
||||
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))
|
||||
if (!var.remapped_variable && type.pointer &&
|
||||
(var.storage == StorageClassInput || var.storage == StorageClassOutput) &&
|
||||
!is_builtin_variable(var) &&
|
||||
interface_variable_exists_in_entry_point(var.self))
|
||||
{
|
||||
if (execution.model == ExecutionModelVertex && is_builtin_variable(var))
|
||||
continue;
|
||||
variables.push_back(&var);
|
||||
if (var.storage == StorageClassInput)
|
||||
input_variables.push_back(&var);
|
||||
else
|
||||
output_variables.push_back(&var);
|
||||
}
|
||||
}
|
||||
}
|
||||
sort(variables.begin(), variables.end(), VariableComparator(meta));
|
||||
for (auto var : variables)
|
||||
{
|
||||
emit_interface_block_in_struct(*var, binding_number, false);
|
||||
}
|
||||
for (auto var : variables)
|
||||
{
|
||||
emit_interface_block_in_struct(*var, binding_number, true);
|
||||
}
|
||||
end_scope_decl();
|
||||
statement("");
|
||||
|
||||
if (execution.model == ExecutionModelVertex)
|
||||
if (!input_variables.empty() || active_input_builtins)
|
||||
{
|
||||
statement("struct OutputVert");
|
||||
require_input = true;
|
||||
statement("struct SPIRV_Cross_Input");
|
||||
|
||||
begin_scope();
|
||||
// FIXME: Use locations properly if they exist.
|
||||
sort(input_variables.begin(), input_variables.end(), VariableComparator(*this));
|
||||
emit_builtin_inputs_in_struct();
|
||||
for (auto var : input_variables)
|
||||
emit_interface_block_in_struct(*var, binding_number);
|
||||
end_scope_decl();
|
||||
statement("");
|
||||
}
|
||||
else
|
||||
{
|
||||
statement("struct OutputFrag");
|
||||
}
|
||||
begin_scope();
|
||||
binding_number = 0;
|
||||
variables.clear();
|
||||
for (auto &id : ids)
|
||||
{
|
||||
if (id.get_type() == TypeVariable)
|
||||
{
|
||||
auto &var = id.get<SPIRVariable>();
|
||||
auto &type = get<SPIRType>(var.basetype);
|
||||
require_input = false;
|
||||
|
||||
if (var.storage != StorageClassFunction && !var.remapped_variable && type.pointer &&
|
||||
var.storage == StorageClassOutput && interface_variable_exists_in_entry_point(var.self))
|
||||
{
|
||||
variables.push_back(&var);
|
||||
}
|
||||
}
|
||||
}
|
||||
sort(variables.begin(), variables.end(), VariableComparator(meta));
|
||||
for (auto var : variables)
|
||||
if (!output_variables.empty() || active_output_builtins)
|
||||
{
|
||||
emit_interface_block_in_struct(*var, binding_number, false);
|
||||
require_output = true;
|
||||
statement("struct SPIRV_Cross_Output");
|
||||
|
||||
begin_scope();
|
||||
// FIXME: Use locations properly if they exist.
|
||||
sort(output_variables.begin(), output_variables.end(), VariableComparator(*this));
|
||||
emit_builtin_outputs_in_struct();
|
||||
for (auto var : output_variables)
|
||||
emit_interface_block_in_struct(*var, binding_number);
|
||||
end_scope_decl();
|
||||
statement("");
|
||||
}
|
||||
for (auto var : variables)
|
||||
{
|
||||
emit_interface_block_in_struct(*var, binding_number, true);
|
||||
}
|
||||
end_scope_decl();
|
||||
statement("");
|
||||
else
|
||||
require_output = false;
|
||||
|
||||
// Global variables.
|
||||
for (auto global : global_variables)
|
||||
@ -542,96 +590,107 @@ void CompilerHLSL::emit_function_prototype(SPIRFunction &func, uint64_t return_f
|
||||
void CompilerHLSL::emit_hlsl_entry_point()
|
||||
{
|
||||
auto &execution = get_entry_point();
|
||||
const char *post = "Frag";
|
||||
if (execution.model == ExecutionModelVertex)
|
||||
{
|
||||
post = "Vert";
|
||||
}
|
||||
|
||||
statement("Output", post, " main(Input", post, " input)");
|
||||
statement(require_output ? "SPIRV_Cross_Output " : "void ", "main(", require_input ? "SPIRV_Cross_Input stage_input)" : ")");
|
||||
begin_scope();
|
||||
|
||||
for (auto &id : ids)
|
||||
if (require_input)
|
||||
{
|
||||
if (id.get_type() == TypeVariable)
|
||||
for (auto &id : ids)
|
||||
{
|
||||
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))
|
||||
// Copy builtins from entry point arguments to globals.
|
||||
for (uint32_t i = 0; i < 64; i++)
|
||||
{
|
||||
if (execution.model == ExecutionModelVertex && is_builtin_variable(var))
|
||||
if (!(active_input_builtins & (1ull << i)))
|
||||
continue;
|
||||
|
||||
auto &m = meta[var.self].decoration;
|
||||
auto &mtype = get<SPIRType>(var.basetype);
|
||||
if (mtype.vecsize == 4 && mtype.columns == 4)
|
||||
{
|
||||
statement(m.alias, "[0] = input.", m.alias, "_0;");
|
||||
statement(m.alias, "[1] = input.", m.alias, "_1;");
|
||||
statement(m.alias, "[2] = input.", m.alias, "_2;");
|
||||
statement(m.alias, "[3] = input.", m.alias, "_3;");
|
||||
}
|
||||
else
|
||||
{
|
||||
statement(m.alias, " = input.", m.alias, ";");
|
||||
}
|
||||
auto builtin = builtin_to_glsl(static_cast<BuiltIn>(i));
|
||||
statement(builtin, " = stage_input.", builtin, ";");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (execution.model == ExecutionModelVertex)
|
||||
{
|
||||
statement("vert_main();");
|
||||
}
|
||||
else
|
||||
{
|
||||
statement("frag_main();");
|
||||
}
|
||||
|
||||
statement("Output", post, " output;");
|
||||
|
||||
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))
|
||||
if (id.get_type() == TypeVariable)
|
||||
{
|
||||
auto &m = meta[var.self].decoration;
|
||||
bool is_no_builtin = !is_builtin_variable(var) && !var.remapped_variable;
|
||||
if (is_no_builtin)
|
||||
statement("output.", m.alias, " = ", m.alias, ";");
|
||||
else if (execution.model == ExecutionModelVertex)
|
||||
auto &var = id.get<SPIRVariable>();
|
||||
auto &type = get<SPIRType>(var.basetype);
|
||||
|
||||
if (var.storage != StorageClassFunction && !var.remapped_variable && type.pointer &&
|
||||
var.storage == StorageClassInput && !is_builtin_variable(var) &&
|
||||
interface_variable_exists_in_entry_point(var.self))
|
||||
{
|
||||
statement("output.gl_Position = gl_Position;");
|
||||
auto name = to_name(var.self);
|
||||
auto &mtype = get<SPIRType>(var.basetype);
|
||||
if (mtype.vecsize == 4 && mtype.columns == 4)
|
||||
{
|
||||
statement(name, "[0] = stage_input.", name, "_0;");
|
||||
statement(name, "[1] = stage_input.", name, "_1;");
|
||||
statement(name, "[2] = stage_input.", name, "_2;");
|
||||
statement(name, "[3] = stage_input.", name, "_3;");
|
||||
}
|
||||
else
|
||||
{
|
||||
statement(name, " = stage_input.", name, ";");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (execution.model == ExecutionModelVertex)
|
||||
{
|
||||
if (options.shader_model <= 30)
|
||||
{
|
||||
statement("output.gl_Position.x = output.gl_Position.x - gl_HalfPixel.x * output.gl_Position.w;");
|
||||
statement("output.gl_Position.y = output.gl_Position.y + gl_HalfPixel.y * output.gl_Position.w;");
|
||||
}
|
||||
if (options.flip_vert_y)
|
||||
{
|
||||
statement("output.gl_Position.y = -output.gl_Position.y;");
|
||||
}
|
||||
if (options.fixup_clipspace)
|
||||
{
|
||||
statement("output.gl_Position.z = (output.gl_Position.z + output.gl_Position.w) * 0.5;");
|
||||
}
|
||||
}
|
||||
statement("vert_main();");
|
||||
else if (execution.model == ExecutionModelFragment)
|
||||
statement("frag_main();");
|
||||
else
|
||||
SPIRV_CROSS_THROW("Unsupported shader stage.");
|
||||
|
||||
statement("return output;");
|
||||
if (require_output)
|
||||
{
|
||||
statement("SPIRV_Cross_Output stage_output;");
|
||||
|
||||
// Copy builtins from globals to return struct.
|
||||
for (uint32_t i = 0; i < 64; i++)
|
||||
{
|
||||
if (!(active_output_builtins & (1ull << i)))
|
||||
continue;
|
||||
|
||||
auto builtin = builtin_to_glsl(static_cast<BuiltIn>(i));
|
||||
statement("stage_output.", builtin, " = ", builtin, ";");
|
||||
}
|
||||
|
||||
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 && !is_builtin_variable(var) &&
|
||||
interface_variable_exists_in_entry_point(var.self))
|
||||
{
|
||||
auto name = to_name(var.self);
|
||||
statement("stage_output.", name, " = ", name, ";");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (execution.model == ExecutionModelVertex)
|
||||
{
|
||||
if (options.shader_model <= 30)
|
||||
{
|
||||
statement("stage_output.gl_Position.x = stage_output.gl_Position.x - gl_HalfPixel.x * stage_output.gl_Position.w;");
|
||||
statement("stage_output.gl_Position.y = stage_output.gl_Position.y + gl_HalfPixel.y * stage_output.gl_Position.w;");
|
||||
}
|
||||
if (options.flip_vert_y)
|
||||
{
|
||||
statement("stage_output.gl_Position.y = -stage_output.gl_Position.y;");
|
||||
}
|
||||
if (options.fixup_clipspace)
|
||||
{
|
||||
statement("stage_output.gl_Position.z = (stage_output.gl_Position.z + stage_output.gl_Position.w) * 0.5;");
|
||||
}
|
||||
}
|
||||
|
||||
statement("return stage_output;");
|
||||
}
|
||||
|
||||
end_scope();
|
||||
}
|
||||
@ -1002,7 +1061,7 @@ string CompilerHLSL::compile()
|
||||
backend.swizzle_is_function = false;
|
||||
backend.shared_is_implied = true;
|
||||
backend.flexible_member_array_supported = false;
|
||||
backend.explicit_struct_type = true;
|
||||
backend.explicit_struct_type = false;
|
||||
backend.use_initializer_list = true;
|
||||
backend.use_constructor_splatting = false;
|
||||
|
||||
|
@ -57,7 +57,9 @@ private:
|
||||
void emit_header() override;
|
||||
void emit_resources();
|
||||
void emit_interface_block_globally(const SPIRVariable &type);
|
||||
void emit_interface_block_in_struct(const SPIRVariable &type, uint32_t &binding_number, bool builtins);
|
||||
void emit_interface_block_in_struct(const SPIRVariable &type, uint32_t &binding_number);
|
||||
void emit_builtin_inputs_in_struct();
|
||||
void emit_builtin_outputs_in_struct();
|
||||
void emit_texture_op(const Instruction &i) override;
|
||||
void emit_instruction(const Instruction &instruction) override;
|
||||
void emit_glsl_op(uint32_t result_type, uint32_t result_id, uint32_t op, const uint32_t *args,
|
||||
@ -70,6 +72,10 @@ private:
|
||||
|
||||
Options options;
|
||||
bool requires_op_fmod = false;
|
||||
|
||||
void emit_builtin_variables();
|
||||
bool require_output = false;
|
||||
bool require_input = false;
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user