diff options
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | 421 |
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 | ||
| 29 | template <class StencilFace> | 29 | template <class StencilFace> |
| 30 | VkStencilOpState GetStencilFaceState(const StencilFace& face) { | 30 | VkStencilOpState 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 | ||
| 42 | bool SupportsPrimitiveRestart(VkPrimitiveTopology topology) { | 42 | bool SupportsPrimitiveRestart(VkPrimitiveTopology topology) { |
| @@ -52,20 +52,21 @@ bool SupportsPrimitiveRestart(VkPrimitiveTopology topology) { | |||
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | VkViewportSwizzleNV UnpackViewportSwizzle(u16 swizzle) { | 54 | VkViewportSwizzleNV 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 | ||
| 101 | vk::DescriptorSetLayout VKGraphicsPipeline::CreateDescriptorSetLayout( | 102 | vk::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 | ||
| 112 | vk::PipelineLayout VKGraphicsPipeline::CreatePipelineLayout() const { | 114 | vk::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 | ||
| 153 | std::vector<vk::ShaderModule> VKGraphicsPipeline::CreateShaderModules( | 157 | std::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 | ||