How do I create a Texture2D array in SlimDX ? Or alternatively, can I use photoshops dds exporter to create a dds texture array to load into the Texture2d as i do for normal Textured2D's ?
I have looked at using CopySubresource region() which looks like a good candidate for copying a texture into a texture array because i can select the destination subresource. But there seems to be a catch : MapSubresource requires CPUAccessFlags.Write, so that excludes Default and Immutable, leaving Staging which must be BindFlags.None so i then cant use it as a resource and Dynamic which cannot have an array size of anything but [1]. So it appeares to me as though CopySubresource cant be used for texture arrays !! That seems really weird to me.
You don't want to copy in the array slices one by one after you've created the texture. What you want to do is have all of the data for all slices ready in CPU memory, then provide that data as the initialization data when you create your texture array. One way to do this is to load all of the array slices as STAGING resources, map them to get the pointer to their data, and then use those pointers when initializing the IMMUTABLE Texture2D resource for your texture array. Unfortunately I'm not too familar with SlimDX so I'm not sure how exactly to express it with that API, but there should be a way to accomplish this.
I have tried to provide all the textures at once in a DataRectangle[] , which as far as i can tell, is similar to a subresource in c++, though maybe the DataBox is the equivalent. Same thing. And I have seen an approach in c++ that uses a subresources to successfully load initial data. However, Texture2D does provide for a DataRectangle[] as a parameter, so I was looking at that route. I will continue my search now ...
Ive had to go back to basics here (again) to try to get a grasp on how DirectX handles resource construction, just to rule out some issues and get a better understanding. So I'm just filling some textures in manually with colors to prove the array is working... and it actually isn't working at all ..
Here is the texture initialization code, including the creation of the Texture2D array :
DataRectangle[] dataRectangleArray = new DataRectangle[2];
float[] sysResource = new float[loadInfo.Width * loadInfo.Height * 4];
int rowPitch = 200 * 16;
// fill in tex 1
for (int j = 0; j < sysResource.Length; j += 4)
{
sysResource[j + 0] = 0; // r
sysResource[j + 1] = 0; // g
sysResource[j + 2] = 1; // b
sysResource[j + 3] = 1; // a
}
DataStream dataStream = new DataStream(sysResource, true, true);
dataRectangleArray[0] = new DataRectangle(rowPitch, dataStream);
// fill in tex 2
for (int j = 0; j < sysResource.Length; j += 4)
{
sysResource[j + 0] = 1; // r
sysResource[j + 1] = 0; // g
sysResource[j + 2] = 0; // b
sysResource[j + 3] = 1; // a
}
dataStream = new DataStream(sysResource, true, true);
dataRectangleArray[1] = new DataRectangle(rowPitch, dataStream);
// create texture array - with initial data from dataRectangleArray
Texture2DDescription textureDescription = new Texture2DDescription()
{
ArraySize = 2,
BindFlags = BindFlags.ShaderResource,
CpuAccessFlags = CpuAccessFlags.None,
Format = SlimDX.DXGI.Format.R32G32B32A32_Float,
Height = 220,
MipLevels = 1,
OptionFlags = ResourceOptionFlags.None,
SampleDescription = new SlimDX.DXGI.SampleDescription(1, 0),
Usage = ResourceUsage.Immutable,
Width = 200
};
texture2DArray_G1Brushes = new Texture2D(SDXForm.Device11, textureDescription, dataRectangleArray);
AddResource("texture2DArray_G1Brushes", texture2DArray_G1Brushes);
And unexpectedly I'm getting a red texture ! But clearly it should be blue from this code ! So could anyone point out what I'm doing wrong in that regard ? By the way, it acutally doesn't matter what number i put into the sample shader in the z postion 0 - 500, it doesn't change anything, I would expect it to at least have the decency to crash on me.
Oh, and can anyone confirm that rowPitch = texture.width * format.width ? So for a texture 200 pixels across and Format.R32G32B32A32_Float, rowPitch = 200*16
At http://www.rastertek.../dx11tut17.html, the author Craig uses a different approach to a texture array,
// Set shader texture array resource in the pixel shader.
deviceContext->PSSetShaderResources(0, 2, textureArray);
but i suspect that all he's doing is loading the textures into consecutive registers, and not utilizing texture array capabilities at all, can someone confirm this ? Because his way looks a lot easier, just by providing an array of ShaderResourcesViews.
I believe your problem is that you're expecting DataStream to create a copy of the data you give it; it does not. It essentially creates a pointer to the data, so after creating the first array slice you go on and overwrite all the data and fill it with red instead, which is why your texture is ending up red no matter what you do.
You can either create separate managed arrays for the data, or you can use the DataStream overload that takes an integer instead of an array. This will allocate the given number of bytes in native memory (avoiding the GC overhead for the large data arrays typically used by textures) and let you write into it with the provided Write() functions. If you do it this way, make sure you rewind the stream to the start by setting Position = 0 before passing it to D3D.