| 1567 | } |
| 1568 | |
| 1569 | id emit_load(const expression &exp, bool) override |
| 1570 | { |
| 1571 | if (exp.is_constant) // Constant expressions do not have a complex access chain |
| 1572 | return emit_constant(exp.type, exp.constant); |
| 1573 | |
| 1574 | size_t i = 0; |
| 1575 | spv::Id result = exp.base; |
| 1576 | type base_type = exp.type; |
| 1577 | bool is_uniform_bool = false; |
| 1578 | |
| 1579 | if (exp.is_lvalue || !exp.chain.empty()) |
| 1580 | add_location(exp.location, *_current_block_data); |
| 1581 | |
| 1582 | // If a variable is referenced, load the value first |
| 1583 | if (exp.is_lvalue && _spec_constants.find(exp.base) == _spec_constants.end()) |
| 1584 | { |
| 1585 | if (!exp.chain.empty()) |
| 1586 | base_type = exp.chain[0].from; |
| 1587 | |
| 1588 | std::pair<spv::StorageClass, spv::ImageFormat> storage = { spv::StorageClassFunction, spv::ImageFormatUnknown }; |
| 1589 | if (const auto it = _storage_lookup.find(exp.base); |
| 1590 | it != _storage_lookup.end()) |
| 1591 | storage = it->second; |
| 1592 | |
| 1593 | spirv_instruction *access_chain = nullptr; |
| 1594 | |
| 1595 | // Check if this is a uniform variable (see 'define_uniform' function above) and dereference it |
| 1596 | if (result & 0xF0000000) |
| 1597 | { |
| 1598 | const uint32_t member_index = result ^ 0xF0000000; |
| 1599 | |
| 1600 | storage.first = spv::StorageClassUniform; |
| 1601 | is_uniform_bool = base_type.is_boolean(); |
| 1602 | |
| 1603 | if (is_uniform_bool) |
| 1604 | base_type.base = type::t_uint; |
| 1605 | |
| 1606 | access_chain = &add_instruction(spv::OpAccessChain) |
| 1607 | .add(_global_ubo_variable) |
| 1608 | .add(emit_constant(member_index)); |
| 1609 | } |
| 1610 | |
| 1611 | // Any indexing expressions can be resolved during load with an 'OpAccessChain' already |
| 1612 | if (!exp.chain.empty() && ( |
| 1613 | exp.chain[0].op == expression::operation::op_member || |
| 1614 | exp.chain[0].op == expression::operation::op_dynamic_index || |
| 1615 | exp.chain[0].op == expression::operation::op_constant_index)) |
| 1616 | { |
| 1617 | // Ensure that 'access_chain' cannot get invalidated by calls to 'emit_constant' or 'convert_type' |
| 1618 | assert(_current_block_data != &_types_and_constants); |
| 1619 | |
| 1620 | // Use access chain from uniform if possible, otherwise create new one |
| 1621 | if (access_chain == nullptr) access_chain = |
| 1622 | &add_instruction(spv::OpAccessChain).add(result); // Base |
| 1623 | |
| 1624 | // Ignore first index into 1xN matrices, since they were translated to a vector type in SPIR-V |
| 1625 | if (exp.chain[0].from.rows == 1 && exp.chain[0].from.cols > 1) |
| 1626 | i = 1; |
nothing calls this directly
no test coverage detected