gpu cpu交互
Your computer’s Central Processing Unit (CPU) and Graphics Processing Unit (GPU) interact every moment you’re using your computer to deliver you a crisp and responsive visual interface. Read on to better understand how they work together.
每次使用计算机时,计算机的中央处理单元(CPU)和图形处理单元(GPU)都会交互,从而为您提供清晰响应的可视界面。 请继续阅读以更好地了解他们如何一起工作。
Photo bysskennel.
通过照片sskennel。
Today’s Question & Answer session comes to us courtesy of SuperUser—a subdivision of Stack Exchange, a community-drive grouping of Q&A web sites.
今天的问答环节由SuperUser提供,它是Stack Exchange的一个分支,它是Q&A网站的社区推动组织。
问题 (The Question)
SuperUser reader Sathya posed the question:
超级用户读者Sathya提出了一个问题:
Here you can see a screenshot of a small C++ program called Triangle.exe with a rotating triangle based on the OpenGL API.
在这里,您可以看到一个名为Triangle.exe的小型C ++程序的屏幕截图,该程序带有一个基于OpenGL API的旋转三角形。
Admittedly a very basic example but I think it’s applicable to other graphic cards operations.
诚然,这是一个非常基本的示例,但我认为它适用于其他图形卡操作。
I was just curious and wanted to know the whole process from double clicking on Triangle.exe under Windows XP until I can see the triangle rotating on the monitor. What happens, how do CPU (which first handles the .exe) and GPU (which finally outputs the triangle on the screen) interact?
我只是好奇,想知道从双击Windows XP下的Triangle.exe直到看到三角形在监视器上旋转的整个过程。 发生什么情况,CPU(首先处理.exe)和GPU(最终在屏幕上输出三角形)如何交互?
I guess involved in displaying this rotating triangle is primarily the following hardware/software among others:
我猜想显示此旋转三角形所涉及的主要是以下硬件/软件:
Hardware
硬件
HDD硬碟 System Memory (RAM)系统内存(RAM) CPU中央处理器 Video memory显存 GPU显卡 LCD display液晶显示器
Software
软件
Operating System操作系统 DirectX/OpenGL APIDirectX / OpenGL API Nvidia DriverNvidia驱动程序
Can anyone explain the process, maybe with some sort of flow chart for illustration?
任何人都可以用某种流程图进行说明来解释该过程吗?
It should not be a complex explanation that covers every single step (guess that would go beyond the scope), but an explanation an intermediate IT guy can follow.
它不应该是涵盖每个步骤的复杂解释(可能超出范围的猜测),而应该是中级IT人员可以遵循的解释。
I’m pretty sure a lot of people that would even call themselves IT professionals could not describe this process correctly.
我敢肯定,很多甚至会自称为IT专业人员的人都无法正确描述此过程。
答案 (The Answer)
Although multiple community members answered the question, Oliver Salzburg went the extra mile and answered it not only with a detailed response but excellent accompanying graphics.
尽管有多个社区成员回答了该问题,但奥利弗·萨尔茨堡付出了更多努力,不仅给出了详尽的答复,而且还提供了精美的随附图片。
Image by JasonC, available as wallpaper here.
JasonC的图片, 可在此处作为壁纸 。
He writes:
他写:
I decided to write a bit about the programming aspect and how components talk to each other. Maybe it’ll shed some light on certain areas.
我决定写一些关于编程方面以及组件之间如何通信的文章。 也许它将为某些领域提供一些启示。
简报 (The Presentation)
What does it take to even have that single image, that you posted in your question, drawn on the screen?
要在屏幕上绘制您在问题中张贴的单个图像,该怎么办?
There are many ways to draw a triangle on the screen. For simplicity, let’s assume no vertex buffers were used. (Avertex bufferis an area of memory where you store coordinates.) Let’s assume the program simply told the graphics processing pipeline about every single vertex (a vertex is just a coordinate in space) in a row.
有多种方法可以在屏幕上绘制三角形。 为简单起见,我们假设不使用顶点缓冲区。 (顶点缓冲区是存储坐标的内存区域。)让我们假设程序只是简单地告诉图形处理管道连续的每个顶点(顶点只是空间中的坐标)。
But, before we can draw anything, we first have to run some scaffolding. We’ll seewhylater:
但是,在绘制任何东西之前,我们首先必须运行一些脚手架。 稍后我们将说明原因:
// Clear The Screen And The Depth BufferglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Reset The Current Modelview MatrixglMatrixMode(GL_MODELVIEW); glLoadIdentity();// Drawing Using TrianglesglBegin(GL_TRIANGLES);// RedglColor3f(1.0f,0.0f,0.0f);// Top Of Triangle (Front)glVertex3f( 0.0f, 1.0f, 0.0f);// GreenglColor3f(0.0f,1.0f,0.0f);// Left Of Triangle (Front)glVertex3f(-1.0f,-1.0f, 1.0f);// BlueglColor3f(0.0f,0.0f,1.0f);// Right Of Triangle (Front)glVertex3f( 1.0f,-1.0f, 1.0f);// Done DrawingglEnd();
// Clear The Screen And The Depth BufferglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Reset The Current Modelview MatrixglMatrixMode(GL_MODELVIEW); glLoadIdentity();// Drawing Using TrianglesglBegin(GL_TRIANGLES);// RedglColor3f(1.0f,0.0f,0.0f);// Top Of Triangle (Front)glVertex3f( 0.0f, 1.0f, 0.0f);// GreenglColor3f(0.0f,1.0f,0.0f);// Left Of Triangle (Front)glVertex3f(-1.0f,-1.0f, 1.0f);// BlueglColor3f(0.0f,0.0f,1.0f);// Right Of Triangle (Front)glVertex3f( 1.0f,-1.0f, 1.0f);// Done DrawingglEnd();
那是做什么的呢? (So what did that do?)
When you write a program that wants to use the graphics card, you’ll usually pick some kind of interface to the driver. Some well known interfaces to the driver are:
当您编写要使用图形卡的程序时,通常会选择某种与驱动程序的接口。 一些众所周知的驱动程序接口是:
OpenGL的OpenGL Direct3DDirect3D CUDA卡达
For this example we’ll stick with OpenGL. Now, yourinterface to the driveris what gives you all the tools you need to make your programtalkto the graphics card (or the driver, which thentalksto the card).
对于此示例,我们将坚持使用OpenGL。 现在,你的界面给司机是什么让你所有你需要让你的程序告诉图形卡(或驱动程序,然后会谈到卡)的工具。
This interface is bound to give you certaintools. These tools take the shape of an API which you can call from your program.
该界面一定会为您提供某些工具。 这些工具采用您可以从程序中调用的API的形式。
That API is what we see being used in the example above. Let’s take a closer look.
我们在上面的示例中看到了该API。 让我们仔细看看。
脚手架 (The Scaffolding)
Before you can really do any actual drawing, you’ll have to perform asetup. You have to define your viewport (the area that will actually be rendered), your perspective (thecamerainto your world), what anti-aliasing you will be using (to smooth out the edged of your triangle)…
在真正进行任何实际绘图之前,您必须执行设置。 您必须定义您的视口(实际要渲染的区域),透视图(摄像机进入您的世界),要使用的抗锯齿功能(使三角形的边缘变平滑)…
But we won’t look at any of that. We’ll just take a peek at the stuff you’ll have to doevery frame. Like:
但是我们不会考虑任何一个。 我们只是看一眼每个框架要做的事情。 喜欢:
Clearing the screen
清除画面
The graphics pipeline is not going to clear the screen for you every frame. You’ll have to tell it. Why? This is why:
图形管道不会为您每一帧清除屏幕。 您必须告诉它。 为什么? 这就是为什么:
If you don’t clear the screen, you’ll simplydraw overit every frame. That’s why we callglClear
with theGL_COLOR_BUFFER_BIT
set. The other bit (GL_DEPTH_BUFFER_BIT
) tells OpenGL to clear thedepthbuffer. This buffer is used to determine which pixels are in front (or behind) other pixels.
如果您不清除屏幕,则只需在每帧上画图即可。 这就是为什么我们使用设置了GL_COLOR_BUFFER_BIT
glClear
的原因。 另一位(GL_DEPTH_BUFFER_BIT
)告诉OpenGL清除深度缓冲区。 此缓冲区用于确定哪些像素在其他像素之前(或之后)。
Transformation
转型
Image source
图片来源
Transformation is the part where we take all the input coordinates (the vertices of our triangle) and apply our ModelView matrix. This is the matrix thatexplainshow ourmodel(the vertices) are rotated, scaled, and translated (moved).
转换是我们获取所有输入坐标(三角形的顶点)并应用我们的ModelView矩阵的部分。 这是解释我们的模型(顶点)如何旋转,缩放和平移(移动)的矩阵。
Next, we apply our Projection matrix. This moves all coordinates so that they face our camera correctly.
接下来,我们应用投影矩阵。 这将移动所有坐标,以便它们正确面对我们的相机。
Now we transform once more, with our Viewport matrix. We do this to scale ourmodelto the size of our monitor. Now we have a set of vertices that are ready to be rendered!
现在,我们使用视口矩阵再次进行变换。 我们这样做是为了将模型缩放到显示器的大小。 现在,我们有一组准备渲染的顶点!
We’ll come back to transformation a bit later.
我们待会儿再进行转换。
Drawing
画画
To draw a triangle, we can simply tell OpenGL to start a newlist of trianglesby callingglBegin
with theGL_TRIANGLES
constant. There are also other forms you can draw. Like a triangle strip or a triangle fan. These are primarily optimizations, as they require less communication between the CPU and the GPU to draw the same amount of triangles.
要绘制三角形,我们可以简单地告诉OpenGL通过使用GL_TRIANGLES
常量调用glBegin
来开始一个新的三角形列表。 您还可以绘制其他形式。 像三角带或三角扇子 。 这些主要是优化,因为它们需要较少的CPU和GPU之间的通信才能绘制相同数量的三角形。
After that, we can provide a list of sets of 3 vertices which should make up each triangle. Every triangle uses 3 coordinates (as we’re in 3D-space). Additionally, I also provide acolorfor each vertex, by callingglColor3f
beforecallingglVertex3f
.
之后,我们可以提供一组3个顶点的列表,这些顶点应该组成每个三角形。 每个三角形使用3个坐标(就像我们在3D空间中一样)。 另外,我还通过在调用glVertex3f
之前调用glColor3f
为每个顶点提供颜色。
The shade between the 3 vertices (the 3 corners of the triangle) is calculated by OpenGLautomatically. It will interpolate the color over the whole face of the polygon.
OpenGL自动计算3个顶点(三角形的3个角)之间的阴影。 它将插值整个多边形的颜色。
相互作用 (Interaction)
Now, when you click the window. The application only has to capture the window message that signals the click. Then you can run any action in your program you want.
现在,当您单击窗口时。 该应用程序仅需捕获表示单击的窗口消息 。 然后,您可以在程序中运行所需的任何操作。
This gets alotmore difficult once you want to start interacting with your 3D scene.
一旦你要开始与你的3D场景互动情况就会变得更加困难。
You first have to clearly know at which pixel the user clicked the window. Then, taking yourperspectiveinto account, you can calculate the direction of a ray, from the point of the mouse click into your scene. You can then calculate if any object in your sceneintersectswith that ray. Now you know if the user clicked an object.
首先,您必须清楚地知道用户单击窗口的像素。 然后,考虑到您的视角,您可以从鼠标单击场景的角度来计算射线的方向。 然后,您可以计算场景中的任何对象是否与该光线相交。 现在您知道用户是否单击了对象。
So, how do you make it rotate?
那么,如何使其旋转呢?
转型 (Transformation)
I am aware of two types of transformations that are generally applied:
我知道通常会应用两种类型的转换:
Matrix-based transformation基于矩阵的转换 Bone-based transformation基于骨骼的转换
The difference is thatbonesaffect singlevertices. Matrices always affect all drawn vertices in the same way. Let’s look at an example.
不同之处在于骨骼会影响单个顶点。 矩阵始终以相同的方式影响所有绘制的顶点。 让我们来看一个例子。
Example
例
Earlier, we loaded ouridentity matrixbefore drawing our triangle. The identity matrix is one that simply providesno transformationat all. So, whatever I draw, is only affected by my perspective. So, the triangle will not be rotated at all.
之前,我们在绘制三角形之前加载了单位矩阵。 单位矩阵是根本不提供任何转换的矩阵。 因此,无论我画什么,都只会受我的观点的影响。 因此,三角形将完全不会旋转。
If I want to rotate it now, I could either do the math myself (on the CPU) and simply callglVertex3f
withothercoordinates (that are rotated). Or I could let the GPU do all the work, by callingglRotatef
before drawing:
如果我现在想旋转它,我可以自己做一个数学运算(在CPU上),而只需用其他坐标(旋转的)调用glVertex3f
。 或者我可以通过在绘制之前调用glRotatef
来让GPU完成所有工作:
// Rotate The Triangle On The Y axis glRotatef(amount,0.0f,1.0f,0.0f);
amount
is, of course, just a fixed value. If you want toanimate, you’ll have to keep track ofamount
and increase it every frame.
amount
当然只是一个固定值。 如果要设置动画,则必须跟踪amount
并每帧增加它。
那么,等等,之前所有矩阵讨论发生了什么? (So, wait, what happened to all the matrix talk earlier?)
In this simple example, we don’t have to care about matrices. We simply callglRotatef
and it takes care of all that for us.
在这个简单的示例中,我们不必关心矩阵。 我们简单地称为glRotatef
,它将为我们处理所有这些工作。
glRotate
produces a rotation ofangle
degrees around the vector x y z . The current matrix (seeglMatrixMode) is multiplied by a rotation matrix with the product replacing the current matrix, as ifglMultMatrix were called with the following matrix as its argument:
glRotate
产生围绕向量xyz的angle
度旋转。 当前矩阵(请参见glMatrixMode )乘以旋转矩阵,乘积替换当前矩阵,就好像使用以下矩阵作为参数调用了glMultMatrix一样:x 2 1 – c + c x y 1 – c – z s x z 1 – c + y s 0 y x 1 – c + z s y 2 1 – c + c y z 1 – c – x s 0 x z 1 – c – y s y z 1 – c + x s z 2 1 – c + c 0 0 0 0 1
x 21 – c + cx y y1 – c – zsxz1 – c + y s s 0 yx1 – c + zsy 21 – c + cyz 1 – c – x s 0 x1 – c – y syz1 – c + x sz 2 z 1 – c + c 0 0 0 0 1
Well, thanks for that!
好吧,谢谢!
结论 (Conclusion)
What becomes obvious is, there’s a lot of talktoOpenGL. But it’s not tellingusanything. Where is the communication?
显而易见的是,关于OpenGL的讨论很多。 但这并没有告诉我们任何事情。 通讯在哪里?
The only thing that OpenGL is telling us in this example iswhen it’s done. Every operation will take a certain amount of time. Some operation take incredibly long, others are incredibly quick.
在此示例中,OpenGL唯一要告诉我们的是何时完成。 每次操作将花费一定的时间。 有些操作花费了难以置信的时间,而另一些则非常快。
Sending a vertexto the GPU will be so fast, I wouldn’t even know how to express it. Sending thousands of vertices from the CPU to the GPU, every single frame, is, most likely, no issue at all.
将顶点发送到GPU将是如此之快,我什至不知道如何表达它。 从单帧将数千个顶点从CPU发送到GPU完全没有问题。
Clearing the screencan take a millisecond or worse (keep in mind, you usually only have about 16 milliseconds of time to draw each frame), depending on how large your viewport is. To clear it, OpenGL has to draw every single pixel in the color you want to clear to, that could be millions of pixels.
清除屏幕可能要花费一毫秒或更长时间(请注意,通常每帧绘制时间只有16毫秒),具体取决于视口的大小。 要清除它,OpenGL必须以要清除的颜色绘制每个像素,该像素可能是数百万个像素。
Other than that, we can pretty much only ask OpenGL about the capabilities of our graphics adapter (max resolution, max anti-aliasing, max color depth, …).
除此之外,我们几乎只能向OpenGL询问我们的图形适配器的功能(最大分辨率,最大抗锯齿,最大颜色深度等)。
But we can also fill a texture with pixels that each have a specific color. Each pixel thus holds a value and the texture is a giant “file” filled with data. We can load that into the graphics card (by creating a texture buffer), then load a shader, tell that shader to use our texture as an input and run some extremely heavy calculations on our “file”.
但是我们也可以用每个都有特定颜色的像素填充纹理。 每个像素因此拥有一个值,纹理是一个充满数据的巨大“文件”。 我们可以将其加载到图形卡中(通过创建纹理缓冲区),然后加载着色器 ,告诉该着色器将纹理用作输入,并对“文件”进行一些非常繁琐的计算。
We can then “render” the result of our computation (in the form of new colors) into a new texture.
然后,我们可以将计算结果(以新颜色的形式)“渲染”为新的纹理。
That’s how you can make the GPU work for you in other ways. I assume CUDA performs similar to that aspect, but I never had the opportunity to work with it.
这样便可以使GPU以其他方式为您工作。 我认为CUDA的表现与该方面相似,但我从未有过使用它的机会。
We really only slightly touched the whole subject. 3D graphics programming is a hell of a beast.
我们真的只触及了整个主题。 3D图形编程是一头野兽。
Image Source
图片来源
Have something to add to the explanation? Sound off in the the comments. Want to read more answers from other tech-savvy Stack Exchange users? Check out the full discussion thread here.
有什么补充说明吗?在评论中听起来不对。是否想从其他精通Stack Exchange的用户那里获得更多答案?在此处查看完整的讨论线程 。
翻译自: /122274/how-do-the-cpu-and-gpu-interact-to-render-computer-graphics/
gpu cpu交互