summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp421
1 files changed, 223 insertions, 198 deletions
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index 844445105..2cc3c1c1a 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -28,15 +28,15 @@ namespace {
28 28
29template <class StencilFace> 29template <class StencilFace>
30VkStencilOpState GetStencilFaceState(const StencilFace& face) { 30VkStencilOpState GetStencilFaceState(const StencilFace& face) {
31 VkStencilOpState state; 31 return {
32 state.failOp = MaxwellToVK::StencilOp(face.ActionStencilFail()); 32 .failOp = MaxwellToVK::StencilOp(face.ActionStencilFail()),
33 state.passOp = MaxwellToVK::StencilOp(face.ActionDepthPass()); 33 .passOp = MaxwellToVK::StencilOp(face.ActionDepthPass()),
34 state.depthFailOp = MaxwellToVK::StencilOp(face.ActionDepthFail()); 34 .depthFailOp = MaxwellToVK::StencilOp(face.ActionDepthFail()),
35 state.compareOp = MaxwellToVK::ComparisonOp(face.TestFunc()); 35 .compareOp = MaxwellToVK::ComparisonOp(face.TestFunc()),
36 state.compareMask = 0; 36 .compareMask = 0,
37 state.writeMask = 0; 37 .writeMask = 0,
38 state.reference = 0; 38 .reference = 0,
39 return state; 39 };
40} 40}
41 41
42bool SupportsPrimitiveRestart(VkPrimitiveTopology topology) { 42bool SupportsPrimitiveRestart(VkPrimitiveTopology topology) {
@@ -52,20 +52,21 @@ bool SupportsPrimitiveRestart(VkPrimitiveTopology topology) {
52} 52}
53 53
54VkViewportSwizzleNV UnpackViewportSwizzle(u16 swizzle) { 54VkViewportSwizzleNV UnpackViewportSwizzle(u16 swizzle) {
55 union { 55 union Swizzle {
56 u32 raw; 56 u32 raw;
57 BitField<0, 3, Maxwell::ViewportSwizzle> x; 57 BitField<0, 3, Maxwell::ViewportSwizzle> x;
58 BitField<4, 3, Maxwell::ViewportSwizzle> y; 58 BitField<4, 3, Maxwell::ViewportSwizzle> y;
59 BitField<8, 3, Maxwell::ViewportSwizzle> z; 59 BitField<8, 3, Maxwell::ViewportSwizzle> z;
60 BitField<12, 3, Maxwell::ViewportSwizzle> w; 60 BitField<12, 3, Maxwell::ViewportSwizzle> w;
61 } const unpacked{swizzle}; 61 };
62 62 const Swizzle unpacked{swizzle};
63 VkViewportSwizzleNV result; 63
64 result.x = MaxwellToVK::ViewportSwizzle(unpacked.x); 64 return {
65 result.y = MaxwellToVK::ViewportSwizzle(unpacked.y); 65 .x = MaxwellToVK::ViewportSwizzle(unpacked.x),
66 result.z = MaxwellToVK::ViewportSwizzle(unpacked.z); 66 .y = MaxwellToVK::ViewportSwizzle(unpacked.y),
67 result.w = MaxwellToVK::ViewportSwizzle(unpacked.w); 67 .z = MaxwellToVK::ViewportSwizzle(unpacked.z),
68 return result; 68 .w = MaxwellToVK::ViewportSwizzle(unpacked.w),
69 };
69} 70}
70 71
71} // Anonymous namespace 72} // Anonymous namespace
@@ -100,24 +101,26 @@ VkDescriptorSet VKGraphicsPipeline::CommitDescriptorSet() {
100 101
101vk::DescriptorSetLayout VKGraphicsPipeline::CreateDescriptorSetLayout( 102vk::DescriptorSetLayout VKGraphicsPipeline::CreateDescriptorSetLayout(
102 vk::Span<VkDescriptorSetLayoutBinding> bindings) const { 103 vk::Span<VkDescriptorSetLayoutBinding> bindings) const {
103 VkDescriptorSetLayoutCreateInfo ci; 104 const VkDescriptorSetLayoutCreateInfo ci{
104 ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; 105 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
105 ci.pNext = nullptr; 106 .pNext = nullptr,
106 ci.flags = 0; 107 .flags = 0,
107 ci.bindingCount = bindings.size(); 108 .bindingCount = bindings.size(),
108 ci.pBindings = bindings.data(); 109 .pBindings = bindings.data(),
110 };
109 return device.GetLogical().CreateDescriptorSetLayout(ci); 111 return device.GetLogical().CreateDescriptorSetLayout(ci);
110} 112}
111 113
112vk::PipelineLayout VKGraphicsPipeline::CreatePipelineLayout() const { 114vk::PipelineLayout VKGraphicsPipeline::CreatePipelineLayout() const {
113 VkPipelineLayoutCreateInfo ci; 115 const VkPipelineLayoutCreateInfo ci{
114 ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 116 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
115 ci.pNext = nullptr; 117 .pNext = nullptr,
116 ci.flags = 0; 118 .flags = 0,
117 ci.setLayoutCount = 1; 119 .setLayoutCount = 1,
118 ci.pSetLayouts = descriptor_set_layout.address(); 120 .pSetLayouts = descriptor_set_layout.address(),
119 ci.pushConstantRangeCount = 0; 121 .pushConstantRangeCount = 0,
120 ci.pPushConstantRanges = nullptr; 122 .pPushConstantRanges = nullptr,
123 };
121 return device.GetLogical().CreatePipelineLayout(ci); 124 return device.GetLogical().CreatePipelineLayout(ci);
122} 125}
123 126
@@ -136,26 +139,28 @@ vk::DescriptorUpdateTemplateKHR VKGraphicsPipeline::CreateDescriptorUpdateTempla
136 return {}; 139 return {};
137 } 140 }
138 141
139 VkDescriptorUpdateTemplateCreateInfoKHR ci; 142 const VkDescriptorUpdateTemplateCreateInfoKHR ci{
140 ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR; 143 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
141 ci.pNext = nullptr; 144 .pNext = nullptr,
142 ci.flags = 0; 145 .flags = 0,
143 ci.descriptorUpdateEntryCount = static_cast<u32>(template_entries.size()); 146 .descriptorUpdateEntryCount = static_cast<u32>(template_entries.size()),
144 ci.pDescriptorUpdateEntries = template_entries.data(); 147 .pDescriptorUpdateEntries = template_entries.data(),
145 ci.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR; 148 .templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR,
146 ci.descriptorSetLayout = *descriptor_set_layout; 149 .descriptorSetLayout = *descriptor_set_layout,
147 ci.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 150 .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
148 ci.pipelineLayout = *layout; 151 .pipelineLayout = *layout,
149 ci.set = DESCRIPTOR_SET; 152 .set = DESCRIPTOR_SET,
153 };
150 return device.GetLogical().CreateDescriptorUpdateTemplateKHR(ci); 154 return device.GetLogical().CreateDescriptorUpdateTemplateKHR(ci);
151} 155}
152 156
153std::vector<vk::ShaderModule> VKGraphicsPipeline::CreateShaderModules( 157std::vector<vk::ShaderModule> VKGraphicsPipeline::CreateShaderModules(
154 const SPIRVProgram& program) const { 158 const SPIRVProgram& program) const {
155 VkShaderModuleCreateInfo ci; 159 VkShaderModuleCreateInfo ci{
156 ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 160 .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
157 ci.pNext = nullptr; 161 .pNext = nullptr,
158 ci.flags = 0; 162 .flags = 0,
163 };
159 164
160 std::vector<vk::ShaderModule> modules; 165 std::vector<vk::ShaderModule> modules;
161 modules.reserve(Maxwell::MaxShaderStage); 166 modules.reserve(Maxwell::MaxShaderStage);
@@ -204,15 +209,17 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
204 const bool instanced = state.binding_divisors[index] != 0; 209 const bool instanced = state.binding_divisors[index] != 0;
205 const auto rate = instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX; 210 const auto rate = instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
206 211
207 auto& vertex_binding = vertex_bindings.emplace_back(); 212 vertex_bindings.push_back({
208 vertex_binding.binding = static_cast<u32>(index); 213 .binding = static_cast<u32>(index),
209 vertex_binding.stride = binding.stride; 214 .stride = binding.stride,
210 vertex_binding.inputRate = rate; 215 .inputRate = rate,
216 });
211 217
212 if (instanced) { 218 if (instanced) {
213 auto& binding_divisor = vertex_binding_divisors.emplace_back(); 219 vertex_binding_divisors.push_back({
214 binding_divisor.binding = static_cast<u32>(index); 220 .binding = static_cast<u32>(index),
215 binding_divisor.divisor = state.binding_divisors[index]; 221 .divisor = state.binding_divisors[index],
222 });
216 } 223 }
217 } 224 }
218 225
@@ -227,116 +234,130 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
227 // Skip attributes not used by the vertex shaders. 234 // Skip attributes not used by the vertex shaders.
228 continue; 235 continue;
229 } 236 }
230 auto& vertex_attribute = vertex_attributes.emplace_back(); 237 vertex_attributes.push_back({
231 vertex_attribute.location = static_cast<u32>(index); 238 .location = static_cast<u32>(index),
232 vertex_attribute.binding = attribute.buffer; 239 .binding = attribute.buffer,
233 vertex_attribute.format = MaxwellToVK::VertexFormat(attribute.Type(), attribute.Size()); 240 .format = MaxwellToVK::VertexFormat(attribute.Type(), attribute.Size()),
234 vertex_attribute.offset = attribute.offset; 241 .offset = attribute.offset,
242 });
235 } 243 }
236 244
237 VkPipelineVertexInputStateCreateInfo vertex_input_ci; 245 VkPipelineVertexInputStateCreateInfo vertex_input_ci{
238 vertex_input_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; 246 .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
239 vertex_input_ci.pNext = nullptr; 247 .pNext = nullptr,
240 vertex_input_ci.flags = 0; 248 .flags = 0,
241 vertex_input_ci.vertexBindingDescriptionCount = static_cast<u32>(vertex_bindings.size()); 249 .vertexBindingDescriptionCount = static_cast<u32>(vertex_bindings.size()),
242 vertex_input_ci.pVertexBindingDescriptions = vertex_bindings.data(); 250 .pVertexBindingDescriptions = vertex_bindings.data(),
243 vertex_input_ci.vertexAttributeDescriptionCount = static_cast<u32>(vertex_attributes.size()); 251 .vertexAttributeDescriptionCount = static_cast<u32>(vertex_attributes.size()),
244 vertex_input_ci.pVertexAttributeDescriptions = vertex_attributes.data(); 252 .pVertexAttributeDescriptions = vertex_attributes.data(),
245 253 };
246 VkPipelineVertexInputDivisorStateCreateInfoEXT input_divisor_ci; 254
247 input_divisor_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT; 255 const VkPipelineVertexInputDivisorStateCreateInfoEXT input_divisor_ci{
248 input_divisor_ci.pNext = nullptr; 256 .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT,
249 input_divisor_ci.vertexBindingDivisorCount = static_cast<u32>(vertex_binding_divisors.size()); 257 .pNext = nullptr,
250 input_divisor_ci.pVertexBindingDivisors = vertex_binding_divisors.data(); 258 .vertexBindingDivisorCount = static_cast<u32>(vertex_binding_divisors.size()),
259 .pVertexBindingDivisors = vertex_binding_divisors.data(),
260 };
251 if (!vertex_binding_divisors.empty()) { 261 if (!vertex_binding_divisors.empty()) {
252 vertex_input_ci.pNext = &input_divisor_ci; 262 vertex_input_ci.pNext = &input_divisor_ci;
253 } 263 }
254 264
255 VkPipelineInputAssemblyStateCreateInfo input_assembly_ci; 265 const auto input_assembly_topology = MaxwellToVK::PrimitiveTopology(device, dynamic.Topology());
256 input_assembly_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; 266 const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci{
257 input_assembly_ci.pNext = nullptr; 267 .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
258 input_assembly_ci.flags = 0; 268 .pNext = nullptr,
259 input_assembly_ci.topology = MaxwellToVK::PrimitiveTopology(device, dynamic.Topology()); 269 .flags = 0,
260 input_assembly_ci.primitiveRestartEnable = 270 .topology = MaxwellToVK::PrimitiveTopology(device, dynamic.Topology()),
261 state.primitive_restart_enable != 0 && SupportsPrimitiveRestart(input_assembly_ci.topology); 271 .primitiveRestartEnable = state.primitive_restart_enable != 0 &&
262 272 SupportsPrimitiveRestart(input_assembly_topology),
263 VkPipelineTessellationStateCreateInfo tessellation_ci; 273 };
264 tessellation_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO; 274
265 tessellation_ci.pNext = nullptr; 275 const VkPipelineTessellationStateCreateInfo tessellation_ci{
266 tessellation_ci.flags = 0; 276 .sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
267 tessellation_ci.patchControlPoints = state.patch_control_points_minus_one.Value() + 1; 277 .pNext = nullptr,
268 278 .flags = 0,
269 VkPipelineViewportStateCreateInfo viewport_ci; 279 .patchControlPoints = state.patch_control_points_minus_one.Value() + 1,
270 viewport_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; 280 };
271 viewport_ci.pNext = nullptr; 281
272 viewport_ci.flags = 0; 282 VkPipelineViewportStateCreateInfo viewport_ci{
273 viewport_ci.viewportCount = Maxwell::NumViewports; 283 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
274 viewport_ci.pViewports = nullptr; 284 .pNext = nullptr,
275 viewport_ci.scissorCount = Maxwell::NumViewports; 285 .flags = 0,
276 viewport_ci.pScissors = nullptr; 286 .viewportCount = Maxwell::NumViewports,
287 .pViewports = nullptr,
288 .scissorCount = Maxwell::NumViewports,
289 .pScissors = nullptr,
290 };
277 291
278 std::array<VkViewportSwizzleNV, Maxwell::NumViewports> swizzles; 292 std::array<VkViewportSwizzleNV, Maxwell::NumViewports> swizzles;
279 std::transform(viewport_swizzles.begin(), viewport_swizzles.end(), swizzles.begin(), 293 std::transform(viewport_swizzles.begin(), viewport_swizzles.end(), swizzles.begin(),
280 UnpackViewportSwizzle); 294 UnpackViewportSwizzle);
281 VkPipelineViewportSwizzleStateCreateInfoNV swizzle_ci; 295 VkPipelineViewportSwizzleStateCreateInfoNV swizzle_ci{
282 swizzle_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV; 296 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV,
283 swizzle_ci.pNext = nullptr; 297 .pNext = nullptr,
284 swizzle_ci.flags = 0; 298 .flags = 0,
285 swizzle_ci.viewportCount = Maxwell::NumViewports; 299 .viewportCount = Maxwell::NumViewports,
286 swizzle_ci.pViewportSwizzles = swizzles.data(); 300 .pViewportSwizzles = swizzles.data(),
301 };
287 if (device.IsNvViewportSwizzleSupported()) { 302 if (device.IsNvViewportSwizzleSupported()) {
288 viewport_ci.pNext = &swizzle_ci; 303 viewport_ci.pNext = &swizzle_ci;
289 } 304 }
290 305
291 VkPipelineRasterizationStateCreateInfo rasterization_ci; 306 const VkPipelineRasterizationStateCreateInfo rasterization_ci{
292 rasterization_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; 307 .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
293 rasterization_ci.pNext = nullptr; 308 .pNext = nullptr,
294 rasterization_ci.flags = 0; 309 .flags = 0,
295 rasterization_ci.depthClampEnable = state.depth_clamp_disabled == 0 ? VK_TRUE : VK_FALSE; 310 .depthClampEnable = state.depth_clamp_disabled == 0 ? VK_TRUE : VK_FALSE,
296 rasterization_ci.rasterizerDiscardEnable = state.rasterize_enable == 0 ? VK_TRUE : VK_FALSE; 311 .rasterizerDiscardEnable = state.rasterize_enable == 0 ? VK_TRUE : VK_FALSE,
297 rasterization_ci.polygonMode = VK_POLYGON_MODE_FILL; 312 .polygonMode = VK_POLYGON_MODE_FILL,
298 rasterization_ci.cullMode = 313 .cullMode =
299 dynamic.cull_enable ? MaxwellToVK::CullFace(dynamic.CullFace()) : VK_CULL_MODE_NONE; 314 dynamic.cull_enable ? MaxwellToVK::CullFace(dynamic.CullFace()) : VK_CULL_MODE_NONE,
300 rasterization_ci.frontFace = MaxwellToVK::FrontFace(dynamic.FrontFace()); 315 .frontFace = MaxwellToVK::FrontFace(dynamic.FrontFace()),
301 rasterization_ci.depthBiasEnable = state.depth_bias_enable; 316 .depthBiasEnable = state.depth_bias_enable,
302 rasterization_ci.depthBiasConstantFactor = 0.0f; 317 .depthBiasConstantFactor = 0.0f,
303 rasterization_ci.depthBiasClamp = 0.0f; 318 .depthBiasClamp = 0.0f,
304 rasterization_ci.depthBiasSlopeFactor = 0.0f; 319 .depthBiasSlopeFactor = 0.0f,
305 rasterization_ci.lineWidth = 1.0f; 320 .lineWidth = 1.0f,
306 321 };
307 VkPipelineMultisampleStateCreateInfo multisample_ci; 322
308 multisample_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; 323 const VkPipelineMultisampleStateCreateInfo multisample_ci{
309 multisample_ci.pNext = nullptr; 324 .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
310 multisample_ci.flags = 0; 325 .pNext = nullptr,
311 multisample_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; 326 .flags = 0,
312 multisample_ci.sampleShadingEnable = VK_FALSE; 327 .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
313 multisample_ci.minSampleShading = 0.0f; 328 .sampleShadingEnable = VK_FALSE,
314 multisample_ci.pSampleMask = nullptr; 329 .minSampleShading = 0.0f,
315 multisample_ci.alphaToCoverageEnable = VK_FALSE; 330 .pSampleMask = nullptr,
316 multisample_ci.alphaToOneEnable = VK_FALSE; 331 .alphaToCoverageEnable = VK_FALSE,
317 332 .alphaToOneEnable = VK_FALSE,
318 VkPipelineDepthStencilStateCreateInfo depth_stencil_ci; 333 };
319 depth_stencil_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; 334
320 depth_stencil_ci.pNext = nullptr; 335 const VkPipelineDepthStencilStateCreateInfo depth_stencil_ci{
321 depth_stencil_ci.flags = 0; 336 .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
322 depth_stencil_ci.depthTestEnable = dynamic.depth_test_enable; 337 .pNext = nullptr,
323 depth_stencil_ci.depthWriteEnable = dynamic.depth_write_enable; 338 .flags = 0,
324 depth_stencil_ci.depthCompareOp = dynamic.depth_test_enable 339 .depthTestEnable = dynamic.depth_test_enable,
325 ? MaxwellToVK::ComparisonOp(dynamic.DepthTestFunc()) 340 .depthWriteEnable = dynamic.depth_write_enable,
326 : VK_COMPARE_OP_ALWAYS; 341 .depthCompareOp = dynamic.depth_test_enable
327 depth_stencil_ci.depthBoundsTestEnable = dynamic.depth_bounds_enable; 342 ? MaxwellToVK::ComparisonOp(dynamic.DepthTestFunc())
328 depth_stencil_ci.stencilTestEnable = dynamic.stencil_enable; 343 : VK_COMPARE_OP_ALWAYS,
329 depth_stencil_ci.front = GetStencilFaceState(dynamic.front); 344 .depthBoundsTestEnable = dynamic.depth_bounds_enable,
330 depth_stencil_ci.back = GetStencilFaceState(dynamic.back); 345 .stencilTestEnable = dynamic.stencil_enable,
331 depth_stencil_ci.minDepthBounds = 0.0f; 346 .front = GetStencilFaceState(dynamic.front),
332 depth_stencil_ci.maxDepthBounds = 0.0f; 347 .back = GetStencilFaceState(dynamic.back),
348 .minDepthBounds = 0.0f,
349 .maxDepthBounds = 0.0f,
350 };
333 351
334 std::array<VkPipelineColorBlendAttachmentState, Maxwell::NumRenderTargets> cb_attachments; 352 std::array<VkPipelineColorBlendAttachmentState, Maxwell::NumRenderTargets> cb_attachments;
335 const auto num_attachments = static_cast<std::size_t>(renderpass_params.num_color_attachments); 353 const auto num_attachments = static_cast<std::size_t>(renderpass_params.num_color_attachments);
336 for (std::size_t index = 0; index < num_attachments; ++index) { 354 for (std::size_t index = 0; index < num_attachments; ++index) {
337 static constexpr std::array COMPONENT_TABLE = { 355 static constexpr std::array COMPONENT_TABLE{
338 VK_COLOR_COMPONENT_R_BIT, VK_COLOR_COMPONENT_G_BIT, VK_COLOR_COMPONENT_B_BIT, 356 VK_COLOR_COMPONENT_R_BIT,
339 VK_COLOR_COMPONENT_A_BIT}; 357 VK_COLOR_COMPONENT_G_BIT,
358 VK_COLOR_COMPONENT_B_BIT,
359 VK_COLOR_COMPONENT_A_BIT,
360 };
340 const auto& blend = state.attachments[index]; 361 const auto& blend = state.attachments[index];
341 362
342 VkColorComponentFlags color_components = 0; 363 VkColorComponentFlags color_components = 0;
@@ -346,35 +367,36 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
346 } 367 }
347 } 368 }
348 369
349 VkPipelineColorBlendAttachmentState& attachment = cb_attachments[index]; 370 cb_attachments[index] = {
350 attachment.blendEnable = blend.enable != 0; 371 .blendEnable = blend.enable != 0,
351 attachment.srcColorBlendFactor = MaxwellToVK::BlendFactor(blend.SourceRGBFactor()); 372 .srcColorBlendFactor = MaxwellToVK::BlendFactor(blend.SourceRGBFactor()),
352 attachment.dstColorBlendFactor = MaxwellToVK::BlendFactor(blend.DestRGBFactor()); 373 .dstColorBlendFactor = MaxwellToVK::BlendFactor(blend.DestRGBFactor()),
353 attachment.colorBlendOp = MaxwellToVK::BlendEquation(blend.EquationRGB()); 374 .colorBlendOp = MaxwellToVK::BlendEquation(blend.EquationRGB()),
354 attachment.srcAlphaBlendFactor = MaxwellToVK::BlendFactor(blend.SourceAlphaFactor()); 375 .srcAlphaBlendFactor = MaxwellToVK::BlendFactor(blend.SourceAlphaFactor()),
355 attachment.dstAlphaBlendFactor = MaxwellToVK::BlendFactor(blend.DestAlphaFactor()); 376 .dstAlphaBlendFactor = MaxwellToVK::BlendFactor(blend.DestAlphaFactor()),
356 attachment.alphaBlendOp = MaxwellToVK::BlendEquation(blend.EquationAlpha()); 377 .alphaBlendOp = MaxwellToVK::BlendEquation(blend.EquationAlpha()),
357 attachment.colorWriteMask = color_components; 378 .colorWriteMask = color_components,
379 };
358 } 380 }
359 381
360 VkPipelineColorBlendStateCreateInfo color_blend_ci; 382 const VkPipelineColorBlendStateCreateInfo color_blend_ci{
361 color_blend_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; 383 .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
362 color_blend_ci.pNext = nullptr; 384 .pNext = nullptr,
363 color_blend_ci.flags = 0; 385 .flags = 0,
364 color_blend_ci.logicOpEnable = VK_FALSE; 386 .logicOpEnable = VK_FALSE,
365 color_blend_ci.logicOp = VK_LOGIC_OP_COPY; 387 .logicOp = VK_LOGIC_OP_COPY,
366 color_blend_ci.attachmentCount = static_cast<u32>(num_attachments); 388 .attachmentCount = static_cast<u32>(num_attachments),
367 color_blend_ci.pAttachments = cb_attachments.data(); 389 .pAttachments = cb_attachments.data(),
368 std::memset(color_blend_ci.blendConstants, 0, sizeof(color_blend_ci.blendConstants)); 390 };
369 391
370 std::vector dynamic_states = { 392 std::vector dynamic_states{
371 VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, 393 VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR,
372 VK_DYNAMIC_STATE_DEPTH_BIAS, VK_DYNAMIC_STATE_BLEND_CONSTANTS, 394 VK_DYNAMIC_STATE_DEPTH_BIAS, VK_DYNAMIC_STATE_BLEND_CONSTANTS,
373 VK_DYNAMIC_STATE_DEPTH_BOUNDS, VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK, 395 VK_DYNAMIC_STATE_DEPTH_BOUNDS, VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
374 VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, VK_DYNAMIC_STATE_STENCIL_REFERENCE, 396 VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, VK_DYNAMIC_STATE_STENCIL_REFERENCE,
375 }; 397 };
376 if (device.IsExtExtendedDynamicStateSupported()) { 398 if (device.IsExtExtendedDynamicStateSupported()) {
377 static constexpr std::array extended = { 399 static constexpr std::array extended{
378 VK_DYNAMIC_STATE_CULL_MODE_EXT, 400 VK_DYNAMIC_STATE_CULL_MODE_EXT,
379 VK_DYNAMIC_STATE_FRONT_FACE_EXT, 401 VK_DYNAMIC_STATE_FRONT_FACE_EXT,
380 VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT, 402 VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT,
@@ -389,18 +411,19 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
389 dynamic_states.insert(dynamic_states.end(), extended.begin(), extended.end()); 411 dynamic_states.insert(dynamic_states.end(), extended.begin(), extended.end());
390 } 412 }
391 413
392 VkPipelineDynamicStateCreateInfo dynamic_state_ci; 414 const VkPipelineDynamicStateCreateInfo dynamic_state_ci{
393 dynamic_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; 415 .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
394 dynamic_state_ci.pNext = nullptr; 416 .pNext = nullptr,
395 dynamic_state_ci.flags = 0; 417 .flags = 0,
396 dynamic_state_ci.dynamicStateCount = static_cast<u32>(dynamic_states.size()); 418 .dynamicStateCount = static_cast<u32>(dynamic_states.size()),
397 dynamic_state_ci.pDynamicStates = dynamic_states.data(); 419 .pDynamicStates = dynamic_states.data(),
420 };
398 421
399 VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci; 422 const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci{
400 subgroup_size_ci.sType = 423 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT,
401 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT; 424 .pNext = nullptr,
402 subgroup_size_ci.pNext = nullptr; 425 .requiredSubgroupSize = GuestWarpSize,
403 subgroup_size_ci.requiredSubgroupSize = GuestWarpSize; 426 };
404 427
405 std::vector<VkPipelineShaderStageCreateInfo> shader_stages; 428 std::vector<VkPipelineShaderStageCreateInfo> shader_stages;
406 std::size_t module_index = 0; 429 std::size_t module_index = 0;
@@ -408,6 +431,7 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
408 if (!program[stage]) { 431 if (!program[stage]) {
409 continue; 432 continue;
410 } 433 }
434
411 VkPipelineShaderStageCreateInfo& stage_ci = shader_stages.emplace_back(); 435 VkPipelineShaderStageCreateInfo& stage_ci = shader_stages.emplace_back();
412 stage_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 436 stage_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
413 stage_ci.pNext = nullptr; 437 stage_ci.pNext = nullptr;
@@ -422,26 +446,27 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
422 } 446 }
423 } 447 }
424 448
425 VkGraphicsPipelineCreateInfo ci; 449 const VkGraphicsPipelineCreateInfo ci{
426 ci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 450 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
427 ci.pNext = nullptr; 451 .pNext = nullptr,
428 ci.flags = 0; 452 .flags = 0,
429 ci.stageCount = static_cast<u32>(shader_stages.size()); 453 .stageCount = static_cast<u32>(shader_stages.size()),
430 ci.pStages = shader_stages.data(); 454 .pStages = shader_stages.data(),
431 ci.pVertexInputState = &vertex_input_ci; 455 .pVertexInputState = &vertex_input_ci,
432 ci.pInputAssemblyState = &input_assembly_ci; 456 .pInputAssemblyState = &input_assembly_ci,
433 ci.pTessellationState = &tessellation_ci; 457 .pTessellationState = &tessellation_ci,
434 ci.pViewportState = &viewport_ci; 458 .pViewportState = &viewport_ci,
435 ci.pRasterizationState = &rasterization_ci; 459 .pRasterizationState = &rasterization_ci,
436 ci.pMultisampleState = &multisample_ci; 460 .pMultisampleState = &multisample_ci,
437 ci.pDepthStencilState = &depth_stencil_ci; 461 .pDepthStencilState = &depth_stencil_ci,
438 ci.pColorBlendState = &color_blend_ci; 462 .pColorBlendState = &color_blend_ci,
439 ci.pDynamicState = &dynamic_state_ci; 463 .pDynamicState = &dynamic_state_ci,
440 ci.layout = *layout; 464 .layout = *layout,
441 ci.renderPass = renderpass; 465 .renderPass = renderpass,
442 ci.subpass = 0; 466 .subpass = 0,
443 ci.basePipelineHandle = nullptr; 467 .basePipelineHandle = nullptr,
444 ci.basePipelineIndex = 0; 468 .basePipelineIndex = 0,
469 };
445 return device.GetLogical().CreateGraphicsPipeline(ci); 470 return device.GetLogical().CreateGraphicsPipeline(ci);
446} 471}
447 472