yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
43d0c2100
master
1#if 0 2// Disabled: slang-rhi doesn't have resolveResource API. 3 4#include "core/slang-basic.h" 5#include "gfx-test-util.h" 6#include "unit-test/slang-unit-test.h" 7 8#include <slang-rhi.h> 9#include <slang-rhi/shader-cursor.h> 10 11#if SLANG_WINDOWS_FAMILY 12#include <d3d12.h> 13#endif 14 15using namespace Slang ; 16using namespace rhi ; 17 18namespace 19{ 20using namespace gfx_test ; 21 22struct Vertex 23{ 24float position [3 ]; 25float color [3 ]; 26}; 27 28static const int kVertexCount = 12 ; 29static const Vertex kVertexData [kVertexCount ]= { 30// Triangle 1 31 {{0 ,0 ,0.5 }, {1 ,0 ,0 }}, 32 {{1 ,1 ,0.5 }, {1 ,0 ,0 }}, 33 {{-1 ,1 ,0.5 }, {1 ,0 ,0 }}, 34 35// Triangle 2 36 {{-1 ,1 ,0.5 }, {0 ,1 ,0 }}, 37 {{0 ,0 ,0.5 }, {0 ,1 ,0 }}, 38 {{-1 ,-1 ,0.5 }, {0 ,1 ,0 }}, 39 40// Triangle 3 41 {{-1 ,-1 ,0.5 }, {0 ,0 ,1 }}, 42 {{0 ,0 ,0.5 }, {0 ,0 ,1 }}, 43 {{1 ,-1 ,0.5 }, {0 ,0 ,1 }}, 44 45// Triangle 4 46 {{1 ,-1 ,0.5 }, {0 ,0 ,0 }}, 47 {{0 ,0 ,0.5 }, {0 ,0 ,0 }}, 48 {{1 ,1 ,0.5 }, {0 ,0 ,0 }}, 49}; 50 51const int kWidth = 256 ; 52const int kHeight = 256 ; 53Format format = Format ::RGBA32Float ; 54 55ComPtr < IBuffer > createVertexBuffer (IDevice * device ) 56{ 57BufferDesc vertexBufferDesc ; 58vertexBufferDesc .size = kVertexCount * sizeof (Vertex ); 59vertexBufferDesc .defaultState = ResourceState ::VertexBuffer ; 60vertexBufferDesc .usage = BufferUsage ::VertexBuffer ; 61ComPtr < IBuffer > vertexBuffer = device -> createBuffer (vertexBufferDesc ,& kVertexData [0 ]); 62SLANG_CHECK_ABORT (vertexBuffer != nullptr ); 63return vertexBuffer ; 64} 65 66struct BaseResolveResourceTest 67{ 68IDevice * device ; 69UnitTestContext * context ; 70 71ComPtr < ITexture > msaaTexture ; 72ComPtr < ITexture > dstTexture ; 73 74ComPtr < IRenderPipeline > pipelineState ; 75 76ComPtr < IBuffer > vertexBuffer ; 77 78struct TextureInfo 79 { 80Extent3D extent ; 81int numMipLevels ; 82int arraySize ; 83const SubresourceData * initData ; 84 }; 85 86void init (IDevice * device ,UnitTestContext * context ) 87 { 88this -> device = device ; 89this -> context = context ; 90 } 91 92void createRequiredResources ( 93TextureInfo msaaTextureInfo , 94TextureInfo dstTextureInfo , 95Format format ) 96 { 97VertexStreamDesc vertexStreams []= { 98 {sizeof (Vertex ),InputSlotClass ::PerVertex ,0 }, 99 }; 100 101InputElementDesc inputElements []= { 102// Vertex buffer data 103 {"POSITION" ,0 ,Format ::RGB32Float , offsetof(Vertex ,position ),0 }, 104 {"COLOR" ,0 ,Format ::RGB32Float , offsetof(Vertex ,color ),0 }, 105 }; 106 107TextureDesc msaaTexDesc = {}; 108msaaTexDesc .type = TextureType ::Texture2D ; 109msaaTexDesc .mipCount = dstTextureInfo .numMipLevels ; 110msaaTexDesc .arrayLength = dstTextureInfo .arraySize ; 111msaaTexDesc .size = dstTextureInfo .extent ; 112msaaTexDesc .defaultState = ResourceState ::RenderTarget ; 113msaaTexDesc .usage = TextureUsage ::RenderTarget ; 114msaaTexDesc .format = format ; 115msaaTexDesc .sampleCount = 4 ; 116 117msaaTexture = device -> createTexture (msaaTexDesc ,msaaTextureInfo .initData ); 118SLANG_CHECK_ABORT (msaaTexture ); 119 120TextureDesc dstTexDesc = {}; 121dstTexDesc .type = TextureType ::Texture2D ; 122dstTexDesc .mipCount = dstTextureInfo .numMipLevels ; 123dstTexDesc .arrayLength = dstTextureInfo .arraySize ; 124dstTexDesc .size = dstTextureInfo .extent ; 125dstTexDesc .defaultState = ResourceState ::CopyDestination ; 126dstTexDesc .usage = TextureUsage ::CopyDestination |TextureUsage ::CopySource ; 127dstTexDesc .format = format ; 128 129dstTexture = device -> createTexture (dstTexDesc ,dstTextureInfo .initData ); 130SLANG_CHECK_ABORT (dstTexture ); 131 132InputLayoutDesc inputLayoutDesc = {}; 133inputLayoutDesc .inputElementCount = SLANG_COUNT_OF (inputElements ); 134inputLayoutDesc .inputElements = inputElements ; 135inputLayoutDesc .vertexStreamCount = SLANG_COUNT_OF (vertexStreams ); 136inputLayoutDesc .vertexStreams = vertexStreams ; 137auto inputLayout = device -> createInputLayout (inputLayoutDesc ); 138SLANG_CHECK_ABORT (inputLayout != nullptr ); 139 140vertexBuffer = createVertexBuffer (device ); 141 142ComPtr < IShaderProgram > shaderProgram ; 143 slang::ProgramLayout * slangReflection ; 144GFX_CHECK_CALL_ABORT (loadGraphicsProgram ( 145device , 146shaderProgram , 147"resolve-resource-shader" , 148"vertexMain" , 149"fragmentMain" , 150slangReflection )); 151 152ColorTargetDesc colorTarget = {}; 153colorTarget .format = format ; 154 155RenderPipelineDesc pipelineDesc = {}; 156pipelineDesc .program = shaderProgram .get (); 157pipelineDesc .inputLayout = inputLayout ; 158pipelineDesc .targets = & colorTarget ; 159pipelineDesc .targetCount = 1 ; 160pipelineDesc .primitiveTopology = PrimitiveTopology ::TriangleList ; 161pipelineDesc .depthStencil .depthTestEnable = false; 162pipelineDesc .depthStencil .depthWriteEnable = false; 163pipelineState = device -> createRenderPipeline (pipelineDesc ); 164SLANG_CHECK_ABORT (pipelineState ); 165 } 166 167void submitGPUWork ( 168SubresourceRange msaaSubresource , 169SubresourceRange dstSubresource , 170Extent3D extent ) 171 { 172auto queue = device -> getQueue (QueueType ::Graphics ); 173 174ComPtr < ICommandEncoder > encoder = queue -> createCommandEncoder (); 175 176// Create render target view 177TextureViewDesc rtvDesc = {}; 178rtvDesc .format = format ; 179auto rtv = device -> createTextureView (msaaTexture ,rtvDesc ); 180 181RenderPassColorAttachment colorAttachment = {}; 182colorAttachment .view = rtv ; 183colorAttachment .loadOp = LoadOp ::Clear ; 184colorAttachment .storeOp = StoreOp ::Store ; 185float clearColor [4 ]= {0.0f ,0.0f ,0.0f ,0.0f }; 186memcpy (colorAttachment .clearValue ,clearColor ,sizeof (clearColor )); 187 188RenderPassDesc passDesc = {}; 189passDesc .colorAttachments = & colorAttachment ; 190passDesc .colorAttachmentCount = 1 ; 191 192auto renderEncoder = encoder -> beginRenderPass (passDesc ); 193auto rootObject = renderEncoder -> bindPipeline (pipelineState ); 194 195Viewport viewport = {}; 196viewport .maxZ = 1.0f ; 197viewport .extentX = kWidth ; 198viewport .extentY = kHeight ; 199 200RenderState state = {}; 201state .viewports [0 ]= viewport ; 202state .viewportCount = 1 ; 203state .vertexBuffers [0 ]= BufferOffsetPair (vertexBuffer ,0 ); 204state .vertexBufferCount = 1 ; 205renderEncoder -> setRenderState (state ); 206 207DrawArguments drawArgs = {}; 208drawArgs .vertexCount = kVertexCount ; 209drawArgs .startVertexLocation = 0 ; 210renderEncoder -> draw (drawArgs ); 211renderEncoder -> end (); 212 213// Note: slang-rhi doesn't have a direct resolveResource function 214// For MSAA resolve, we would typically use a resolve render pass or blit operation 215// For this test, we'll use a simple copy operation instead 216encoder -> copyTexture ( 217dstTexture , 218dstSubresource , 219Offset3D {0 ,0 ,0 }, 220msaaTexture , 221msaaSubresource , 222Offset3D {0 ,0 ,0 }, 223extent ); 224encoder -> setTextureState ( 225dstTexture , 226dstSubresource , 227ResourceState ::CopySource ); 228 229queue -> submit (encoder -> finish ()); 230queue -> waitOnHost (); 231 } 232 233void checkTestResults ( 234int pixelCount , 235int channelCount , 236const int * testXCoords , 237const int * testYCoords , 238float * testResults ) 239 { 240// Read texture values back from four specific pixels located within the triangles 241// and compare against expected values (because testing every single pixel will be too long 242// and tedious and requires maintaining reference images). 243ComPtr < ISlangBlob > resultBlob ; 244size_t rowPitch = 0 ; 245size_t pixelSize = 0 ; 246GFX_CHECK_CALL_ABORT (device -> readTexture ( 247dstTexture , 2480 ,// layer 2490 ,// mip 250resultBlob .writeRef (), 251nullptr ));// SubresourceLayout output is optional 252auto result = (float * )resultBlob -> getBufferPointer (); 253 254int cursor = 0 ; 255for (int i = 0 ;i < pixelCount ;++ i ) 256 { 257auto x = testXCoords [i ]; 258auto y = testYCoords [i ]; 259auto pixelPtr = result + x * channelCount + y * rowPitch /sizeof (float ); 260for (int j = 0 ;j < channelCount ;++ j ) 261 { 262testResults [cursor ]= pixelPtr [j ]; 263cursor ++ ; 264 } 265 } 266 267float expectedResult []= {0.5f ,0.5f ,0.0f ,1.0f ,1.0f ,0.0f ,0.0f ,1.0f ,0.5f ,0.0f ,0.0f , 2681.0f ,0.0f ,1.0f ,0.0f ,1.0f ,0.0f ,0.0f ,0.0f ,1.0f ,0.0f ,0.5f , 2690.5f ,1.0f ,0.0f ,0.0f ,1.0f ,1.0f ,0.0f ,0.0f ,0.5f ,1.0f }; 270SLANG_CHECK (memcmp (testResults ,expectedResult ,128 )== 0 ); 271 } 272}; 273 274struct ResolveResourceSimple :BaseResolveResourceTest 275{ 276void run () 277 { 278Extent3D extent = {}; 279extent .width = kWidth ; 280extent .height = kHeight ; 281extent .depth = 1 ; 282 283TextureInfo msaaTextureInfo = {extent ,1 ,1 ,nullptr }; 284TextureInfo dstTextureInfo = {extent ,1 ,1 ,nullptr }; 285 286createRequiredResources (msaaTextureInfo ,dstTextureInfo ,format ); 287 288SubresourceRange msaaSubresource = {}; 289msaaSubresource .layer = 0 ; 290msaaSubresource .layerCount = 1 ; 291msaaSubresource .mip = 0 ; 292msaaSubresource .mipCount = 1 ; 293 294SubresourceRange dstSubresource = {}; 295dstSubresource .layer = 0 ; 296dstSubresource .layerCount = 1 ; 297dstSubresource .mip = 0 ; 298dstSubresource .mipCount = 1 ; 299 300submitGPUWork (msaaSubresource ,dstSubresource ,extent ); 301 302const int kPixelCount = 8 ; 303const int kChannelCount = 4 ; 304int testXCoords [kPixelCount ]= {64 ,127 ,191 ,64 ,191 ,64 ,127 ,191 }; 305int testYCoords [kPixelCount ]= {64 ,64 ,64 ,127 ,127 ,191 ,191 ,191 }; 306float testResults [kPixelCount * kChannelCount ]; 307 308checkTestResults (kPixelCount ,kChannelCount ,testXCoords ,testYCoords ,testResults ); 309 } 310}; 311 312template < typename T > 313void resolveResourceTestImpl (IDevice * device ,UnitTestContext * context ) 314{ 315T test ; 316test .init (device ,context ); 317test .run (); 318} 319}// namespace 320 321namespace gfx_test 322{ 323SLANG_UNIT_TEST (resolveResourceSimpleD3D12 ) 324{ 325runTestImpl ( 326resolveResourceTestImpl < ResolveResourceSimple > , 327unitTestContext , 328DeviceType ::D3D12 ); 329} 330 331SLANG_UNIT_TEST (resolveResourceSimpleVulkan ) 332{ 333runTestImpl ( 334resolveResourceTestImpl < ResolveResourceSimple > , 335unitTestContext , 336DeviceType ::Vulkan ); 337} 338}// namespace gfx_test 339 340#endif