@@ -169,6 +169,157 @@ void InlineRayTracingInComputePplnReferenceMtl(ISwapChain* pSwapChain)
169169 }
170170}
171171
172+ void RayTracingPRSReferenceMtl (ISwapChain* pSwapChain)
173+ {
174+ auto * const pEnv = TestingEnvironmentMtl::GetInstance ();
175+ auto const mtlDevice = pEnv->GetMtlDevice ();
176+
177+ if (@available (macos 11.0 , ios 14.0 , *))
178+ {
179+ @autoreleasepool
180+ {
181+ auto * progSrc = [NSString stringWithUTF8String: MSL: :RayTracingTest9_CS.c_str ()];
182+ NSError *errors = nil ; // Autoreleased
183+ id <MTLLibrary > library = [mtlDevice newLibraryWithSource: progSrc
184+ options: nil
185+ error: &errors];
186+ ASSERT_TRUE (library != nil );
187+ [library autorelease ];
188+
189+ id <MTLFunction > computeFunc = [library newFunctionWithName: @" CSMain" ];
190+ ASSERT_TRUE (computeFunc != nil );
191+ [computeFunc autorelease ];
192+
193+ auto * computePipeline = [mtlDevice newComputePipelineStateWithFunction: computeFunc error: &errors];
194+ ASSERT_TRUE (computePipeline != nil );
195+ [computePipeline autorelease ];
196+
197+ auto * pTestingSwapChainMtl = ValidatedCast<TestingSwapChainMtl>(pSwapChain);
198+ auto * pUAV = pTestingSwapChainMtl->GetCurrentBackBufferUAV ();
199+ auto * mtlTexture = ValidatedCast<ITextureViewMtl>(pUAV)->GetMtlTexture ();
200+ const auto & SCDesc = pTestingSwapChainMtl->GetDesc ();
201+
202+ const auto & Vertices = TestingConstants::TriangleClosestHit::Vertices;
203+ auto * mtlVertexBuf = [mtlDevice newBufferWithLength: sizeof (Vertices)
204+ options: (MTLResourceCPUCacheModeDefaultCache | MTLResourceStorageModeShared | MTLResourceHazardTrackingModeDefault )];
205+ ASSERT_TRUE (mtlVertexBuf != nil );
206+ [mtlVertexBuf autorelease ];
207+ memcpy ([mtlVertexBuf contents ], Vertices, sizeof (Vertices));
208+
209+ auto * mtlBLASDesc = [MTLPrimitiveAccelerationStructureDescriptor descriptor ];
210+ auto * mtlTriangleDesc = [MTLAccelerationStructureTriangleGeometryDescriptor descriptor ];
211+ auto * mtlTriangleArr = [[[NSMutableArray <MTLAccelerationStructureTriangleGeometryDescriptor*> alloc] initWithCapacity: 1 ] autorelease ];
212+
213+ mtlTriangleDesc.intersectionFunctionTableOffset = 0 ;
214+ mtlTriangleDesc.allowDuplicateIntersectionFunctionInvocation = false ;
215+ mtlTriangleDesc.opaque = true ;
216+ mtlTriangleDesc.triangleCount = _countof (Vertices) / 3 ;
217+ mtlTriangleDesc.vertexBuffer = mtlVertexBuf;
218+ mtlTriangleDesc.vertexBufferOffset = 0 ;
219+ mtlTriangleDesc.vertexStride = sizeof (Vertices[0 ]);
220+ mtlTriangleDesc.indexType = MTLIndexTypeUInt32 ;
221+ [mtlTriangleArr addObject: mtlTriangleDesc];
222+
223+ [mtlBLASDesc setUsage: MTLAccelerationStructureUsageNone];
224+ [mtlBLASDesc setGeometryDescriptors: mtlTriangleArr];
225+
226+ const auto mtlBLASSizes = [mtlDevice accelerationStructureSizesWithDescriptor: mtlBLASDesc];
227+ auto * mtlBLAS = [mtlDevice newAccelerationStructureWithSize: mtlBLASSizes.accelerationStructureSize];
228+ ASSERT_TRUE (mtlBLAS != nil );
229+ [mtlBLAS autorelease ];
230+
231+ auto * mtlInstanceBuf = [mtlDevice newBufferWithLength: sizeof (MTLAccelerationStructureInstanceDescriptor)
232+ options: (MTLResourceCPUCacheModeDefaultCache | MTLResourceStorageModeShared | MTLResourceHazardTrackingModeDefault )];
233+ ASSERT_TRUE (mtlInstanceBuf != nil );
234+ [mtlInstanceBuf autorelease ];
235+ auto * Instances = static_cast <MTLAccelerationStructureInstanceDescriptor*>([mtlInstanceBuf contents ]);
236+
237+ Instances->transformationMatrix .columns [0 ] = MTLPackedFloat3{1 .0f , 0 .0f , 0 .0f };
238+ Instances->transformationMatrix .columns [1 ] = MTLPackedFloat3{0 .0f , 1 .0f , 0 .0f };
239+ Instances->transformationMatrix .columns [2 ] = MTLPackedFloat3{0 .0f , 0 .0f , 1 .0f };
240+ Instances->transformationMatrix .columns [3 ] = MTLPackedFloat3{0 .0f , 0 .0f , 0 .0f };
241+ Instances->accelerationStructureIndex = 0 ;
242+ Instances->intersectionFunctionTableOffset = 0 ;
243+ Instances->mask = ~0u ;
244+ Instances->options = MTLAccelerationStructureInstanceOptionOpaque;
245+
246+ auto * mtlTLASDesc = [MTLInstanceAccelerationStructureDescriptor descriptor ];
247+ auto * mtlAccelStrArr = [[[NSMutableArray <id <MTLAccelerationStructure>> alloc] initWithCapacity: 1 ] autorelease ];
248+ [mtlAccelStrArr addObject: mtlBLAS];
249+ [mtlTLASDesc setUsage: MTLAccelerationStructureUsageNone];
250+ [mtlTLASDesc setInstanceCount: 1 ];
251+ [mtlTLASDesc setInstanceDescriptorBuffer: mtlInstanceBuf];
252+ [mtlTLASDesc setInstancedAccelerationStructures: mtlAccelStrArr];
253+
254+ const auto mtlTLASSizes = [mtlDevice accelerationStructureSizesWithDescriptor: mtlTLASDesc];
255+ auto * mtlTLAS = [mtlDevice newAccelerationStructureWithSize: mtlTLASSizes.accelerationStructureSize];
256+ ASSERT_TRUE (mtlTLAS != nil );
257+ [mtlTLAS autorelease ];
258+
259+ const auto ScratchBuffSize = std::max (mtlBLASSizes.buildScratchBufferSize , mtlTLASSizes.buildScratchBufferSize );
260+ auto * ScratchBuf = [mtlDevice newBufferWithLength: ScratchBuffSize
261+ options: (MTLResourceCPUCacheModeDefaultCache | MTLResourceStorageModePrivate | MTLResourceHazardTrackingModeDefault )];
262+ ASSERT_TRUE (ScratchBuf != nil );
263+ [ScratchBuf autorelease ];
264+
265+ auto * ConstBuf = [mtlDevice newBufferWithLength: 256 * 3
266+ options: (MTLResourceCPUCacheModeDefaultCache | MTLResourceStorageModeShared | MTLResourceHazardTrackingModeDefault )];
267+ ASSERT_TRUE (ConstBuf != nil );
268+ [ConstBuf autorelease ];
269+
270+ uint8_t * pMapped = (uint8_t *)ConstBuf.contents ;
271+ const float Const1[] = {0 .5f , 0 .9f , 0 .75f , 1 .0f };
272+ const float Const2[] = {0 .2f , 0 .0f , 1 .0f , 0 .5f };
273+ const float Const3[] = {0 .9f , 0 .1f , 0 .2f , 1 .0f };
274+ memcpy (pMapped + 0 , Const1, sizeof (Const1));
275+ memcpy (pMapped + 256 , Const2, sizeof (Const2));
276+ memcpy (pMapped + 512 , Const3, sizeof (Const3));
277+
278+ auto * mtlCommandQueue = pEnv->GetMtlCommandQueue ();
279+ auto * mtlCommandBuffer = [mtlCommandQueue commandBuffer ]; // Autoreleased
280+ auto * asEncoder = [mtlCommandBuffer accelerationStructureCommandEncoder ]; // Autoreleased
281+ ASSERT_TRUE (asEncoder != nil );
282+
283+ [asEncoder buildAccelerationStructure: mtlBLAS
284+ descriptor: mtlBLASDesc
285+ scratchBuffer: ScratchBuf
286+ scratchBufferOffset: 0 ];
287+ [asEncoder buildAccelerationStructure: mtlTLAS
288+ descriptor: mtlTLASDesc
289+ scratchBuffer: ScratchBuf
290+ scratchBufferOffset: 0 ];
291+ [asEncoder endEncoding ];
292+
293+ auto * cmdEncoder = [mtlCommandBuffer computeCommandEncoder ]; // Autoreleased
294+ ASSERT_TRUE (cmdEncoder != nil );
295+
296+ [cmdEncoder setComputePipelineState: computePipeline];
297+ [cmdEncoder setTexture: mtlTexture
298+ atIndex: 0 ];
299+ [cmdEncoder setBuffer: ConstBuf
300+ offset: 0
301+ atIndex: 0 ];
302+ [cmdEncoder setBuffer: ConstBuf
303+ offset: 256
304+ atIndex: 1 ];
305+ [cmdEncoder setBuffer: ConstBuf
306+ offset: 512
307+ atIndex: 2 ];
308+ [cmdEncoder setAccelerationStructure: mtlTLAS
309+ atBufferIndex: 3 ];
310+ [cmdEncoder setAccelerationStructure: mtlTLAS
311+ atBufferIndex: 4 ];
312+ [cmdEncoder dispatchThreadgroups: MTLSizeMake ((SCDesc.Width + 15 ) / 16 , (SCDesc.Height + 15 ) / 16 , 1 )
313+ threadsPerThreadgroup: MTLSizeMake (16 , 16 , 1 )];
314+
315+ [cmdEncoder endEncoding ];
316+ [mtlCommandBuffer commit ];
317+ [mtlCommandBuffer waitUntilCompleted ];
318+
319+ } // @autoreleasepool
320+ } // @available
321+ }
322+
172323} // namespace Testing
173324
174325} // namespace Diligent
0 commit comments