VkBool32 VKTS_APIENTRY engineAddUpdateThread(const IUpdateThreadSP& updateThread) { if (g_engineState != VKTS_ENGINE_INIT_STATE) { logPrint(VKTS_LOG_ERROR, "Engine: Adding update thread failed! Not in initialize state."); return VK_FALSE; } if (!updateThread.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Adding update thread failed! No update thread."); return VK_FALSE; } if (engineGetNumberUpdateThreads() >= VKTS_MAX_UPDATE_THREADS) { logPrint(VKTS_LOG_ERROR, "Engine: Adding update thread failed! Too many update threads."); return VK_FALSE; } g_allUpdateThreads.append(updateThread); return VK_TRUE; }
VkBool32 set(const K& key, const V& value) { for (size_t i = 0; i < allKeys.size(); i++) { if (key == allKeys[i]) { allValues[i] = value; return VK_TRUE; } else if (key < allKeys[i]) { allKeys.insert(i, key); allValues.insert(i, value); return VK_TRUE; } } allKeys.append(key); allValues.append(value); return VK_TRUE; }
VkBool32 VKTS_APIENTRY engineRun() { if (g_engineState != VKTS_ENGINE_INIT_STATE) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Not in initialize state."); return VK_FALSE; } if (engineGetNumberUpdateThreads() < VKTS_MIN_UPDATE_THREADS || engineGetNumberUpdateThreads() > VKTS_MAX_UPDATE_THREADS) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Number of update threads not correct."); return VK_FALSE; } // // Main thread gets all displays and windows attached. // const auto& displayList = _visualGetActiveDisplays(); for (size_t i = 0; i < displayList.size(); i++) { engineAttachDisplayToUpdateThread(displayList[i], g_allUpdateThreads[g_allUpdateThreads.size() - 1]); } const auto& windowList = _visualGetActiveWindows(); for (size_t i = 0; i < windowList.size(); i++) { engineAttachWindowToUpdateThread(windowList[i], g_allUpdateThreads[g_allUpdateThreads.size() - 1]); } // g_engineState = VKTS_ENGINE_UPDATE_STATE; logPrint(VKTS_LOG_INFO, "Engine: Started."); // Task queue creation. TaskQueueSP sendTaskQueue; TaskQueueSP executedTaskQueue; if (g_taskExecutorCount > 0) { sendTaskQueue = TaskQueueSP(new TaskQueue); if (!sendTaskQueue.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create task queue."); return VK_FALSE; } executedTaskQueue = TaskQueueSP(new TaskQueue); if (!executedTaskQueue.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create task queue."); return VK_FALSE; } } // Message dispatcher creation. MessageDispatcherSP messageDispatcher = MessageDispatcherSP(new MessageDispatcher()); if (!messageDispatcher.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create message dispatcher."); return VK_FALSE; } // Object, needed for synchronizing the executors. ExecutorSync executorSync; // // Task executor creation and launching, // SmartPointerVector<TaskExecutorSP> realTaskExecutors; SmartPointerVector<ThreadSP> realTaskThreads; for (uint32_t i = 0; i < g_taskExecutorCount; i++) { auto currentTaskExecutor = TaskExecutorSP(new TaskExecutor(i, executorSync, sendTaskQueue, executedTaskQueue)); if (!currentTaskExecutor.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create current task executor."); return VK_FALSE; } auto currentRealThread = ThreadSP(new std::thread(&TaskExecutor::run, currentTaskExecutor)); if (!currentRealThread.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create current real thread."); return VK_FALSE; } // realTaskExecutors.append(currentTaskExecutor); realTaskThreads.append(currentRealThread); logPrint(VKTS_LOG_INFO, "Engine: Task %d started.", currentTaskExecutor->getIndex()); } // // Update Thread creation and launching. // UpdateThreadExecutorSP mainUpdateThreadExecutor; SmartPointerVector<UpdateThreadExecutorSP> realUpdateThreadExecutors; SmartPointerVector<ThreadSP> realUpdateThreads; int32_t index = 0; for (size_t updateThreadIndex = 0; updateThreadIndex < g_allUpdateThreads.size(); updateThreadIndex++) { const auto& currentUpdateThread = g_allUpdateThreads[updateThreadIndex]; // const auto currentMessageDispatcher = (index == engineGetNumberUpdateThreads() - 1) ? messageDispatcher : MessageDispatcherSP(); // auto currentUpdateThreadContext = UpdateThreadContextSP(new UpdateThreadContext((int32_t) updateThreadIndex, (int32_t) g_allUpdateThreads.size(), g_tickTime, sendTaskQueue, executedTaskQueue)); if (!currentUpdateThreadContext.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create update thread context."); return VK_FALSE; } // for (auto currentDisplayWalker = g_allAttachedDisplays.lower_bound(currentUpdateThread); currentDisplayWalker != g_allAttachedDisplays.upper_bound(currentUpdateThread); currentDisplayWalker++) { currentUpdateThreadContext->attachDisplay(currentDisplayWalker->second); } // for (auto currentWindowWalker = g_allAttachedWindows.lower_bound(currentUpdateThread); currentWindowWalker != g_allAttachedWindows.upper_bound(currentUpdateThread); currentWindowWalker++) { currentUpdateThreadContext->attachWindow(currentWindowWalker->second); } // if (index == engineGetNumberUpdateThreads() - 1) { // Last thread is the main thread. mainUpdateThreadExecutor = UpdateThreadExecutorSP(new UpdateThreadExecutor(index, executorSync, currentUpdateThread, currentUpdateThreadContext, currentMessageDispatcher)); if (!mainUpdateThreadExecutor.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create main update thread executor."); return VK_FALSE; } } else { // Receive queue is the threads send queue. auto currentUpdateThreadExecutor = UpdateThreadExecutorSP(new UpdateThreadExecutor(index, executorSync, currentUpdateThread, currentUpdateThreadContext, currentMessageDispatcher)); if (!currentUpdateThreadExecutor.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create current update thread executor."); return VK_FALSE; } realUpdateThreadExecutors.append(currentUpdateThreadExecutor); logPrint(VKTS_LOG_INFO, "Engine: Thread %d started.", currentUpdateThreadExecutor->getIndex()); auto currentRealThread = ThreadSP(new std::thread(&UpdateThreadExecutor::run, currentUpdateThreadExecutor)); if (!currentRealThread.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create current real thread."); return VK_FALSE; } realUpdateThreads.append(currentRealThread); } index++; } // Run last thread and loop. logPrint(VKTS_LOG_INFO, "Engine: Thread %d started.", mainUpdateThreadExecutor->getIndex()); mainUpdateThreadExecutor->run(); // // Stopping everything. // logPrint(VKTS_LOG_INFO, "Engine: Thread %d stopped.", mainUpdateThreadExecutor->getIndex()); // Wait for all threads to finish in the reverse order they were created. for (auto reverseIndex = static_cast<int32_t>(realUpdateThreads.size()) - 1; reverseIndex >= 0; reverseIndex--) { const auto& currentRealThread = realUpdateThreads[reverseIndex]; currentRealThread->join(); logPrint(VKTS_LOG_INFO, "Engine: Thread %d stopped.", reverseIndex); } realUpdateThreadExecutors.clear(); realUpdateThreads.clear(); // if (sendTaskQueue.get()) { // Empty the queue. // As no update thread can feed the queue anymore, it is save to call reset. sendTaskQueue->reset(); // ITaskSP stopTask; logPrint(VKTS_LOG_SEVERE, "Engine: Disabling task queue."); for (uint32_t i = 0; i < g_taskExecutorCount; i++) { // Send an empty task to the queue, to exit the thread. sendTaskQueue->addTask(stopTask); } } // Wait for all tasks to finish in the reverse order they were created. for (auto reverseIndex = static_cast<int32_t>(realTaskThreads.size()) - 1; reverseIndex >= 0; reverseIndex--) { const auto& currentRealThread = realTaskThreads[reverseIndex]; currentRealThread->join(); logPrint(VKTS_LOG_INFO, "Engine: Task %d stopped.", reverseIndex); } realTaskExecutors.clear(); realTaskThreads.clear(); // g_engineState = VKTS_ENGINE_INIT_STATE; logPrint(VKTS_LOG_INFO, "Engine: Stopped."); return VK_TRUE; }
SmartPointerVector<IImageDataSP> VKTS_APIENTRY imageDataMipmap(const IImageDataSP& sourceImage, VkBool32 addSourceAsCopy, const std::string& name) { if (name.size() == 0 || !sourceImage.get()) { return SmartPointerVector<IImageDataSP>(); } std::string sourceImageFilename = name; auto dotIndex = sourceImageFilename.rfind("."); if (dotIndex == sourceImageFilename.npos) { return SmartPointerVector<IImageDataSP>(); } auto sourceImageName = sourceImageFilename.substr(0, dotIndex); auto sourceImageExtension = sourceImageFilename.substr(dotIndex); IImageDataSP currentSourceImage = sourceImage; int32_t width = currentSourceImage->getWidth(); int32_t height = currentSourceImage->getHeight(); int32_t depth = currentSourceImage->getDepth(); IImageDataSP currentTargetImage; std::string targetImageFilename; int32_t level = 0; SmartPointerVector<IImageDataSP> result; if (addSourceAsCopy) { targetImageFilename = sourceImageName + "_L" + std::to_string(level++) + sourceImageExtension; currentTargetImage = imageDataCopy(sourceImage, targetImageFilename); if (!currentTargetImage.get()) { return SmartPointerVector<IImageDataSP>(); } result.append(currentTargetImage); } else { result.append(sourceImage); level++; } while (width > 1 || height > 1 || depth > 1) { width = glm::max(width / 2, 1); height = glm::max(height / 2, 1); depth = glm::max(depth / 2, 1); targetImageFilename = sourceImageName + "_L" + std::to_string(level++) + sourceImageExtension; currentTargetImage = imageDataCreate(targetImageFilename, width, height, depth, 0.0f, 0.0f, 0.0f, 0.0f, sourceImage->getImageType(), sourceImage->getFormat()); if (!currentTargetImage.get()) { return SmartPointerVector<IImageDataSP>(); } for (int32_t z = 0; z < depth; z++) { for (int32_t y = 0; y < height; y++) { for (int32_t x = 0; x < width; x++) { glm::vec4 rgba = glm::vec4(0.0f, 0.0f, 0.0f, 0.0f); float sampleCount = 0.0f; for (int32_t iz = z * 2; iz < z * 2 + 1; iz++) { for (int32_t iy = y * 2; iy < y * 2 + 1; iy++) { for (int32_t ix = x * 2; ix < x * 2 + 1; ix++) { rgba += currentSourceImage->getTexel(ix, iy, iz); sampleCount += 1.0f; } } } if (sampleCount > 0.0f) { rgba /= sampleCount; currentTargetImage->setTexel(rgba, x, y, z); } } } } result.append(currentTargetImage); // currentSourceImage = currentTargetImage; width = currentSourceImage->getWidth(); height = currentSourceImage->getHeight(); depth = currentSourceImage->getDepth(); } return result; }