X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Fspirv.cpp;h=07d4eb072c0989eb1745405aae0c85ea2ae59fc7;hb=145fcb8a11096f3db31e938d14196cc8ade6aa7b;hp=40e731fe63fa9fcfb384dd61baf8429e34be3382;hpb=efbce87192ce73ba577684369f759693dccec67c;p=libs%2Fgl.git diff --git a/source/glsl/spirv.cpp b/source/glsl/spirv.cpp index 40e731fe..07d4eb07 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) @@ -337,10 +338,10 @@ bool SpirVGenerator::is_scalar_type(Id type_id, BasicTypeDeclaration::Kind kind) return (i!=standard_type_ids.end() && i->second==type_id); } -SpirVGenerator::Id SpirVGenerator::get_array_type_id(TypeDeclaration &base_type, Id size_id) +SpirVGenerator::Id SpirVGenerator::get_array_type_id(TypeDeclaration &base_type, Id size_id, bool extended_align) { Id base_type_id = get_id(base_type); - Id &array_type_id = array_type_ids[TypeKey(base_type_id, size_id)]; + Id &array_type_id = array_type_ids[TypeKey(base_type_id, extended_align*0x400000 | size_id)]; if(!array_type_id) { array_type_id = next_id++; @@ -350,6 +351,8 @@ SpirVGenerator::Id SpirVGenerator::get_array_type_id(TypeDeclaration &base_type, writer.write_op(content.globals, OP_TYPE_RUNTIME_ARRAY, array_type_id, base_type_id); unsigned stride = MemoryRequirementsCalculator().apply(base_type).stride; + if(extended_align) + stride = (stride+15)&~15U; writer.write_op_decorate(array_type_id, DECO_ARRAY_STRIDE, stride); } @@ -382,7 +385,7 @@ SpirVGenerator::Id SpirVGenerator::get_variable_type_id(const VariableDeclaratio } else size_id = get_constant_id(get_standard_type_id(BasicTypeDeclaration::INT, 1), 1); - return get_array_type_id(*basic->base_type, size_id); + return get_array_type_id(*basic->base_type, size_id, true); } return get_id(*var.type_declaration); @@ -1591,6 +1594,12 @@ void SpirVGenerator::visit(VariableDeclaration &var) 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); @@ -1598,12 +1607,11 @@ void SpirVGenerator::visit(VariableDeclaration &var) 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 { @@ -1677,7 +1685,7 @@ void SpirVGenerator::visit(InterfaceBlock &iface) StorageClass storage = (push_const ? STORAGE_PUSH_CONSTANT : get_interface_storage(iface.interface, true)); Id type_id; if(iface.array) - type_id = get_array_type_id(*iface.struct_declaration, 0); + type_id = get_array_type_id(*iface.struct_declaration, 0, true); else type_id = get_id(*iface.struct_declaration); Id ptr_type_id = get_pointer_type_id(type_id, storage); @@ -1740,7 +1748,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);