blob: 59d215445c318bea78b908961404a1f9f878ca6d [file] [log] [blame]
Nathaniel Cesario9ee6c572022-04-06 10:56:19 -06001/* Copyright (c) 2015-2017, 2019-2022 The Khronos Group Inc.
2 * Copyright (c) 2015-2017, 2019-2022 Valve Corporation
3 * Copyright (c) 2015-2017, 2019-2022 LunarG, Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * Author: Nathaniel Cesario <nathaniel@lunarg.com>
18 */
19
Nathaniel Cesario52398442022-02-15 16:33:46 -070020#include "pipeline_sub_state.h"
21
22#include "state_tracker.h"
23
Nathaniel Cesarioef6e2052022-02-28 14:09:45 -070024VertexInputState::VertexInputState(const PIPELINE_STATE &p, const safe_VkGraphicsPipelineCreateInfo &create_info)
25 : parent(p), input_state(create_info.pVertexInputState), input_assembly_state(create_info.pInputAssemblyState) {
Nathaniel Cesario52398442022-02-15 16:33:46 -070026 if (create_info.pVertexInputState) {
27 const auto *vici = create_info.pVertexInputState;
28 if (vici->vertexBindingDescriptionCount) {
29 const auto count = vici->vertexBindingDescriptionCount;
30 binding_descriptions.reserve(count);
31 binding_to_index_map.reserve(count);
32
33 for (uint32_t i = 0; i < count; i++) {
34 binding_descriptions.emplace_back(vici->pVertexBindingDescriptions[i]);
35 binding_to_index_map[binding_descriptions.back().binding] = i;
36 }
37 }
38
39 if (vici->vertexAttributeDescriptionCount) {
40 vertex_attribute_descriptions.reserve(vici->vertexAttributeDescriptionCount);
41 std::copy(vici->pVertexAttributeDescriptions,
42 vici->pVertexAttributeDescriptions + vici->vertexAttributeDescriptionCount,
43 std::back_inserter(vertex_attribute_descriptions));
44 }
45
46 vertex_attribute_alignments.reserve(vertex_attribute_descriptions.size());
47 for (const auto &attr : vertex_attribute_descriptions) {
48 VkDeviceSize vtx_attrib_req_alignment = FormatElementSize(attr.format);
49 if (FormatElementIsTexel(attr.format)) {
50 vtx_attrib_req_alignment = SafeDivision(vtx_attrib_req_alignment, FormatComponentCount(attr.format));
51 }
52 vertex_attribute_alignments.push_back(vtx_attrib_req_alignment);
53 }
54 }
55}
56
Nathaniel Cesarioef6e2052022-02-28 14:09:45 -070057PreRasterState::PreRasterState(const PIPELINE_STATE &p, const ValidationStateTracker &dev_data,
58 const safe_VkGraphicsPipelineCreateInfo &create_info)
59 : parent(p), subpass(create_info.subpass) {
Nathaniel Cesario52398442022-02-15 16:33:46 -070060 pipeline_layout = dev_data.Get<PIPELINE_LAYOUT_STATE>(create_info.layout);
61
62 viewport_state = create_info.pViewportState;
63
64 rp_state = dev_data.Get<RENDER_PASS_STATE>(create_info.renderPass);
65
66 raster_state = create_info.pRasterizationState;
67
68 tess_create_info = create_info.pTessellationState;
69
70 for (uint32_t i = 0; i < create_info.stageCount; ++i) {
71 // TODO might need to filter out more than just fragment shaders here
72 if (create_info.pStages[i].stage != VK_SHADER_STAGE_FRAGMENT_BIT) {
73 auto module_state = dev_data.Get<SHADER_MODULE_STATE>(create_info.pStages[i].module);
74 if (!module_state) {
75 // If module is null and there is a VkShaderModuleCreateInfo in the pNext chain of the stage info, then this
76 // module is part of a library and the state must be created
77 const auto shader_ci = LvlFindInChain<VkShaderModuleCreateInfo>(create_info.pStages[i].pNext);
78 if (shader_ci) {
79 const uint32_t unique_shader_id = 0; // TODO GPU-AV rework required to get this value properly
80 module_state = dev_data.CreateShaderModuleState(*shader_ci, unique_shader_id);
81 }
82 }
83
84 if (module_state) {
85 const auto *stage_ci = &create_info.pStages[i];
86 switch (create_info.pStages[i].stage) {
87 case VK_SHADER_STAGE_VERTEX_BIT:
88 vertex_shader = std::move(module_state);
89 vertex_shader_ci = stage_ci;
90 break;
91 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
92 tessc_shader = std::move(module_state);
93 tessc_shader_ci = stage_ci;
94 break;
95 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
96 tesse_shader = std::move(module_state);
97 tesse_shader_ci = stage_ci;
98 break;
99 case VK_SHADER_STAGE_GEOMETRY_BIT:
100 geometry_shader = std::move(module_state);
101 geometry_shader_ci = stage_ci;
102 break;
103 // TODO mesh shaders?
104 default:
105 // TODO is this an error?
106 break;
107 }
108 }
109 }
110 }
111}
112
113std::unique_ptr<const safe_VkPipelineColorBlendStateCreateInfo> ToSafeColorBlendState(
114 const safe_VkPipelineColorBlendStateCreateInfo &cbs) {
115 // This is needlessly copied here. Might better to make this a plain pointer, with an optional "backing unique_ptr"
116 return layer_data::make_unique<const safe_VkPipelineColorBlendStateCreateInfo>(cbs);
117}
118std::unique_ptr<const safe_VkPipelineColorBlendStateCreateInfo> ToSafeColorBlendState(
119 const VkPipelineColorBlendStateCreateInfo &cbs) {
120 return layer_data::make_unique<const safe_VkPipelineColorBlendStateCreateInfo>(&cbs);
121}
122std::unique_ptr<const safe_VkPipelineMultisampleStateCreateInfo> ToSafeMultisampleState(
123 const safe_VkPipelineMultisampleStateCreateInfo &cbs) {
124 // This is needlessly copied here. Might better to make this a plain pointer, with an optional "backing unique_ptr"
125 return layer_data::make_unique<const safe_VkPipelineMultisampleStateCreateInfo>(cbs);
126}
127std::unique_ptr<const safe_VkPipelineMultisampleStateCreateInfo> ToSafeMultisampleState(
128 const VkPipelineMultisampleStateCreateInfo &cbs) {
129 return layer_data::make_unique<const safe_VkPipelineMultisampleStateCreateInfo>(&cbs);
130}
131std::unique_ptr<const safe_VkPipelineDepthStencilStateCreateInfo> ToSafeDepthStencilState(
132 const safe_VkPipelineDepthStencilStateCreateInfo &cbs) {
133 // This is needlessly copied here. Might better to make this a plain pointer, with an optional "backing unique_ptr"
134 return layer_data::make_unique<const safe_VkPipelineDepthStencilStateCreateInfo>(cbs);
135}
136std::unique_ptr<const safe_VkPipelineDepthStencilStateCreateInfo> ToSafeDepthStencilState(
137 const VkPipelineDepthStencilStateCreateInfo &cbs) {
138 return layer_data::make_unique<const safe_VkPipelineDepthStencilStateCreateInfo>(&cbs);
139}
140std::unique_ptr<const safe_VkPipelineShaderStageCreateInfo> ToShaderStageCI(const safe_VkPipelineShaderStageCreateInfo &cbs) {
141 // This is needlessly copied here. Might better to make this a plain pointer, with an optional "backing unique_ptr"
142 return layer_data::make_unique<const safe_VkPipelineShaderStageCreateInfo>(cbs);
143}
144std::unique_ptr<const safe_VkPipelineShaderStageCreateInfo> ToShaderStageCI(const VkPipelineShaderStageCreateInfo &cbs) {
145 return layer_data::make_unique<const safe_VkPipelineShaderStageCreateInfo>(&cbs);
146}
147
148template <typename CreateInfo>
149void SetFragmentShaderInfoPrivate(FragmentShaderState &fs_state, const ValidationStateTracker &state_data,
150 const CreateInfo &create_info) {
151 for (uint32_t i = 0; i < create_info.stageCount; ++i) {
152 if (create_info.pStages[i].stage == VK_SHADER_STAGE_FRAGMENT_BIT) {
153 auto module_state = state_data.Get<SHADER_MODULE_STATE>(create_info.pStages[i].module);
154 if (!module_state) {
155 // If module is null and there is a VkShaderModuleCreateInfo in the pNext chain of the stage info, then this
156 // module is part of a library and the state must be created
157 const auto shader_ci = LvlFindInChain<VkShaderModuleCreateInfo>(create_info.pStages[i].pNext);
158 if (shader_ci) {
159 const uint32_t unique_shader_id = 0; // TODO GPU-AV rework required to get this value properly
160 module_state = state_data.CreateShaderModuleState(*shader_ci, unique_shader_id);
161 }
162 }
163
164 if (module_state) {
165 fs_state.fragment_shader = std::move(module_state);
166 fs_state.fragment_shader_ci = ToShaderStageCI(create_info.pStages[i]);
167 }
168 }
169 }
170}
171
172// static
173void FragmentShaderState::SetFragmentShaderInfo(FragmentShaderState &fs_state, const ValidationStateTracker &state_data,
174 const VkGraphicsPipelineCreateInfo &create_info) {
175 SetFragmentShaderInfoPrivate(fs_state, state_data, create_info);
176}
177
178// static
179void FragmentShaderState::SetFragmentShaderInfo(FragmentShaderState &fs_state, const ValidationStateTracker &state_data,
180 const safe_VkGraphicsPipelineCreateInfo &create_info) {
181 SetFragmentShaderInfoPrivate(fs_state, state_data, create_info);
182}
183
Nathaniel Cesarioef6e2052022-02-28 14:09:45 -0700184FragmentShaderState::FragmentShaderState(const PIPELINE_STATE &p, const ValidationStateTracker &dev_data, VkRenderPass rp,
185 uint32_t subp, VkPipelineLayout layout)
186 : parent(p),
187 rp_state(dev_data.Get<RENDER_PASS_STATE>(rp)),
188 subpass(subp),
189 pipeline_layout(dev_data.Get<PIPELINE_LAYOUT_STATE>(layout)) {}
Nathaniel Cesario52398442022-02-15 16:33:46 -0700190
Nathaniel Cesarioef6e2052022-02-28 14:09:45 -0700191FragmentOutputState::FragmentOutputState(const PIPELINE_STATE &p, const ValidationStateTracker &dev_data, VkRenderPass rp,
192 uint32_t sp)
193 : parent(p), rp_state(dev_data.Get<RENDER_PASS_STATE>(rp)), subpass(sp) {}
Nathaniel Cesario52398442022-02-15 16:33:46 -0700194
195// static
196bool FragmentOutputState::IsBlendConstantsEnabled(const AttachmentVector &attachments) {
197 bool result = false;
198 for (const auto &attachment : attachments) {
199 if (VK_TRUE == attachment.blendEnable) {
200 if (((attachment.dstAlphaBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) &&
201 (attachment.dstAlphaBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) ||
202 ((attachment.dstColorBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) &&
203 (attachment.dstColorBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) ||
204 ((attachment.srcAlphaBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) &&
205 (attachment.srcAlphaBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) ||
206 ((attachment.srcColorBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) &&
207 (attachment.srcColorBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA))) {
208 result = true;
209 break;
210 }
211 }
212 }
213 return result;
214}
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700215
216// static
217bool FragmentOutputState::GetDualSourceBlending(const safe_VkPipelineColorBlendStateCreateInfo *color_blend_state) {
218 if (!color_blend_state) {
219 return false;
220 }
221 const std::array<VkBlendFactor, 4> dual_modes = {
222 VK_BLEND_FACTOR_SRC1_COLOR,
223 VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR,
224 VK_BLEND_FACTOR_SRC1_ALPHA,
225 VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA,
226 };
227 for (uint32_t i = 0; i < color_blend_state->attachmentCount; ++i) {
228 const auto &attachment = color_blend_state->pAttachments[i];
229 if (attachment.blendEnable) {
230 if (std::find(dual_modes.begin(), dual_modes.end(), attachment.srcColorBlendFactor) != dual_modes.end() ||
231 std::find(dual_modes.begin(), dual_modes.end(), attachment.dstColorBlendFactor) != dual_modes.end() ||
232 std::find(dual_modes.begin(), dual_modes.end(), attachment.srcAlphaBlendFactor) != dual_modes.end() ||
233 std::find(dual_modes.begin(), dual_modes.end(), attachment.dstAlphaBlendFactor) != dual_modes.end()) {
234 return true;
235 }
236 }
237 }
238 return false;
239}