PipelineStateMTL.mm 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  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/PipelineStateMTL.h>
  6. #include <Renderer/MTL/RendererMTL.h>
  7. #include <Renderer/MTL/FatalErrorIfFailedMTL.h>
  8. PipelineStateMTL::PipelineStateMTL(RendererMTL *inRenderer, const VertexShaderMTL *inVertexShader, const EInputDescription *inInputDescription, uint inInputDescriptionCount, const PixelShaderMTL *inPixelShader, EDrawPass inDrawPass, EFillMode inFillMode, ETopology inTopology, EDepthTest inDepthTest, EBlendMode inBlendMode, ECullMode inCullMode) :
  9. mRenderer(inRenderer),
  10. mVertexShader(inVertexShader),
  11. mPixelShader(inPixelShader)
  12. {
  13. // Create a vertex descriptor
  14. MTLVertexDescriptor *vertex_descriptor = [[MTLVertexDescriptor alloc] init];
  15. uint vertex_offset = 0;
  16. uint instance_offset = 0, instance_alignment = 4;
  17. uint index = 0;
  18. for (uint i = 0; i < inInputDescriptionCount; ++i)
  19. switch (inInputDescription[i])
  20. {
  21. case EInputDescription::Position:
  22. case EInputDescription::Normal:
  23. vertex_descriptor.attributes[index].format = MTLVertexFormatFloat3;
  24. vertex_descriptor.attributes[index].offset = vertex_offset;
  25. vertex_descriptor.attributes[index].bufferIndex = 0;
  26. vertex_offset += 3 * sizeof(float);
  27. ++index;
  28. break;
  29. case EInputDescription::Color:
  30. vertex_descriptor.attributes[index].format = MTLVertexFormatUChar4;
  31. vertex_descriptor.attributes[index].offset = vertex_offset;
  32. vertex_descriptor.attributes[index].bufferIndex = 0;
  33. vertex_offset += 4 * sizeof(uint8);
  34. ++index;
  35. break;
  36. case EInputDescription::TexCoord:
  37. vertex_descriptor.attributes[index].format = MTLVertexFormatFloat2;
  38. vertex_descriptor.attributes[index].offset = vertex_offset;
  39. vertex_descriptor.attributes[index].bufferIndex = 0;
  40. vertex_offset += 2 * sizeof(float);
  41. ++index;
  42. break;
  43. case EInputDescription::InstanceColor:
  44. vertex_descriptor.attributes[index].format = MTLVertexFormatUChar4;
  45. vertex_descriptor.attributes[index].offset = instance_offset;
  46. vertex_descriptor.attributes[index].bufferIndex = 1;
  47. instance_offset += 4 * sizeof(uint8);
  48. ++index;
  49. break;
  50. case EInputDescription::InstanceTransform:
  51. case EInputDescription::InstanceInvTransform:
  52. instance_alignment = max(instance_alignment, 16u);
  53. instance_offset = AlignUp(instance_offset, 16u);
  54. for (int j = 0; j < 4; ++j)
  55. {
  56. vertex_descriptor.attributes[index].format = MTLVertexFormatFloat4;
  57. vertex_descriptor.attributes[index].offset = instance_offset;
  58. vertex_descriptor.attributes[index].bufferIndex = 1;
  59. instance_offset += 4 * sizeof(float);
  60. ++index;
  61. }
  62. break;
  63. }
  64. // Configure layouts
  65. vertex_descriptor.layouts[0].stride = vertex_offset;
  66. vertex_descriptor.layouts[0].stepRate = 1;
  67. vertex_descriptor.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex;
  68. if (instance_offset > 0)
  69. {
  70. vertex_descriptor.layouts[1].stride = AlignUp(instance_offset, instance_alignment);
  71. vertex_descriptor.layouts[1].stepRate = 1;
  72. vertex_descriptor.layouts[1].stepFunction = MTLVertexStepFunctionPerInstance;
  73. }
  74. // Create the pipeline descriptor
  75. MTLRenderPipelineDescriptor *descriptor = [[MTLRenderPipelineDescriptor alloc] init];
  76. descriptor.vertexFunction = inVertexShader->GetFunction();
  77. descriptor.fragmentFunction = inPixelShader->GetFunction();
  78. descriptor.vertexDescriptor = vertex_descriptor;
  79. switch (inDrawPass)
  80. {
  81. case EDrawPass::Shadow:
  82. descriptor.depthAttachmentPixelFormat = static_cast<TextureMTL *>(mRenderer->GetShadowMap())->GetTexture().pixelFormat;
  83. break;
  84. case EDrawPass::Normal:
  85. descriptor.colorAttachments[0].pixelFormat = mRenderer->GetView().colorPixelFormat;
  86. switch (inBlendMode)
  87. {
  88. case EBlendMode::Write:
  89. descriptor.colorAttachments[0].blendingEnabled = NO;
  90. break;
  91. case EBlendMode::AlphaBlend:
  92. descriptor.colorAttachments[0].blendingEnabled = YES;
  93. descriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;
  94. descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
  95. descriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;
  96. descriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorZero;
  97. descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorZero;
  98. descriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;
  99. break;
  100. }
  101. descriptor.depthAttachmentPixelFormat = mRenderer->GetView().depthStencilPixelFormat;
  102. }
  103. NSError *error = nullptr;
  104. mPipelineState = [mRenderer->GetDevice() newRenderPipelineStateWithDescriptor: descriptor error: &error];
  105. FatalErrorIfFailed(error);
  106. [descriptor release];
  107. [vertex_descriptor release];
  108. // Create depth descriptor
  109. MTLDepthStencilDescriptor *depth_descriptor = [[MTLDepthStencilDescriptor new] init];
  110. if (inDepthTest == EDepthTest::On)
  111. {
  112. depth_descriptor.depthCompareFunction = MTLCompareFunctionGreater;
  113. depth_descriptor.depthWriteEnabled = YES;
  114. }
  115. else
  116. {
  117. depth_descriptor.depthCompareFunction = MTLCompareFunctionAlways;
  118. depth_descriptor.depthWriteEnabled = NO;
  119. }
  120. mDepthState = [mRenderer->GetDevice() newDepthStencilStateWithDescriptor: depth_descriptor];
  121. [depth_descriptor release];
  122. // Determine cull mode
  123. if (inCullMode == ECullMode::FrontFace)
  124. mCullMode = MTLCullModeFront;
  125. else
  126. mCullMode = MTLCullModeBack;
  127. // Determine fill mode
  128. if (inFillMode == EFillMode::Solid)
  129. mFillMode = MTLTriangleFillModeFill;
  130. else
  131. mFillMode = MTLTriangleFillModeLines;
  132. }
  133. PipelineStateMTL::~PipelineStateMTL()
  134. {
  135. [mPipelineState release];
  136. [mDepthState release];
  137. }
  138. void PipelineStateMTL::Activate()
  139. {
  140. id<MTLRenderCommandEncoder> encoder = mRenderer->GetRenderEncoder();
  141. [encoder setRenderPipelineState: mPipelineState];
  142. [encoder setDepthStencilState: mDepthState];
  143. [encoder setCullMode: mCullMode];
  144. [encoder setTriangleFillMode: mFillMode];
  145. }