• 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 VertexInputBinding
36 {
37 	Buffer *buffer = nullptr;
38 	VkDeviceSize offset = 0;
39 	VkDeviceSize size = 0;
40 	VkDeviceSize stride = 0;
41 };
42 
43 struct IndexBuffer
44 {
getIndexTypevk::IndexBuffer45 	inline VkIndexType getIndexType() const { return indexType; }
46 	void setIndexBufferBinding(const VertexInputBinding &indexBufferBinding, VkIndexType type);
47 	void getIndexBuffers(VkPrimitiveTopology topology, uint32_t count, uint32_t first, bool indexed, bool hasPrimitiveRestartEnable, std::vector<std::pair<uint32_t, void *>> *indexBuffers) const;
48 
49 private:
50 	uint32_t bytesPerIndex() const;
51 
52 	VertexInputBinding binding;
53 	VkIndexType indexType;
54 };
55 
56 struct Attachments
57 {
58 	ImageView *colorBuffer[sw::MAX_COLOR_BUFFERS] = {};
59 	ImageView *depthBuffer = nullptr;
60 	ImageView *stencilBuffer = nullptr;
61 
62 	VkFormat colorFormat(int index) const;
63 	VkFormat depthFormat() const;
64 };
65 
66 struct Inputs
67 {
68 	void initialize(const VkPipelineVertexInputStateCreateInfo *vertexInputState);
69 
70 	void updateDescriptorSets(const DescriptorSet::Array &dso,
71 	                          const DescriptorSet::Bindings &ds,
72 	                          const DescriptorSet::DynamicOffsets &ddo);
getDescriptorSetObjectsvk::Inputs73 	inline const DescriptorSet::Array &getDescriptorSetObjects() const { return descriptorSetObjects; }
getDescriptorSetsvk::Inputs74 	inline const DescriptorSet::Bindings &getDescriptorSets() const { return descriptorSets; }
getDescriptorDynamicOffsetsvk::Inputs75 	inline const DescriptorSet::DynamicOffsets &getDescriptorDynamicOffsets() const { return descriptorDynamicOffsets; }
getStreamvk::Inputs76 	inline const sw::Stream &getStream(uint32_t i) const { return stream[i]; }
77 
78 	void bindVertexInputs(int firstInstance, bool dynamicInstanceStride);
79 	void setVertexInputBinding(const VertexInputBinding vertexInputBindings[]);
80 	void advanceInstanceAttributes(bool dynamicInstanceStride);
81 	VkDeviceSize getVertexStride(uint32_t i, bool dynamicVertexStride) const;
82 	VkDeviceSize getInstanceStride(uint32_t i, bool dynamicVertexStride) const;
83 
84 private:
85 	VertexInputBinding vertexInputBindings[MAX_VERTEX_INPUT_BINDINGS] = {};
86 	DescriptorSet::Array descriptorSetObjects = {};
87 	DescriptorSet::Bindings descriptorSets = {};
88 	DescriptorSet::DynamicOffsets descriptorDynamicOffsets = {};
89 	sw::Stream stream[sw::MAX_INTERFACE_COMPONENTS / 4];
90 };
91 
92 struct MultisampleState
93 {
94 	bool sampleShadingEnable = false;
95 	bool alphaToCoverage = false;
96 
97 	int sampleCount = 0;
98 	unsigned int multiSampleMask = 0;
99 	float minSampleShading = 0.0f;
100 
101 	void set(const VkPipelineMultisampleStateCreateInfo *multisampleState);
102 };
103 
104 struct BlendState : sw::Memset<BlendState>
105 {
BlendStatevk::BlendState106 	BlendState()
107 	    : Memset(this, 0)
108 	{}
109 
BlendStatevk::BlendState110 	BlendState(bool alphaBlendEnable,
111 	           VkBlendFactor sourceBlendFactor,
112 	           VkBlendFactor destBlendFactor,
113 	           VkBlendOp blendOperation,
114 	           VkBlendFactor sourceBlendFactorAlpha,
115 	           VkBlendFactor destBlendFactorAlpha,
116 	           VkBlendOp blendOperationAlpha)
117 	    : Memset(this, 0)
118 	    , alphaBlendEnable(alphaBlendEnable)
119 	    , sourceBlendFactor(sourceBlendFactor)
120 	    , destBlendFactor(destBlendFactor)
121 	    , blendOperation(blendOperation)
122 	    , sourceBlendFactorAlpha(sourceBlendFactorAlpha)
123 	    , destBlendFactorAlpha(destBlendFactorAlpha)
124 	    , blendOperationAlpha(blendOperationAlpha)
125 	{}
126 
127 	bool alphaBlendEnable;
128 	VkBlendFactor sourceBlendFactor;
129 	VkBlendFactor destBlendFactor;
130 	VkBlendOp blendOperation;
131 	VkBlendFactor sourceBlendFactorAlpha;
132 	VkBlendFactor destBlendFactorAlpha;
133 	VkBlendOp blendOperationAlpha;
134 };
135 
136 struct DynamicState
137 {
138 	VkViewport viewport = {};
139 	VkRect2D scissor = {};
140 	sw::float4 blendConstants = {};
141 	float depthBiasConstantFactor = 0.0f;
142 	float depthBiasClamp = 0.0f;
143 	float depthBiasSlopeFactor = 0.0f;
144 	float minDepthBounds = 0.0f;
145 	float maxDepthBounds = 0.0f;
146 	float lineWidth = 0.0f;
147 
148 	VkCullModeFlags cullMode = VK_CULL_MODE_NONE;
149 	VkBool32 depthBoundsTestEnable = VK_FALSE;
150 	VkCompareOp depthCompareOp = VK_COMPARE_OP_NEVER;
151 	VkBool32 depthTestEnable = VK_FALSE;
152 	VkBool32 depthWriteEnable = VK_FALSE;
153 	VkFrontFace frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
154 	VkPrimitiveTopology primitiveTopology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
155 	uint32_t scissorCount = 0;
156 	VkRect2D scissors[vk::MAX_VIEWPORTS] = {};
157 	VkStencilFaceFlags faceMask = (VkStencilFaceFlags)0;
158 	VkStencilOpState frontStencil = {};
159 	VkStencilOpState backStencil = {};
160 	VkBool32 stencilTestEnable = VK_FALSE;
161 	uint32_t viewportCount = 0;
162 	VkRect2D viewports[vk::MAX_VIEWPORTS] = {};
163 	VkBool32 rasterizerDiscardEnable = VK_FALSE;
164 	VkBool32 depthBiasEnable = VK_FALSE;
165 	VkBool32 primitiveRestartEnable = VK_FALSE;
166 };
167 
168 struct VertexInputInterfaceDynamicStateFlags
169 {
170 	bool dynamicPrimitiveRestartEnable : 1;
171 	bool dynamicPrimitiveTopology : 1;
172 	bool dynamicVertexInputBindingStride : 1;
173 };
174 
175 struct PreRasterizationDynamicStateFlags
176 {
177 	bool dynamicLineWidth : 1;
178 	bool dynamicDepthBias : 1;
179 	bool dynamicDepthBiasEnable : 1;
180 	bool dynamicCullMode : 1;
181 	bool dynamicFrontFace : 1;
182 	bool dynamicViewport : 1;
183 	bool dynamicScissor : 1;
184 	bool dynamicViewportWithCount : 1;
185 	bool dynamicScissorWithCount : 1;
186 	bool dynamicRasterizerDiscardEnable : 1;
187 };
188 
189 struct FragmentDynamicStateFlags
190 {
191 	bool dynamicDepthTestEnable : 1;
192 	bool dynamicDepthWriteEnable : 1;
193 	bool dynamicDepthBoundsTestEnable : 1;
194 	bool dynamicDepthBounds : 1;
195 	bool dynamicDepthCompareOp : 1;
196 	bool dynamicStencilTestEnable : 1;
197 	bool dynamicStencilOp : 1;
198 	bool dynamicStencilCompareMask : 1;
199 	bool dynamicStencilWriteMask : 1;
200 	bool dynamicStencilReference : 1;
201 };
202 
203 struct FragmentOutputInterfaceDynamicStateFlags
204 {
205 	bool dynamicBlendConstants : 1;
206 };
207 
208 struct DynamicStateFlags
209 {
210 	VertexInputInterfaceDynamicStateFlags vertexInputInterface;
211 	PreRasterizationDynamicStateFlags preRasterization;
212 	FragmentDynamicStateFlags fragment;
213 	FragmentOutputInterfaceDynamicStateFlags fragmentOutputInterface;
214 };
215 
216 struct VertexInputInterfaceState
217 {
218 	void initialize(const VkPipelineVertexInputStateCreateInfo *vertexInputState,
219 	                const VkPipelineInputAssemblyStateCreateInfo *inputAssemblyState,
220 	                const DynamicStateFlags &allDynamicStateFlags);
221 
222 	void applyState(const DynamicState &dynamicState);
223 
getTopologyvk::VertexInputInterfaceState224 	inline VkPrimitiveTopology getTopology() const { return topology; }
hasPrimitiveRestartEnablevk::VertexInputInterfaceState225 	inline bool hasPrimitiveRestartEnable() const { return primitiveRestartEnable; }
226 
hasDynamicVertexStridevk::VertexInputInterfaceState227 	inline bool hasDynamicVertexStride() const { return dynamicStateFlags.dynamicVertexInputBindingStride; }
hasDynamicTopologyvk::VertexInputInterfaceState228 	inline bool hasDynamicTopology() const { return dynamicStateFlags.dynamicPrimitiveTopology; }
hasDynamicPrimitiveRestartEnablevk::VertexInputInterfaceState229 	inline bool hasDynamicPrimitiveRestartEnable() const { return dynamicStateFlags.dynamicPrimitiveRestartEnable; }
230 
231 	bool isDrawPoint(bool polygonModeAware, VkPolygonMode polygonMode) const;
232 	bool isDrawLine(bool polygonModeAware, VkPolygonMode polygonMode) const;
233 	bool isDrawTriangle(bool polygonModeAware, VkPolygonMode polygonMode) const;
234 
235 private:
236 	VertexInputInterfaceDynamicStateFlags dynamicStateFlags = {};
237 
238 	bool primitiveRestartEnable = false;
239 
240 	VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
241 };
242 
243 struct PreRasterizationState
244 {
245 	void initialize(const vk::Device *device,
246 	                const PipelineLayout *layout,
247 	                const VkPipelineViewportStateCreateInfo *viewportState,
248 	                const VkPipelineRasterizationStateCreateInfo *rasterizationState,
249 	                const vk::RenderPass *renderPass, uint32_t subpassIndex,
250 	                const VkPipelineRenderingCreateInfo *rendering,
251 	                const DynamicStateFlags &allDynamicStateFlags);
252 
getPipelineLayoutvk::PreRasterizationState253 	inline const PipelineLayout *getPipelineLayout() const { return pipelineLayout; }
overridePipelineLayoutvk::PreRasterizationState254 	inline void overridePipelineLayout(const PipelineLayout *linkedLayout) { pipelineLayout = linkedLayout; }
255 
256 	void applyState(const DynamicState &dynamicState);
257 
getCullModevk::PreRasterizationState258 	inline VkCullModeFlags getCullMode() const { return cullMode; }
getFrontFacevk::PreRasterizationState259 	inline VkFrontFace getFrontFace() const { return frontFace; }
getPolygonModevk::PreRasterizationState260 	inline VkPolygonMode getPolygonMode() const { return polygonMode; }
getProvokingVertexModevk::PreRasterizationState261 	inline VkProvokingVertexModeEXT getProvokingVertexMode() const { return provokingVertexMode; }
getLineRasterizationModevk::PreRasterizationState262 	inline VkLineRasterizationModeEXT getLineRasterizationMode() const { return lineRasterizationMode; }
263 
hasRasterizerDiscardvk::PreRasterizationState264 	inline bool hasRasterizerDiscard() const { return rasterizerDiscard; }
265 
getConstantDepthBiasvk::PreRasterizationState266 	inline float getConstantDepthBias() const { return depthBiasEnable ? constantDepthBias : 0; }
getSlopeDepthBiasvk::PreRasterizationState267 	inline float getSlopeDepthBias() const { return depthBiasEnable ? slopeDepthBias : 0; }
getDepthBiasClampvk::PreRasterizationState268 	inline float getDepthBiasClamp() const { return depthBiasEnable ? depthBiasClamp : 0; }
269 
hasDepthRangeUnrestrictedvk::PreRasterizationState270 	inline bool hasDepthRangeUnrestricted() const { return depthRangeUnrestricted; }
getDepthClampEnablevk::PreRasterizationState271 	inline bool getDepthClampEnable() const { return depthClampEnable; }
getDepthClipEnablevk::PreRasterizationState272 	inline bool getDepthClipEnable() const { return depthClipEnable; }
getDepthClipNegativeOneToOnevk::PreRasterizationState273 	inline bool getDepthClipNegativeOneToOne() const { return depthClipNegativeOneToOne; }
274 
getLineWidthvk::PreRasterizationState275 	inline float getLineWidth() const { return lineWidth; }
276 
getScissorvk::PreRasterizationState277 	inline const VkRect2D &getScissor() const { return scissor; }
getViewportvk::PreRasterizationState278 	inline const VkViewport &getViewport() const { return viewport; }
279 
280 private:
281 	const PipelineLayout *pipelineLayout = nullptr;
282 
283 	PreRasterizationDynamicStateFlags dynamicStateFlags = {};
284 
285 	bool rasterizerDiscard = false;
286 	bool depthClampEnable = false;
287 	bool depthClipEnable = false;
288 	bool depthClipNegativeOneToOne = false;
289 	bool depthBiasEnable = false;
290 	bool depthRangeUnrestricted = false;
291 
292 	VkCullModeFlags cullMode = 0;
293 	VkFrontFace frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
294 	VkPolygonMode polygonMode = VK_POLYGON_MODE_FILL;
295 	VkProvokingVertexModeEXT provokingVertexMode = VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT;
296 	VkLineRasterizationModeEXT lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
297 
298 	float depthBiasClamp = 0.0f;
299 	float constantDepthBias = 0.0f;
300 	float slopeDepthBias = 0.0f;
301 
302 	float lineWidth = 0.0f;
303 
304 	VkRect2D scissor = {};
305 	VkViewport viewport = {};
306 };
307 
308 struct FragmentState
309 {
310 	void initialize(const PipelineLayout *layout,
311 	                const VkPipelineDepthStencilStateCreateInfo *depthStencilState,
312 	                const vk::RenderPass *renderPass, uint32_t subpassIndex,
313 	                const VkPipelineRenderingCreateInfo *rendering,
314 	                const DynamicStateFlags &allDynamicStateFlags);
315 
getPipelineLayoutvk::FragmentState316 	inline const PipelineLayout *getPipelineLayout() const { return pipelineLayout; }
overridePipelineLayoutvk::FragmentState317 	inline void overridePipelineLayout(const PipelineLayout *linkedLayout) { pipelineLayout = linkedLayout; }
318 
319 	void applyState(const DynamicState &dynamicState);
320 
getFrontStencilvk::FragmentState321 	inline VkStencilOpState getFrontStencil() const { return frontStencil; }
getBackStencilvk::FragmentState322 	inline VkStencilOpState getBackStencil() const { return backStencil; }
323 
getMinDepthBoundsvk::FragmentState324 	inline float getMinDepthBounds() const { return minDepthBounds; }
getMaxDepthBoundsvk::FragmentState325 	inline float getMaxDepthBounds() const { return maxDepthBounds; }
326 
getDepthCompareModevk::FragmentState327 	inline VkCompareOp getDepthCompareMode() const { return depthCompareMode; }
328 
329 	bool depthWriteActive(const Attachments &attachments) const;
330 	bool depthTestActive(const Attachments &attachments) const;
331 	bool stencilActive(const Attachments &attachments) const;
332 	bool depthBoundsTestActive(const Attachments &attachments) const;
333 
334 private:
335 	void setDepthStencilState(const VkPipelineDepthStencilStateCreateInfo *depthStencilState);
336 
337 	const PipelineLayout *pipelineLayout = nullptr;
338 
339 	FragmentDynamicStateFlags dynamicStateFlags = {};
340 
341 	bool depthTestEnable = false;
342 	bool depthWriteEnable = false;
343 	bool depthBoundsTestEnable = false;
344 	bool stencilEnable = false;
345 
346 	float minDepthBounds = 0.0f;
347 	float maxDepthBounds = 0.0f;
348 
349 	VkCompareOp depthCompareMode = VK_COMPARE_OP_NEVER;
350 
351 	VkStencilOpState frontStencil = {};
352 	VkStencilOpState backStencil = {};
353 
354 	// Note: if a pipeline library is created with the fragment state only, and sample shading
355 	// is enabled or a render pass is provided, VkPipelineMultisampleStateCreateInfo must be
356 	// provided.  This must identically match with the one provided for the fragment output
357 	// interface library.
358 	//
359 	// Currently, SwiftShader can always use the copy provided and stored in
360 	// FragmentOutputInterfaceState.  If a future optimization requires access to this state in
361 	// a pipeline library without fragment output interface, a copy of MultisampleState can be
362 	// placed here and initialized under the above condition.
363 	//
364 	// Ref: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap10.html#pipeline-graphics-subsets
365 };
366 
367 struct FragmentOutputInterfaceState
368 {
369 	void initialize(const VkPipelineColorBlendStateCreateInfo *colorBlendState,
370 	                const VkPipelineMultisampleStateCreateInfo *multisampleState,
371 	                const vk::RenderPass *renderPass, uint32_t subpassIndex,
372 	                const VkPipelineRenderingCreateInfo *rendering,
373 	                const DynamicStateFlags &allDynamicStateFlags);
374 
375 	void applyState(const DynamicState &dynamicState);
376 
getMultiSampleMaskvk::FragmentOutputInterfaceState377 	inline unsigned int getMultiSampleMask() const { return multisample.multiSampleMask; }
getSampleCountvk::FragmentOutputInterfaceState378 	inline int getSampleCount() const { return multisample.sampleCount; }
hasSampleShadingEnabledvk::FragmentOutputInterfaceState379 	inline bool hasSampleShadingEnabled() const { return multisample.sampleShadingEnable; }
getMinSampleShadingvk::FragmentOutputInterfaceState380 	inline float getMinSampleShading() const { return multisample.minSampleShading; }
hasAlphaToCoveragevk::FragmentOutputInterfaceState381 	inline bool hasAlphaToCoverage() const { return multisample.alphaToCoverage; }
382 
getBlendConstantsvk::FragmentOutputInterfaceState383 	inline const sw::float4 &getBlendConstants() const { return blendConstants; }
384 
385 	BlendState getBlendState(int index, const Attachments &attachments, bool fragmentContainsKill) const;
386 
387 	int colorWriteActive(int index, const Attachments &attachments) const;
388 
389 private:
390 	void setColorBlendState(const VkPipelineColorBlendStateCreateInfo *colorBlendState);
391 
392 	VkBlendFactor blendFactor(VkBlendOp blendOperation, VkBlendFactor blendFactor) const;
393 	VkBlendOp blendOperation(VkBlendOp blendOperation, VkBlendFactor sourceBlendFactor, VkBlendFactor destBlendFactor, vk::Format format) const;
394 
395 	bool alphaBlendActive(int index, const Attachments &attachments, bool fragmentContainsKill) const;
396 	bool colorWriteActive(const Attachments &attachments) const;
397 
398 	int colorWriteMask[sw::MAX_COLOR_BUFFERS] = {};  // RGBA
399 
400 	FragmentOutputInterfaceDynamicStateFlags dynamicStateFlags = {};
401 
402 	sw::float4 blendConstants = {};
403 	BlendState blendState[sw::MAX_COLOR_BUFFERS] = {};
404 
405 	MultisampleState multisample;
406 };
407 
408 struct GraphicsState
409 {
410 	GraphicsState(const Device *device, const VkGraphicsPipelineCreateInfo *pCreateInfo, const PipelineLayout *layout);
411 
412 	GraphicsState combineStates(const DynamicState &dynamicState) const;
413 
hasVertexInputInterfaceStatevk::GraphicsState414 	bool hasVertexInputInterfaceState() const
415 	{
416 		return (validSubset & VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT) != 0;
417 	}
hasPreRasterizationStatevk::GraphicsState418 	bool hasPreRasterizationState() const
419 	{
420 		return (validSubset & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) != 0;
421 	}
hasFragmentStatevk::GraphicsState422 	bool hasFragmentState() const
423 	{
424 		return (validSubset & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) != 0;
425 	}
hasFragmentOutputInterfaceStatevk::GraphicsState426 	bool hasFragmentOutputInterfaceState() const
427 	{
428 		return (validSubset & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT) != 0;
429 	}
430 
getVertexInputInterfaceStatevk::GraphicsState431 	const VertexInputInterfaceState &getVertexInputInterfaceState() const
432 	{
433 		ASSERT(hasVertexInputInterfaceState());
434 		return vertexInputInterfaceState;
435 	}
getPreRasterizationStatevk::GraphicsState436 	const PreRasterizationState &getPreRasterizationState() const
437 	{
438 		ASSERT(hasPreRasterizationState());
439 		return preRasterizationState;
440 	}
getFragmentStatevk::GraphicsState441 	const FragmentState &getFragmentState() const
442 	{
443 		ASSERT(hasFragmentState());
444 		return fragmentState;
445 	}
getFragmentOutputInterfaceStatevk::GraphicsState446 	const FragmentOutputInterfaceState &getFragmentOutputInterfaceState() const
447 	{
448 		ASSERT(hasFragmentOutputInterfaceState());
449 		return fragmentOutputInterfaceState;
450 	}
451 
452 private:
453 	// The four subsets of a graphics pipeline as described in the spec.  With
454 	// VK_EXT_graphics_pipeline_library, a number of these may be valid.
455 	VertexInputInterfaceState vertexInputInterfaceState;
456 	PreRasterizationState preRasterizationState;
457 	FragmentState fragmentState;
458 	FragmentOutputInterfaceState fragmentOutputInterfaceState;
459 
460 	VkGraphicsPipelineLibraryFlagsEXT validSubset = 0;
461 };
462 
463 }  // namespace vk
464 
465 #endif  // vk_Context_hpp
466