xref: /aosp_15_r20/external/swiftshader/src/Vulkan/VkPipeline.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker // Copyright 2018 The SwiftShader Authors. All Rights Reserved.
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*03ce13f7SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*03ce13f7SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*03ce13f7SAndroid Build Coastguard Worker //
7*03ce13f7SAndroid Build Coastguard Worker //    http://www.apache.org/licenses/LICENSE-2.0
8*03ce13f7SAndroid Build Coastguard Worker //
9*03ce13f7SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*03ce13f7SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*03ce13f7SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*03ce13f7SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*03ce13f7SAndroid Build Coastguard Worker // limitations under the License.
14*03ce13f7SAndroid Build Coastguard Worker 
15*03ce13f7SAndroid Build Coastguard Worker #include "VkPipeline.hpp"
16*03ce13f7SAndroid Build Coastguard Worker 
17*03ce13f7SAndroid Build Coastguard Worker #include "VkDestroy.hpp"
18*03ce13f7SAndroid Build Coastguard Worker #include "VkDevice.hpp"
19*03ce13f7SAndroid Build Coastguard Worker #include "VkPipelineCache.hpp"
20*03ce13f7SAndroid Build Coastguard Worker #include "VkPipelineLayout.hpp"
21*03ce13f7SAndroid Build Coastguard Worker #include "VkRenderPass.hpp"
22*03ce13f7SAndroid Build Coastguard Worker #include "VkShaderModule.hpp"
23*03ce13f7SAndroid Build Coastguard Worker #include "VkStringify.hpp"
24*03ce13f7SAndroid Build Coastguard Worker #include "Pipeline/ComputeProgram.hpp"
25*03ce13f7SAndroid Build Coastguard Worker #include "Pipeline/SpirvShader.hpp"
26*03ce13f7SAndroid Build Coastguard Worker 
27*03ce13f7SAndroid Build Coastguard Worker #include "marl/trace.h"
28*03ce13f7SAndroid Build Coastguard Worker 
29*03ce13f7SAndroid Build Coastguard Worker #include "spirv-tools/optimizer.hpp"
30*03ce13f7SAndroid Build Coastguard Worker 
31*03ce13f7SAndroid Build Coastguard Worker #include <iostream>
32*03ce13f7SAndroid Build Coastguard Worker 
33*03ce13f7SAndroid Build Coastguard Worker namespace {
34*03ce13f7SAndroid Build Coastguard Worker 
35*03ce13f7SAndroid Build Coastguard Worker // optimizeSpirv() applies and freezes specializations into constants, and runs spirv-opt.
optimizeSpirv(const vk::PipelineCache::SpirvBinaryKey & key)36*03ce13f7SAndroid Build Coastguard Worker sw::SpirvBinary optimizeSpirv(const vk::PipelineCache::SpirvBinaryKey &key)
37*03ce13f7SAndroid Build Coastguard Worker {
38*03ce13f7SAndroid Build Coastguard Worker 	const sw::SpirvBinary &code = key.getBinary();
39*03ce13f7SAndroid Build Coastguard Worker 	const VkSpecializationInfo *specializationInfo = key.getSpecializationInfo();
40*03ce13f7SAndroid Build Coastguard Worker 	bool optimize = key.getOptimization();
41*03ce13f7SAndroid Build Coastguard Worker 
42*03ce13f7SAndroid Build Coastguard Worker 	spvtools::Optimizer opt{ vk::SPIRV_VERSION };
43*03ce13f7SAndroid Build Coastguard Worker 
44*03ce13f7SAndroid Build Coastguard Worker 	opt.SetMessageConsumer([](spv_message_level_t level, const char *source, const spv_position_t &position, const char *message) {
45*03ce13f7SAndroid Build Coastguard Worker 		switch(level)
46*03ce13f7SAndroid Build Coastguard Worker 		{
47*03ce13f7SAndroid Build Coastguard Worker 		case SPV_MSG_FATAL: sw::warn("SPIR-V FATAL: %d:%d %s\n", int(position.line), int(position.column), message);
48*03ce13f7SAndroid Build Coastguard Worker 		case SPV_MSG_INTERNAL_ERROR: sw::warn("SPIR-V INTERNAL_ERROR: %d:%d %s\n", int(position.line), int(position.column), message);
49*03ce13f7SAndroid Build Coastguard Worker 		case SPV_MSG_ERROR: sw::warn("SPIR-V ERROR: %d:%d %s\n", int(position.line), int(position.column), message);
50*03ce13f7SAndroid Build Coastguard Worker 		case SPV_MSG_WARNING: sw::warn("SPIR-V WARNING: %d:%d %s\n", int(position.line), int(position.column), message);
51*03ce13f7SAndroid Build Coastguard Worker 		case SPV_MSG_INFO: sw::trace("SPIR-V INFO: %d:%d %s\n", int(position.line), int(position.column), message);
52*03ce13f7SAndroid Build Coastguard Worker 		case SPV_MSG_DEBUG: sw::trace("SPIR-V DEBUG: %d:%d %s\n", int(position.line), int(position.column), message);
53*03ce13f7SAndroid Build Coastguard Worker 		default: sw::trace("SPIR-V MESSAGE: %d:%d %s\n", int(position.line), int(position.column), message);
54*03ce13f7SAndroid Build Coastguard Worker 		}
55*03ce13f7SAndroid Build Coastguard Worker 	});
56*03ce13f7SAndroid Build Coastguard Worker 
57*03ce13f7SAndroid Build Coastguard Worker 	// If the pipeline uses specialization, apply the specializations before freezing
58*03ce13f7SAndroid Build Coastguard Worker 	if(specializationInfo)
59*03ce13f7SAndroid Build Coastguard Worker 	{
60*03ce13f7SAndroid Build Coastguard Worker 		std::unordered_map<uint32_t, std::vector<uint32_t>> specializations;
61*03ce13f7SAndroid Build Coastguard Worker 		const uint8_t *specializationData = static_cast<const uint8_t *>(specializationInfo->pData);
62*03ce13f7SAndroid Build Coastguard Worker 
63*03ce13f7SAndroid Build Coastguard Worker 		for(uint32_t i = 0; i < specializationInfo->mapEntryCount; i++)
64*03ce13f7SAndroid Build Coastguard Worker 		{
65*03ce13f7SAndroid Build Coastguard Worker 			const VkSpecializationMapEntry &entry = specializationInfo->pMapEntries[i];
66*03ce13f7SAndroid Build Coastguard Worker 			const uint8_t *value_ptr = specializationData + entry.offset;
67*03ce13f7SAndroid Build Coastguard Worker 			std::vector<uint32_t> value(reinterpret_cast<const uint32_t *>(value_ptr),
68*03ce13f7SAndroid Build Coastguard Worker 			                            reinterpret_cast<const uint32_t *>(value_ptr + entry.size));
69*03ce13f7SAndroid Build Coastguard Worker 			specializations.emplace(entry.constantID, std::move(value));
70*03ce13f7SAndroid Build Coastguard Worker 		}
71*03ce13f7SAndroid Build Coastguard Worker 
72*03ce13f7SAndroid Build Coastguard Worker 		opt.RegisterPass(spvtools::CreateSetSpecConstantDefaultValuePass(specializations));
73*03ce13f7SAndroid Build Coastguard Worker 	}
74*03ce13f7SAndroid Build Coastguard Worker 
75*03ce13f7SAndroid Build Coastguard Worker 	if(optimize)
76*03ce13f7SAndroid Build Coastguard Worker 	{
77*03ce13f7SAndroid Build Coastguard Worker 		// Remove DontInline flags so the optimizer force-inlines all functions,
78*03ce13f7SAndroid Build Coastguard Worker 		// as we currently don't support OpFunctionCall (b/141246700).
79*03ce13f7SAndroid Build Coastguard Worker 		opt.RegisterPass(spvtools::CreateRemoveDontInlinePass());
80*03ce13f7SAndroid Build Coastguard Worker 
81*03ce13f7SAndroid Build Coastguard Worker 		// Full optimization list taken from spirv-opt.
82*03ce13f7SAndroid Build Coastguard Worker 		opt.RegisterPerformancePasses();
83*03ce13f7SAndroid Build Coastguard Worker 	}
84*03ce13f7SAndroid Build Coastguard Worker 
85*03ce13f7SAndroid Build Coastguard Worker 	spvtools::OptimizerOptions optimizerOptions = {};
86*03ce13f7SAndroid Build Coastguard Worker #if defined(NDEBUG)
87*03ce13f7SAndroid Build Coastguard Worker 	optimizerOptions.set_run_validator(false);
88*03ce13f7SAndroid Build Coastguard Worker #else
89*03ce13f7SAndroid Build Coastguard Worker 	optimizerOptions.set_run_validator(true);
90*03ce13f7SAndroid Build Coastguard Worker 	spvtools::ValidatorOptions validatorOptions = {};
91*03ce13f7SAndroid Build Coastguard Worker 	validatorOptions.SetScalarBlockLayout(true);            // VK_EXT_scalar_block_layout
92*03ce13f7SAndroid Build Coastguard Worker 	validatorOptions.SetUniformBufferStandardLayout(true);  // VK_KHR_uniform_buffer_standard_layout
93*03ce13f7SAndroid Build Coastguard Worker 	validatorOptions.SetAllowLocalSizeId(true);             // VK_KHR_maintenance4
94*03ce13f7SAndroid Build Coastguard Worker 	optimizerOptions.set_validator_options(validatorOptions);
95*03ce13f7SAndroid Build Coastguard Worker #endif
96*03ce13f7SAndroid Build Coastguard Worker 
97*03ce13f7SAndroid Build Coastguard Worker 	sw::SpirvBinary optimized;
98*03ce13f7SAndroid Build Coastguard Worker 	opt.Run(code.data(), code.size(), &optimized, optimizerOptions);
99*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(optimized.size() > 0);
100*03ce13f7SAndroid Build Coastguard Worker 
101*03ce13f7SAndroid Build Coastguard Worker 	if(false)
102*03ce13f7SAndroid Build Coastguard Worker 	{
103*03ce13f7SAndroid Build Coastguard Worker 		spvtools::SpirvTools core(vk::SPIRV_VERSION);
104*03ce13f7SAndroid Build Coastguard Worker 		std::string preOpt;
105*03ce13f7SAndroid Build Coastguard Worker 		core.Disassemble(code, &preOpt, SPV_BINARY_TO_TEXT_OPTION_NONE);
106*03ce13f7SAndroid Build Coastguard Worker 		std::string postOpt;
107*03ce13f7SAndroid Build Coastguard Worker 		core.Disassemble(optimized, &postOpt, SPV_BINARY_TO_TEXT_OPTION_NONE);
108*03ce13f7SAndroid Build Coastguard Worker 		std::cout << "PRE-OPT: " << preOpt << std::endl
109*03ce13f7SAndroid Build Coastguard Worker 		          << "POST-OPT: " << postOpt << std::endl;
110*03ce13f7SAndroid Build Coastguard Worker 	}
111*03ce13f7SAndroid Build Coastguard Worker 
112*03ce13f7SAndroid Build Coastguard Worker 	return optimized;
113*03ce13f7SAndroid Build Coastguard Worker }
114*03ce13f7SAndroid Build Coastguard Worker 
createProgram(vk::Device * device,std::shared_ptr<sw::SpirvShader> shader,const vk::PipelineLayout * layout)115*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<sw::ComputeProgram> createProgram(vk::Device *device, std::shared_ptr<sw::SpirvShader> shader, const vk::PipelineLayout *layout)
116*03ce13f7SAndroid Build Coastguard Worker {
117*03ce13f7SAndroid Build Coastguard Worker 	MARL_SCOPED_EVENT("createProgram");
118*03ce13f7SAndroid Build Coastguard Worker 
119*03ce13f7SAndroid Build Coastguard Worker 	vk::DescriptorSet::Bindings descriptorSets;  // TODO(b/129523279): Delay code generation until dispatch time.
120*03ce13f7SAndroid Build Coastguard Worker 	// TODO(b/119409619): use allocator.
121*03ce13f7SAndroid Build Coastguard Worker 	auto program = std::make_shared<sw::ComputeProgram>(device, shader, layout, descriptorSets);
122*03ce13f7SAndroid Build Coastguard Worker 	program->generate();
123*03ce13f7SAndroid Build Coastguard Worker 	program->finalize("ComputeProgram");
124*03ce13f7SAndroid Build Coastguard Worker 
125*03ce13f7SAndroid Build Coastguard Worker 	return program;
126*03ce13f7SAndroid Build Coastguard Worker }
127*03ce13f7SAndroid Build Coastguard Worker 
128*03ce13f7SAndroid Build Coastguard Worker class PipelineCreationFeedback
129*03ce13f7SAndroid Build Coastguard Worker {
130*03ce13f7SAndroid Build Coastguard Worker public:
PipelineCreationFeedback(const VkGraphicsPipelineCreateInfo * pCreateInfo)131*03ce13f7SAndroid Build Coastguard Worker 	PipelineCreationFeedback(const VkGraphicsPipelineCreateInfo *pCreateInfo)
132*03ce13f7SAndroid Build Coastguard Worker 	    : pipelineCreationFeedback(GetPipelineCreationFeedback(pCreateInfo->pNext))
133*03ce13f7SAndroid Build Coastguard Worker 	{
134*03ce13f7SAndroid Build Coastguard Worker 		pipelineCreationBegins();
135*03ce13f7SAndroid Build Coastguard Worker 	}
136*03ce13f7SAndroid Build Coastguard Worker 
PipelineCreationFeedback(const VkComputePipelineCreateInfo * pCreateInfo)137*03ce13f7SAndroid Build Coastguard Worker 	PipelineCreationFeedback(const VkComputePipelineCreateInfo *pCreateInfo)
138*03ce13f7SAndroid Build Coastguard Worker 	    : pipelineCreationFeedback(GetPipelineCreationFeedback(pCreateInfo->pNext))
139*03ce13f7SAndroid Build Coastguard Worker 	{
140*03ce13f7SAndroid Build Coastguard Worker 		pipelineCreationBegins();
141*03ce13f7SAndroid Build Coastguard Worker 	}
142*03ce13f7SAndroid Build Coastguard Worker 
~PipelineCreationFeedback()143*03ce13f7SAndroid Build Coastguard Worker 	~PipelineCreationFeedback()
144*03ce13f7SAndroid Build Coastguard Worker 	{
145*03ce13f7SAndroid Build Coastguard Worker 		pipelineCreationEnds();
146*03ce13f7SAndroid Build Coastguard Worker 	}
147*03ce13f7SAndroid Build Coastguard Worker 
stageCreationBegins(uint32_t stage)148*03ce13f7SAndroid Build Coastguard Worker 	void stageCreationBegins(uint32_t stage)
149*03ce13f7SAndroid Build Coastguard Worker 	{
150*03ce13f7SAndroid Build Coastguard Worker 		if(pipelineCreationFeedback && (stage < pipelineCreationFeedback->pipelineStageCreationFeedbackCount))
151*03ce13f7SAndroid Build Coastguard Worker 		{
152*03ce13f7SAndroid Build Coastguard Worker 			// Record stage creation begin time
153*03ce13f7SAndroid Build Coastguard Worker 			pipelineCreationFeedback->pPipelineStageCreationFeedbacks[stage].duration = now();
154*03ce13f7SAndroid Build Coastguard Worker 		}
155*03ce13f7SAndroid Build Coastguard Worker 	}
156*03ce13f7SAndroid Build Coastguard Worker 
cacheHit(uint32_t stage)157*03ce13f7SAndroid Build Coastguard Worker 	void cacheHit(uint32_t stage)
158*03ce13f7SAndroid Build Coastguard Worker 	{
159*03ce13f7SAndroid Build Coastguard Worker 		if(pipelineCreationFeedback)
160*03ce13f7SAndroid Build Coastguard Worker 		{
161*03ce13f7SAndroid Build Coastguard Worker 			pipelineCreationFeedback->pPipelineCreationFeedback->flags |=
162*03ce13f7SAndroid Build Coastguard Worker 			    VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT;
163*03ce13f7SAndroid Build Coastguard Worker 			if(stage < pipelineCreationFeedback->pipelineStageCreationFeedbackCount)
164*03ce13f7SAndroid Build Coastguard Worker 			{
165*03ce13f7SAndroid Build Coastguard Worker 				pipelineCreationFeedback->pPipelineStageCreationFeedbacks[stage].flags |=
166*03ce13f7SAndroid Build Coastguard Worker 				    VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT;
167*03ce13f7SAndroid Build Coastguard Worker 			}
168*03ce13f7SAndroid Build Coastguard Worker 		}
169*03ce13f7SAndroid Build Coastguard Worker 	}
170*03ce13f7SAndroid Build Coastguard Worker 
stageCreationEnds(uint32_t stage)171*03ce13f7SAndroid Build Coastguard Worker 	void stageCreationEnds(uint32_t stage)
172*03ce13f7SAndroid Build Coastguard Worker 	{
173*03ce13f7SAndroid Build Coastguard Worker 		if(pipelineCreationFeedback && (stage < pipelineCreationFeedback->pipelineStageCreationFeedbackCount))
174*03ce13f7SAndroid Build Coastguard Worker 		{
175*03ce13f7SAndroid Build Coastguard Worker 			pipelineCreationFeedback->pPipelineStageCreationFeedbacks[stage].flags |=
176*03ce13f7SAndroid Build Coastguard Worker 			    VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT;
177*03ce13f7SAndroid Build Coastguard Worker 			pipelineCreationFeedback->pPipelineStageCreationFeedbacks[stage].duration =
178*03ce13f7SAndroid Build Coastguard Worker 			    now() - pipelineCreationFeedback->pPipelineStageCreationFeedbacks[stage].duration;
179*03ce13f7SAndroid Build Coastguard Worker 		}
180*03ce13f7SAndroid Build Coastguard Worker 	}
181*03ce13f7SAndroid Build Coastguard Worker 
pipelineCreationError()182*03ce13f7SAndroid Build Coastguard Worker 	void pipelineCreationError()
183*03ce13f7SAndroid Build Coastguard Worker 	{
184*03ce13f7SAndroid Build Coastguard Worker 		clear();
185*03ce13f7SAndroid Build Coastguard Worker 		pipelineCreationFeedback = nullptr;
186*03ce13f7SAndroid Build Coastguard Worker 	}
187*03ce13f7SAndroid Build Coastguard Worker 
188*03ce13f7SAndroid Build Coastguard Worker private:
GetPipelineCreationFeedback(const void * pNext)189*03ce13f7SAndroid Build Coastguard Worker 	static const VkPipelineCreationFeedbackCreateInfo *GetPipelineCreationFeedback(const void *pNext)
190*03ce13f7SAndroid Build Coastguard Worker 	{
191*03ce13f7SAndroid Build Coastguard Worker 		return vk::GetExtendedStruct<VkPipelineCreationFeedbackCreateInfo>(pNext, VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO);
192*03ce13f7SAndroid Build Coastguard Worker 	}
193*03ce13f7SAndroid Build Coastguard Worker 
pipelineCreationBegins()194*03ce13f7SAndroid Build Coastguard Worker 	void pipelineCreationBegins()
195*03ce13f7SAndroid Build Coastguard Worker 	{
196*03ce13f7SAndroid Build Coastguard Worker 		if(pipelineCreationFeedback)
197*03ce13f7SAndroid Build Coastguard Worker 		{
198*03ce13f7SAndroid Build Coastguard Worker 			clear();
199*03ce13f7SAndroid Build Coastguard Worker 
200*03ce13f7SAndroid Build Coastguard Worker 			// Record pipeline creation begin time
201*03ce13f7SAndroid Build Coastguard Worker 			pipelineCreationFeedback->pPipelineCreationFeedback->duration = now();
202*03ce13f7SAndroid Build Coastguard Worker 		}
203*03ce13f7SAndroid Build Coastguard Worker 	}
204*03ce13f7SAndroid Build Coastguard Worker 
pipelineCreationEnds()205*03ce13f7SAndroid Build Coastguard Worker 	void pipelineCreationEnds()
206*03ce13f7SAndroid Build Coastguard Worker 	{
207*03ce13f7SAndroid Build Coastguard Worker 		if(pipelineCreationFeedback)
208*03ce13f7SAndroid Build Coastguard Worker 		{
209*03ce13f7SAndroid Build Coastguard Worker 			pipelineCreationFeedback->pPipelineCreationFeedback->flags |=
210*03ce13f7SAndroid Build Coastguard Worker 			    VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT;
211*03ce13f7SAndroid Build Coastguard Worker 			pipelineCreationFeedback->pPipelineCreationFeedback->duration =
212*03ce13f7SAndroid Build Coastguard Worker 			    now() - pipelineCreationFeedback->pPipelineCreationFeedback->duration;
213*03ce13f7SAndroid Build Coastguard Worker 		}
214*03ce13f7SAndroid Build Coastguard Worker 	}
215*03ce13f7SAndroid Build Coastguard Worker 
clear()216*03ce13f7SAndroid Build Coastguard Worker 	void clear()
217*03ce13f7SAndroid Build Coastguard Worker 	{
218*03ce13f7SAndroid Build Coastguard Worker 		if(pipelineCreationFeedback)
219*03ce13f7SAndroid Build Coastguard Worker 		{
220*03ce13f7SAndroid Build Coastguard Worker 			// Clear all flags and durations
221*03ce13f7SAndroid Build Coastguard Worker 			pipelineCreationFeedback->pPipelineCreationFeedback->flags = 0;
222*03ce13f7SAndroid Build Coastguard Worker 			pipelineCreationFeedback->pPipelineCreationFeedback->duration = 0;
223*03ce13f7SAndroid Build Coastguard Worker 			for(uint32_t i = 0; i < pipelineCreationFeedback->pipelineStageCreationFeedbackCount; i++)
224*03ce13f7SAndroid Build Coastguard Worker 			{
225*03ce13f7SAndroid Build Coastguard Worker 				pipelineCreationFeedback->pPipelineStageCreationFeedbacks[i].flags = 0;
226*03ce13f7SAndroid Build Coastguard Worker 				pipelineCreationFeedback->pPipelineStageCreationFeedbacks[i].duration = 0;
227*03ce13f7SAndroid Build Coastguard Worker 			}
228*03ce13f7SAndroid Build Coastguard Worker 		}
229*03ce13f7SAndroid Build Coastguard Worker 	}
230*03ce13f7SAndroid Build Coastguard Worker 
now()231*03ce13f7SAndroid Build Coastguard Worker 	uint64_t now()
232*03ce13f7SAndroid Build Coastguard Worker 	{
233*03ce13f7SAndroid Build Coastguard Worker 		return std::chrono::time_point_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
234*03ce13f7SAndroid Build Coastguard Worker 	}
235*03ce13f7SAndroid Build Coastguard Worker 
236*03ce13f7SAndroid Build Coastguard Worker 	const VkPipelineCreationFeedbackCreateInfo *pipelineCreationFeedback = nullptr;
237*03ce13f7SAndroid Build Coastguard Worker };
238*03ce13f7SAndroid Build Coastguard Worker 
getRobustBufferAccess(VkPipelineRobustnessBufferBehaviorEXT behavior,bool inheritRobustBufferAccess)239*03ce13f7SAndroid Build Coastguard Worker bool getRobustBufferAccess(VkPipelineRobustnessBufferBehaviorEXT behavior, bool inheritRobustBufferAccess)
240*03ce13f7SAndroid Build Coastguard Worker {
241*03ce13f7SAndroid Build Coastguard Worker 	// Based on behavior:
242*03ce13f7SAndroid Build Coastguard Worker 	// - <not provided>:
243*03ce13f7SAndroid Build Coastguard Worker 	//   * For pipelines, use device's robustBufferAccess
244*03ce13f7SAndroid Build Coastguard Worker 	//   * For shaders, use pipeline's robustBufferAccess
245*03ce13f7SAndroid Build Coastguard Worker 	//     Note that pipeline's robustBufferAccess is already set to device's if not overriden.
246*03ce13f7SAndroid Build Coastguard Worker 	// - Default: Use device's robustBufferAccess
247*03ce13f7SAndroid Build Coastguard Worker 	// - Disabled / Enabled: Override to disabled or enabled
248*03ce13f7SAndroid Build Coastguard Worker 	//
249*03ce13f7SAndroid Build Coastguard Worker 	// This function is passed "DEFAULT" when override is not provided, and
250*03ce13f7SAndroid Build Coastguard Worker 	// inheritRobustBufferAccess is appropriately set to the device or pipeline's
251*03ce13f7SAndroid Build Coastguard Worker 	// robustBufferAccess
252*03ce13f7SAndroid Build Coastguard Worker 	switch(behavior)
253*03ce13f7SAndroid Build Coastguard Worker 	{
254*03ce13f7SAndroid Build Coastguard Worker 	case VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DEVICE_DEFAULT_EXT:
255*03ce13f7SAndroid Build Coastguard Worker 		return inheritRobustBufferAccess;
256*03ce13f7SAndroid Build Coastguard Worker 	case VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DISABLED_EXT:
257*03ce13f7SAndroid Build Coastguard Worker 		return false;
258*03ce13f7SAndroid Build Coastguard Worker 	case VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_EXT:
259*03ce13f7SAndroid Build Coastguard Worker 		return true;
260*03ce13f7SAndroid Build Coastguard Worker 	default:
261*03ce13f7SAndroid Build Coastguard Worker 		UNSUPPORTED("Unsupported robustness behavior");
262*03ce13f7SAndroid Build Coastguard Worker 		return true;
263*03ce13f7SAndroid Build Coastguard Worker 	}
264*03ce13f7SAndroid Build Coastguard Worker }
265*03ce13f7SAndroid Build Coastguard Worker 
getRobustBufferAccess(const VkPipelineRobustnessCreateInfoEXT * overrideRobustness,bool deviceRobustBufferAccess,bool inheritRobustBufferAccess)266*03ce13f7SAndroid Build Coastguard Worker bool getRobustBufferAccess(const VkPipelineRobustnessCreateInfoEXT *overrideRobustness, bool deviceRobustBufferAccess, bool inheritRobustBufferAccess)
267*03ce13f7SAndroid Build Coastguard Worker {
268*03ce13f7SAndroid Build Coastguard Worker 	VkPipelineRobustnessBufferBehaviorEXT storageBehavior = VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DEVICE_DEFAULT_EXT;
269*03ce13f7SAndroid Build Coastguard Worker 	VkPipelineRobustnessBufferBehaviorEXT uniformBehavior = VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DEVICE_DEFAULT_EXT;
270*03ce13f7SAndroid Build Coastguard Worker 	VkPipelineRobustnessBufferBehaviorEXT vertexBehavior = VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DEVICE_DEFAULT_EXT;
271*03ce13f7SAndroid Build Coastguard Worker 
272*03ce13f7SAndroid Build Coastguard Worker 	if(overrideRobustness)
273*03ce13f7SAndroid Build Coastguard Worker 	{
274*03ce13f7SAndroid Build Coastguard Worker 		storageBehavior = overrideRobustness->storageBuffers;
275*03ce13f7SAndroid Build Coastguard Worker 		uniformBehavior = overrideRobustness->uniformBuffers;
276*03ce13f7SAndroid Build Coastguard Worker 		vertexBehavior = overrideRobustness->vertexInputs;
277*03ce13f7SAndroid Build Coastguard Worker 		inheritRobustBufferAccess = deviceRobustBufferAccess;
278*03ce13f7SAndroid Build Coastguard Worker 	}
279*03ce13f7SAndroid Build Coastguard Worker 
280*03ce13f7SAndroid Build Coastguard Worker 	bool storageRobustBufferAccess = getRobustBufferAccess(storageBehavior, inheritRobustBufferAccess);
281*03ce13f7SAndroid Build Coastguard Worker 	bool uniformRobustBufferAccess = getRobustBufferAccess(uniformBehavior, inheritRobustBufferAccess);
282*03ce13f7SAndroid Build Coastguard Worker 	bool vertexRobustBufferAccess = getRobustBufferAccess(vertexBehavior, inheritRobustBufferAccess);
283*03ce13f7SAndroid Build Coastguard Worker 
284*03ce13f7SAndroid Build Coastguard Worker 	// Note: in the initial implementation, enabling robust access for any buffer enables it for
285*03ce13f7SAndroid Build Coastguard Worker 	// all.  TODO(b/185122256) split robustBufferAccess in the pipeline and shaders into three
286*03ce13f7SAndroid Build Coastguard Worker 	// categories and provide robustness for storage, uniform and vertex buffers accordingly.
287*03ce13f7SAndroid Build Coastguard Worker 	return storageRobustBufferAccess || uniformRobustBufferAccess || vertexRobustBufferAccess;
288*03ce13f7SAndroid Build Coastguard Worker }
289*03ce13f7SAndroid Build Coastguard Worker 
getPipelineRobustBufferAccess(const void * pNext,vk::Device * device)290*03ce13f7SAndroid Build Coastguard Worker bool getPipelineRobustBufferAccess(const void *pNext, vk::Device *device)
291*03ce13f7SAndroid Build Coastguard Worker {
292*03ce13f7SAndroid Build Coastguard Worker 	const VkPipelineRobustnessCreateInfoEXT *overrideRobustness = vk::GetExtendedStruct<VkPipelineRobustnessCreateInfoEXT>(pNext, VK_STRUCTURE_TYPE_PIPELINE_ROBUSTNESS_CREATE_INFO_EXT);
293*03ce13f7SAndroid Build Coastguard Worker 	const bool deviceRobustBufferAccess = device->getEnabledFeatures().robustBufferAccess;
294*03ce13f7SAndroid Build Coastguard Worker 
295*03ce13f7SAndroid Build Coastguard Worker 	// For pipelines, there's no robustBufferAccess to inherit from.  Default and no-override
296*03ce13f7SAndroid Build Coastguard Worker 	// both lead to using the device's robustBufferAccess.
297*03ce13f7SAndroid Build Coastguard Worker 	return getRobustBufferAccess(overrideRobustness, deviceRobustBufferAccess, deviceRobustBufferAccess);
298*03ce13f7SAndroid Build Coastguard Worker }
299*03ce13f7SAndroid Build Coastguard Worker 
getPipelineStageRobustBufferAccess(const void * pNext,vk::Device * device,bool pipelineRobustBufferAccess)300*03ce13f7SAndroid Build Coastguard Worker bool getPipelineStageRobustBufferAccess(const void *pNext, vk::Device *device, bool pipelineRobustBufferAccess)
301*03ce13f7SAndroid Build Coastguard Worker {
302*03ce13f7SAndroid Build Coastguard Worker 	const VkPipelineRobustnessCreateInfoEXT *overrideRobustness = vk::GetExtendedStruct<VkPipelineRobustnessCreateInfoEXT>(pNext, VK_STRUCTURE_TYPE_PIPELINE_ROBUSTNESS_CREATE_INFO_EXT);
303*03ce13f7SAndroid Build Coastguard Worker 	const bool deviceRobustBufferAccess = device->getEnabledFeatures().robustBufferAccess;
304*03ce13f7SAndroid Build Coastguard Worker 
305*03ce13f7SAndroid Build Coastguard Worker 	return getRobustBufferAccess(overrideRobustness, deviceRobustBufferAccess, pipelineRobustBufferAccess);
306*03ce13f7SAndroid Build Coastguard Worker }
307*03ce13f7SAndroid Build Coastguard Worker 
308*03ce13f7SAndroid Build Coastguard Worker }  // anonymous namespace
309*03ce13f7SAndroid Build Coastguard Worker 
310*03ce13f7SAndroid Build Coastguard Worker namespace vk {
Pipeline(PipelineLayout * layout,Device * device,bool robustBufferAccess)311*03ce13f7SAndroid Build Coastguard Worker Pipeline::Pipeline(PipelineLayout *layout, Device *device, bool robustBufferAccess)
312*03ce13f7SAndroid Build Coastguard Worker     : layout(layout)
313*03ce13f7SAndroid Build Coastguard Worker     , device(device)
314*03ce13f7SAndroid Build Coastguard Worker     , robustBufferAccess(robustBufferAccess)
315*03ce13f7SAndroid Build Coastguard Worker {
316*03ce13f7SAndroid Build Coastguard Worker 	if(layout)
317*03ce13f7SAndroid Build Coastguard Worker 	{
318*03ce13f7SAndroid Build Coastguard Worker 		layout->incRefCount();
319*03ce13f7SAndroid Build Coastguard Worker 	}
320*03ce13f7SAndroid Build Coastguard Worker }
321*03ce13f7SAndroid Build Coastguard Worker 
destroy(const VkAllocationCallbacks * pAllocator)322*03ce13f7SAndroid Build Coastguard Worker void Pipeline::destroy(const VkAllocationCallbacks *pAllocator)
323*03ce13f7SAndroid Build Coastguard Worker {
324*03ce13f7SAndroid Build Coastguard Worker 	destroyPipeline(pAllocator);
325*03ce13f7SAndroid Build Coastguard Worker 
326*03ce13f7SAndroid Build Coastguard Worker 	if(layout)
327*03ce13f7SAndroid Build Coastguard Worker 	{
328*03ce13f7SAndroid Build Coastguard Worker 		vk::release(static_cast<VkPipelineLayout>(*layout), pAllocator);
329*03ce13f7SAndroid Build Coastguard Worker 	}
330*03ce13f7SAndroid Build Coastguard Worker }
331*03ce13f7SAndroid Build Coastguard Worker 
GraphicsPipeline(const VkGraphicsPipelineCreateInfo * pCreateInfo,void * mem,Device * device)332*03ce13f7SAndroid Build Coastguard Worker GraphicsPipeline::GraphicsPipeline(const VkGraphicsPipelineCreateInfo *pCreateInfo, void *mem, Device *device)
333*03ce13f7SAndroid Build Coastguard Worker     : Pipeline(vk::Cast(pCreateInfo->layout), device, getPipelineRobustBufferAccess(pCreateInfo->pNext, device))
334*03ce13f7SAndroid Build Coastguard Worker     , state(device, pCreateInfo, layout)
335*03ce13f7SAndroid Build Coastguard Worker {
336*03ce13f7SAndroid Build Coastguard Worker 	// Either the vertex input interface comes from a pipeline library, or the
337*03ce13f7SAndroid Build Coastguard Worker 	// VkGraphicsPipelineCreateInfo itself.  Same with shaders.
338*03ce13f7SAndroid Build Coastguard Worker 	const auto *libraryCreateInfo = GetExtendedStruct<VkPipelineLibraryCreateInfoKHR>(pCreateInfo->pNext, VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR);
339*03ce13f7SAndroid Build Coastguard Worker 	bool vertexInputInterfaceInLibraries = false;
340*03ce13f7SAndroid Build Coastguard Worker 	bool fragmentOutputInterfaceInLibraries = false;
341*03ce13f7SAndroid Build Coastguard Worker 	if(libraryCreateInfo)
342*03ce13f7SAndroid Build Coastguard Worker 	{
343*03ce13f7SAndroid Build Coastguard Worker 		for(uint32_t i = 0; i < libraryCreateInfo->libraryCount; ++i)
344*03ce13f7SAndroid Build Coastguard Worker 		{
345*03ce13f7SAndroid Build Coastguard Worker 			const auto *library = static_cast<const vk::GraphicsPipeline *>(vk::Cast(libraryCreateInfo->pLibraries[i]));
346*03ce13f7SAndroid Build Coastguard Worker 			if(library->state.hasVertexInputInterfaceState())
347*03ce13f7SAndroid Build Coastguard Worker 			{
348*03ce13f7SAndroid Build Coastguard Worker 				inputs = library->inputs;
349*03ce13f7SAndroid Build Coastguard Worker 				vertexInputInterfaceInLibraries = true;
350*03ce13f7SAndroid Build Coastguard Worker 			}
351*03ce13f7SAndroid Build Coastguard Worker 			if(library->state.hasPreRasterizationState())
352*03ce13f7SAndroid Build Coastguard Worker 			{
353*03ce13f7SAndroid Build Coastguard Worker 				vertexShader = library->vertexShader;
354*03ce13f7SAndroid Build Coastguard Worker 			}
355*03ce13f7SAndroid Build Coastguard Worker 			if(library->state.hasFragmentState())
356*03ce13f7SAndroid Build Coastguard Worker 			{
357*03ce13f7SAndroid Build Coastguard Worker 				fragmentShader = library->fragmentShader;
358*03ce13f7SAndroid Build Coastguard Worker 			}
359*03ce13f7SAndroid Build Coastguard Worker 			if(library->state.hasFragmentOutputInterfaceState())
360*03ce13f7SAndroid Build Coastguard Worker 			{
361*03ce13f7SAndroid Build Coastguard Worker 				memcpy(attachments.indexToLocation, library->attachments.indexToLocation, sizeof(attachments.indexToLocation));
362*03ce13f7SAndroid Build Coastguard Worker 				memcpy(attachments.locationToIndex, library->attachments.locationToIndex, sizeof(attachments.locationToIndex));
363*03ce13f7SAndroid Build Coastguard Worker 				fragmentOutputInterfaceInLibraries = true;
364*03ce13f7SAndroid Build Coastguard Worker 			}
365*03ce13f7SAndroid Build Coastguard Worker 		}
366*03ce13f7SAndroid Build Coastguard Worker 	}
367*03ce13f7SAndroid Build Coastguard Worker 	if(state.hasVertexInputInterfaceState() && !vertexInputInterfaceInLibraries)
368*03ce13f7SAndroid Build Coastguard Worker 	{
369*03ce13f7SAndroid Build Coastguard Worker 		inputs.initialize(pCreateInfo->pVertexInputState, pCreateInfo->pDynamicState);
370*03ce13f7SAndroid Build Coastguard Worker 	}
371*03ce13f7SAndroid Build Coastguard Worker 	if(state.hasFragmentOutputInterfaceState() && !fragmentOutputInterfaceInLibraries)
372*03ce13f7SAndroid Build Coastguard Worker 	{
373*03ce13f7SAndroid Build Coastguard Worker 		const auto *colorMapping = GetExtendedStruct<VkRenderingAttachmentLocationInfoKHR>(pCreateInfo->pNext, VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_LOCATION_INFO_KHR);
374*03ce13f7SAndroid Build Coastguard Worker 		if(colorMapping)
375*03ce13f7SAndroid Build Coastguard Worker 		{
376*03ce13f7SAndroid Build Coastguard Worker 			// Note that with VK_KHR_dynamic_rendering_local_read, if
377*03ce13f7SAndroid Build Coastguard Worker 			// VkRenderingAttachmentLocationInfoKHR is provided, setting an index to
378*03ce13f7SAndroid Build Coastguard Worker 			// VK_ATTACHMENT_UNUSED disables output for that attachment, even if write
379*03ce13f7SAndroid Build Coastguard Worker 			// mask is not explicitly disabled.
380*03ce13f7SAndroid Build Coastguard Worker 			for(uint32_t i = 0; i < sw::MAX_COLOR_BUFFERS; ++i)
381*03ce13f7SAndroid Build Coastguard Worker 			{
382*03ce13f7SAndroid Build Coastguard Worker 				attachments.indexToLocation[i] = VK_ATTACHMENT_UNUSED;
383*03ce13f7SAndroid Build Coastguard Worker 				attachments.locationToIndex[i] = VK_ATTACHMENT_UNUSED;
384*03ce13f7SAndroid Build Coastguard Worker 			}
385*03ce13f7SAndroid Build Coastguard Worker 
386*03ce13f7SAndroid Build Coastguard Worker 			for(uint32_t i = 0; i < colorMapping->colorAttachmentCount; ++i)
387*03ce13f7SAndroid Build Coastguard Worker 			{
388*03ce13f7SAndroid Build Coastguard Worker 				const uint32_t location = colorMapping->pColorAttachmentLocations[i];
389*03ce13f7SAndroid Build Coastguard Worker 				if(location != VK_ATTACHMENT_UNUSED)
390*03ce13f7SAndroid Build Coastguard Worker 				{
391*03ce13f7SAndroid Build Coastguard Worker 					attachments.indexToLocation[i] = location;
392*03ce13f7SAndroid Build Coastguard Worker 					attachments.locationToIndex[location] = i;
393*03ce13f7SAndroid Build Coastguard Worker 				}
394*03ce13f7SAndroid Build Coastguard Worker 			}
395*03ce13f7SAndroid Build Coastguard Worker 		}
396*03ce13f7SAndroid Build Coastguard Worker 		else
397*03ce13f7SAndroid Build Coastguard Worker 		{
398*03ce13f7SAndroid Build Coastguard Worker 			for(uint32_t i = 0; i < sw::MAX_COLOR_BUFFERS; ++i)
399*03ce13f7SAndroid Build Coastguard Worker 			{
400*03ce13f7SAndroid Build Coastguard Worker 				attachments.indexToLocation[i] = i;
401*03ce13f7SAndroid Build Coastguard Worker 				attachments.locationToIndex[i] = i;
402*03ce13f7SAndroid Build Coastguard Worker 			}
403*03ce13f7SAndroid Build Coastguard Worker 		}
404*03ce13f7SAndroid Build Coastguard Worker 	}
405*03ce13f7SAndroid Build Coastguard Worker }
406*03ce13f7SAndroid Build Coastguard Worker 
destroyPipeline(const VkAllocationCallbacks * pAllocator)407*03ce13f7SAndroid Build Coastguard Worker void GraphicsPipeline::destroyPipeline(const VkAllocationCallbacks *pAllocator)
408*03ce13f7SAndroid Build Coastguard Worker {
409*03ce13f7SAndroid Build Coastguard Worker 	vertexShader.reset();
410*03ce13f7SAndroid Build Coastguard Worker 	fragmentShader.reset();
411*03ce13f7SAndroid Build Coastguard Worker }
412*03ce13f7SAndroid Build Coastguard Worker 
ComputeRequiredAllocationSize(const VkGraphicsPipelineCreateInfo * pCreateInfo)413*03ce13f7SAndroid Build Coastguard Worker size_t GraphicsPipeline::ComputeRequiredAllocationSize(const VkGraphicsPipelineCreateInfo *pCreateInfo)
414*03ce13f7SAndroid Build Coastguard Worker {
415*03ce13f7SAndroid Build Coastguard Worker 	return 0;
416*03ce13f7SAndroid Build Coastguard Worker }
417*03ce13f7SAndroid Build Coastguard Worker 
GetGraphicsPipelineSubset(const VkGraphicsPipelineCreateInfo * pCreateInfo)418*03ce13f7SAndroid Build Coastguard Worker VkGraphicsPipelineLibraryFlagsEXT GraphicsPipeline::GetGraphicsPipelineSubset(const VkGraphicsPipelineCreateInfo *pCreateInfo)
419*03ce13f7SAndroid Build Coastguard Worker {
420*03ce13f7SAndroid Build Coastguard Worker 	const auto *libraryCreateInfo = vk::GetExtendedStruct<VkPipelineLibraryCreateInfoKHR>(pCreateInfo->pNext, VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR);
421*03ce13f7SAndroid Build Coastguard Worker 	const auto *graphicsLibraryCreateInfo = vk::GetExtendedStruct<VkGraphicsPipelineLibraryCreateInfoEXT>(pCreateInfo->pNext, VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT);
422*03ce13f7SAndroid Build Coastguard Worker 
423*03ce13f7SAndroid Build Coastguard Worker 	if(graphicsLibraryCreateInfo)
424*03ce13f7SAndroid Build Coastguard Worker 	{
425*03ce13f7SAndroid Build Coastguard Worker 		return graphicsLibraryCreateInfo->flags;
426*03ce13f7SAndroid Build Coastguard Worker 	}
427*03ce13f7SAndroid Build Coastguard Worker 
428*03ce13f7SAndroid Build Coastguard Worker 	// > If this structure is omitted, and either VkGraphicsPipelineCreateInfo::flags
429*03ce13f7SAndroid Build Coastguard Worker 	// > includes VK_PIPELINE_CREATE_LIBRARY_BIT_KHR or the
430*03ce13f7SAndroid Build Coastguard Worker 	// > VkGraphicsPipelineCreateInfo::pNext chain includes a VkPipelineLibraryCreateInfoKHR
431*03ce13f7SAndroid Build Coastguard Worker 	// > structure with a libraryCount greater than 0, it is as if flags is 0. Otherwise if
432*03ce13f7SAndroid Build Coastguard Worker 	// > this structure is omitted, it is as if flags includes all possible subsets of the
433*03ce13f7SAndroid Build Coastguard Worker 	// > graphics pipeline (i.e. a complete graphics pipeline).
434*03ce13f7SAndroid Build Coastguard Worker 	//
435*03ce13f7SAndroid Build Coastguard Worker 	// The above basically says that when a pipeline is created:
436*03ce13f7SAndroid Build Coastguard Worker 	// - If not a library and not created from libraries, it's a complete pipeline (i.e.
437*03ce13f7SAndroid Build Coastguard Worker 	//   Vulkan 1.0 pipelines)
438*03ce13f7SAndroid Build Coastguard Worker 	// - If only created from other libraries, no state is taken from
439*03ce13f7SAndroid Build Coastguard Worker 	//   VkGraphicsPipelineCreateInfo.
440*03ce13f7SAndroid Build Coastguard Worker 	//
441*03ce13f7SAndroid Build Coastguard Worker 	// Otherwise the behavior when creating a library from other libraries is that some
442*03ce13f7SAndroid Build Coastguard Worker 	// state is taken from VkGraphicsPipelineCreateInfo and some from the libraries.
443*03ce13f7SAndroid Build Coastguard Worker 	const bool isLibrary = (pCreateInfo->flags & VK_PIPELINE_CREATE_LIBRARY_BIT_KHR) != 0;
444*03ce13f7SAndroid Build Coastguard Worker 	if(isLibrary || (libraryCreateInfo && libraryCreateInfo->libraryCount > 0))
445*03ce13f7SAndroid Build Coastguard Worker 	{
446*03ce13f7SAndroid Build Coastguard Worker 		return 0;
447*03ce13f7SAndroid Build Coastguard Worker 	}
448*03ce13f7SAndroid Build Coastguard Worker 
449*03ce13f7SAndroid Build Coastguard Worker 	return VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT |
450*03ce13f7SAndroid Build Coastguard Worker 	       VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT |
451*03ce13f7SAndroid Build Coastguard Worker 	       VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT |
452*03ce13f7SAndroid Build Coastguard Worker 	       VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT;
453*03ce13f7SAndroid Build Coastguard Worker }
454*03ce13f7SAndroid Build Coastguard Worker 
getIndexBuffers(const vk::DynamicState & dynamicState,uint32_t count,uint32_t first,bool indexed,std::vector<std::pair<uint32_t,void * >> * indexBuffers) const455*03ce13f7SAndroid Build Coastguard Worker void GraphicsPipeline::getIndexBuffers(const vk::DynamicState &dynamicState, uint32_t count, uint32_t first, bool indexed, std::vector<std::pair<uint32_t, void *>> *indexBuffers) const
456*03ce13f7SAndroid Build Coastguard Worker {
457*03ce13f7SAndroid Build Coastguard Worker 	const vk::VertexInputInterfaceState &vertexInputInterfaceState = state.getVertexInputInterfaceState();
458*03ce13f7SAndroid Build Coastguard Worker 
459*03ce13f7SAndroid Build Coastguard Worker 	const VkPrimitiveTopology topology = vertexInputInterfaceState.hasDynamicTopology() ? dynamicState.primitiveTopology : vertexInputInterfaceState.getTopology();
460*03ce13f7SAndroid Build Coastguard Worker 	const bool hasPrimitiveRestartEnable = vertexInputInterfaceState.hasDynamicPrimitiveRestartEnable() ? dynamicState.primitiveRestartEnable : vertexInputInterfaceState.hasPrimitiveRestartEnable();
461*03ce13f7SAndroid Build Coastguard Worker 	indexBuffer.getIndexBuffers(topology, count, first, indexed, hasPrimitiveRestartEnable, indexBuffers);
462*03ce13f7SAndroid Build Coastguard Worker }
463*03ce13f7SAndroid Build Coastguard Worker 
preRasterizationContainsImageWrite() const464*03ce13f7SAndroid Build Coastguard Worker bool GraphicsPipeline::preRasterizationContainsImageWrite() const
465*03ce13f7SAndroid Build Coastguard Worker {
466*03ce13f7SAndroid Build Coastguard Worker 	return vertexShader.get() && vertexShader->containsImageWrite();
467*03ce13f7SAndroid Build Coastguard Worker }
468*03ce13f7SAndroid Build Coastguard Worker 
fragmentContainsImageWrite() const469*03ce13f7SAndroid Build Coastguard Worker bool GraphicsPipeline::fragmentContainsImageWrite() const
470*03ce13f7SAndroid Build Coastguard Worker {
471*03ce13f7SAndroid Build Coastguard Worker 	return fragmentShader.get() && fragmentShader->containsImageWrite();
472*03ce13f7SAndroid Build Coastguard Worker }
473*03ce13f7SAndroid Build Coastguard Worker 
setShader(const VkShaderStageFlagBits & stage,const std::shared_ptr<sw::SpirvShader> spirvShader)474*03ce13f7SAndroid Build Coastguard Worker void GraphicsPipeline::setShader(const VkShaderStageFlagBits &stage, const std::shared_ptr<sw::SpirvShader> spirvShader)
475*03ce13f7SAndroid Build Coastguard Worker {
476*03ce13f7SAndroid Build Coastguard Worker 	switch(stage)
477*03ce13f7SAndroid Build Coastguard Worker 	{
478*03ce13f7SAndroid Build Coastguard Worker 	case VK_SHADER_STAGE_VERTEX_BIT:
479*03ce13f7SAndroid Build Coastguard Worker 		ASSERT(vertexShader.get() == nullptr);
480*03ce13f7SAndroid Build Coastguard Worker 		vertexShader = spirvShader;
481*03ce13f7SAndroid Build Coastguard Worker 		break;
482*03ce13f7SAndroid Build Coastguard Worker 
483*03ce13f7SAndroid Build Coastguard Worker 	case VK_SHADER_STAGE_FRAGMENT_BIT:
484*03ce13f7SAndroid Build Coastguard Worker 		ASSERT(fragmentShader.get() == nullptr);
485*03ce13f7SAndroid Build Coastguard Worker 		fragmentShader = spirvShader;
486*03ce13f7SAndroid Build Coastguard Worker 		break;
487*03ce13f7SAndroid Build Coastguard Worker 
488*03ce13f7SAndroid Build Coastguard Worker 	default:
489*03ce13f7SAndroid Build Coastguard Worker 		UNSUPPORTED("Unsupported stage");
490*03ce13f7SAndroid Build Coastguard Worker 		break;
491*03ce13f7SAndroid Build Coastguard Worker 	}
492*03ce13f7SAndroid Build Coastguard Worker }
493*03ce13f7SAndroid Build Coastguard Worker 
getShader(const VkShaderStageFlagBits & stage) const494*03ce13f7SAndroid Build Coastguard Worker const std::shared_ptr<sw::SpirvShader> GraphicsPipeline::getShader(const VkShaderStageFlagBits &stage) const
495*03ce13f7SAndroid Build Coastguard Worker {
496*03ce13f7SAndroid Build Coastguard Worker 	switch(stage)
497*03ce13f7SAndroid Build Coastguard Worker 	{
498*03ce13f7SAndroid Build Coastguard Worker 	case VK_SHADER_STAGE_VERTEX_BIT:
499*03ce13f7SAndroid Build Coastguard Worker 		return vertexShader;
500*03ce13f7SAndroid Build Coastguard Worker 	case VK_SHADER_STAGE_FRAGMENT_BIT:
501*03ce13f7SAndroid Build Coastguard Worker 		return fragmentShader;
502*03ce13f7SAndroid Build Coastguard Worker 	default:
503*03ce13f7SAndroid Build Coastguard Worker 		UNSUPPORTED("Unsupported stage");
504*03ce13f7SAndroid Build Coastguard Worker 		return fragmentShader;
505*03ce13f7SAndroid Build Coastguard Worker 	}
506*03ce13f7SAndroid Build Coastguard Worker }
507*03ce13f7SAndroid Build Coastguard Worker 
compileShaders(const VkAllocationCallbacks * pAllocator,const VkGraphicsPipelineCreateInfo * pCreateInfo,PipelineCache * pPipelineCache)508*03ce13f7SAndroid Build Coastguard Worker VkResult GraphicsPipeline::compileShaders(const VkAllocationCallbacks *pAllocator, const VkGraphicsPipelineCreateInfo *pCreateInfo, PipelineCache *pPipelineCache)
509*03ce13f7SAndroid Build Coastguard Worker {
510*03ce13f7SAndroid Build Coastguard Worker 	PipelineCreationFeedback pipelineCreationFeedback(pCreateInfo);
511*03ce13f7SAndroid Build Coastguard Worker 	VkGraphicsPipelineLibraryFlagsEXT pipelineSubset = GetGraphicsPipelineSubset(pCreateInfo);
512*03ce13f7SAndroid Build Coastguard Worker 	const bool expectVertexShader = (pipelineSubset & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) != 0;
513*03ce13f7SAndroid Build Coastguard Worker 	const bool expectFragmentShader = (pipelineSubset & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) != 0;
514*03ce13f7SAndroid Build Coastguard Worker 
515*03ce13f7SAndroid Build Coastguard Worker 	const auto *inputAttachmentMapping = GetExtendedStruct<VkRenderingInputAttachmentIndexInfoKHR>(pCreateInfo->pNext, VK_STRUCTURE_TYPE_RENDERING_INPUT_ATTACHMENT_INDEX_INFO_KHR);
516*03ce13f7SAndroid Build Coastguard Worker 
517*03ce13f7SAndroid Build Coastguard Worker 	for(uint32_t stageIndex = 0; stageIndex < pCreateInfo->stageCount; stageIndex++)
518*03ce13f7SAndroid Build Coastguard Worker 	{
519*03ce13f7SAndroid Build Coastguard Worker 		const VkPipelineShaderStageCreateInfo &stageInfo = pCreateInfo->pStages[stageIndex];
520*03ce13f7SAndroid Build Coastguard Worker 
521*03ce13f7SAndroid Build Coastguard Worker 		// Ignore stages that don't exist in the pipeline library.
522*03ce13f7SAndroid Build Coastguard Worker 		if((stageInfo.stage == VK_SHADER_STAGE_VERTEX_BIT && !expectVertexShader) ||
523*03ce13f7SAndroid Build Coastguard Worker 		   (stageInfo.stage == VK_SHADER_STAGE_FRAGMENT_BIT && !expectFragmentShader))
524*03ce13f7SAndroid Build Coastguard Worker 		{
525*03ce13f7SAndroid Build Coastguard Worker 			continue;
526*03ce13f7SAndroid Build Coastguard Worker 		}
527*03ce13f7SAndroid Build Coastguard Worker 
528*03ce13f7SAndroid Build Coastguard Worker 		pipelineCreationFeedback.stageCreationBegins(stageIndex);
529*03ce13f7SAndroid Build Coastguard Worker 
530*03ce13f7SAndroid Build Coastguard Worker 		if((stageInfo.flags &
531*03ce13f7SAndroid Build Coastguard Worker 		    ~(VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT |
532*03ce13f7SAndroid Build Coastguard Worker 		      VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT)) != 0)
533*03ce13f7SAndroid Build Coastguard Worker 		{
534*03ce13f7SAndroid Build Coastguard Worker 			UNSUPPORTED("pStage->flags 0x%08X", int(stageInfo.flags));
535*03ce13f7SAndroid Build Coastguard Worker 		}
536*03ce13f7SAndroid Build Coastguard Worker 
537*03ce13f7SAndroid Build Coastguard Worker 		const bool optimize = true;  // TODO(b/251802301): Don't optimize when debugging shaders.
538*03ce13f7SAndroid Build Coastguard Worker 
539*03ce13f7SAndroid Build Coastguard Worker 		const ShaderModule *module = vk::Cast(stageInfo.module);
540*03ce13f7SAndroid Build Coastguard Worker 
541*03ce13f7SAndroid Build Coastguard Worker 		// VK_EXT_graphics_pipeline_library allows VkShaderModuleCreateInfo to be chained to
542*03ce13f7SAndroid Build Coastguard Worker 		// VkPipelineShaderStageCreateInfo, which is used if stageInfo.module is
543*03ce13f7SAndroid Build Coastguard Worker 		// VK_NULL_HANDLE.
544*03ce13f7SAndroid Build Coastguard Worker 		VkShaderModule tempModule = {};
545*03ce13f7SAndroid Build Coastguard Worker 		if(stageInfo.module == VK_NULL_HANDLE)
546*03ce13f7SAndroid Build Coastguard Worker 		{
547*03ce13f7SAndroid Build Coastguard Worker 			const auto *moduleCreateInfo = vk::GetExtendedStruct<VkShaderModuleCreateInfo>(stageInfo.pNext,
548*03ce13f7SAndroid Build Coastguard Worker 			                                                                               VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO);
549*03ce13f7SAndroid Build Coastguard Worker 			ASSERT(moduleCreateInfo);
550*03ce13f7SAndroid Build Coastguard Worker 			VkResult createResult = vk::ShaderModule::Create(nullptr, moduleCreateInfo, &tempModule);
551*03ce13f7SAndroid Build Coastguard Worker 			if(createResult != VK_SUCCESS)
552*03ce13f7SAndroid Build Coastguard Worker 			{
553*03ce13f7SAndroid Build Coastguard Worker 				return createResult;
554*03ce13f7SAndroid Build Coastguard Worker 			}
555*03ce13f7SAndroid Build Coastguard Worker 
556*03ce13f7SAndroid Build Coastguard Worker 			module = vk::Cast(tempModule);
557*03ce13f7SAndroid Build Coastguard Worker 		}
558*03ce13f7SAndroid Build Coastguard Worker 
559*03ce13f7SAndroid Build Coastguard Worker 		const PipelineCache::SpirvBinaryKey key(module->getBinary(), stageInfo.pSpecializationInfo, robustBufferAccess, optimize);
560*03ce13f7SAndroid Build Coastguard Worker 
561*03ce13f7SAndroid Build Coastguard Worker 		if((pCreateInfo->flags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT) &&
562*03ce13f7SAndroid Build Coastguard Worker 		   (!pPipelineCache || !pPipelineCache->contains(key)))
563*03ce13f7SAndroid Build Coastguard Worker 		{
564*03ce13f7SAndroid Build Coastguard Worker 			pipelineCreationFeedback.pipelineCreationError();
565*03ce13f7SAndroid Build Coastguard Worker 			return VK_PIPELINE_COMPILE_REQUIRED_EXT;
566*03ce13f7SAndroid Build Coastguard Worker 		}
567*03ce13f7SAndroid Build Coastguard Worker 
568*03ce13f7SAndroid Build Coastguard Worker 		sw::SpirvBinary spirv;
569*03ce13f7SAndroid Build Coastguard Worker 
570*03ce13f7SAndroid Build Coastguard Worker 		if(pPipelineCache)
571*03ce13f7SAndroid Build Coastguard Worker 		{
572*03ce13f7SAndroid Build Coastguard Worker 			auto onCacheMiss = [&] { return optimizeSpirv(key); };
573*03ce13f7SAndroid Build Coastguard Worker 			auto onCacheHit = [&] { pipelineCreationFeedback.cacheHit(stageIndex); };
574*03ce13f7SAndroid Build Coastguard Worker 			spirv = pPipelineCache->getOrOptimizeSpirv(key, onCacheMiss, onCacheHit);
575*03ce13f7SAndroid Build Coastguard Worker 		}
576*03ce13f7SAndroid Build Coastguard Worker 		else
577*03ce13f7SAndroid Build Coastguard Worker 		{
578*03ce13f7SAndroid Build Coastguard Worker 			spirv = optimizeSpirv(key);
579*03ce13f7SAndroid Build Coastguard Worker 
580*03ce13f7SAndroid Build Coastguard Worker 			// If the pipeline does not have specialization constants, there's a 1-to-1 mapping between the unoptimized and optimized SPIR-V,
581*03ce13f7SAndroid Build Coastguard Worker 			// so we should use a 1-to-1 mapping of the identifiers to avoid JIT routine recompiles.
582*03ce13f7SAndroid Build Coastguard Worker 			if(!key.getSpecializationInfo())
583*03ce13f7SAndroid Build Coastguard Worker 			{
584*03ce13f7SAndroid Build Coastguard Worker 				spirv.mapOptimizedIdentifier(key.getBinary());
585*03ce13f7SAndroid Build Coastguard Worker 			}
586*03ce13f7SAndroid Build Coastguard Worker 		}
587*03ce13f7SAndroid Build Coastguard Worker 
588*03ce13f7SAndroid Build Coastguard Worker 		const bool stageRobustBufferAccess = getPipelineStageRobustBufferAccess(stageInfo.pNext, device, robustBufferAccess);
589*03ce13f7SAndroid Build Coastguard Worker 
590*03ce13f7SAndroid Build Coastguard Worker 		// TODO(b/201798871): use allocator.
591*03ce13f7SAndroid Build Coastguard Worker 		auto shader = std::make_shared<sw::SpirvShader>(stageInfo.stage, stageInfo.pName, spirv,
592*03ce13f7SAndroid Build Coastguard Worker 		                                                vk::Cast(pCreateInfo->renderPass), pCreateInfo->subpass, inputAttachmentMapping, stageRobustBufferAccess);
593*03ce13f7SAndroid Build Coastguard Worker 
594*03ce13f7SAndroid Build Coastguard Worker 		setShader(stageInfo.stage, shader);
595*03ce13f7SAndroid Build Coastguard Worker 
596*03ce13f7SAndroid Build Coastguard Worker 		pipelineCreationFeedback.stageCreationEnds(stageIndex);
597*03ce13f7SAndroid Build Coastguard Worker 
598*03ce13f7SAndroid Build Coastguard Worker 		if(tempModule != VK_NULL_HANDLE)
599*03ce13f7SAndroid Build Coastguard Worker 		{
600*03ce13f7SAndroid Build Coastguard Worker 			vk::destroy(tempModule, nullptr);
601*03ce13f7SAndroid Build Coastguard Worker 		}
602*03ce13f7SAndroid Build Coastguard Worker 	}
603*03ce13f7SAndroid Build Coastguard Worker 
604*03ce13f7SAndroid Build Coastguard Worker 	return VK_SUCCESS;
605*03ce13f7SAndroid Build Coastguard Worker }
606*03ce13f7SAndroid Build Coastguard Worker 
ComputePipeline(const VkComputePipelineCreateInfo * pCreateInfo,void * mem,Device * device)607*03ce13f7SAndroid Build Coastguard Worker ComputePipeline::ComputePipeline(const VkComputePipelineCreateInfo *pCreateInfo, void *mem, Device *device)
608*03ce13f7SAndroid Build Coastguard Worker     : Pipeline(vk::Cast(pCreateInfo->layout), device, getPipelineRobustBufferAccess(pCreateInfo->pNext, device))
609*03ce13f7SAndroid Build Coastguard Worker {
610*03ce13f7SAndroid Build Coastguard Worker }
611*03ce13f7SAndroid Build Coastguard Worker 
destroyPipeline(const VkAllocationCallbacks * pAllocator)612*03ce13f7SAndroid Build Coastguard Worker void ComputePipeline::destroyPipeline(const VkAllocationCallbacks *pAllocator)
613*03ce13f7SAndroid Build Coastguard Worker {
614*03ce13f7SAndroid Build Coastguard Worker 	shader.reset();
615*03ce13f7SAndroid Build Coastguard Worker 	program.reset();
616*03ce13f7SAndroid Build Coastguard Worker }
617*03ce13f7SAndroid Build Coastguard Worker 
ComputeRequiredAllocationSize(const VkComputePipelineCreateInfo * pCreateInfo)618*03ce13f7SAndroid Build Coastguard Worker size_t ComputePipeline::ComputeRequiredAllocationSize(const VkComputePipelineCreateInfo *pCreateInfo)
619*03ce13f7SAndroid Build Coastguard Worker {
620*03ce13f7SAndroid Build Coastguard Worker 	return 0;
621*03ce13f7SAndroid Build Coastguard Worker }
622*03ce13f7SAndroid Build Coastguard Worker 
compileShaders(const VkAllocationCallbacks * pAllocator,const VkComputePipelineCreateInfo * pCreateInfo,PipelineCache * pPipelineCache)623*03ce13f7SAndroid Build Coastguard Worker VkResult ComputePipeline::compileShaders(const VkAllocationCallbacks *pAllocator, const VkComputePipelineCreateInfo *pCreateInfo, PipelineCache *pPipelineCache)
624*03ce13f7SAndroid Build Coastguard Worker {
625*03ce13f7SAndroid Build Coastguard Worker 	PipelineCreationFeedback pipelineCreationFeedback(pCreateInfo);
626*03ce13f7SAndroid Build Coastguard Worker 	pipelineCreationFeedback.stageCreationBegins(0);
627*03ce13f7SAndroid Build Coastguard Worker 
628*03ce13f7SAndroid Build Coastguard Worker 	auto &stage = pCreateInfo->stage;
629*03ce13f7SAndroid Build Coastguard Worker 	const ShaderModule *module = vk::Cast(stage.module);
630*03ce13f7SAndroid Build Coastguard Worker 
631*03ce13f7SAndroid Build Coastguard Worker 	// VK_EXT_graphics_pipeline_library allows VkShaderModuleCreateInfo to be chained to
632*03ce13f7SAndroid Build Coastguard Worker 	// VkPipelineShaderStageCreateInfo, which is used if stageInfo.module is
633*03ce13f7SAndroid Build Coastguard Worker 	// VK_NULL_HANDLE.
634*03ce13f7SAndroid Build Coastguard Worker 	VkShaderModule tempModule = {};
635*03ce13f7SAndroid Build Coastguard Worker 	if(stage.module == VK_NULL_HANDLE)
636*03ce13f7SAndroid Build Coastguard Worker 	{
637*03ce13f7SAndroid Build Coastguard Worker 		const auto *moduleCreateInfo = vk::GetExtendedStruct<VkShaderModuleCreateInfo>(stage.pNext,
638*03ce13f7SAndroid Build Coastguard Worker 		                                                                               VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO);
639*03ce13f7SAndroid Build Coastguard Worker 		ASSERT(moduleCreateInfo);
640*03ce13f7SAndroid Build Coastguard Worker 		VkResult createResult = vk::ShaderModule::Create(nullptr, moduleCreateInfo, &tempModule);
641*03ce13f7SAndroid Build Coastguard Worker 		if(createResult != VK_SUCCESS)
642*03ce13f7SAndroid Build Coastguard Worker 		{
643*03ce13f7SAndroid Build Coastguard Worker 			return createResult;
644*03ce13f7SAndroid Build Coastguard Worker 		}
645*03ce13f7SAndroid Build Coastguard Worker 
646*03ce13f7SAndroid Build Coastguard Worker 		module = vk::Cast(tempModule);
647*03ce13f7SAndroid Build Coastguard Worker 	}
648*03ce13f7SAndroid Build Coastguard Worker 
649*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(shader.get() == nullptr);
650*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(program.get() == nullptr);
651*03ce13f7SAndroid Build Coastguard Worker 
652*03ce13f7SAndroid Build Coastguard Worker 	const bool optimize = true;  // TODO(b/251802301): Don't optimize when debugging shaders.
653*03ce13f7SAndroid Build Coastguard Worker 
654*03ce13f7SAndroid Build Coastguard Worker 	const PipelineCache::SpirvBinaryKey shaderKey(module->getBinary(), stage.pSpecializationInfo, robustBufferAccess, optimize);
655*03ce13f7SAndroid Build Coastguard Worker 
656*03ce13f7SAndroid Build Coastguard Worker 	if((pCreateInfo->flags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT) &&
657*03ce13f7SAndroid Build Coastguard Worker 	   (!pPipelineCache || !pPipelineCache->contains(shaderKey)))
658*03ce13f7SAndroid Build Coastguard Worker 	{
659*03ce13f7SAndroid Build Coastguard Worker 		pipelineCreationFeedback.pipelineCreationError();
660*03ce13f7SAndroid Build Coastguard Worker 		return VK_PIPELINE_COMPILE_REQUIRED_EXT;
661*03ce13f7SAndroid Build Coastguard Worker 	}
662*03ce13f7SAndroid Build Coastguard Worker 
663*03ce13f7SAndroid Build Coastguard Worker 	sw::SpirvBinary spirv;
664*03ce13f7SAndroid Build Coastguard Worker 
665*03ce13f7SAndroid Build Coastguard Worker 	if(pPipelineCache)
666*03ce13f7SAndroid Build Coastguard Worker 	{
667*03ce13f7SAndroid Build Coastguard Worker 		auto onCacheMiss = [&] { return optimizeSpirv(shaderKey); };
668*03ce13f7SAndroid Build Coastguard Worker 		auto onCacheHit = [&] { pipelineCreationFeedback.cacheHit(0); };
669*03ce13f7SAndroid Build Coastguard Worker 		spirv = pPipelineCache->getOrOptimizeSpirv(shaderKey, onCacheMiss, onCacheHit);
670*03ce13f7SAndroid Build Coastguard Worker 	}
671*03ce13f7SAndroid Build Coastguard Worker 	else
672*03ce13f7SAndroid Build Coastguard Worker 	{
673*03ce13f7SAndroid Build Coastguard Worker 		spirv = optimizeSpirv(shaderKey);
674*03ce13f7SAndroid Build Coastguard Worker 
675*03ce13f7SAndroid Build Coastguard Worker 		// If the pipeline does not have specialization constants, there's a 1-to-1 mapping between the unoptimized and optimized SPIR-V,
676*03ce13f7SAndroid Build Coastguard Worker 		// so we should use a 1-to-1 mapping of the identifiers to avoid JIT routine recompiles.
677*03ce13f7SAndroid Build Coastguard Worker 		if(!shaderKey.getSpecializationInfo())
678*03ce13f7SAndroid Build Coastguard Worker 		{
679*03ce13f7SAndroid Build Coastguard Worker 			spirv.mapOptimizedIdentifier(shaderKey.getBinary());
680*03ce13f7SAndroid Build Coastguard Worker 		}
681*03ce13f7SAndroid Build Coastguard Worker 	}
682*03ce13f7SAndroid Build Coastguard Worker 
683*03ce13f7SAndroid Build Coastguard Worker 	const bool stageRobustBufferAccess = getPipelineStageRobustBufferAccess(stage.pNext, device, robustBufferAccess);
684*03ce13f7SAndroid Build Coastguard Worker 
685*03ce13f7SAndroid Build Coastguard Worker 	// TODO(b/201798871): use allocator.
686*03ce13f7SAndroid Build Coastguard Worker 	shader = std::make_shared<sw::SpirvShader>(stage.stage, stage.pName, spirv,
687*03ce13f7SAndroid Build Coastguard Worker 	                                           nullptr, 0, nullptr, stageRobustBufferAccess);
688*03ce13f7SAndroid Build Coastguard Worker 
689*03ce13f7SAndroid Build Coastguard Worker 	const PipelineCache::ComputeProgramKey programKey(shader->getIdentifier(), layout->identifier);
690*03ce13f7SAndroid Build Coastguard Worker 
691*03ce13f7SAndroid Build Coastguard Worker 	if(pPipelineCache)
692*03ce13f7SAndroid Build Coastguard Worker 	{
693*03ce13f7SAndroid Build Coastguard Worker 		program = pPipelineCache->getOrCreateComputeProgram(programKey, [&] {
694*03ce13f7SAndroid Build Coastguard Worker 			return createProgram(device, shader, layout);
695*03ce13f7SAndroid Build Coastguard Worker 		});
696*03ce13f7SAndroid Build Coastguard Worker 	}
697*03ce13f7SAndroid Build Coastguard Worker 	else
698*03ce13f7SAndroid Build Coastguard Worker 	{
699*03ce13f7SAndroid Build Coastguard Worker 		program = createProgram(device, shader, layout);
700*03ce13f7SAndroid Build Coastguard Worker 	}
701*03ce13f7SAndroid Build Coastguard Worker 
702*03ce13f7SAndroid Build Coastguard Worker 	pipelineCreationFeedback.stageCreationEnds(0);
703*03ce13f7SAndroid Build Coastguard Worker 
704*03ce13f7SAndroid Build Coastguard Worker 	return VK_SUCCESS;
705*03ce13f7SAndroid Build Coastguard Worker }
706*03ce13f7SAndroid Build Coastguard Worker 
run(uint32_t baseGroupX,uint32_t baseGroupY,uint32_t baseGroupZ,uint32_t groupCountX,uint32_t groupCountY,uint32_t groupCountZ,const vk::DescriptorSet::Array & descriptorSetObjects,const vk::DescriptorSet::Bindings & descriptorSets,const vk::DescriptorSet::DynamicOffsets & descriptorDynamicOffsets,const vk::Pipeline::PushConstantStorage & pushConstants)707*03ce13f7SAndroid Build Coastguard Worker void ComputePipeline::run(uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ,
708*03ce13f7SAndroid Build Coastguard Worker                           uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ,
709*03ce13f7SAndroid Build Coastguard Worker                           const vk::DescriptorSet::Array &descriptorSetObjects,
710*03ce13f7SAndroid Build Coastguard Worker                           const vk::DescriptorSet::Bindings &descriptorSets,
711*03ce13f7SAndroid Build Coastguard Worker                           const vk::DescriptorSet::DynamicOffsets &descriptorDynamicOffsets,
712*03ce13f7SAndroid Build Coastguard Worker                           const vk::Pipeline::PushConstantStorage &pushConstants)
713*03ce13f7SAndroid Build Coastguard Worker {
714*03ce13f7SAndroid Build Coastguard Worker 	ASSERT_OR_RETURN(program != nullptr);
715*03ce13f7SAndroid Build Coastguard Worker 	program->run(
716*03ce13f7SAndroid Build Coastguard Worker 	    descriptorSetObjects, descriptorSets, descriptorDynamicOffsets, pushConstants,
717*03ce13f7SAndroid Build Coastguard Worker 	    baseGroupX, baseGroupY, baseGroupZ,
718*03ce13f7SAndroid Build Coastguard Worker 	    groupCountX, groupCountY, groupCountZ);
719*03ce13f7SAndroid Build Coastguard Worker }
720*03ce13f7SAndroid Build Coastguard Worker 
721*03ce13f7SAndroid Build Coastguard Worker }  // namespace vk
722