Skip to main content
GameDev.net gamedev.net
🔒 Locked

[SlimDX] Access Texture data

Started by Kevin31 May 15, 2009 at 7:16 AM 15 replies 4.4k views
Original Post
Kevin31
Kevin31
Hi, I'm using SlimDX in combination with DX10 and I'm trying to write a Terrain class, therefore I need access to the heightmap data of the texture. In XNA it was easy, but in SlimDX it seems more difficult... I tried this:

//Constructor
public Terrain(Device device, string heightMapAsset) {
	Texture2D tex = Texture2D.FromFile(device, heightMapAsset);
	heightData = new float[tex.Description.Width, tex.Description.Height];
	//Exception in this line:
        DataRectangle data = tex.Map(0, MapMode.WriteDiscard, MapFlags.None);
}
But it doesn't work...I get: E_INVALIDARG: An invalid parameter was passed to the returning function (-2147024809) In the DX SDK Docu it says that I should call D3D10CalcSubresource() for the first argument...but where is the function in slimdx?? By the way, are there any tutorials for DX10 with SlimDX available?
Kevin31
Kevin31
Has nobody any idea???
I'm really desperate, because there are nearly no tutorials or documentation for SlimDX available... :(
nobodynews
nobodynews
If you examined the function D3D10CalcSubresource in the docs you'd see that this is said about it:
ParametersMipSlice[in] A zero-based index into an array of subtextures; 0 indicates the first, most detailed subtexture (or mipmap level).ArraySlice[in] The zero-based index of the first texture to use (in an array of textures).MipLevels[in] Number of mipmap levels (or subtextures) to use.Return ValuesThe index which equals MipSlice + (ArraySlice * MipLevels)
With emphasis on the "Return Values". Essentially, that function just returns that calculated value. However, I have looked at the SlimDX code here and the Map member function actually uses D3D10CalcSubresource internally, like so:
int subresource = D3D10CalcSubresource( mipSlice, 0, Description.MipLevels );
I'll give the full definition:
SlimDX::DataRectangle^ Texture2D::Map( int mipSlice, MapMode mode, MapFlags flags ){	int subresource = D3D10CalcSubresource( mipSlice, 0, Description.MipLevels );	int mipHeight = GetMipSize( mipSlice, Description.Height );	D3D10_MAPPED_TEXTURE2D mappedRect;	if( RECORD_D3D10( InternalPointer->Map( subresource, static_cast<D3D10_MAP>( mode ), static_cast<UINT>( flags ), &mappedRect ) ).IsFailure )		return nullptr;	int lockedSize = mipHeight * mappedRect.RowPitch;	return gcnew SlimDX::DataRectangle( mappedRect.RowPitch, gcnew DataStream( mappedRect.pData, lockedSize, true, true, false ) );}

I can't see why this would fail from your passed in parameters, but while looking for the error message I found this post describing how to get more debugging information with SlimDX. Hope this helps.
C++: A Dialog | C++0x Features: Part1 (lambdas, auto, static_assert) , Part 2 (rvalue references) ,
Kevin31
Kevin31
Thanks for reply.
Now I enabled unmanaged code debugging in VS, and there is the following error in the output window:

