// ============================================= // Aster: helpers.cpp // Copyright (c) 2020-2024 Anish Bhobe // ============================================= #include "helpers.h" #include "aster/core/device.h" #include "aster/core/physical_device.h" #include constexpr QueueSupportFlags REQUIRED_QUEUE_SUPPORT = QueueSupportFlags{} | QueueSupportFlagBits::eGraphics | QueueSupportFlagBits::eCompute | QueueSupportFlagBits::ePresent | QueueSupportFlagBits::eTransfer; bool IsSuitableDevice(const PhysicalDevice *physicalDevice) { const bool hasAllRequiredQueues = std::ranges::any_of(physicalDevice->m_QueueFamilies, [](const auto &queueFamilyProp) { return (queueFamilyProp.m_Support & REQUIRED_QUEUE_SUPPORT) == REQUIRED_QUEUE_SUPPORT; }); const bool isNotCpu = physicalDevice->m_DeviceProperties.deviceType != vk::PhysicalDeviceType::eCpu; const bool hasPresentMode = !physicalDevice->m_PresentModes.empty(); const bool hasSurfaceFormat = !physicalDevice->m_SurfaceFormats.empty(); return hasSurfaceFormat && hasPresentMode && isNotCpu && hasAllRequiredQueues; } PhysicalDevice FindSuitableDevice(const PhysicalDevices &physicalDevices) { for (auto &physicalDevice : physicalDevices) { if (IsSuitableDevice(&physicalDevice)) { return physicalDevice; } } ERROR("No suitable GPU available on the system.") THEN_ABORT(vk::Result::eErrorUnknown); } QueueAllocation FindAppropriateQueueAllocation(const PhysicalDevice *physicalDevice) { for (auto &queueFamilyInfo : physicalDevice->m_QueueFamilies) { if ((queueFamilyInfo.m_Support & REQUIRED_QUEUE_SUPPORT) == REQUIRED_QUEUE_SUPPORT) { return { .m_Family = queueFamilyInfo.m_Index, .m_Count = queueFamilyInfo.m_Count, }; } } ERROR("No suitable queue family on the GPU.") THEN_ABORT(vk::Result::eErrorUnknown); } eastl::vector ReadFile(cstr fileName) { FILE *filePtr = fopen(fileName, "rb"); if (!filePtr) { ERROR("Invalid read of {}", fileName) THEN_ABORT(-1); } eastl::vector outputVec; eastl::array buffer{}; usize totalRead = 0; usize readCount; do { readCount = fread(buffer.data(), sizeof(u32), buffer.size(), filePtr); const auto nextSize = totalRead + readCount; outputVec.resize(nextSize); memcpy(outputVec.data() + totalRead, buffer.data(), readCount * sizeof *buffer.data()); totalRead = nextSize; } while (readCount == buffer.size()); return outputVec; } eastl::vector ReadFileBytes(cstr fileName, bool errorOnFail) { FILE *filePtr = fopen(fileName, "rb"); if (!filePtr) { ERROR_IF(errorOnFail, "Invalid open (r) of {}. Cause: {}", fileName, errno); return {}; } eastl::vector outputVec; eastl::array buffer{}; usize totalRead = 0; usize readCount; do { readCount = fread(buffer.data(), sizeof(u8), buffer.size(), filePtr); const auto nextSize = totalRead + readCount; outputVec.resize(nextSize); memcpy(outputVec.data() + totalRead, buffer.data(), readCount * sizeof *buffer.data()); totalRead = nextSize; } while (readCount == buffer.size()); (void)fclose(filePtr); return outputVec; } bool WriteFileBytes(cstr fileName, eastl::span data) { FILE *filePtr = fopen(fileName, "wb"); if (!filePtr) { ERROR("Invalid open (w) of {}. Cause: {}", fileName, errno); return false; } const usize written = fwrite(data.data(), sizeof(u8), data.size(), filePtr); (void)fclose(filePtr); return written == data.size(); }