﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-playerwing - Life is like a game</title><link>http://www.cnitblog.com/playerwing/</link><description>&lt;br&gt;&lt;img src=http://www.cnitblog.com/images/cnitblog_com/playerwing/2914/r_02.jpg&gt;&lt;/img&gt;&lt;br&gt;
</description><language>zh-cn</language><lastBuildDate>Tue, 05 May 2026 03:12:26 GMT</lastBuildDate><pubDate>Tue, 05 May 2026 03:12:26 GMT</pubDate><ttl>60</ttl><item><title>Memory footprint ( explanation from Wikipedia )</title><link>http://www.cnitblog.com/playerwing/archive/2008/06/02/44742.html</link><dc:creator>Konami wiki</dc:creator><author>Konami wiki</author><pubDate>Mon, 02 Jun 2008 03:30:00 GMT</pubDate><guid>http://www.cnitblog.com/playerwing/archive/2008/06/02/44742.html</guid><wfw:comment>http://www.cnitblog.com/playerwing/comments/44742.html</wfw:comment><comments>http://www.cnitblog.com/playerwing/archive/2008/06/02/44742.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/playerwing/comments/commentRss/44742.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/playerwing/services/trackbacks/44742.html</trackback:ping><description><![CDATA[<p><strong><br>Memory footprint</strong> refers to the amount of main <a title="Random access memory" href="http://en.wikipedia.org/wiki/Random_access_memory"><u><font color=#0000ff>memory</font></u></a> that a program uses or references while running.</p>
<p>This includes all sorts of active memory regions like code, <a class=new title="Static data sections (page does not exist)" href="http://en.wikipedia.org/w/index.php?title=Static_data_sections&amp;action=edit&amp;redlink=1"><u><font color=#0000ff>static data sections</font></u></a> (both initialized and uninitialized), heap, as well as all the stacks, plus memory required to hold any additional data structures, such as <a class=mw-redirect title="Symbol tables" href="http://en.wikipedia.org/wiki/Symbol_tables"><u><font color=#0000ff>symbol tables</font></u></a>, <a class=new title="Constant tables (page does not exist)" href="http://en.wikipedia.org/w/index.php?title=Constant_tables&amp;action=edit&amp;redlink=1"><u><font color=#0000ff>constant tables</font></u></a>, <a class=new title="Debugging structures (page does not exist)" href="http://en.wikipedia.org/w/index.php?title=Debugging_structures&amp;action=edit&amp;redlink=1"><u><font color=#0000ff>debugging structures</font></u></a>, open files, etc, that the program ever needs while executing and will be loaded at least once during the entire run.</p>
<p>Larger programs have larger memory footprints. Excessive number of utility classes and methods in a programming language design would increase the footprint for API users even if they did not use non-standard plug-ins or applications. Programs themselves often do not contribute the largest portions to their own memory footprints; rather, structures introduced by the run-time environment take up most of the memory. For example, a C++ compiler inserts vtables, type_info objects and many temporary and anonymous objects that are active during a program's execution. In a Java program the memory footprint is predominantly made up of the runtime environment in form of the the <a title="Java Virtual Machine" href="http://en.wikipedia.org/wiki/Java_Virtual_Machine"><u><font color=#0000ff>Java Virtual Machine</font></u></a> (JVM) itself that is loaded indirectly when a Java application launches.</p>
<p>During the 1990s, computer memory became cheaper and programs with larger memory footprints became commonplace. This trend has been mostly due to the widespread use of computer software, from large enterprise-wide applications that consume vast amounts of memory (such as databases), to memory intensive multimedia authoring and editing software. To tackle the ever increasing memory needs, <a class=mw-redirect title="Virtual Memory" href="http://en.wikipedia.org/wiki/Virtual_Memory"><u><font color=#0000ff>Virtual Memory</font></u></a> systems were introduced that divide the available memory into equally-sized portions and loads them from "pages" stored on the hard-disk on an as-and-when required basis.</p>
<p>This approach to support programs with huge-memory-footprints has been quite successful. Most modern operating systems including <a title="Microsoft Windows" href="http://en.wikipedia.org/wiki/Microsoft_Windows"><u><font color=#0000ff>Microsoft Windows</font></u></a>, Apple's <a title="Mac OS X" href="http://en.wikipedia.org/wiki/Mac_OS_X"><u><font color=#0000ff>Mac OS X</font></u></a>, and all versions of <a title=Linux href="http://en.wikipedia.org/wiki/Linux"><u><font color=#0000ff>Linux</font></u></a> and <a title=Unix href="http://en.wikipedia.org/wiki/Unix"><u><font color=#0000ff>Unix</font></u></a> provide Virtual memory systems.</p>
<p>With the proliferation of <a class=new title="Intelligent consumer electronics (page does not exist)" href="http://en.wikipedia.org/w/index.php?title=Intelligent_consumer_electronics&amp;action=edit&amp;redlink=1"><u><font color=#0000ff>intelligent consumer electronics</font></u></a> or <a class=mw-redirect title="Embedded systems" href="http://en.wikipedia.org/wiki/Embedded_systems"><u><font color=#0000ff>embedded systems</font></u></a> low-memory-footprint programs have regained importance once more. Low-memory-footprint programs are of paramount to running applications on embedded platforms where memory is often constrained to within a few MBs &#8211; so much so that developers typically sacrifice efficiency (processing speeds) just to make program footprints small enough to fit into the available RAM. So much so that <a title="Sun Microsystems" href="http://en.wikipedia.org/wiki/Sun_Microsystems"><u><font color=#0000ff>Sun Microsystems</font></u></a> has now brought out a version of its <a title="Java Virtual Machine" href="http://en.wikipedia.org/wiki/Java_Virtual_Machine"><u><font color=#0000ff>Java Virtual Machine</font></u></a> (JVM) for these devices; it goes by the name of <em>KVM</em>. The KVM works on platforms where memory is in Kilobytes as opposed to the Megabytes (or even Gigabytes) of memory available on even a regular home PC.</p>
<img src ="http://www.cnitblog.com/playerwing/aggbug/44742.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/playerwing/" target="_blank">Konami wiki</a> 2008-06-02 11:30 <a href="http://www.cnitblog.com/playerwing/archive/2008/06/02/44742.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Some threads about D3Device::BeginScene() / EndScene() &amp; Present();</title><link>http://www.cnitblog.com/playerwing/archive/2008/03/18/41137.html</link><dc:creator>Konami wiki</dc:creator><author>Konami wiki</author><pubDate>Tue, 18 Mar 2008 15:42:00 GMT</pubDate><guid>http://www.cnitblog.com/playerwing/archive/2008/03/18/41137.html</guid><wfw:comment>http://www.cnitblog.com/playerwing/comments/41137.html</wfw:comment><comments>http://www.cnitblog.com/playerwing/archive/2008/03/18/41137.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/playerwing/comments/commentRss/41137.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/playerwing/services/trackbacks/41137.html</trackback:ping><description><![CDATA[<span style="COLOR: red">Thread 1:</span> <br><br>I recorded the time it takes to call the Present method of the Direct3D device I'm using. It takes 15 - 16 ms. Doesn't this method just flip the backbuffer to the front? Why does it take so long?<br><br>-Devin<br><br><br><span style="COLOR: red">Answer 1.1&nbsp;( selected ):</span><br><br>Present is a blocking call, and may take quite a while to finish, even when VSync is off.<br><br>During regular DX calls, the GPU and CPU are not sync'd. The CPU can issue commands to the GPU before it finishes the previous calls, by pushing them in to a command queue. The GPU then just processes commands in the queue at it's own time.<br><br>When you call Present, DX syncs between the CPU and GPU, to make sure the two don't drift apart too far. If the GPU has a lot more work to do than the CPU has, the CPU will be waiting for the GPU to finish before Present returns.<br><br>If you'd like, you can call Present with the D3DPRESENT_DONOTWAIT flag (I think it actually goes in the PresentParameters when you set up the device). With that flag set, Present returns immediately. Instead of waiting for the GPU to finish, Present returns a D3DERR_WASSTILLDRAWINGerror, to indicate the GPU hasn't finished it's work yet. This allows you to use these extra cycles for non-critical tasks.<br>psuedocode:<br>
<pre>while (Device-&gt;Present(0, 0, 0, 0) == D3DERR_WASSTILLDRAWING)
CountSheep();</pre>
<br><br>Hope this helps.<br><br><span style="COLOR: red">Answer 1.2&nbsp;( selected ):</span><br>
<blockquote><span class=smallfont>Quote:</span>
<table cellSpacing=0 cellPadding=4 width="95%" border=0>
    <tbody>
        <tr>
            <td class=quote><!--/quote--><!--startquote--><em>Original post by devronious</em><br>while (Device-&gt;Present(0, 0, 0, 0) == D3DERR_WASSTILLDRAWING)<br>CountSheep();<br><br>How can this work if present returns void? Also, I only show up to 3 params for that method.<!--quote--></td>
        </tr>
    </tbody>