D3D10: ERROR: ID3D10Texture2D::Map: Map cannot be called with MAP_WRITE_DISCARD access, because the Resource was not created with the D3D10_CPU_ACCESS_WRITE flag. [ RESOURCE_MANIPULATION ERROR #307: TEXTURE2D_MAP_INVALIDMAPTYPE ]

But how can I load a texture with CPU_ACCESS_WRITE flags?
jpetrie
jpetrie
There should be an overload of FromFile() that takes an ImageLoadInformation. This structure allows you to specify (among other things) the CPU access flags.
Kevin31
Kevin31
Ok, do I have to set all properties?
Now I have:

public Terrain(Device device, string heightMapAsset) {	ImageLoadInformation info = new ImageLoadInformation();	info.CpuAccessFlags = CpuAccessFlags.Write;        //Exception at this line:	Texture2D tex = Texture2D.FromFile(device, heightMapAsset, info);	heightData = new float[tex.Description.Width, tex.Description.Height];	DataRectangle data = tex.Map(0, MapMode.WriteDiscard, MapFlags.None);}


But I still get a exception...
If I have to set all properties of the ImageLoadInformation, how do I get dynamicly for example the height/width of the heightmap (except of loading the texturing two times and use the descritpion).
nobodynews
nobodynews
I haven't found the solution, but I did find out what the problem was. The static member function FromFile uses the more generic Texture member function FromFile which, in turn, calls the Texture member function ConstructFromFile which just uses the D3DX function D3DX10CreateTextureFromFile called like so:

HRESULT hr = D3DX10CreateTextureFromFile( device->InternalPointer, pinnedName, 0, 0, &resource, 0 );

The declaration for this function is:
HRESULT D3DX10CreateTextureFromFile(  ID3D10Device *pDevice,  LPCTSTR pSrcFile,  D3DX10_IMAGE_LOAD_INFO *pLoadInfo,  ID3DX10ThreadPump *pPump,  ID3D10Resource **ppTexture,  HRESULT *pHResult);

The third member controls the flags you are interested in. SlimDX passes in 0 which means 'read the characteristics of a texture when the texture is loaded'. I am not sure it is possible to do what you want in SlimDX directly. Try asking in #gamedev IRC chat maybe someone there will be able to help you.
C++: A Dialog | C++0x Features: Part1 (lambdas, auto, static_assert) , Part 2 (rvalue references) ,
jpetrie
jpetrie
Quote:
Original post by Kevin31
Ok, do I have to set all properties?

Probably. ImageLoadInformation is a value type, so default-constructing it will simply zero every field -- that will result in values that are usually not what you want.

Quote:

If I have to set all properties of the ImageLoadInformation, how do I get dynamicly for example the height/width of the heightmap

Setting all the ImageLoadInformation properties and getting the width and height of the file (or resulting texture) are different things. If you only want the width/height so that you can pass them to ImageLoadInformation's property setters, you can instead use ImageLoadInformation::FileDefaultValue, which is the equivalent to D3DX10_DEFAULT, which will pick up the value from the file itself.

Once created, the "texture" has no width or height, but individually surfaces (mip levels) within the texture will. The width and height of a texture are commonly abstracted as the width and height of the first or only mip level; however that is a higher-level concern and not the purview of SlimDX.

Quote:

I haven't found the solution, but I did find out what the problem was. The static member function FromFile uses the more generic Texture member function FromFile which, in turn, calls the Texture member function ConstructFromFile which just uses the D3DX function D3DX10CreateTextureFromFile called like so:

The Texture2D.FromFile() overload that takes the ImageImageInformation object will delegate to the base Texture ConstructFromFile method that takes an ImageImageInformation.
Kevin31
Kevin31
ok...
but how can I solve my problem???
I have, thanks to your help, the following code:

public Terrain(Device device, string heightMapAsset) {		ImageLoadInformation info = new ImageLoadInformation();	info.BindFlags = BindFlags.None;	info.CpuAccessFlags = CpuAccessFlags.Write;	info.Depth = 0;	info.FilterFlags = FilterFlags.None;	info.FirstMipLevel = 0;	info.Format = SlimDX.DXGI.Format.R32G32B32_Float;	info.Height = ImageLoadInformation.FileDefaultValue;	info.MipFilterFlags = FilterFlags.None;	info.MipLevels = ImageLoadInformation.FileDefaultValue;	info.OptionFlags = ResourceOptionFlags.None;	info.Usage = ResourceUsage.Dynamic;	info.Width = ImageLoadInformation.FileDefaultValue;	//Exception at this line:	Texture2D tex = Texture2D.FromFile(device, heightMapAsset, info);	heightData = new float[tex.Description.Width, tex.Description.Height];	DataRectangle data = tex.Map(0, MapMode.WriteDiscard, MapFlags.None);	//...}


What's wrong with this code???
jpetrie
jpetrie
What's the debug runtime say now? The same thing as before?
Kevin31
Kevin31
D3D10: ERROR: ID3D10Device::CreateTexture2D: Returning E_INVALIDARG, meaning invalid parameters were passed. [ STATE_CREATION ERROR #104: CREATETEXTURE2D_INVALIDARG_RETURN ]
jpetrie
jpetrie
Why are you using a 96-bit floating point format?
Kevin31
Kevin31
Ohh...
Well if you replace the line with

info.Format = SlimDX.DXGI.Format.R32G32_Float;

it still doesn't work...
(same exception)
Kevin31
Kevin31
Ohh...
Well if you replace the line with

info.Format = SlimDX.DXGI.Format.R32G32_Float;

it still doesn't work...
(same exception)
jpetrie
jpetrie
Why are you using a 64-bit red/green only format? It looks to me like you don't understand the meaning of those format constants.

You probably want to pass FileDefault for the format parameter as well. This may not be the cause of your problem, but since you were unable to actually answer my original question about the format I feel safe concluding you don't actually need to be changing the format to something obscure like that.
Kevin31
Kevin31
Ok, i don't really know what the format is for...but I think I have to use B8G8R8A8_UNorm, because the texture stores colors in argb. Is this right?

note: I had used XNA for a long time, so I did't had to do this stuff...
wlastas
wlastas
I have the same storage problem - you have found the correct code?

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.