2
0

RendererMTL.mm 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2025 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #include <TestFramework.h>
  5. #include <Renderer/MTL/RendererMTL.h>
  6. #include <Renderer/MTL/RenderPrimitiveMTL.h>
  7. #include <Renderer/MTL/RenderInstancesMTL.h>
  8. #include <Renderer/MTL/PipelineStateMTL.h>
  9. #include <Renderer/MTL/VertexShaderMTL.h>
  10. #include <Renderer/MTL/PixelShaderMTL.h>
  11. #include <Renderer/MTL/TextureMTL.h>
  12. #include <Renderer/MTL/FatalErrorIfFailedMTL.h>
  13. #include <Window/ApplicationWindowMacOS.h>
  14. #include <Utils/Log.h>
  15. #include <Utils/AssetStream.h>
  16. #include <Jolt/Core/Profiler.h>
  17. RendererMTL::~RendererMTL()
  18. {
  19. [mCommandQueue release];
  20. [mShadowRenderPass release];
  21. [mShaderLibrary release];
  22. }
  23. void RendererMTL::Initialize(ApplicationWindow *inWindow)
  24. {
  25. Renderer::Initialize(inWindow);
  26. mView = static_cast<ApplicationWindowMacOS *>(inWindow)->GetMetalView();
  27. id<MTLDevice> device = GetDevice();
  28. // Load the shader library containing all shaders for the test framework
  29. NSError *error = nullptr;
  30. NSURL *url = [NSURL URLWithString: [NSString stringWithCString: (AssetStream::sGetAssetsBasePath() + "Shaders/MTL/Shaders.metallib").c_str() encoding: NSUTF8StringEncoding]];
  31. mShaderLibrary = [device newLibraryWithURL: url error: &error];
  32. FatalErrorIfFailed(error);
  33. // Create depth only texture (no color buffer, as seen from light)
  34. mShadowMap = new TextureMTL(this, cShadowMapSize, cShadowMapSize);
  35. // Create render pass descriptor for shadow pass
  36. mShadowRenderPass = [[MTLRenderPassDescriptor alloc] init];
  37. mShadowRenderPass.depthAttachment.texture = mShadowMap->GetTexture();
  38. mShadowRenderPass.depthAttachment.loadAction = MTLLoadActionClear;
  39. mShadowRenderPass.depthAttachment.storeAction = MTLStoreActionStore;
  40. mShadowRenderPass.depthAttachment.clearDepth = 0.0f;
  41. // Create the command queue
  42. mCommandQueue = [device newCommandQueue];
  43. }
  44. bool RendererMTL::BeginFrame(const CameraState &inCamera, float inWorldScale)
  45. {
  46. JPH_PROFILE_FUNCTION();
  47. Renderer::BeginFrame(inCamera, inWorldScale);
  48. // Update frame index
  49. mFrameIndex = (mFrameIndex + 1) % cFrameCount;
  50. // Create a new command buffer
  51. mCommandBuffer = [mCommandQueue commandBuffer];
  52. // Create shadow render encoder
  53. mRenderEncoder = [mCommandBuffer renderCommandEncoderWithDescriptor: mShadowRenderPass];
  54. // Set viewport to size of shadow map
  55. [mRenderEncoder setViewport: (MTLViewport){ 0.0, 0.0, double(cShadowMapSize), double(cShadowMapSize), 0.0, 1.0 }];
  56. // Set pixel shader constants
  57. [mRenderEncoder setFragmentBytes: &mPSBuffer length: sizeof(mPSBuffer) atIndex: 0];
  58. // Counter clockwise is default winding order
  59. [mRenderEncoder setFrontFacingWinding: MTLWindingCounterClockwise];
  60. // Start with projection mode
  61. SetProjectionMode();
  62. return true;
  63. }
  64. void RendererMTL::EndShadowPass()
  65. {
  66. // Finish the shadow encoder
  67. [mRenderEncoder endEncoding];
  68. mRenderEncoder = nil;
  69. // Get the descriptor for the main window
  70. MTLRenderPassDescriptor *render_pass_descriptor = mView.currentRenderPassDescriptor;
  71. if (render_pass_descriptor == nullptr)
  72. return;
  73. // Create render encoder
  74. mRenderEncoder = [mCommandBuffer renderCommandEncoderWithDescriptor: render_pass_descriptor];
  75. // Set viewport
  76. [mRenderEncoder setViewport: (MTLViewport){ 0.0, 0.0, double(mWindow->GetWindowWidth()), double(mWindow->GetWindowHeight()), 0.0, 1.0 }];
  77. // Set pixel shader constants
  78. [mRenderEncoder setFragmentBytes: &mPSBuffer length: sizeof(mPSBuffer) atIndex: 0];
  79. // Counter clockwise is default winding order
  80. [mRenderEncoder setFrontFacingWinding: MTLWindingCounterClockwise];
  81. // Start with projection mode
  82. SetProjectionMode();
  83. }
  84. void RendererMTL::EndFrame()
  85. {
  86. JPH_PROFILE_FUNCTION();
  87. // Finish the encoder
  88. [mRenderEncoder endEncoding];
  89. mRenderEncoder = nil;
  90. // Schedule a present
  91. [mCommandBuffer presentDrawable: mView.currentDrawable];
  92. // Commit the command buffer
  93. [mCommandBuffer commit];
  94. Renderer::EndFrame();
  95. }
  96. void RendererMTL::SetProjectionMode()
  97. {
  98. JPH_ASSERT(mInFrame);
  99. [mRenderEncoder setVertexBytes: &mVSBuffer length: sizeof(mVSBuffer) atIndex: 2];
  100. }
  101. void RendererMTL::SetOrthoMode()
  102. {
  103. JPH_ASSERT(mInFrame);
  104. [mRenderEncoder setVertexBytes: &mVSBufferOrtho length: sizeof(mVSBufferOrtho) atIndex: 2];
  105. }
  106. Ref<Texture> RendererMTL::CreateTexture(const Surface *inSurface)
  107. {
  108. return new TextureMTL(this, inSurface);
  109. }
  110. Ref<VertexShader> RendererMTL::CreateVertexShader(const char *inName)
  111. {
  112. id<MTLFunction> function = [mShaderLibrary newFunctionWithName: [NSString stringWithCString: inName encoding: NSUTF8StringEncoding]];
  113. if (function == nil)
  114. FatalError("Vertex shader %s not found", inName);
  115. return new VertexShaderMTL(function);
  116. }
  117. Ref<PixelShader> RendererMTL::CreatePixelShader(const char *inName)
  118. {
  119. id<MTLFunction> function = [mShaderLibrary newFunctionWithName: [NSString stringWithCString: inName encoding: NSUTF8StringEncoding]];
  120. if (function == nil)
  121. FatalError("Pixel shader %s not found", inName);
  122. return new PixelShaderMTL(function);
  123. }
  124. unique_ptr<PipelineState> RendererMTL::CreatePipelineState(const VertexShader *inVertexShader, const PipelineState::EInputDescription *inInputDescription, uint inInputDescriptionCount, const PixelShader *inPixelShader, PipelineState::EDrawPass inDrawPass, PipelineState::EFillMode inFillMode, PipelineState::ETopology inTopology, PipelineState::EDepthTest inDepthTest, PipelineState::EBlendMode inBlendMode, PipelineState::ECullMode inCullMode)
  125. {
  126. return make_unique<PipelineStateMTL>(this, static_cast<const VertexShaderMTL *>(inVertexShader), inInputDescription, inInputDescriptionCount, static_cast<const PixelShaderMTL *>(inPixelShader), inDrawPass, inFillMode, inTopology, inDepthTest, inBlendMode, inCullMode);
  127. }
  128. RenderPrimitive *RendererMTL::CreateRenderPrimitive(PipelineState::ETopology inType)
  129. {
  130. return new RenderPrimitiveMTL(this, inType == PipelineState::ETopology::Line? MTLPrimitiveTypeLine : MTLPrimitiveTypeTriangle);
  131. }
  132. RenderInstances *RendererMTL::CreateRenderInstances()
  133. {
  134. return new RenderInstancesMTL(this);
  135. }
  136. #ifndef JPH_ENABLE_VULKAN
  137. Renderer *Renderer::sCreate()
  138. {
  139. return new RendererMTL;
  140. }
  141. #endif