SlicePitch 值是否错误?

问题描述 投票:0回答:1

我一直在尝试使用

Device.ImmediateContext.Mapsubresource()
从Texture2DArray复制内容。我已经在我的旧笔记本电脑上多次执行此操作,并且运行良好,但当我使用 Intel Iris Xe Graphics 执行此操作时,由于某种原因,中间出现了零间隙。

这是它的示例代码:

[DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);

public static unsafe float[] GetData()
{
    int gpuAdapterIndex = 0;

    SharpDX.DXGI.Adapter1 gpu;
    using (var factory = new SharpDX.DXGI.Factory1())
    {
        gpu = factory.GetAdapter1(gpuAdapterIndex);
    }

    Device device = new Device(gpu, DeviceCreationFlags.Debug);

    int pixelSize = sizeof(float);
    int width = 10;
    int height = 19;
    int depth = 3;
    float[] data = new float[width * height * depth];
    for (int i = 0; i < data.Length; i++)
    {
        data[i] = i;  
    }

    DataRectangle[] rectangles = new DataRectangle[depth];

    fixed (float* dataPtr = data)
    {
        IntPtr p = (IntPtr)dataPtr;

        for (int i = 0; i < rectangles.Length; i++)
        {
            rectangles[i] = new DataRectangle(IntPtr.Add(p, width * height * pixelSize * i), width * pixelSize);
        }
    }

    Texture2D t = new Texture2D(device, new Texture2DDescription()
    {
        ArraySize = depth,
        CpuAccessFlags = CpuAccessFlags.Write | CpuAccessFlags.Read,
        BindFlags = BindFlags.None,
        Format = SharpDX.DXGI.Format.R32_Float,
        Height = height,
        Width = width,
        MipLevels = 1,
        Usage = ResourceUsage.Staging,
        SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0),
        OptionFlags = ResourceOptionFlags.None,
    }, rectangles);

    float[] output = new float[data.Length];

    DataBox box = device.ImmediateContext.MapSubresource(t, 0, MapMode.Read, MapFlags.None);

    fixed (float* o = output)
    {
        IntPtr dst = (IntPtr)o;
        IntPtr scr = box.DataPointer;

        for (int z = 0; z < depth; z++)
        {
            for (int y = 0; y < height; y++)
            {
                CopyMemory(dst, scr, (uint)(width * pixelSize));

                scr = IntPtr.Add(scr, box.RowPitch);
                dst = IntPtr.Add(dst, width * pixelSize);
            }
        }
    }

    device.ImmediateContext.UnmapSubresource(t, 0);

    t.Dispose();
    device.Dispose();

    return output;
}

当我检查

box.SlicePitch
并将其与每个切片的实际大小进行比较时,它们是不同的,如果我没记错的话,这是不应该发生的。

(width,height), box.rowpitch, box.slicepitch, real slice pitch
(2, 38), 64, 2432, 2560
(3, 38), 64, 2432, 2560
(4, 38), 64, 2432, 2560
(5, 38), 64, 2432, 2560
(6, 38), 64, 2432, 2560
(7, 38), 64, 2432, 2560
(8, 38), 64, 2432, 2560
(9, 38), 64, 2432, 2560
(10, 38), 64, 2432, 2560
(11, 38), 64, 2432, 2560
(12, 38), 64, 2432, 2560
(13, 38), 64, 2432, 2560
(14, 38), 64, 2432, 2560
(15, 38), 64, 2432, 2560
(17, 38), 128, 4864, 5120
(18, 38), 128, 4864, 5120
(19, 38), 128, 4864, 5120
(20, 38), 128, 4864, 5120
(21, 38), 128, 4864, 5120
(22, 38), 128, 4864, 5120
(23, 38), 128, 4864, 5120
(24, 38), 128, 4864, 5120
(25, 38), 128, 4864, 5120
(26, 38), 128, 4864, 5120
(27, 38), 128, 4864, 5120
(28, 38), 128, 4864, 5120
(29, 38), 128, 4864, 5120
(30, 38), 128, 4864, 5120
(31, 38), 128, 4864, 5120
(33, 38), 192, 7296, 7680
(34, 38), 192, 7296, 7680
(35, 38), 192, 7296, 7680
(36, 38), 192, 7296, 7680
(37, 38), 192, 7296, 7680
(38, 38), 192, 7296, 7680
(39, 38), 192, 7296, 7680
(40, 38), 192, 7296, 7680

我拥有的任何其他显卡(Intel Graphics HD 520 和 nvidia mx450)都不会发生这种情况。 看来发生的情况是,不是将切片间距计算为

height * box.RowPitch
,而是将高度四舍五入到其上方最接近的 4 的倍数,然后乘以
box.RowPitch
。我最担心的是在其他情况下也会发生这种情况吗?如果是的话,有没有通用的方法来处理它们?

c# textures directx-11 sharpdx direct3d11
1个回答
0
投票

其他情况也会发生这种情况吗?

是的,间距大小可以调整以利于内存对齐或压缩,D3D11 并不强制每个硬件都以相同的方式执行此操作,而且这个概念不仅限于 DirectX;您当前的显卡没有做任何错误,它只是选择了对齐。

有通用的方法来处理它们吗?

只是不要假设每个子资源或其行和深度在内存中始终彼此相邻。您应该单独处理每个内存块(在您的情况下,每行)。

© www.soinside.com 2019 - 2024. All rights reserved.