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 195 of file render_pass_mtl.mm.

Constructor & Destructor Documentation

◆ PassBindingsCache() [1/3]

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

Definition at line 196 of file render_pass_mtl.mm.

197  : 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::testing::TEST().

◆ SetBuffer()

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

Definition at line 219 of file render_pass_mtl.mm.

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

References VALIDATION_LOG.

Referenced by impeller::Bind().

◆ SetDepthStencilState()

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

Definition at line 211 of file render_pass_mtl.mm.

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

◆ SetRenderPipelineState()

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

Definition at line 203 of file render_pass_mtl.mm.

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

◆ SetSampler()

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

Definition at line 285 of file render_pass_mtl.mm.

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

References VALIDATION_LOG.

Referenced by impeller::Bind().

◆ SetScissor() [1/2]

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

Definition at line 324 of file render_pass_mtl.mm.

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

References impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), and impeller::TRect< T >::GetY().

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::testing::TEST().

◆ SetTexture()

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

Definition at line 263 of file render_pass_mtl.mm.

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

References VALIDATION_LOG.

Referenced by impeller::Bind().

◆ SetViewport() [1/2]

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

Definition at line 309 of file render_pass_mtl.mm.

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

References impeller::Viewport::depth_range, impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::Viewport::rect, 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:67
impeller::ShaderStage::kVertex
@ kVertex