6
\$\begingroup\$

I never really fully understood this, or found an article which explained all the steps in a friendly way.

I'll start with what I do know already (which I hope do not contain misconceptions). I'm pretty sure allocating a multi-sampled frame buffer requires as many times the memory (of a regular buffer) as the number of samples (N). This makes sense because each pixel may be sampled up to N times.

During rasterization, the GPU generates a fragment for the MS frame buffer by testing if each sample is inside of the geometry being drawn. This is what provides edge anti-aliasing. Each sample produces a fragment.

I'm unsure about what occurs when all samples of a pixel are inside the geometry. How many fragments are generated? Is this configurable? What if I want to sample the "inside" pixels 4 times, and the edge pixels 16 times? This would require a 16x MS frame buffer.

Are there other differences? It seems like if the fragment shader is run once on each sample then we are left with something not much different from basic supersampling with the exception of jittered sample locations.

Actually, I'm also a bit unsure about what a frogment really is. It seems like a fragment shader gets (can get) executed more than once per pixel in a multi sampled scene, however this doesn't seem to necessarily mean that a fragment is more related to the sample than the pixel. Is a fragment best thought of as a sample, a pixel, or something else?

\$\endgroup\$
1
  • \$\begingroup\$ I found an article written a few months after this question was written which goes in depth and was very helpful as well. \$\endgroup\$
    – Steven Lu
    Jul 8, 2014 at 8:59

1 Answer 1

6
\$\begingroup\$

Multisampling runs the pixel shader once per pixel, while visibility (geometry coverage, depth/stencil tests, etc.) are done per sample. The same color output from the pixel shader is replicated to all the samples that pass the visibility tests. The fact that the pixel shader is only run once per pixel is what makes MSAA faster than supersampling.

In fact, in D3D10-11 you can cause the pixel shader to run per-sample if you really want to, by using the SV_SampleIndex parameter, or by marking an interpolated parameter with the sample keyword; see the MSDN for more. The OpenGL equivalent is the ARB_sample_shading extension (also part of core OpenGL since 4.0). If you do this, then it would turn into just plain supersampling. This is not the normal use case, though.

There is currently not a way to do something like run the PS 4x per pixel while having MSAA at 16x. Your only choices are to run the PS per-pixel or per-sample. But you could achieve what you described by having a 4x larger buffer that is 4x multisampled, then resolving the MSAA and downsampling the extra 4x yourself before displaying.

You're right that a multi-sampled frame buffer takes as much memory as a super-sampled one - although GPUs often internally use some sort of compression to reduce the memory bandwidth required, they still have to allocate the full amount of memory as a fallback, in case of "bad" pixels that aren't amenable to compression.

A "fragment" means a sample-sized chunk of a triangle (or other primitive, technically). As Nicol Bolas says, "A fragment is the state generated by the rasterization process for a particular sample, which will be used in various processing", e.g. depth/stencil testing. So yes, when using multisampling multiple fragments may be generated for the same primitive in the same pixel. However, the fragment shader still normally runs once per pixel.

\$\endgroup\$
4
  • \$\begingroup\$ Doesn't this mean that the OpenGL fragment shader is more of a pixel shader than a fragment shader, if it generally runs on a per-pixel basis rather than on a per-fragment basis? \$\endgroup\$
    – Steven Lu
    Jul 25, 2012 at 16:38
  • 2
    \$\begingroup\$ Hmm. I found this: "Note: Using the gl_SamplePosition variable in any way will cause the fragment shader to be evaluated per-sample. Since the whole point of multisampling is to avoid that, it's probably not a good idea to do so unless you really need it." from opengl.org/wiki/GLSL_Predefined_Variables \$\endgroup\$
    – Steven Lu
    Jul 25, 2012 at 16:40
  • \$\begingroup\$ Forgive my ignorance, but does the GPU really store the image data compressed? -- I thought the compression was just for the transport (i.e. sending/receiving data to/from the graphics card). I would like to learn more about this, can you cite a source here? [It seems like storing the data compressed in the graphics card's local memory would be a huge bottle neck for the parallel work flows that modern graphics cards are optimized for.] \$\endgroup\$ Jun 27, 2015 at 17:12
  • \$\begingroup\$ @BrainSlugs83 Yes, GPUs these days often use simple lossless compression formats for render targets, especially MSAA ones. It's done in hardware and is transparent to applications. Saves a ton of memory bandwidth. (Note this is a totally different thing from DXT/BC texture compression, which is lossy and precompressed offline. But that also does store the data compressed in video memory; it's decompressed in hardware when the texture is sampled. Again, saves a ton of bandwidth.) Source: I work at NVIDIA. \$\endgroup\$ Jun 27, 2015 at 19:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .