X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Fspirv.cpp;h=7f99ebb3d9ecc61b737739542feed5a72994633f;hb=5871764de7aa23d2c40cac03ad9d07088fb57e06;hp=c9062efa12ae7aee7dfb54ca6638d64ca57b3da8;hpb=25629675e83449d986ef8896e830db562a8ae64e;p=libs%2Fgl.git diff --git a/source/glsl/spirv.cpp b/source/glsl/spirv.cpp index c9062efa..7f99ebb3 100644 --- a/source/glsl/spirv.cpp +++ b/source/glsl/spirv.cpp @@ -135,8 +135,9 @@ SpirVGenerator::SpirVGenerator(): writer(content) { } -void SpirVGenerator::apply(Module &module) +void SpirVGenerator::apply(Module &module, const Features &f) { + features = f; use_capability(CAP_SHADER); for(Stage &s: module.stages) @@ -1582,16 +1583,6 @@ void SpirVGenerator::visit(StructDeclaration &strct) void SpirVGenerator::visit(VariableDeclaration &var) { - const vector *layout_ql = (var.layout ? &var.layout->qualifiers : 0); - - int spec_id = -1; - if(layout_ql) - { - auto i = find_member(*layout_ql, string("constant_id"), &Layout::Qualifier::name); - if(i!=layout_ql->end()) - spec_id = i->value; - } - Id type_id = get_variable_type_id(var); Id var_id; @@ -1600,18 +1591,25 @@ void SpirVGenerator::visit(VariableDeclaration &var) if(!var.init_expression) throw internal_error("const variable without initializer"); + int spec_id = get_layout_value(var.layout.get(), "constant_id"); + Id *spec_var_id = (spec_id>=0 ? &declared_spec_ids[spec_id] : 0); + if(spec_id>=0 && *spec_var_id) + { + insert_unique(declared_ids, &var, Declaration(*spec_var_id, type_id)); + return; + } + SetFlag set_const(constant_expression); SetFlag set_spec(spec_constant, spec_id>=0); r_expression_result_id = 0; var.init_expression->visit(*this); var_id = r_expression_result_id; insert_unique(declared_ids, &var, Declaration(var_id, type_id)); - writer.write_op_decorate(var_id, DECO_SPEC_ID, spec_id); - - /* It's unclear what should be done if a specialization constant is - initialized with anything other than a literal. GLSL doesn't seem to - prohibit that but SPIR-V says OpSpecConstantOp can't be updated via - specialization. */ + if(spec_id>=0) + { + writer.write_op_decorate(var_id, DECO_SPEC_ID, spec_id); + *spec_var_id = var_id; + } } else { @@ -1650,9 +1648,9 @@ void SpirVGenerator::visit(VariableDeclaration &var) writer.write(init_id); writer.end_op(OP_VARIABLE); - if(layout_ql) + if(var.layout) { - for(const Layout::Qualifier &q: *layout_ql) + for(const Layout::Qualifier &q: var.layout->qualifiers) { if(q.name=="location") writer.write_op_decorate(var_id, DECO_LOCATION, q.value); @@ -1680,14 +1678,7 @@ void SpirVGenerator::visit(VariableDeclaration &var) void SpirVGenerator::visit(InterfaceBlock &iface) { - const vector *layout_ql = (iface.layout ? &iface.layout->qualifiers : 0); - - bool push_const = false; - if(layout_ql) - { - auto i = find_member(*layout_ql, string("push_constant"), &Layout::Qualifier::name); - push_const = (i!=layout_ql->end()); - } + bool push_const = has_layout_qualifier(iface.layout.get(), "push_constant"); StorageClass storage = (push_const ? STORAGE_PUSH_CONSTANT : get_interface_storage(iface.interface, true)); Id type_id; @@ -1715,11 +1706,15 @@ void SpirVGenerator::visit(InterfaceBlock &iface) writer.write_op(content.globals, OP_VARIABLE, ptr_type_id, block_id, storage); - if(layout_ql) + if(iface.layout) { - auto i = find_member(*layout_ql, string("binding"), &Layout::Qualifier::name); - if(i!=layout_ql->end()) - writer.write_op_decorate(block_id, DECO_BINDING, i->value); + for(const Layout::Qualifier &q: iface.layout->qualifiers) + { + if(q.name=="set") + writer.write_op_decorate(block_id, DECO_DESCRIPTOR_SET, q.value); + else if(q.name=="binding") + writer.write_op_decorate(block_id, DECO_BINDING, q.value); + } } } @@ -1751,7 +1746,10 @@ void SpirVGenerator::visit_entry_point(FunctionDeclaration &func, Id func_id) writer.end_op(OP_ENTRY_POINT); if(stage->type==Stage::FRAGMENT) - writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_ORIGIN_LOWER_LEFT); + { + SpirVExecutionMode origin = (features.target_api==VULKAN ? EXEC_ORIGIN_UPPER_LEFT : EXEC_ORIGIN_LOWER_LEFT); + writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, origin); + } else if(stage->type==Stage::GEOMETRY) use_capability(CAP_GEOMETRY);