• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
schupf

Texture Pitch

9 posts in this topic

Hello, I need to create two float textures which have exactly the same values (except that one texture has usage DYNAMIC and the second STAGING). First I create the DYNAMIC texture:
	D3D10_TEXTURE2D_DESC alphaMapDesc;
ZeroMemory(&alphaMapDesc, sizeof(alphaMapDesc));
alphaMapDesc.Width		= verticesAlongSide;
alphaMapDesc.Height		= verticesAlongSide;
alphaMapDesc.MipLevels		= alphaMapDesc.ArraySize = 1;
alphaMapDesc.Format		= DXGI_FORMAT_R32G32B32A32_FLOAT; 
alphaMapDesc.SampleDesc.Count	= 1;
alphaMapDesc.SampleDesc.Quality = 0;
alphaMapDesc.Usage		= D3D10_USAGE_DYNAMIC;
alphaMapDesc.BindFlags		= D3D10_BIND_SHADER_RESOURCE;
alphaMapDesc.CPUAccessFlags	= D3D10_CPU_ACCESS_WRITE;
alphaMapDesc.MiscFlags		= 0;
d3d10Device->CreateTexture2D(&alphaMapDesc, NULL, &alphaMap);

Then I create the second (STAGING) texture filled with 0's with exactly the same values:
alphaMapDesc.Usage =  D3D10_USAGE_STAGING;
alphaMapDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
alphaMapDesc.BindFlags	    = 0;

D3D10_SUBRESOURCE_DATA initialData;
float* texelData = new float[verticesAlongSide * verticesAlongSide * 4];
ZeroMemory(texelData, verticesAlongSide * verticesAlongSide * 4 * sizeof(float));
initialData.pSysMem		= texelData;
initialData.SysMemPitch		= verticesAlongSide * 4 * sizeof(float);
initialData.SysMemSlicePitch	= 0;
d3d10Device->CreateTexture2D(&alphaMapDesc, &initialData, &alphaMapConsistent);

I thought the SysMemPitch is the width of one row in bytes, so I set it to verticesAlongSide * 4 * sizeof(float) (the texture has a width of verticesAlongSide texels and every texel has four floats). Since both textures are basically the same I assumed that they both have the same pitch values. Just to be sure I checked the pitch of the first texture:
alphaMap->Map(D3D10CalcSubresource(0, 0, 1), D3D10_MAP_WRITE_DISCARD, 0, &mappedAlphaMap);
UINT pitch = mappedAlphaMap.RowPitch;

But surprisingly they have different pitch values! The second texture (where I manually set the pitch) has a pitch of 8208 (verticesAlongSide = 513, thus: 513*4*4) and the first texture has a pitch of 16384. Does anyknow know why the first texture has a pitch of 16384? Is my calculated pitch of 8208 wrong?
0

Share this post


Link to post
Share on other sites
The pitch is the distance from the begin of one line to the next line. It’s not necessary equal to the size of a line as the hardware can decide to use a different data layout.

To make things even more complicate you should only write to the bytes that are part of the actual texture as the graphics adapter may use the padding bytes for other things.
0

Share this post


Link to post
Share on other sites
Hm, well ok, so DX adds some bytes at the end of each line and so I get the "strange" pitch of 16384 for the first texture.

But is my pitch value for the second texture correct? (verticesAlongSide * 4 * sizeof(float) for a texture of size verticesAlongSide x verticesAlongSide with R32G32B32A32_FLOAT)?
0

Share this post


Link to post
Share on other sites
Quote:
Original post by Demirug
It’s not the pitch it’s the size of a line you have calculated.

Yes, because if these "extra bytes" at the end of each line is 0 then the pitch size is equal to the size of on line. How should I know how many "extra bytes" DX10 expects? If my pitch calculation is wrong, how would the correct calculation look like?
0

Share this post


Link to post
Share on other sites
If you provide the data during creation or an UpdateResource Direct3D will use the pitch that you set. If the internal pitch is different from your pitch the runtime/driver is responsible to copy your data to the right places. Therefore if you use the line size as pitch during resource creation or updating you are fine. Direct3D just offers you the option to use a different pitch in the case your data is padded.
0

Share this post


Link to post
Share on other sites
Hm, I made 2 tests:
I created the texture with a pitch of 8208 (verticesAlongSide *4 * sizeof(float)), then I called Map() on the texture and read the value of RowPitch. It is: 8256.

