164 lines
5.8 KiB
Plaintext
164 lines
5.8 KiB
Plaintext
|
|
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||
|
|
// SPDX-FileCopyrightText: 2025 Jorrit Rouwe
|
||
|
|
// SPDX-License-Identifier: MIT
|
||
|
|
|
||
|
|
#include <TestFramework.h>
|
||
|
|
|
||
|
|
#include <Renderer/MTL/PipelineStateMTL.h>
|
||
|
|
#include <Renderer/MTL/RendererMTL.h>
|
||
|
|
#include <Renderer/MTL/FatalErrorIfFailedMTL.h>
|
||
|
|
|
||
|
|
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) :
|
||
|
|
mRenderer(inRenderer),
|
||
|
|
mVertexShader(inVertexShader),
|
||
|
|
mPixelShader(inPixelShader)
|
||
|
|
{
|
||
|
|
// Create a vertex descriptor
|
||
|
|
MTLVertexDescriptor *vertex_descriptor = [[MTLVertexDescriptor alloc] init];
|
||
|
|
uint vertex_offset = 0;
|
||
|
|
uint instance_offset = 0, instance_alignment = 4;
|
||
|
|
uint index = 0;
|
||
|
|
for (uint i = 0; i < inInputDescriptionCount; ++i)
|
||
|
|
switch (inInputDescription[i])
|
||
|
|
{
|
||
|
|
case EInputDescription::Position:
|
||
|
|
case EInputDescription::Normal:
|
||
|
|
vertex_descriptor.attributes[index].format = MTLVertexFormatFloat3;
|
||
|
|
vertex_descriptor.attributes[index].offset = vertex_offset;
|
||
|
|
vertex_descriptor.attributes[index].bufferIndex = 0;
|
||
|
|
vertex_offset += 3 * sizeof(float);
|
||
|
|
++index;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case EInputDescription::Color:
|
||
|
|
vertex_descriptor.attributes[index].format = MTLVertexFormatUChar4;
|
||
|
|
vertex_descriptor.attributes[index].offset = vertex_offset;
|
||
|
|
vertex_descriptor.attributes[index].bufferIndex = 0;
|
||
|
|
vertex_offset += 4 * sizeof(uint8);
|
||
|
|
++index;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case EInputDescription::TexCoord:
|
||
|
|
vertex_descriptor.attributes[index].format = MTLVertexFormatFloat2;
|
||
|
|
vertex_descriptor.attributes[index].offset = vertex_offset;
|
||
|
|
vertex_descriptor.attributes[index].bufferIndex = 0;
|
||
|
|
vertex_offset += 2 * sizeof(float);
|
||
|
|
++index;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case EInputDescription::InstanceColor:
|
||
|
|
vertex_descriptor.attributes[index].format = MTLVertexFormatUChar4;
|
||
|
|
vertex_descriptor.attributes[index].offset = instance_offset;
|
||
|
|
vertex_descriptor.attributes[index].bufferIndex = 1;
|
||
|
|
instance_offset += 4 * sizeof(uint8);
|
||
|
|
++index;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case EInputDescription::InstanceTransform:
|
||
|
|
case EInputDescription::InstanceInvTransform:
|
||
|
|
instance_alignment = max(instance_alignment, 16u);
|
||
|
|
instance_offset = AlignUp(instance_offset, 16u);
|
||
|
|
for (int j = 0; j < 4; ++j)
|
||
|
|
{
|
||
|
|
vertex_descriptor.attributes[index].format = MTLVertexFormatFloat4;
|
||
|
|
vertex_descriptor.attributes[index].offset = instance_offset;
|
||
|
|
vertex_descriptor.attributes[index].bufferIndex = 1;
|
||
|
|
instance_offset += 4 * sizeof(float);
|
||
|
|
++index;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Configure layouts
|
||
|
|
vertex_descriptor.layouts[0].stride = vertex_offset;
|
||
|
|
vertex_descriptor.layouts[0].stepRate = 1;
|
||
|
|
vertex_descriptor.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex;
|
||
|
|
|
||
|
|
if (instance_offset > 0)
|
||
|
|
{
|
||
|
|
vertex_descriptor.layouts[1].stride = AlignUp(instance_offset, instance_alignment);
|
||
|
|
vertex_descriptor.layouts[1].stepRate = 1;
|
||
|
|
vertex_descriptor.layouts[1].stepFunction = MTLVertexStepFunctionPerInstance;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Create the pipeline descriptor
|
||
|
|
MTLRenderPipelineDescriptor *descriptor = [[MTLRenderPipelineDescriptor alloc] init];
|
||
|
|
descriptor.vertexFunction = inVertexShader->GetFunction();
|
||
|
|
descriptor.fragmentFunction = inPixelShader->GetFunction();
|
||
|
|
descriptor.vertexDescriptor = vertex_descriptor;
|
||
|
|
switch (inDrawPass)
|
||
|
|
{
|
||
|
|
case EDrawPass::Shadow:
|
||
|
|
descriptor.depthAttachmentPixelFormat = static_cast<TextureMTL *>(mRenderer->GetShadowMap())->GetTexture().pixelFormat;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case EDrawPass::Normal:
|
||
|
|
descriptor.colorAttachments[0].pixelFormat = mRenderer->GetView().colorPixelFormat;
|
||
|
|
switch (inBlendMode)
|
||
|
|
{
|
||
|
|
case EBlendMode::Write:
|
||
|
|
descriptor.colorAttachments[0].blendingEnabled = NO;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case EBlendMode::AlphaBlend:
|
||
|
|
descriptor.colorAttachments[0].blendingEnabled = YES;
|
||
|
|
descriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;
|
||
|
|
descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
|
||
|
|
descriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;
|
||
|
|
descriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorZero;
|
||
|
|
descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorZero;
|
||
|
|
descriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
descriptor.depthAttachmentPixelFormat = mRenderer->GetView().depthStencilPixelFormat;
|
||
|
|
}
|
||
|
|
|
||
|
|
NSError *error = nullptr;
|
||
|
|
mPipelineState = [mRenderer->GetDevice() newRenderPipelineStateWithDescriptor: descriptor error: &error];
|
||
|
|
FatalErrorIfFailed(error);
|
||
|
|
[descriptor release];
|
||
|
|
[vertex_descriptor release];
|
||
|
|
|
||
|
|
// Create depth descriptor
|
||
|
|
MTLDepthStencilDescriptor *depth_descriptor = [[MTLDepthStencilDescriptor new] init];
|
||
|
|
if (inDepthTest == EDepthTest::On)
|
||
|
|
{
|
||
|
|
depth_descriptor.depthCompareFunction = MTLCompareFunctionGreaterEqual;
|
||
|
|
depth_descriptor.depthWriteEnabled = YES;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
depth_descriptor.depthCompareFunction = MTLCompareFunctionAlways;
|
||
|
|
depth_descriptor.depthWriteEnabled = NO;
|
||
|
|
}
|
||
|
|
mDepthState = [mRenderer->GetDevice() newDepthStencilStateWithDescriptor: depth_descriptor];
|
||
|
|
[depth_descriptor release];
|
||
|
|
|
||
|
|
// Determine cull mode
|
||
|
|
if (inCullMode == ECullMode::FrontFace)
|
||
|
|
mCullMode = MTLCullModeFront;
|
||
|
|
else
|
||
|
|
mCullMode = MTLCullModeBack;
|
||
|
|
|
||
|
|
// Determine fill mode
|
||
|
|
if (inFillMode == EFillMode::Solid)
|
||
|
|
mFillMode = MTLTriangleFillModeFill;
|
||
|
|
else
|
||
|
|
mFillMode = MTLTriangleFillModeLines;
|
||
|
|
}
|
||
|
|
|
||
|
|
PipelineStateMTL::~PipelineStateMTL()
|
||
|
|
{
|
||
|
|
[mPipelineState release];
|
||
|
|
[mDepthState release];
|
||
|
|
}
|
||
|
|
|
||
|
|
void PipelineStateMTL::Activate()
|
||
|
|
{
|
||
|
|
id<MTLRenderCommandEncoder> encoder = mRenderer->GetRenderEncoder();
|
||
|
|
[encoder setRenderPipelineState: mPipelineState];
|
||
|
|
[encoder setDepthStencilState: mDepthState];
|
||
|
|
[encoder setCullMode: mCullMode];
|
||
|
|
[encoder setTriangleFillMode: mFillMode];
|
||
|
|
}
|