c ++ - Sådan kalder du glReadPixels på forskellige tråd?

Indlæg af Hanne Mølgaard Plasc

Problem



Når jeg kalder glReadPixels på en anden tråd, returnerer jeg ikke nogen data. Jeg læser et sted, der tyder på, at jeg skal oprette en ny kontekst i opkaldstråden og kopiere hukommelsen over. Hvordan gør jeg det præcist?


Dette er glReadPixels-koden, jeg bruger:


pixels = new BYTE[ 3 * width * height];
glReadPixels(0, 0, width, height, GL\_RGB, GL\_UNSIGNED\_BYTE, pixels);
image = FreeImage\_ConvertFromRawBits(pixels, width, height, 3 * width, 24, 0xFF0000, 0x00FF00, 0x0000FF, false);
FreeImage\_Save(FIF\_PNG, image, pngpath.c\_str() , 0);


Alternativt læser jeg fra denne tråd de foreslår at bruge et andet stykke kode (se slutningen), men jeg forstår ikke hvad origX, origY, srcOrigX, srcOrigY? [4]

Bedste reference


Du kan oprette delte sammenhænge, ​​og dette vil fungere som du ønskede. Se wglShareLists (navnet er valgt dårligt, det deler mere end blot lister). Eller brug WGL\_ARB\_create\_context, som direkte understøtter deling af sammenhænge (du har tagget spørgsmålet 'windows', men der findes lignende funktionalitet til ikke-WGL).


Imidlertid er det meget, meget nemmere at bruge en pixelbufferobjekt i stedet, som vil have samme neteffekt som multithreading (overførslen vil køre asynkront uden at blokere render-tråden), og det er mange gange mindre komplekst.

Andre referencer 1


Du har forskellige muligheder.


Du ringer til ReadPixel pipelined med renderingstråden. I dette tilfælde skal de returnerede data gemmes på en buffer, der kan tilskrives en tråd, der er dedikeret til at gemme billeder. Dette kan gøres nemt med en buffer kø, en mutex og en semafor: renderingstråd får data ved hjælp af ReadPixel , lås mutex, enqueue (systemminne) pixelbuffer, låse op mutexen, øg semaphoreen; Arbejdsgarnet (låst på semaforen) vil blive signaleret af renderingstråden, låse mutexen, dequeue pixelbufferen, låse op mutexen og gemme billedet.


Ellers kan du kopiere den nuværende fremføringsbuffer på en tekstur eller en pixelbufferobjekt. I dette tilfælde skal du have to forskellige tråde, der har en OpenGL kontekststrøm (via MakeCurrent ) hver, der deler deres objektrum med hinanden (som foreslået af user771921 ). Når den første renderingstråd kalder ReadPixels (eller CopyPixels ), meddeler den anden tråd om operationen (f.eks. Med en semafor); den anden renderingstråd vil kortlægge pixelbufferobjektet (eller få teksturdata).
Denne metode har den fordel, at føreren kan pipeline den første trådlæsningsoperation, men det fordobler faktisk hukommelseskopioperationerne ved at indføre en ekstra understøtningsbuffer. Desuden skylles ReadPixel -operationen, når den anden tråd kortlægger bufferen, som udføres (sandsynligvis) lige efter den anden tråd er signaleret.


Jeg vil foreslå den første mulighed, da det er meget renere og enkle. Den anden er for kompliceret, og jeg tvivler på, at du kan få fordele ved at bruge den: billedbesparende operation er meget langsommere end ReadPixel .


Selvom ReadPixel ikke er pipelined, sænker din FPS virkelig? Du må ikke optimere, før du kan profilere.


Eksemplet du har linket bruger GDI-funktioner, som ikke er OpenGL-relaterede. Jeg tror, ​​at koden ville forårsage omsmudse formularhændelse og derefter fange indholdet af vindueklientområdet. Det ser ud til meget langsommere sammenlignet med ReadPixel , selvom jeg ikke har udført nogen profilering om dette problem.

Andre referencer 2


Nå, at bruge opengl i et multi-threaded-program er en dårlig idé - specielt hvis du bruger opengl-funktioner i en tråd, der ikke har nogen kontekst skabt.


Bortset fra det er der intet galt i dit kodeeksempel.