Then I created the texture with exact the same settings, but this time I (randomly) set the pitch to 1 (which makes no sense at all). Again I mapped the texture and read back the RowPitch and it was again 8256.

So what is the sense of parameter SysMemPitch if DirectX calculates its own pitch anyway? (It seems like I could you any value)
0

Share this post


Link to post
Share on other sites
Quote:
Original post by schupf
So what is the sense of parameter SysMemPitch if DirectX calculates its own pitch anyway? (It seems like I could you any value)

Let's say you have a 512x512 image, but you want to create a 256x256 texture from the top left part.

The trivial option is to create a new 256x256 array, and copy your data to it. Then you'd lock the destination texture, and copy the data to it in one memcpy. The pitch would then be 256xpixelSize, but you had to copy your data once just to get it to the right size. Of course, there's a much simpler way.

If you pass a pointer to the start of the first row, and provide a pitch of 512*pixelsize, DX will automagically load just the top left part. Why? because each row is 256 pixels wide. When DX finishes reading the first row, it will skip 512*pixelSize bytes forward (the pitch you provided), landing at the start of the second row in the bigger source image.
By the time it finishes 256 rows, it would have read the entire top left corner of the source image, and copied it to the new texture.

This works great for any part of a bigger image, not just the top left. And, in fact, this is exactly why DX returns a pitch value when you map a texture. If you map just part of the texture, the pitch returned allows DX to let you modify the memory directly where it is. If DX had to return all memory in a single consecutive unit, it would have had to copy the data to a new array, give it to you, and then copy it back to the right place after an Unmap. This is clearly very wasteful, and that's what memory pitch values are for, both when you pass data to DX and when DX returns data for you.

Hope this helps.
0

Share this post


Link to post
Share on other sites
Ok things getting clearer now!

Quote:
If you pass a pointer to the start of the first row, and provide a pitch of 512*pixelsize, DX will automagically load just the top left part. Why? because each row is 256 pixels wide. When DX finishes reading the first row, it will skip 512*pixelSize bytes forward (the pitch you provided), landing at the start of the second row in the bigger source image.
By the time it finishes 256 rows, it would have read the entire top left corner of the source image, and copied it to the new texture.

Just to be sure: You mean the following:
D3D10_TEXTURE2D_DESC tex256; // 256 x 256 destination texture
tex256.Width = tex256.Height = 256;
//... set all other parameters
D3D10_SUBRESOURCE_DATA initialData;
initialData.pSysMem = texelDataFrom512x512Texture; // This is a pointer to the data of the 512 x 512 source texture received by calling Map() on the 512x512 texture
initialData.SysMemPitch = 512 * texelData512x512;
initialData.SysMemSlicePitch = 0;
d3d10Device->CreateTexture2D(&tex256, &initialData, &texture256);


And DX will basically perform this operation (pseudocode):
for(int i=0; i < tex256.Height; i++) {
memcpy(tex256.texelData + i*tex256.Width*tex256TexelSize,
tex512.texelData + i*initialData.SysMemPitch, tex256.Width*tex256TexelSize);



So it reads "byte size of one row of the destination texture" bytes of the source texture, copies it to the source texture and then advances the read pointer (of the source texture) about the delivered pitch of the structure D3D10_SUBRESOURCE_DATA (here 512*texelSizeDestTexture) to read the next line and so on. Is this correct?

Quote:
This works great for any part of a bigger image, not just the top left.

I don't understand how you could read any part of a bigger texture except the top left part. I mean in order to read the top right part DirectX had to start reading in the middle of the first row but I cant see any way to tell DX to do so?!

Quote:
And, in fact, this is exactly why DX returns a pitch value when you map a texture. If you map just part of the texture, the pitch returned allows DX to let you modify the memory directly where it is. If DX had to return all memory in a single consecutive unit, it would have had to copy the data to a new array, give it to you, and then copy it back to the right place after an Unmap. This is clearly very wasteful, and that's what memory pitch values are for, both when you pass data to DX and when DX returns data for you.

I understood that the pitch can be used to copy a part of a bigger texture to a new smaller texture but I still can't see the sense of the pitch AFTER the copy is executed. All I need are the texels so why should I need these "extra bytes" at the end of each row after the texture is created?
0

Share this post


Link to post
Share on other sites
What about the pitch when I use block compression. Is it the size of one row of 4x4 blocks, or what?
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0