Flutter Impeller
impeller::PassBindingsCache Class Reference

Ensures that bindings on the pass are not redundantly set or updated. Avoids making the driver do additional checks and makes the frame insights during profiling and instrumentation not complain about the same. More...

#include <pass_bindings_cache.h>

Public Member Functions

 PassBindingsCache (id< MTLRenderCommandEncoder > encoder)
 
 PassBindingsCache (const PassBindingsCache &)=delete
 
 PassBindingsCache (PassBindingsCache &&)=delete
 
void SetRenderPipelineState (id< MTLRenderPipelineState > pipeline)
 
void SetDepthStencilState (id< MTLDepthStencilState > depth_stencil)
 
bool SetBuffer (ShaderStage stage, uint64_t index, uint64_t offset, id< MTLBuffer > buffer)
 
bool SetTexture (ShaderStage stage, uint64_t index, id< MTLTexture > texture)
 
bool SetSampler (ShaderStage stage, uint64_t index, id< MTLSamplerState > sampler)
 
void SetViewport (const Viewport &viewport)
 
void SetScissor (const IRect &scissor)
 
void BindPipeline (vk::CommandBuffer command_buffer, vk::PipelineBindPoint pipeline_bind_point, vk::Pipeline pipeline)
 
void SetStencilReference (vk::CommandBuffer command_buffer, vk::StencilFaceFlags face_mask, uint32_t reference)
 
void SetScissor (vk::CommandBuffer command_buffer, uint32_t first_scissor, uint32_t scissor_count, const vk::Rect2D *scissors)
 
void SetViewport (vk::CommandBuffer command_buffer, uint32_t first_viewport, uint32_t viewport_count, const vk::Viewport *viewports)
 

Detailed Description

Ensures that bindings on the pass are not redundantly set or updated. Avoids making the driver do additional checks and makes the frame insights during profiling and instrumentation not complain about the same.

There should be no change to rendering if this caching was absent.

Definition at line 194 of file render_pass_mtl.mm.

Constructor & Destructor Documentation

◆ PassBindingsCache() [1/3]

impeller::PassBindingsCache::PassBindingsCache ( id< MTLRenderCommandEncoder >  encoder)
inlineexplicit

Definition at line 195 of file render_pass_mtl.mm.

196  : encoder_(encoder) {}

◆ PassBindingsCache() [2/3]

impeller::PassBindingsCache::PassBindingsCache ( const PassBindingsCache )
delete

◆ PassBindingsCache() [3/3]

impeller::PassBindingsCache::PassBindingsCache ( PassBindingsCache &&  )
delete

Member Function Documentation

◆ BindPipeline()

void impeller::PassBindingsCache::BindPipeline ( vk::CommandBuffer  command_buffer,
vk::PipelineBindPoint  pipeline_bind_point,
vk::Pipeline  pipeline 
)

Definition at line 8 of file pass_bindings_cache.cc.

10  {
11  switch (pipeline_bind_point) {
12  case vk::PipelineBindPoint::eGraphics:
13  if (graphics_pipeline_.has_value() &&
14  graphics_pipeline_.value() == pipeline) {
15  return;
16  }
17  graphics_pipeline_ = pipeline;
18  break;
19  case vk::PipelineBindPoint::eCompute:
20  if (compute_pipeline_.has_value() &&
21  compute_pipeline_.value() == pipeline) {
22  return;
23  }
24  compute_pipeline_ = pipeline;
25  break;
26  default:
27  break;
28  }
29  command_buffer.bindPipeline(pipeline_bind_point, pipeline);
30 }

Referenced by impeller::EncodeCommand(), and impeller::testing::TEST().

◆ SetBuffer()

bool impeller::PassBindingsCache::SetBuffer ( ShaderStage  stage,
uint64_t  index,
uint64_t  offset,
id< MTLBuffer >  buffer 
)
inline

Definition at line 218 of file render_pass_mtl.mm.

