#include "graphics/graphics.h" #include "core/gpu.h" #include "util.h" #include static struct { bool initialized; gpu_device device; gpu_features features; gpu_limits limits; } state; // Helpers static void onMessage(void* context, const char* message, bool severe); // Entry bool lovrGraphicsInit(bool debug) { if (state.initialized) return false; gpu_config config = { .debug = debug, .callback = onMessage, .device = &state.device, .features = &state.features, .limits = &state.limits }; if (!gpu_init(&config)) { lovrThrow("Failed to initialize GPU"); } state.initialized = true; return true; } void lovrGraphicsDestroy() { if (!state.initialized) return; gpu_destroy(); memset(&state, 0, sizeof(state)); } void lovrGraphicsGetDevice(GraphicsDevice* device) { device->discrete = state.device.discrete; device->serial = state.device.serial; device->vendor = state.device.vendor; device->version = state.device.version; device->name = state.device.name; device->renderer = state.device.renderer; device->subgroupSize = state.device.subgroupSize; } void lovrGraphicsGetFeatures(GraphicsFeatures* features) { features->bptc = state.features.bptc; features->astc = state.features.astc; features->wireframe = state.features.wireframe; features->depthClamp = state.features.depthClamp; features->clipDistance = state.features.clipDistance; features->cullDistance = state.features.cullDistance; features->indirectDrawFirstInstance = state.features.indirectDrawFirstInstance; features->dynamicIndexing = state.features.dynamicIndexing; features->float64 = state.features.float64; features->int64 = state.features.int64; features->int16 = state.features.int16; } void lovrGraphicsGetLimits(GraphicsLimits* limits) { limits->textureSize2D = state.limits.textureSize2D; limits->textureSize3D = state.limits.textureSize3D; limits->textureSizeCube = state.limits.textureSizeCube; limits->textureLayers = state.limits.textureLayers; limits->renderSize[0] = state.limits.renderSize[0]; limits->renderSize[1] = state.limits.renderSize[1]; limits->renderSize[2] = state.limits.renderSize[2]; limits->uniformBufferRange = state.limits.uniformBufferRange; limits->storageBufferRange = state.limits.storageBufferRange; limits->uniformBufferAlign = state.limits.uniformBufferAlign; limits->storageBufferAlign = state.limits.storageBufferAlign; limits->vertexAttributes = state.limits.vertexAttributes; limits->vertexBufferStride = state.limits.vertexBufferStride; limits->vertexShaderOutputs = state.limits.vertexShaderOutputs; memcpy(limits->computeDispatchCount, state.limits.computeDispatchCount, 3 * sizeof(uint32_t)); memcpy(limits->computeWorkgroupSize, state.limits.computeWorkgroupSize, 3 * sizeof(uint32_t)); limits->computeWorkgroupVolume = state.limits.computeWorkgroupVolume; limits->computeSharedMemory = state.limits.computeSharedMemory; limits->shaderConstantSize = state.limits.pushConstantSize; limits->indirectDrawCount = state.limits.indirectDrawCount; limits->instances = state.limits.instances; limits->anisotropy = state.limits.anisotropy; limits->pointSize = state.limits.pointSize; } // Helpers static void onMessage(void* context, const char* message, bool severe) { if (severe) { lovrLog(LOG_ERROR, "GPU", message); } else { lovrLog(LOG_DEBUG, "GPU", message); } }