|
@@ -129,6 +129,12 @@ public:
|
|
|
if (activeJobs.find(request.id) != activeJobs.end()) {
|
|
if (activeJobs.find(request.id) != activeJobs.end()) {
|
|
|
activeJobs[request.id].status = GenerationStatus::PROCESSING;
|
|
activeJobs[request.id].status = GenerationStatus::PROCESSING;
|
|
|
activeJobs[request.id].startTime = startTime;
|
|
activeJobs[request.id].startTime = startTime;
|
|
|
|
|
+ activeJobs[request.id].progress = 0.0f;
|
|
|
|
|
+ activeJobs[request.id].currentStep = 0;
|
|
|
|
|
+ activeJobs[request.id].totalSteps = 0;
|
|
|
|
|
+ activeJobs[request.id].timeElapsed = 0;
|
|
|
|
|
+ activeJobs[request.id].timeRemaining = 0;
|
|
|
|
|
+ activeJobs[request.id].speed = 0.0f;
|
|
|
saveJobToFile(activeJobs[request.id]);
|
|
saveJobToFile(activeJobs[request.id]);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -139,8 +145,8 @@ public:
|
|
|
<< " (prompt: " << request.prompt.substr(0, 50)
|
|
<< " (prompt: " << request.prompt.substr(0, 50)
|
|
|
<< (request.prompt.length() > 50 ? "..." : "") << ")" << std::endl;
|
|
<< (request.prompt.length() > 50 ? "..." : "") << ")" << std::endl;
|
|
|
|
|
|
|
|
- // Real generation logic using stable-diffusion.cpp
|
|
|
|
|
- GenerationResult result = performActualGeneration(request);
|
|
|
|
|
|
|
+ // Real generation logic using stable-diffusion.cpp with progress tracking
|
|
|
|
|
+ GenerationResult result = performActualGeneration(request, request.id);
|
|
|
|
|
|
|
|
auto endTime = std::chrono::steady_clock::now();
|
|
auto endTime = std::chrono::steady_clock::now();
|
|
|
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime);
|
|
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime);
|
|
@@ -152,6 +158,14 @@ public:
|
|
|
if (activeJobs.find(request.id) != activeJobs.end()) {
|
|
if (activeJobs.find(request.id) != activeJobs.end()) {
|
|
|
activeJobs[request.id].status = result.success ? GenerationStatus::COMPLETED : GenerationStatus::FAILED;
|
|
activeJobs[request.id].status = result.success ? GenerationStatus::COMPLETED : GenerationStatus::FAILED;
|
|
|
activeJobs[request.id].endTime = endTime;
|
|
activeJobs[request.id].endTime = endTime;
|
|
|
|
|
+
|
|
|
|
|
+ // Set final progress to 100% if successful
|
|
|
|
|
+ if (result.success) {
|
|
|
|
|
+ activeJobs[request.id].progress = 1.0f;
|
|
|
|
|
+ if (activeJobs[request.id].totalSteps > 0) {
|
|
|
|
|
+ activeJobs[request.id].currentStep = activeJobs[request.id].totalSteps;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// Store output files and error message
|
|
// Store output files and error message
|
|
|
activeJobs[request.id].outputFiles = result.imagePaths;
|
|
activeJobs[request.id].outputFiles = result.imagePaths;
|
|
@@ -181,7 +195,32 @@ public:
|
|
|
std::cout << std::endl;
|
|
std::cout << std::endl;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- GenerationResult performActualGeneration(const GenerationRequest& request) {
|
|
|
|
|
|
|
+ // Progress callback that updates the job info
|
|
|
|
|
+ void updateJobProgress(const std::string& jobId, int step, int totalSteps, float progress, uint64_t timeElapsed) {
|
|
|
|
|
+ std::lock_guard<std::mutex> lock(jobsMutex);
|
|
|
|
|
+ auto it = activeJobs.find(jobId);
|
|
|
|
|
+ if (it != activeJobs.end()) {
|
|
|
|
|
+ it->second.progress = progress;
|
|
|
|
|
+ it->second.currentStep = step;
|
|
|
|
|
+ it->second.totalSteps = totalSteps;
|
|
|
|
|
+ it->second.timeElapsed = static_cast<int64_t>(timeElapsed);
|
|
|
|
|
+
|
|
|
|
|
+ // Calculate time remaining and speed
|
|
|
|
|
+ if (step > 0 && timeElapsed > 0) {
|
|
|
|
|
+ double avgStepTime = static_cast<double>(timeElapsed) / step;
|
|
|
|
|
+ int remainingSteps = totalSteps - step;
|
|
|
|
|
+ it->second.timeRemaining = static_cast<int64_t>(avgStepTime * remainingSteps);
|
|
|
|
|
+ it->second.speed = 1000.0 / avgStepTime; // steps per second
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Save progress to file periodically (every 10 steps or on significant progress changes)
|
|
|
|
|
+ if (step % 10 == 0 || progress >= 0.99f) {
|
|
|
|
|
+ saveJobToFile(it->second);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ GenerationResult performActualGeneration(const GenerationRequest& request, const std::string& jobId) {
|
|
|
GenerationResult result;
|
|
GenerationResult result;
|
|
|
result.requestId = request.id;
|
|
result.requestId = request.id;
|
|
|
result.success = false;
|
|
result.success = false;
|
|
@@ -252,13 +291,19 @@ public:
|
|
|
}
|
|
}
|
|
|
result.actualSeed = params.seed;
|
|
result.actualSeed = params.seed;
|
|
|
|
|
|
|
|
- // Generate images based on request type
|
|
|
|
|
|
|
+ // Generate images based on request type with progress tracking
|
|
|
try {
|
|
try {
|
|
|
std::vector<StableDiffusionWrapper::GeneratedImage> generatedImages;
|
|
std::vector<StableDiffusionWrapper::GeneratedImage> generatedImages;
|
|
|
|
|
|
|
|
|
|
+ // Create progress callback that updates job info
|
|
|
|
|
+ auto progressCallback = [this, jobId](int step, int totalSteps, float progress, uint64_t timeElapsed) -> bool {
|
|
|
|
|
+ updateJobProgress(jobId, step, totalSteps, progress, timeElapsed);
|
|
|
|
|
+ return true; // Continue generation
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
switch (request.requestType) {
|
|
switch (request.requestType) {
|
|
|
case GenerationRequest::RequestType::TEXT2IMG:
|
|
case GenerationRequest::RequestType::TEXT2IMG:
|
|
|
- generatedImages = modelWrapper->generateImage(params);
|
|
|
|
|
|
|
+ generatedImages = modelWrapper->generateImage(params, progressCallback);
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
case GenerationRequest::RequestType::IMG2IMG:
|
|
case GenerationRequest::RequestType::IMG2IMG:
|
|
@@ -270,7 +315,8 @@ public:
|
|
|
params,
|
|
params,
|
|
|
request.initImageData,
|
|
request.initImageData,
|
|
|
request.initImageWidth,
|
|
request.initImageWidth,
|
|
|
- request.initImageHeight
|
|
|
|
|
|
|
+ request.initImageHeight,
|
|
|
|
|
+ progressCallback
|
|
|
);
|
|
);
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
@@ -283,7 +329,8 @@ public:
|
|
|
params,
|
|
params,
|
|
|
request.controlImageData,
|
|
request.controlImageData,
|
|
|
request.controlImageWidth,
|
|
request.controlImageWidth,
|
|
|
- request.controlImageHeight
|
|
|
|
|
|
|
+ request.controlImageHeight,
|
|
|
|
|
+ progressCallback
|
|
|
);
|
|
);
|
|
|
break;
|
|
break;
|
|
|
|
|
|