7namespace Grindstone::GraphicsAPI {
8 enum class TextureWrapMode : uint8_t {
16 enum class TextureFilter : uint8_t {
21 enum class ClearMode : uint8_t {
29 enum class ImageLayout : uint8_t {
41 enum class ImageDimension {
48 enum class ImageAspectBits : uint16_t {
53 Metadata = 0x00000008,
57 MemoryPlane0 = 0x00000080,
58 MemoryPlane1 = 0x00000100,
59 MemoryPlane2 = 0x00000200,
60 MemoryPlane3 = 0x00000400,
63 inline ImageAspectBits operator|(ImageAspectBits a, ImageAspectBits b) {
64 return static_cast<ImageAspectBits
>(
static_cast<uint32_t
>(a) |
static_cast<uint32_t
>(b));
67 inline ImageAspectBits& operator|=(ImageAspectBits& a, ImageAspectBits b) {
72 enum class PipelineStageBit : uint32_t {
74 TopOfPipe = 0x00000001,
75 DrawIndirect = 0x00000002,
76 VertexInput = 0x00000004,
77 VertexShader = 0x00000008,
78 TesslationControlShader = 0x00000010,
79 TesselationEvaluationShader = 0x00000020,
80 GeometryShader = 0x00000040,
81 FragmentShader = 0x00000080,
82 EarlyFragmentTests = 0x00000100,
83 LateFragmentTests = 0x00000200,
84 ColorAttachmentOutput = 0x00000400,
85 ComputeShader = 0x00000800,
86 Transfer = 0x00001000,
87 BottomOfPipe = 0x00002000,
89 AllGraphics = 0x00008000,
90 AllCommands = 0x00010000,
91 TransformFeedback = 0x01000000,
92 ConditionalRendering = 0x00040000,
93 AccelerationStructureBuild = 0x02000000,
94 RayTracingShader = 0x00200000,
95 FragmentDensityProcess = 0x00800000,
96 FragmentShaderRateAttachment = 0x00400000,
97 CommandPreprocess = 0x00020000,
98 TaskShader = 0x00080000,
99 MeshShader = 0x00100000,
102 inline PipelineStageBit operator|(PipelineStageBit a, PipelineStageBit b) {
103 return static_cast<PipelineStageBit
>(
static_cast<uint32_t
>(a) |
static_cast<uint32_t
>(b));
106 inline PipelineStageBit& operator|=(PipelineStageBit& a, PipelineStageBit b) {
114 R4G4B4A4_UNORM_PACK16,
115 B4G4R4A4_UNORM_PACK16,
118 R5G5B5A1_UNORM_PACK16,
119 B5G5R5A1_UNORM_PACK16,
120 A1R5G5B5_UNORM_PACK16,
163 A8B8G8R8_UNORM_PACK32,
164 A8B8G8R8_SNORM_PACK32,
165 A8B8G8R8_USCALED_PACK32,
166 A8B8G8R8_SSCALED_PACK32,
167 A8B8G8R8_UINT_PACK32,
168 A8B8G8R8_SINT_PACK32,
169 A8B8G8R8_SRGB_PACK32,
170 A2R10G10B10_UNORM_PACK32,
171 A2R10G10B10_SNORM_PACK32,
172 A2R10G10B10_USCALED_PACK32,
173 A2R10G10B10_SSCALED_PACK32,
174 A2R10G10B10_UINT_PACK32,
175 A2R10G10B10_SINT_PACK32,
176 A2B10G10R10_UNORM_PACK32,
177 A2B10G10R10_SNORM_PACK32,
178 A2B10G10R10_USCALED_PACK32,
179 A2B10G10R10_SSCALED_PACK32,
180 A2B10G10R10_UINT_PACK32,
181 A2B10G10R10_SINT_PACK32,
205 R16G16B16A16_USCALED,
206 R16G16B16A16_SSCALED,
234 B10G11R11_UFLOAT_PACK32,
235 E5B9G9R9_UFLOAT_PACK32,
247 BC1_RGBA_UNORM_BLOCK,
261 ETC2_R8G8B8_UNORM_BLOCK,
262 ETC2_R8G8B8_SRGB_BLOCK,
263 ETC2_R8G8B8A1_UNORM_BLOCK,
264 ETC2_R8G8B8A1_SRGB_BLOCK,
265 ETC2_R8G8B8A8_UNORM_BLOCK,
266 ETC2_R8G8B8A8_SRGB_BLOCK,
269 EAC_R11G11_UNORM_BLOCK,
270 EAC_R11G11_SNORM_BLOCK,
271 ASTC_4x4_UNORM_BLOCK,
273 ASTC_5x4_UNORM_BLOCK,
275 ASTC_5x5_UNORM_BLOCK,
277 ASTC_6x5_UNORM_BLOCK,
279 ASTC_6x6_UNORM_BLOCK,
281 ASTC_8x5_UNORM_BLOCK,
283 ASTC_8x6_UNORM_BLOCK,
285 ASTC_8x8_UNORM_BLOCK,
287 ASTC_10x5_UNORM_BLOCK,
288 ASTC_10x5_SRGB_BLOCK,
289 ASTC_10x6_UNORM_BLOCK,
290 ASTC_10x6_SRGB_BLOCK,
291 ASTC_10x8_UNORM_BLOCK,
292 ASTC_10x8_SRGB_BLOCK,
293 ASTC_10x10_UNORM_BLOCK,
294 ASTC_10x10_SRGB_BLOCK,
295 ASTC_12x10_UNORM_BLOCK,
296 ASTC_12x10_SRGB_BLOCK,
297 ASTC_12x12_UNORM_BLOCK,
298 ASTC_12x12_SRGB_BLOCK,
301 G8_B8_R8_3PLANE_420_UNORM,
302 G8_B8R8_2PLANE_420_UNORM,
303 G8_B8_R8_3PLANE_422_UNORM,
304 G8_B8R8_2PLANE_422_UNORM,
305 G8_B8_R8_3PLANE_444_UNORM,
307 R10X6G10X6_UNORM_2PACK16,
308 R10X6G10X6B10X6A10X6_UNORM_4PACK16,
309 G10X6B10X6G10X6R10X6_422_UNORM_4PACK16,
310 B10X6G10X6R10X6G10X6_422_UNORM_4PACK16,
311 G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16,
312 G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
313 G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16,
314 G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16,
315 G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16,
317 R12X4G12X4_UNORM_2PACK16,
318 R12X4G12X4B12X4A12X4_UNORM_4PACK16,
319 G12X4B12X4G12X4R12X4_422_UNORM_4PACK16,
320 B12X4G12X4R12X4G12X4_422_UNORM_4PACK16,
321 G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16,
322 G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16,
323 G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16,
324 G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16,
325 G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16,
326 G16B16G16R16_422_UNORM,
327 B16G16R16G16_422_UNORM,
328 G16_B16_R16_3PLANE_420_UNORM,
329 G16_B16R16_2PLANE_420_UNORM,
330 G16_B16_R16_3PLANE_422_UNORM,
331 G16_B16R16_2PLANE_422_UNORM,
332 G16_B16_R16_3PLANE_444_UNORM,
333 G8_B8R8_2PLANE_444_UNORM,
334 G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16,
335 G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16,
336 G16_B16R16_2PLANE_444_UNORM,
337 A4R4G4B4_UNORM_PACK16,
338 A4B4G4R4_UNORM_PACK16,
364 A1B5G5R5_UNORM_PACK16,
368 enum class FormatDepthStencilType {
375 FormatDepthStencilType GetFormatDepthStencilType(Format format);
376 bool IsFormatCompressed(Format format);
377 uint8_t GetCompressedFormatBlockSize(Format format);
378 uint8_t GetFormatBytesPerPixel(Grindstone::GraphicsAPI::Format format);
380 #define SHADER_STAGE_TYPES \
381 GSExpandEntry(Vertex, 1 << 0),\
382 GSExpandEntry(TesselationEvaluation, 1 << 1),\
383 GSExpandEntry(TesselationControl, 1 << 2),\
384 GSExpandEntry(Geometry, 1 << 3),\
385 GSExpandEntry(Fragment, 1 << 4),\
386 GSExpandEntry(Task, 1 << 5),\
387 GSExpandEntry(Mesh, 1 << 6),\
388 GSExpandEntry(Compute, 1 << 7)
390 enum class ShaderStage : uint8_t {
391 #define GSExpandEntry(key, bit) key
394 GraphicsCount = Compute,
398 constexpr uint8_t numShaderGraphicStage =
static_cast<uint8_t
>(ShaderStage::GraphicsCount);
399 constexpr uint8_t numShaderTotalStage =
static_cast<uint8_t
>(ShaderStage::Count);
401 enum class ShaderStageBit : uint8_t {
403#define GSExpandEntry(key, bit) key = bit
406 AllGraphics = Vertex | TesselationEvaluation | TesselationControl | Geometry | Fragment | Task | Mesh,
407 All = AllGraphics | Compute
410 constexpr const char* shaderStageNames[] = {
411 #define GSExpandEntry(key, bit) #key
416 inline const char* GetShaderStageName(Grindstone::GraphicsAPI::ShaderStage stage) {
417 uint8_t index =
static_cast<uint8_t
>(stage);
418 if (index >=
static_cast<uint8_t
>(ShaderStage::Count)) {
422 return shaderStageNames[index];
425 enum class BindingType {
428 CombinedImageSampler,
435 UniformBufferDynamic,
436 StorageBufferDynamic,
437 AccelerationStructure
440#define BLEND_OPERATIONS_LIST \
441 GSExpandEntry(None),\
443 GSExpandEntry(Subtract),\
444 GSExpandEntry(ReverseSubtract),\
445 GSExpandEntry(Minimum),\
446 GSExpandEntry(Maximum),\
447 GSExpandEntry(Zero),\
448 GSExpandEntry(Source),\
449 GSExpandEntry(Destination),\
450 GSExpandEntry(SourceOver),\
451 GSExpandEntry(DestinationOver),\
452 GSExpandEntry(SourceIn),\
453 GSExpandEntry(DestinationIn),\
454 GSExpandEntry(SourceOut),\
455 GSExpandEntry(DestinationOut),\
456 GSExpandEntry(SourceAtop),\
457 GSExpandEntry(DestinationAtop),\
459 GSExpandEntry(Multiply),\
460 GSExpandEntry(Screen),\
461 GSExpandEntry(Overlay),\
462 GSExpandEntry(Darken),\
463 GSExpandEntry(Lighten),\
464 GSExpandEntry(ColorDodge),\
465 GSExpandEntry(ColorBurn),\
466 GSExpandEntry(HardLight),\
467 GSExpandEntry(SoftLight),\
468 GSExpandEntry(Difference),\
469 GSExpandEntry(Exclusion),\
470 GSExpandEntry(Invert),\
471 GSExpandEntry(InvertRGB),\
472 GSExpandEntry(LinearDodge),\
473 GSExpandEntry(LinearBurn),\
474 GSExpandEntry(VividLight),\
475 GSExpandEntry(LinearLight),\
476 GSExpandEntry(PinLight),\
477 GSExpandEntry(HardMix),\
478 GSExpandEntry(HSLHue),\
479 GSExpandEntry(HSLSaturation),\
480 GSExpandEntry(HSLColor),\
481 GSExpandEntry(HSLLuminosity),\
482 GSExpandEntry(Plus),\
483 GSExpandEntry(PlusClamped),\
484 GSExpandEntry(PlusClampedAlpha),\
485 GSExpandEntry(PlusDark),\
486 GSExpandEntry(Minus),\
487 GSExpandEntry(MinusClamped),\
488 GSExpandEntry(Contrast),\
489 GSExpandEntry(InvertOVG),\
491 GSExpandEntry(Green),\
494 enum class BlendOperation : uint8_t {
495#define GSExpandEntry(key) key
496 BLEND_OPERATIONS_LIST,
501 constexpr const char* blendOperationNames[] = {
502 #define GSExpandEntry(key) #key
503 BLEND_OPERATIONS_LIST
507 inline const char* GetBlendOperationName(Grindstone::GraphicsAPI::BlendOperation op) {
508 uint8_t index =
static_cast<uint8_t
>(op);
509 if (index >=
static_cast<uint8_t
>(BlendOperation::Count)) {
513 return blendOperationNames[index];
517#define BLEND_FACTORS_LIST \
518 GSExpandEntry(Zero),\
520 GSExpandEntry(SrcColor),\
521 GSExpandEntry(OneMinusSrcColor),\
522 GSExpandEntry(DstColor),\
523 GSExpandEntry(OneMinusDstColor),\
524 GSExpandEntry(SrcAlpha),\
525 GSExpandEntry(OneMinusSrcAlpha),\
526 GSExpandEntry(DstAlpha),\
527 GSExpandEntry(OneMinusDstAlpha),\
528 GSExpandEntry(ConstantColor),\
529 GSExpandEntry(OneMinusConstantColor),\
530 GSExpandEntry(ConstantAlpha),\
531 GSExpandEntry(OneMinusConstantAlpha),\
532 GSExpandEntry(SrcAlphaSaturate),\
533 GSExpandEntry(Src1Color),\
534 GSExpandEntry(OneMinusSrc1Color),\
535 GSExpandEntry(Src1Alpha),\
536 GSExpandEntry(OneMinusSrc1Alpha)
538 enum class BlendFactor : uint8_t {
539 #define GSExpandEntry(key) key
545 constexpr const char* blendFactorNames[] = {
546 #define GSExpandEntry(key) #key
551 inline const char* GetBlendFactorName(Grindstone::GraphicsAPI::BlendFactor factor) {
552 uint8_t index =
static_cast<uint8_t
>(factor);
553 if (index >=
static_cast<uint8_t
>(BlendFactor::Count)) {
557 return blendFactorNames[index];
561 BlendOperation colorOperation = BlendOperation::None;
562 BlendFactor colorFactorSrc = BlendFactor::One;
563 BlendFactor colorFactorDst = BlendFactor::One;
565 BlendOperation alphaOperation = BlendOperation::None;
566 BlendFactor alphaFactorSrc = BlendFactor::One;
567 BlendFactor alphaFactorDst = BlendFactor::One;
571 BlendOperation::None,
575 BlendOperation::None,
596 BlendFactor::SrcAlpha,
597 BlendFactor::OneMinusSrcAlpha,
601 BlendFactor::OneMinusSrcAlpha
606#define GEOMETRY_TYPES_LIST \
607 GSExpandEntry(Points),\
608 GSExpandEntry(Lines),\
609 GSExpandEntry(LineStrips),\
610 GSExpandEntry(LineLoops),\
611 GSExpandEntry(TriangleStrips),\
612 GSExpandEntry(TriangleFans),\
613 GSExpandEntry(Triangles),\
614 GSExpandEntry(LinesAdjacency),\
615 GSExpandEntry(TrianglesAdjacency),\
616 GSExpandEntry(TriangleStripsAdjacency),\
617 GSExpandEntry(Patches)
619 enum class GeometryType : uint8_t {
620 #define GSExpandEntry(key) key
626 constexpr const char* geometryTypeNames[] = {
627 #define GSExpandEntry(key) #key
632 inline const char* GetGeometryTypeName(Grindstone::GraphicsAPI::GeometryType stage) {
633 uint8_t index =
static_cast<uint8_t
>(stage);
634 if (index >=
static_cast<uint8_t
>(GeometryType::Count)) {
638 return geometryTypeNames[index];
641 enum class PolygonFillMode : uint8_t {
647 constexpr const char* polygonFillModeNames[] = {
653 inline const char* GetPolygonFillModeName(Grindstone::GraphicsAPI::PolygonFillMode mode) {
654 uint8_t index =
static_cast<uint8_t
>(mode);
655 if (index >
static_cast<uint8_t
>(PolygonFillMode::Fill)) {
659 return polygonFillModeNames[index];
662 enum class CompareOperation : uint8_t {
673 constexpr const char* compareOperationNames[] = {
674 #define GSExpandEntry(key, bit) #key
679 inline const char* GetCompareOperationName(Grindstone::GraphicsAPI::CompareOperation op) {
680 uint8_t index =
static_cast<uint8_t
>(op);
681 if (index >
static_cast<uint8_t
>(CompareOperation::Always)) {
685 return compareOperationNames[index];
688 enum class ColorMask : uint8_t {
702 RGB = Red | Green | Blue,
703 RGA = Red | Green | Alpha,
704 RBA = Red | Blue | Alpha,
705 GBA = Green | Blue | Alpha,
707 RGBA = Red | Green | Blue | Alpha
710 constexpr const char* colorMaskNames[] = {
729 inline const char* GetColorMaskName(Grindstone::GraphicsAPI::ColorMask colorMask) {
730 uint8_t index =
static_cast<uint8_t
>(colorMask);
731 if (index >
static_cast<uint8_t
>(ColorMask::RGBA)) {
735 return colorMaskNames[index];
738 enum class CullMode : uint8_t {
745 constexpr const char* cullModeNames[] = {
752 inline const char* GetCullModeName(Grindstone::GraphicsAPI::CullMode cullMode) {
753 uint8_t index =
static_cast<uint8_t
>(cullMode);
754 if (index >
static_cast<uint8_t
>(CullMode::Both)) {
758 return cullModeNames[index];
762 enum class AttributeUsage {
777 enum class VertexInputRate {
784 const char* name =
nullptr;
785 uint32_t bindingIndex;
786 uint32_t locationIndex = 0;
787 Format format = Format::R32_SFLOAT;
788 uint32_t byteOffset = 0;
789 AttributeUsage attributeUsage = AttributeUsage::Other;
794 uint32_t bindingIndex;
796 VertexInputRate inputRate = VertexInputRate::Vertex;
800 std::vector<VertexBindingDescription> bindings;
801 std::vector<VertexAttributeDescription> attributes;
804 struct VertexInputLayoutBuilder {
805 std::vector<VertexBindingDescription> bindings;
806 std::vector<VertexAttributeDescription> attributes;
808 VertexInputLayoutBuilder() =
default;
812 uint32_t locationIndex;
815 AttributeUsage attributeUsage;
818 VertexInputLayoutBuilder& AddBinding(
820 std::initializer_list<InlineAttribute> newAttributes
822 bindings.emplace_back(binding);
826 binding.bindingIndex,
827 attrib.locationIndex,
830 attrib.attributeUsage
837 VertexInputLayoutBuilder& AddBinding(VertexBindingDescription binding) {
838 bindings.emplace_back(binding);
842 VertexInputLayoutBuilder& AddAttribute(VertexAttributeDescription attribute) {
843 attributes.emplace_back(attribute);
847 VertexInputLayout Build() {
856inline Grindstone::GraphicsAPI::ShaderStageBit ToShaderStageBit(
const Grindstone::GraphicsAPI::ShaderStage stage) {
857 using ShaderStageType = uint8_t;
858 return static_cast<Grindstone::GraphicsAPI::ShaderStageBit
>(1 <<
static_cast<ShaderStageType
>(stage));
861inline Grindstone::GraphicsAPI::ShaderStageBit operator~(
const Grindstone::GraphicsAPI::ShaderStageBit stages) {
862 using ShaderStageBitType = uint8_t;
863 return static_cast<Grindstone::GraphicsAPI::ShaderStageBit
>(~static_cast<ShaderStageBitType>(stages));
866inline Grindstone::GraphicsAPI::ShaderStageBit operator|(
const Grindstone::GraphicsAPI::ShaderStageBit a,
const Grindstone::GraphicsAPI::ShaderStageBit b) {
867 using ShaderStageBitType = uint8_t;
868 return static_cast<Grindstone::GraphicsAPI::ShaderStageBit
>(
static_cast<ShaderStageBitType
>(a) |
static_cast<ShaderStageBitType
>(b));
871inline Grindstone::GraphicsAPI::ShaderStageBit operator&(
const Grindstone::GraphicsAPI::ShaderStageBit a,
const Grindstone::GraphicsAPI::ShaderStageBit b) {
872 using ShaderStageBitType = uint8_t;
873 return static_cast<Grindstone::GraphicsAPI::ShaderStageBit
>(
static_cast<ShaderStageBitType
>(a) &
static_cast<ShaderStageBitType
>(b));
876inline Grindstone::GraphicsAPI::ShaderStageBit operator^(
const Grindstone::GraphicsAPI::ShaderStageBit a,
const Grindstone::GraphicsAPI::ShaderStageBit b) {
877 using ShaderStageBitType = uint8_t;
878 return static_cast<Grindstone::GraphicsAPI::ShaderStageBit
>(
static_cast<ShaderStageBitType
>(a) ^
static_cast<ShaderStageBitType
>(b));
881inline Grindstone::GraphicsAPI::ShaderStageBit& operator|=(Grindstone::GraphicsAPI::ShaderStageBit& a,
const Grindstone::GraphicsAPI::ShaderStageBit b) {
886inline Grindstone::GraphicsAPI::ShaderStageBit& operator&=(Grindstone::GraphicsAPI::ShaderStageBit& a,
const Grindstone::GraphicsAPI::ShaderStageBit b) {
891inline Grindstone::GraphicsAPI::ShaderStageBit& operator^=(Grindstone::GraphicsAPI::ShaderStageBit& a,
const Grindstone::GraphicsAPI::ShaderStageBit b) {
896inline Grindstone::GraphicsAPI::ColorMask operator~(
const Grindstone::GraphicsAPI::ColorMask stages) {
897 using ColorMaskType = uint8_t;
898 return static_cast<Grindstone::GraphicsAPI::ColorMask
>(~static_cast<ColorMaskType>(stages));
901inline Grindstone::GraphicsAPI::ColorMask operator|(
const Grindstone::GraphicsAPI::ColorMask a,
const Grindstone::GraphicsAPI::ColorMask b) {
902 using ColorMaskType = uint8_t;
903 return static_cast<Grindstone::GraphicsAPI::ColorMask
>(
static_cast<ColorMaskType
>(a) |
static_cast<ColorMaskType
>(b));
906inline Grindstone::GraphicsAPI::ColorMask operator&(
const Grindstone::GraphicsAPI::ColorMask a,
const Grindstone::GraphicsAPI::ColorMask b) {
907 using ColorMaskType = uint8_t;
908 return static_cast<Grindstone::GraphicsAPI::ColorMask
>(
static_cast<ColorMaskType
>(a) &
static_cast<ColorMaskType
>(b));
911inline Grindstone::GraphicsAPI::ColorMask operator^(
const Grindstone::GraphicsAPI::ColorMask a,
const Grindstone::GraphicsAPI::ColorMask b) {
912 using ColorMaskType = uint8_t;
913 return static_cast<Grindstone::GraphicsAPI::ColorMask
>(
static_cast<ColorMaskType
>(a) ^
static_cast<ColorMaskType
>(b));
916inline Grindstone::GraphicsAPI::ColorMask& operator|=(Grindstone::GraphicsAPI::ColorMask& a,
const Grindstone::GraphicsAPI::ColorMask b) {
921inline Grindstone::GraphicsAPI::ColorMask& operator&=(Grindstone::GraphicsAPI::ColorMask& a,
const Grindstone::GraphicsAPI::ColorMask b) {
926inline Grindstone::GraphicsAPI::ColorMask& operator^=(Grindstone::GraphicsAPI::ColorMask& a,
const Grindstone::GraphicsAPI::ColorMask b) {
935 size_t result = std::hash<size_t>{}(
936 static_cast<size_t>(binding.bindingIndex) << 8 |
937 static_cast<size_t>(binding.stride) << 32
939 result ^= std::hash<size_t>{}(
static_cast<size_t>(binding.inputRate));
947 size_t result = std::hash<size_t>{}(
948 static_cast<size_t>(attribute.attributeUsage) |
949 static_cast<size_t>(attribute.bindingIndex) << 32
952 result ^= std::hash<size_t>{}(
953 static_cast<size_t>(attribute.byteOffset) |
954 static_cast<size_t>(attribute.format) << 32
957 result ^= std::hash<size_t>{}(
958 static_cast<size_t>(attribute.locationIndex) << 32
968 size_t result = std::hash<size_t>{}(vertexInputLayout.attributes.size()) ^ std::hash<size_t>{}(vertexInputLayout.bindings.size());
971 result ^= std::hash<Grindstone::GraphicsAPI::VertexBindingDescription>{}(binding);
975 result ^= std::hash<Grindstone::GraphicsAPI::VertexAttributeDescription>{}(attribute);
Definition Formats.hpp:560
Definition Formats.hpp:783
Definition Formats.hpp:793