<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

	<channel>
		<title>VirtualBlog</title>
		<link>http://virtualdub.org/blog/index.php</link>
		<description>Life as the author of VirtualDub</description>
		<dc:language>en-us</dc:language>
		<dc:creator />
		<dc:rights>Copyright 2012</dc:rights>
		<dc:date>2012-05-27T00:01:37-04:00</dc:date>
		<admin:generatorAgent rdf:resource="http://www.pivotlog.net/?ver=Pivot+-+1.15%3A+%27Soundwave%27" />
		<admin:errorReportsTo rdf:resource="mailto:rsserrors@pivotlog.net" />
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
		<sy:updateBase>2000-01-01T12:00+00:00</sy:updateBase>
	<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/virtualdub" /><feedburner:info uri="virtualdub" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>What did they do to the small caption font?</title>
		<link>http://feedproxy.google.com/~r/virtualdub/~3/S5F3UCVqA18/entry.php</link>
		<comments>http://virtualdub.org/blog/pivot/entry.php?id=367#comm</comments>
		<description>Noticed something weird while doing some debugging in Windows 8 Consumer Preview:

Apparently the small caption font entry in the non-client metrics has been tweaked in Windows 8 CP to use the same font size as&amp;nbsp;for main caption bars, which is a bit out of proportion for where&amp;nbsp;it is intended to be used. Here you can see the problem it causes in WinDbg, where all of the dockable windows now have huge caption bars. Even better yet, the old dialog that&amp;nbsp;used to allow the non-client metrics to be adjusted -- somewhat hidden in Windows 7 under the Window Color link in Personalization -- seems to have been removed, so this can't be fixed easily. I hope this is fixed for RTM, because otherwise it kinda sucks to be punished for trying to do the right thing by using system UI parameters.</description>
		<guid isPermaLink="false">367@http://virtualdub.org/blog/</guid>
		<content:encoded><![CDATA[ <p>Noticed something weird while doing some debugging in Windows 8 Consumer Preview:</p>
<p style="text-align:center;"><img src="http://virtualdub.org/blog/images/win8smallcaption.png" border="0" title="" alt="" /></p>
<p>Apparently the small caption font entry in the non-client metrics has been tweaked in Windows 8 CP to use the same font size as for main caption bars, which is a bit out of proportion for where it is intended to be used. Here you can see the problem it causes in WinDbg, where all of the dockable windows now have huge caption bars. Even better yet, the old dialog that used to allow the non-client metrics to be adjusted -- somewhat hidden in Windows 7 under the Window Color link in Personalization -- seems to have been removed, so this can't be fixed easily. I hope this is fixed for RTM, because otherwise it kinda sucks to be punished for trying to do the right thing by using system UI parameters.</p> <img src="http://feeds.feedburner.com/~r/virtualdub/~4/S5F3UCVqA18" height="1" width="1"/>]]></content:encoded>
		<dc:subject>default</dc:subject>
		<dc:date>2012-05-26T15:51:00-04:00</dc:date>
    <feedburner:origLink>http://virtualdub.org/blog/pivot/entry.php?id=367</feedburner:origLink></item>

	<item>
		<title>Pixel center positioning with 10level9</title>
		<link>http://feedproxy.google.com/~r/virtualdub/~3/IdGbHdGYQcE/entry.php</link>
		<comments>http://virtualdub.org/blog/pivot/entry.php?id=366#comm</comments>
		<description>I seem to have a knack for asking questions that no one has an answer to. The most recent one has to do with Microsoft's Direct3D 10level9&amp;nbsp;technology, which lets you write Direct3D 11 applications that target DX9-class hardware. Specifically, I wanted to know the positioning of pixel centers. As usual, I couldn't find anything on this in the documented and online, so I had to do some investigation and testing.
Before I get to the results, some background. The way that conventionally 3D rendering works is by sampling on a regular grid -- if you imagine that you have a continuous image with all your polygons rendered out at infinite resolution and then drop a regular grid of pins onto it, the color beneath all of the pinpoints determines the color of the pixels of the final image. I say "conventionally" because once you throw in multisampling, centroid sampling, etc. it gets a bit more complex, although it's still sampling. The positions of these samples can also be thought as pixel centers.&amp;nbsp;Now, as it turns out, the exact placement of these samples in the clip space coordinate system differs between rendering APIs:

OpenGL, Direct3D 10/11: for x in [0, width), center is at (x+0.5)/(2*width)-1
Direct3D 9: for x in [0, width), center is at x/(2*width)-1
Looking at this, you might think that the D3D9 placement is simpler and thus better, but in fact it's incredibly annoying. The reason is that the samples aren't centered, but are shifted up and left by half a pixel in the coordinate space. This means that, unlike the OpenGL placement, the coordinate space isn't symmetric about (0,0), and far worse, it makes your projection matrix dependent on viewport size. When setting up a regular 3D scene, the usual approach is to just ignore the problem and render with an uncompensated projection matrix. After all, who's going to notice if the image is shifted by half a pixel? Thankfully, Microsoft adjusted the coordinate system in Direct3D 10&amp;nbsp;to match OpenGL's half-integer samples, but everyone who still has to deal with D3D9 is stuck with this.
With 2D rendering,&amp;nbsp;the story is different. In this case getting the mapping right is critical, and failure to do so can result in serious artifacts such as directional smearing with multiple passes. My favorite symptoms are one pixel gaps&amp;nbsp;along two edges of the screen, missing corners on rectangles drawn using lines, and a 2x2 box filter blur across the entire image. Point sampling is often used as a hack to fix this problem, but that's dangerous because the half pixel offset means you're sampling exactly between texels -- and numerical accuracy issues can then introduce a lovely diagonal seam across your image. The right way is to adjust your projection matrix, and that means schlepping around the viewport-dependent offset all over the place as well as getting all the minus signs right (the Y offset is negated from the X offset!).
That brings us to 10level9, which is a special Direct3D 11 back end that interfaces to a Direct3D 9 device driver. Problem is, the pixel center offsets are different between D3D9 and D3D10/11, so the question I had was, do I need to correct for the offset? There were a few ways this could work out:</description>
		<guid isPermaLink="false">366@http://virtualdub.org/blog/</guid>
		<content:encoded><![CDATA[ <p>I seem to have a knack for asking questions that no one has an answer to. The most recent one has to do with Microsoft's Direct3D <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876%28v=vs.85%29.aspx">10level9</a> technology, which lets you write Direct3D 11 applications that target DX9-class hardware. Specifically, I wanted to know the positioning of pixel centers. As usual, I couldn't find anything on this in the documented and online, so I had to do some investigation and testing.</p>
<p>Before I get to the results, some background. The way that conventionally 3D rendering works is by sampling on a regular grid -- if you imagine that you have a continuous image with all your polygons rendered out at infinite resolution and then drop a regular grid of pins onto it, the color beneath all of the pinpoints determines the color of the pixels of the final image. I say "conventionally" because once you throw in multisampling, centroid sampling, etc. it gets a bit more complex, although it's still sampling. The positions of these samples can also be thought as pixel centers. Now, as it turns out, the exact placement of these samples in the clip space coordinate system differs between rendering APIs:</p>
<ul>
<li>OpenGL, Direct3D 10/11: for x in [0, width), center is at (x+0.5)/(2*width)-1</li>
<li>Direct3D 9: for x in [0, width), center is at x/(2*width)-1</li></ul>
<p>Looking at this, you might think that the D3D9 placement is simpler and thus better, but in fact it's incredibly annoying. The reason is that the samples aren't centered, but are shifted up and left by half a pixel in the coordinate space. This means that, unlike the OpenGL placement, the coordinate space isn't symmetric about (0,0), and far worse, it makes your projection matrix dependent on viewport size. When setting up a regular 3D scene, the usual approach is to just ignore the problem and render with an uncompensated projection matrix. After all, who's going to notice if the image is shifted by half a pixel? Thankfully, Microsoft adjusted the coordinate system in Direct3D 10 to match OpenGL's half-integer samples, but everyone who still has to deal with D3D9 is stuck with this.</p>
<p>With 2D rendering, the story is different. In this case getting the mapping right is critical, and failure to do so can result in serious artifacts such as directional smearing with multiple passes. My favorite symptoms are one pixel gaps along two edges of the screen, missing corners on rectangles drawn using lines, and a 2x2 box filter blur across the entire image. Point sampling is often used as a hack to fix this problem, but that's dangerous because the half pixel offset means you're sampling <strong>exactly</strong> between texels -- and numerical accuracy issues can then introduce a lovely diagonal seam across your image. The right way is to adjust your projection matrix, and that means schlepping around the viewport-dependent offset all over the place as well as getting all the minus signs right (the Y offset is negated from the X offset!).</p>
<p>That brings us to 10level9, which is a special Direct3D 11 back end that interfaces to a Direct3D 9 device driver. Problem is, the pixel center offsets are different between D3D9 and D3D10/11, so the question I had was, do I need to correct for the offset? There were a few ways this could work out:</p><ul>
<li>10level9 could ignore the difference, and the coordinate system would differ based on the underlying driver. This would be annoying but unsurprising; I still remember when you couldn't depend on glTexImage() getting red and blue straight for some formats and having the alpha blending cap set didn't necessarily mean the GPU <em>did</em> alpha blending.</li>
<li>10level9 could force software vertex processing, adjust the vertices on the CPU, and render the post-transformed geometry in hardware. This would be slower and not great for games or productivity apps, but OK for image processing where vertex transform load is low.</li>
<li>10level9 could rewrite the vertex shader to adjust the vertices. The problem with this is that there are hard limits on both instruction count and constant count for the base 9_1 profile that maps to vertex shader 2.0, and thus 10level9 might not be able to rewrite some vertex shaders to target shader model 2.0 hardware.</li></ul>
<p>Now, I have a trick that I use to check pixel center alignment on graphics hardware, which is to render a series of micro-sized quads at varying offsets across a grid. A pixel will only light up when the sampling location at the pixel's center falls within one of these quads, and rendering a series of such quads with progressively nudged offsets across a grid thus produces a picture indicating the sampling locations. Here's what the output can look like:</p>
<p style="text-align:center;"><img src="http://virtualdub.org/blog/images/sampling4x.png" border="0" title="Sampling grid - 4xAA" alt="Sampling grid - 4xAA" /></p>
<p>This was a trick originally I used to catch graphics drivers that were evilly set to force full-scene antialiasing on against the application's will, which made games look great but totally screwed over the image processing operations I was trying to do. (When you're trying to do a tricky sampling pattern and packing four monochrome results into an ARGB output, the last thing you want is the driver shifting your samples and slathering a big blur pass over the result.) The image above is catching one such driver in the act, which is doing 4xAA on what is supposed to be a regular one sample per pixel frame buffer. You can see the positioning of the four sub-samples which contribute to the antialiased result. It's also good for detecting deviations in sampling rules, however, which is how it applies here:</p>
<p style="text-align:center;"><img src="http://virtualdub.org/blog/images/sampling10level9.png" border="0" title="Sampling grid - 10level9" alt="Sampling grid - 10level9" /></p>
<p>As it turns out, no drama here, just a bullseye in the middle of the pixel -- which means that 10level9 <strong>does</strong> correct for the pixel offset between D3D9 and D3D10. I checked the WARP and reference drivers too, just in case this was a bug or misfeature in the hardware driver, but they gave the same result.</p>
<p>The next question I had was how. I'm embarrassed to say that I spent far too much time in WinDbg trying to coax this out of the 10level9 driver using symbols and tracing when all I actually needed to do was examine the output of the shader compiler. You see, in order to use 10level9, you have to compile your shaders in a special mode like vs_4_0_level_9_1:</p><pre>Microsoft (R) Direct3D Shader Compiler 9.29.952.3111<br  />Copyright (C) Microsoft Corporation 2002-2009. All rights reserved.</pre><pre>//<br  />// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111<br  />//<br  />//<br  />//   fxc /Tvs_4_0_level_9_1 /EVS shaders.fx<br  />//<br  />//<br  />//<br  />// Input signature:<br  />//<br  />// Name                 Index   Mask Register SysValue Format   Used<br  />// -------------------- ----- ------ -------- -------- ------ ------<br  />// POSITION                 0   xy          0     NONE  float   xy<br  />// COLOR                    0   xyzw        1     NONE  float   xyzw<br  />//<br  />//<br  />// Output signature:<br  />//<br  />// Name                 Index   Mask Register SysValue Format   Used<br  />// -------------------- ----- ------ -------- -------- ------ ------<br  />// COLOR                    0   xyzw        0     NONE  float   xyzw<br  />// SV_Position              0   xyzw        1      POS  float   xyzw<br  />//<br  />//<br  />// Runtime generated constant mappings:<br  />//<br  />// Target Reg                               Constant Description<br  />// ---------- --------------------------------------------------<br  /><font color="red">// c0                              Vertex Shader position offset<br  /></font>//<br  />//<br  />// Level9 shader bytecode:<br  />//<br  />    vs_2_0<br  />    def c1, 0.00312500005, -0.00416666688, -1, 1<br  />    def c2, 0.5, 1, 0, 0<br  />    dcl_texcoord v0<br  />    dcl_texcoord1 v1<br  />    mov r0.xy, c1<br  /><font color="red">    mad r0.xy, v0, r0, c0</font><br  />    add oPos.xy, r0, c1.zwzw<br  />    mov oT0, v1<br  />    mov oPos.zw, c2.xyxy</pre><pre>// approximately 5 instruction slots used<br  />vs_4_0<br  />dcl_input v0.xy<br  />dcl_input v1.xyzw<br  />dcl_output o0.xyzw<br  />dcl_output_siv o1.xyzw, position<br  />mov o0.xyzw, v1.xyzw<br  />mad o1.xy, v0.xyxx, l(0.003125, -0.004167, 0.000000, 0.000000), l(-1.000000, 1.000000, 0.000000, 0.000000)<br  />mov o1.zw, l(0,0,0.500000,1.000000)<br  />ret<br  />// Approximately 4 instruction slots used</pre>
<p>The shader compiler actually generates two versions of the vertex shader, one for Direct3D 9 class devices, and another for D3D10/11 capable ones. The telltale sign is the two lines in red, which compensate for the pixel offset. When compiling the shader for D3D9, the compiler reserves a special constant register for the offset and then emits additional logic to do the adjustment, like so:</p>
<blockquote style="MARGIN-RIGHT: 0px" dir="ltr">
<p>oPos.xy += offset.xy * oPos.w;</p></blockquote>
<p>Since the output position is in homogeneous coordinates, adding the offset scaled by w to the pre-divide position is equivalent to adding the offset to the post-divide position. This is apparently done at a higher level as the shader compiler is able to optimize this with the surrounding code: the multiply by w was omitted above because this was a 2D shader and the compiler noticed that w=1. In any case, the mystery of how the adjustment is done is solved -- not only is it done in the vertex shader, but the shader compiler modifies the shader so that 10level9 doesn't have to, and running into limits with the modified shader isn't a problem because the shader compiler can just enforce lower limits to allow for the adjustment. It also means you're taking the hit of an extra constant and an extra instruction for the adjustment, but for 2D stuff drawing big huge rectangles with four verts this is a non-issue.</p>
<p>tl;dr: 10level9 compensates for the different coordinate systems to make D3D9 hardware render with D3D10 rules and nice half-integer positioning, and all is good.</p> <img src="http://feeds.feedburner.com/~r/virtualdub/~4/IdGbHdGYQcE" height="1" width="1"/>]]></content:encoded>
		<dc:subject>default</dc:subject>
		<dc:date>2012-05-24T16:09:00-04:00</dc:date>
    <feedburner:origLink>http://virtualdub.org/blog/pivot/entry.php?id=366</feedburner:origLink></item>

</channel>
</rss>