221  {
222  auto& buffers_map = buffers_[stage];
223  auto found = buffers_map.find(index);
224  if (found != buffers_map.end() && found->second.buffer == buffer) {
225  // The right buffer is bound. Check if its offset needs to be updated.
226  if (found->second.offset == offset) {
227  // Buffer and its offset is identical. Nothing to do.
228  return true;
229  }
230 
231  // Only the offset needs to be updated.
232  found->second.offset = offset;
233 
234  switch (stage) {
236  [encoder_ setVertexBufferOffset:offset atIndex:index];
237  return true;
239  [encoder_ setFragmentBufferOffset:offset atIndex:index];
240  return true;
241  default:
242  VALIDATION_LOG << "Cannot update buffer offset of an unknown stage.";
243  return false;
244  }
245  return true;
246  }
247  buffers_map[index] = {buffer, static_cast<size_t>(offset)};
248  switch (stage) {
250  [encoder_ setVertexBuffer:buffer offset:offset atIndex:index];
251  return true;
253  [encoder_ setFragmentBuffer:buffer offset:offset atIndex:index];
254  return true;
255  default:
256  VALIDATION_LOG << "Cannot bind buffer to unknown shader stage.";
257  return false;
258  }
259  return false;
260  }

References VALIDATION_LOG.

Referenced by impeller::Bind().

◆ SetDepthStencilState()

void impeller::PassBindingsCache::SetDepthStencilState ( id< MTLDepthStencilState >  depth_stencil)
inline

Definition at line 210 of file render_pass_mtl.mm.

210  {
211  if (depth_stencil_ == depth_stencil) {
212  return;
213  }
214  depth_stencil_ = depth_stencil;
215  [encoder_ setDepthStencilState:depth_stencil_];
216  }

◆ SetRenderPipelineState()

void impeller::PassBindingsCache::SetRenderPipelineState ( id< MTLRenderPipelineState >  pipeline)
inline

Definition at line 202 of file render_pass_mtl.mm.

202  {
203  if (pipeline == pipeline_) {
204  return;
205  }
206  pipeline_ = pipeline;
207  [encoder_ setRenderPipelineState:pipeline_];
208  }

◆ SetSampler()

bool impeller::PassBindingsCache::SetSampler ( ShaderStage  stage,
uint64_t  index,
id< MTLSamplerState >  sampler 
)
inline

Definition at line 284 of file render_pass_mtl.mm.

286  {
287  auto& sampler_map = samplers_[stage];
288  auto found = sampler_map.find(index);
289  if (found != sampler_map.end() && found->second == sampler) {
290  // Already bound.
291  return true;
292  }
293  sampler_map[index] = sampler;
294  switch (stage) {
296  [encoder_ setVertexSamplerState:sampler atIndex:index];
297  return true;
299  [encoder_ setFragmentSamplerState:sampler atIndex:index];
300  return true;
301  default:
302  VALIDATION_LOG << "Cannot bind buffer to unknown shader stage.";
303  return false;
304  }
305  return false;
306  }

References VALIDATION_LOG.

Referenced by impeller::Bind().

◆ SetScissor() [1/2]

void impeller::PassBindingsCache::SetScissor ( const IRect scissor)
inline

Definition at line 323 of file render_pass_mtl.mm.

323  {
324  if (scissor_.has_value() && scissor_.value() == scissor) {
325  return;
326  }
327  [encoder_
328  setScissorRect:MTLScissorRect{
329  .x = static_cast<NSUInteger>(scissor.origin.x),
330  .y = static_cast<NSUInteger>(scissor.origin.y),
331  .width = static_cast<NSUInteger>(scissor.size.width),
332  .height =
333  static_cast<NSUInteger>(scissor.size.height),
334  }];
335  scissor_ = scissor;
336  }

References impeller::TSize< T >::height, impeller::TRect< T >::origin, impeller::TRect< T >::size, impeller::TSize< T >::width, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

Referenced by impeller::SetViewportAndScissor(), and impeller::testing::TEST().

◆ SetScissor() [2/2]

