blob: df5c52be90bbc2db08f03445f721ee18f86eb5c3 [file] [log] [blame]
Lionel Landwerlin2d9f5632022-01-08 01:12:47 +02001/* Copyright (c) 2015-2022 The Khronos Group Inc.
2 * Copyright (c) 2015-2022 Valve Corporation
3 * Copyright (c) 2015-2022 LunarG, Inc.
4 * Copyright (C) 2015-2022 Google Inc.
Jeremy Gebbenadb3eb02021-06-15 12:55:19 -06005 * Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * Author: Courtney Goeltzenleuchter <courtneygo@google.com>
20 * Author: Tobin Ehlis <tobine@google.com>
21 * Author: Chris Forbes <chrisf@ijw.co.nz>
22 * Author: Mark Lobodzinski <mark@lunarg.com>
23 * Author: Dave Houlton <daveh@lunarg.com>
24 * Author: John Zulauf <jzulauf@lunarg.com>
25 * Author: Tobias Hector <tobias.hector@amd.com>
Jeremy Gebben11af9792021-08-20 10:20:09 -060026 * Author: Jeremy Gebben <jeremyg@lunarg.com>
Jeremy Gebbenadb3eb02021-06-15 12:55:19 -060027 */
28#include "pipeline_state.h"
29#include "descriptor_sets.h"
30#include "cmd_buffer_state.h"
Jeremy Gebbenadb3eb02021-06-15 12:55:19 -060031#include "state_tracker.h"
Jeremy Gebben84b838b2021-08-23 08:41:39 -060032#include "shader_module.h"
Jeremy Gebbenadb3eb02021-06-15 12:55:19 -060033
Jeremy Gebben84b838b2021-08-23 08:41:39 -060034static bool HasWriteableDescriptor(const std::vector<PipelineStageState::DescriptorUse> &descriptor_uses) {
35 return std::any_of(descriptor_uses.begin(), descriptor_uses.end(),
ziga-lunarg1a535052022-03-10 01:04:28 +010036 [](const PipelineStageState::DescriptorUse &use) { return use.second.is_writable; });
Jeremy Gebben84b838b2021-08-23 08:41:39 -060037}
38
39static bool HasAtomicDescriptor(const std::vector<PipelineStageState::DescriptorUse> &descriptor_uses) {
40 return std::any_of(descriptor_uses.begin(), descriptor_uses.end(),
ziga-lunarg1a535052022-03-10 01:04:28 +010041 [](const PipelineStageState::DescriptorUse &use) { return use.second.is_atomic_operation; });
Jeremy Gebben84b838b2021-08-23 08:41:39 -060042}
43
Jeremy Gebben3dfeacf2021-12-02 08:46:39 -070044static bool WrotePrimitiveShadingRate(VkShaderStageFlagBits stage_flag, spirv_inst_iter entrypoint,
sfricke-samsungef15e482022-01-26 11:32:49 -080045 const SHADER_MODULE_STATE *module_state) {
Jeremy Gebben3dfeacf2021-12-02 08:46:39 -070046 bool primitiverate_written = false;
47 if (stage_flag == VK_SHADER_STAGE_VERTEX_BIT || stage_flag == VK_SHADER_STAGE_GEOMETRY_BIT ||
48 stage_flag == VK_SHADER_STAGE_MESH_BIT_NV) {
sfricke-samsungef15e482022-01-26 11:32:49 -080049 for (const auto &set : module_state->GetBuiltinDecorationList()) {
50 auto insn = module_state->at(set.offset);
Jeremy Gebben3dfeacf2021-12-02 08:46:39 -070051 if (set.builtin == spv::BuiltInPrimitiveShadingRateKHR) {
sfricke-samsungef15e482022-01-26 11:32:49 -080052 primitiverate_written = module_state->IsBuiltInWritten(insn, entrypoint);
Jeremy Gebben3dfeacf2021-12-02 08:46:39 -070053 }
54 if (primitiverate_written) {
55 break;
56 }
57 }
58 }
59 return primitiverate_written;
60}
61
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -070062PipelineStageState::PipelineStageState(const safe_VkPipelineShaderStageCreateInfo *stage,
sfricke-samsungef15e482022-01-26 11:32:49 -080063 std::shared_ptr<const SHADER_MODULE_STATE> &module_state)
64 : module_state(module_state),
Jeremy Gebben84b838b2021-08-23 08:41:39 -060065 create_info(stage),
66 stage_flag(stage->stage),
sfricke-samsungef15e482022-01-26 11:32:49 -080067 entrypoint(module_state->FindEntrypoint(stage->pName, stage->stage)),
68 accessible_ids(module_state->MarkAccessibleIds(entrypoint)),
69 descriptor_uses(module_state->CollectInterfaceByDescriptorSlot(accessible_ids)),
Jeremy Gebben84b838b2021-08-23 08:41:39 -060070 has_writable_descriptor(HasWriteableDescriptor(descriptor_uses)),
Jeremy Gebben3dfeacf2021-12-02 08:46:39 -070071 has_atomic_descriptor(HasAtomicDescriptor(descriptor_uses)),
ziga-lunargdab1c1e2022-04-21 23:53:49 +020072 wrote_primitive_shading_rate(WrotePrimitiveShadingRate(stage_flag, entrypoint, module_state.get())),
ziga-lunarg143bdbf2022-05-04 19:04:58 +020073 writes_to_gl_layer(module_state->WritesToGlLayer()),
74 has_input_attachment_capability(module_state->HasInputAttachmentCapability()) {}
Jeremy Gebben84b838b2021-08-23 08:41:39 -060075
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -070076// static
77PIPELINE_STATE::StageStateVec PIPELINE_STATE::GetStageStates(const ValidationStateTracker &state_data,
78 const PIPELINE_STATE &pipe_state) {
Jeremy Gebben84b838b2021-08-23 08:41:39 -060079 PIPELINE_STATE::StageStateVec stage_states;
Jeremy Gebben84b838b2021-08-23 08:41:39 -060080 // shader stages need to be recorded in pipeline order
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -070081 const auto stages = pipe_state.GetShaderStages();
82
Jeremy Gebben84b838b2021-08-23 08:41:39 -060083 for (uint32_t stage_idx = 0; stage_idx < 32; ++stage_idx) {
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -070084 bool stage_found = false;
85 const auto stage = static_cast<VkShaderStageFlagBits>(1 << stage_idx);
86 for (const auto &shader_stage : stages) {
87 if (shader_stage.stage == stage) {
88 auto module = state_data.Get<SHADER_MODULE_STATE>(shader_stage.module);
89 if (!module) {
90 // If module is null and there is a VkShaderModuleCreateInfo in the pNext chain of the stage info, then this
91 // module is part of a library and the state must be created
92 const auto shader_ci = LvlFindInChain<VkShaderModuleCreateInfo>(shader_stage.pNext);
Tony-LunarGcab5d812022-08-04 14:07:32 -060093 const uint32_t unique_shader_id = 0;
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -070094 if (shader_ci) {
Tony-LunarGcab5d812022-08-04 14:07:32 -060095 // TODO GPU-AV rework required to get this value properly
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -070096 module = state_data.CreateShaderModuleState(*shader_ci, unique_shader_id);
97 } else {
Tony-LunarGcab5d812022-08-04 14:07:32 -060098 // shader_module_identifier could legally provide a null module handle
99 VkShaderModuleCreateInfo dummy_module_ci = LvlInitStruct<VkShaderModuleCreateInfo>();
100 dummy_module_ci.pCode = &unique_shader_id; // Ensure tripping invalid spirv
101 module = state_data.CreateShaderModuleState(dummy_module_ci, unique_shader_id);
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700102 }
103 }
104 stage_states.emplace_back(&shader_stage, module);
105 stage_found = true;
106 }
107 }
108 if (!stage_found) {
109 // Check if stage has been supplied by a library
110 switch (stage) {
111 case VK_SHADER_STAGE_VERTEX_BIT:
112 if (pipe_state.pre_raster_state && pipe_state.pre_raster_state->vertex_shader) {
113 stage_states.emplace_back(pipe_state.pre_raster_state->vertex_shader_ci,
114 pipe_state.pre_raster_state->vertex_shader);
115 }
116 break;
117 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
118 if (pipe_state.pre_raster_state && pipe_state.pre_raster_state->tessc_shader) {
119 stage_states.emplace_back(pipe_state.pre_raster_state->tessc_shader_ci,
120 pipe_state.pre_raster_state->tessc_shader);
121 }
122 break;
123 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
124 if (pipe_state.pre_raster_state && pipe_state.pre_raster_state->tesse_shader) {
125 stage_states.emplace_back(pipe_state.pre_raster_state->tesse_shader_ci,
126 pipe_state.pre_raster_state->tesse_shader);
127 }
128 break;
129 case VK_SHADER_STAGE_GEOMETRY_BIT:
130 if (pipe_state.pre_raster_state && pipe_state.pre_raster_state->geometry_shader) {
131 stage_states.emplace_back(pipe_state.pre_raster_state->geometry_shader_ci,
132 pipe_state.pre_raster_state->geometry_shader);
133 }
134 break;
135 case VK_SHADER_STAGE_FRAGMENT_BIT:
136 if (pipe_state.fragment_shader_state && pipe_state.fragment_shader_state->fragment_shader) {
137 stage_states.emplace_back(pipe_state.fragment_shader_state->fragment_shader_ci.get(),
138 pipe_state.fragment_shader_state->fragment_shader);
139 }
140 break;
141 default:
142 // no-op
143 break;
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600144 }
145 }
146 }
147 return stage_states;
148}
149
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700150// static
151PIPELINE_STATE::ActiveSlotMap PIPELINE_STATE::GetActiveSlots(const StageStateVec &stage_states) {
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600152 PIPELINE_STATE::ActiveSlotMap active_slots;
153 for (const auto &stage : stage_states) {
sfricke-samsungef15e482022-01-26 11:32:49 -0800154 if (stage.entrypoint == stage.module_state->end()) {
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600155 continue;
156 }
157 // Capture descriptor uses for the pipeline
158 for (const auto &use : stage.descriptor_uses) {
159 // While validating shaders capture which slots are used by the pipeline
160 auto &entry = active_slots[use.first.set][use.first.binding];
161 entry.is_writable |= use.second.is_writable;
162
163 auto &reqs = entry.reqs;
sfricke-samsungef15e482022-01-26 11:32:49 -0800164 reqs |= stage.module_state->DescriptorTypeToReqs(use.second.type_id);
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600165 if (use.second.is_atomic_operation) reqs |= DESCRIPTOR_REQ_VIEW_ATOMIC_OPERATION;
166 if (use.second.is_sampler_implicitLod_dref_proj) reqs |= DESCRIPTOR_REQ_SAMPLER_IMPLICITLOD_DREF_PROJ;
167 if (use.second.is_sampler_bias_offset) reqs |= DESCRIPTOR_REQ_SAMPLER_BIAS_OFFSET;
Lionel Landwerlinbc7401b2021-12-07 15:43:05 +0200168 if (use.second.is_read_without_format) reqs |= DESCRIPTOR_REQ_IMAGE_READ_WITHOUT_FORMAT;
169 if (use.second.is_write_without_format) reqs |= DESCRIPTOR_REQ_IMAGE_WRITE_WITHOUT_FORMAT;
Lionel Landwerlincdbe8682021-12-08 15:10:37 +0200170 if (use.second.is_dref_operation) reqs |= DESCRIPTOR_REQ_IMAGE_DREF;
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600171
172 if (use.second.samplers_used_by_image.size()) {
173 if (use.second.samplers_used_by_image.size() > entry.samplers_used_by_image.size()) {
174 entry.samplers_used_by_image.resize(use.second.samplers_used_by_image.size());
175 }
176 uint32_t image_index = 0;
177 for (const auto &samplers : use.second.samplers_used_by_image) {
178 for (const auto &sampler : samplers) {
Jeremy Gebben856b8c62021-12-01 15:20:07 -0700179 entry.samplers_used_by_image[image_index].emplace(sampler);
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600180 }
181 ++image_index;
182 }
183 }
184 }
185 }
186 return active_slots;
187}
188
189static uint32_t GetMaxActiveSlot(const PIPELINE_STATE::ActiveSlotMap &active_slots) {
190 uint32_t max_active_slot = 0;
191 for (const auto &entry : active_slots) {
192 max_active_slot = std::max(max_active_slot, entry.first);
193 }
194 return max_active_slot;
195}
196
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700197static uint32_t GetActiveShaders(const PIPELINE_STATE::StageStateVec &stages) {
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600198 uint32_t result = 0;
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700199 for (const auto &stage : stages) {
200 result |= stage.stage_flag;
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600201 }
202 return result;
203}
204
Tony-LunarG1672d002022-08-03 14:35:34 -0600205static bool UsesShaderModuleId(const PIPELINE_STATE::StageStateVec &stages) {
206 bool result = false;
207 for (const auto &stage : stages) {
208 const auto module_id_info = LvlFindInChain<VkPipelineShaderStageModuleIdentifierCreateInfoEXT>(stage.create_info->pNext);
209 if (module_id_info) result |= (module_id_info->identifierSize > 0);
210 }
211 return result;
212}
213
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600214static layer_data::unordered_set<uint32_t> GetFSOutputLocations(const PIPELINE_STATE::StageStateVec &stage_states) {
215 layer_data::unordered_set<uint32_t> result;
216 for (const auto &stage : stage_states) {
sfricke-samsungef15e482022-01-26 11:32:49 -0800217 if (stage.entrypoint == stage.module_state->end()) {
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600218 continue;
219 }
220 if (stage.stage_flag == VK_SHADER_STAGE_FRAGMENT_BIT) {
sfricke-samsungef15e482022-01-26 11:32:49 -0800221 result = stage.module_state->CollectWritableOutputLocationinFS(stage.entrypoint);
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600222 break;
223 }
224 }
225 return result;
226}
227
228static VkPrimitiveTopology GetTopologyAtRasterizer(const PIPELINE_STATE::StageStateVec &stage_states,
229 const safe_VkPipelineInputAssemblyStateCreateInfo *assembly_state) {
230 VkPrimitiveTopology result = assembly_state ? assembly_state->topology : static_cast<VkPrimitiveTopology>(0);
231 for (const auto &stage : stage_states) {
sfricke-samsungef15e482022-01-26 11:32:49 -0800232 if (stage.entrypoint == stage.module_state->end()) {
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600233 continue;
234 }
sfricke-samsungef15e482022-01-26 11:32:49 -0800235 auto stage_topo = stage.module_state->GetTopology(stage.entrypoint);
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600236 if (stage_topo) {
237 result = *stage_topo;
238 }
239 }
240 return result;
241}
242
Nathaniel Cesario52398442022-02-15 16:33:46 -0700243// static
Nathaniel Cesarioef6e2052022-02-28 14:09:45 -0700244std::shared_ptr<VertexInputState> PIPELINE_STATE::CreateVertexInputState(const PIPELINE_STATE &p,
245 const ValidationStateTracker &state,
Nathaniel Cesario52398442022-02-15 16:33:46 -0700246 const safe_VkGraphicsPipelineCreateInfo &create_info) {
247 const auto lib_type = GetGraphicsLibType(create_info);
248 if (lib_type & VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT) { // Vertex input graphics library
Nathaniel Cesarioef6e2052022-02-28 14:09:45 -0700249 return std::make_shared<VertexInputState>(p, create_info);
Nathaniel Cesario52398442022-02-15 16:33:46 -0700250 }
251
252 const auto link_info = LvlFindInChain<VkPipelineLibraryCreateInfoKHR>(create_info.pNext);
253 if (link_info) {
Nathaniel Cesario0f5906a2022-04-05 11:10:18 -0600254 auto ss = GetLibSubState<VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT>(state, *link_info);
Nathaniel Cesario52398442022-02-15 16:33:46 -0700255 if (ss) {
256 return ss;
257 }
Nathaniel Cesariofe8d7862022-02-16 17:27:29 -0700258 } else {
259 if (lib_type == static_cast<VkGraphicsPipelineLibraryFlagsEXT>(0)) { // Not a graphics library
Nathaniel Cesarioef6e2052022-02-28 14:09:45 -0700260 return std::make_shared<VertexInputState>(p, create_info);
Nathaniel Cesariofe8d7862022-02-16 17:27:29 -0700261 }
Nathaniel Cesario52398442022-02-15 16:33:46 -0700262 }
263
264 // We shouldn't get here...
265 return {};
266}
267
268// static
Nathaniel Cesarioef6e2052022-02-28 14:09:45 -0700269std::shared_ptr<PreRasterState> PIPELINE_STATE::CreatePreRasterState(const PIPELINE_STATE &p, const ValidationStateTracker &state,
Nathaniel Cesario711be932022-03-15 13:08:00 -0600270 const safe_VkGraphicsPipelineCreateInfo &create_info,
271 std::shared_ptr<const RENDER_PASS_STATE> rp) {
Nathaniel Cesario52398442022-02-15 16:33:46 -0700272 const auto lib_type = GetGraphicsLibType(create_info);
273 if (lib_type & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) { // Pre-raster graphics library
Nathaniel Cesario711be932022-03-15 13:08:00 -0600274 return std::make_shared<PreRasterState>(p, state, create_info, rp);
Nathaniel Cesario52398442022-02-15 16:33:46 -0700275 }
276
277 const auto link_info = LvlFindInChain<VkPipelineLibraryCreateInfoKHR>(create_info.pNext);
278 if (link_info) {
Nathaniel Cesario0f5906a2022-04-05 11:10:18 -0600279 auto ss = GetLibSubState<VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT>(state, *link_info);
Nathaniel Cesario52398442022-02-15 16:33:46 -0700280 if (ss) {
281 return ss;
282 }
Nathaniel Cesariofe8d7862022-02-16 17:27:29 -0700283 } else {
284 if (lib_type == static_cast<VkGraphicsPipelineLibraryFlagsEXT>(0)) { // Not a graphics library
Nathaniel Cesario711be932022-03-15 13:08:00 -0600285 return std::make_shared<PreRasterState>(p, state, create_info, rp);
Nathaniel Cesariofe8d7862022-02-16 17:27:29 -0700286 }
Nathaniel Cesario52398442022-02-15 16:33:46 -0700287 }
288
289 // We shouldn't get here...
290 return {};
291}
292
293// static
294std::shared_ptr<FragmentShaderState> PIPELINE_STATE::CreateFragmentShaderState(
Nathaniel Cesarioef6e2052022-02-28 14:09:45 -0700295 const PIPELINE_STATE &p, const ValidationStateTracker &state, const VkGraphicsPipelineCreateInfo &create_info,
Nathaniel Cesario711be932022-03-15 13:08:00 -0600296 const safe_VkGraphicsPipelineCreateInfo &safe_create_info, std::shared_ptr<const RENDER_PASS_STATE> rp) {
Nathaniel Cesario52398442022-02-15 16:33:46 -0700297 const auto lib_type = GetGraphicsLibType(create_info);
298 if (lib_type & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) { // Fragment shader graphics library
Nathaniel Cesario711be932022-03-15 13:08:00 -0600299 return std::make_shared<FragmentShaderState>(p, state, create_info, rp);
Nathaniel Cesario52398442022-02-15 16:33:46 -0700300 }
301
302 const auto link_info = LvlFindInChain<VkPipelineLibraryCreateInfoKHR>(create_info.pNext);
303 if (link_info) {
Nathaniel Cesario0f5906a2022-04-05 11:10:18 -0600304 auto ss = GetLibSubState<VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT>(state, *link_info);
Nathaniel Cesario52398442022-02-15 16:33:46 -0700305 if (ss) {
306 return ss;
307 }
Nathaniel Cesariofe8d7862022-02-16 17:27:29 -0700308 } else {
309 if (lib_type == static_cast<VkGraphicsPipelineLibraryFlagsEXT>(0)) { // Not a graphics library
Nathaniel Cesario711be932022-03-15 13:08:00 -0600310 return std::make_shared<FragmentShaderState>(p, state, safe_create_info, rp);
Nathaniel Cesariofe8d7862022-02-16 17:27:29 -0700311 }
Nathaniel Cesario52398442022-02-15 16:33:46 -0700312 }
313
314 // We shouldn't get here...
315 return {};
316}
317
318// static
319// Pointers that should be ignored have been set to null in safe_create_info, but if this is a graphics library we need the "raw"
320// create_info.
321std::shared_ptr<FragmentOutputState> PIPELINE_STATE::CreateFragmentOutputState(
Nathaniel Cesarioef6e2052022-02-28 14:09:45 -0700322 const PIPELINE_STATE &p, const ValidationStateTracker &state, const VkGraphicsPipelineCreateInfo &create_info,
Nathaniel Cesario711be932022-03-15 13:08:00 -0600323 const safe_VkGraphicsPipelineCreateInfo &safe_create_info, std::shared_ptr<const RENDER_PASS_STATE> rp) {
Nathaniel Cesario52398442022-02-15 16:33:46 -0700324 const auto lib_type = GetGraphicsLibType(create_info);
325 if (lib_type & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT) { // Fragment output graphics library
Nathaniel Cesario711be932022-03-15 13:08:00 -0600326 return std::make_shared<FragmentOutputState>(p, create_info, rp);
Nathaniel Cesario52398442022-02-15 16:33:46 -0700327 }
328
329 const auto link_info = LvlFindInChain<VkPipelineLibraryCreateInfoKHR>(create_info.pNext);
330 if (link_info) {
Nathaniel Cesario0f5906a2022-04-05 11:10:18 -0600331 auto ss = GetLibSubState<VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT>(state, *link_info);
Nathaniel Cesario52398442022-02-15 16:33:46 -0700332 if (ss) {
333 return ss;
334 }
Nathaniel Cesariofe8d7862022-02-16 17:27:29 -0700335 } else {
336 if (lib_type == static_cast<VkGraphicsPipelineLibraryFlagsEXT>(0)) { // Not a graphics library
Nathaniel Cesario711be932022-03-15 13:08:00 -0600337 return std::make_shared<FragmentOutputState>(p, safe_create_info, rp);
Nathaniel Cesariofe8d7862022-02-16 17:27:29 -0700338 }
Nathaniel Cesario52398442022-02-15 16:33:46 -0700339 }
340
341 // We shouldn't get here...
342 return {};
343}
344
Nathaniel Cesario41f7c802022-03-01 14:28:58 -0700345template <typename Substate>
346void AppendDynamicStateFromSubstate(const Substate &substate, std::vector<VkDynamicState> &dyn_states,
347 VkPipelineDynamicStateCreateFlags &flags) {
348 if (substate) {
349 const auto *dyn_state = substate->parent.DynamicState();
350 if (dyn_state) {
351 flags |= dyn_state->flags;
352 for (uint32_t i = 0; i < dyn_state->dynamicStateCount; ++i) {
353 const auto itr = std::find(dyn_states.cbegin(), dyn_states.cend(), dyn_state->pDynamicStates[i]);
354 if (itr == dyn_states.cend()) {
355 dyn_states.emplace_back(dyn_state->pDynamicStates[i]);
356 }
357 }
358 }
359 }
360}
361
Nathaniel Cesariocb17f982022-06-02 15:33:49 -0600362std::vector<std::shared_ptr<const PIPELINE_LAYOUT_STATE>> PIPELINE_STATE::PipelineLayoutStateUnion() const {
363 std::vector<std::shared_ptr<const PIPELINE_LAYOUT_STATE>> ret;
364 ret.reserve(2);
365 // Only need to check pre-raster _or_ fragment shader layout; if either one is not merged_graphics_layout, then
366 // merged_graphics_layout is a union
367 if (pre_raster_state) {
368 if (pre_raster_state->pipeline_layout != fragment_shader_state->pipeline_layout) {
369 return {pre_raster_state->pipeline_layout, fragment_shader_state->pipeline_layout};
370 } else {
371 return {pre_raster_state->pipeline_layout};
372 }
373 }
374 return {merged_graphics_layout};
375}
376
Nathaniel Cesariod4d8fce2022-05-06 15:01:10 -0600377template <>
378VkPipeline PIPELINE_STATE::BasePipeline<VkGraphicsPipelineCreateInfo>() const {
379 assert(create_info.graphics.sType == VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO);
380 return create_info.graphics.basePipelineHandle;
381}
382template <>
383VkPipeline PIPELINE_STATE::BasePipeline<VkComputePipelineCreateInfo>() const {
384 assert(create_info.compute.sType == VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO);
385 return create_info.compute.basePipelineHandle;
386}
387template <>
388VkPipeline PIPELINE_STATE::BasePipeline<VkRayTracingPipelineCreateInfoKHR>() const {
389 assert(create_info.raytracing.sType == VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR);
390 return create_info.raytracing.basePipelineHandle;
391}
392template <>
393VkPipeline PIPELINE_STATE::BasePipeline<VkRayTracingPipelineCreateInfoNV>() const {
394 assert(create_info.raytracing.sType == VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV);
395 return create_info.raytracing.basePipelineHandle;
396}
397
398template <>
399int32_t PIPELINE_STATE::BasePipelineIndex<VkGraphicsPipelineCreateInfo>() const {
400 assert(create_info.graphics.sType == VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO);
401 return create_info.graphics.basePipelineIndex;
402}
403template <>
404int32_t PIPELINE_STATE::BasePipelineIndex<VkComputePipelineCreateInfo>() const {
405 assert(create_info.compute.sType == VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO);
406 return create_info.compute.basePipelineIndex;
407}
408template <>
409int32_t PIPELINE_STATE::BasePipelineIndex<VkRayTracingPipelineCreateInfoKHR>() const {
410 assert(create_info.raytracing.sType == VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR);
411 return create_info.raytracing.basePipelineIndex;
412}
413template <>
414int32_t PIPELINE_STATE::BasePipelineIndex<VkRayTracingPipelineCreateInfoNV>() const {
415 assert(create_info.raytracing.sType == VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV);
416 return create_info.raytracing.basePipelineIndex;
417}
418
419template <>
420VkShaderModule PIPELINE_STATE::PIPELINE_STATE::GetShaderModuleByCIIndex<VkGraphicsPipelineCreateInfo>(uint32_t i) {
421 assert(create_info.graphics.sType == VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO);
422 return create_info.graphics.pStages[i].module;
423}
424template <>
425VkShaderModule PIPELINE_STATE::GetShaderModuleByCIIndex<VkComputePipelineCreateInfo>(uint32_t) {
426 assert(create_info.compute.sType == VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO);
427 return create_info.compute.stage.module;
428}
429template <>
430VkShaderModule PIPELINE_STATE::GetShaderModuleByCIIndex<VkRayTracingPipelineCreateInfoKHR>(uint32_t i) {
431 assert(create_info.raytracing.sType == VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR);
432 return create_info.raytracing.pStages[i].module;
433}
434template <>
435VkShaderModule PIPELINE_STATE::GetShaderModuleByCIIndex<VkRayTracingPipelineCreateInfoNV>(uint32_t i) {
436 assert(create_info.raytracing.sType == VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV);
437 return create_info.raytracing.pStages[i].module;
438}
439
Jeremy Gebben11af9792021-08-20 10:20:09 -0600440PIPELINE_STATE::PIPELINE_STATE(const ValidationStateTracker *state_data, const VkGraphicsPipelineCreateInfo *pCreateInfo,
441 std::shared_ptr<const RENDER_PASS_STATE> &&rpstate,
442 std::shared_ptr<const PIPELINE_LAYOUT_STATE> &&layout)
443 : BASE_NODE(static_cast<VkPipeline>(VK_NULL_HANDLE), kVulkanObjectTypePipeline),
Nathaniel Cesario711be932022-03-15 13:08:00 -0600444 rp_state(rpstate),
amhagana448ea52021-11-02 14:09:14 -0400445 create_info(pCreateInfo, rpstate),
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700446 graphics_lib_type(GetGraphicsLibType(create_info.graphics)),
Nathaniel Cesarioef6e2052022-02-28 14:09:45 -0700447 vertex_input_state(CreateVertexInputState(*this, *state_data, create_info.graphics)),
Nathaniel Cesario711be932022-03-15 13:08:00 -0600448 pre_raster_state(CreatePreRasterState(*this, *state_data, create_info.graphics, rpstate)),
449 fragment_shader_state(CreateFragmentShaderState(*this, *state_data, *pCreateInfo, create_info.graphics, rpstate)),
450 fragment_output_state(CreateFragmentOutputState(*this, *state_data, *pCreateInfo, create_info.graphics, rpstate)),
ziga-lunargeb65bdb2022-04-29 15:24:21 +0200451 rendering_create_info(LvlFindInChain<VkPipelineRenderingCreateInfo>(PNext())),
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700452 stage_state(GetStageStates(*state_data, *this)),
453 fragmentShader_writable_output_location_list(GetFSOutputLocations(stage_state)),
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600454 active_slots(GetActiveSlots(stage_state)),
455 max_active_slot(GetMaxActiveSlot(active_slots)),
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700456 active_shaders(GetActiveShaders(stage_state)),
Tony-LunarG1672d002022-08-03 14:35:34 -0600457 topology_at_rasterizer(GetTopologyAtRasterizer(stage_state, create_info.graphics.pInputAssemblyState)),
458 uses_shader_module_id(UsesShaderModuleId(stage_state)) {
Nathaniel Cesario81257cb2022-02-16 17:15:58 -0700459 const auto link_info = LvlFindInChain<VkPipelineLibraryCreateInfoKHR>(PNext());
460 if (link_info) {
Nathaniel Cesario41f7c802022-03-01 14:28:58 -0700461 // accumulate dynamic state
462 // TODO is this correct?
463 auto *dyn_state_ci = const_cast<safe_VkPipelineDynamicStateCreateInfo *>(create_info.graphics.pDynamicState);
464 std::vector<VkDynamicState> dyn_states;
Nathaniel Cesarioc4e8f262022-04-02 21:34:30 -0600465 VkPipelineDynamicStateCreateFlags dyn_flags = 0;
Nathaniel Cesario41f7c802022-03-01 14:28:58 -0700466 if (create_info.graphics.pDynamicState) {
467 std::copy(dyn_state_ci->pDynamicStates, dyn_state_ci->pDynamicStates + dyn_state_ci->dynamicStateCount,
468 std::back_inserter(dyn_states));
469 dyn_flags = dyn_state_ci->flags;
470 }
471 AppendDynamicStateFromSubstate(vertex_input_state, dyn_states, dyn_flags);
472 AppendDynamicStateFromSubstate(pre_raster_state, dyn_states, dyn_flags);
473 AppendDynamicStateFromSubstate(fragment_shader_state, dyn_states, dyn_flags);
474 AppendDynamicStateFromSubstate(fragment_output_state, dyn_states, dyn_flags);
475 if (dyn_states.size() > 0) {
476 // We have dynamic state
Nathaniel Cesarioe1113e42022-03-22 14:49:09 -0600477 if (!dyn_state_ci || (dyn_state_ci->dynamicStateCount < dyn_states.size())) {
Nathaniel Cesario41f7c802022-03-01 14:28:58 -0700478 // There is dynamic state defined in libraries that the is not included in this pipeline's create info
Nathaniel Cesarioe1113e42022-03-22 14:49:09 -0600479 if (!dyn_state_ci) {
480 // *All* dynamic state defined is coming from graphics libraries
481 // NOTE: heap allocation cleaned up in ~safe_VkGraphicsPipelineCreateInfo
482 dyn_state_ci = new safe_VkPipelineDynamicStateCreateInfo;
483 const_cast<safe_VkGraphicsPipelineCreateInfo *>(&create_info.graphics)->pDynamicState = dyn_state_ci;
484 }
Nathaniel Cesario41f7c802022-03-01 14:28:58 -0700485 dyn_state_ci->flags = dyn_flags;
486 dyn_state_ci->dynamicStateCount = static_cast<uint32_t>(dyn_states.size());
487 // NOTE: heap allocation cleaned up in ~safe_VkPipelineDynamicStateCreateInfo
488 dyn_state_ci->pDynamicStates = new VkDynamicState[dyn_states.size()];
489 std::copy(&dyn_states.front(), &dyn_states.front() + dyn_states.size(),
490 const_cast<VkDynamicState *>(dyn_state_ci->pDynamicStates));
491 }
492 }
493
Nathaniel Cesario81257cb2022-02-16 17:15:58 -0700494 const auto &exe_layout_state = state_data->Get<PIPELINE_LAYOUT_STATE>(create_info.graphics.layout);
495 const auto *exe_layout = exe_layout_state.get();
496 const auto *pre_raster_layout =
497 (pre_raster_state && pre_raster_state->pipeline_layout) ? pre_raster_state->pipeline_layout.get() : nullptr;
498 const auto *fragment_shader_layout = (fragment_shader_state && fragment_shader_state->pipeline_layout)
499 ? fragment_shader_state->pipeline_layout.get()
500 : nullptr;
501 std::array<decltype(exe_layout), 3> layouts;
Nathaniel Cesario16ba1ec2022-03-16 11:26:47 -0600502 layouts[0] = exe_layout;
Nathaniel Cesario81257cb2022-02-16 17:15:58 -0700503 layouts[1] = fragment_shader_layout;
Nathaniel Cesario16ba1ec2022-03-16 11:26:47 -0600504 layouts[2] = pre_raster_layout;
Nathaniel Cesario81257cb2022-02-16 17:15:58 -0700505 merged_graphics_layout = std::make_shared<PIPELINE_LAYOUT_STATE>(layouts);
Nathaniel Cesariofe8d7862022-02-16 17:27:29 -0700506
507 // TODO Could store the graphics_lib_type in the sub-state rather than searching for it again here.
508 // Or, could store a pointer back to the owning PIPELINE_STATE.
509 for (uint32_t i = 0; i < link_info->libraryCount; ++i) {
510 const auto &state = state_data->Get<PIPELINE_STATE>(link_info->pLibraries[i]);
511 if (state) {
512 graphics_lib_type |= state->graphics_lib_type;
513 }
514 }
Nathaniel Cesario81257cb2022-02-16 17:15:58 -0700515 }
516}
Jeremy Gebbenadb3eb02021-06-15 12:55:19 -0600517
Jeremy Gebben11af9792021-08-20 10:20:09 -0600518PIPELINE_STATE::PIPELINE_STATE(const ValidationStateTracker *state_data, const VkComputePipelineCreateInfo *pCreateInfo,
519 std::shared_ptr<const PIPELINE_LAYOUT_STATE> &&layout)
520 : BASE_NODE(static_cast<VkPipeline>(VK_NULL_HANDLE), kVulkanObjectTypePipeline),
521 create_info(pCreateInfo),
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700522 stage_state(GetStageStates(*state_data, *this)),
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600523 active_slots(GetActiveSlots(stage_state)),
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700524 active_shaders(GetActiveShaders(stage_state)),
525 topology_at_rasterizer{},
Tony-LunarG1672d002022-08-03 14:35:34 -0600526 uses_shader_module_id(UsesShaderModuleId(stage_state)),
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700527 merged_graphics_layout(layout) {
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600528 assert(active_shaders == VK_SHADER_STAGE_COMPUTE_BIT);
Jeremy Gebbenadb3eb02021-06-15 12:55:19 -0600529}
530
Nathaniel Cesarioc8c11c12022-02-16 17:23:50 -0700531PIPELINE_STATE::PIPELINE_STATE(const ValidationStateTracker *state_data, const VkRayTracingPipelineCreateInfoKHR *pCreateInfo,
532 std::shared_ptr<const PIPELINE_LAYOUT_STATE> &&layout)
533 : BASE_NODE(static_cast<VkPipeline>(VK_NULL_HANDLE), kVulkanObjectTypePipeline),
534 create_info(pCreateInfo),
535 stage_state(GetStageStates(*state_data, *this)),
536 active_slots(GetActiveSlots(stage_state)),
537 active_shaders(GetActiveShaders(stage_state)),
538 topology_at_rasterizer{},
Tony-LunarG1672d002022-08-03 14:35:34 -0600539 uses_shader_module_id(UsesShaderModuleId(stage_state)),
Nathaniel Cesarioc8c11c12022-02-16 17:23:50 -0700540 merged_graphics_layout(std::move(layout)) {
541 assert(0 == (active_shaders &
542 ~(VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR |
543 VK_SHADER_STAGE_MISS_BIT_KHR | VK_SHADER_STAGE_INTERSECTION_BIT_KHR | VK_SHADER_STAGE_CALLABLE_BIT_KHR)));
544}
545
Jeremy Gebben20da7a12022-02-25 14:07:46 -0700546PIPELINE_STATE::PIPELINE_STATE(const ValidationStateTracker *state_data, const VkRayTracingPipelineCreateInfoNV *pCreateInfo,
Jeremy Gebben11af9792021-08-20 10:20:09 -0600547 std::shared_ptr<const PIPELINE_LAYOUT_STATE> &&layout)
548 : BASE_NODE(static_cast<VkPipeline>(VK_NULL_HANDLE), kVulkanObjectTypePipeline),
549 create_info(pCreateInfo),
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700550 stage_state(GetStageStates(*state_data, *this)),
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600551 active_slots(GetActiveSlots(stage_state)),
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700552 active_shaders(GetActiveShaders(stage_state)),
553 topology_at_rasterizer{},
Tony-LunarG1672d002022-08-03 14:35:34 -0600554 uses_shader_module_id(UsesShaderModuleId(stage_state)),
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700555 merged_graphics_layout(std::move(layout)) {
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600556 assert(0 == (active_shaders &
557 ~(VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR |
558 VK_SHADER_STAGE_MISS_BIT_KHR | VK_SHADER_STAGE_INTERSECTION_BIT_KHR | VK_SHADER_STAGE_CALLABLE_BIT_KHR)));
Jeremy Gebbenadb3eb02021-06-15 12:55:19 -0600559}
560
Jeremy Gebbenf087ddb2022-08-04 09:36:17 -0600561void LAST_BOUND_STATE::UnbindAndResetPushDescriptorSet(std::shared_ptr<cvdescriptorset::DescriptorSet> &&ds) {
Jeremy Gebbenadb3eb02021-06-15 12:55:19 -0600562 if (push_descriptor_set) {
563 for (auto &ps : per_set) {
Jeremy Gebben4d51c552022-01-06 21:27:15 -0700564 if (ps.bound_descriptor_set == push_descriptor_set) {
Jeremy Gebbenf087ddb2022-08-04 09:36:17 -0600565 cb_state.RemoveChild(ps.bound_descriptor_set);
Jeremy Gebben4d51c552022-01-06 21:27:15 -0700566 ps.bound_descriptor_set.reset();
Jeremy Gebbenadb3eb02021-06-15 12:55:19 -0600567 }
568 }
569 }
Jeremy Gebbenf087ddb2022-08-04 09:36:17 -0600570 cb_state.AddChild(ds);
Jeremy Gebben4d51c552022-01-06 21:27:15 -0700571 push_descriptor_set = std::move(ds);
Jeremy Gebbenadb3eb02021-06-15 12:55:19 -0600572}
573
574void LAST_BOUND_STATE::Reset() {
575 pipeline_state = nullptr;
576 pipeline_layout = VK_NULL_HANDLE;
577 if (push_descriptor_set) {
Jeremy Gebbenf087ddb2022-08-04 09:36:17 -0600578 cb_state.RemoveChild(push_descriptor_set);
Jeremy Gebben4d51c552022-01-06 21:27:15 -0700579 push_descriptor_set->Destroy();
Jeremy Gebbenadb3eb02021-06-15 12:55:19 -0600580 }
Jeremy Gebben4d51c552022-01-06 21:27:15 -0700581 push_descriptor_set.reset();
Jeremy Gebbenadb3eb02021-06-15 12:55:19 -0600582 per_set.clear();
583}