blob: ab5370a7a14efc0c58540cd6164dbe63c69dc4b7 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/renderer/backend/metal/pass_bindings_cache_mtl.h"
namespace impeller {
void PassBindingsCacheMTL::SetEncoder(id<MTLRenderCommandEncoder> encoder) {
encoder_ = encoder;
}
void PassBindingsCacheMTL::SetRenderPipelineState(
id<MTLRenderPipelineState> pipeline) {
if (pipeline == pipeline_) {
return;
}
pipeline_ = pipeline;
[encoder_ setRenderPipelineState:pipeline_];
}
void PassBindingsCacheMTL::SetDepthStencilState(
id<MTLDepthStencilState> depth_stencil) {
if (depth_stencil_ == depth_stencil) {
return;
}
depth_stencil_ = depth_stencil;
[encoder_ setDepthStencilState:depth_stencil_];
}
bool PassBindingsCacheMTL::SetBuffer(ShaderStage stage,
uint64_t index,
uint64_t offset,
id<MTLBuffer> buffer) {
auto& buffers_map = buffers_[stage];
auto found = buffers_map.find(index);
if (found != buffers_map.end() && found->second.buffer == buffer) {
// The right buffer is bound. Check if its offset needs to be updated.
if (found->second.offset == offset) {
// Buffer and its offset is identical. Nothing to do.
return true;
}
// Only the offset needs to be updated.
found->second.offset = offset;
switch (stage) {
case ShaderStage::kVertex:
[encoder_ setVertexBufferOffset:offset atIndex:index];
return true;
case ShaderStage::kFragment:
[encoder_ setFragmentBufferOffset:offset atIndex:index];
return true;
default:
VALIDATION_LOG << "Cannot update buffer offset of an unknown stage.";
return false;
}
return true;
}
buffers_map[index] = {buffer, static_cast<size_t>(offset)};
switch (stage) {
case ShaderStage::kVertex:
[encoder_ setVertexBuffer:buffer offset:offset atIndex:index];
return true;
case ShaderStage::kFragment:
[encoder_ setFragmentBuffer:buffer offset:offset atIndex:index];
return true;
default:
VALIDATION_LOG << "Cannot bind buffer to unknown shader stage.";
return false;
}
return false;
}
bool PassBindingsCacheMTL::SetTexture(ShaderStage stage,
uint64_t index,
id<MTLTexture> texture) {
auto& texture_map = textures_[stage];
auto found = texture_map.find(index);
if (found != texture_map.end() && found->second == texture) {
// Already bound.
return true;
}
texture_map[index] = texture;
switch (stage) {
case ShaderStage::kVertex:
[encoder_ setVertexTexture:texture atIndex:index];
return true;
case ShaderStage::kFragment:
[encoder_ setFragmentTexture:texture atIndex:index];
return true;
default:
VALIDATION_LOG << "Cannot bind buffer to unknown shader stage.";
return false;
}
return false;
}
bool PassBindingsCacheMTL::SetSampler(ShaderStage stage,
uint64_t index,
id<MTLSamplerState> sampler) {
auto& sampler_map = samplers_[stage];
auto found = sampler_map.find(index);
if (found != sampler_map.end() && found->second == sampler) {
// Already bound.
return true;
}
sampler_map[index] = sampler;
switch (stage) {
case ShaderStage::kVertex:
[encoder_ setVertexSamplerState:sampler atIndex:index];
return true;
case ShaderStage::kFragment:
[encoder_ setFragmentSamplerState:sampler atIndex:index];
return true;
default:
VALIDATION_LOG << "Cannot bind buffer to unknown shader stage.";
return false;
}
return false;
}
void PassBindingsCacheMTL::SetViewport(const Viewport& viewport) {
if (viewport_.has_value() && viewport_.value() == viewport) {
return;
}
[encoder_ setViewport:MTLViewport{
.originX = viewport.rect.GetX(),
.originY = viewport.rect.GetY(),
.width = viewport.rect.GetWidth(),
.height = viewport.rect.GetHeight(),
.znear = viewport.depth_range.z_near,
.zfar = viewport.depth_range.z_far,
}];
viewport_ = viewport;
}
void PassBindingsCacheMTL::SetScissor(const IRect& scissor) {
if (scissor_.has_value() && scissor_.value() == scissor) {
return;
}
[encoder_
setScissorRect:MTLScissorRect{
.x = static_cast<NSUInteger>(scissor.GetX()),
.y = static_cast<NSUInteger>(scissor.GetY()),
.width = static_cast<NSUInteger>(scissor.GetWidth()),
.height = static_cast<NSUInteger>(scissor.GetHeight()),
}];
scissor_ = scissor;
}
} // namespace impeller