44using namespace rhi ;
55using namespace rhi ::testing;
66
7- static Result createTestTexture (IDevice* device, ITexture** outTexture)
7+ static Result createTestTexture (IDevice* device, ISampler* sampler, ITexture** outTexture)
88{
99 ComPtr<ITexture> texture;
1010 TextureDesc desc = {};
@@ -14,6 +14,7 @@ static Result createTestTexture(IDevice* device, ITexture** outTexture)
1414 desc.mipCount = 2 ;
1515 desc.memoryType = MemoryType::DeviceLocal;
1616 desc.usage = TextureUsage::ShaderResource | TextureUsage::CopyDestination | TextureUsage::CopySource;
17+ desc.sampler = sampler;
1718
1819 // mip 0
1920 // ---------------------
@@ -62,95 +63,77 @@ struct TestRecord
6263 float expectedColor[4 ];
6364};
6465
65- struct SamplerTest
66+ static void testSampler (IDevice* device, const SamplerDesc& samplerDesc, span<TestRecord> testRecords)
6667{
67- static constexpr size_t kMaxRecords = 32 ;
68+ ComPtr<ISampler> sampler;
69+ REQUIRE_CALL (device->createSampler (samplerDesc, sampler.writeRef ()));
6870
69- ComPtr<IDevice> device;
7071 ComPtr<ITexture> texture;
72+ // On CUDA, we need to have a sampler associated with the texture for sampling to work.
73+ REQUIRE_CALL (
74+ createTestTexture (device, device->getDeviceType () == DeviceType::CUDA ? sampler : nullptr , texture.writeRef ())
75+ );
76+
77+ ComPtr<IShaderProgram> shaderProgram;
78+ REQUIRE_CALL (loadProgram (device, " test-sampler" , " sampleTexture" , shaderProgram.writeRef ()));
79+
80+ ComputePipelineDesc pipelineDesc = {};
81+ pipelineDesc.program = shaderProgram.get ();
82+ ComPtr<IComputePipeline> pipeline;
83+ REQUIRE_CALL (device->createComputePipeline (pipelineDesc, pipeline.writeRef ()));
84+
85+ BufferDesc bufferDesc = {};
86+ bufferDesc.size = testRecords.size () * sizeof (TestInput);
87+ bufferDesc.elementSize = sizeof (TestInput);
88+ bufferDesc.usage = BufferUsage::ShaderResource | BufferUsage::CopyDestination;
7189 ComPtr<IBuffer> inputBuffer;
90+ REQUIRE_CALL (device->createBuffer (bufferDesc, nullptr , inputBuffer.writeRef ()));
91+
92+ bufferDesc.size = testRecords.size () * sizeof (TestOutput);
93+ bufferDesc.elementSize = sizeof (TestOutput);
94+ bufferDesc.usage = BufferUsage::UnorderedAccess | BufferUsage::CopySource;
7295 ComPtr<IBuffer> resultBuffer;
73- ComPtr<IComputePipeline> pipeline ;
96+ REQUIRE_CALL (device-> createBuffer (bufferDesc, nullptr , resultBuffer. writeRef ())) ;
7497
75- void init (IDevice* device_)
98+ std::vector<TestInput> inputData;
99+ for (const auto & record : testRecords)
76100 {
77- this ->device = device_;
78- REQUIRE_CALL (createTestTexture (device, texture.writeRef ()));
79-
80- ComPtr<IShaderProgram> shaderProgram;
81- REQUIRE_CALL (loadProgram (device, " test-sampler" , " sampleTexture" , shaderProgram.writeRef ()));
82-
83- ComputePipelineDesc pipelineDesc = {};
84- pipelineDesc.program = shaderProgram.get ();
85- REQUIRE_CALL (device->createComputePipeline (pipelineDesc, pipeline.writeRef ()));
86-
87- BufferDesc bufferDesc = {};
88- bufferDesc.size = kMaxRecords * sizeof (TestInput);
89- bufferDesc.elementSize = sizeof (TestInput);
90- bufferDesc.usage = BufferUsage::ShaderResource | BufferUsage::CopyDestination;
91- REQUIRE_CALL (device->createBuffer (bufferDesc, nullptr , inputBuffer.writeRef ()));
92-
93- bufferDesc.size = kMaxRecords * sizeof (TestOutput);
94- bufferDesc.elementSize = sizeof (TestOutput);
95- bufferDesc.usage = BufferUsage::UnorderedAccess | BufferUsage::CopySource;
96- REQUIRE_CALL (device->createBuffer (bufferDesc, nullptr , resultBuffer.writeRef ()));
101+ inputData.push_back ({record.u , record.v , record.level , 0 .f });
97102 }
98-
99- void check (ISampler* sampler, span<TestRecord> testRecords)
103+ ComPtr<ICommandQueue> queue = device->getQueue (QueueType::Graphics);
104+ ComPtr<ICommandEncoder> encoder = queue->createCommandEncoder ();
105+ encoder->uploadBufferData (inputBuffer, 0 , inputData.size () * sizeof (TestInput), inputData.data ());
106+ IComputePassEncoder* passEncoder = encoder->beginComputePass ();
107+ IShaderObject* rootObject = passEncoder->bindPipeline (pipeline);
108+ ShaderCursor cursor (rootObject);
109+ cursor[" texture" ].setBinding (texture);
110+ cursor[" sampler" ].setBinding (sampler);
111+ cursor[" inputs" ].setBinding (inputBuffer);
112+ cursor[" results" ].setBinding (resultBuffer);
113+ cursor[" count" ].setData ((uint32_t )testRecords.size ());
114+ passEncoder->dispatchCompute ((uint32_t )testRecords.size (), 1 , 1 );
115+ passEncoder->end ();
116+ queue->submit (encoder->finish ());
117+ queue->waitOnHost ();
118+
119+ ComPtr<ISlangBlob> resultData;
120+ REQUIRE_CALL (device->readBuffer (resultBuffer, 0 , testRecords.size () * sizeof (TestOutput), resultData.writeRef ()));
121+ const TestOutput* output = (const TestOutput*)resultData->getBufferPointer ();
122+ for (size_t i = 0 ; i < testRecords.size (); i++)
100123 {
101- REQUIRE (testRecords.size () <= kMaxRecords );
102- std::vector<TestInput> inputData;
103- for (const auto & record : testRecords)
124+ const TestRecord& record = testRecords[i];
125+ CAPTURE (record.u );
126+ CAPTURE (record.v );
127+ CAPTURE (record.level );
128+ for (size_t j = 0 ; j < 4 ; j++)
104129 {
105- inputData.push_back ({record.u , record.v , record.level , 0 .f });
106- }
107- ComPtr<ICommandQueue> queue = device->getQueue (QueueType::Graphics);
108- ComPtr<ICommandEncoder> encoder = queue->createCommandEncoder ();
109- encoder->uploadBufferData (inputBuffer, 0 , inputData.size () * sizeof (TestInput), inputData.data ());
110- IComputePassEncoder* passEncoder = encoder->beginComputePass ();
111- IShaderObject* rootObject = passEncoder->bindPipeline (pipeline);
112- ShaderCursor cursor (rootObject);
113- cursor[" texture" ].setBinding (texture);
114- cursor[" sampler" ].setBinding (sampler);
115- cursor[" inputs" ].setBinding (inputBuffer);
116- cursor[" results" ].setBinding (resultBuffer);
117- cursor[" count" ].setData ((uint32_t )testRecords.size ());
118- passEncoder->dispatchCompute ((uint32_t )testRecords.size (), 1 , 1 );
119- passEncoder->end ();
120- queue->submit (encoder->finish ());
121- queue->waitOnHost ();
122-
123- ComPtr<ISlangBlob> resultData;
124- REQUIRE_CALL (
125- device->readBuffer (resultBuffer, 0 , testRecords.size () * sizeof (TestOutput), resultData.writeRef ())
126- );
127- const TestOutput* output = (const TestOutput*)resultData->getBufferPointer ();
128- for (size_t i = 0 ; i < testRecords.size (); i++)
129- {
130- const TestRecord& record = testRecords[i];
131- CAPTURE (record.u );
132- CAPTURE (record.v );
133- CAPTURE (record.level );
134- for (size_t j = 0 ; j < 4 ; j++)
135- {
136- CAPTURE (j);
137- REQUIRE_EQ (output[i].color [j], testRecords[i].expectedColor [j]);
138- }
130+ CAPTURE (j);
131+ REQUIRE_EQ (output[i].color [j], testRecords[i].expectedColor [j]);
139132 }
140133 }
141- };
142-
143- static void testSampler (IDevice* device, const SamplerDesc& samplerDesc, span<TestRecord> testRecords)
144- {
145- ComPtr<ISampler> sampler;
146- REQUIRE_CALL (device->createSampler (samplerDesc, sampler.writeRef ()));
147-
148- SamplerTest test;
149- test.init (device);
150- test.check (sampler, testRecords);
151134}
152135
153- GPU_TEST_CASE (" sampler-filter-point" , D3D11 | D3D12 | Vulkan | Metal | WGPU)
136+ GPU_TEST_CASE (" sampler-filter-point" , D3D11 | D3D12 | Vulkan | Metal | WGPU | CUDA )
154137{
155138 SamplerDesc desc = {};
156139 desc.minFilter = TextureFilteringMode::Point;
@@ -178,7 +161,7 @@ GPU_TEST_CASE("sampler-filter-point", D3D11 | D3D12 | Vulkan | Metal | WGPU)
178161 testSampler (device, desc, testRecords);
179162}
180163
181- GPU_TEST_CASE (" sampler-filter-linear" , D3D11 | D3D12 | Vulkan | Metal | WGPU)
164+ GPU_TEST_CASE (" sampler-filter-linear" , D3D11 | D3D12 | Vulkan | Metal | WGPU | CUDA )
182165{
183166 SamplerDesc desc = {};
184167 desc.minFilter = TextureFilteringMode::Linear;
@@ -208,7 +191,7 @@ GPU_TEST_CASE("sampler-filter-linear", D3D11 | D3D12 | Vulkan | Metal | WGPU)
208191 testSampler (device, desc, testRecords);
209192}
210193
211- GPU_TEST_CASE (" sampler-border-black-transparent" , D3D11 | D3D12 | Vulkan | Metal)
194+ GPU_TEST_CASE (" sampler-border-black-transparent" , D3D11 | D3D12 | Vulkan | Metal | CUDA )
212195{
213196 SamplerDesc desc = {};
214197 desc.addressU = TextureAddressingMode::ClampToBorder;
@@ -223,7 +206,7 @@ GPU_TEST_CASE("sampler-border-black-transparent", D3D11 | D3D12 | Vulkan | Metal
223206 testSampler (device, desc, testRecords);
224207}
225208
226- GPU_TEST_CASE (" sampler-border-black-opaque" , D3D11 | D3D12 | Vulkan | Metal)
209+ GPU_TEST_CASE (" sampler-border-black-opaque" , D3D11 | D3D12 | Vulkan | Metal | CUDA )
227210{
228211 SamplerDesc desc = {};
229212 desc.addressU = TextureAddressingMode::ClampToBorder;
@@ -243,7 +226,7 @@ GPU_TEST_CASE("sampler-border-black-opaque", D3D11 | D3D12 | Vulkan | Metal)
243226 testSampler (device, desc, testRecords);
244227}
245228
246- GPU_TEST_CASE (" sampler-border-white-opaque" , D3D11 | D3D12 | Vulkan | Metal)
229+ GPU_TEST_CASE (" sampler-border-white-opaque" , D3D11 | D3D12 | Vulkan | Metal | CUDA )
247230{
248231 SamplerDesc desc = {};
249232 desc.addressU = TextureAddressingMode::ClampToBorder;
@@ -262,7 +245,7 @@ GPU_TEST_CASE("sampler-border-white-opaque", D3D11 | D3D12 | Vulkan | Metal)
262245 testSampler (device, desc, testRecords);
263246}
264247
265- GPU_TEST_CASE (" sampler-border-custom-color" , D3D11 | D3D12 | Vulkan | Metal)
248+ GPU_TEST_CASE (" sampler-border-custom-color" , D3D11 | D3D12 | Vulkan | Metal | CUDA )
266249{
267250 if (!device->hasFeature (Feature::CustomBorderColor))
268251 SKIP (" Custom border color not supported" );
0 commit comments