| 36 | static thread_local std::vector<std::vector<uint8_t>> s_data_to_delete; |
| 37 | |
| 38 | static bool load_shader_code(device_api device_type, shader_desc &desc, std::vector<std::vector<uint8_t>> &data_to_delete) |
| 39 | { |
| 40 | if (desc.code_size == 0) |
| 41 | return false; |
| 42 | |
| 43 | uint32_t shader_hash = compute_crc32(static_cast<const uint8_t *>(desc.code), desc.code_size); |
| 44 | |
| 45 | const wchar_t *extension = L".cso"; |
| 46 | if (device_type == device_api::vulkan || (device_type == device_api::opengl && desc.code_size > sizeof(uint32_t) && *static_cast<const uint32_t *>(desc.code) == SPIRV_MAGIC)) |
| 47 | extension = L".spv"; // Vulkan uses SPIR-V (and sometimes OpenGL does too) |
| 48 | else if (device_type == device_api::opengl) |
| 49 | extension = desc.code_size > 5 && std::strncmp(static_cast<const char *>(desc.code), "!!ARB", 5) == 0 ? L".txt" : L".glsl"; // OpenGL otherwise uses plain text ARB assembly language or GLSL |
| 50 | |
| 51 | const std::filesystem::path file_path = make_shader_file_path(shader_hash, extension); |
| 52 | |
| 53 | // Check if a replacement file for this shader hash exists and if so, overwrite the shader code with its contents |
| 54 | if (!std::filesystem::exists(file_path)) |
| 55 | return false; |
| 56 | |
| 57 | std::ifstream file(file_path, std::ios::binary); |
| 58 | file.seekg(0, std::ios::end); |
| 59 | std::vector<uint8_t> shader_code(static_cast<size_t>(file.tellg())); |
| 60 | file.seekg(0, std::ios::beg).read(reinterpret_cast<char *>(shader_code.data()), shader_code.size()); |
| 61 | file.close(); |
| 62 | |
| 63 | // Keep the shader code memory alive after returning from this 'create_pipeline' event callback |
| 64 | // It may only be freed after the 'init_pipeline' event was called for this pipeline |
| 65 | data_to_delete.push_back(std::move(shader_code)); |
| 66 | |
| 67 | desc.code = data_to_delete.back().data(); |
| 68 | desc.code_size = data_to_delete.back().size(); |
| 69 | return true; |
| 70 | } |
| 71 | |
| 72 | static bool on_create_pipeline(device *device, pipeline_layout, uint32_t subobject_count, const pipeline_subobject *subobjects) |
| 73 | { |
no test coverage detected