</table>
</blockquote><!--/quote--><!--endquote-->You need to go via a proper swap-chain interface to get the <tt>Present()</tt> function in the form sirob posted it. The default/implicit chain controlled via the device doesn't expose it.<br><br>I don't have my docs to hand, but I'm pretty sure you can extract an <tt>IDirect3DSwapChain9</tt> interface from the device and work from there...<br><br>btw, be very careful how you're profiling your application - there are a lot of ways to generate completely bogus results <img src="http://www.gamedev.net/community/forums/images/smileys/wink.gif" border=0><br><br>hth<br>Jack<br><br><br><br><span style="COLOR: red">Thread 2:</span> <br>I'm using DirectX9<br><br>In a rendering loop, I believe there must be a blocking function call (Present(), EndScene() or BeginScene() ???)<br>in order for the CPU to wait for the GPU to finish drawing its frame.<br><br><br>I then wondered how could I achieve maximum parrallelism/concurrency betwwen CPU &amp; GPU.<br><br>Intuitively (if we admit that present() is the "blocking" function) my loop would look like this<br><br><br>BeginScene()<br>DrawIndexedPrimitive()<br>.<br>. (all kinds of drawing functions)<br>.<br>EndScene()<br><br>//While the graphic card/driver is executing all drawing commands, do some CPU intensive tasks<br><br>ComputeAI()<br>ComputePhysics()<br>.... <br><br>Present() //Stall the CPU while the GPU has finished drawing (if not yet)<br><br><br>Am I wrong ? right ? and which is the "blocking function" if one exists ?<br><br><br><span style="COLOR: red">Answer 2.1&nbsp;( selected ):</span><br>I believe there are two blocking factors. One is that the driver isn't supposed to queue more than 3 frames at a time. Present will block under these circumstances (unless you present on the swap chain itself, in which case you have the opportunity to D3DPRESENT_DONOTWAIT and the call will return immediately with D3DERR_WASSTILLDRAWING).<br><br>The other is that you can't render to a back buffer that's queued for display. So in some circumstances DrawPrimitive will block.<br><br>And I seem to recall that D3DSWAPEFFECT_COPY will block on Present until the back buffer has been blitted. But I haven't gotten around to testing all this, so don't hold me to it. Grain of salt and all that... <img height=15 src="http://www.gamedev.net/community/forums/smile.gif" width=15 align=middle>
<img src ="http://www.cnitblog.com/playerwing/aggbug/41137.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/playerwing/" target="_blank">Konami wiki</a> 2008-03-18 23:42 <a href="http://www.cnitblog.com/playerwing/archive/2008/03/18/41137.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>floating point precision control</title><link>http://www.cnitblog.com/playerwing/archive/2008/03/02/40370.html</link><dc:creator>Konami wiki</dc:creator><author>Konami wiki</author><pubDate>Sun, 02 Mar 2008 15:19:00 GMT</pubDate><guid>http://www.cnitblog.com/playerwing/archive/2008/03/02/40370.html</guid><wfw:comment>http://www.cnitblog.com/playerwing/comments/40370.html</wfw:comment><comments>http://www.cnitblog.com/playerwing/archive/2008/03/02/40370.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/playerwing/comments/commentRss/40370.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/playerwing/services/trackbacks/40370.html</trackback:ping><description><![CDATA[　　过年了简直时间就不够用，冷落了博客&#8230;&#8230; 补偿一下，找到一篇关于浮点精度控制的文章，兴趣满大的（但我不知道是哪里找来的，故无法贴出原帖地址，为此向作者说声抱歉）<br><br>
<h3>Precision control</h3>
First -- a tiny introduction on IEEE floating point formats. On most chips, IEEE floats come in three flavors: 32-bit, 64-bit, and 80-bit, called "single-", "double-" and "extended-" precision, respectively. The increase in precision from one to the next is better than it appears: 32-bit floats only give you 24 bits of mantissa, while 64-bit ones give you 53 bits. Extended gives you 64 bits. (Unfortunately, you can't use extended precision under Windows NT without special drivers. This is ostensibly for compatibility with other chips.) Other CPUs, like the PowerPC, have even larger formats, like a 128-bit format.
<p>Second -- to dispel a myth. Typing "float" rather than "double" changes the memory representation of your data, but doesn't really change the way the chip uses it. In fact, it guarantees you <em>at least</em> floating point accuracy. Because optimized code keeps data in registers longer, it will sometimes be more precise than debug code, which flushes to the stack often.
<p>Again: typing "float" does not change anything that goes on in the FPU internally. If you don't actively change the chip's precision, you're probably doing double-precision arithmetic while an operand is being processed.
<p>The x86 FPU <em>does</em> have precision control, which will stop calculation after it's computed enough to achieve floating point accuracy. But, you can't change FPU precision from ANSI C.
<p>
<h3>What runs faster in single precision?</h3>
Speedwise, single precision affects exactly two calls: <strong>divides</strong> and <strong>sqrts</strong>. It won't make trancendentals any faster (sin, acos, log, etc., all run the same no matter what: 100+ cycles.) If your program does lots of single-precision divides and sqrts, then you need to know about this.
<p>Single precision will at least double the speed of divides and sqrts. Divides take 17 cycles and sqrts take about 25 cycles. In double precision, they're at least twice that.
<p>On x86, precision control is adjusted using the assembly call "fldcw". Microsoft has a nice wrapper called <strong>_controlfp</strong> that's easier to use. If you're using Linux, I recommend getting the Intel Instruction Set Reference and writing the inline assembly. (Send me code so I can post it!)
<p>To set the FPU to single precision:
<pre>  _controlfp( _PC_24, MCW_PC );
</pre>
To set it back to default (double) precision:
<pre>  _controlfp( _CW_DEFAULT, 0xfffff );
</pre>
I use a C++ class that sets the precision while it's in scope and then drops back to the previous rounding and precision mode as it goes out -- very convenient, so you don't forget to reset the precision, and you can handle error cases properly.
<p>
<hr>
<a name=convert>
<h3>Fast conversions: float to int</h3>
</a>Lots of people have been talking about how bad Intel chips are at converting floating point to integer. (Intel, NVIDIA, and hordes of people on Usenet.)
<p>I thought it would be fun to try to do the definitive, complete, version of this discussion. This will get a little winded at the end, but try to hang on -- good stuff ahead.
<p>So, if you ever do this:
<pre>inline int Convert(float x)
{
int i = (int) x;
return i;
}
</pre>
or you call floor() or ceil() or anything like that, you probably shouldn't.
<p>The problem is that there is no dedicated x86 instruction to do an "ANSI C" conversion from floating point to integer. There is an instruction on the chip that does a conversion (<strong>fistp</strong>), but it respects the chip's current rounding mode (set with fldcw like the precision flags up above.) Of course, the default rounding mode does not clamp to zero.
<p>To implement a "correct" conversion, compiler writers have had to switch the rounding mode, do the conversion with fistp, and switch back. Each switch requires a complete flush of the floating point state, and takes about 25 cycles.
<p>This means that this function, even inlined, takes upwards of <strong>80 (EIGHTY) cycles</strong>!
<p>Let me put it this way: this isn't something to scoff at and say, "Machines are getting faster." I've seen quite well-written code get <strong>8 TIMES FASTER</strong> after fixing conversion problems. Fix yours! And here's how...
<p>
<h3>Sree's Real2Int</h3>
There are quite a few ways to fix this. One of the best general conversion utilities I have is one that Sree Kotay wrote. It's only safe to use when your FPU is in <em>double-precision</em> mode, so you have to be careful about it if you're switching precision like above. It'll basically return '0' all the time if you're in single precision.
<p>(I've recently discovered that this discussion bears a lot of resemblance to <a href="http://www.d6.com/users/checker/pdfs/gdmfp.pdf"><u><font color=#0000ff>Chris Hecker's article</font></u></a> on the topic, so be sure to read that if you can't figure out what I'm saying.)
<p>This function is basically an ANSI C compliant conversion -- it always chops, always does the right thing, for positive or negative inputs.
<p>
<pre>typedef double lreal;
typedef float  real;
typedef unsigned long uint32;
typedef long int32;
const lreal _double2fixmagic = 68719476736.0*1.5;     //2^36 * 1.5,  (52-_shiftamt=36) uses limited precisicion to floor
const int32 _shiftamt        = 16;                    //16.16 fixed point representation,
#if BigEndian_
#define iexp_				0
#define iman_				1
#else
#define iexp_				1
#define iman_				0
#endif //BigEndian_
// ================================================================================================
// Real2Int
// ================================================================================================
inline int32 Real2Int(lreal val)
{
#if DEFAULT_CONVERSION
return val;
#else
val		= val + _double2fixmagic;
return ((int32*)&amp;val)[iman_] &gt;&gt; _shiftamt;
#endif
}
// ================================================================================================
// Real2Int
// ================================================================================================
inline int32 Real2Int(real val)
{
#if DEFAULT_CONVERSION
return val;
#else
return Real2Int ((lreal)val);
#endif
}
</pre>
<h3>fistp</h3>
In either precision mode, you can call fistp (the regular conversion) directly. However, this means you need to know the current FPU rounding mode. In most cases, the following function will round the conversion to the nearest integer, rather than clamping towards zero, so that's what I call it:
<p>
<pre>inline int32 Round(real32 a) {
int32 retval;
__asm fld a
__asm fistp retval
return retval;
}
</pre>
<h3>Direct conversions</h3>
I originally learned this one (and this way of thinking about the FPU) from <a href="http://www.cs.rice.edu/~dwallach/"><u><font color=#0000ff>Dan Wallach</font></u></a> when we were both at Microsoft in the summer of 1995. He showed me how to implement a fast lookup table by direct manipulation of the mantissa of a floating point number in a certain range.
<p>First, you have to know a single precision float has three components:
<pre>  sign[1 bit]  exp[8 bits]  mantissa[23 bits]
</pre>
The value of the number is computed as:<br>(-1)^sign * 1.mantissa * 2^(exp - 127)
<p>So what does that mean? Well, it has a nice effect:
<p>Between any power of two and the next (e.g., [2, 4) ), the exponent is <em>constant</em>. For certain cases, you can just mask out the mantissa, and use that as a fixed-point number. Let's say you know your input is between 0 and 1, not including 1. You can do this:
<pre>int FloatTo23Bits(float x)
{
float y = x + 1.f;
return ((unsigned long&amp;)y) &amp; 0x7FFFFF;	// last 23 bits
}
</pre>
The first line makes 'y' lie between 1 and 2, where the exponent is a constant 127. Reading the last 23 bits gives an exact 23 bit representation of the number between 0 and 1. Fast and easy.
<p>
<h3>Timing: fast conversions</h3>
Sree and I have benchmarked and spent a lot of time on this problem. I tend to use fistp a lot more than his conversion, because I write a lot of code that needs single precision. His tends to be faster, so I need to remember to use it more.
<p>In specific cases, the direct conversions can be very useful, but they're about as fast as Sree's code, so generally there's not too much advantage. You can save a shift, maybe, and it does work in single precision mode.
<p>Each of the above functions is about 6 cycles by itself. However, the <strong>Real2Int</strong> version is <strong>much</strong> better at pairing with floating point (it doesn't lock the FPU for 6 cycles like <strong>fistp</strong> does.) So in really well pipelined code, his function can be close to free. <strong>fistp</strong> will take about 6 cycles.
<p>
<h3>Hacking VC's Runtime for Fun and Debugging</h3>
Finally, here's a function that overrides Microsoft's <strong>_ftol</strong> (the root of all evil.) One of the comp.lang.x86.asm guys ripped this out of Microsoft's library, then Terje Mathison did the "OR" optimization, and then I hacked it into manually munging of the stack (note: no frame pointer?) like you see below. But don't do this at home -- it's evil too.
<p>It also may have some bugs -- I'm not sure it works when there are floating point exceptions. Anyway, it's about 10-15 cycles faster than Microsoft's implementation.
<p>Also, it will show up in a profile, which is a really great thing. You can put a breakpoint in it and see who's calling slow conversions, then go fix them. Overall, <strong>I don't recommend shipping code with it</strong>, but definitely use it for debugging.
<p>Also, there's a "fast" mode that does simple rounding instead, but that doesn't get inlined, and it's generally a pain, since you can't get "ANSI correct" behavior when you want it.
<p>
<pre>#define ANSI_FTOL 1
extern "C" {
__declspec(naked) void _ftol() {
__asm    {
#if ANSI_FTOL
fnstcw   WORD PTR [esp-2]
mov      ax, WORD PTR [esp-2]
OR AX,	 0C00h
mov      WORD PTR [esp-4], ax
fldcw    WORD PTR [esp-4]
fistp    QWORD PTR [esp-12]
fldcw    WORD PTR [esp-2]
mov      eax, DWORD PTR [esp-12]
mov      edx, DWORD PTR [esp-8]
#else
fistp    DWORD PTR [esp-12]
mov		 eax, DWORD PTR [esp-12]
mov		 ecx, DWORD PTR [esp-8]
#endif
ret
}
}
}
</pre>
<a name=gcc>
<hr>
I got some great code from Kevin Egan at Brown University. He reimplemented precision control and the inline conversion calls with AT&amp;T-compatible syntax so they work on gcc.
<p>It's a lot of code, so I'm posting it at the end here. :) <!--ok, you can copy and paste, I'm not escaping the gt's and lt's-->
<pre>#include <stdio.h>
#include <assert.h>
#ifdef USE_SSE
#include <xmmintrin.h>
#endif // USE_SSE
/*
SAMPLE RUN
~/mod -&gt; g++-3.2 fpu.cpp
~/mod -&gt; ./a.out
ANSI slow, default FPU, float 1.80000 int 1
fast, default FPU, float 1.80000 int 2
ANSI slow, modified FPU, float 1.80000 int 1
fast, modified FPU, float 1.80000 int 1
ANSI slow, default FPU, float 1.80000 int 1
fast, default FPU, float 1.80000 int 2
ANSI slow, modified FPU, float 1.80000 int 1
fast, modified FPU, float 1.80000 int 1
ANSI slow, default FPU, float 1.10000 int 1
fast, default FPU, float 1.10000 int 1
ANSI slow, modified FPU, float 1.10000 int 1
fast, modified FPU, float 1.10000 int 1
ANSI slow, default FPU, float -1.80000 int -1
fast, default FPU, float -1.80000 int -2
ANSI slow, modified FPU, float -1.80000 int -1
fast, modified FPU, float -1.80000 int -1
ANSI slow, default FPU, float -1.10000 int -1
fast, default FPU, float -1.10000 int -1
ANSI slow, modified FPU, float -1.10000 int -1
fast, modified FPU, float -1.10000 int -1
*/
/**
* bits to set the floating point control word register
*
* Sections 4.9, 8.1.4, 10.2.2 and 11.5 in
* IA-32 Intel Architecture Software Developer's Manual
*   Volume 1: Basic Architecture
*
* http://www.intel.com/design/pentium4/manuals/245471.htm
*
* http://www.geisswerks.com/ryan/FAQS/fpu.html
*
* windows has _controlfp() but it takes different parameters
*
* 0 : IM invalid operation mask
* 1 : DM denormalized operand mask
* 2 : ZM divide by zero mask
* 3 : OM overflow mask
* 4 : UM underflow mask
* 5 : PM precision, inexact mask
* 6,7 : reserved
* 8,9 : PC precision control
* 10,11 : RC rounding control
*
* precision control:
* 00 : single precision
* 01 : reserved
* 10 : double precision
* 11 : extended precision
*
* rounding control:
* 00 = Round to nearest whole number. (default)
* 01 = Round down, toward -infinity.
* 10 = Round up, toward +infinity.
* 11 = Round toward zero (truncate).
*/
#define __FPU_CW_EXCEPTION_MASK__   (0x003f)
#define __FPU_CW_INVALID__          (0x0001)
#define __FPU_CW_DENORMAL__         (0x0002)
#define __FPU_CW_ZERODIVIDE__       (0x0004)
#define __FPU_CW_OVERFLOW__         (0x0008)
#define __FPU_CW_UNDERFLOW__        (0x0010)
#define __FPU_CW_INEXACT__          (0x0020)
#define __FPU_CW_PREC_MASK__        (0x0300)
#define __FPU_CW_PREC_SINGLE__      (0x0000)
#define __FPU_CW_PREC_DOUBLE__      (0x0200)
#define __FPU_CW_PREC_EXTENDED__    (0x0300)
#define __FPU_CW_ROUND_MASK__       (0x0c00)
#define __FPU_CW_ROUND_NEAR__       (0x0000)
#define __FPU_CW_ROUND_DOWN__       (0x0400)
#define __FPU_CW_ROUND_UP__         (0x0800)
#define __FPU_CW_ROUND_CHOP__       (0x0c00)
#define __FPU_CW_MASK_ALL__         (0x1f3f)
#define __SSE_CW_FLUSHZERO__        (0x8000)
#define __SSE_CW_ROUND_MASK__       (0x6000)
#define __SSE_CW_ROUND_NEAR__       (0x0000)
#define __SSE_CW_ROUND_DOWN__       (0x2000)
#define __SSE_CW_ROUND_UP__         (0x4000)
#define __SSE_CW_ROUND_CHOP__       (0x6000)
#define __SSE_CW_EXCEPTION_MASK__   (0x1f80)
#define __SSE_CW_PRECISION__        (0x1000)
#define __SSE_CW_UNDERFLOW__        (0x0800)
#define __SSE_CW_OVERFLOW__         (0x0400)
#define __SSE_CW_DIVIDEZERO__       (0x0200)
#define __SSE_CW_DENORMAL__         (0x0100)
#define __SSE_CW_INVALID__          (0x0080)
// not on all SSE machines
// #define __SSE_CW_DENORMALZERO__     (0x0040)
#define __SSE_CW_MASK_ALL__         (0xffc0)
#define __MOD_FPU_CW_DEFAULT__ \
(__FPU_CW_EXCEPTION_MASK__ + __FPU_CW_PREC_DOUBLE__ + __FPU_CW_ROUND_CHOP__)
#define __MOD_SSE_CW_DEFAULT__ \
(__SSE_CW_EXCEPTION_MASK__ + __SSE_CW_ROUND_CHOP__ + __SSE_CW_FLUSHZERO__)
#ifdef USE_SSE
inline unsigned int getSSEStateX86(void);
inline void setSSEModDefault(unsigned int control);
inline void modifySSEStateX86(unsigned int control, unsigned int mask);
#endif // USE_SSE
inline void setRoundingMode(unsigned int round);
inline unsigned int getFPUStateX86(void);
inline void setFPUStateX86(unsigned int control);
inline void setFPUModDefault(void);
inline void assertFPUModDefault(void);
inline void modifyFPUStateX86(const unsigned int control, const unsigned int mask);
inline int FastFtol(const float a);
// assume for now that we are running on an x86
// #ifdef __i386__
#ifdef USE_SSE
inline
unsigned int
getSSEStateX86
(void)
{
return _mm_getcsr();
}
inline
void
setSSEStateX86
(unsigned int control)
{
_mm_setcsr(control);
}
inline
void
modifySSEStateX86
(unsigned int control, unsigned int mask)
{
unsigned int oldControl = getFPUStateX86();
unsigned int newControl = ((oldControl &amp; (~mask)) | (control &amp; mask));
setFPUStateX86(newControl);
}
inline
void
setSSEModDefault
(void)
{
modifySSEStateX86(__MOD_SSE_CW_DEFAULT__, __SSE_CW_MASK_ALL__);
}
#endif // USE_SSE
inline
void
setRoundingMode
(Uint32 round)
{
ASSERT(round &lt; 4);
Uint32 mask = 0x3;
Uint32 fpuControl = getFPUStateX86();
fpuControl &amp;= ~(mask &lt;&lt; 10);
fpuControl |= round &lt;&lt; 10;
setFPUStateX86(fpuControl);
#ifdef USE_SSE
Uint32 sseControl = getSSEStateX86();
sseControl &amp;= ~(mask &lt;&lt; 13);
sseControl |= round &lt;&lt; 13;
setSSEStateX86(sseControl);
#endif // USE_SSE
}
inline
unsigned int
getFPUStateX86
(void)
{
unsigned int control = 0;
#if defined(_MSVC)
__asm fnstcw control;
#elif defined(__GNUG__)
__asm__ __volatile__ ("fnstcw %0" : "=m" (control));
#endif
return control;
}
/* set status */
inline
void
setFPUStateX86
(unsigned int control)
{
#if defined(_MSVC)
__asm fldcw control;
#elif defined(__GNUG__)
__asm__ __volatile__ ("fldcw %0" : : "m" (control));
#endif
}
inline
void
modifyFPUStateX86
(const unsigned int control, const unsigned int mask)
{
unsigned int oldControl = getFPUStateX86();
unsigned int newControl = ((oldControl &amp; (~mask)) | (control &amp; mask));
setFPUStateX86(newControl);
}
inline
void
setFPUModDefault
(void)
{
modifyFPUStateX86(__MOD_FPU_CW_DEFAULT__, __FPU_CW_MASK_ALL__);
assertFPUModDefault();
}
inline
void
assertFPUModDefault
(void)
{
assert((getFPUStateX86() &amp; (__FPU_CW_MASK_ALL__)) ==
__MOD_FPU_CW_DEFAULT__);
}
// taken from http://www.stereopsis.com/FPU.html
// this assumes the CPU is in double precision mode
inline
int
FastFtol(const float a)
{
static int    b;
#if defined(_MSVC)
__asm fld a
__asm fistp b
#elif defined(__GNUG__)
// use AT&amp;T inline assembly style, document that
// we use memory as output (=m) and input (m)
__asm__ __volatile__ (
"flds %1        \n\t"
"fistpl %0      \n\t"
: "=m" (b)
: "m" (a));
#endif
return b;
}
void test()
{
float testFloats[] = { 1.8, 1.8, 1.1, -1.8, -1.1 };
int testInt;
unsigned int oldControl = getFPUStateX86();
for (int i = 0; i &lt; 5; i++) {
float curTest = testFloats[i];
setFPUStateX86(oldControl);
testInt = (int) curTest;
printf("ANSI slow, default FPU, float %.5f int %d\n",
curTest, testInt);
testInt = FastFtol(curTest);
printf("fast, default FPU, float %.5f int %d\n",
curTest, testInt);
setFPUModDefault();
testInt = (int) curTest;
printf("ANSI slow, modified FPU, float %.5f int %d\n",
curTest, testInt);
testInt = FastFtol(curTest);
printf("fast, modified FPU, float %.5f int %d\n\n",
curTest, testInt);
}
}
int
main
(int argc, char** argv)
{
test();
return 0;
}
</pre>
</a>
<img src ="http://www.cnitblog.com/playerwing/aggbug/40370.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/playerwing/" target="_blank">Konami wiki</a> 2008-03-02 23:19 <a href="http://www.cnitblog.com/playerwing/archive/2008/03/02/40370.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>看看我们国家的司法</title><link>http://www.cnitblog.com/playerwing/archive/2007/12/24/38013.html</link><dc:creator>Konami wiki</dc:creator><author>Konami wiki</author><pubDate>Mon, 24 Dec 2007 01:50:00 GMT</pubDate><guid>http://www.cnitblog.com/playerwing/archive/2007/12/24/38013.html</guid><wfw:comment>http://www.cnitblog.com/playerwing/comments/38013.html</wfw:comment><comments>http://www.cnitblog.com/playerwing/archive/2007/12/24/38013.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/playerwing/comments/commentRss/38013.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/playerwing/services/trackbacks/38013.html</trackback:ping><description><![CDATA[<p><a href="http://news.qq.com/a/20071224/000889.htm">http://news.qq.com/a/20071224/000889.htm</a><br>《恶意取款者被判无期 专家称处罚太过令人震惊》<br><br><span style="COLOR: red">不好意思地转载了几位网友的评论：</span><br><br><span class="bolds b1"><strong><span class=reply_top><font color=#008000>[热]</font></span> </strong></span>腾讯网友 发表评论：<span id=r_pk_0>[支持:2人 反对:35人 中立:0人]</span><br></p>
<p>连同发表反对重刑的所谓的&#8220;律师&#8221;一起判，许某钻银行的空子171次，而且挥霍一空，于情于理都没有可宽恕的地方，律师钻法律的空子，歪曲字面含义，应该取消其律师资格，永世不得录用</p>
<p><br><br><span class="bolds b1"><strong><span class=reply_top><font color=#008000>[热]</font></span> </strong></span>腾讯网友 发表评论：<span id=r_pk_1>[支持:31人 反对:0人 中立:0人]</span><br></p>
<p>重得不是一点半点儿！贪污几个亿的也没死成，提了十几万就无期了？银行系统有问题管理者没有责任吗？那是不是银行的管理者以及软件制造商和ATM机制造商也得判？</p>
<p><br><br><span class="bolds b1"><strong><span class=reply_top><font color=#008000>[热]</font></span> </strong></span>腾讯网友 发表评论：<span id=r_pk_2>[支持:72人 反对:0人 中立:1人]</span><br>ATM取出假钱---&gt;银行无责</p>
<p>网上银行被盗---&gt;储户责任 </p>
<p>ATM机出现故障少给钱---&gt;用户负责 </p>
<p>ATM机出现故障多给钱---&gt;用户盗窃，刑事责任</p>
<p>银行多给了钱---&gt;储户义务归还 </p>
<p>银行少给了钱---〉离开柜台银行概不负责<br></p>
<img src ="http://www.cnitblog.com/playerwing/aggbug/38013.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/playerwing/" target="_blank">Konami wiki</a> 2007-12-24 09:50 <a href="http://www.cnitblog.com/playerwing/archive/2007/12/24/38013.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>《性命呼叫转移》</title><link>http://www.cnitblog.com/playerwing/archive/2007/12/12/37622.html</link><dc:creator>Konami wiki</dc:creator><author>Konami wiki</author><pubDate>Wed, 12 Dec 2007 03:55:00 GMT</pubDate><guid>http://www.cnitblog.com/playerwing/archive/2007/12/12/37622.html</guid><wfw:comment>http://www.cnitblog.com/playerwing/comments/37622.html</wfw:comment><comments>http://www.cnitblog.com/playerwing/archive/2007/12/12/37622.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/playerwing/comments/commentRss/37622.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/playerwing/services/trackbacks/37622.html</trackback:ping><description><![CDATA[<a href="http://www.tudou.com/programs/view/WXJ2VgSBoro/">http://www.tudou.com/programs/view/WXJ2VgSBoro/</a><br><br>强烈推荐，我觉得是目前我见过的恶搞片里做的做好的一部。<br>数次回味，后果是：数次满身是灰，数次脸上有像哭过一样的泪痕&#8230;&#8230; 
<img src ="http://www.cnitblog.com/playerwing/aggbug/37622.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/playerwing/" target="_blank">Konami wiki</a> 2007-12-12 11:55 <a href="http://www.cnitblog.com/playerwing/archive/2007/12/12/37622.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Portal 结尾曲： Still Alive </title><link>http://www.cnitblog.com/playerwing/archive/2007/11/09/36049.html</link><dc:creator>Konami wiki</dc:creator><author>Konami wiki</author><pubDate>Fri, 09 Nov 2007 05:57:00 GMT</pubDate><guid>http://www.cnitblog.com/playerwing/archive/2007/11/09/36049.html</guid><wfw:comment>http://www.cnitblog.com/playerwing/comments/36049.html</wfw:comment><comments>http://www.cnitblog.com/playerwing/archive/2007/11/09/36049.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/playerwing/comments/commentRss/36049.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/playerwing/services/trackbacks/36049.html</trackback:ping><description><![CDATA[<p>　　This Was A Triumph&nbsp;&nbsp; 这是一次大胜利<br>　　I'm Making A Note Here:&nbsp; 我要做点记录：<br>　　HUGE SUCCESS&nbsp;&nbsp;&nbsp;&nbsp; 巨大的成功！<br>　　It's hard to overstate&nbsp;&nbsp; 难以用语言表达<br>　　my satisfaction.&nbsp; 我的满足 <br>　　Aperture Science&nbsp;&nbsp; 光圈科技<br>　　We do what we must&nbsp;&nbsp; 我们的做我们必须做的<br>　　because we can.&nbsp;&nbsp; 因为我们可以做大<br>　　For the good of all of us.&nbsp;&nbsp;&nbsp;&nbsp; 为了我们美好的一切<br>　　Except the ones who are dead. 除过那些死掉的人</p>
<p>　　But there's no sense crying&nbsp; over every mistake.在每次犯错后，哭也是毫无意义的<br>　　You just keep on trying 继续尝试<br>　　till you run out of cake. 直到&#8221;用完蛋糕&#8220;(不懂，延伸的太厉害了)<br>　　And the Science gets done. 直到我们的科技完成<br>　　And you make a neat gun. 你充当一头小白鼠<br>　　For the people who are 为了那些仍然活着的人<br>　　Still Alive</p>
<p>　　I'm not even angry.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我甚至都不生气<br>　　I'm being so sincere right now.&nbsp;&nbsp;&nbsp;&nbsp; 我现在是如此的纯真<br>　　Even though you broke my heart.&nbsp;&nbsp; 哪怕你使我心碎<br>　　And killed me.&nbsp;&nbsp; 而且杀了我<br>　　And tore me to pieces.&nbsp; 将我撕成碎片<br>　　And threw every piece into a fire. 扔进烈火里<br>　　As they burned it hurt because&nbsp;&nbsp; 碎片依然燃烧的那么凶<br>　　I was so happy for you! 因为我为你如此高兴！<br>　　Now these points of data make a beautiful line.现在这些数据成了如此美力的一条线<br>　　And we're out of beta.&nbsp; 我们不再是试验产品了<br>　　We're releasing on time. 我们从时间获得解放<br>　　So I'm GLAD. I got burned. 我如此开心，我被烧了<br>　　Think of all the things we learned&nbsp;&nbsp; 想想我们学到的东西<br>　　for the people who are 为了那些仍然活着的人们<br>　　still alive.</p>
<p>　　Go ahead and leave me. 前进吧，留下我<br>　　I think I prefer to stay inside. 我想我还是愿意呆在里面<br>　　Maybe you'll find someone else 可能你会找到其他人帮你<br>　　to help you.<br>　　Maybe Black Mesa. . .&nbsp; 可能黑山基地 T<br>　　HAT WAS A JOKE. HAHA FAT CHANCE.也是一个骗局，哈哈，好机会。<br>　　Anyway. this cake is great. 不管怎么样，蛋糕很棒<br>　　It's so delicious and moist.&nbsp; 如此美味<br>　　Look at me still talking 看着我，当我还能说话的时候<br>　　When Theres Science to do. 当还有实验的时候，<br>　　When I look out there, 我望向窗外<br>　　it makes me GLAD I'm not you. 我真高兴，我不是你<br>　　I've experiments to run. 我还有实验要做<br>　　There is research to be done. 还有研究要做<br>　　On the people who are 为了那些依然活着的人<br>　　still alive.</p>
<p>　　And believe me I am still alive. 相信我，我还活着</p>
<p>　　I'm doing Science and I'm still alive. 我还活着，而且我在做实验</p>
<p>　　T feel FANTASTIC and I'm still alive. 如此难以置信，我还活着</p>
<p>　　While you're dying I'll be still. 当你快死了，我也活着</p>
<p>　　And when you're dead I will be still alive.当你死了，我依旧活着</p>
<p>　　STILL ALIVE&nbsp; 依旧活着</p>
<img src ="http://www.cnitblog.com/playerwing/aggbug/36049.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/playerwing/" target="_blank">Konami wiki</a> 2007-11-09 13:57 <a href="http://www.cnitblog.com/playerwing/archive/2007/11/09/36049.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Applying Decals to Arbitrary</title><link>http://www.cnitblog.com/playerwing/archive/2007/10/28/35484.html</link><dc:creator>Konami wiki</dc:creator><author>Konami wiki</author><pubDate>Sun, 28 Oct 2007 02:48:00 GMT</pubDate><guid>http://www.cnitblog.com/playerwing/archive/2007/10/28/35484.html</guid><wfw:comment>http://www.cnitblog.com/playerwing/comments/35484.html</wfw:comment><comments>http://www.cnitblog.com/playerwing/archive/2007/10/28/35484.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/playerwing/comments/commentRss/35484.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/playerwing/services/trackbacks/35484.html</trackback:ping><description><![CDATA[　　decal是我一直想实现的一个3D技术之一，在这里纠正一下我之前的一篇关于decal的文章，那个其实只是利用解决平面decal下z-fighting的问题！无法解决任意表明的问题！由于工作太忙一直没有去搞最后还是&#8220;挤牙膏&#8221;的方式挤出点时间来，抓起Game&nbsp;programming&nbsp;GemII开始了decal的实现，花了2天终于搞出来了！<br><br>　　最后再恶习一下！呵呵！<br><br>snapshot1:&nbsp;&nbsp;decal&nbsp;rendering&nbsp;in&nbsp;wireframe&nbsp;mode.<br><img height=469 alt="" src="http://www.cnitblog.com/images/cnitblog_com/playerwing/6449/o_decal1.jpg" width=580 border=0><br><br><br>snapshot2:&nbsp;decal&nbsp;rendering&nbsp;in&nbsp;solid&nbsp;mode&nbsp;(&nbsp;no&nbsp;texture )<br><img height=532 alt="" src="http://www.cnitblog.com/images/cnitblog_com/playerwing/6449/o_decal2.jpg" width=800 border=0><br><br>snapshot3&nbsp;&amp;&nbsp;4:&nbsp;decal&nbsp;rendering&nbsp;with&nbsp;texture<br><img height=600 alt="" src="http://www.cnitblog.com/images/cnitblog_com/playerwing/6449/o_decal3.jpg" width=731 border=0><br><br><br><img height=600 alt="" src="http://www.cnitblog.com/images/cnitblog_com/playerwing/6449/o_decal4.jpg" width=735 border=0>
<img src ="http://www.cnitblog.com/playerwing/aggbug/35484.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/playerwing/" target="_blank">Konami wiki</a> 2007-10-28 10:48 <a href="http://www.cnitblog.com/playerwing/archive/2007/10/28/35484.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Power of NVPerfHUD</title><link>http://www.cnitblog.com/playerwing/archive/2007/10/20/35117.html</link><dc:creator>Konami wiki</dc:creator><author>Konami wiki</author><pubDate>Sat, 20 Oct 2007 12:32:00 GMT</pubDate><guid>http://www.cnitblog.com/playerwing/archive/2007/10/20/35117.html</guid><wfw:comment>http://www.cnitblog.com/playerwing/comments/35117.html</wfw:comment><comments>http://www.cnitblog.com/playerwing/archive/2007/10/20/35117.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/playerwing/comments/commentRss/35117.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/playerwing/services/trackbacks/35117.html</trackback:ping><description><![CDATA[<p>　　最近研究了一下NVPerfHUD，感觉它太强大了！相比之下PIX要差点( just my peronal&nbsp;viewpoint )，个人认为这是PC 3D游戏开发者必备的东西，目前我很难找到形容词来赞美它（无情地赞美就免了， 呵呵）<br>　　最后放点图来show哈&nbsp; 恶习啊！！！=。=|||</p>
<p>&nbsp;</p>
<p><img height=615 alt="" src="http://www.cnitblog.com/images/cnitblog_com/playerwing/6402/o_1.jpg" width=800 border=0><br><img height=600 alt="" src="http://www.cnitblog.com/images/cnitblog_com/playerwing/6402/o_3.jpg" width=800 border=0></p>
<img src ="http://www.cnitblog.com/playerwing/aggbug/35117.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/playerwing/" target="_blank">Konami wiki</a> 2007-10-20 20:32 <a href="http://www.cnitblog.com/playerwing/archive/2007/10/20/35117.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Dynamic memory  VS  Static memory</title><link>http://www.cnitblog.com/playerwing/archive/2007/10/19/35074.html</link><dc:creator>Konami wiki</dc:creator><author>Konami wiki</author><pubDate>Fri, 19 Oct 2007 04:07:00 GMT</pubDate><guid>http://www.cnitblog.com/playerwing/archive/2007/10/19/35074.html</guid><wfw:comment>http://www.cnitblog.com/playerwing/comments/35074.html</wfw:comment><comments>http://www.cnitblog.com/playerwing/archive/2007/10/19/35074.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/playerwing/comments/commentRss/35074.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/playerwing/services/trackbacks/35074.html</trackback:ping><description><![CDATA[<font style="LINE-HEIGHT: 1.3em" color=#ff0000>This&nbsp;article&nbsp;is&nbsp;quoted&nbsp;from&nbsp;forums&nbsp;of&nbsp;GameDev.net(&nbsp;In&nbsp;fact&nbsp;it&nbsp;is&nbsp;a&nbsp;thread&nbsp;)</font><br><br>The&nbsp;&nbsp;question&nbsp;:&nbsp;<br>----------------------------------------------------------------------------------------------------------------------------------------------------------------&nbsp;<br><br>Hello&nbsp;all,&nbsp;<br><br>I&nbsp;am&nbsp;slightly&nbsp;unsure&nbsp;of&nbsp;which&nbsp;direction&nbsp;to&nbsp;take.&nbsp;I&nbsp;have&nbsp;a&nbsp;large&nbsp;array&nbsp;which&nbsp;will&nbsp;contain&nbsp;data&nbsp;pulled&nbsp;from&nbsp;a&nbsp;file.&nbsp;Like&nbsp;always,&nbsp;I&nbsp;proceeded&nbsp;to&nbsp;declare&nbsp;this&nbsp;array:&nbsp;<br><br><font style="LINE-HEIGHT: 1.3em" color=#3300ff><em><wbr>&nbsp;&nbsp;int&nbsp;array[1000];</em><wbr></font><wbr>&nbsp;<br><br>Then&nbsp;I&nbsp;remembered&nbsp;some&nbsp;code&nbsp;that&nbsp;I&nbsp;saw&nbsp;in&nbsp;a&nbsp;tutorial:&nbsp;<br><br><font style="LINE-HEIGHT: 1.3em" color=#3300ff><em><wbr>&nbsp;&nbsp;int&nbsp;*array;&nbsp;</em><wbr></font><wbr><br><em><wbr><font style="LINE-HEIGHT: 1.3em" color=#3300ff>&nbsp;&nbsp;array&nbsp;=&nbsp;new&nbsp;int[1000];</font><wbr>&nbsp;</em><wbr><br><br><br>I&nbsp;read&nbsp;up&nbsp;on&nbsp;it&nbsp;and&nbsp;it&nbsp;seems&nbsp;that&nbsp;dynamic&nbsp;memory&nbsp;goes&nbsp;on&nbsp;the&nbsp;heap,&nbsp;while&nbsp;static&nbsp;memory&nbsp;goes&nbsp;on&nbsp;the&nbsp;stack.&nbsp;I&nbsp;also&nbsp;learned&nbsp;that&nbsp;the&nbsp;heap&nbsp;is&nbsp;much&nbsp;larger&nbsp;than&nbsp;the&nbsp;stack.&nbsp;So&nbsp;my&nbsp;question&nbsp;is,&nbsp;which&nbsp;of&nbsp;the&nbsp;above&nbsp;methods&nbsp;is&nbsp;the&nbsp;best?&nbsp;And&nbsp;please&nbsp;correct&nbsp;me&nbsp;if&nbsp;I'm&nbsp;wrong&nbsp;on&nbsp;my&nbsp;new&nbsp;found&nbsp;knowledge.&nbsp;Thank&nbsp;you.&nbsp;<br><br><br>The&nbsp;&nbsp;answer:&nbsp;(&nbsp;selected&nbsp;)&nbsp;<br>----------------------------------------------------------------------------------------------------------------------------------------------------------------&nbsp;<br><br>Many&nbsp;people&nbsp;like&nbsp;to&nbsp;think&nbsp;there&nbsp;are&nbsp;2&nbsp;types&nbsp;of&nbsp;memory,&nbsp;stack&nbsp;and&nbsp;heap&nbsp;...&nbsp;because&nbsp;that's&nbsp;all&nbsp;most&nbsp;people&nbsp;have&nbsp;to&nbsp;think&nbsp;about&nbsp;most&nbsp;the&nbsp;time,&nbsp;there&nbsp;are&nbsp;really&nbsp;more&nbsp;than&nbsp;that.&nbsp;<br><br>There&nbsp;is&nbsp;data&nbsp;segment&nbsp;data&nbsp;(as&nbsp;mentioned&nbsp;by&nbsp;fpsgamer)&nbsp;and&nbsp;memory&nbsp;mapped&nbsp;i/o&nbsp;addresses&nbsp;(for&nbsp;instance&nbsp;when&nbsp;you&nbsp;write&nbsp;to&nbsp;video&nbsp;buffers&nbsp;or&nbsp;files,&nbsp;it&nbsp;is&nbsp;not&nbsp;using&nbsp;normal&nbsp;ram,&nbsp;it&nbsp;is&nbsp;just&nbsp;that&nbsp;certain&nbsp;addresses&nbsp;are&nbsp;mapped&nbsp;by&nbsp;the&nbsp;os&nbsp;to&nbsp;write&nbsp;to&nbsp;certain&nbsp;destinations).&nbsp;<br><br>between&nbsp;the&nbsp;3&nbsp;you&nbsp;can&nbsp;control:&nbsp;<br><br><font style="LINE-HEIGHT: 1.3em" color=#3300ff><em><wbr>//&nbsp;without&nbsp;initialization&nbsp;</em><wbr></font><wbr><br><font style="LINE-HEIGHT: 1.3em" color=#3300ff><em><wbr>int&nbsp;dataSegment[1000];&nbsp;</em><wbr></font><wbr><br><font style="LINE-HEIGHT: 1.3em" color=#3300ff><em><wbr>int&nbsp;main()&nbsp;</em><wbr></font><wbr><br><font style="LINE-HEIGHT: 1.3em" color=#3300ff><em><wbr>{&nbsp;</em><wbr></font><wbr><br><font style="LINE-HEIGHT: 1.3em" color=#3300ff><em><wbr>&nbsp;&nbsp;int&nbsp;stack[1000];&nbsp;</em><wbr></font><wbr><br><font style="LINE-HEIGHT: 1.3em" color=#3300ff><em><wbr>&nbsp;&nbsp;int&nbsp;*heap;&nbsp;</em><wbr></font><wbr><br><font style="LINE-HEIGHT: 1.3em" color=#3300ff><em><wbr>&nbsp;&nbsp;heap&nbsp;=&nbsp;new&nbsp;int[1000];&nbsp;</em><wbr></font><wbr><br><font style="LINE-HEIGHT: 1.3em" color=#3300ff><em><wbr>}&nbsp;</em><wbr></font><wbr><br><font style="LINE-HEIGHT: 1.3em" color=#3300ff><em><wbr>//&nbsp;with&nbsp;initialization&nbsp;</em><wbr></font><wbr><br><font style="LINE-HEIGHT: 1.3em" color=#3300ff><em><wbr>int&nbsp;dataSegmentB[4]&nbsp;=&nbsp;{56,&nbsp;23,&nbsp;11,&nbsp;945};&nbsp;</em><wbr></font><wbr><br><font style="LINE-HEIGHT: 1.3em" color=#3300ff><em><wbr>int&nbsp;mainB()&nbsp;</em><wbr></font><wbr><br><font style="LINE-HEIGHT: 1.3em" color=#3300ff><em><wbr>{&nbsp;</em><wbr></font><wbr><br><font style="LINE-HEIGHT: 1.3em" color=#3300ff><em><wbr>&nbsp;&nbsp;int&nbsp;stackB[4]&nbsp;=&nbsp;{56,&nbsp;23,&nbsp;11,&nbsp;945};&nbsp;</em><wbr></font><wbr><br><font style="LINE-HEIGHT: 1.3em" color=#3300ff><em><wbr>&nbsp;&nbsp;int&nbsp;*heapB;&nbsp;</em><wbr></font><wbr><br><font style="LINE-HEIGHT: 1.3em" color=#3300ff><em><wbr>&nbsp;&nbsp;heap&nbsp;=&nbsp;new&nbsp;int[4];&nbsp;</em><wbr></font><wbr><br><font style="LINE-HEIGHT: 1.3em" color=#3300ff><em><wbr>&nbsp;&nbsp;heapB[0]&nbsp;=&nbsp;56;&nbsp;</em><wbr></font><wbr><br><font style="LINE-HEIGHT: 1.3em" color=#3300ff><em><wbr>&nbsp;&nbsp;heapB[1]&nbsp;=&nbsp;23;&nbsp;</em><wbr></font><wbr><br><font style="LINE-HEIGHT: 1.3em" color=#3300ff><em><wbr>&nbsp;&nbsp;heapB[2]&nbsp;=&nbsp;11;&nbsp;</em><wbr></font><wbr><br><font style="LINE-HEIGHT: 1.3em" color=#3300ff><em><wbr>&nbsp;&nbsp;heapB[3]&nbsp;=&nbsp;945;&nbsp;</em><wbr></font><wbr><br><font style="LINE-HEIGHT: 1.3em" color=#3300ff><em><wbr>}</em><wbr></font><wbr>&nbsp;<br><br>The&nbsp;dataSegment&nbsp;normallys&nbsp;grows&nbsp;the&nbsp;size&nbsp;of&nbsp;your&nbsp;executable&nbsp;to&nbsp;hold&nbsp;it.&nbsp;This&nbsp;data&nbsp;will&nbsp;then&nbsp;be&nbsp;loaded&nbsp;in&nbsp;main&nbsp;memory&nbsp;when&nbsp;the&nbsp;program&nbsp;loads,&nbsp;along&nbsp;with&nbsp;the&nbsp;rest&nbsp;of&nbsp;the&nbsp;application.&nbsp;<br><br>The&nbsp;stack&nbsp;values&nbsp;are&nbsp;pushed&nbsp;onto&nbsp;the&nbsp;stack&nbsp;when&nbsp;the&nbsp;function&nbsp;is&nbsp;called&nbsp;and&nbsp;poped&nbsp;off&nbsp;when&nbsp;it&nbsp;returns.&nbsp;if&nbsp;a&nbsp;function&nbsp;is&nbsp;in&nbsp;the&nbsp;call&nbsp;stack&nbsp;more&nbsp;than&nbsp;once&nbsp;(ie&nbsp;recursion)&nbsp;than&nbsp;there&nbsp;is&nbsp;memory&nbsp;in&nbsp;the&nbsp;stack&nbsp;for&nbsp;each&nbsp;instance,&nbsp;and&nbsp;that&nbsp;memory&nbsp;may&nbsp;of&nbsp;course&nbsp;have&nbsp;different&nbsp;values.&nbsp;<br><br>paramters&nbsp;to&nbsp;function&nbsp;are&nbsp;passed&nbsp;on&nbsp;the&nbsp;stack.&nbsp;In&nbsp;fact&nbsp;the&nbsp;purpose&nbsp;of&nbsp;the&nbsp;stack&nbsp;is&nbsp;to&nbsp;hold&nbsp;the&nbsp;return&nbsp;address&nbsp;of&nbsp;the&nbsp;function,&nbsp;its&nbsp;parameters,&nbsp;and&nbsp;its&nbsp;local&nbsp;variables.&nbsp;<br><br>there&nbsp;is&nbsp;a&nbsp;stack&nbsp;PER&nbsp;THREAD.&nbsp;<br><br>The&nbsp;heap&nbsp;values&nbsp;are&nbsp;allocated&nbsp;by&nbsp;the&nbsp;language&nbsp;or&nbsp;operating&nbsp;system&nbsp;from&nbsp;a&nbsp;dynamic&nbsp;pool&nbsp;of&nbsp;memory.&nbsp;The&nbsp;heap&nbsp;is&nbsp;shared&nbsp;by&nbsp;all&nbsp;threads&nbsp;in&nbsp;a&nbsp;process&nbsp;(in&nbsp;most&nbsp;normal&nbsp;OSes)&nbsp;so&nbsp;it&nbsp;can&nbsp;be&nbsp;slower&nbsp;to&nbsp;use&nbsp;heap&nbsp;memory&nbsp;in&nbsp;multithread&nbsp;capable&nbsp;apps&nbsp;because&nbsp;they&nbsp;must&nbsp;use&nbsp;locks&nbsp;to&nbsp;protect&nbsp;allocations&nbsp;and&nbsp;returns&nbsp;that&nbsp;use&nbsp;the&nbsp;heap.&nbsp;Many&nbsp;advanced&nbsp;systems&nbsp;have&nbsp;been&nbsp;built&nbsp;to&nbsp;have&nbsp;block&nbsp;allocating&nbsp;heaps,&nbsp;or&nbsp;thread&nbsp;specific&nbsp;heaps&nbsp;to&nbsp;eliminate&nbsp;various&nbsp;costs&nbsp;when&nbsp;it&nbsp;is&nbsp;important.&nbsp;<br><br>In&nbsp;general&nbsp;the&nbsp;cost&nbsp;of&nbsp;accessing&nbsp;any&nbsp;memory&nbsp;once&nbsp;allocated&nbsp;is&nbsp;not&nbsp;at&nbsp;all&nbsp;based&nbsp;on&nbsp;stack&nbsp;/&nbsp;data&nbsp;segment&nbsp;/&nbsp;heap&nbsp;...&nbsp;but&nbsp;instead&nbsp;is&nbsp;based&nbsp;on&nbsp;whether&nbsp;or&nbsp;not&nbsp;the&nbsp;memory&nbsp;is&nbsp;currently&nbsp;in&nbsp;the&nbsp;CPU&nbsp;cache,&nbsp;if&nbsp;not,&nbsp;it&nbsp;causes&nbsp;a&nbsp;cache&nbsp;miss.&nbsp;This&nbsp;is&nbsp;based&nbsp;almost&nbsp;exclusively&nbsp;on&nbsp;how&nbsp;recently&nbsp;the&nbsp;memory&nbsp;was&nbsp;accessed,&nbsp;so&nbsp;hitting&nbsp;the&nbsp;same&nbsp;area&nbsp;in&nbsp;the&nbsp;heap&nbsp;500&nbsp;times&nbsp;in&nbsp;a&nbsp;row&nbsp;is&nbsp;no&nbsp;different&nbsp;than&nbsp;hitting&nbsp;the&nbsp;stack&nbsp;500&nbsp;times&nbsp;in&nbsp;a&nbsp;row.&nbsp;But&nbsp;hitting&nbsp;40&nbsp;variables&nbsp;right&nbsp;next&nbsp;to&nbsp;each&nbsp;other&nbsp;in&nbsp;the&nbsp;stack&nbsp;is&nbsp;less&nbsp;likely&nbsp;to&nbsp;use&nbsp;many&nbsp;data&nbsp;pages&nbsp;of&nbsp;cache&nbsp;than&nbsp;hitting&nbsp;40&nbsp;variables&nbsp;allocated&nbsp;on&nbsp;the&nbsp;heap&nbsp;...&nbsp;especially&nbsp;if&nbsp;those&nbsp;variables&nbsp;we're&nbsp;allocated&nbsp;at&nbsp;different&nbsp;times&nbsp;in&nbsp;the&nbsp;application,&nbsp;and&nbsp;vary&nbsp;in&nbsp;size,&nbsp;etc.&nbsp;<br><br>The&nbsp;stack&nbsp;is&nbsp;often&nbsp;very&nbsp;limited&nbsp;in&nbsp;size&nbsp;(like&nbsp;8kb&nbsp;on&nbsp;many&nbsp;platforms),&nbsp;so&nbsp;it&nbsp;is&nbsp;a&nbsp;VERY&nbsp;bad&nbsp;choice&nbsp;to&nbsp;use&nbsp;the&nbsp;stack&nbsp;for&nbsp;large&nbsp;data.&nbsp;Although&nbsp;the&nbsp;normal&nbsp;reason&nbsp;you&nbsp;choose&nbsp;between&nbsp;heap&nbsp;and&nbsp;stack&nbsp;is&nbsp;not&nbsp;size,&nbsp;but&nbsp;object&nbsp;lifetime.&nbsp;If&nbsp;the&nbsp;variable&nbsp;needs&nbsp;to&nbsp;exist&nbsp;only&nbsp;for&nbsp;the&nbsp;life&nbsp;of&nbsp;the&nbsp;function&nbsp;-&nbsp;and&nbsp;is&nbsp;known&nbsp;at&nbsp;compile&nbsp;time,&nbsp;it&nbsp;should&nbsp;be&nbsp;put&nbsp;on&nbsp;the&nbsp;stack&nbsp;(unless&nbsp;it&nbsp;is&nbsp;very&nbsp;large).&nbsp;If&nbsp;it&nbsp;needs&nbsp;to&nbsp;exist&nbsp;for&nbsp;longer&nbsp;than&nbsp;the&nbsp;life&nbsp;of&nbsp;the&nbsp;function&nbsp;it&nbsp;cannot&nbsp;be&nbsp;put&nbsp;on&nbsp;the&nbsp;stack,&nbsp;so&nbsp;only&nbsp;heap&nbsp;and&nbsp;data&nbsp;segment&nbsp;are&nbsp;possible.&nbsp;data&nbsp;segment&nbsp;values&nbsp;are,&nbsp;by&nbsp;definition,&nbsp;alive&nbsp;for&nbsp;the&nbsp;entire&nbsp;application&nbsp;and&nbsp;are&nbsp;effectively&nbsp;permanent&nbsp;globals&nbsp;/&nbsp;statics.&nbsp;<br>
<img src ="http://www.cnitblog.com/playerwing/aggbug/35074.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/playerwing/" target="_blank">Konami wiki</a> 2007-10-19 12:07 <a href="http://www.cnitblog.com/playerwing/archive/2007/10/19/35074.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Video memory, AGP memory and System memory (转载， 原文：http://www.gamedev.net/community/forums/topic.asp?topic_id=388869 )</title><link>http://www.cnitblog.com/playerwing/archive/2007/10/05/34407.html</link><dc:creator>Konami wiki</dc:creator><author>Konami wiki</author><pubDate>Fri, 05 Oct 2007 06:50:00 GMT</pubDate><guid>http://www.cnitblog.com/playerwing/archive/2007/10/05/34407.html</guid><wfw:comment>http://www.cnitblog.com/playerwing/comments/34407.html</wfw:comment><comments>http://www.cnitblog.com/playerwing/archive/2007/10/05/34407.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/playerwing/comments/commentRss/34407.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/playerwing/services/trackbacks/34407.html</trackback:ping><description><![CDATA[<span>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: #333333; LINE-HEIGHT: 150%; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">Those two identifiers are hints to the driver for how the buffer will be used, to optimize how the card accesses the data. They make sense even without AGP memory.<br><br>On systems with AGP memory, there are three classes of memory:<br><br>1) System Memory. This is cached, and reasonably fast to read from and write to with the CPU. However, it typically needs an additional copy before the graphics card can use it. System and scratch pool memory goes here.<br><br>2) AGP Memory. This is still CPU-local RAM, but it is not cached. This means that it's slow to read from, and it's slow to write to, UNLESS you write sequentially, without doing too much other memory traffic inbetween, and overwrite every byte, so that the write combiners don't need to fetch lines from RAM to do a combine. Thus, generating software-transformed vertices as a stream into this buffer might still be fast. For the GPU, the AGP memory is directly accessible, so no additional copy is needed. Dynamic pool memory goes here.<br><br>3) Video Memory. This is RAM that's local to the GPU. It typically has insanely high throughput. It is accessible over the bus for the CPU, but going over the bus is really slow; typically both for reading and for writing. Thus writing directly into this memory (or even worse, reading out of it), is not recommended. Default pool memory goes here.<br><br>On systems with PCI-Express, some of the AGP vs system memory differences are reduced, but the usage hints you're giving the driver ("I will change the data by writing it sequentially" vs "I will not change the data much") are still useful for optimizing performance.<br><br>Video memory is the memory chips physically located on the card. The card can easily access this memory, while reading it from the CPU is extremely slow.<br><br>AGP memory a part of your main memory on the motherboard that has been set aside for talking to the graphics card. The card and your CPU can access this memory at a decent speed.<br><br><a href="http://www.adriansrojakpot.com/Speed_Demonz/New_BIOS_Guide/AGP_Aperture_Size.htm"><span style="LINE-HEIGHT: 150%; mso-bidi-font-size: 12.0pt"><u><font color=#0000ff>This page</font></u></span></a>shows that your BIOS "AGP aperture size" controls the size of your AGP memory, and explains how "reducing the AGP aperture size won't save you any RAM. Again, what setting the AGP aperture size does is limit the amount of RAM the AGP bus can appropriate when it needs to. It is not used unless absolutely necessary. So, setting a 64MB AGP aperture doesn't mean 64MB of your RAM will be used up as AGP memory. It will only limit the maximum amount that can be used by the AGP bus to 64MB (with a usable AGP memory size of only 26MB)."<br><br>1) </span><em><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: #333333; LINE-HEIGHT: 150%; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体; mso-bidi-font-size: 12.0pt; mso-font-kerning: 0pt">video memory</span></em><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: #333333; LINE-HEIGHT: 150%; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> can mean one of two things depending on the context the term is used in:<br><br>a. video memory is generally any memory which is used by the graphics chip.<br><br>b. video memory (correctly </span><em><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: #333333; LINE-HEIGHT: 150%; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体; mso-bidi-font-size: 12.0pt; mso-font-kerning: 0pt">"local video memory"</span></em><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: #333333; LINE-HEIGHT: 150%; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">) is memory that exists on the graphic card itself (i.e. RAM chips that live on the graphics card, they are 'local' to the graphics chip).<br><br><br>2) AGP memory is main memory on your system motherboard that has been specially assigned for graphics use. The "AGP Aperture" setting in your system BIOS controls this assignment. The more you have assigned for AGP use, the less you have for general system use. AGP memory is sometimes also known as "non-local video memory".<br><br><br><st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="3" UnitName="a">3a</st1:chmetcnv>) 'Local' video memory is very fast for the graphics chip to read from and write to because it is 'local' to the graphics chip.<br><br>3b) 'Local' video memory is extremely slow to read from using for the system CPU, and reasonably slow to write to using the system CPU. <br>This is for a number of reasons; partly because the memory is physically on a different board (the graphics card) to the CPU (i.e. it's not 'local' for the CPU); partly because that memory isn't cached at all for reads using the CPU, and only burst cached for writes; partly due to the way data transfers over bus standards such as AGP must be done.<br><br><br><st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="4" UnitName="a">4a</st1:chmetcnv>) AGP memory is reasonably fast for the graphics chip to read from or write to, but not as fast as local video memory.<br><br>4b) AGP memory is fairly slow to read from using the system CPU because it is marked as "Write Combined" so any reads don't benefit from the L2 and L1 caches (i.e. each read is effectively a cache-miss). <br>AGP memory is however faster than local video memory to read from using the CPU since it is local to the CPU.<br><br><st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="4" UnitName="C">4c</st1:chmetcnv>) AGP memory is reasonably fast to write to using the system CPU. Although not fully cached, "Write Combined" memory uses a small buffer that collects sequential writes to memory (32 or 64 bytes IIRC) and writes them out in one go. This is why sequential access of vertex data using the CPU is preferable for performance.<br><br><br>5) D3DUSAGE_DYNAMIC is only a </span><strong><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: #333333; LINE-HEIGHT: 150%; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体; mso-bidi-font-size: 12.0pt; mso-font-kerning: 0pt">hint</span></strong><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: #333333; LINE-HEIGHT: 150%; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> to the display driver about how you intend using that resource, </span><em><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: #333333; LINE-HEIGHT: 150%; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体; mso-bidi-font-size: 12.0pt; mso-font-kerning: 0pt">usually</span></em><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: #333333; LINE-HEIGHT: 150%; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> it </span><em><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: #333333; LINE-HEIGHT: 150%; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体; mso-bidi-font-size: 12.0pt; mso-font-kerning: 0pt">will</span></em><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: #333333; LINE-HEIGHT: 150%; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> give you AGP memory, but it isn't guaranteed (so don't rely it!).<br><br><br>6) Generally, for vertex buffers which you need to Lock() and update using the CPU regularly at runtime should be D3DUSAGE_DYNAMIC, and all others should be static.<br><br><br>7) Graphics drivers use techniques such as "buffer renaming" where multiple copies of the buffer are created and cycled through to reduce the chance of stalls when dynamic resources are locked. This is why it's essential to use the D3DLOCK_DISCARD and D3DLOCK_NOOVERWRITE locking flags correctly if you want good performance. It's also one of the many reasons you shouldn't rely on the data pointer from a Lock() after the resource has been unlocked.<br><br><br>8) General advice for good performance:<br>- treat all graphics resources as write-only for the CPU, particularly those in local video memory. CPU reads from graphics resources is a recipe for slowness.<br><br>- CPU writes to locked graphics resources should be done sequentially.<br><br>- it's better to write all of a vertex out to memory with the CPU than it is to skip elements of it. Skipping can harm the effectiveness of write combining, and even cause hidden reads in some situations (and reads are bad - see above).<br><br><br>since the "local video memory" is fast for video card to manipulate, and the video card dedicated to GRAPHICS PROCESS,why bother to use the "AGP memory"?<br>is that only because the "local video memory" may be not enough for graphic data storage?<br>what role does the CPU play in the process of graphics??<br><br>Yes. That's one of the main reasons. AGP comes from a time (~10 years ago!) when a typical graphics card would have, say, 2MB of local video memory and a typical PC system had 64-128MB of main system memory, so it made sense to set some system memory aside for situations where there wasn't enough local memory.<br><br>In these days of monster graphics cards with 512MB of local video memory, it's less likely used as an overflow.<br><br><br>Another reason is dynamic graphics data - any data that needs to be regularly modified with the CPU is usually better off in AGP memory (it's write combined, but it's local to the CPU too, so uses less CPU time to access)<br>Not very much these days. Mostly application-side jobs like writing vertex data into locked buffers, object culling, traversing scene graphs, loading resources into main memory, things like that. <br>On the D3D and device driver side: handling the D3D API, swizzling and other conversion when some types of resources are locked/unlocked [I believe some GPUs can even do their own swizzling now though], and setting up the command buffer for the GPU.<br><br>Before hardware T&amp;L, the CPU also handled all vertex processing.<br><br>The fact that modern GPUs now handle so much of the graphics pipeline makes avoiding unnecessary serialization between CPU and GPU all the more important (i.e. stalls where one has a resource locked and the other wants to use it), thus things like buffer renaming. Serialization between CPU and GPU throws away the GPUs processing ability.<o:p></o:p></span></p>
<br></span>
<img src ="http://www.cnitblog.com/playerwing/aggbug/34407.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/playerwing/" target="_blank">Konami wiki</a> 2007-10-05 14:50 <a href="http://www.cnitblog.com/playerwing/archive/2007/10/05/34407.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>