xref: /aosp_15_r20/external/swiftshader/src/Device/Context.hpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
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 	// VK_KHR_dynamic_rendering_local_read allows color locations to be mapped to the render
119 	// pass attachments, but blend and other state is not affected by this map.  The image views
120 	// placed in colorBuffer are indexed by "location" (i.e the decoration in the shader), and
121 	// the following maps facilitate the association between the attachment-specific state and
122 	// the location-indexed color buffers.
123 	uint32_t indexToLocation[sw::MAX_COLOR_BUFFERS] = {};
124 	uint32_t locationToIndex[sw::MAX_COLOR_BUFFERS] = {};
125 
126 	VkFormat colorFormat(int location) const;
127 	VkFormat depthFormat() const;
128 	VkFormat depthStencilFormat() const;
129 };
130 
131 struct DynamicState;
132 struct Inputs
133 {
134 	void initialize(const VkPipelineVertexInputStateCreateInfo *vertexInputState, const VkPipelineDynamicStateCreateInfo *dynamicStateCreateInfo);
135 
136 	void updateDescriptorSets(const DescriptorSet::Array &dso,
137 	                          const DescriptorSet::Bindings &ds,
138 	                          const DescriptorSet::DynamicOffsets &ddo);
getDescriptorSetObjectsvk::Inputs139 	inline const DescriptorSet::Array &getDescriptorSetObjects() const { return descriptorSetObjects; }
getDescriptorSetsvk::Inputs140 	inline const DescriptorSet::Bindings &getDescriptorSets() const { return descriptorSets; }
getDescriptorDynamicOffsetsvk::Inputs141 	inline const DescriptorSet::DynamicOffsets &getDescriptorDynamicOffsets() const { return descriptorDynamicOffsets; }
getStreamvk::Inputs142 	inline const sw::Stream &getStream(uint32_t i) const { return stream[i]; }
143 
144 	void bindVertexInputs(int firstInstance);
145 	void setVertexInputBinding(const VertexInputBinding vertexInputBindings[], const DynamicState &dynamicState);
146 	void advanceInstanceAttributes();
147 	VkDeviceSize getVertexStride(uint32_t i) const;
148 	VkDeviceSize getInstanceStride(uint32_t i) const;
149 
150 private:
151 	InputsDynamicStateFlags dynamicStateFlags = {};
152 	VertexInputBinding vertexInputBindings[MAX_VERTEX_INPUT_BINDINGS] = {};
153 	DescriptorSet::Array descriptorSetObjects = {};
154 	DescriptorSet::Bindings descriptorSets = {};
155 	DescriptorSet::DynamicOffsets descriptorDynamicOffsets = {};
156 	sw::Stream stream[sw::MAX_INTERFACE_COMPONENTS / 4];
157 };
158 
159 struct MultisampleState
160 {
161 	bool sampleShadingEnable = false;
162 	bool alphaToCoverage = false;
163 
164 	int sampleCount = 0;
165 	unsigned int multiSampleMask = 0;
166 	float minSampleShading = 0.0f;
167 
168 	void set(const VkPipelineMultisampleStateCreateInfo *multisampleState);
169 };
170 
171 struct BlendState : sw::Memset<BlendState>
172 {
BlendStatevk::BlendState173 	BlendState()
174 	    : Memset(this, 0)
175 	{}
176 
BlendStatevk::BlendState177 	BlendState(bool alphaBlendEnable,
178 	           VkBlendFactor sourceBlendFactor,
179 	           VkBlendFactor destBlendFactor,
180 	           VkBlendOp blendOperation,
181 	           VkBlendFactor sourceBlendFactorAlpha,
182 	           VkBlendFactor destBlendFactorAlpha,
183 	           VkBlendOp blendOperationAlpha)
184 	    : Memset(this, 0)
185 	    , alphaBlendEnable(alphaBlendEnable)
186 	    , sourceBlendFactor(sourceBlendFactor)
187 	    , destBlendFactor(destBlendFactor)
188 	    , blendOperation(blendOperation)
189 	    , sourceBlendFactorAlpha(sourceBlendFactorAlpha)
190 	    , destBlendFactorAlpha(destBlendFactorAlpha)
191 	    , blendOperationAlpha(blendOperationAlpha)
192 	{}
193 
194 	bool alphaBlendEnable;
195 	VkBlendFactor sourceBlendFactor;
196 	VkBlendFactor destBlendFactor;
197 	VkBlendOp blendOperation;
198 	VkBlendFactor sourceBlendFactorAlpha;
199 	VkBlendFactor destBlendFactorAlpha;
200 	VkBlendOp blendOperationAlpha;
201 };
202 
203 struct DynamicVertexInputBindingState
204 {
205 	VkVertexInputRate inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
206 	VkDeviceSize stride = 0;
207 	unsigned int divisor = 0;
208 };
209 
210 struct DynamicVertexInputAttributeState
211 {
212 	VkFormat format = VK_FORMAT_UNDEFINED;
213 	unsigned int offset = 0;
214 	unsigned int binding = 0;
215 };
216 
217 struct DynamicState
218 {
219 	VkViewport viewport = {};
220 	VkRect2D scissor = {};
221 	sw::float4 blendConstants = {};
222 	float depthBiasConstantFactor = 0.0f;
223 	float depthBiasClamp = 0.0f;
224 	float depthBiasSlopeFactor = 0.0f;
225 	float minDepthBounds = 0.0f;
226 	float maxDepthBounds = 0.0f;
227 	float lineWidth = 0.0f;
228 
229 	VkCullModeFlags cullMode = VK_CULL_MODE_NONE;
230 	VkBool32 depthBoundsTestEnable = VK_FALSE;
231 	VkCompareOp depthCompareOp = VK_COMPARE_OP_NEVER;
232 	VkBool32 depthTestEnable = VK_FALSE;
233 	VkBool32 depthWriteEnable = VK_FALSE;
234 	VkFrontFace frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
235 	VkPrimitiveTopology primitiveTopology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
236 	uint32_t scissorCount = 0;
237 	VkRect2D scissors[vk::MAX_VIEWPORTS] = {};
238 	VkStencilFaceFlags faceMask = (VkStencilFaceFlags)0;
239 	VkStencilOpState frontStencil = {};
240 	VkStencilOpState backStencil = {};
241 	VkBool32 stencilTestEnable = VK_FALSE;
242 	uint32_t viewportCount = 0;
243 	VkViewport viewports[vk::MAX_VIEWPORTS] = {};
244 	VkBool32 rasterizerDiscardEnable = VK_FALSE;
245 	VkBool32 depthBiasEnable = VK_FALSE;
246 	VkBool32 primitiveRestartEnable = VK_FALSE;
247 	DynamicVertexInputBindingState vertexInputBindings[MAX_VERTEX_INPUT_BINDINGS];
248 	DynamicVertexInputAttributeState vertexInputAttributes[sw::MAX_INTERFACE_COMPONENTS / 4];
249 };
250 
251 struct VertexInputInterfaceState
252 {
253 	void initialize(const VkPipelineVertexInputStateCreateInfo *vertexInputState,
254 	                const VkPipelineInputAssemblyStateCreateInfo *inputAssemblyState,
255 	                const DynamicStateFlags &allDynamicStateFlags);
256 
257 	void applyState(const DynamicState &dynamicState);
258 
getTopologyvk::VertexInputInterfaceState259 	inline VkPrimitiveTopology getTopology() const { return topology; }
hasPrimitiveRestartEnablevk::VertexInputInterfaceState260 	inline bool hasPrimitiveRestartEnable() const { return primitiveRestartEnable; }
261 
hasDynamicTopologyvk::VertexInputInterfaceState262 	inline bool hasDynamicTopology() const { return dynamicStateFlags.dynamicPrimitiveTopology; }
hasDynamicPrimitiveRestartEnablevk::VertexInputInterfaceState263 	inline bool hasDynamicPrimitiveRestartEnable() const { return dynamicStateFlags.dynamicPrimitiveRestartEnable; }
264 
265 	bool isDrawPoint(bool polygonModeAware, VkPolygonMode polygonMode) const;
266 	bool isDrawLine(bool polygonModeAware, VkPolygonMode polygonMode) const;
267 	bool isDrawTriangle(bool polygonModeAware, VkPolygonMode polygonMode) const;
268 
269 private:
270 	VertexInputInterfaceDynamicStateFlags dynamicStateFlags = {};
271 
272 	bool primitiveRestartEnable = false;
273 
274 	VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
275 };
276 
277 struct PreRasterizationState
278 {
279 	void initialize(const vk::Device *device,
280 	                const PipelineLayout *layout,
281 	                const VkPipelineViewportStateCreateInfo *viewportState,
282 	                const VkPipelineRasterizationStateCreateInfo *rasterizationState,
283 	                const vk::RenderPass *renderPass, uint32_t subpassIndex,
284 	                const VkPipelineRenderingCreateInfo *rendering,
285 	                const DynamicStateFlags &allDynamicStateFlags);
286 
getPipelineLayoutvk::PreRasterizationState287 	inline const PipelineLayout *getPipelineLayout() const { return pipelineLayout; }
overridePipelineLayoutvk::PreRasterizationState288 	inline void overridePipelineLayout(const PipelineLayout *linkedLayout) { pipelineLayout = linkedLayout; }
289 
290 	void applyState(const DynamicState &dynamicState);
291 
getCullModevk::PreRasterizationState292 	inline VkCullModeFlags getCullMode() const { return cullMode; }
getFrontFacevk::PreRasterizationState293 	inline VkFrontFace getFrontFace() const { return frontFace; }
getPolygonModevk::PreRasterizationState294 	inline VkPolygonMode getPolygonMode() const { return polygonMode; }
getProvokingVertexModevk::PreRasterizationState295 	inline VkProvokingVertexModeEXT getProvokingVertexMode() const { return provokingVertexMode; }
getLineRasterizationModevk::PreRasterizationState296 	inline VkLineRasterizationModeEXT getLineRasterizationMode() const { return lineRasterizationMode; }
297 
hasRasterizerDiscardvk::PreRasterizationState298 	inline bool hasRasterizerDiscard() const { return rasterizerDiscard; }
299 
getConstantDepthBiasvk::PreRasterizationState300 	inline float getConstantDepthBias() const { return depthBiasEnable ? constantDepthBias : 0; }
getSlopeDepthBiasvk::PreRasterizationState301 	inline float getSlopeDepthBias() const { return depthBiasEnable ? slopeDepthBias : 0; }
getDepthBiasClampvk::PreRasterizationState302 	inline float getDepthBiasClamp() const { return depthBiasEnable ? depthBiasClamp : 0; }
303 
hasDepthRangeUnrestrictedvk::PreRasterizationState304 	inline bool hasDepthRangeUnrestricted() const { return depthRangeUnrestricted; }
getDepthClampEnablevk::PreRasterizationState305 	inline bool getDepthClampEnable() const { return depthClampEnable; }
getDepthClipEnablevk::PreRasterizationState306 	inline bool getDepthClipEnable() const { return depthClipEnable; }
getDepthClipNegativeOneToOnevk::PreRasterizationState307 	inline bool getDepthClipNegativeOneToOne() const { return depthClipNegativeOneToOne; }
308 
getLineWidthvk::PreRasterizationState309 	inline float getLineWidth() const { return lineWidth; }
310 
getScissorvk::PreRasterizationState311 	inline const VkRect2D &getScissor() const { return scissor; }
getViewportvk::PreRasterizationState312 	inline const VkViewport &getViewport() const { return viewport; }
313 
314 private:
315 	const PipelineLayout *pipelineLayout = nullptr;
316 
317 	PreRasterizationDynamicStateFlags dynamicStateFlags = {};
318 
319 	bool rasterizerDiscard = false;
320 	bool depthClampEnable = false;
321 	bool depthClipEnable = false;
322 	bool depthClipNegativeOneToOne = false;
323 	bool depthBiasEnable = false;
324 	bool depthRangeUnrestricted = false;
325 
326 	VkCullModeFlags cullMode = 0;
327 	VkFrontFace frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
328 	VkPolygonMode polygonMode = VK_POLYGON_MODE_FILL;
329 	VkProvokingVertexModeEXT provokingVertexMode = VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT;
330 	VkLineRasterizationModeEXT lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
331 
332 	float depthBiasClamp = 0.0f;
333 	float constantDepthBias = 0.0f;
334 	float slopeDepthBias = 0.0f;
335 
336 	float lineWidth = 0.0f;
337 
338 	VkRect2D scissor = {};
339 	VkViewport viewport = {};
340 };
341 
342 struct FragmentState
343 {
344 	void initialize(const PipelineLayout *layout,
345 	                const VkPipelineDepthStencilStateCreateInfo *depthStencilState,
346 	                const vk::RenderPass *renderPass, uint32_t subpassIndex,
347 	                const VkPipelineRenderingCreateInfo *rendering,
348 	                const DynamicStateFlags &allDynamicStateFlags);
349 
getPipelineLayoutvk::FragmentState350 	inline const PipelineLayout *getPipelineLayout() const { return pipelineLayout; }
overridePipelineLayoutvk::FragmentState351 	inline void overridePipelineLayout(const PipelineLayout *linkedLayout) { pipelineLayout = linkedLayout; }
352 
353 	void applyState(const DynamicState &dynamicState);
354 
getFrontStencilvk::FragmentState355 	inline VkStencilOpState getFrontStencil() const { return frontStencil; }
getBackStencilvk::FragmentState356 	inline VkStencilOpState getBackStencil() const { return backStencil; }
357 
getMinDepthBoundsvk::FragmentState358 	inline float getMinDepthBounds() const { return minDepthBounds; }
getMaxDepthBoundsvk::FragmentState359 	inline float getMaxDepthBounds() const { return maxDepthBounds; }
360 
getDepthCompareModevk::FragmentState361 	inline VkCompareOp getDepthCompareMode() const { return depthCompareMode; }
362 
363 	bool depthWriteActive(const Attachments &attachments) const;
364 	bool depthTestActive(const Attachments &attachments) const;
365 	bool stencilActive(const Attachments &attachments) const;
366 	bool depthBoundsTestActive(const Attachments &attachments) const;
367 
368 private:
369 	void setDepthStencilState(const VkPipelineDepthStencilStateCreateInfo *depthStencilState);
370 
371 	const PipelineLayout *pipelineLayout = nullptr;
372 
373 	FragmentDynamicStateFlags dynamicStateFlags = {};
374 
375 	bool depthTestEnable = false;
376 	bool depthWriteEnable = false;
377 	bool depthBoundsTestEnable = false;
378 	bool stencilEnable = false;
379 
380 	float minDepthBounds = 0.0f;
381 	float maxDepthBounds = 0.0f;
382 
383 	VkCompareOp depthCompareMode = VK_COMPARE_OP_NEVER;
384 
385 	VkStencilOpState frontStencil = {};
386 	VkStencilOpState backStencil = {};
387 
388 	// Note: if a pipeline library is created with the fragment state only, and sample shading
389 	// is enabled or a render pass is provided, VkPipelineMultisampleStateCreateInfo must be
390 	// provided.  This must identically match with the one provided for the fragment output
391 	// interface library.
392 	//
393 	// Currently, SwiftShader can always use the copy provided and stored in
394 	// FragmentOutputInterfaceState.  If a future optimization requires access to this state in
395 	// a pipeline library without fragment output interface, a copy of MultisampleState can be
396 	// placed here and initialized under the above condition.
397 	//
398 	// Ref: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap10.html#pipeline-graphics-subsets
399 };
400 
401 struct FragmentOutputInterfaceState
402 {
403 	void initialize(const VkPipelineColorBlendStateCreateInfo *colorBlendState,
404 	                const VkPipelineMultisampleStateCreateInfo *multisampleState,
405 	                const vk::RenderPass *renderPass, uint32_t subpassIndex,
406 	                const VkPipelineRenderingCreateInfo *rendering,
407 	                const DynamicStateFlags &allDynamicStateFlags);
408 
409 	void applyState(const DynamicState &dynamicState);
410 
getMultiSampleMaskvk::FragmentOutputInterfaceState411 	inline unsigned int getMultiSampleMask() const { return multisample.multiSampleMask; }
getSampleCountvk::FragmentOutputInterfaceState412 	inline int getSampleCount() const { return multisample.sampleCount; }
hasSampleShadingEnabledvk::FragmentOutputInterfaceState413 	inline bool hasSampleShadingEnabled() const { return multisample.sampleShadingEnable; }
getMinSampleShadingvk::FragmentOutputInterfaceState414 	inline float getMinSampleShading() const { return multisample.minSampleShading; }
hasAlphaToCoveragevk::FragmentOutputInterfaceState415 	inline bool hasAlphaToCoverage() const { return multisample.alphaToCoverage; }
416 
getBlendConstantsvk::FragmentOutputInterfaceState417 	inline const sw::float4 &getBlendConstants() const { return blendConstants; }
418 
419 	// The following take the attachment "location", which may not be the same as the index in
420 	// the attachment list with VK_KHR_dynamic_rendering_local_read.
421 	BlendState getBlendState(int location, const Attachments &attachments, bool fragmentContainsKill) const;
422 	int colorWriteActive(int location, const Attachments &attachments) const;
423 
424 private:
425 	void setColorBlendState(const VkPipelineColorBlendStateCreateInfo *colorBlendState);
426 
427 	VkBlendFactor blendFactor(VkBlendOp blendOperation, VkBlendFactor blendFactor) const;
428 	VkBlendOp blendOperation(VkBlendOp blendOperation, VkBlendFactor sourceBlendFactor, VkBlendFactor destBlendFactor, vk::Format format) const;
429 
430 	bool alphaBlendActive(int location, const Attachments &attachments, bool fragmentContainsKill) const;
431 	bool colorWriteActive(const Attachments &attachments) const;
432 
433 	int colorWriteMask[sw::MAX_COLOR_BUFFERS] = {};  // RGBA
434 
435 	FragmentOutputInterfaceDynamicStateFlags dynamicStateFlags = {};
436 
437 	sw::float4 blendConstants = {};
438 	BlendState blendState[sw::MAX_COLOR_BUFFERS] = {};
439 
440 	MultisampleState multisample;
441 };
442 
443 struct GraphicsState
444 {
445 	GraphicsState(const Device *device, const VkGraphicsPipelineCreateInfo *pCreateInfo, const PipelineLayout *layout);
446 
447 	GraphicsState combineStates(const DynamicState &dynamicState) const;
448 
hasVertexInputInterfaceStatevk::GraphicsState449 	bool hasVertexInputInterfaceState() const
450 	{
451 		return (validSubset & VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT) != 0;
452 	}
hasPreRasterizationStatevk::GraphicsState453 	bool hasPreRasterizationState() const
454 	{
455 		return (validSubset & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) != 0;
456 	}
hasFragmentStatevk::GraphicsState457 	bool hasFragmentState() const
458 	{
459 		return (validSubset & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) != 0;
460 	}
hasFragmentOutputInterfaceStatevk::GraphicsState461 	bool hasFragmentOutputInterfaceState() const
462 	{
463 		return (validSubset & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT) != 0;
464 	}
465 
getVertexInputInterfaceStatevk::GraphicsState466 	const VertexInputInterfaceState &getVertexInputInterfaceState() const
467 	{
468 		ASSERT(hasVertexInputInterfaceState());
469 		return vertexInputInterfaceState;
470 	}
getPreRasterizationStatevk::GraphicsState471 	const PreRasterizationState &getPreRasterizationState() const
472 	{
473 		ASSERT(hasPreRasterizationState());
474 		return preRasterizationState;
475 	}
getFragmentStatevk::GraphicsState476 	const FragmentState &getFragmentState() const
477 	{
478 		ASSERT(hasFragmentState());
479 		return fragmentState;
480 	}
getFragmentOutputInterfaceStatevk::GraphicsState481 	const FragmentOutputInterfaceState &getFragmentOutputInterfaceState() const
482 	{
483 		ASSERT(hasFragmentOutputInterfaceState());
484 		return fragmentOutputInterfaceState;
485 	}
486 
487 private:
488 	// The four subsets of a graphics pipeline as described in the spec.  With
489 	// VK_EXT_graphics_pipeline_library, a number of these may be valid.
490 	VertexInputInterfaceState vertexInputInterfaceState;
491 	PreRasterizationState preRasterizationState;
492 	FragmentState fragmentState;
493 	FragmentOutputInterfaceState fragmentOutputInterfaceState;
494 
495 	VkGraphicsPipelineLibraryFlagsEXT validSubset = 0;
496 };
497 
498 }  // namespace vk
499 
500 #endif  // vk_Context_hpp
501