| 213 | return code; |
| 214 | } |
| 215 | bool assemble_code_for_entry_point(const std::string &entry_point_name, std::string &code, std::string &, std::string &) const override |
| 216 | { |
| 217 | const function *const entry_point = find_function(entry_point_name); |
| 218 | if (entry_point == nullptr) |
| 219 | return false; |
| 220 | |
| 221 | code = finalize_preamble(); |
| 222 | |
| 223 | if (entry_point->type != shader_type::pixel) |
| 224 | code += |
| 225 | // OpenGL does not allow using 'discard' in the vertex shader profile |
| 226 | "#define discard\n" |
| 227 | // 'dFdx', 'dFdx' and 'fwidth' too are only available in fragment shaders |
| 228 | "#define dFdx(x) x\n" |
| 229 | "#define dFdy(y) y\n" |
| 230 | "#define fwidth(p) p\n"; |
| 231 | |
| 232 | if (entry_point->type != shader_type::compute) |
| 233 | code += |
| 234 | // OpenGL does not allow using 'shared' in vertex/fragment shader profile |
| 235 | "#define shared\n" |
| 236 | "#define atomicAdd(a, b) a\n" |
| 237 | "#define atomicAnd(a, b) a\n" |
| 238 | "#define atomicOr(a, b) a\n" |
| 239 | "#define atomicXor(a, b) a\n" |
| 240 | "#define atomicMin(a, b) a\n" |
| 241 | "#define atomicMax(a, b) a\n" |
| 242 | "#define atomicExchange(a, b) a\n" |
| 243 | "#define atomicCompSwap(a, b, c) a\n" |
| 244 | // Barrier intrinsics are only available in compute shaders |
| 245 | "#define barrier()\n" |
| 246 | "#define memoryBarrier()\n" |
| 247 | "#define groupMemoryBarrier()\n"; |
| 248 | |
| 249 | const auto replace_binding = |
| 250 | [](std::string &code, uint32_t binding) { |
| 251 | const size_t beg = code.find("layout(binding = ") + 17; |
| 252 | const size_t end = code.find_first_of("),", beg); |
| 253 | code.replace(beg, end - beg, std::to_string(binding)); |
| 254 | }; |
| 255 | |
| 256 | // Add referenced sampler definitions |
| 257 | for (uint32_t binding = 0; binding < entry_point->referenced_samplers.size(); ++binding) |
| 258 | { |
| 259 | if (entry_point->referenced_samplers[binding] == 0) |
| 260 | continue; |
| 261 | |
| 262 | std::string block_code = _blocks.at(entry_point->referenced_samplers[binding]); |
| 263 | replace_binding(block_code, binding); |
| 264 | code += block_code; |
| 265 | } |
| 266 | |
| 267 | // Add referenced storage definitions |
| 268 | for (uint32_t binding = 0; binding < entry_point->referenced_storages.size(); ++binding) |
| 269 | { |
| 270 | if (entry_point->referenced_storages[binding] == 0) |
| 271 | continue; |
| 272 |
no test coverage detected