blob: 31ff355cffb2d24e1716d85f86abe4f24eb14d75 [file] [log] [blame]
// Copyright 2017 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "dawn_native/metal/RenderPipelineMTL.h"
#include "dawn_native/metal/BlendStateMTL.h"
#include "dawn_native/metal/DepthStencilStateMTL.h"
#include "dawn_native/metal/DeviceMTL.h"
#include "dawn_native/metal/InputStateMTL.h"
#include "dawn_native/metal/PipelineLayoutMTL.h"
#include "dawn_native/metal/ShaderModuleMTL.h"
#include "dawn_native/metal/TextureMTL.h"
namespace dawn_native { namespace metal {
namespace {
MTLPrimitiveType MTLPrimitiveTopology(dawn::PrimitiveTopology primitiveTopology) {
switch (primitiveTopology) {
case dawn::PrimitiveTopology::PointList:
return MTLPrimitiveTypePoint;
case dawn::PrimitiveTopology::LineList:
return MTLPrimitiveTypeLine;
case dawn::PrimitiveTopology::LineStrip:
return MTLPrimitiveTypeLineStrip;
case dawn::PrimitiveTopology::TriangleList:
return MTLPrimitiveTypeTriangle;
case dawn::PrimitiveTopology::TriangleStrip:
return MTLPrimitiveTypeTriangleStrip;
}
}
MTLPrimitiveTopologyClass MTLInputPrimitiveTopology(
dawn::PrimitiveTopology primitiveTopology) {
switch (primitiveTopology) {
case dawn::PrimitiveTopology::PointList:
return MTLPrimitiveTopologyClassPoint;
case dawn::PrimitiveTopology::LineList:
case dawn::PrimitiveTopology::LineStrip:
return MTLPrimitiveTopologyClassLine;
case dawn::PrimitiveTopology::TriangleList:
case dawn::PrimitiveTopology::TriangleStrip:
return MTLPrimitiveTopologyClassTriangle;
}
}
MTLIndexType MTLIndexFormat(dawn::IndexFormat format) {
switch (format) {
case dawn::IndexFormat::Uint16:
return MTLIndexTypeUInt16;
case dawn::IndexFormat::Uint32:
return MTLIndexTypeUInt32;
}
}
}
RenderPipeline::RenderPipeline(Device* device, const RenderPipelineDescriptor* descriptor)
: RenderPipelineBase(device, descriptor),
mMtlIndexType(MTLIndexFormat(GetIndexFormat())),
mMtlPrimitiveTopology(MTLPrimitiveTopology(GetPrimitiveTopology())) {
auto mtlDevice = device->GetMTLDevice();
MTLRenderPipelineDescriptor* descriptorMTL = [MTLRenderPipelineDescriptor new];
const ShaderModule* vertexModule = ToBackend(descriptor->vertexStage->module);
const char* vertexEntryPoint = descriptor->vertexStage->entryPoint;
ShaderModule::MetalFunctionData vertexData = vertexModule->GetFunction(
vertexEntryPoint, dawn::ShaderStage::Vertex, ToBackend(GetLayout()));
descriptorMTL.vertexFunction = vertexData.function;
const ShaderModule* fragmentModule = ToBackend(descriptor->fragmentStage->module);
const char* fragmentEntryPoint = descriptor->fragmentStage->entryPoint;
ShaderModule::MetalFunctionData fragmentData = fragmentModule->GetFunction(
fragmentEntryPoint, dawn::ShaderStage::Fragment, ToBackend(GetLayout()));
descriptorMTL.fragmentFunction = fragmentData.function;
if (HasDepthStencilAttachment()) {
// TODO(kainino@chromium.org): Handle depth-only and stencil-only formats.
dawn::TextureFormat depthStencilFormat = GetDepthStencilFormat();
descriptorMTL.depthAttachmentPixelFormat = MetalPixelFormat(depthStencilFormat);
descriptorMTL.stencilAttachmentPixelFormat = MetalPixelFormat(depthStencilFormat);
}
for (uint32_t i : IterateBitSet(GetColorAttachmentsMask())) {
descriptorMTL.colorAttachments[i].pixelFormat =
MetalPixelFormat(GetColorAttachmentFormat(i));
ToBackend(GetBlendState(i))->ApplyBlendState(descriptorMTL.colorAttachments[i]);
}
descriptorMTL.inputPrimitiveTopology = MTLInputPrimitiveTopology(GetPrimitiveTopology());
InputState* inputState = ToBackend(GetInputState());
descriptorMTL.vertexDescriptor = inputState->GetMTLVertexDescriptor();
// TODO(kainino@chromium.org): push constants, textures, samplers
NSError* error = nil;
mMtlRenderPipelineState = [mtlDevice newRenderPipelineStateWithDescriptor:descriptorMTL
error:&error];
if (error != nil) {
NSLog(@" error => %@", error);
device->HandleError("Error creating rendering pipeline state");
[descriptorMTL release];
return;
}
[descriptorMTL release];
}
RenderPipeline::~RenderPipeline() {
[mMtlRenderPipelineState release];
}
MTLIndexType RenderPipeline::GetMTLIndexType() const {
return mMtlIndexType;
}
MTLPrimitiveType RenderPipeline::GetMTLPrimitiveTopology() const {
return mMtlPrimitiveTopology;
}
void RenderPipeline::Encode(id<MTLRenderCommandEncoder> encoder) {
[encoder setRenderPipelineState:mMtlRenderPipelineState];
}
}} // namespace dawn_native::metal