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 MemoryUsage {
49 enum class ImageDimension {
56 enum class ImageAspectBits : uint16_t {
61 Metadata = 0x00000008,
65 MemoryPlane0 = 0x00000080,
66 MemoryPlane1 = 0x00000100,
67 MemoryPlane2 = 0x00000200,
68 MemoryPlane3 = 0x00000400,
71 inline ImageAspectBits operator|(ImageAspectBits a, ImageAspectBits b) {
72 return static_cast<ImageAspectBits
>(
static_cast<uint32_t
>(a) |
static_cast<uint32_t
>(b));
75 inline ImageAspectBits& operator|=(ImageAspectBits& a, ImageAspectBits b) {
80 enum class PipelineStageBit : uint32_t {
82 TopOfPipe = 0x00000001,
83 DrawIndirect = 0x00000002,
84 VertexInput = 0x00000004,
85 VertexShader = 0x00000008,
86 TesslationControlShader = 0x00000010,
87 TesselationEvaluationShader = 0x00000020,
88 GeometryShader = 0x00000040,
89 FragmentShader = 0x00000080,
90 EarlyFragmentTests = 0x00000100,
91 LateFragmentTests = 0x00000200,
92 ColorAttachmentOutput = 0x00000400,
93 ComputeShader = 0x00000800,
94 Transfer = 0x00001000,
95 BottomOfPipe = 0x00002000,
97 AllGraphics = 0x00008000,
98 AllCommands = 0x00010000,
99 TransformFeedback = 0x01000000,
100 ConditionalRendering = 0x00040000,
101 AccelerationStructureBuild = 0x02000000,
102 RayTracingShader = 0x00200000,
103 FragmentDensityProcess = 0x00800000,
104 FragmentShaderRateAttachment = 0x00400000,
105 CommandPreprocess = 0x00020000,
106 TaskShader = 0x00080000,
107 MeshShader = 0x00100000,
110 inline PipelineStageBit operator|(PipelineStageBit a, PipelineStageBit b) {
111 return static_cast<PipelineStageBit
>(
static_cast<uint32_t
>(a) |
static_cast<uint32_t
>(b));
114 inline PipelineStageBit& operator|=(PipelineStageBit& a, PipelineStageBit b) {
122 R4G4B4A4_UNORM_PACK16,
123 B4G4R4A4_UNORM_PACK16,
126 R5G5B5A1_UNORM_PACK16,
127 B5G5R5A1_UNORM_PACK16,
128 A1R5G5B5_UNORM_PACK16,
171 A8B8G8R8_UNORM_PACK32,
172 A8B8G8R8_SNORM_PACK32,
173 A8B8G8R8_USCALED_PACK32,
174 A8B8G8R8_SSCALED_PACK32,
175 A8B8G8R8_UINT_PACK32,
176 A8B8G8R8_SINT_PACK32,
177 A8B8G8R8_SRGB_PACK32,
178 A2R10G10B10_UNORM_PACK32,
179 A2R10G10B10_SNORM_PACK32,
180 A2R10G10B10_USCALED_PACK32,
181 A2R10G10B10_SSCALED_PACK32,
182 A2R10G10B10_UINT_PACK32,
183 A2R10G10B10_SINT_PACK32,
184 A2B10G10R10_UNORM_PACK32,
185 A2B10G10R10_SNORM_PACK32,
186 A2B10G10R10_USCALED_PACK32,
187 A2B10G10R10_SSCALED_PACK32,
188 A2B10G10R10_UINT_PACK32,
189 A2B10G10R10_SINT_PACK32,
213 R16G16B16A16_USCALED,
214 R16G16B16A16_SSCALED,
242 B10G11R11_UFLOAT_PACK32,
243 E5B9G9R9_UFLOAT_PACK32,
255 BC1_RGBA_UNORM_BLOCK,
269 ETC2_R8G8B8_UNORM_BLOCK,
270 ETC2_R8G8B8_SRGB_BLOCK,
271 ETC2_R8G8B8A1_UNORM_BLOCK,
272 ETC2_R8G8B8A1_SRGB_BLOCK,
273 ETC2_R8G8B8A8_UNORM_BLOCK,
274 ETC2_R8G8B8A8_SRGB_BLOCK,
277 EAC_R11G11_UNORM_BLOCK,
278 EAC_R11G11_SNORM_BLOCK,
279 ASTC_4x4_UNORM_BLOCK,
281 ASTC_5x4_UNORM_BLOCK,
283 ASTC_5x5_UNORM_BLOCK,
285 ASTC_6x5_UNORM_BLOCK,
287 ASTC_6x6_UNORM_BLOCK,
289 ASTC_8x5_UNORM_BLOCK,
291 ASTC_8x6_UNORM_BLOCK,
293 ASTC_8x8_UNORM_BLOCK,
295 ASTC_10x5_UNORM_BLOCK,
296 ASTC_10x5_SRGB_BLOCK,
297 ASTC_10x6_UNORM_BLOCK,
298 ASTC_10x6_SRGB_BLOCK,
299 ASTC_10x8_UNORM_BLOCK,
300 ASTC_10x8_SRGB_BLOCK,
301 ASTC_10x10_UNORM_BLOCK,
302 ASTC_10x10_SRGB_BLOCK,
303 ASTC_12x10_UNORM_BLOCK,
304 ASTC_12x10_SRGB_BLOCK,
305 ASTC_12x12_UNORM_BLOCK,
306 ASTC_12x12_SRGB_BLOCK,
309 G8_B8_R8_3PLANE_420_UNORM,
310 G8_B8R8_2PLANE_420_UNORM,
311 G8_B8_R8_3PLANE_422_UNORM,
312 G8_B8R8_2PLANE_422_UNORM,
313 G8_B8_R8_3PLANE_444_UNORM,
315 R10X6G10X6_UNORM_2PACK16,
316 R10X6G10X6B10X6A10X6_UNORM_4PACK16,
317 G10X6B10X6G10X6R10X6_422_UNORM_4PACK16,
318 B10X6G10X6R10X6G10X6_422_UNORM_4PACK16,
319 G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16,
320 G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
321 G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16,
322 G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16,
323 G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16,
325 R12X4G12X4_UNORM_2PACK16,
326 R12X4G12X4B12X4A12X4_UNORM_4PACK16,
327 G12X4B12X4G12X4R12X4_422_UNORM_4PACK16,
328 B12X4G12X4R12X4G12X4_422_UNORM_4PACK16,
329 G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16,
330 G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16,
331 G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16,
332 G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16,
333 G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16,
334 G16B16G16R16_422_UNORM,
335 B16G16R16G16_422_UNORM,
336 G16_B16_R16_3PLANE_420_UNORM,
337 G16_B16R16_2PLANE_420_UNORM,
338 G16_B16_R16_3PLANE_422_UNORM,
339 G16_B16R16_2PLANE_422_UNORM,
340 G16_B16_R16_3PLANE_444_UNORM,
341 G8_B8R8_2PLANE_444_UNORM,
342 G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16,
343 G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16,
344 G16_B16R16_2PLANE_444_UNORM,
345 A4R4G4B4_UNORM_PACK16,
346 A4B4G4R4_UNORM_PACK16,
372 A1B5G5R5_UNORM_PACK16,
376 enum class FormatDepthStencilType {
383 FormatDepthStencilType GetFormatDepthStencilType(Format format);
384 bool IsFormatCompressed(Format format);
385 uint8_t GetCompressedFormatBlockSize(Format format);
386 uint8_t GetFormatBytesPerPixel(Grindstone::GraphicsAPI::Format format);
388 #define SHADER_STAGE_TYPES \
389 GSExpandEntry(Vertex, 1 << 0),\
390 GSExpandEntry(TesselationEvaluation, 1 << 1),\
391 GSExpandEntry(TesselationControl, 1 << 2),\
392 GSExpandEntry(Geometry, 1 << 3),\
393 GSExpandEntry(Fragment, 1 << 4),\
394 GSExpandEntry(Task, 1 << 5),\
395 GSExpandEntry(Mesh, 1 << 6),\
396 GSExpandEntry(Compute, 1 << 7)
398 enum class ShaderStage : uint8_t {
399 #define GSExpandEntry(key, bit) key
402 GraphicsCount = Compute,
406 constexpr uint8_t numShaderGraphicStage =
static_cast<uint8_t
>(ShaderStage::GraphicsCount);
407 constexpr uint8_t numShaderTotalStage =
static_cast<uint8_t
>(ShaderStage::Count);
409 enum class ShaderStageBit : uint8_t {
411#define GSExpandEntry(key, bit) key = bit
414 AllGraphics = Vertex | TesselationEvaluation | TesselationControl | Geometry | Fragment | Task | Mesh,
415 All = AllGraphics | Compute
418 constexpr const char* shaderStageNames[] = {
419 #define GSExpandEntry(key, bit) #key
424 inline const char* GetShaderStageName(Grindstone::GraphicsAPI::ShaderStage stage) {
425 uint8_t index =
static_cast<uint8_t
>(stage);
426 if (index >=
static_cast<uint8_t
>(ShaderStage::Count)) {
430 return shaderStageNames[index];
433 enum class BindingType {
436 CombinedImageSampler,
443 UniformBufferDynamic,
444 StorageBufferDynamic,
445 AccelerationStructure
448#define BLEND_OPERATIONS_LIST \
449 GSExpandEntry(None),\
451 GSExpandEntry(Subtract),\
452 GSExpandEntry(ReverseSubtract),\
453 GSExpandEntry(Minimum),\
454 GSExpandEntry(Maximum),\
455 GSExpandEntry(Zero),\
456 GSExpandEntry(Source),\
457 GSExpandEntry(Destination),\
458 GSExpandEntry(SourceOver),\
459 GSExpandEntry(DestinationOver),\
460 GSExpandEntry(SourceIn),\
461 GSExpandEntry(DestinationIn),\
462 GSExpandEntry(SourceOut),\
463 GSExpandEntry(DestinationOut),\
464 GSExpandEntry(SourceAtop),\
465 GSExpandEntry(DestinationAtop),\
467 GSExpandEntry(Multiply),\
468 GSExpandEntry(Screen),\
469 GSExpandEntry(Overlay),\
470 GSExpandEntry(Darken),\
471 GSExpandEntry(Lighten),\
472 GSExpandEntry(ColorDodge),\
473 GSExpandEntry(ColorBurn),\
474 GSExpandEntry(HardLight),\
475 GSExpandEntry(SoftLight),\
476 GSExpandEntry(Difference),\
477 GSExpandEntry(Exclusion),\
478 GSExpandEntry(Invert),\
479 GSExpandEntry(InvertRGB),\
480 GSExpandEntry(LinearDodge),\
481 GSExpandEntry(LinearBurn),\
482 GSExpandEntry(VividLight),\
483 GSExpandEntry(LinearLight),\
484 GSExpandEntry(PinLight),\
485 GSExpandEntry(HardMix),\
486 GSExpandEntry(HSLHue),\
487 GSExpandEntry(HSLSaturation),\
488 GSExpandEntry(HSLColor),\
489 GSExpandEntry(HSLLuminosity),\
490 GSExpandEntry(Plus),\
491 GSExpandEntry(PlusClamped),\
492 GSExpandEntry(PlusClampedAlpha),\
493 GSExpandEntry(PlusDark),\
494 GSExpandEntry(Minus),\
495 GSExpandEntry(MinusClamped),\
496 GSExpandEntry(Contrast),\
497 GSExpandEntry(InvertOVG),\
499 GSExpandEntry(Green),\
502 enum class BlendOperation : uint8_t {
503#define GSExpandEntry(key) key
504 BLEND_OPERATIONS_LIST,
509 constexpr const char* blendOperationNames[] = {
510 #define GSExpandEntry(key) #key
511 BLEND_OPERATIONS_LIST
515 inline const char* GetBlendOperationName(Grindstone::GraphicsAPI::BlendOperation op) {
516 uint8_t index =
static_cast<uint8_t
>(op);
517 if (index >=
static_cast<uint8_t
>(BlendOperation::Count)) {
521 return blendOperationNames[index];
525#define BLEND_FACTORS_LIST \
526 GSExpandEntry(Zero),\
528 GSExpandEntry(SrcColor),\
529 GSExpandEntry(OneMinusSrcColor),\
530 GSExpandEntry(DstColor),\
531 GSExpandEntry(OneMinusDstColor),\
532 GSExpandEntry(SrcAlpha),\
533 GSExpandEntry(OneMinusSrcAlpha),\
534 GSExpandEntry(DstAlpha),\
535 GSExpandEntry(OneMinusDstAlpha),\
536 GSExpandEntry(ConstantColor),\
537 GSExpandEntry(OneMinusConstantColor),\
538 GSExpandEntry(ConstantAlpha),\
539 GSExpandEntry(OneMinusConstantAlpha),\
540 GSExpandEntry(SrcAlphaSaturate),\
541 GSExpandEntry(Src1Color),\
542 GSExpandEntry(OneMinusSrc1Color),\
543 GSExpandEntry(Src1Alpha),\
544 GSExpandEntry(OneMinusSrc1Alpha)
546 enum class BlendFactor : uint8_t {
547 #define GSExpandEntry(key) key
553 constexpr const char* blendFactorNames[] = {
554 #define GSExpandEntry(key) #key
559 inline const char* GetBlendFactorName(Grindstone::GraphicsAPI::BlendFactor factor) {
560 uint8_t index =
static_cast<uint8_t
>(factor);
561 if (index >=
static_cast<uint8_t
>(BlendFactor::Count)) {
565 return blendFactorNames[index];
569 BlendOperation colorOperation = BlendOperation::None;
570 BlendFactor colorFactorSrc = BlendFactor::One;
571 BlendFactor colorFactorDst = BlendFactor::One;
573 BlendOperation alphaOperation = BlendOperation::None;
574 BlendFactor alphaFactorSrc = BlendFactor::One;
575 BlendFactor alphaFactorDst = BlendFactor::One;
579 BlendOperation::None,
583 BlendOperation::None,
604 BlendFactor::SrcAlpha,
605 BlendFactor::OneMinusSrcAlpha,
609 BlendFactor::OneMinusSrcAlpha
614#define GEOMETRY_TYPES_LIST \
615 GSExpandEntry(Points),\
616 GSExpandEntry(Lines),\
617 GSExpandEntry(LineStrips),\
618 GSExpandEntry(LineLoops),\
619 GSExpandEntry(TriangleStrips),\
620 GSExpandEntry(TriangleFans),\
621 GSExpandEntry(Triangles),\
622 GSExpandEntry(LinesAdjacency),\
623 GSExpandEntry(TrianglesAdjacency),\
624 GSExpandEntry(TriangleStripsAdjacency),\
625 GSExpandEntry(Patches)
627 enum class GeometryType : uint8_t {
628 #define GSExpandEntry(key) key
634 constexpr const char* geometryTypeNames[] = {
635 #define GSExpandEntry(key) #key
640 inline const char* GetGeometryTypeName(Grindstone::GraphicsAPI::GeometryType stage) {
641 uint8_t index =
static_cast<uint8_t
>(stage);
642 if (index >=
static_cast<uint8_t
>(GeometryType::Count)) {
646 return geometryTypeNames[index];
649 enum class PolygonFillMode : uint8_t {
655 constexpr const char* polygonFillModeNames[] = {
661 inline const char* GetPolygonFillModeName(Grindstone::GraphicsAPI::PolygonFillMode mode) {
662 uint8_t index =
static_cast<uint8_t
>(mode);
663 if (index >
static_cast<uint8_t
>(PolygonFillMode::Fill)) {
667 return polygonFillModeNames[index];
670 enum class CompareOperation : uint8_t {
681 constexpr const char* compareOperationNames[] = {
682 #define GSExpandEntry(key, bit) #key
687 inline const char* GetCompareOperationName(Grindstone::GraphicsAPI::CompareOperation op) {
688 uint8_t index =
static_cast<uint8_t
>(op);
689 if (index >
static_cast<uint8_t
>(CompareOperation::Always)) {
693 return compareOperationNames[index];
696 enum class ColorMask : uint8_t {
710 RGB = Red | Green | Blue,
711 RGA = Red | Green | Alpha,
712 RBA = Red | Blue | Alpha,
713 GBA = Green | Blue | Alpha,
715 RGBA = Red | Green | Blue | Alpha
718 constexpr const char* colorMaskNames[] = {
737 inline const char* GetColorMaskName(Grindstone::GraphicsAPI::ColorMask colorMask) {
738 uint8_t index =
static_cast<uint8_t
>(colorMask);
739 if (index >
static_cast<uint8_t
>(ColorMask::RGBA)) {
743 return colorMaskNames[index];
746 enum class CullMode : uint8_t {
753 constexpr const char* cullModeNames[] = {
760 inline const char* GetCullModeName(Grindstone::GraphicsAPI::CullMode cullMode) {
761 uint8_t index =
static_cast<uint8_t
>(cullMode);
762 if (index >
static_cast<uint8_t
>(CullMode::Both)) {
766 return cullModeNames[index];
770 enum class AttributeUsage {
785 enum class VertexInputRate {
792 const char* name =
nullptr;
793 uint32_t bindingIndex;
794 uint32_t locationIndex = 0;
795 Format format = Format::R32_SFLOAT;
796 uint32_t byteOffset = 0;
797 AttributeUsage attributeUsage = AttributeUsage::Other;
802 uint32_t bindingIndex;
804 VertexInputRate inputRate = VertexInputRate::Vertex;
808 std::vector<VertexBindingDescription> bindings;
809 std::vector<VertexAttributeDescription> attributes;
812 struct VertexInputLayoutBuilder {
813 std::vector<VertexBindingDescription> bindings;
814 std::vector<VertexAttributeDescription> attributes;
816 VertexInputLayoutBuilder() =
default;
820 uint32_t locationIndex;
823 AttributeUsage attributeUsage;
826 VertexInputLayoutBuilder& AddBinding(
828 std::initializer_list<InlineAttribute> newAttributes
830 bindings.emplace_back(binding);
834 binding.bindingIndex,
835 attrib.locationIndex,
838 attrib.attributeUsage
845 VertexInputLayoutBuilder& AddBinding(VertexBindingDescription binding) {
846 bindings.emplace_back(binding);
850 VertexInputLayoutBuilder& AddAttribute(VertexAttributeDescription attribute) {
851 attributes.emplace_back(attribute);
855 VertexInputLayout Build() {
864inline Grindstone::GraphicsAPI::ShaderStageBit ToShaderStageBit(
const Grindstone::GraphicsAPI::ShaderStage stage) {
865 using ShaderStageType = uint8_t;
866 return static_cast<Grindstone::GraphicsAPI::ShaderStageBit
>(1 <<
static_cast<ShaderStageType
>(stage));
869inline Grindstone::GraphicsAPI::ShaderStageBit operator~(
const Grindstone::GraphicsAPI::ShaderStageBit stages) {
870 using ShaderStageBitType = uint8_t;
871 return static_cast<Grindstone::GraphicsAPI::ShaderStageBit
>(~static_cast<ShaderStageBitType>(stages));
874inline Grindstone::GraphicsAPI::ShaderStageBit operator|(
const Grindstone::GraphicsAPI::ShaderStageBit a,
const Grindstone::GraphicsAPI::ShaderStageBit b) {
875 using ShaderStageBitType = uint8_t;
876 return static_cast<Grindstone::GraphicsAPI::ShaderStageBit
>(
static_cast<ShaderStageBitType
>(a) |
static_cast<ShaderStageBitType
>(b));
879inline Grindstone::GraphicsAPI::ShaderStageBit operator&(
const Grindstone::GraphicsAPI::ShaderStageBit a,
const Grindstone::GraphicsAPI::ShaderStageBit b) {
880 using ShaderStageBitType = uint8_t;
881 return static_cast<Grindstone::GraphicsAPI::ShaderStageBit
>(
static_cast<ShaderStageBitType
>(a) &
static_cast<ShaderStageBitType
>(b));
884inline Grindstone::GraphicsAPI::ShaderStageBit operator^(
const Grindstone::GraphicsAPI::ShaderStageBit a,
const Grindstone::GraphicsAPI::ShaderStageBit b) {
885 using ShaderStageBitType = uint8_t;
886 return static_cast<Grindstone::GraphicsAPI::ShaderStageBit
>(
static_cast<ShaderStageBitType
>(a) ^
static_cast<ShaderStageBitType
>(b));
889inline Grindstone::GraphicsAPI::ShaderStageBit& operator|=(Grindstone::GraphicsAPI::ShaderStageBit& a,
const Grindstone::GraphicsAPI::ShaderStageBit b) {
894inline Grindstone::GraphicsAPI::ShaderStageBit& operator&=(Grindstone::GraphicsAPI::ShaderStageBit& a,
const Grindstone::GraphicsAPI::ShaderStageBit b) {
899inline Grindstone::GraphicsAPI::ShaderStageBit& operator^=(Grindstone::GraphicsAPI::ShaderStageBit& a,
const Grindstone::GraphicsAPI::ShaderStageBit b) {
904inline Grindstone::GraphicsAPI::ColorMask operator~(
const Grindstone::GraphicsAPI::ColorMask stages) {
905 using ColorMaskType = uint8_t;
906 return static_cast<Grindstone::GraphicsAPI::ColorMask
>(~static_cast<ColorMaskType>(stages));
909inline Grindstone::GraphicsAPI::ColorMask operator|(
const Grindstone::GraphicsAPI::ColorMask a,
const Grindstone::GraphicsAPI::ColorMask b) {
910 using ColorMaskType = uint8_t;
911 return static_cast<Grindstone::GraphicsAPI::ColorMask
>(
static_cast<ColorMaskType
>(a) |
static_cast<ColorMaskType
>(b));
914inline Grindstone::GraphicsAPI::ColorMask operator&(
const Grindstone::GraphicsAPI::ColorMask a,
const Grindstone::GraphicsAPI::ColorMask b) {
915 using ColorMaskType = uint8_t;
916 return static_cast<Grindstone::GraphicsAPI::ColorMask
>(
static_cast<ColorMaskType
>(a) &
static_cast<ColorMaskType
>(b));
919inline Grindstone::GraphicsAPI::ColorMask operator^(
const Grindstone::GraphicsAPI::ColorMask a,
const Grindstone::GraphicsAPI::ColorMask b) {
920 using ColorMaskType = uint8_t;
921 return static_cast<Grindstone::GraphicsAPI::ColorMask
>(
static_cast<ColorMaskType
>(a) ^
static_cast<ColorMaskType
>(b));
924inline Grindstone::GraphicsAPI::ColorMask& operator|=(Grindstone::GraphicsAPI::ColorMask& a,
const Grindstone::GraphicsAPI::ColorMask b) {
929inline Grindstone::GraphicsAPI::ColorMask& operator&=(Grindstone::GraphicsAPI::ColorMask& a,
const Grindstone::GraphicsAPI::ColorMask b) {
934inline Grindstone::GraphicsAPI::ColorMask& operator^=(Grindstone::GraphicsAPI::ColorMask& a,
const Grindstone::GraphicsAPI::ColorMask b) {
941 struct std::hash<Grindstone::GraphicsAPI::VertexBindingDescription> {
943 size_t result = std::hash<size_t>{}(
944 static_cast<size_t>(binding.bindingIndex) << 8 |
945 static_cast<size_t>(binding.stride) << 32
947 result ^= std::hash<size_t>{}(
static_cast<size_t>(binding.inputRate));
953 struct std::hash<Grindstone::GraphicsAPI::VertexAttributeDescription> {
955 size_t result = std::hash<size_t>{}(
956 static_cast<size_t>(attribute.attributeUsage) |
957 static_cast<size_t>(attribute.bindingIndex) << 32
960 result ^= std::hash<size_t>{}(
961 static_cast<size_t>(attribute.byteOffset) |
962 static_cast<size_t>(attribute.format) << 32
965 result ^= std::hash<size_t>{}(
966 static_cast<size_t>(attribute.locationIndex) << 32
974 struct std::hash<Grindstone::GraphicsAPI::VertexInputLayout> {
976 size_t result = std::hash<size_t>{}(vertexInputLayout.attributes.size()) ^ std::hash<size_t>{}(vertexInputLayout.bindings.size());
979 result ^= std::hash<Grindstone::GraphicsAPI::VertexBindingDescription>{}(binding);
983 result ^= std::hash<Grindstone::GraphicsAPI::VertexAttributeDescription>{}(attribute);
Definition Formats.hpp:568
Definition Formats.hpp:791
Definition Formats.hpp:801