blob: fe6e620146b7af61777b0f047f7a4abfe002e17e [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)),
sfricke-samsungef15e482022-01-26 11:32:49 -080072 wrote_primitive_shading_rate(WrotePrimitiveShadingRate(stage_flag, entrypoint, module_state.get())) {}
Jeremy Gebben84b838b2021-08-23 08:41:39 -060073
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -070074// static
75PIPELINE_STATE::StageStateVec PIPELINE_STATE::GetStageStates(const ValidationStateTracker &state_data,
76 const PIPELINE_STATE &pipe_state) {
Jeremy Gebben84b838b2021-08-23 08:41:39 -060077 PIPELINE_STATE::StageStateVec stage_states;
Jeremy Gebben84b838b2021-08-23 08:41:39 -060078 // shader stages need to be recorded in pipeline order
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -070079 const auto stages = pipe_state.GetShaderStages();
80
Jeremy Gebben84b838b2021-08-23 08:41:39 -060081 for (uint32_t stage_idx = 0; stage_idx < 32; ++stage_idx) {
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -070082 bool stage_found = false;
83 const auto stage = static_cast<VkShaderStageFlagBits>(1 << stage_idx);
84 for (const auto &shader_stage : stages) {
85 if (shader_stage.stage == stage) {
86 auto module = state_data.Get<SHADER_MODULE_STATE>(shader_stage.module);
87 if (!module) {
88 // If module is null and there is a VkShaderModuleCreateInfo in the pNext chain of the stage info, then this
89 // module is part of a library and the state must be created
90 const auto shader_ci = LvlFindInChain<VkShaderModuleCreateInfo>(shader_stage.pNext);
91 if (shader_ci) {
92 const uint32_t unique_shader_id = 0; // TODO GPU-AV rework required to get this value properly
93 module = state_data.CreateShaderModuleState(*shader_ci, unique_shader_id);
94 } else {
95 // TODO This should be an error of some sort. Just assert for now
96 assert(false);
97 }
98 }
99 stage_states.emplace_back(&shader_stage, module);
100 stage_found = true;
101 }
102 }
103 if (!stage_found) {
104 // Check if stage has been supplied by a library
105 switch (stage) {
106 case VK_SHADER_STAGE_VERTEX_BIT:
107 if (pipe_state.pre_raster_state && pipe_state.pre_raster_state->vertex_shader) {
108 stage_states.emplace_back(pipe_state.pre_raster_state->vertex_shader_ci,
109 pipe_state.pre_raster_state->vertex_shader);
110 }
111 break;
112 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
113 if (pipe_state.pre_raster_state && pipe_state.pre_raster_state->tessc_shader) {
114 stage_states.emplace_back(pipe_state.pre_raster_state->tessc_shader_ci,
115 pipe_state.pre_raster_state->tessc_shader);
116 }
117 break;
118 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
119 if (pipe_state.pre_raster_state && pipe_state.pre_raster_state->tesse_shader) {
120 stage_states.emplace_back(pipe_state.pre_raster_state->tesse_shader_ci,
121 pipe_state.pre_raster_state->tesse_shader);
122 }
123 break;
124 case VK_SHADER_STAGE_GEOMETRY_BIT:
125 if (pipe_state.pre_raster_state && pipe_state.pre_raster_state->geometry_shader) {
126 stage_states.emplace_back(pipe_state.pre_raster_state->geometry_shader_ci,
127 pipe_state.pre_raster_state->geometry_shader);
128 }
129 break;
130 case VK_SHADER_STAGE_FRAGMENT_BIT:
131 if (pipe_state.fragment_shader_state && pipe_state.fragment_shader_state->fragment_shader) {
132 stage_states.emplace_back(pipe_state.fragment_shader_state->fragment_shader_ci.get(),
133 pipe_state.fragment_shader_state->fragment_shader);
134 }
135 break;
136 default:
137 // no-op
138 break;
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600139 }
140 }
141 }
142 return stage_states;
143}
144
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700145// static
146PIPELINE_STATE::ActiveSlotMap PIPELINE_STATE::GetActiveSlots(const StageStateVec &stage_states) {
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600147 PIPELINE_STATE::ActiveSlotMap active_slots;
148 for (const auto &stage : stage_states) {
sfricke-samsungef15e482022-01-26 11:32:49 -0800149 if (stage.entrypoint == stage.module_state->end()) {
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600150 continue;
151 }
152 // Capture descriptor uses for the pipeline
153 for (const auto &use : stage.descriptor_uses) {
154 // While validating shaders capture which slots are used by the pipeline
155 auto &entry = active_slots[use.first.set][use.first.binding];
156 entry.is_writable |= use.second.is_writable;
157
158 auto &reqs = entry.reqs;
sfricke-samsungef15e482022-01-26 11:32:49 -0800159 reqs |= stage.module_state->DescriptorTypeToReqs(use.second.type_id);
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600160 if (use.second.is_atomic_operation) reqs |= DESCRIPTOR_REQ_VIEW_ATOMIC_OPERATION;
161 if (use.second.is_sampler_implicitLod_dref_proj) reqs |= DESCRIPTOR_REQ_SAMPLER_IMPLICITLOD_DREF_PROJ;
162 if (use.second.is_sampler_bias_offset) reqs |= DESCRIPTOR_REQ_SAMPLER_BIAS_OFFSET;
Lionel Landwerlinbc7401b2021-12-07 15:43:05 +0200163 if (use.second.is_read_without_format) reqs |= DESCRIPTOR_REQ_IMAGE_READ_WITHOUT_FORMAT;
164 if (use.second.is_write_without_format) reqs |= DESCRIPTOR_REQ_IMAGE_WRITE_WITHOUT_FORMAT;
Lionel Landwerlincdbe8682021-12-08 15:10:37 +0200165 if (use.second.is_dref_operation) reqs |= DESCRIPTOR_REQ_IMAGE_DREF;
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600166
167 if (use.second.samplers_used_by_image.size()) {
168 if (use.second.samplers_used_by_image.size() > entry.samplers_used_by_image.size()) {
169 entry.samplers_used_by_image.resize(use.second.samplers_used_by_image.size());
170 }
171 uint32_t image_index = 0;
172 for (const auto &samplers : use.second.samplers_used_by_image) {
173 for (const auto &sampler : samplers) {
Jeremy Gebben856b8c62021-12-01 15:20:07 -0700174 entry.samplers_used_by_image[image_index].emplace(sampler);
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600175 }
176 ++image_index;
177 }
178 }
179 }
180 }
181 return active_slots;
182}
183
184static uint32_t GetMaxActiveSlot(const PIPELINE_STATE::ActiveSlotMap &active_slots) {
185 uint32_t max_active_slot = 0;
186 for (const auto &entry : active_slots) {
187 max_active_slot = std::max(max_active_slot, entry.first);
188 }
189 return max_active_slot;
190}
191
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700192static uint32_t GetActiveShaders(const PIPELINE_STATE::StageStateVec &stages) {
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600193 uint32_t result = 0;
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700194 for (const auto &stage : stages) {
195 result |= stage.stage_flag;
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600196 }
197 return result;
198}
199
200static layer_data::unordered_set<uint32_t> GetFSOutputLocations(const PIPELINE_STATE::StageStateVec &stage_states) {
201 layer_data::unordered_set<uint32_t> result;
202 for (const auto &stage : stage_states) {
sfricke-samsungef15e482022-01-26 11:32:49 -0800203 if (stage.entrypoint == stage.module_state->end()) {
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600204 continue;
205 }
206 if (stage.stage_flag == VK_SHADER_STAGE_FRAGMENT_BIT) {
sfricke-samsungef15e482022-01-26 11:32:49 -0800207 result = stage.module_state->CollectWritableOutputLocationinFS(stage.entrypoint);
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600208 break;
209 }
210 }
211 return result;
212}
213
214static VkPrimitiveTopology GetTopologyAtRasterizer(const PIPELINE_STATE::StageStateVec &stage_states,
215 const safe_VkPipelineInputAssemblyStateCreateInfo *assembly_state) {
216 VkPrimitiveTopology result = assembly_state ? assembly_state->topology : static_cast<VkPrimitiveTopology>(0);
217 for (const auto &stage : stage_states) {
sfricke-samsungef15e482022-01-26 11:32:49 -0800218 if (stage.entrypoint == stage.module_state->end()) {
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600219 continue;
220 }
sfricke-samsungef15e482022-01-26 11:32:49 -0800221 auto stage_topo = stage.module_state->GetTopology(stage.entrypoint);
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600222 if (stage_topo) {
223 result = *stage_topo;
224 }
225 }
226 return result;
227}
228
Nathaniel Cesario52398442022-02-15 16:33:46 -0700229// static
Nathaniel Cesarioef6e2052022-02-28 14:09:45 -0700230std::shared_ptr<VertexInputState> PIPELINE_STATE::CreateVertexInputState(const PIPELINE_STATE &p,
231 const ValidationStateTracker &state,
Nathaniel Cesario52398442022-02-15 16:33:46 -0700232 const safe_VkGraphicsPipelineCreateInfo &create_info) {
233 const auto lib_type = GetGraphicsLibType(create_info);
234 if (lib_type & VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT) { // Vertex input graphics library
Nathaniel Cesarioef6e2052022-02-28 14:09:45 -0700235 return std::make_shared<VertexInputState>(p, create_info);
Nathaniel Cesario52398442022-02-15 16:33:46 -0700236 }
237
238 const auto link_info = LvlFindInChain<VkPipelineLibraryCreateInfoKHR>(create_info.pNext);
239 if (link_info) {
Nathaniel Cesario0f5906a2022-04-05 11:10:18 -0600240 auto ss = GetLibSubState<VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT>(state, *link_info);
Nathaniel Cesario52398442022-02-15 16:33:46 -0700241 if (ss) {
242 return ss;
243 }
Nathaniel Cesariofe8d7862022-02-16 17:27:29 -0700244 } else {
245 if (lib_type == static_cast<VkGraphicsPipelineLibraryFlagsEXT>(0)) { // Not a graphics library
Nathaniel Cesarioef6e2052022-02-28 14:09:45 -0700246 return std::make_shared<VertexInputState>(p, create_info);
Nathaniel Cesariofe8d7862022-02-16 17:27:29 -0700247 }
Nathaniel Cesario52398442022-02-15 16:33:46 -0700248 }
249
250 // We shouldn't get here...
251 return {};
252}
253
254// static
Nathaniel Cesarioef6e2052022-02-28 14:09:45 -0700255std::shared_ptr<PreRasterState> PIPELINE_STATE::CreatePreRasterState(const PIPELINE_STATE &p, const ValidationStateTracker &state,
Nathaniel Cesario711be932022-03-15 13:08:00 -0600256 const safe_VkGraphicsPipelineCreateInfo &create_info,
257 std::shared_ptr<const RENDER_PASS_STATE> rp) {
Nathaniel Cesario52398442022-02-15 16:33:46 -0700258 const auto lib_type = GetGraphicsLibType(create_info);
259 if (lib_type & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) { // Pre-raster graphics library
Nathaniel Cesario711be932022-03-15 13:08:00 -0600260 return std::make_shared<PreRasterState>(p, state, create_info, rp);
Nathaniel Cesario52398442022-02-15 16:33:46 -0700261 }
262
263 const auto link_info = LvlFindInChain<VkPipelineLibraryCreateInfoKHR>(create_info.pNext);
264 if (link_info) {
Nathaniel Cesario0f5906a2022-04-05 11:10:18 -0600265 auto ss = GetLibSubState<VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT>(state, *link_info);
Nathaniel Cesario52398442022-02-15 16:33:46 -0700266 if (ss) {
267 return ss;
268 }
Nathaniel Cesariofe8d7862022-02-16 17:27:29 -0700269 } else {
270 if (lib_type == static_cast<VkGraphicsPipelineLibraryFlagsEXT>(0)) { // Not a graphics library
Nathaniel Cesario711be932022-03-15 13:08:00 -0600271 return std::make_shared<PreRasterState>(p, state, create_info, rp);
Nathaniel Cesariofe8d7862022-02-16 17:27:29 -0700272 }
Nathaniel Cesario52398442022-02-15 16:33:46 -0700273 }
274
275 // We shouldn't get here...
276 return {};
277}
278
279// static
280std::shared_ptr<FragmentShaderState> PIPELINE_STATE::CreateFragmentShaderState(
Nathaniel Cesarioef6e2052022-02-28 14:09:45 -0700281 const PIPELINE_STATE &p, const ValidationStateTracker &state, const VkGraphicsPipelineCreateInfo &create_info,
Nathaniel Cesario711be932022-03-15 13:08:00 -0600282 const safe_VkGraphicsPipelineCreateInfo &safe_create_info, std::shared_ptr<const RENDER_PASS_STATE> rp) {
Nathaniel Cesario52398442022-02-15 16:33:46 -0700283 const auto lib_type = GetGraphicsLibType(create_info);
284 if (lib_type & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) { // Fragment shader graphics library
Nathaniel Cesario711be932022-03-15 13:08:00 -0600285 return std::make_shared<FragmentShaderState>(p, state, create_info, rp);
Nathaniel Cesario52398442022-02-15 16:33:46 -0700286 }
287
288 const auto link_info = LvlFindInChain<VkPipelineLibraryCreateInfoKHR>(create_info.pNext);
289 if (link_info) {
Nathaniel Cesario0f5906a2022-04-05 11:10:18 -0600290 auto ss = GetLibSubState<VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT>(state, *link_info);
Nathaniel Cesario52398442022-02-15 16:33:46 -0700291 if (ss) {
292 return ss;
293 }
Nathaniel Cesariofe8d7862022-02-16 17:27:29 -0700294 } else {
295 if (lib_type == static_cast<VkGraphicsPipelineLibraryFlagsEXT>(0)) { // Not a graphics library
Nathaniel Cesario711be932022-03-15 13:08:00 -0600296 return std::make_shared<FragmentShaderState>(p, state, safe_create_info, rp);
Nathaniel Cesariofe8d7862022-02-16 17:27:29 -0700297 }
Nathaniel Cesario52398442022-02-15 16:33:46 -0700298 }
299
300 // We shouldn't get here...
301 return {};
302}
303
304// static
305// 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"
306// create_info.
307std::shared_ptr<FragmentOutputState> PIPELINE_STATE::CreateFragmentOutputState(
Nathaniel Cesarioef6e2052022-02-28 14:09:45 -0700308 const PIPELINE_STATE &p, const ValidationStateTracker &state, const VkGraphicsPipelineCreateInfo &create_info,
Nathaniel Cesario711be932022-03-15 13:08:00 -0600309 const safe_VkGraphicsPipelineCreateInfo &safe_create_info, std::shared_ptr<const RENDER_PASS_STATE> rp) {
Nathaniel Cesario52398442022-02-15 16:33:46 -0700310 const auto lib_type = GetGraphicsLibType(create_info);
311 if (lib_type & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT) { // Fragment output graphics library
Nathaniel Cesario711be932022-03-15 13:08:00 -0600312 return std::make_shared<FragmentOutputState>(p, create_info, rp);
Nathaniel Cesario52398442022-02-15 16:33:46 -0700313 }
314
315 const auto link_info = LvlFindInChain<VkPipelineLibraryCreateInfoKHR>(create_info.pNext);
316 if (link_info) {
Nathaniel Cesario0f5906a2022-04-05 11:10:18 -0600317 auto ss = GetLibSubState<VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT>(state, *link_info);
Nathaniel Cesario52398442022-02-15 16:33:46 -0700318 if (ss) {
319 return ss;
320 }
Nathaniel Cesariofe8d7862022-02-16 17:27:29 -0700321 } else {
322 if (lib_type == static_cast<VkGraphicsPipelineLibraryFlagsEXT>(0)) { // Not a graphics library
Nathaniel Cesario711be932022-03-15 13:08:00 -0600323 return std::make_shared<FragmentOutputState>(p, safe_create_info, rp);
Nathaniel Cesariofe8d7862022-02-16 17:27:29 -0700324 }
Nathaniel Cesario52398442022-02-15 16:33:46 -0700325 }
326
327 // We shouldn't get here...
328 return {};
329}
330
Nathaniel Cesario41f7c802022-03-01 14:28:58 -0700331template <typename Substate>
332void AppendDynamicStateFromSubstate(const Substate &substate, std::vector<VkDynamicState> &dyn_states,
333 VkPipelineDynamicStateCreateFlags &flags) {
334 if (substate) {
335 const auto *dyn_state = substate->parent.DynamicState();
336 if (dyn_state) {
337 flags |= dyn_state->flags;
338 for (uint32_t i = 0; i < dyn_state->dynamicStateCount; ++i) {
339 const auto itr = std::find(dyn_states.cbegin(), dyn_states.cend(), dyn_state->pDynamicStates[i]);
340 if (itr == dyn_states.cend()) {
341 dyn_states.emplace_back(dyn_state->pDynamicStates[i]);
342 }
343 }
344 }
345 }
346}
347
Jeremy Gebben11af9792021-08-20 10:20:09 -0600348PIPELINE_STATE::PIPELINE_STATE(const ValidationStateTracker *state_data, const VkGraphicsPipelineCreateInfo *pCreateInfo,
349 std::shared_ptr<const RENDER_PASS_STATE> &&rpstate,
350 std::shared_ptr<const PIPELINE_LAYOUT_STATE> &&layout)
351 : BASE_NODE(static_cast<VkPipeline>(VK_NULL_HANDLE), kVulkanObjectTypePipeline),
Nathaniel Cesario711be932022-03-15 13:08:00 -0600352 rp_state(rpstate),
amhagana448ea52021-11-02 14:09:14 -0400353 create_info(pCreateInfo, rpstate),
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700354 graphics_lib_type(GetGraphicsLibType(create_info.graphics)),
Nathaniel Cesarioef6e2052022-02-28 14:09:45 -0700355 vertex_input_state(CreateVertexInputState(*this, *state_data, create_info.graphics)),
Nathaniel Cesario711be932022-03-15 13:08:00 -0600356 pre_raster_state(CreatePreRasterState(*this, *state_data, create_info.graphics, rpstate)),
357 fragment_shader_state(CreateFragmentShaderState(*this, *state_data, *pCreateInfo, create_info.graphics, rpstate)),
358 fragment_output_state(CreateFragmentOutputState(*this, *state_data, *pCreateInfo, create_info.graphics, rpstate)),
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700359 stage_state(GetStageStates(*state_data, *this)),
360 fragmentShader_writable_output_location_list(GetFSOutputLocations(stage_state)),
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600361 active_slots(GetActiveSlots(stage_state)),
362 max_active_slot(GetMaxActiveSlot(active_slots)),
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700363 active_shaders(GetActiveShaders(stage_state)),
Nathaniel Cesario711be932022-03-15 13:08:00 -0600364 topology_at_rasterizer(GetTopologyAtRasterizer(stage_state, create_info.graphics.pInputAssemblyState)) {
Nathaniel Cesario81257cb2022-02-16 17:15:58 -0700365 const auto link_info = LvlFindInChain<VkPipelineLibraryCreateInfoKHR>(PNext());
366 if (link_info) {
Nathaniel Cesario41f7c802022-03-01 14:28:58 -0700367 // accumulate dynamic state
368 // TODO is this correct?
369 auto *dyn_state_ci = const_cast<safe_VkPipelineDynamicStateCreateInfo *>(create_info.graphics.pDynamicState);
370 std::vector<VkDynamicState> dyn_states;
371 VkPipelineDynamicStateCreateFlags dyn_flags;
372 if (create_info.graphics.pDynamicState) {
373 std::copy(dyn_state_ci->pDynamicStates, dyn_state_ci->pDynamicStates + dyn_state_ci->dynamicStateCount,
374 std::back_inserter(dyn_states));
375 dyn_flags = dyn_state_ci->flags;
376 }
377 AppendDynamicStateFromSubstate(vertex_input_state, dyn_states, dyn_flags);
378 AppendDynamicStateFromSubstate(pre_raster_state, dyn_states, dyn_flags);
379 AppendDynamicStateFromSubstate(fragment_shader_state, dyn_states, dyn_flags);
380 AppendDynamicStateFromSubstate(fragment_output_state, dyn_states, dyn_flags);
381 if (dyn_states.size() > 0) {
382 // We have dynamic state
383 if (!dyn_state_ci) {
384 // *All* dynamic state defined is coming from graphics libraries
385 // NOTE: heap allocation cleaned up in ~safe_VkGraphicsPipelineCreateInfo
386 dyn_state_ci = new safe_VkPipelineDynamicStateCreateInfo;
387 }
388
389 if (dyn_state_ci->dynamicStateCount < dyn_states.size()) {
390 // There is dynamic state defined in libraries that the is not included in this pipeline's create info
391 dyn_state_ci->flags = dyn_flags;
392 dyn_state_ci->dynamicStateCount = static_cast<uint32_t>(dyn_states.size());
393 // NOTE: heap allocation cleaned up in ~safe_VkPipelineDynamicStateCreateInfo
394 dyn_state_ci->pDynamicStates = new VkDynamicState[dyn_states.size()];
395 std::copy(&dyn_states.front(), &dyn_states.front() + dyn_states.size(),
396 const_cast<VkDynamicState *>(dyn_state_ci->pDynamicStates));
397 }
398 }
399
Nathaniel Cesario81257cb2022-02-16 17:15:58 -0700400 const auto &exe_layout_state = state_data->Get<PIPELINE_LAYOUT_STATE>(create_info.graphics.layout);
401 const auto *exe_layout = exe_layout_state.get();
402 const auto *pre_raster_layout =
403 (pre_raster_state && pre_raster_state->pipeline_layout) ? pre_raster_state->pipeline_layout.get() : nullptr;
404 const auto *fragment_shader_layout = (fragment_shader_state && fragment_shader_state->pipeline_layout)
405 ? fragment_shader_state->pipeline_layout.get()
406 : nullptr;
407 std::array<decltype(exe_layout), 3> layouts;
408 layouts[0] = pre_raster_layout;
409 layouts[1] = fragment_shader_layout;
410 layouts[2] = exe_layout;
411 merged_graphics_layout = std::make_shared<PIPELINE_LAYOUT_STATE>(layouts);
Nathaniel Cesariofe8d7862022-02-16 17:27:29 -0700412
413 // TODO Could store the graphics_lib_type in the sub-state rather than searching for it again here.
414 // Or, could store a pointer back to the owning PIPELINE_STATE.
415 for (uint32_t i = 0; i < link_info->libraryCount; ++i) {
416 const auto &state = state_data->Get<PIPELINE_STATE>(link_info->pLibraries[i]);
417 if (state) {
418 graphics_lib_type |= state->graphics_lib_type;
419 }
420 }
Nathaniel Cesario81257cb2022-02-16 17:15:58 -0700421 }
422}
Jeremy Gebbenadb3eb02021-06-15 12:55:19 -0600423
Jeremy Gebben11af9792021-08-20 10:20:09 -0600424PIPELINE_STATE::PIPELINE_STATE(const ValidationStateTracker *state_data, const VkComputePipelineCreateInfo *pCreateInfo,
425 std::shared_ptr<const PIPELINE_LAYOUT_STATE> &&layout)
426 : BASE_NODE(static_cast<VkPipeline>(VK_NULL_HANDLE), kVulkanObjectTypePipeline),
427 create_info(pCreateInfo),
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700428 stage_state(GetStageStates(*state_data, *this)),
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600429 active_slots(GetActiveSlots(stage_state)),
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700430 active_shaders(GetActiveShaders(stage_state)),
431 topology_at_rasterizer{},
432 merged_graphics_layout(layout) {
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600433 assert(active_shaders == VK_SHADER_STAGE_COMPUTE_BIT);
Jeremy Gebbenadb3eb02021-06-15 12:55:19 -0600434}
435
Nathaniel Cesarioc8c11c12022-02-16 17:23:50 -0700436PIPELINE_STATE::PIPELINE_STATE(const ValidationStateTracker *state_data, const VkRayTracingPipelineCreateInfoKHR *pCreateInfo,
437 std::shared_ptr<const PIPELINE_LAYOUT_STATE> &&layout)
438 : BASE_NODE(static_cast<VkPipeline>(VK_NULL_HANDLE), kVulkanObjectTypePipeline),
439 create_info(pCreateInfo),
440 stage_state(GetStageStates(*state_data, *this)),
441 active_slots(GetActiveSlots(stage_state)),
442 active_shaders(GetActiveShaders(stage_state)),
443 topology_at_rasterizer{},
444 merged_graphics_layout(std::move(layout)) {
445 assert(0 == (active_shaders &
446 ~(VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR |
447 VK_SHADER_STAGE_MISS_BIT_KHR | VK_SHADER_STAGE_INTERSECTION_BIT_KHR | VK_SHADER_STAGE_CALLABLE_BIT_KHR)));
448}
449
Jeremy Gebben20da7a12022-02-25 14:07:46 -0700450PIPELINE_STATE::PIPELINE_STATE(const ValidationStateTracker *state_data, const VkRayTracingPipelineCreateInfoNV *pCreateInfo,
Jeremy Gebben11af9792021-08-20 10:20:09 -0600451 std::shared_ptr<const PIPELINE_LAYOUT_STATE> &&layout)
452 : BASE_NODE(static_cast<VkPipeline>(VK_NULL_HANDLE), kVulkanObjectTypePipeline),
453 create_info(pCreateInfo),
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700454 stage_state(GetStageStates(*state_data, *this)),
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600455 active_slots(GetActiveSlots(stage_state)),
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700456 active_shaders(GetActiveShaders(stage_state)),
457 topology_at_rasterizer{},
458 merged_graphics_layout(std::move(layout)) {
Jeremy Gebben84b838b2021-08-23 08:41:39 -0600459 assert(0 == (active_shaders &
460 ~(VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR |
461 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 -0600462}
463
Jeremy Gebben4d51c552022-01-06 21:27:15 -0700464void LAST_BOUND_STATE::UnbindAndResetPushDescriptorSet(CMD_BUFFER_STATE *cb_state,
465 std::shared_ptr<cvdescriptorset::DescriptorSet> &&ds) {
Jeremy Gebbenadb3eb02021-06-15 12:55:19 -0600466 if (push_descriptor_set) {
467 for (auto &ps : per_set) {
Jeremy Gebben4d51c552022-01-06 21:27:15 -0700468 if (ps.bound_descriptor_set == push_descriptor_set) {
Jeremy Gebben610d3a62022-01-01 12:53:17 -0700469 cb_state->RemoveChild(ps.bound_descriptor_set);
Jeremy Gebben4d51c552022-01-06 21:27:15 -0700470 ps.bound_descriptor_set.reset();
Jeremy Gebbenadb3eb02021-06-15 12:55:19 -0600471 }
472 }
473 }
474 cb_state->AddChild(ds);
Jeremy Gebben4d51c552022-01-06 21:27:15 -0700475 push_descriptor_set = std::move(ds);
Jeremy Gebbenadb3eb02021-06-15 12:55:19 -0600476}
477
478void LAST_BOUND_STATE::Reset() {
479 pipeline_state = nullptr;
480 pipeline_layout = VK_NULL_HANDLE;
481 if (push_descriptor_set) {
Jeremy Gebben4d51c552022-01-06 21:27:15 -0700482 push_descriptor_set->Destroy();
Jeremy Gebbenadb3eb02021-06-15 12:55:19 -0600483 }
Jeremy Gebben4d51c552022-01-06 21:27:15 -0700484 push_descriptor_set.reset();
Jeremy Gebbenadb3eb02021-06-15 12:55:19 -0600485 per_set.clear();
486}