Overte C++ Documentation
State.h
1 //
2 // State
3 // libraries/gpu/src/gpu
4 //
5 // Created by Sam Gateau on 3/8/2015.
6 // Copyright 2014 High Fidelity, Inc.
7 //
8 // Distributed under the Apache License, Version 2.0.
9 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10 //
11 #ifndef hifi_gpu_State_h
12 #define hifi_gpu_State_h
13 
14 #include "Format.h"
15 
16 #include <memory>
17 #include <sstream>
18 #include <vector>
19 #include <unordered_map>
20 #include <bitset>
21 #include <QString>
22 
23 #include "Sampler.h"
24 
25 // Why a macro and not a fancy template you will ask me ?
26 // Because some of the fields are bool packed tightly in the State::Cache class
27 // and it s just not good anymore for template T& variable manipulation...
28 #define SET_FIELD(FIELD, PATH, value) \
29  { \
30  _values.PATH = value; \
31  if (value == DEFAULT.PATH) { \
32  _signature.reset(FIELD); \
33  } else { \
34  _signature.set(FIELD); \
35  } \
36  _stamp++; \
37  }
38 
39 namespace gpu {
40 
41 class GPUObject;
42 
44 class State {
45 public:
46  State();
47  State(const State& state) : _values(state._values), _signature(state._signature), _stamp(state._stamp) {}
48  virtual ~State();
49 
56  Stamp getStamp() const { return _stamp; }
57 
58  enum FillMode
59  {
60  FILL_POINT = 0,
61  FILL_LINE,
62  FILL_FACE,
63 
64  NUM_FILL_MODES,
65  };
66 
67  enum CullMode
68  {
69  CULL_NONE = 0,
70  CULL_FRONT,
71  CULL_BACK,
72 
73  NUM_CULL_MODES,
74  };
75 
76  enum StencilOp
77  {
78  STENCIL_OP_KEEP = 0,
79  STENCIL_OP_ZERO,
80  STENCIL_OP_REPLACE,
81  STENCIL_OP_INCR_SAT,
82  STENCIL_OP_DECR_SAT,
83  STENCIL_OP_INVERT,
84  STENCIL_OP_INCR,
85  STENCIL_OP_DECR,
86 
87  NUM_STENCIL_OPS,
88  };
89 
90  enum BlendArg
91  {
92  ZERO = 0,
93  ONE,
94  SRC_COLOR,
95  INV_SRC_COLOR,
96  SRC_ALPHA,
97  INV_SRC_ALPHA,
98  DEST_ALPHA,
99  INV_DEST_ALPHA,
100  DEST_COLOR,
101  INV_DEST_COLOR,
102  SRC_ALPHA_SAT,
103  FACTOR_COLOR,
104  INV_FACTOR_COLOR,
105  FACTOR_ALPHA,
106  INV_FACTOR_ALPHA,
107 
108  NUM_BLEND_ARGS,
109  };
110 
111  enum BlendOp
112  {
113  BLEND_OP_ADD = 0,
114  BLEND_OP_SUBTRACT,
115  BLEND_OP_REV_SUBTRACT,
116  BLEND_OP_MIN,
117  BLEND_OP_MAX,
118 
119  NUM_BLEND_OPS,
120  };
121 
122  enum ColorMask
123  {
124  WRITE_NONE = 0,
125  WRITE_RED = 1,
126  WRITE_GREEN = 2,
127  WRITE_BLUE = 4,
128  WRITE_ALPHA = 8,
129  WRITE_ALL = (WRITE_RED | WRITE_GREEN | WRITE_BLUE | WRITE_ALPHA),
130  };
131 
133  class DepthTest {
134  public:
136  uint8 writeMask{ true };
137 
139  uint8 enabled{ false };
140 
141  ComparisonFunction function{ ComparisonFunction::LESS };
142 
143  public:
150  DepthTest(bool enabled = false, bool writeMask = true, ComparisonFunction func = ComparisonFunction::LESS) :
151  writeMask(writeMask), enabled(enabled), function(func) {}
152 
156  bool isEnabled() const { return enabled != 0; }
157 
161  ComparisonFunction getFunction() const { return function; }
162 
166  uint8 getWriteMask() const { return writeMask; }
167 
168  bool operator==(const DepthTest& right) const {
169  return
170  writeMask == right.writeMask &&
171  enabled == right.enabled &&
172  function == right.function;
173  }
174 
175  bool operator!=(const DepthTest& right) const {
176  return !(*this == right);
177  }
178 
179  operator QString() const {
180  return QString("{ writeMask = %1, enabled = %2, function = %3 }").arg(writeMask).arg(enabled).arg((uint8_t)function);
181  }
182  };
183 
185  struct StencilTest {
186  ComparisonFunction function;
187  StencilOp failOp;
188  StencilOp depthFailOp;
189  StencilOp passOp;
190  int8 reference{ 0 };
191  uint8 readMask{ 0xff };
192 
193  public:
202  StencilTest(int8 reference = 0,
203  uint8 readMask = 0xFF,
204  ComparisonFunction func = ComparisonFunction::ALWAYS,
205  StencilOp failOp = STENCIL_OP_KEEP,
206  StencilOp depthFailOp = STENCIL_OP_KEEP,
207  StencilOp passOp = STENCIL_OP_KEEP) :
208  function(func),
209  failOp(failOp), depthFailOp(depthFailOp), passOp(passOp), reference(reference), readMask(readMask) {}
210 
214  ComparisonFunction getFunction() const { return function; }
215 
219  StencilOp getFailOp() const { return failOp; }
220 
224  StencilOp getDepthFailOp() const { return depthFailOp; }
225 
229  StencilOp getPassOp() const { return passOp; }
230 
234  int8 getReference() const { return reference; }
235 
239  uint8 getReadMask() const { return readMask; }
240 
241  bool operator==(const StencilTest& right) const {
242  return
243  function == right.function &&
244  failOp == right.failOp &&
245  depthFailOp == right.depthFailOp &&
246  passOp == right.passOp &&
247  reference == right.reference &&
248  readMask == right.readMask;
249 
250  }
251 
252  bool operator!=(const StencilTest &right) const { return !(right==*this); }
253  };
254 
256  struct StencilActivation {
257  uint8 frontWriteMask = 0xFF;
258  uint8 backWriteMask = 0xFF;
259  bool enabled;
260 
261  public:
267  StencilActivation(bool enabled = false, uint8 frontWriteMask = 0xFF, uint8 backWriteMask = 0xFF) :
268  frontWriteMask(frontWriteMask), backWriteMask(backWriteMask), enabled(enabled) {}
269 
273  bool isEnabled() const { return enabled; }
274 
278  uint8 getWriteMaskFront() const { return frontWriteMask; }
279 
283  uint8 getWriteMaskBack() const { return backWriteMask; }
284 
285  bool operator==(const StencilActivation& right) const {
286  return
287  frontWriteMask == right.frontWriteMask &&
288  backWriteMask == right.backWriteMask &&
289  enabled == right.enabled;
290  }
291 
292  bool operator!=(const StencilActivation& right) const {
293  return !(*this == right);
294  }
295  };
296 
298  struct BlendFunction {
299  // Using uint8 here will make the structure as a whole not align to 32 bits
301  uint16 enabled;
302 
304  BlendArg sourceColor;
305 
307  BlendArg sourceAlpha;
308 
310  BlendArg destColor;
311 
313  BlendArg destAlpha;
314 
316  BlendOp opColor;
317 
319  BlendOp opAlpha;
320 
321  public:
333  BlendArg sourceColor,
334  BlendOp operationColor,
335  BlendArg destinationColor,
336  BlendArg sourceAlpha,
337  BlendOp operationAlpha,
338  BlendArg destinationAlpha) :
339  enabled(enabled),
341  destColor(destinationColor), destAlpha(destinationAlpha),
342  opColor(operationColor), opAlpha(operationAlpha) {}
343 
350  BlendFunction(bool enabled = false, BlendArg source = ONE, BlendOp operation = BLEND_OP_ADD, BlendArg destination = ZERO) :
351  BlendFunction(enabled, source, operation, destination, source, operation, destination) {}
352 
356  bool isEnabled() const { return (enabled != 0); }
357 
361  BlendArg getSourceColor() const { return sourceColor; }
362 
366  BlendArg getDestinationColor() const { return destColor; }
367 
371  BlendOp getOperationColor() const { return opColor; }
372 
376  BlendArg getSourceAlpha() const { return sourceAlpha; }
377 
381  BlendArg getDestinationAlpha() const { return destAlpha; }
382 
386  BlendOp getOperationAlpha() const { return opAlpha; }
387 
388  bool operator==(const BlendFunction& right) const {
389  return
390  enabled == right.enabled &&
391  sourceColor == right.sourceColor &&
392  sourceAlpha == right.sourceAlpha &&
393  destColor == right.destColor &&
394  destAlpha == right.destAlpha &&
395  opColor == right.opColor &&
396  opAlpha == right.opAlpha;
397 
398  }
399 
400  bool operator!=(const BlendFunction& right) const {
401  return !(*this == right);
402  }
403  };
404 
406  struct Flags {
407  Flags() :
408  frontFaceClockwise(false), depthClampEnable(false), scissorEnable(false), multisampleEnable(false),
409  antialisedLineEnable(true), alphaToCoverageEnable(false) {}
410  bool frontFaceClockwise;
411  bool depthClampEnable;
412  bool scissorEnable;
413  bool multisampleEnable;
414  bool antialisedLineEnable;
415  bool alphaToCoverageEnable;
416 
417 
418  bool operator==(const Flags& right) const {
419  return
420  frontFaceClockwise == right.frontFaceClockwise &&
421  depthClampEnable == right.depthClampEnable &&
422  scissorEnable == right.scissorEnable &&
423  multisampleEnable == right.multisampleEnable &&
424  antialisedLineEnable == right.antialisedLineEnable &&
425  alphaToCoverageEnable == right.alphaToCoverageEnable;
426 
427  }
428 
429  bool operator!=(const Flags& right) const {
430  return !(*this == right);
431  }
432  };
433 
439  class Data {
440  public:
441  float depthBias = 0.0f;
442  float depthBiasSlopeScale = 0.0f;
443 
444  DepthTest depthTest;
445  StencilActivation stencilActivation;
446  StencilTest stencilTestFront;
447  StencilTest stencilTestBack;
448  uint32 sampleMask = 0xFFFFFFFF;
449  BlendFunction blendFunction;
450  FillMode fillMode{ FILL_FACE };
451  CullMode cullMode{ CULL_NONE };
452  ColorMask colorWriteMask{ WRITE_ALL };
453 
454  Flags flags;
455  };
456 
460  std::string getKey() const;
461 
463  static const Data DEFAULT;
464  void setFillMode(FillMode fill) { SET_FIELD(FILL_MODE, fillMode, fill); }
465  FillMode getFillMode() const { return _values.fillMode; }
466 
467  void setCullMode(CullMode cull) { SET_FIELD(CULL_MODE, cullMode, cull); }
468  CullMode getCullMode() const { return _values.cullMode; }
469 
473  const Flags& getFlags() const { return _values.flags; }
474 
475  void setFrontFaceClockwise(bool isClockwise) { SET_FIELD(FRONT_FACE_CLOCKWISE, flags.frontFaceClockwise, isClockwise); }
476  bool isFrontFaceClockwise() const { return _values.flags.frontFaceClockwise; }
477 
478  void setDepthClampEnable(bool enable) { SET_FIELD(DEPTH_CLAMP_ENABLE, flags.depthClampEnable, enable); }
479  bool isDepthClampEnable() const { return _values.flags.depthClampEnable; }
480 
481  void setScissorEnable(bool enable) { SET_FIELD(SCISSOR_ENABLE, flags.scissorEnable, enable); }
482  bool isScissorEnable() const { return _values.flags.scissorEnable; }
483 
484  void setMultisampleEnable(bool enable) { SET_FIELD(MULTISAMPLE_ENABLE, flags.multisampleEnable, enable); }
485  bool isMultisampleEnable() const { return _values.flags.multisampleEnable; }
486 
487  void setAntialiasedLineEnable(bool enable) { SET_FIELD(ANTIALISED_LINE_ENABLE, flags.antialisedLineEnable, enable); }
488  bool isAntialiasedLineEnable() const { return _values.flags.antialisedLineEnable; }
489 
490  // Depth Bias
491  void setDepthBias(float bias) { SET_FIELD(DEPTH_BIAS, depthBias, bias); }
492  float getDepthBias() const { return _values.depthBias; }
493 
494  void setDepthBiasSlopeScale(float scale) { SET_FIELD(DEPTH_BIAS_SLOPE_SCALE, depthBiasSlopeScale, scale); }
495  float getDepthBiasSlopeScale() const { return _values.depthBiasSlopeScale; }
496 
497  // Depth Test
498  void setDepthTest(DepthTest newDepthTest) { SET_FIELD(DEPTH_TEST, depthTest, newDepthTest); }
499  void setDepthTest(bool enable, bool writeMask, ComparisonFunction func) {
500  setDepthTest(DepthTest(enable, writeMask, func));
501  }
502  DepthTest getDepthTest() const { return _values.depthTest; }
503 
504  bool isDepthTestEnabled() const { return getDepthTest().isEnabled(); }
505  uint8 getDepthTestWriteMask() const { return getDepthTest().getWriteMask(); }
506  ComparisonFunction getDepthTestFunc() const { return getDepthTest().getFunction(); }
507 
508  // Stencil test
516  void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest, uint8 backWriteMask, StencilTest backTest) {
517  SET_FIELD(STENCIL_ACTIVATION, stencilActivation, StencilActivation(enabled, frontWriteMask, backWriteMask));
518  SET_FIELD(STENCIL_TEST_FRONT, stencilTestFront, frontTest);
519  SET_FIELD(STENCIL_TEST_BACK, stencilTestBack, backTest);
520  }
521 
527  void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest) {
528  setStencilTest(enabled, frontWriteMask, frontTest, frontWriteMask, frontTest);
529  }
530 
531  StencilActivation getStencilActivation() const { return _values.stencilActivation; }
532  StencilTest getStencilTestFront() const { return _values.stencilTestFront; }
533  StencilTest getStencilTestBack() const { return _values.stencilTestBack; }
534 
535  bool isStencilEnabled() const { return getStencilActivation().isEnabled(); }
536  uint8 getStencilWriteMaskFront() const { return getStencilActivation().getWriteMaskFront(); }
537  uint8 getStencilWriteMaskBack() const { return getStencilActivation().getWriteMaskBack(); }
538 
539  // Alpha to coverage
540  void setAlphaToCoverageEnable(bool enable) { SET_FIELD(ALPHA_TO_COVERAGE_ENABLE, flags.alphaToCoverageEnable, enable); }
541  bool isAlphaToCoverageEnabled() const { return _values.flags.alphaToCoverageEnable; }
542 
543  // Sample mask
550  void setSampleMask(uint32 mask) { SET_FIELD(SAMPLE_MASK, sampleMask, mask); }
551 
558  uint32 getSampleMask() const { return _values.sampleMask; }
559 
560  // Blend Function
561  void setBlendFunction(BlendFunction function) { SET_FIELD(BLEND_FUNCTION, blendFunction, function); }
562  const BlendFunction& getBlendFunction() const { return _values.blendFunction; }
563 
573  void setBlendFunction(bool enabled,
574  BlendArg sourceColor,
575  BlendOp operationColor,
576  BlendArg destinationColor,
577  BlendArg sourceAlpha,
578  BlendOp operationAlpha,
579  BlendArg destinationAlpha) {
580  setBlendFunction(BlendFunction(enabled, sourceColor, operationColor, destinationColor, sourceAlpha, operationAlpha,
581  destinationAlpha));
582  }
583 
590  void setBlendFunction(bool enabled, BlendArg source, BlendOp operation, BlendArg destination) {
591  setBlendFunction(BlendFunction(enabled, source, operation, destination));
592  }
593 
594  bool isBlendEnabled() const { return getBlendFunction().isEnabled(); }
595 
596  // Color write mask
600  void setColorWriteMask(ColorMask mask) { SET_FIELD(COLOR_WRITE_MASK, colorWriteMask, mask); }
601 
610  void setColorWriteMask(bool red, bool green, bool blue, bool alpha) {
611  ColorMask value = (ColorMask)((WRITE_RED * red) | (WRITE_GREEN * green) | (WRITE_BLUE * blue) | (WRITE_ALPHA * alpha));
612  SET_FIELD(COLOR_WRITE_MASK, colorWriteMask, value);
613  }
614  ColorMask getColorWriteMask() const { return _values.colorWriteMask; }
615 
618  enum Field
619  {
620  FILL_MODE,
621  CULL_MODE,
622  FRONT_FACE_CLOCKWISE,
623  DEPTH_CLAMP_ENABLE,
624  SCISSOR_ENABLE,
625  MULTISAMPLE_ENABLE,
626  ANTIALISED_LINE_ENABLE,
627 
628  DEPTH_BIAS,
629  DEPTH_BIAS_SLOPE_SCALE,
630 
631  DEPTH_TEST,
632 
633  STENCIL_ACTIVATION,
634  STENCIL_TEST_FRONT,
635  STENCIL_TEST_BACK,
636 
637  SAMPLE_MASK,
638 
639  ALPHA_TO_COVERAGE_ENABLE,
640 
641  BLEND_FUNCTION,
642 
643  COLOR_WRITE_MASK,
644 
645  NUM_FIELDS, // not a valid field, just the count
646  };
647 
650  typedef std::bitset<NUM_FIELDS> Signature;
651 
655  Signature getSignature() const { return _signature; }
656 
661  static Signature evalSignature(const Data& state);
662 
664  State(const Data& values);
665 
669  const Data& getValues() const { return _values; }
670 
673 
674 protected:
675  State& operator=(const State& state);
676 
679 
682 
684  Stamp _stamp{ 0 };
685 };
686 
687 typedef std::shared_ptr<State> StatePointer;
688 typedef std::vector<StatePointer> States;
689 
690 }; // namespace gpu
691 
692 #endif
Definition: gpu/src/gpu/Forward.h:134
The Data class is the full explicit description of the State class fields value.
Definition: State.h:439
Represents setting for depth testing and writing.
Definition: State.h:133
uint8 enabled
Enable depth test.
Definition: State.h:139
uint8 getWriteMask() const
Definition: State.h:166
bool isEnabled() const
Definition: State.h:156
ComparisonFunction getFunction() const
Definition: State.h:161
DepthTest(bool enabled=false, bool writeMask=true, ComparisonFunction func=ComparisonFunction::LESS)
Definition: State.h:150
uint8 writeMask
Enable writing to the depth buffer.
Definition: State.h:136
Describes pipeline state.
Definition: State.h:44
void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest)
Definition: State.h:527
static Signature evalSignature(const Data &state)
Definition: State.cpp:27
uint32 getSampleMask() const
Definition: State.h:558
Stamp _stamp
Incremented on changes and used to determine if API-specific backend object needs updating.
Definition: State.h:684
static const Data DEFAULT
The unique default values for all the fields.
Definition: State.h:463
void setColorWriteMask(bool red, bool green, bool blue, bool alpha)
Sets which color channels can be written to.
Definition: State.h:610
const GPUObjectPointer gpuObject
Object representing state on the API-specific backend side.
Definition: State.h:672
void setBlendFunction(bool enabled, BlendArg source, BlendOp operation, BlendArg destination)
Definition: State.h:590
const Data & getValues() const
Definition: State.h:669
const Flags & getFlags() const
Definition: State.h:473
Field
Definition: State.h:619
void setColorWriteMask(ColorMask mask)
Definition: State.h:600
Signature _signature
Used to tell which fields have default values and which are changed.
Definition: State.h:681
Data _values
Full description of the state.
Definition: State.h:678
void setSampleMask(uint32 mask)
Definition: State.h:550
void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest, uint8 backWriteMask, StencilTest backTest)
Definition: State.h:516
std::string getKey() const
Definition: State.cpp:90
Signature getSignature() const
Definition: State.h:655
std::bitset< NUM_FIELDS > Signature
Definition: State.h:650
Stamp getStamp() const
Get the current stamp.
Definition: State.h:56
void setBlendFunction(bool enabled, BlendArg sourceColor, BlendOp operationColor, BlendArg destinationColor, BlendArg sourceAlpha, BlendOp operationAlpha, BlendArg destinationAlpha)
Definition: State.h:573
Represents blending state.
Definition: State.h:298
BlendArg sourceColor
Determines how source color will be used.
Definition: State.h:304
BlendArg getDestinationAlpha() const
Definition: State.h:381
BlendOp getOperationAlpha() const
Definition: State.h:386
BlendFunction(bool enabled, BlendArg sourceColor, BlendOp operationColor, BlendArg destinationColor, BlendArg sourceAlpha, BlendOp operationAlpha, BlendArg destinationAlpha)
Definition: State.h:332
uint16 enabled
true if blending is enabled.
Definition: State.h:301
BlendArg getDestinationColor() const
Definition: State.h:366
BlendOp getOperationColor() const
Definition: State.h:371
BlendFunction(bool enabled=false, BlendArg source=ONE, BlendOp operation=BLEND_OP_ADD, BlendArg destination=ZERO)
Definition: State.h:350
BlendArg getSourceAlpha() const
Definition: State.h:376
BlendOp opColor
Type of operation that will be performed on color if blending is enabled.
Definition: State.h:316
BlendArg getSourceColor() const
Definition: State.h:361
BlendArg destColor
Determines how destination color will be used.
Definition: State.h:310
BlendArg destAlpha
Determines how destination alpha will be used.
Definition: State.h:313
BlendOp opAlpha
Type of operation that will be performed on alpha if blending is enabled.
Definition: State.h:319
bool isEnabled() const
Definition: State.h:356
BlendArg sourceAlpha
Determines how source alpha will be used.
Definition: State.h:307
Flags for enabling or disabling various settings for the pipeline.
Definition: State.h:406