Αρχική σελίδα » πως να » Πώς η αλληλεπίδραση CPU και GPU για τη δημιουργία γραφικών υπολογιστών;

    Πώς η αλληλεπίδραση CPU και GPU για τη δημιουργία γραφικών υπολογιστών;

    Η Κεντρική Μονάδα Επεξεργασίας (CPU) και η Μονάδα επεξεργασίας γραφικών (GPU) του υπολογιστή σας αλληλεπιδρούν κάθε στιγμή που χρησιμοποιείτε τον υπολογιστή σας για να σας προσφέρουμε μια ευκρινή οπτική διασύνδεση. Διαβάστε παρακάτω για να καταλάβετε καλύτερα πώς συνεργάζονται.

    Φωτογραφία από sskennel.

    Η σημερινή συνάντηση ερωτήσεων και απαντήσεων έρχεται σε επαφή με τον εαυτό μας με το SuperUser - μια υποδιαίρεση του Stack Exchange, μια κοινοτική μονάδα δίσκου των ιστότοπων ερωτήσεων & απαντήσεων.

    Το ερώτημα

    Ο αναγνώστης του SuperUser Sathya έθεσε την ερώτηση:

    Εδώ μπορείτε να δείτε ένα στιγμιότυπο οθόνης ενός μικρού προγράμματος C ++ που ονομάζεται Triangle.exe με περιστρεφόμενο τρίγωνο βασισμένο στο OpenGL API.

    Βεβαίως ένα πολύ βασικό παράδειγμα, αλλά νομίζω ότι είναι εφαρμόσιμο σε άλλες λειτουργίες γραφικών καρτών.

    Ήμουν απλώς περίεργος και ήθελα να μάθω όλη τη διαδικασία από το διπλό κλικ στο Triangle.exe στα Windows XP μέχρι να μπορώ να δω το τρίγωνο να περιστρέφεται στην οθόνη. Τι συμβαίνει, πώς αλληλεπιδρά ο επεξεργαστής (ο οποίος χειρίζεται πρώτα το .exe) και η GPU (που τελικά εξάγει το τρίγωνο στην οθόνη)?

    Υποθέτω ότι συμμετέχει στην εμφάνιση αυτού του περιστρεφόμενου τριγώνου είναι κυρίως το ακόλουθο υλικό / λογισμικό μεταξύ άλλων:

    Σκεύη, εξαρτήματα

    • HDD
    • Μνήμη συστήματος (RAM)
    • ΕΠΕΞΕΡΓΑΣΤΗΣ
    • Μνήμη βίντεο
    • GPU
    • οθόνη LCD

    Λογισμικό

    • Λειτουργικό σύστημα
    • API DirectX / OpenGL
    • Οδηγός Nvidia

    Μπορεί κανείς να εξηγήσει τη διαδικασία, ίσως με κάποιο διάγραμμα ροής για παράδειγμα?

    Δεν πρέπει να είναι μια σύνθετη εξήγηση που να καλύπτει κάθε βήμα (υποθέστε ότι θα ξεπεράσει το πεδίο εφαρμογής), αλλά μια εξήγηση που μπορεί να ακολουθήσει ένας ενδιάμεσος τύπος πληροφορικής.

    Είμαι βέβαιος ότι πολλοί άνθρωποι που θα αποκαλούσαν ακόμη και επαγγελματίες πληροφορικής δεν θα μπορούσαν να περιγράψουν τη διαδικασία αυτή σωστά.

    Η απάντηση

    Παρόλο που πολλά μέλη της κοινότητας απάντησαν στην ερώτηση, ο Oliver Salzburg πήγε το επιπλέον μίλι και απάντησε όχι μόνο με μια λεπτομερή απάντηση, αλλά και με εξαιρετικά συνοδευτικά γραφικά.

    Εικόνα από την JasonC, διαθέσιμη ως ταπετσαρία εδώ.

    Αυτός γράφει:

    Αποφάσισα να γράψω λίγο για την πτυχή προγραμματισμού και για το πώς τα μέρη μιλούν μεταξύ τους. Ίσως να ρίξει φως σε ορισμένες περιοχές.

    Η παρουσίαση

    Τι χρειάζεται για να έχετε ακόμη και εκείνη την ενιαία εικόνα, την οποία δημοσιεύσατε στην ερώτησή σας, στην οθόνη?

    Υπάρχουν πολλοί τρόποι για να σχεδιάσετε ένα τρίγωνο στην οθόνη. Για λόγους απλότητας, ας υποθέσουμε ότι δεν χρησιμοποιήθηκαν κανένα buffer κορυφής. (ΕΝΑ ρυθμιστή κορυφώνείναι μια περιοχή μνήμης όπου αποθηκεύετε τις συντεταγμένες.) Ας υποθέσουμε ότι το πρόγραμμα απλά είπε στον αγωγό επεξεργασίας γραφικών για κάθε κορυφή (μια κορυφή είναι απλώς μια συντεταγμένη στο διάστημα) σε μια σειρά.

    Αλλά, πριν μπορέσουμε να σχεδιάσουμε οτιδήποτε, πρώτα πρέπει να τρέξουμε κάποια σκαλωσιά. Θα δούμε Γιατί αργότερα:

    // Καθαρίστε την οθόνη και το ρυθμιστικό βάθους glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT). // Επαναφορά του τρέχοντος μοντέλου Matrixview glMatrixMode (GL_MODELVIEW); glLoadIdentity (); // Σχέδιο χρησιμοποιώντας τρίγωνα glBegin (GL_TRIANGLES); // Κόκκινο glColor3f (1.0f, 0.0f, 0.0f); // κορυφή του τριγώνου (μπροστά) glVertex3f (0.0f, 1.0f, 0.0f); // Πράσινο glColor3f (0.0f, 1.0f, 0.0f); // Αριστερά του τριγώνου (μπροστά) glVertex3f (-1.0f, -1.0f, 1.0f); // Μπλε glColor3f (0.0f, 0.0f, 1.0f); // Δεξιά του τριγώνου (μπροστά) glVertex3f (1.0f, -1.0f, 1.0f); // Λήψη σχεδίου glEnd ();

    Έτσι τι έκανε αυτό?

    Όταν γράφετε ένα πρόγραμμα που θέλει να χρησιμοποιήσει την κάρτα γραφικών, συνήθως θα επιλέξετε κάποιο είδος διεπαφής στο πρόγραμμα οδήγησης. Ορισμένες γνωστές διεπαφές με τον οδηγό είναι οι εξής:

    • OpenGL
    • Direct3D
    • CUDA

    Για αυτό το παράδειγμα θα παραμείνουμε στο OpenGL. Τώρα, το δικό σου διεπαφή στον οδηγό είναι αυτό που σας δίνει όλα τα εργαλεία που χρειάζεστε για να κάνετε το πρόγραμμά σας ΜΙΛΑ ρε στην κάρτα γραφικών (ή στον οδηγό, που στη συνέχεια συνομιλίες στην κάρτα).

    Αυτή η διεπαφή είναι βέβαιο ότι θα σας δώσει ορισμένες εργαλεία. Αυτά τα εργαλεία έχουν τη μορφή ενός API το οποίο μπορείτε να καλέσετε από το πρόγραμμά σας.

    Αυτό το API είναι αυτό που βλέπουμε να χρησιμοποιείται στο παραπάνω παράδειγμα. Ας δούμε πιο προσεκτικά.

    Η σκαλωσιά

    Προτού να μπορέσετε πραγματικά να κάνετε κάποιο πραγματικό σχέδιο, θα πρέπει να εκτελέσετε ένα ρύθμισης. Πρέπει να ορίσετε το παράθυρο προβολής (την περιοχή που πραγματικά θα αναπαραχθεί), την προοπτική σας (το ΦΩΤΟΓΡΑΦΙΚΗ ΜΗΧΑΝΗ στον κόσμο σας), τι anti-aliasing θα χρησιμοποιήσετε (για την εξομάλυνση των άκρων του τριγώνου σας) ...

    Αλλά δεν θα εξετάσουμε κανένα από αυτά. Θα ρίξουμε μια ματιά στα πράγματα που θα πρέπει να κάνετε κάθε καρέ. Σαν:

    Εκκαθάριση της οθόνης

    Ο αγωγός γραφικών δεν πρόκειται να καθαρίσει την οθόνη για σας κάθε καρέ. Θα πρέπει να το πείτε. Γιατί; Αυτός είναι ο λόγος:

    Εάν δεν καθαρίσετε την οθόνη, απλά επαναλάβετε κάθε πλαίσιο. Γι 'αυτό καλούμε glClear με τοGL_COLOR_BUFFER_BIT σειρά. Το άλλο κομμάτι (GL_DEPTH_BUFFER_BIT) λέει στο OpenGL να διαγράψει το βάθοςρυθμιστής. Αυτή η προσωρινή μνήμη χρησιμοποιείται για να προσδιορίσει ποια εικονοστοιχεία είναι μπροστά (ή πίσω) άλλα εικονοστοιχεία.

    Μεταμόρφωση


    Πηγή εικόνας

    Ο μετασχηματισμός είναι το μέρος όπου παίρνουμε όλες τις συντεταγμένες εισόδου (τις κορυφές του τριγώνου μας) και εφαρμόζουμε το Matrix ModelView. Αυτή είναι η μήτρα που εξηγεί πώς μας μοντέλο (οι κορυφές) περιστρέφονται, κλιμακώνουν και μεταφράζονται (μετακινούνται).

    Στη συνέχεια, εφαρμόζουμε το Matrix προβολής μας. Αυτό μετακινεί όλες τις συντεταγμένες έτσι ώστε να αντιμετωπίζουν σωστά τη φωτογραφική μηχανή.

    Τώρα μεταμορφώνουμε για άλλη μια φορά, με το Matrix Viewport. Το κάνουμε αυτό για να το μεγεθύνουμε μοντέλο στο μέγεθος της οθόνης μας. Τώρα έχουμε μια σειρά από κορυφές που είναι έτοιμες να αποτυπωθούν!

    Θα επιστρέψουμε στο μετασχηματισμό λίγο αργότερα.

    Σχέδιο

    Για να σχεδιάσουμε ένα τρίγωνο, μπορούμε απλά να πούμε στο OpenGL να ξεκινήσει ένα νέο λίστα τριγώνων καλώντας glBegin με το GL_TRIANGLES συνεχής.
    Υπάρχουν και άλλες μορφές που μπορείτε να σχεδιάσετε. Όπως μια ταινία τριγώνου ή ένας ανεμιστήρας τριγώνου. Αυτές είναι κυρίως βελτιστοποιήσεις, καθώς απαιτούν λιγότερη επικοινωνία μεταξύ της CPU και της GPU για να αντλήσουν την ίδια ποσότητα τριγώνων.

    Μετά από αυτό, μπορούμε να παράσχουμε μια λίστα με σύνολα 3 κορυφών που θα πρέπει να συνθέτουν κάθε τρίγωνο. Κάθε τρίγωνο χρησιμοποιεί 3 συντεταγμένες (όπως είμαστε σε 3D-space). Επιπλέον, παρέχω και ένα χρώμα για κάθε κορυφή, καλώνταςglColor3f πριν κλήση glVertex3f.

    Η απόχρωση μεταξύ των 3 κορυφών (οι 3 γωνίες του τριγώνου) υπολογίζεται από το OpenGLαυτομάτως. Θα παρεμβάλλει το χρώμα σε ολόκληρη την όψη του πολυγώνου.

    ΑΛΛΗΛΕΠΙΔΡΑΣΗ

    Τώρα, όταν κάνετε κλικ στο παράθυρο. Η εφαρμογή πρέπει μόνο να καταγράψει το μήνυμα παραθύρου που σηματοδοτεί το κλικ. Στη συνέχεια, μπορείτε να εκτελέσετε οποιαδήποτε ενέργεια στο πρόγραμμα που θέλετε.

    Αυτό παίρνει ένα παρτίδα δυσκολότερη όταν αρχίσετε να αλληλεπιδράτε με τη σκηνή 3D.

    Πρώτα πρέπει να ξέρετε με σαφήνεια σε ποιο pixel ο χρήστης έκανε κλικ στο παράθυρο. Στη συνέχεια, λαμβάνοντας σας προοπτικήμπορείτε να υπολογίσετε την κατεύθυνση μιας ακτίνας από το σημείο του κλικ του ποντικιού στη σκηνή σας. Στη συνέχεια, μπορείτε να υπολογίσετε αν υπάρχει κάποιο αντικείμενο στη σκηνή σας διασταυρώνεται με την ακτίνα. Τώρα ξέρετε αν ο χρήστης έκανε κλικ σε ένα αντικείμενο.

    Λοιπόν, πώς μπορείτε να το περιστρέψετε?

    Μεταμόρφωση

    Γνωρίζω δύο τύπους μετασχηματισμών που εφαρμόζονται γενικά:

    • Μετασχηματισμός με βάση το πλέγμα
    • Μετασχηματισμός με βάση τα οστά

    Η διαφορά είναι αυτή οστά επηρεάζουν μόνο κορυφές. Οι μήτρες επηρεάζουν πάντοτε όλες τις κορυφές με τον ίδιο τρόπο. Ας δούμε ένα παράδειγμα.

    Παράδειγμα

    Νωρίτερα, φορτώσαμε μας μήτρα ταυτότητας πριν βγάλουμε το τρίγωνό μας. Ο πίνακας ταυτότητας είναι αυτός που απλά παρέχει χωρίς μετασχηματισμό καθόλου. Έτσι, ό, τι σχεδιάζω, επηρεάζεται μόνο από την προοπτική μου. Έτσι, το τρίγωνο δεν θα περιστραφεί καθόλου.

    Αν θέλω να το περιστρέψω τώρα, θα μπορούσα είτε να κάνω τα μαθηματικά μόνος μου (στο CPU) και απλά να καλέσω glVertex3f μεάλλα συντεταγμένες (που περιστρέφονται). Ή θα μπορούσα να αφήσω τη GPU να κάνει όλη τη δουλειά, καλώντας glRotatefπριν σχεδιάσετε:

    // Περιστρέψτε το τρίγωνο στον άξονα y glRotatef (ποσό, 0.0f, 1.0f, 0.0f); 

    ποσό είναι, φυσικά, απλά μια σταθερή αξία. Αν θέλεις έμψυχος, θα πρέπει να παρακολουθείτε ποσόκαι να αυξάνεται κάθε πλαίσιο.

    ¶Έτσι, περιμένετε, τι συνέβη σε όλες τις συζητήσεις μήτρας νωρίτερα?

    Σε αυτό το απλό παράδειγμα, δεν χρειάζεται να νοιάζουμε για τις μήτρες. Απλά τηλεφωνούμε glRotatef και φροντίζει όλα αυτά για μας.

    glRotate παράγει μια περιστροφή του γωνία βαθμούς γύρω από τον φορέα x y z. Η τρέχουσα μήτρα (seeglMatrixMode) πολλαπλασιάζεται με μια μήτρα περιστροφής με το προϊόν που αντικαθιστά τον τρέχοντα πίνακα, καθώς ονομάστηκε ifglMultMatrix με τον ακόλουθο πίνακα ως όρισμα:

    x 2 ⁡ 1 - c + cx ı y ⁡ 1 - c - z s x z ⁡ 1 - c + y y y ⁡ 1 - c + z sy 2 ⁡ 1 - c + cy z z 1 - c - x - 1 - c + x sz 2 ⁡ 1 - c + c 0 0 0 0 1

    Ευχαριστώ γι 'αυτό!

    συμπέρασμα

    Αυτό που γίνεται προφανές είναι ότι υπάρχει πολλή συζήτηση προς το OpenGL. Αλλά δεν λέει μας Οτιδήποτε. Πού είναι η επικοινωνία?

    Το μόνο πράγμα που μας λέει το OpenGL σε αυτό το παράδειγμα είναι όταν έχει γίνει. Κάθε πράξη θα πάρει ένα συγκεκριμένο χρονικό διάστημα. Ορισμένες λειτουργίες έχουν απίστευτα μεγάλη διάρκεια, άλλες είναι απίστευτα γρήγορες.

    Αποστολή κορυφής στη GPU θα είναι τόσο γρήγορη, δεν θα ήξερα καν πώς να το εκφράσω. Η αποστολή χιλιάδων κορυφών από την CPU στη GPU, σε κάθε καρέ, είναι πιθανότατα μηδενική.

    Εκκαθάριση της οθόνης μπορεί να διαρκέσει ένα χιλιοστό του δευτερολέπτου ή ακόμα χειρότερα (λάβετε υπόψη ότι συνήθως έχετε μόνο περίπου 16 χιλιοστά του δευτερολέπτου για να σχεδιάσετε κάθε καρέ), ανάλογα με το πόσο μεγάλο είναι το παράθυρό σας προβολής. Για να το καθαρίσετε, το OpenGL πρέπει να σχεδιάσει κάθε pixel στο χρώμα που θέλετε να καθαρίσετε, που θα μπορούσε να είναι εκατομμύρια pixels.

    Εκτός από αυτό, μπορούμε λίγο πολύ να ζητήσουμε από την OpenGL μόνο τις δυνατότητες του προσαρμογέα γραφικών (μέγιστη ανάλυση, μέγιστη αντιαναβολή, μέγιστο βάθος χρώματος, ...).

    Αλλά μπορούμε επίσης να γεμίσει μια υφή με εικονοστοιχεία που έχουν το καθένα ένα συγκεκριμένο χρώμα. Κάθε pixel διατηρεί έτσι μια τιμή και η υφή είναι ένα γιγαντιαίο "αρχείο" γεμάτο με δεδομένα. Μπορούμε να το φορτώσουμε στην κάρτα γραφικών (δημιουργώντας ένα ρυθμιστικό υφής) και στη συνέχεια να φορτώσουμε ένα shader, να πούμε ότι ο shader θα χρησιμοποιήσει την υφή μας ως είσοδο και θα εκτελέσει κάποιες εξαιρετικά βαρείς υπολογισμούς στο "αρχείο".

    Μπορούμε τότε να "καταστήσουμε" το αποτέλεσμα του υπολογισμού μας (με τη μορφή νέων χρωμάτων) σε μια νέα υφή.

    Έτσι μπορείτε να κάνετε τη GPU να λειτουργήσει για σας με άλλους τρόπους. Υποθέτω ότι η CUDA εκτελεί παρόμοια με αυτή την πτυχή, αλλά ποτέ δεν είχα την ευκαιρία να συνεργαστώ με αυτήν.

    Εμείς πραγματικά μόνο λίγο άγγιξε ολόκληρο το θέμα. Ο προγραμματισμός 3D γραφικών είναι μια κόλαση ενός θηρίου.


    Πηγή εικόνας


    Έχετε κάτι να προσθέσετε στην εξήγηση; Απενεργοποιήστε τα σχόλια. Θέλετε να διαβάσετε περισσότερες απαντήσεις από άλλους τεχνολογικούς χρήστες Stack Exchange; Δείτε το πλήρες νήμα συζήτησης εδώ.