void impeller::PassBindingsCache::SetScissor ( vk::CommandBuffer  command_buffer,
uint32_t  first_scissor,
uint32_t  scissor_count,
const vk::Rect2D *  scissors 
)

Definition at line 45 of file pass_bindings_cache.cc.

48  {
49  if (first_scissor == 0 && scissor_count == 1) {
50  if (scissors_.has_value() && scissors_.value() == scissors[0]) {
51  return;
52  }
53  scissors_ = scissors[0];
54  }
55  command_buffer.setScissor(first_scissor, scissor_count, scissors);
56 }

◆ SetStencilReference()

void impeller::PassBindingsCache::SetStencilReference ( vk::CommandBuffer  command_buffer,
vk::StencilFaceFlags  face_mask,
uint32_t  reference 
)

Definition at line 32 of file pass_bindings_cache.cc.

34  {
35  if (stencil_face_flags_.has_value() &&
36  face_mask == stencil_face_flags_.value() &&
37  reference == stencil_reference_) {
38  return;
39  }
40  stencil_face_flags_ = face_mask;
41  stencil_reference_ = reference;
42  command_buffer.setStencilReference(face_mask, reference);
43 }

Referenced by impeller::EncodeCommand(), and impeller::testing::TEST().

◆ SetTexture()

bool impeller::PassBindingsCache::SetTexture ( ShaderStage  stage,
uint64_t  index,
id< MTLTexture >  texture 
)
inline

Definition at line 262 of file render_pass_mtl.mm.

262  {
263  auto& texture_map = textures_[stage];
264  auto found = texture_map.find(index);
265  if (found != texture_map.end() && found->second == texture) {
266  // Already bound.
267  return true;
268  }
269  texture_map[index] = texture;
270  switch (stage) {
272  [encoder_ setVertexTexture:texture atIndex:index];
273  return true;
275  [encoder_ setFragmentTexture:texture atIndex:index];
276  return true;
277  default:
278  VALIDATION_LOG << "Cannot bind buffer to unknown shader stage.";
279  return false;
280  }
281  return false;
282  }

References VALIDATION_LOG.

Referenced by impeller::Bind().

◆ SetViewport() [1/2]

void impeller::PassBindingsCache::SetViewport ( const Viewport viewport)
inline

Definition at line 308 of file render_pass_mtl.mm.

308  {
309  if (viewport_.has_value() && viewport_.value() == viewport) {
310  return;
311  }
312  [encoder_ setViewport:MTLViewport{
313  .originX = viewport.rect.origin.x,
314  .originY = viewport.rect.origin.y,
315  .width = viewport.rect.size.width,
316  .height = viewport.rect.size.height,
317  .znear = viewport.depth_range.z_near,
318  .zfar = viewport.depth_range.z_far,
319  }];
320  viewport_ = viewport;
321  }

References impeller::Viewport::depth_range, impeller::TSize< T >::height, impeller::TRect< T >::origin, impeller::Viewport::rect, impeller::TRect< T >::size, impeller::TSize< T >::width, impeller::TPoint< T >::x, impeller::TPoint< T >::y, impeller::DepthRange::z_far, and impeller::DepthRange::z_near.

Referenced by impeller::SetViewportAndScissor(), and impeller::testing::TEST().

◆ SetViewport() [2/2]

void impeller::PassBindingsCache::SetViewport ( vk::CommandBuffer  command_buffer,
uint32_t  first_viewport,
uint32_t  viewport_count,
const vk::Viewport *  viewports 
)

Definition at line 58 of file pass_bindings_cache.cc.

61  {
62  if (first_viewport == 0 && viewport_count == 1) {
63  // Note that this is doing equality checks on floating point numbers.
64  if (viewport_.has_value() && viewport_.value() == viewports[0]) {
65  return;
66  }
67  viewport_ = viewports[0];
68  }
69  command_buffer.setViewport(first_viewport, viewport_count, viewports);
70 }

The documentation for this class was generated from the following files:
impeller::ShaderStage::kFragment
@ kFragment
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:60
impeller::ShaderStage::kVertex
@ kVertex