• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef vk_Context_hpp
16 #define vk_Context_hpp
17 
18 #include "Config.hpp"
19 #include "Memset.hpp"
20 #include "Stream.hpp"
21 #include "System/Types.hpp"
22 #include "Vulkan/VkDescriptorSet.hpp"
23 #include "Vulkan/VkFormat.hpp"
24 
25 #include <vector>
26 
27 namespace vk {
28 
29 class Buffer;
30 class Device;
31 class ImageView;
32 class PipelineLayout;
33 class RenderPass;
34 
35 struct InputsDynamicStateFlags
36 {
37 	bool dynamicVertexInputBindingStride : 1;
38         bool dynamicVertexInput : 1;
39 };
40 
41 // Note: The split between Inputs and VertexInputInterfaceState is mostly superficial.  The state
42 // (be it dynamic or static) in Inputs should have been mostly a part of VertexInputInterfaceState.
43 // Changing that requires some surgery.
44 struct VertexInputInterfaceDynamicStateFlags
45 {
46 	bool dynamicPrimitiveRestartEnable : 1;
47 	bool dynamicPrimitiveTopology : 1;
48 };
49 
50 struct PreRasterizationDynamicStateFlags
51 {
52 	bool dynamicLineWidth : 1;
53 	bool dynamicDepthBias : 1;
54 	bool dynamicDepthBiasEnable : 1;
55 	bool dynamicCullMode : 1;
56 	bool dynamicFrontFace : 1;
57 	bool dynamicViewport : 1;
58 	bool dynamicScissor : 1;
59 	bool dynamicViewportWithCount : 1;
60 	bool dynamicScissorWithCount : 1;
61 	bool dynamicRasterizerDiscardEnable : 1;
62 };
63 
64 struct FragmentDynamicStateFlags
65 {
66 	bool dynamicDepthTestEnable : 1;
67 	bool dynamicDepthWriteEnable : 1;
68 	bool dynamicDepthBoundsTestEnable : 1;
69 	bool dynamicDepthBounds : 1;
70 	bool dynamicDepthCompareOp : 1;
71 	bool dynamicStencilTestEnable : 1;
72 	bool dynamicStencilOp : 1;
73 	bool dynamicStencilCompareMask : 1;
74 	bool dynamicStencilWriteMask : 1;
75 	bool dynamicStencilReference : 1;
76 };
77 
78 struct FragmentOutputInterfaceDynamicStateFlags
79 {
80 	bool dynamicBlendConstants : 1;
81 };
82 
83 struct DynamicStateFlags
84 {
85     // Note: InputsDynamicStateFlags is kept local to Inputs
86 	VertexInputInterfaceDynamicStateFlags vertexInputInterface;
87 	PreRasterizationDynamicStateFlags preRasterization;
88 	FragmentDynamicStateFlags fragment;
89 	FragmentOutputInterfaceDynamicStateFlags fragmentOutputInterface;
90 };
91 
92 struct VertexInputBinding
93 {
94 	Buffer *buffer = nullptr;
95 	VkDeviceSize offset = 0;
96 	VkDeviceSize size = 0;
97 };
98 
99 struct IndexBuffer
100 {
getIndexTypevk::IndexBuffer101 	inline VkIndexType getIndexType() const { return indexType; }
102 	void setIndexBufferBinding(const VertexInputBinding &indexBufferBinding, VkIndexType type);
103 	void getIndexBuffers(VkPrimitiveTopology topology, uint32_t count, uint32_t first, bool indexed, bool hasPrimitiveRestartEnable, std::vector<std::pair<uint32_t, void *>> *indexBuffers) const;
104 
105 private:
106 	uint32_t bytesPerIndex() const;
107 
108 	VertexInputBinding binding;
109 	VkIndexType indexType;
110 };
111 
112 struct Attachments
113 {
114 	ImageView *colorBuffer[sw::MAX_COLOR_BUFFERS] = {};
115 	ImageView *depthBuffer = nullptr;
116 	ImageView *stencilBuffer = nullptr;
117 
118 	VkFormat colorFormat(int index) const;
119 	VkFormat depthFormat() const;
120 };
121 
122 struct DynamicState;
123 struct Inputs
124 {
125 	void initialize(const VkPipelineVertexInputStateCreateInfo *vertexInputState, const VkPipelineDynamicStateCreateInfo *dynamicStateCreateInfo);
126 
127 	void updateDescriptorSets(const DescriptorSet::Array &dso,
128 	                          const DescriptorSet::Bindings &ds,
129 	                          const DescriptorSet::DynamicOffsets &ddo);
getDescriptorSetObjectsvk::Inputs130 	inline const DescriptorSet::Array &getDescriptorSetObjects() const { return descriptorSetObjects; }
getDescriptorSetsvk::Inputs131 	inline const DescriptorSet::Bindings &getDescriptorSets() const { return descriptorSets; }
getDescriptorDynamicOffsetsvk::Inputs132 	inline const DescriptorSet::DynamicOffsets &getDescriptorDynamicOffsets() const { return descriptorDynamicOffsets; }
getStreamvk::Inputs133 	inline const sw::Stream &getStream(uint32_t i) const { return stream[i]; }
134 
135 	void bindVertexInputs(int firstInstance);
136 	void setVertexInputBinding(const VertexInputBinding vertexInputBindings[], const DynamicState &dynamicState);
137 	void advanceInstanceAttributes();
138 	VkDeviceSize getVertexStride(uint32_t i) const;
139 	VkDeviceSize getInstanceStride(uint32_t i) const;
140 
141 private:
142 	InputsDynamicStateFlags dynamicStateFlags = {};
143 	VertexInputBinding vertexInputBindings[MAX_VERTEX_INPUT_BINDINGS] = {};
144 	DescriptorSet::Array descriptorSetObjects = {};
145 	DescriptorSet::Bindings descriptorSets = {};
146 	DescriptorSet::DynamicOffsets descriptorDynamicOffsets = {};
147 	sw::Stream stream[sw::MAX_INTERFACE_COMPONENTS / 4];
148 };
149 
150 struct MultisampleState
151 {
152 	bool sampleShadingEnable = false;
153 	bool alphaToCoverage = false;
154 
155 	int sampleCount = 0;
156 	unsigned int multiSampleMask = 0;
157 	float minSampleShading = 0.0f;
158 
159 	void set(const VkPipelineMultisampleStateCreateInfo *multisampleState);
160 };
161 
162 struct BlendState : sw::Memset<BlendState>
163 {
BlendStatevk::BlendState164 	BlendState()
165 	    : Memset(this, 0)
166 	{}
167 
BlendStatevk::BlendState168 	BlendState(bool alphaBlendEnable,
169 	           VkBlendFactor sourceBlendFactor,
170 	           VkBlendFactor destBlendFactor,
171 	           VkBlendOp blendOperation,
172 	           VkBlendFactor sourceBlendFactorAlpha,
173 	           VkBlendFactor destBlendFactorAlpha,
174 	           VkBlendOp blendOperationAlpha)
175 	    : Memset(this, 0)
176 	    , alphaBlendEnable(alphaBlendEnable)
177 	    , sourceBlendFactor(sourceBlendFactor)
178 	    , destBlendFactor(destBlendFactor)
179 	    , blendOperation(blendOperation)
180 	    , sourceBlendFactorAlpha(sourceBlendFactorAlpha)
181 	    , destBlendFactorAlpha(destBlendFactorAlpha)
182 	    , blendOperationAlpha(blendOperationAlpha)
183 	{}
184 
185 	bool alphaBlendEnable;
186 	VkBlendFactor sourceBlendFactor;
187 	VkBlendFactor destBlendFactor;
188 	VkBlendOp blendOperation;
189 	VkBlendFactor sourceBlendFactorAlpha;
190 	VkBlendFactor destBlendFactorAlpha;
191 	VkBlendOp blendOperationAlpha;
192 };
193 
194 struct DynamicVertexInputBindingState
195 {
196 	VkVertexInputRate inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
197 	VkDeviceSize stride = 0;
198 	unsigned int divisor = 0;
199 };
200 
201 struct DynamicVertexInputAttributeState
202 {
203 	VkFormat format = VK_FORMAT_UNDEFINED;
204 	unsigned int offset = 0;
205 	unsigned int binding = 0;
206 };
207 
208 struct DynamicState
209 {
210 	VkViewport viewport = {};
211 	VkRect2D scissor = {};
212 	sw::float4 blendConstants = {};
213 	float depthBiasConstantFactor = 0.0f;
214 	float depthBiasClamp = 0.0f;
215 	float depthBiasSlopeFactor = 0.0f;
216 	float minDepthBounds = 0.0f;
217 	float maxDepthBounds = 0.0f;
218 	float lineWidth = 0.0f;
219 
220 	VkCullModeFlags cullMode = VK_CULL_MODE_NONE;
221 	VkBool32 depthBoundsTestEnable = VK_FALSE;
222 	VkCompareOp depthCompareOp = VK_COMPARE_OP_NEVER;
223 	VkBool32 depthTestEnable = VK_FALSE;
224 	VkBool32 depthWriteEnable = VK_FALSE;
225 	VkFrontFace frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
226 	VkPrimitiveTopology primitiveTopology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
227 	uint32_t scissorCount = 0;
228 	VkRect2D scissors[vk::MAX_VIEWPORTS] = {};
229 	VkStencilFaceFlags faceMask = (VkStencilFaceFlags)0;
230 	VkStencilOpState frontStencil = {};
231 	VkStencilOpState backStencil = {};
232 	VkBool32 stencilTestEnable = VK_FALSE;
233 	uint32_t viewportCount = 0;
234 	VkRect2D viewports[vk::MAX_VIEWPORTS] = {};
235 	VkBool32 rasterizerDiscardEnable = VK_FALSE;
236 	VkBool32 depthBiasEnable = VK_FALSE;
237 	VkBool32 primitiveRestartEnable = VK_FALSE;
238 	DynamicVertexInputBindingState vertexInputBindings[MAX_VERTEX_INPUT_BINDINGS];
239 	DynamicVertexInputAttributeState vertexInputAttributes[sw::MAX_INTERFACE_COMPONENTS / 4];
240 };
241 
242 struct VertexInputInterfaceState
243 {
244 	void initialize(const VkPipelineVertexInputStateCreateInfo *vertexInputState,
245 	                const VkPipelineInputAssemblyStateCreateInfo *inputAssemblyState,
246 	                const DynamicStateFlags &allDynamicStateFlags);
247 
248 	void applyState(const DynamicState &dynamicState);
249 
getTopologyvk::VertexInputInterfaceState250 	inline VkPrimitiveTopology getTopology() const { return topology; }
hasPrimitiveRestartEnablevk::VertexInputInterfaceState251 	inline bool hasPrimitiveRestartEnable() const { return primitiveRestartEnable; }
252 
hasDynamicTopologyvk::VertexInputInterfaceState253 	inline bool hasDynamicTopology() const { return dynamicStateFlags.dynamicPrimitiveTopology; }
hasDynamicPrimitiveRestartEnablevk::VertexInputInterfaceState254 	inline bool hasDynamicPrimitiveRestartEnable() const { return dynamicStateFlags.dynamicPrimitiveRestartEnable; }
255 
256 	bool isDrawPoint(bool polygonModeAware, VkPolygonMode polygonMode) const;
257 	bool isDrawLine(bool polygonModeAware, VkPolygonMode polygonMode) const;
258 	bool isDrawTriangle(bool polygonModeAware, VkPolygonMode polygonMode) const;
259 
260 private:
261 	VertexInputInterfaceDynamicStateFlags dynamicStateFlags = {};
262 
263 	bool primitiveRestartEnable = false;
264 
265 	VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
266 };
267 
268 struct PreRasterizationState
269 {
270 	void initialize(const vk::Device *device,
271 	                const PipelineLayout *layout,
272 	                const VkPipelineViewportStateCreateInfo *viewportState,
273 	                const VkPipelineRasterizationStateCreateInfo *rasterizationState,
274 	                const vk::RenderPass *renderPass, uint32_t subpassIndex,
275 	                const VkPipelineRenderingCreateInfo *rendering,
276 	                const DynamicStateFlags &allDynamicStateFlags);
277 
getPipelineLayoutvk::PreRasterizationState278 	inline const PipelineLayout *getPipelineLayout() const { return pipelineLayout; }
overridePipelineLayoutvk::PreRasterizationState279 	inline void overridePipelineLayout(const PipelineLayout *linkedLayout) { pipelineLayout = linkedLayout; }
280 
281 	void applyState(const DynamicState &dynamicState);
282 
getCullModevk::PreRasterizationState283 	inline VkCullModeFlags getCullMode() const { return cullMode; }
getFrontFacevk::PreRasterizationState284 	inline VkFrontFace getFrontFace() const { return frontFace; }
getPolygonModevk::PreRasterizationState285 	inline VkPolygonMode getPolygonMode() const { return polygonMode; }
getProvokingVertexModevk::PreRasterizationState286 	inline VkProvokingVertexModeEXT getProvokingVertexMode() const { return provokingVertexMode; }
getLineRasterizationModevk::PreRasterizationState287 	inline VkLineRasterizationModeEXT getLineRasterizationMode() const { return lineRasterizationMode; }
288 
hasRasterizerDiscardvk::PreRasterizationState289 	inline bool hasRasterizerDiscard() const { return rasterizerDiscard; }
290 
getConstantDepthBiasvk::PreRasterizationState291 	inline float getConstantDepthBias() const { return depthBiasEnable ? constantDepthBias : 0; }
getSlopeDepthBiasvk::PreRasterizationState292 	inline float getSlopeDepthBias() const { return depthBiasEnable ? slopeDepthBias : 0; }
getDepthBiasClampvk::PreRasterizationState293 	inline float getDepthBiasClamp() const { return depthBiasEnable ? depthBiasClamp : 0; }
294 
hasDepthRangeUnrestrictedvk::PreRasterizationState295 	inline bool hasDepthRangeUnrestricted() const { return depthRangeUnrestricted; }
getDepthClampEnablevk::PreRasterizationState296 	inline bool getDepthClampEnable() const { return depthClampEnable; }
getDepthClipEnablevk::PreRasterizationState297 	inline bool getDepthClipEnable() const { return depthClipEnable; }
getDepthClipNegativeOneToOnevk::PreRasterizationState298 	inline bool getDepthClipNegativeOneToOne() const { return depthClipNegativeOneToOne; }
299 
getLineWidthvk::PreRasterizationState300 	inline float getLineWidth() const { return lineWidth; }
301 
getScissorvk::PreRasterizationState302 	inline const VkRect2D &getScissor() const { return scissor; }
getViewportvk::PreRasterizationState303 	inline const VkViewport &getViewport() const { return viewport; }
304 
305 private:
306 	const PipelineLayout *pipelineLayout = nullptr;
307 
308 	PreRasterizationDynamicStateFlags dynamicStateFlags = {};
309 
310 	bool rasterizerDiscard = false;
311 	bool depthClampEnable = false;
312 	bool depthClipEnable = false;
313 	bool depthClipNegativeOneToOne = false;
314 	bool depthBiasEnable = false;
315 	bool depthRangeUnrestricted = false;
316 
317 	VkCullModeFlags cullMode = 0;
318 	VkFrontFace frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
319 	VkPolygonMode polygonMode = VK_POLYGON_MODE_FILL;
320 	VkProvokingVertexModeEXT provokingVertexMode = VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT;
321 	VkLineRasterizationModeEXT lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
322 
323 	float depthBiasClamp = 0.0f;
324 	float constantDepthBias = 0.0f;
325 	float slopeDepthBias = 0.0f;
326 
327 	float lineWidth = 0.0f;
328 
329 	VkRect2D scissor = {};
330 	VkViewport viewport = {};
331 };
332 
333 struct FragmentState
334 {
335 	void initialize(const PipelineLayout *layout,
336 	                const VkPipelineDepthStencilStateCreateInfo *depthStencilState,
337 	                const vk::RenderPass *renderPass, uint32_t subpassIndex,
338 	                const VkPipelineRenderingCreateInfo *rendering,
339 	                const DynamicStateFlags &allDynamicStateFlags);
340 
getPipelineLayoutvk::FragmentState341 	inline const PipelineLayout *getPipelineLayout() const { return pipelineLayout; }
overridePipelineLayoutvk::FragmentState342 	inline void overridePipelineLayout(const PipelineLayout *linkedLayout) { pipelineLayout = linkedLayout; }
343 
344 	void applyState(const DynamicState &dynamicState);
345 
getFrontStencilvk::FragmentState346 	inline VkStencilOpState getFrontStencil() const { return frontStencil; }
getBackStencilvk::FragmentState347 	inline VkStencilOpState getBackStencil() const { return backStencil; }
348 
getMinDepthBoundsvk::FragmentState349 	inline float getMinDepthBounds() const { return minDepthBounds; }
getMaxDepthBoundsvk::FragmentState350 	inline float getMaxDepthBounds() const { return maxDepthBounds; }
351 
getDepthCompareModevk::FragmentState352 	inline VkCompareOp getDepthCompareMode() const { return depthCompareMode; }
353 
354 	bool depthWriteActive(const Attachments &attachments) const;
355 	bool depthTestActive(const Attachments &attachments) const;
356 	bool stencilActive(const Attachments &attachments) const;
357 	bool depthBoundsTestActive(const Attachments &attachments) const;
358 
359 private:
360 	void setDepthStencilState(const VkPipelineDepthStencilStateCreateInfo *depthStencilState);
361 
362 	const PipelineLayout *pipelineLayout = nullptr;
363 
364 	FragmentDynamicStateFlags dynamicStateFlags = {};
365 
366 	bool depthTestEnable = false;
367 	bool depthWriteEnable = false;
368 	bool depthBoundsTestEnable = false;
369 	bool stencilEnable = false;
370 
371 	float minDepthBounds = 0.0f;
372 	float maxDepthBounds = 0.0f;
373 
374 	VkCompareOp depthCompareMode = VK_COMPARE_OP_NEVER;
375 
376 	VkStencilOpState frontStencil = {};
377 	VkStencilOpState backStencil = {};
378 
379 	// Note: if a pipeline library is created with the fragment state only, and sample shading
380 	// is enabled or a render pass is provided, VkPipelineMultisampleStateCreateInfo must be
381 	// provided.  This must identically match with the one provided for the fragment output
382 	// interface library.
383 	//
384 	// Currently, SwiftShader can always use the copy provided and stored in
385 	// FragmentOutputInterfaceState.  If a future optimization requires access to this state in
386 	// a pipeline library without fragment output interface, a copy of MultisampleState can be
387 	// placed here and initialized under the above condition.
388 	//
389 	// Ref: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap10.html#pipeline-graphics-subsets
390 };
391 
392 struct FragmentOutputInterfaceState
393 {
394 	void initialize(const VkPipelineColorBlendStateCreateInfo *colorBlendState,
395 	                const VkPipelineMultisampleStateCreateInfo *multisampleState,
396 	                const vk::RenderPass *renderPass, uint32_t subpassIndex,
397 	                const VkPipelineRenderingCreateInfo *rendering,
398 	                const DynamicStateFlags &allDynamicStateFlags);
399 
400 	void applyState(const DynamicState &dynamicState);
401 
getMultiSampleMaskvk::FragmentOutputInterfaceState402 	inline unsigned int getMultiSampleMask() const { return multisample.multiSampleMask; }
getSampleCountvk::FragmentOutputInterfaceState403 	inline int getSampleCount() const { return multisample.sampleCount; }
hasSampleShadingEnabledvk::FragmentOutputInterfaceState404 	inline bool hasSampleShadingEnabled() const { return multisample.sampleShadingEnable; }
getMinSampleShadingvk::FragmentOutputInterfaceState405 	inline float getMinSampleShading() const { return multisample.minSampleShading; }
hasAlphaToCoveragevk::FragmentOutputInterfaceState406 	inline bool hasAlphaToCoverage() const { return multisample.alphaToCoverage; }
407 
getBlendConstantsvk::FragmentOutputInterfaceState408 	inline const sw::float4 &getBlendConstants() const { return blendConstants; }
409 
410 	BlendState getBlendState(int index, const Attachments &attachments, bool fragmentContainsKill) const;
411 
412 	int colorWriteActive(int index, const Attachments &attachments) const;
413 
414 private:
415 	void setColorBlendState(const VkPipelineColorBlendStateCreateInfo *colorBlendState);
416 
417 	VkBlendFactor blendFactor(VkBlendOp blendOperation, VkBlendFactor blendFactor) const;
418 	VkBlendOp blendOperation(VkBlendOp blendOperation, VkBlendFactor sourceBlendFactor, VkBlendFactor destBlendFactor, vk::Format format) const;
419 
420 	bool alphaBlendActive(int index, const Attachments &attachments, bool fragmentContainsKill) const;
421 	bool colorWriteActive(const Attachments &attachments) const;
422 
423 	int colorWriteMask[sw::MAX_COLOR_BUFFERS] = {};  // RGBA
424 
425 	FragmentOutputInterfaceDynamicStateFlags dynamicStateFlags = {};
426 
427 	sw::float4 blendConstants = {};
428 	BlendState blendState[sw::MAX_COLOR_BUFFERS] = {};
429 
430 	MultisampleState multisample;
431 };
432 
433 struct GraphicsState
434 {
435 	GraphicsState(const Device *device, const VkGraphicsPipelineCreateInfo *pCreateInfo, const PipelineLayout *layout);
436 
437 	GraphicsState combineStates(const DynamicState &dynamicState) const;
438 
hasVertexInputInterfaceStatevk::GraphicsState439 	bool hasVertexInputInterfaceState() const
440 	{
441 		return (validSubset & VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT) != 0;
442 	}
hasPreRasterizationStatevk::GraphicsState443 	bool hasPreRasterizationState() const
444 	{
445 		return (validSubset & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) != 0;
446 	}
hasFragmentStatevk::GraphicsState447 	bool hasFragmentState() const
448 	{
449 		return (validSubset & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) != 0;
450 	}
hasFragmentOutputInterfaceStatevk::GraphicsState451 	bool hasFragmentOutputInterfaceState() const
452 	{
453 		return (validSubset & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT) != 0;
454 	}
455 
getVertexInputInterfaceStatevk::GraphicsState456 	const VertexInputInterfaceState &getVertexInputInterfaceState() const
457 	{
458 		ASSERT(hasVertexInputInterfaceState());
459 		return vertexInputInterfaceState;
460 	}
getPreRasterizationStatevk::GraphicsState461 	const PreRasterizationState &getPreRasterizationState() const
462 	{
463 		ASSERT(hasPreRasterizationState());
464 		return preRasterizationState;
465 	}
getFragmentStatevk::GraphicsState466 	const FragmentState &getFragmentState() const
467 	{
468 		ASSERT(hasFragmentState());
469 		return fragmentState;
470 	}
getFragmentOutputInterfaceStatevk::GraphicsState471 	const FragmentOutputInterfaceState &getFragmentOutputInterfaceState() const
472 	{
473 		ASSERT(hasFragmentOutputInterfaceState());
474 		return fragmentOutputInterfaceState;
475 	}
476 
477 private:
478 	// The four subsets of a graphics pipeline as described in the spec.  With
479 	// VK_EXT_graphics_pipeline_library, a number of these may be valid.
480 	VertexInputInterfaceState vertexInputInterfaceState;
481 	PreRasterizationState preRasterizationState;
482 	FragmentState fragmentState;
483 	FragmentOutputInterfaceState fragmentOutputInterfaceState;
484 
485 	VkGraphicsPipelineLibraryFlagsEXT validSubset = 0;
486 };
487 
488 }  // namespace vk
489 
490 #endif  // vk_Context_hpp
491