yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Gangzheng TongConvert gfx unit tests and examples to use slang-rhi (#7577)43d0c2100

master
32.7 KiB928 linesraw
1#if 0
2// Duplicated: This test is identical to slang-rhi\tests\test-cmd-copy-texture.cpp
3
4#include "core/slang-basic.h"
5#include "gfx-test-texture-util.h"
6#include "gfx-test-util.h"
7#include "slang-rhi.h"
8#include "slang-rhi/shader-cursor.h"
9#include "unit-test/slang-unit-test.h"
10
11#if SLANG_WINDOWS_FAMILY
12#include <d3d12.h>
13#endif
14
15using namespace Slang;
16using namespace rhi;
17
18namespace gfx_test
19{
20struct TextureToTextureCopyInfo
21{
22    SubresourceRange srcSubresource;
23    SubresourceRange dstSubresource;
24    Extents extent;
25    Offset3D srcOffset;
26    Offset3D dstOffset;
27};
28
29struct TextureToBufferCopyInfo
30{
31    SubresourceRange srcSubresource;
32    Extents extent;
33    Offset3D textureOffset;
34    Offset bufferOffset;
35    Offset bufferSize;
36};
37
38struct BaseCopyTextureTest
39{
40    IDevice* device;
41    UnitTestContext* context;
42
43    rhi::Size alignedRowStride;
44
45    RefPtr<TextureInfo> srcTextureInfo;
46    RefPtr<TextureInfo> dstTextureInfo;
47    TextureToTextureCopyInfo texCopyInfo;
48    TextureToBufferCopyInfo bufferCopyInfo;
49
50    ComPtr<ITexture> srcTexture;
51    ComPtr<ITexture> dstTexture;
52    ComPtr<IBuffer> resultsBuffer;
53
54    RefPtr<ValidationTextureFormatBase> validationFormat;
55
56    void init(
57        IDevice* device,
58        UnitTestContext* context,
59        Format format,
60        RefPtr<ValidationTextureFormatBase> validationFormat,
61        TextureType type)
62    {
63        this->device = device;
64        this->context = context;
65        this->validationFormat = validationFormat;
66
67        this->srcTextureInfo = new TextureInfo();
68        this->srcTextureInfo->format = format;
69        this->srcTextureInfo->textureType = type;
70
71        this->dstTextureInfo = new TextureInfo();
72        this->dstTextureInfo->format = format;
73        this->dstTextureInfo->textureType = type;
74    }
75
76    void createRequiredResources()
77    {
78        TextureDesc srcTexDesc = {};
79        srcTexDesc.type = srcTextureInfo->textureType;
80        srcTexDesc.mipCount = srcTextureInfo->mipLevelCount;
81        srcTexDesc.arraySize = srcTextureInfo->arrayLayerCount;
82        srcTexDesc.extent = srcTextureInfo->extents;
83        srcTexDesc.defaultState = ResourceState::ShaderResource;
84        srcTexDesc.format = srcTextureInfo->format;
85
86        GFX_CHECK_CALL_ABORT(device->createTexture(
87            srcTexDesc,
88            srcTextureInfo->subresourceDatas.getBuffer(),
89            srcTexture.writeRef()));
90
91        TextureDesc dstTexDesc = {};
92        dstTexDesc.type = dstTextureInfo->textureType;
93        dstTexDesc.mipCount = dstTextureInfo->mipLevelCount;
94        dstTexDesc.arraySize = dstTextureInfo->arrayLayerCount;
95        dstTexDesc.extent = dstTextureInfo->extents;
96        dstTexDesc.defaultState = ResourceState::CopyDestination;
97        dstTexDesc.format = dstTextureInfo->format;
98
99        GFX_CHECK_CALL_ABORT(device->createTexture(
100            dstTexDesc,
101            dstTextureInfo->subresourceDatas.getBuffer(),
102            dstTexture.writeRef()));
103
104        auto bufferCopyExtents = bufferCopyInfo.extent;
105        auto texelSize = getTexelSize(dstTextureInfo->format);
106        size_t alignment;
107        device->getTextureRowAlignment(&alignment);
108        alignedRowStride = (bufferCopyExtents.width * texelSize + alignment - 1) & ~(alignment - 1);
109        BufferDesc bufferDesc = {};
110        bufferDesc.size =
111            bufferCopyExtents.height * bufferCopyExtents.depth * alignedRowStride;
112        bufferDesc.format = Format::Unknown;
113        bufferDesc.elementSize = 0;
114        bufferDesc.defaultState = ResourceState::CopyDestination;
115        bufferDesc.memoryType = MemoryType::DeviceLocal;
116
117        GFX_CHECK_CALL_ABORT(
118            device->createBuffer(bufferDesc, nullptr, resultsBuffer.writeRef()));
119
120        bufferCopyInfo.bufferSize = bufferDesc.size;
121    }
122
123    void submitGPUWork()
124    {
125        ICommandQueue::Desc queueDesc = {ICommandQueue::QueueType::Graphics};
126        auto queue = device->createCommandQueue(queueDesc);
127
128        auto commandBuffer = queue->createCommandBuffer();
129        auto encoder = commandBuffer->encodeResourceCommands();
130
131        encoder->textureBarrier(
132            srcTexture,
133            texCopyInfo.srcSubresource,
134            ResourceState::ShaderResource,
135            ResourceState::CopySource);
136        encoder->copyTexture(
137            dstTexture,
138            texCopyInfo.dstSubresource,
139            texCopyInfo.dstOffset,
140            srcTexture,
141            texCopyInfo.srcSubresource,
142            texCopyInfo.srcOffset,
143            texCopyInfo.extent);
144
145        encoder->textureBarrier(
146            dstTexture,
147            bufferCopyInfo.srcSubresource,
148            ResourceState::CopyDestination,
149            ResourceState::CopySource);
150        encoder->copyTextureToBuffer(
151            resultsBuffer,
152            bufferCopyInfo.bufferOffset,
153            bufferCopyInfo.bufferSize,
154            alignedRowStride,
155            dstTexture,
156            bufferCopyInfo.srcSubresource,
157            bufferCopyInfo.textureOffset,
158            bufferCopyInfo.extent);
159
160        encoder->endEncoding();
161        commandBuffer->close();
162        queue->executeCommandBuffer(commandBuffer);
163        queue->waitOnHost();
164    }
165
166    bool isWithinCopyBounds(GfxIndex x, GfxIndex y, GfxIndex z)
167    {
168        auto copyExtents = texCopyInfo.extent;
169        auto copyOffset = texCopyInfo.dstOffset;
170
171        auto xLowerBound = copyOffset.x;
172        auto xUpperBound = copyOffset.x + copyExtents.width;
173        auto yLowerBound = copyOffset.y;
174        auto yUpperBound = copyOffset.y + copyExtents.height;
175        auto zLowerBound = copyOffset.z;
176        auto zUpperBound = copyOffset.z + copyExtents.depth;
177
178        if (x < xLowerBound || x >= xUpperBound || y < yLowerBound || y >= yUpperBound ||
179            z < zLowerBound || z >= zUpperBound)
180            return false;
181        else
182            return true;
183    }
184
185    void validateTestResults(
186        ValidationTextureData actual,
187        ValidationTextureData expectedCopied,
188        ValidationTextureData expectedOriginal)
189    {
190        auto actualExtents = actual.extents;
191        auto copyExtent = texCopyInfo.extent;
192        auto srcTexOffset = texCopyInfo.srcOffset;
193        auto dstTexOffset = texCopyInfo.dstOffset;
194
195        for (GfxIndex x = 0; x < actualExtents.width; ++x)
196        {
197            for (GfxIndex y = 0; y < actualExtents.height; ++y)
198            {
199                for (GfxIndex z = 0; z < actualExtents.depth; ++z)
200                {
201                    auto actualBlock = actual.getBlockAt(x, y, z);
202                    if (isWithinCopyBounds(x, y, z))
203                    {
204                        // Block is located within the bounds of the source texture
205                        auto xSource = x + srcTexOffset.x - dstTexOffset.x;
206                        auto ySource = y + srcTexOffset.y - dstTexOffset.y;
207                        auto zSource = z + srcTexOffset.z - dstTexOffset.z;
208                        auto expectedBlock = expectedCopied.getBlockAt(xSource, ySource, zSource);
209                        validationFormat->validateBlocksEqual(actualBlock, expectedBlock);
210                    }
211                    else
212                    {
213                        // Block is located outside the bounds of the source texture and should be
214                        // compared against known expected values for the destination texture.
215                        auto expectedBlock = expectedOriginal.getBlockAt(x, y, z);
216                        validationFormat->validateBlocksEqual(actualBlock, expectedBlock);
217                    }
218                }
219            }
220        }
221    }
222
223    void checkTestResults(
224        Extents srcMipExtent,
225        const void* expectedCopiedData,
226        const void* expectedOriginalData)
227    {
228        ComPtr<ISlangBlob> resultBlob;
229        GFX_CHECK_CALL_ABORT(device->readBuffer(
230            resultsBuffer,
231            0,
232            bufferCopyInfo.bufferSize,
233            resultBlob.writeRef()));
234        auto results = resultBlob->getBufferPointer();
235
236        ValidationTextureData actual;
237        actual.extents = bufferCopyInfo.extent;
238        actual.textureData = results;
239        actual.strides.x = getTexelSize(dstTextureInfo->format);
240        actual.strides.y = alignedRowStride;
241        actual.strides.z = actual.extents.height * actual.strides.y;
242
243        ValidationTextureData expectedCopied;
244        expectedCopied.extents = srcMipExtent;
245        expectedCopied.textureData = expectedCopiedData;
246        expectedCopied.strides.x = getTexelSize(srcTextureInfo->format);
247        expectedCopied.strides.y = expectedCopied.extents.width * expectedCopied.strides.x;
248        expectedCopied.strides.z = expectedCopied.extents.height * expectedCopied.strides.y;
249
250        ValidationTextureData expectedOriginal;
251        if (expectedOriginalData)
252        {
253            expectedOriginal.extents = bufferCopyInfo.extent;
254            expectedOriginal.textureData = expectedOriginalData;
255            expectedOriginal.strides.x = getTexelSize(dstTextureInfo->format);
256            expectedOriginal.strides.y =
257                expectedOriginal.extents.width * expectedOriginal.strides.x;
258            expectedOriginal.strides.z =
259                expectedOriginal.extents.height * expectedOriginal.strides.y;
260        }
261
262        validateTestResults(actual, expectedCopied, expectedOriginal);
263    }
264};
265
266struct SimpleCopyTexture : BaseCopyTextureTest
267{
268    void run()
269    {
270        auto textureType = srcTextureInfo->textureType;
271        auto format = srcTextureInfo->format;
272
273        srcTextureInfo->extents.width = 4;
274        srcTextureInfo->extents.height = (textureType == TextureType::Texture1D) ? 1 : 4;
275        srcTextureInfo->extents.depth = (textureType == TextureType::Texture3D) ? 2 : 1;
276        srcTextureInfo->mipLevelCount = 1;
277        srcTextureInfo->arrayLayerCount = 1;
278
279        dstTextureInfo = srcTextureInfo;
280
281        generateTextureData(srcTextureInfo, validationFormat);
282
283        SubresourceRange srcSubresource = {};
284        srcSubresource.aspectMask = getTextureAspect(format);
285        srcSubresource.mipLevel = 0;
286        srcSubresource.mipLevelCount = 1;
287        srcSubresource.baseArrayLayer = 0;
288        srcSubresource.layerCount = 1;
289
290        SubresourceRange dstSubresource = {};
291        dstSubresource.aspectMask = getTextureAspect(format);
292        dstSubresource.mipLevel = 0;
293        dstSubresource.mipLevelCount = 1;
294        dstSubresource.baseArrayLayer = 0;
295        dstSubresource.layerCount = 1;
296
297        texCopyInfo.srcSubresource = srcSubresource;
298        texCopyInfo.dstSubresource = dstSubresource;
299        texCopyInfo.extent = srcTextureInfo->extents;
300        texCopyInfo.srcOffset = {0, 0, 0};
301        texCopyInfo.dstOffset = {0, 0, 0};
302
303        bufferCopyInfo.srcSubresource = dstSubresource;
304        bufferCopyInfo.extent = dstTextureInfo->extents;
305        bufferCopyInfo.textureOffset = {0, 0, 0};
306        bufferCopyInfo.bufferOffset = 0;
307
308        createRequiredResources();
309        submitGPUWork();
310
311        auto subresourceIndex = getSubresourceIndex(
312            srcSubresource.mipLevel,
313            srcTextureInfo->mipLevelCount,
314            srcSubresource.baseArrayLayer);
315        auto expectedData = srcTextureInfo->subresourceDatas[subresourceIndex];
316        checkTestResults(srcTextureInfo->extents, expectedData.data, nullptr);
317    }
318};
319
320struct CopyTextureSection : BaseCopyTextureTest
321{
322    void run()
323    {
324        auto textureType = srcTextureInfo->textureType;
325        auto format = srcTextureInfo->format;
326
327        srcTextureInfo->extents.width = 4;
328        srcTextureInfo->extents.height = (textureType == TextureType::Texture1D) ? 1 : 4;
329        srcTextureInfo->extents.depth = (textureType == TextureType::Texture3D) ? 2 : 1;
330        srcTextureInfo->mipLevelCount = 2;
331        srcTextureInfo->arrayLayerCount =
332            (textureType == TextureType::Texture3D) ? 1 : 2;
333
334        dstTextureInfo = srcTextureInfo;
335
336        generateTextureData(srcTextureInfo, validationFormat);
337
338        SubresourceRange srcSubresource = {};
339        srcSubresource.aspectMask = getTextureAspect(format);
340        srcSubresource.mipLevel = 0;
341        srcSubresource.mipLevelCount = 1;
342        srcSubresource.baseArrayLayer = (textureType == TextureType::Texture3D) ? 0 : 1;
343        srcSubresource.layerCount = 1;
344
345        SubresourceRange dstSubresource = {};
346        dstSubresource.aspectMask = getTextureAspect(format);
347        dstSubresource.mipLevel = 0;
348        dstSubresource.mipLevelCount = 1;
349        dstSubresource.baseArrayLayer = 0;
350        dstSubresource.layerCount = 1;
351
352        texCopyInfo.srcSubresource = srcSubresource;
353        texCopyInfo.dstSubresource = dstSubresource;
354        texCopyInfo.extent = srcTextureInfo->extents;
355        texCopyInfo.srcOffset = {0, 0, 0};
356        texCopyInfo.dstOffset = {0, 0, 0};
357
358        bufferCopyInfo.srcSubresource = dstSubresource;
359        bufferCopyInfo.extent = dstTextureInfo->extents;
360        bufferCopyInfo.textureOffset = {0, 0, 0};
361        bufferCopyInfo.bufferOffset = 0;
362
363        createRequiredResources();
364        submitGPUWork();
365
366        auto subresourceIndex = getSubresourceIndex(
367            srcSubresource.mipLevel,
368            srcTextureInfo->mipLevelCount,
369            srcSubresource.baseArrayLayer);
370        SubresourceData expectedData =
371            srcTextureInfo->subresourceDatas[subresourceIndex];
372        checkTestResults(srcTextureInfo->extents, expectedData.data, nullptr);
373    }
374};
375
376struct LargeSrcToSmallDst : BaseCopyTextureTest
377{
378    void run()
379    {
380        auto textureType = srcTextureInfo->textureType;
381        auto format = srcTextureInfo->format;
382
383        srcTextureInfo->extents.width = 8;
384        srcTextureInfo->extents.height = (textureType == TextureType::Texture1D) ? 1 : 8;
385        srcTextureInfo->extents.depth = (textureType == TextureType::Texture3D) ? 2 : 1;
386        srcTextureInfo->mipLevelCount = 1;
387        srcTextureInfo->arrayLayerCount = 1;
388
389        generateTextureData(srcTextureInfo, validationFormat);
390
391        dstTextureInfo->extents.width = 4;
392        dstTextureInfo->extents.height = (textureType == TextureType::Texture1D) ? 1 : 4;
393        dstTextureInfo->extents.depth = (textureType == TextureType::Texture3D) ? 2 : 1;
394        dstTextureInfo->mipLevelCount = 1;
395        dstTextureInfo->arrayLayerCount = 1;
396
397        SubresourceRange srcSubresource = {};
398        srcSubresource.aspectMask = getTextureAspect(format);
399        srcSubresource.mipLevel = 0;
400        srcSubresource.mipLevelCount = 1;
401        srcSubresource.baseArrayLayer = 0;
402        srcSubresource.layerCount = 1;
403
404        SubresourceRange dstSubresource = {};
405        dstSubresource.aspectMask = getTextureAspect(format);
406        dstSubresource.mipLevel = 0;
407        dstSubresource.mipLevelCount = 1;
408        dstSubresource.baseArrayLayer = 0;
409        dstSubresource.layerCount = 1;
410
411        texCopyInfo.srcSubresource = srcSubresource;
412        texCopyInfo.dstSubresource = dstSubresource;
413        texCopyInfo.extent = dstTextureInfo->extents;
414        texCopyInfo.srcOffset = {0, 0, 0};
415        texCopyInfo.dstOffset = {0, 0, 0};
416
417        bufferCopyInfo.srcSubresource = dstSubresource;
418        bufferCopyInfo.extent = dstTextureInfo->extents;
419        bufferCopyInfo.textureOffset = {0, 0, 0};
420        bufferCopyInfo.bufferOffset = 0;
421
422        createRequiredResources();
423        submitGPUWork();
424
425        auto subresourceIndex = getSubresourceIndex(
426            srcSubresource.mipLevel,
427            srcTextureInfo->mipLevelCount,
428            srcSubresource.baseArrayLayer);
429        SubresourceData expectedData =
430            srcTextureInfo->subresourceDatas[subresourceIndex];
431        checkTestResults(srcTextureInfo->extents, expectedData.data, nullptr);
432    }
433};
434
435struct SmallSrcToLargeDst : BaseCopyTextureTest
436{
437    void run()
438    {
439        auto textureType = srcTextureInfo->textureType;
440        auto format = srcTextureInfo->format;
441
442        srcTextureInfo->extents.width = 4;
443        srcTextureInfo->extents.height = (textureType == TextureType::Texture1D) ? 1 : 4;
444        srcTextureInfo->extents.depth = (textureType == TextureType::Texture3D) ? 2 : 1;
445        srcTextureInfo->mipLevelCount = 1;
446        srcTextureInfo->arrayLayerCount = 1;
447
448        generateTextureData(srcTextureInfo, validationFormat);
449
450        dstTextureInfo->extents.width = 8;
451        dstTextureInfo->extents.height = (textureType == TextureType::Texture1D) ? 1 : 8;
452        dstTextureInfo->extents.depth = (textureType == TextureType::Texture3D) ? 2 : 1;
453        dstTextureInfo->mipLevelCount = 1;
454        dstTextureInfo->arrayLayerCount = 1;
455
456        generateTextureData(dstTextureInfo, validationFormat);
457
458        SubresourceRange srcSubresource = {};
459        srcSubresource.aspectMask = getTextureAspect(format);
460        srcSubresource.mipLevel = 0;
461        srcSubresource.mipLevelCount = 1;
462        srcSubresource.baseArrayLayer = 0;
463        srcSubresource.layerCount = 1;
464
465        SubresourceRange dstSubresource = {};
466        dstSubresource.aspectMask = getTextureAspect(format);
467        dstSubresource.mipLevel = 0;
468        dstSubresource.mipLevelCount = 1;
469        dstSubresource.baseArrayLayer = 0;
470        dstSubresource.layerCount = 1;
471
472        texCopyInfo.srcSubresource = srcSubresource;
473        texCopyInfo.dstSubresource = dstSubresource;
474        texCopyInfo.extent = srcTextureInfo->extents;
475        texCopyInfo.srcOffset = {0, 0, 0};
476        texCopyInfo.dstOffset = {0, 0, 0};
477
478        bufferCopyInfo.srcSubresource = dstSubresource;
479        bufferCopyInfo.extent = dstTextureInfo->extents;
480        bufferCopyInfo.textureOffset = {0, 0, 0};
481        bufferCopyInfo.bufferOffset = 0;
482
483        createRequiredResources();
484        submitGPUWork();
485
486        auto copiedSubresourceIndex = getSubresourceIndex(
487            srcSubresource.mipLevel,
488            srcTextureInfo->mipLevelCount,
489            srcSubresource.baseArrayLayer);
490        SubresourceData expectedCopiedData =
491            srcTextureInfo->subresourceDatas[copiedSubresourceIndex];
492        auto originalSubresourceIndex = getSubresourceIndex(
493            dstSubresource.mipLevel,
494            dstTextureInfo->mipLevelCount,
495            dstSubresource.baseArrayLayer);
496        SubresourceData expectedOriginalData =
497            dstTextureInfo->subresourceDatas[originalSubresourceIndex];
498        checkTestResults(
499            srcTextureInfo->extents,
500            expectedCopiedData.data,
501            expectedOriginalData.data);
502    }
503};
504
505struct CopyBetweenMips : BaseCopyTextureTest
506{
507    void run()
508    {
509        auto textureType = srcTextureInfo->textureType;
510        auto format = srcTextureInfo->format;
511
512        srcTextureInfo->extents.width = 16;
513        srcTextureInfo->extents.height =
514            (textureType == TextureType::Texture1D) ? 1 : 16;
515        srcTextureInfo->extents.depth = (textureType == TextureType::Texture3D) ? 2 : 1;
516        srcTextureInfo->mipLevelCount = 4;
517        srcTextureInfo->arrayLayerCount = 1;
518
519        generateTextureData(srcTextureInfo, validationFormat);
520
521        dstTextureInfo->extents.width = 16;
522        dstTextureInfo->extents.height =
523            (textureType == TextureType::Texture1D) ? 1 : 16;
524        dstTextureInfo->extents.depth = (textureType == TextureType::Texture3D) ? 2 : 1;
525        dstTextureInfo->mipLevelCount = 4;
526        dstTextureInfo->arrayLayerCount = 1;
527
528        generateTextureData(dstTextureInfo, validationFormat);
529
530        SubresourceRange srcSubresource = {};
531        srcSubresource.aspectMask = getTextureAspect(format);
532        srcSubresource.mipLevel = 2;
533        srcSubresource.mipLevelCount = 1;
534        srcSubresource.baseArrayLayer = 0;
535        srcSubresource.layerCount = 1;
536
537        SubresourceRange dstSubresource = {};
538        dstSubresource.aspectMask = getTextureAspect(format);
539        dstSubresource.mipLevel = 1;
540        dstSubresource.mipLevelCount = 1;
541        dstSubresource.baseArrayLayer = 0;
542        dstSubresource.layerCount = 1;
543
544        auto copiedSubresourceIndex = getSubresourceIndex(
545            srcSubresource.mipLevel,
546            srcTextureInfo->mipLevelCount,
547            srcSubresource.baseArrayLayer);
548        auto originalSubresourceIndex = getSubresourceIndex(
549            dstSubresource.mipLevel,
550            dstTextureInfo->mipLevelCount,
551            dstSubresource.baseArrayLayer);
552
553        texCopyInfo.srcSubresource = srcSubresource;
554        texCopyInfo.dstSubresource = dstSubresource;
555        texCopyInfo.extent = srcTextureInfo->subresourceObjects[copiedSubresourceIndex]->extents;
556        texCopyInfo.srcOffset = {0, 0, 0};
557        texCopyInfo.dstOffset = {0, 0, 0};
558
559        bufferCopyInfo.srcSubresource = dstSubresource;
560        bufferCopyInfo.extent =
561            dstTextureInfo->subresourceObjects[originalSubresourceIndex]->extents;
562        bufferCopyInfo.textureOffset = {0, 0, 0};
563        bufferCopyInfo.bufferOffset = 0;
564
565        createRequiredResources();
566        submitGPUWork();
567
568        SubresourceData expectedCopiedData =
569            srcTextureInfo->subresourceDatas[copiedSubresourceIndex];
570        SubresourceData expectedOriginalData =
571            dstTextureInfo->subresourceDatas[originalSubresourceIndex];
572        auto srcMipExtent = srcTextureInfo->subresourceObjects[2]->extents;
573        checkTestResults(srcMipExtent, expectedCopiedData.data, expectedOriginalData.data);
574    }
575};
576
577struct CopyBetweenLayers : BaseCopyTextureTest
578{
579    void run()
580    {
581        auto textureType = srcTextureInfo->textureType;
582        auto format = srcTextureInfo->format;
583
584        srcTextureInfo->extents.width = 4;
585        srcTextureInfo->extents.height = (textureType == TextureType::Texture1D) ? 1 : 4;
586        srcTextureInfo->extents.depth = (textureType == TextureType::Texture3D) ? 2 : 1;
587        srcTextureInfo->mipLevelCount = 1;
588        srcTextureInfo->arrayLayerCount =
589            (textureType == TextureType::Texture3D) ? 1 : 2;
590
591        generateTextureData(srcTextureInfo, validationFormat);
592        dstTextureInfo = srcTextureInfo;
593
594        SubresourceRange srcSubresource = {};
595        srcSubresource.aspectMask = getTextureAspect(format);
596        srcSubresource.mipLevel = 0;
597        srcSubresource.mipLevelCount = 1;
598        srcSubresource.baseArrayLayer = 0;
599        srcSubresource.layerCount = 1;
600
601        SubresourceRange dstSubresource = {};
602        dstSubresource.aspectMask = getTextureAspect(format);
603        dstSubresource.mipLevel = 0;
604        dstSubresource.mipLevelCount = 1;
605        dstSubresource.baseArrayLayer = (textureType == TextureType::Texture3D) ? 0 : 1;
606        dstSubresource.layerCount = 1;
607
608        texCopyInfo.srcSubresource = srcSubresource;
609        texCopyInfo.dstSubresource = dstSubresource;
610        texCopyInfo.extent = srcTextureInfo->extents;
611        texCopyInfo.srcOffset = {0, 0, 0};
612        texCopyInfo.dstOffset = {0, 0, 0};
613
614        bufferCopyInfo.srcSubresource = dstSubresource;
615        bufferCopyInfo.extent = dstTextureInfo->extents;
616        bufferCopyInfo.textureOffset = {0, 0, 0};
617        bufferCopyInfo.bufferOffset = 0;
618
619        createRequiredResources();
620        submitGPUWork();
621
622        auto copiedSubresourceIndex = getSubresourceIndex(
623            srcSubresource.mipLevel,
624            srcTextureInfo->mipLevelCount,
625            srcSubresource.baseArrayLayer);
626        SubresourceData expectedCopiedData =
627            srcTextureInfo->subresourceDatas[copiedSubresourceIndex];
628        auto originalSubresourceIndex = getSubresourceIndex(
629            dstSubresource.mipLevel,
630            dstTextureInfo->mipLevelCount,
631            dstSubresource.baseArrayLayer);
632        SubresourceData expectedOriginalData =
633            dstTextureInfo->subresourceDatas[originalSubresourceIndex];
634        checkTestResults(
635            srcTextureInfo->extents,
636            expectedCopiedData.data,
637            expectedOriginalData.data);
638    }
639};
640
641struct CopyWithOffsets : BaseCopyTextureTest
642{
643    void run()
644    {
645        auto textureType = srcTextureInfo->textureType;
646        auto format = srcTextureInfo->format;
647
648        srcTextureInfo->extents.width = 8;
649        srcTextureInfo->extents.height = (textureType == TextureType::Texture1D) ? 1 : 8;
650        srcTextureInfo->extents.depth = (textureType == TextureType::Texture3D) ? 2 : 1;
651        srcTextureInfo->mipLevelCount = 1;
652        srcTextureInfo->arrayLayerCount = 1;
653
654        generateTextureData(srcTextureInfo, validationFormat);
655
656        dstTextureInfo->extents.width = 16;
657        dstTextureInfo->extents.height =
658            (textureType == TextureType::Texture1D) ? 1 : 16;
659        dstTextureInfo->extents.depth = (textureType == TextureType::Texture3D) ? 4 : 1;
660        dstTextureInfo->mipLevelCount = 1;
661        dstTextureInfo->arrayLayerCount = 1;
662
663        generateTextureData(dstTextureInfo, validationFormat);
664
665        SubresourceRange srcSubresource = {};
666        srcSubresource.aspectMask = getTextureAspect(format);
667        srcSubresource.mipLevel = 0;
668        srcSubresource.mipLevelCount = 1;
669        srcSubresource.baseArrayLayer = 0;
670        srcSubresource.layerCount = 1;
671
672        SubresourceRange dstSubresource = {};
673        dstSubresource.aspectMask = getTextureAspect(format);
674        dstSubresource.mipLevel = 0;
675        dstSubresource.mipLevelCount = 1;
676        dstSubresource.baseArrayLayer = 0;
677        dstSubresource.layerCount = 1;
678
679        texCopyInfo.srcSubresource = srcSubresource;
680        texCopyInfo.dstSubresource = dstSubresource;
681        texCopyInfo.extent.width = 4;
682        texCopyInfo.extent.height = 4;
683        texCopyInfo.extent.depth = 1;
684        texCopyInfo.srcOffset = {2, 2, 0};
685        texCopyInfo.dstOffset = {4, 4, 0};
686
687        if (textureType == TextureType::Texture1D)
688        {
689            texCopyInfo.extent.height = 1;
690            texCopyInfo.srcOffset.y = 0;
691            texCopyInfo.dstOffset.y = 0;
692        }
693        else if (textureType == TextureType::Texture3D)
694        {
695            texCopyInfo.extent.depth = srcTextureInfo->extents.depth;
696            texCopyInfo.dstOffset.z = 1;
697        }
698
699        bufferCopyInfo.srcSubresource = dstSubresource;
700        bufferCopyInfo.extent = dstTextureInfo->extents;
701        bufferCopyInfo.textureOffset = {0, 0, 0};
702        bufferCopyInfo.bufferOffset = 0;
703
704        createRequiredResources();
705        submitGPUWork();
706
707        auto copiedSubresourceIndex = getSubresourceIndex(
708            srcSubresource.mipLevel,
709            srcTextureInfo->mipLevelCount,
710            srcSubresource.baseArrayLayer);
711        SubresourceData expectedCopiedData =
712            srcTextureInfo->subresourceDatas[copiedSubresourceIndex];
713        auto originalSubresourceIndex = getSubresourceIndex(
714            dstSubresource.mipLevel,
715            dstTextureInfo->mipLevelCount,
716            dstSubresource.baseArrayLayer);
717        SubresourceData expectedOriginalData =
718            dstTextureInfo->subresourceDatas[originalSubresourceIndex];
719        checkTestResults(
720            srcTextureInfo->extents,
721            expectedCopiedData.data,
722            expectedOriginalData.data);
723    }
724};
725
726struct CopySectionWithSetExtent : BaseCopyTextureTest
727{
728    void run()
729    {
730        auto textureType = srcTextureInfo->textureType;
731        auto format = srcTextureInfo->format;
732
733        srcTextureInfo->extents.width = 8;
734        srcTextureInfo->extents.height = (textureType == TextureType::Texture1D) ? 1 : 8;
735        srcTextureInfo->extents.depth = (textureType == TextureType::Texture3D) ? 2 : 1;
736        srcTextureInfo->mipLevelCount = 1;
737        srcTextureInfo->arrayLayerCount = 1;
738
739        generateTextureData(srcTextureInfo, validationFormat);
740        dstTextureInfo = srcTextureInfo;
741
742        SubresourceRange srcSubresource = {};
743        srcSubresource.aspectMask = getTextureAspect(format);
744        srcSubresource.mipLevel = 0;
745        srcSubresource.mipLevelCount = 1;
746        srcSubresource.baseArrayLayer = 0;
747        srcSubresource.layerCount = 1;
748
749        SubresourceRange dstSubresource = {};
750        dstSubresource.aspectMask = getTextureAspect(format);
751        dstSubresource.mipLevel = 0;
752        dstSubresource.mipLevelCount = 1;
753        dstSubresource.baseArrayLayer = 0;
754        dstSubresource.layerCount = 1;
755
756        texCopyInfo.srcSubresource = srcSubresource;
757        texCopyInfo.dstSubresource = dstSubresource;
758        texCopyInfo.extent.width = 4;
759        texCopyInfo.extent.height = 4;
760        texCopyInfo.extent.depth = 1;
761        texCopyInfo.srcOffset = {0, 0, 0};
762        texCopyInfo.dstOffset = {4, 4, 0};
763
764        if (textureType == TextureType::Texture1D)
765        {
766            texCopyInfo.extent.height = 1;
767            texCopyInfo.dstOffset.y = 0;
768        }
769        else if (textureType == TextureType::Texture3D)
770        {
771            texCopyInfo.extent.depth = srcTextureInfo->extents.depth;
772        }
773
774        bufferCopyInfo.srcSubresource = dstSubresource;
775        bufferCopyInfo.extent = dstTextureInfo->extents;
776        bufferCopyInfo.textureOffset = {0, 0, 0};
777        bufferCopyInfo.bufferOffset = 0;
778
779        createRequiredResources();
780        submitGPUWork();
781
782        auto copiedSubresourceIndex = getSubresourceIndex(
783            srcSubresource.mipLevel,
784            srcTextureInfo->mipLevelCount,
785            srcSubresource.baseArrayLayer);
786        SubresourceData expectedCopiedData =
787            srcTextureInfo->subresourceDatas[copiedSubresourceIndex];
788        auto originalSubresourceIndex = getSubresourceIndex(
789            dstSubresource.mipLevel,
790            dstTextureInfo->mipLevelCount,
791            dstSubresource.baseArrayLayer);
792        SubresourceData expectedOriginalData =
793            dstTextureInfo->subresourceDatas[originalSubresourceIndex];
794        checkTestResults(
795            srcTextureInfo->extents,
796            expectedCopiedData.data,
797            expectedOriginalData.data);
798    }
799};
800
801template<typename T>
802void copyTextureTestImpl(IDevice* device, UnitTestContext* context)
803{
804    const bool isVkd3d =
805        SLANG_ENABLE_VKD3D && strcmp(device->getDeviceInfo().apiName, "Direct3D 12") == 0;
806
807    // Skip Type::Unknown and Type::Buffer as well as Format::Unknown
808    // TODO: Add support for TextureCube
809    Format formats[] = {
810        Format::R8G8B8A8_UNORM,
811        Format::R16_FLOAT,
812        Format::R16G16_FLOAT,
813        Format::R10G10B10A2_UNORM,
814        Format::B5G5R5A1_UNORM};
815    for (uint32_t i = 2; i < (uint32_t)TextureType::_Count - 1; ++i)
816    {
817        for (auto format : formats)
818        {
819            // Fails validation VUID-VkImageCreateInfo-imageCreateMaxMipLevels-02251
820            if (isVkd3d &&
821                (format == Format::R32G32B32_TYPELESS || format == Format::R32G32B32_FLOAT ||
822                 format == Format::R32G32B32_UINT || format == Format::R32G32B32_SINT))
823            {
824                continue;
825            }
826            auto type = (TextureType)i;
827            auto validationFormat = getValidationTextureFormat(format);
828            if (!validationFormat)
829                continue;
830
831            T test;
832            test.init(device, context, format, validationFormat, type);
833            test.run();
834        }
835    }
836}
837
838SLANG_UNIT_TEST(copyTextureSimple)
839{
840    runTestImpl(
841        copyTextureTestImpl<SimpleCopyTexture>,
842        unitTestContext,
843        Slang::RenderApiFlag::D3D12);
844    runTestImpl(
845        copyTextureTestImpl<SimpleCopyTexture>,
846        unitTestContext,
847        Slang::RenderApiFlag::Vulkan);
848}
849
850SLANG_UNIT_TEST(copyTextureSection)
851{
852    runTestImpl(
853        copyTextureTestImpl<CopyTextureSection>,
854        unitTestContext,
855        Slang::RenderApiFlag::D3D12);
856    runTestImpl(
857        copyTextureTestImpl<CopyTextureSection>,
858        unitTestContext,
859        Slang::RenderApiFlag::Vulkan);
860}
861
862SLANG_UNIT_TEST(copyLargeToSmallTexture)
863{
864    runTestImpl(
865        copyTextureTestImpl<LargeSrcToSmallDst>,
866        unitTestContext,
867        Slang::RenderApiFlag::D3D12);
868    runTestImpl(
869        copyTextureTestImpl<LargeSrcToSmallDst>,
870        unitTestContext,
871        Slang::RenderApiFlag::Vulkan);
872}
873
874SLANG_UNIT_TEST(copySmallToLargeTexture)
875{
876    runTestImpl(
877        copyTextureTestImpl<SmallSrcToLargeDst>,
878        unitTestContext,
879        Slang::RenderApiFlag::D3D12);
880    runTestImpl(
881        copyTextureTestImpl<SmallSrcToLargeDst>,
882        unitTestContext,
883        Slang::RenderApiFlag::Vulkan);
884}
885
886SLANG_UNIT_TEST(copyBetweenMips)
887{
888    runTestImpl(copyTextureTestImpl<CopyBetweenMips>, unitTestContext, Slang::RenderApiFlag::D3D12);
889    runTestImpl(
890        copyTextureTestImpl<CopyBetweenMips>,
891        unitTestContext,
892        Slang::RenderApiFlag::Vulkan);
893}
894
895SLANG_UNIT_TEST(copyBetweenLayers)
896{
897    runTestImpl(
898        copyTextureTestImpl<CopyBetweenLayers>,
899        unitTestContext,
900        Slang::RenderApiFlag::D3D12);
901    runTestImpl(
902        copyTextureTestImpl<CopyBetweenLayers>,
903        unitTestContext,
904        Slang::RenderApiFlag::Vulkan);
905}
906
907SLANG_UNIT_TEST(copyWithOffsets)
908{
909    runTestImpl(copyTextureTestImpl<CopyWithOffsets>, unitTestContext, Slang::RenderApiFlag::D3D12);
910    runTestImpl(
911        copyTextureTestImpl<CopyWithOffsets>,
912        unitTestContext,
913        Slang::RenderApiFlag::Vulkan);
914}
915
916SLANG_UNIT_TEST(copySectionWithSetExtent)
917{
918    runTestImpl(
919        copyTextureTestImpl<CopySectionWithSetExtent>,
920        unitTestContext,
921        Slang::RenderApiFlag::D3D12);
922    runTestImpl(
923        copyTextureTestImpl<CopySectionWithSetExtent>,
924        unitTestContext,
925        Slang::RenderApiFlag::Vulkan);
926}
927} // namespace gfx_test
928#endif