20#include <boost/test/unit_test.hpp>
22#include <checkerboard_comp.h>
23#include <workgroup_comp.h>
24#include <reduction_comp.h>
25#include <multipass_comp.h>
51 std::shared_ptr<GPU_COMPUTE> gpu;
52 std::vector<RHI_BufferHandle> buffers;
53 std::vector<RHI_ComputePipelineHandle> pipelines;
59 gpu->DestroyBindGroup( group );
60 gpu->DestroyBindGroupLayout( layout );
62 for(
auto pipeline : pipelines )
63 gpu->DestroyPipeline( pipeline );
65 for(
auto buffer : buffers )
66 gpu->DestroyBuffer( buffer );
71 auto buffer = gpu->CreateStorageBuffer( aBytes );
73 buffers.push_back( buffer );
79 auto pipeline = gpu->CreatePipeline( aDesc );
81 pipelines.push_back( pipeline );
85 void Group(
const RHI_BIND_GROUP_LAYOUT_DESC& aLayout,
const std::vector<RHI_BIND_GROUP_RESOURCE>& aEntries )
87 layout = gpu->CreateBindGroupLayout( aLayout );
89 group = gpu->CreateBindGroup( { layout, aEntries } );
130 std::array<uint32_t, 2> data{ 37, 19 };
135 const std::array<uint32_t, 2>
expected{ 37, 19 };
136 const auto* bytes =
reinterpret_cast<const uint8_t*
>(
expected.data() );
138 BOOST_REQUIRE_EQUAL( job.
Commands().size(), 2 );
140 for(
const auto& command : job.
Commands() )
145 BOOST_CHECK( !invalid.
IsValid() );
159 auto buffer = gpu->CreateStorageBuffer( 11 );
161 std::array<uint8_t, 11> initial{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
162 std::array<uint8_t, 7> replacement{ 31, 32, 33, 34, 35, 36, 37 };
163 std::array<uint8_t, 11> first{};
164 std::array<uint8_t, 8> second{};
165 const std::array<uint8_t, 8>
expected{ 2, 31, 32, 33, 34, 35, 36, 37 };
167 job.
Upload( buffer, initial.data(), initial.size() );
168 job.
Readback( buffer, 0, first.size(), first.data() );
169 job.
Upload( buffer, replacement.data(), replacement.size(), 3 );
170 replacement.fill( 0 );
171 job.
Readback( buffer, 2, second.size(), second.data() );
173 gpu->DestroyBuffer( buffer );
189 RESOURCES resources{ gpu };
190 constexpr uint32_t width = 37, height = 19;
191 const std::array<uint32_t, 2> params{ width, height };
192 const auto layout = StorageLayout();
193 auto buffer = resources.Buffer( width * height *
sizeof( uint32_t ) );
194 resources.Group( layout, { { 1, buffer } } );
196 for(
auto workgroup : { std::array<uint32_t, 2>{ 8, 8 }, std::array<uint32_t, 2>{ 16, 4 } } )
198 for( uint32_t rb = 0; rb < 2; ++rb )
201 desc.
shader = k_checkerboard_comp;
207 auto pipeline = resources.Pipeline( desc );
208 std::vector<uint32_t> cells( width * height, 0xfeedu );
210 job.
Upload( buffer, cells.data(), cells.size() *
sizeof( cells[0] ) );
211 std::fill( cells.begin(), cells.end(), 0u );
212 job.
Bind( pipeline );
215 job.
Dispatch( ( width + workgroup[0] - 1 ) / workgroup[0], ( height + workgroup[1] - 1 ) / workgroup[1] );
216 job.
Readback( buffer, 0, cells.size() *
sizeof( cells[0] ), cells.data() );
219 for( uint32_t y = 0; y < height; ++y )
221 for( uint32_t x = 0; x < width; ++x )
222 BOOST_CHECK_EQUAL( cells[y * width + x], ( ( x + y ) & 1 ) == rb ? 17u + rb : 0xfeedu );
238 RESOURCES resources{ gpu };
239 auto buffer = resources.Buffer( 2 *
sizeof( uint32_t ) );
240 const auto layout = StorageLayout();
241 resources.Group( layout, { { 1, buffer } } );
243 for(
auto size : { std::array<uint32_t, 2>{ 8, 8 }, std::array<uint32_t, 2>{ 16, 4 } } )
246 desc.
shader = k_workgroup_comp;
250 std::array<uint32_t, 2>
result{};
253 job.
Bind( resources.Pipeline( desc ) );
273 RESOURCES resources{ gpu };
274 constexpr uint32_t groups = 16, localSize = 64;
275 std::vector<float> input( groups * localSize );
277 for(
size_t i = 0; i < input.size(); ++i )
278 input[i] =
static_cast<float>(
static_cast<int>( ( i * 37 ) % 2003 ) - 1001 ) / 8.0f;
280 auto in = resources.Buffer( input.size() *
sizeof(
float ) );
281 auto out = resources.Buffer( groups *
sizeof(
float ) );
282 const auto layout = StorageLayout(
true );
283 resources.Group( layout, { { 1, in }, { 2, out } } );
285 desc.
shader = k_reduction_comp;
289 std::array<float, groups>
result;
292 job.
Upload( in, input.data(), input.size() *
sizeof(
float ) );
294 job.
Bind( resources.Pipeline( desc ) );
304 for( uint32_t local = 0; local < localSize; ++local )
321 RESOURCES resources{ gpu };
322 constexpr uint32_t width = 37, height = 19, iterations = 5;
323 std::array<uint32_t, 2> params{ width, height };
324 auto buffer = resources.Buffer( width * height *
sizeof( uint32_t ) );
325 const auto layout = StorageLayout();
326 resources.Group( layout, { { 1, buffer } } );
327 std::array<RHI_ComputePipelineHandle, 3> pipelines;
329 for( uint32_t pass = 0; pass < pipelines.size(); ++pass )
332 desc.
shader = k_multipass_comp;
336 pipelines[pass] = resources.Pipeline( desc );
339 std::vector<uint32_t>
expected( width * height ),
result( width * height, 0xfeedu );
341 for( uint32_t y = 0; y < height; ++y )
343 for( uint32_t x = 0; x < width; ++x )
344 expected[y * width + x] = ( x + 3 * y ) % 11;
350 const auto pass = [&]( uint32_t aPass )
352 job.
Bind( pipelines[aPass] );
354 job.
Dispatch( ( width + 7 ) / 8, ( height + 7 ) / 8 );
359 for( uint32_t iteration = 0; iteration < iterations; ++iteration )
361 for( uint32_t rb = 0; rb < 2; ++rb )
365 for( uint32_t y = 0; y < height; ++y )
367 for( uint32_t x = 0; x < width; ++x )
369 if( ( ( x + y ) & 1 ) == rb )
371 auto i = y * width + x;
static std::shared_ptr< GPU_COMPUTE > Get()
Return nullptr if compute is unavailable; replace a lost instance on the next call.
Plain owning command data, recordable on any thread without device access.
void Dispatch(uint32_t aGroupsX, uint32_t aGroupsY=1)
const std::vector< COMMAND > & Commands() const
void BindGroup(uint32_t aIndex, RHI_BindGroupHandle aGroup)
void Readback(RHI_BufferHandle aBuffer, size_t aOffset, size_t aBytes, void *aDestination)
void Upload(RHI_BufferHandle aBuffer, const void *aData, size_t aBytes, size_t aOffset=0)
Copy upload bytes immediately.
void Bind(RHI_ComputePipelineHandle aPipeline)
void PushConstants(const void *aData, size_t aBytes)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
@ STORAGE_BUFFER_READONLY
constexpr uint32_t RHI_MAX_PUSH_CONSTANT_BYTES
Largest push constant size SetPushConstants() accepts, in bytes.
bool RhiValidateComputePipelineDesc(const RHI_COMPUTE_PIPELINE_DESC &aDesc)
Validate the portable contract without accessing a GPU or inspecting shader bytecode.
bool RhiValidateComputeBindGroupLayout(const RHI_BIND_GROUP_LAYOUT_DESC &aLayout)
Validate a compute bind group layout.
RHI_HANDLE< RHI_TAG_BUFFER > RHI_BufferHandle
RHI_HANDLE< RHI_TAG_BIND_GROUP > RHI_BindGroupHandle
RHI_HANDLE< RHI_TAG_COMPUTE_PIPELINE > RHI_ComputePipelineHandle
RHI_HANDLE< RHI_TAG_BIND_GROUP_LAYOUT > RHI_BindGroupLayoutHandle
std::vector< RHI_BINDING_ENTRY > entries
std::vector< RHI_SPECIALIZATION_CONSTANT > constants
uint32_t pushConstantBytes
std::vector< RHI_BIND_GROUP_LAYOUT_DESC > bindGroupLayouts
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_CHECK_EQUAL_COLLECTIONS(mixed.begin(), mixed.end(), expMixed.begin(), expMixed.end())
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
VECTOR3I expected(15, 30, 45)
BOOST_AUTO_TEST_CASE(DescriptorValidation)
BOOST_TEST_MESSAGE("Polyline has "<< chain.PointCount()<< " points")
wxString result
Test unit parsing edge cases and error handling.
BOOST_CHECK_EQUAL(result, "25.4")