visit_isolated(*binary.right);
return visit_composite(*binary.left, 0x400000|r_expression_result_id, *binary.type);
}
visit_isolated(*binary.right);
return visit_composite(*binary.left, 0x400000|r_expression_result_id, *binary.type);
}
+ 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));
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;
+ }
- StorageClass storage = get_interface_storage(iface.interface, true);
+ bool push_const = has_layout_qualifier(iface.layout.get(), "push_constant");
+
+ StorageClass storage = (push_const ? STORAGE_PUSH_CONSTANT : get_interface_storage(iface.interface, true));
- auto i = find_member(iface.layout->qualifiers, string("binding"), &Layout::Qualifier::name);
- if(i!=iface.layout->qualifiers.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);
+ }
- 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);
+ }
writer.begin_function_body(next_id++);
SetForScope<FunctionDeclaration *> set_func(current_function, &func);
func.body.visit(*this);
writer.begin_function_body(next_id++);
SetForScope<FunctionDeclaration *> set_func(current_function, &func);
func.body.visit(*this);
writer.write_op(content.function_body, OP_SELECTION_MERGE, merge_block_id, 0); // Selection control (none)
writer.write_op(content.function_body, OP_BRANCH_CONDITIONAL, r_expression_result_id, true_label_id, false_label_id);
writer.write_op(content.function_body, OP_SELECTION_MERGE, merge_block_id, 0); // Selection control (none)
writer.write_op(content.function_body, OP_BRANCH_CONDITIONAL, r_expression_result_id, true_label_id, false_label_id);
writer.write_op_label(false_label_id);
cond.else_body.visit(*this);
reachable |= reachable_if_true;
writer.write_op_label(false_label_id);
cond.else_body.visit(*this);
reachable |= reachable_if_true;
- for(VariableDeclaration *v: AssignmentCollector().apply(iter))
- variable_load_ids.erase(v);
+ for(Node *n: AssignmentCollector().apply(iter))
+ if(VariableDeclaration *var = dynamic_cast<VariableDeclaration *>(n))
+ variable_load_ids.erase(var);