我正在测试从纹理读取数据。问题是我的最终数组的数据不完整。
我使用自己的类创建源纹理来简化代码(https://github.com/Kordi3112/BasicSilkDirect3D11Template/blob/main/Engine/Video/Texture.cs)
texture = new Texture();
texture.Create(videoManager.Device, new Vector2i(3, 2), [
new Color(1, 2, 3, 4), new Color(5, 6, 7, 8), new Color(9, 10, 11, 12),
new Color(13, 14, 15, 16), new Color(17, 18, 19, 20), new Color(21, 22, 23, 24)
]);
然后我创建分段纹理:
var testTexture = Texture.CreateStagged(videoManager.Device, texture.Size);
|纹理创建代码|:
public unsafe static ComPtr<ID3D11Texture2D> CreateStagged(ComPtr<ID3D11Device> device, Vector2i size)
{
ComPtr<ID3D11Texture2D> texture = default;
var texture2DDesc = new Texture2DDesc()
{
Width = (uint)size.X,
Height = (uint)size.Y,
ArraySize = 1,
BindFlags = (uint)BindFlag.None,
Usage = Usage.Staging,
CPUAccessFlags = (uint)CpuAccessFlag.Read,
Format = Format.FormatR8G8B8A8Unorm,
MipLevels = 1,
MiscFlags = (uint)ResourceMiscFlag.None,
SampleDesc = new SampleDesc(1, 0),
};
CrashHandler.CheckForError(device.CreateTexture2D(texture2DDesc, Unsafe.NullRef<SubresourceData>(), ref texture), "Stagged Texture creation error");
return texture;
}
然后我将“texture”复制到“testTexture”,映射资源,并将映射的源数据复制到字节数组:
videoManager.DeviceContext.CopyResource(testTexture, texture.texture);
var mappedSubresource = new MappedSubresource();
mappedSubresource.RowPitch = (uint)texture.Size.X * 4; // im not sure if its neccesary
videoManager.DeviceContext.Map(testTexture, 0, Map.Read, 0, ref mappedSubresource);
byte[] data = new byte[texture.Size.X * texture.Size.Y * 4];
fixed (byte* pData = data)
{
System.Buffer.MemoryCopy(mappedSubresource.PData, pData , data.Length, data.Length);
}
videoManager.DeviceContext.Unmap(testTexture, 0);
当我尝试查看数据数组的内容时,我看到的数字是 0-12 而不是 0-24:
for (int i = 0; i < data.Length; i++)
{
Console.WriteLine((int)data[i]);
}
当我将纹理大小更改为 [2,3] 时,它将显示 0-8 的数据,所以我认为以下两件事之一可能是错误的:
虽然 Silk 将其定义为
ref
,但 mappedSubresource
实际上是一个“out”参数,正如您在相应的 D3D11 ID3D11DeviceContext::Map 方法 定义中看到的那样
HRESULT Map(
[in] ID3D11Resource *pResource,
[in] UINT Subresource,
[in] D3D11_MAP MapType,
[in] UINT MapFlags,
[out, optional] D3D11_MAPPED_SUBRESOURCE *pMappedResource
);
(它是丝绸中的
ref
,允许您传递空指针,因为它也标记为optional
)
当您映射资源时,您必须使用GPU上定义的行间距,它可能与您在CPU中使用的行间距不同,因此要将其从GPU复制回来,您可以这样做:
var mappedSubresource = new MappedSubresource();
videoManager.DeviceContext.Map(testTexture, 0, Map.Read, 0, ref mappedSubresource);
var dataRowSize = 4 * texture.Size.X;
byte[] data = new byte[dataRowSize * texture.Size.Y];
// we must copy row by row
fixed (byte* pData = data)
{
for (var i = 0; i < texture.Size.Y; i++)
{
System.Buffer.MemoryCopy((byte*)mappedSubresource.PData + i * mappedSubresource.RowPitch, pData + i * dataRowSize, dataRowSize, dataRowSize);
}
}
videoManager.DeviceContext.Unmap(testTexture, 0);