Alexis Hetu | 000df8b | 2018-10-24 15:22:41 -0400 | [diff] [blame] | 1 | // Copyright 2018 The SwiftShader Authors. All Rights Reserved. |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
| 15 | #include "VkPipeline.hpp" |
Nicolas Capens | a29aa77 | 2019-06-26 00:36:28 -0400 | [diff] [blame] | 16 | |
| 17 | #include "VkDevice.hpp" |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 18 | #include "VkPipelineCache.hpp" |
Ben Clayton | 76e9bc0 | 2019-02-26 15:02:18 +0000 | [diff] [blame] | 19 | #include "VkPipelineLayout.hpp" |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 20 | #include "VkRenderPass.hpp" |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 21 | #include "VkShaderModule.hpp" |
Alexis Hetu | 7b29abf | 2019-11-21 17:26:17 -0500 | [diff] [blame] | 22 | #include "VkStringify.hpp" |
Ben Clayton | f2be26a | 2019-03-08 12:02:05 +0000 | [diff] [blame] | 23 | #include "Pipeline/ComputeProgram.hpp" |
Nicolas Capens | 73c3124 | 2019-02-12 00:09:23 -0500 | [diff] [blame] | 24 | #include "Pipeline/SpirvShader.hpp" |
| 25 | |
Ben Clayton | e693b62 | 2019-09-05 12:48:37 +0100 | [diff] [blame] | 26 | #include "marl/trace.h" |
Ben Clayton | d6c6136 | 2019-08-14 18:16:01 +0100 | [diff] [blame] | 27 | |
Nicolas Capens | 73c3124 | 2019-02-12 00:09:23 -0500 | [diff] [blame] | 28 | #include "spirv-tools/optimizer.hpp" |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 29 | |
Ben Clayton | 62758f5 | 2019-03-13 14:18:58 +0000 | [diff] [blame] | 30 | #include <iostream> |
| 31 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 32 | namespace { |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 33 | |
Nicolas Capens | 4aa4fcd | 2019-06-19 13:14:11 -0400 | [diff] [blame] | 34 | // preprocessSpirv applies and freezes specializations into constants, and inlines all functions. |
Ben Clayton | 45faa08 | 2019-03-05 13:20:40 +0000 | [diff] [blame] | 35 | std::vector<uint32_t> preprocessSpirv( |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 36 | std::vector<uint32_t> const &code, |
Ben Clayton | 5349f3c | 2020-01-14 11:50:24 +0000 | [diff] [blame] | 37 | VkSpecializationInfo const *specializationInfo, |
| 38 | bool optimize) |
Ben Clayton | 45faa08 | 2019-03-05 13:20:40 +0000 | [diff] [blame] | 39 | { |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 40 | spvtools::Optimizer opt{ SPV_ENV_VULKAN_1_1 }; |
Ben Clayton | 45faa08 | 2019-03-05 13:20:40 +0000 | [diff] [blame] | 41 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 42 | opt.SetMessageConsumer([](spv_message_level_t level, const char *, const spv_position_t &p, const char *m) { |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 43 | switch(level) |
Ben Clayton | 45faa08 | 2019-03-05 13:20:40 +0000 | [diff] [blame] | 44 | { |
Ben Clayton | 25e06e0 | 2020-02-07 11:19:08 +0000 | [diff] [blame^] | 45 | case SPV_MSG_FATAL: sw::warn("SPIR-V FATAL: %d:%d %s\n", int(p.line), int(p.column), m); |
| 46 | case SPV_MSG_INTERNAL_ERROR: sw::warn("SPIR-V INTERNAL_ERROR: %d:%d %s\n", int(p.line), int(p.column), m); |
| 47 | case SPV_MSG_ERROR: sw::warn("SPIR-V ERROR: %d:%d %s\n", int(p.line), int(p.column), m); |
| 48 | case SPV_MSG_WARNING: sw::warn("SPIR-V WARNING: %d:%d %s\n", int(p.line), int(p.column), m); |
| 49 | case SPV_MSG_INFO: sw::trace("SPIR-V INFO: %d:%d %s\n", int(p.line), int(p.column), m); |
| 50 | case SPV_MSG_DEBUG: sw::trace("SPIR-V DEBUG: %d:%d %s\n", int(p.line), int(p.column), m); |
| 51 | default: sw::trace("SPIR-V MESSAGE: %d:%d %s\n", int(p.line), int(p.column), m); |
Ben Clayton | 45faa08 | 2019-03-05 13:20:40 +0000 | [diff] [blame] | 52 | } |
| 53 | }); |
| 54 | |
Ben Clayton | 45faa08 | 2019-03-05 13:20:40 +0000 | [diff] [blame] | 55 | // If the pipeline uses specialization, apply the specializations before freezing |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 56 | if(specializationInfo) |
Ben Clayton | 45faa08 | 2019-03-05 13:20:40 +0000 | [diff] [blame] | 57 | { |
| 58 | std::unordered_map<uint32_t, std::vector<uint32_t>> specializations; |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 59 | for(auto i = 0u; i < specializationInfo->mapEntryCount; ++i) |
Ben Clayton | 45faa08 | 2019-03-05 13:20:40 +0000 | [diff] [blame] | 60 | { |
| 61 | auto const &e = specializationInfo->pMapEntries[i]; |
| 62 | auto value_ptr = |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 63 | static_cast<uint32_t const *>(specializationInfo->pData) + e.offset / sizeof(uint32_t); |
Ben Clayton | 45faa08 | 2019-03-05 13:20:40 +0000 | [diff] [blame] | 64 | specializations.emplace(e.constantID, |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 65 | std::vector<uint32_t>{ value_ptr, value_ptr + e.size / sizeof(uint32_t) }); |
Ben Clayton | 45faa08 | 2019-03-05 13:20:40 +0000 | [diff] [blame] | 66 | } |
| 67 | opt.RegisterPass(spvtools::CreateSetSpecConstantDefaultValuePass(specializations)); |
| 68 | } |
Ben Clayton | 45faa08 | 2019-03-05 13:20:40 +0000 | [diff] [blame] | 69 | |
Ben Clayton | 5349f3c | 2020-01-14 11:50:24 +0000 | [diff] [blame] | 70 | if(optimize) |
| 71 | { |
| 72 | // Full optimization list taken from spirv-opt. |
| 73 | opt.RegisterPerformancePasses(); |
| 74 | } |
Ben Clayton | 4fa92a7 | 2019-04-03 11:03:53 +0100 | [diff] [blame] | 75 | |
Ben Clayton | 45faa08 | 2019-03-05 13:20:40 +0000 | [diff] [blame] | 76 | std::vector<uint32_t> optimized; |
| 77 | opt.Run(code.data(), code.size(), &optimized); |
Ben Clayton | 62758f5 | 2019-03-13 14:18:58 +0000 | [diff] [blame] | 78 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 79 | if(false) |
| 80 | { |
Ben Clayton | 62758f5 | 2019-03-13 14:18:58 +0000 | [diff] [blame] | 81 | spvtools::SpirvTools core(SPV_ENV_VULKAN_1_1); |
| 82 | std::string preOpt; |
Ben Clayton | 555c333 | 2019-03-28 17:15:04 +0000 | [diff] [blame] | 83 | core.Disassemble(code, &preOpt, SPV_BINARY_TO_TEXT_OPTION_NONE); |
Ben Clayton | 62758f5 | 2019-03-13 14:18:58 +0000 | [diff] [blame] | 84 | std::string postOpt; |
Ben Clayton | 555c333 | 2019-03-28 17:15:04 +0000 | [diff] [blame] | 85 | core.Disassemble(optimized, &postOpt, SPV_BINARY_TO_TEXT_OPTION_NONE); |
Ben Clayton | 62758f5 | 2019-03-13 14:18:58 +0000 | [diff] [blame] | 86 | std::cout << "PRE-OPT: " << preOpt << std::endl |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 87 | << "POST-OPT: " << postOpt << std::endl; |
Ben Clayton | 62758f5 | 2019-03-13 14:18:58 +0000 | [diff] [blame] | 88 | } |
| 89 | |
Ben Clayton | 45faa08 | 2019-03-05 13:20:40 +0000 | [diff] [blame] | 90 | return optimized; |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 91 | } |
Alexis Hetu | 000df8b | 2018-10-24 15:22:41 -0400 | [diff] [blame] | 92 | |
Ben Clayton | 7d0ce41 | 2019-12-03 13:26:31 +0000 | [diff] [blame] | 93 | std::shared_ptr<sw::SpirvShader> createShader( |
| 94 | const vk::PipelineCache::SpirvShaderKey &key, |
| 95 | const vk::ShaderModule *module, |
| 96 | bool robustBufferAccess, |
| 97 | const std::shared_ptr<vk::dbg::Context> &dbgctx) |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 98 | { |
Ben Clayton | 5349f3c | 2020-01-14 11:50:24 +0000 | [diff] [blame] | 99 | // Do not optimize the shader if we have a debugger context. |
| 100 | // Optimization passes are likely to damage debug information, and reorder |
| 101 | // instructions. |
| 102 | const bool optimize = !dbgctx; |
| 103 | |
| 104 | // TODO(b/147726513): Do not preprocess the shader if we have a debugger |
| 105 | // context. |
| 106 | // This is a work-around for the SPIR-V tools incorrectly reporting errors |
| 107 | // when debug information is provided. This can be removed once the |
| 108 | // following SPIR-V tools bugs are fixed: |
| 109 | // https://github.com/KhronosGroup/SPIRV-Tools/issues/3102 |
| 110 | // https://github.com/KhronosGroup/SPIRV-Tools/issues/3103 |
| 111 | // https://github.com/KhronosGroup/SPIRV-Tools/issues/3118 |
| 112 | auto code = dbgctx ? key.getInsns() : preprocessSpirv(key.getInsns(), key.getSpecializationInfo(), optimize); |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 113 | ASSERT(code.size() > 0); |
| 114 | |
| 115 | // If the pipeline has specialization constants, assume they're unique and |
| 116 | // use a new serial ID so the shader gets recompiled. |
| 117 | uint32_t codeSerialID = (key.getSpecializationInfo() ? vk::ShaderModule::nextSerialID() : module->getSerialID()); |
| 118 | |
| 119 | // TODO(b/119409619): use allocator. |
| 120 | return std::make_shared<sw::SpirvShader>(codeSerialID, key.getPipelineStage(), key.getEntryPointName().c_str(), |
Ben Clayton | 7d0ce41 | 2019-12-03 13:26:31 +0000 | [diff] [blame] | 121 | code, key.getRenderPass(), key.getSubpassIndex(), robustBufferAccess, dbgctx); |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 122 | } |
| 123 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 124 | std::shared_ptr<sw::ComputeProgram> createProgram(const vk::PipelineCache::ComputeProgramKey &key) |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 125 | { |
Ben Clayton | e693b62 | 2019-09-05 12:48:37 +0100 | [diff] [blame] | 126 | MARL_SCOPED_EVENT("createProgram"); |
Ben Clayton | d6c6136 | 2019-08-14 18:16:01 +0100 | [diff] [blame] | 127 | |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 128 | vk::DescriptorSet::Bindings descriptorSets; // FIXME(b/129523279): Delay code generation until invoke time. |
| 129 | // TODO(b/119409619): use allocator. |
| 130 | auto program = std::make_shared<sw::ComputeProgram>(key.getShader(), key.getLayout(), descriptorSets); |
| 131 | program->generate(); |
Ben Clayton | 056d692 | 2019-07-04 12:41:13 +0100 | [diff] [blame] | 132 | program->finalize(); |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 133 | return program; |
| 134 | } |
| 135 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 136 | } // anonymous namespace |
Ben Clayton | 45faa08 | 2019-03-05 13:20:40 +0000 | [diff] [blame] | 137 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 138 | namespace vk { |
Alexis Hetu | 000df8b | 2018-10-24 15:22:41 -0400 | [diff] [blame] | 139 | |
Nicolas Capens | a29aa77 | 2019-06-26 00:36:28 -0400 | [diff] [blame] | 140 | Pipeline::Pipeline(PipelineLayout const *layout, const Device *device) |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 141 | : layout(layout) |
Ben Clayton | 7d0ce41 | 2019-12-03 13:26:31 +0000 | [diff] [blame] | 142 | , device(device) |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 143 | , robustBufferAccess(device->getEnabledFeatures().robustBufferAccess) |
Nicolas Capens | a29aa77 | 2019-06-26 00:36:28 -0400 | [diff] [blame] | 144 | { |
| 145 | } |
Ben Clayton | 76e9bc0 | 2019-02-26 15:02:18 +0000 | [diff] [blame] | 146 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 147 | GraphicsPipeline::GraphicsPipeline(const VkGraphicsPipelineCreateInfo *pCreateInfo, void *mem, const Device *device) |
| 148 | : Pipeline(vk::Cast(pCreateInfo->layout), device) |
Alexis Hetu | 000df8b | 2018-10-24 15:22:41 -0400 | [diff] [blame] | 149 | { |
Alexis Hetu | f9c8d5f | 2019-09-12 09:54:54 -0400 | [diff] [blame] | 150 | context.robustBufferAccess = robustBufferAccess; |
| 151 | |
Nicolas Capens | 44bd43a | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 152 | if((pCreateInfo->flags & |
| 153 | ~(VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT | |
| 154 | VK_PIPELINE_CREATE_DERIVATIVE_BIT | |
| 155 | VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT)) != 0) |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 156 | { |
Nicolas Capens | 44bd43a | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 157 | UNSUPPORTED("pCreateInfo->flags %d", int(pCreateInfo->flags)); |
| 158 | } |
| 159 | |
| 160 | if(pCreateInfo->pTessellationState != nullptr) |
| 161 | { |
| 162 | UNSUPPORTED("pCreateInfo->pTessellationState"); |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 163 | } |
| 164 | |
Alexis Hetu | 7383243 | 2019-04-11 16:43:18 -0400 | [diff] [blame] | 165 | if(pCreateInfo->pDynamicState) |
| 166 | { |
Nicolas Capens | 44bd43a | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 167 | if(pCreateInfo->pDynamicState->flags != 0) |
| 168 | { |
| 169 | // Vulkan 1.2: "flags is reserved for future use." "flags must be 0" |
| 170 | UNSUPPORTED("pCreateInfo->pDynamicState->flags %d", int(pCreateInfo->pDynamicState->flags)); |
| 171 | } |
| 172 | |
Alexis Hetu | 7383243 | 2019-04-11 16:43:18 -0400 | [diff] [blame] | 173 | for(uint32_t i = 0; i < pCreateInfo->pDynamicState->dynamicStateCount; i++) |
| 174 | { |
| 175 | VkDynamicState dynamicState = pCreateInfo->pDynamicState->pDynamicStates[i]; |
| 176 | switch(dynamicState) |
| 177 | { |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 178 | case VK_DYNAMIC_STATE_VIEWPORT: |
| 179 | case VK_DYNAMIC_STATE_SCISSOR: |
| 180 | case VK_DYNAMIC_STATE_LINE_WIDTH: |
| 181 | case VK_DYNAMIC_STATE_DEPTH_BIAS: |
| 182 | case VK_DYNAMIC_STATE_BLEND_CONSTANTS: |
| 183 | case VK_DYNAMIC_STATE_DEPTH_BOUNDS: |
| 184 | case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK: |
| 185 | case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK: |
| 186 | case VK_DYNAMIC_STATE_STENCIL_REFERENCE: |
| 187 | ASSERT(dynamicState < (sizeof(dynamicStateFlags) * 8)); |
| 188 | dynamicStateFlags |= (1 << dynamicState); |
| 189 | break; |
| 190 | default: |
Nicolas Capens | 44bd43a | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 191 | UNSUPPORTED("VkDynamicState %d", int(dynamicState)); |
Alexis Hetu | 7383243 | 2019-04-11 16:43:18 -0400 | [diff] [blame] | 192 | } |
| 193 | } |
| 194 | } |
| 195 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 196 | const VkPipelineVertexInputStateCreateInfo *vertexInputState = pCreateInfo->pVertexInputState; |
Nicolas Capens | 44bd43a | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 197 | |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 198 | if(vertexInputState->flags != 0) |
| 199 | { |
Nicolas Capens | 44bd43a | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 200 | // Vulkan 1.2: "flags is reserved for future use." "flags must be 0" |
Nicolas Capens | 865f889 | 2020-01-21 14:27:10 -0500 | [diff] [blame] | 201 | UNSUPPORTED("vertexInputState->flags"); |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 202 | } |
| 203 | |
Ben Clayton | 76e9bc0 | 2019-02-26 15:02:18 +0000 | [diff] [blame] | 204 | // Context must always have a PipelineLayout set. |
| 205 | context.pipelineLayout = layout; |
| 206 | |
Chris Forbes | fe3d497 | 2019-02-22 17:21:23 -0800 | [diff] [blame] | 207 | // Temporary in-binding-order representation of buffer strides, to be consumed below |
| 208 | // when considering attributes. TODO: unfuse buffers from attributes in backend, is old GL model. |
Chris Forbes | e1cf863 | 2019-03-08 18:17:35 -0800 | [diff] [blame] | 209 | uint32_t vertexStrides[MAX_VERTEX_INPUT_BINDINGS]; |
| 210 | uint32_t instanceStrides[MAX_VERTEX_INPUT_BINDINGS]; |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 211 | for(uint32_t i = 0; i < vertexInputState->vertexBindingDescriptionCount; i++) |
| 212 | { |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 213 | auto const &desc = vertexInputState->pVertexBindingDescriptions[i]; |
Chris Forbes | e1cf863 | 2019-03-08 18:17:35 -0800 | [diff] [blame] | 214 | vertexStrides[desc.binding] = desc.inputRate == VK_VERTEX_INPUT_RATE_VERTEX ? desc.stride : 0; |
| 215 | instanceStrides[desc.binding] = desc.inputRate == VK_VERTEX_INPUT_RATE_INSTANCE ? desc.stride : 0; |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 216 | } |
| 217 | |
| 218 | for(uint32_t i = 0; i < vertexInputState->vertexAttributeDescriptionCount; i++) |
| 219 | { |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 220 | auto const &desc = vertexInputState->pVertexAttributeDescriptions[i]; |
| 221 | sw::Stream &input = context.input[desc.location]; |
Alexis Hetu | b766e5e | 2020-01-20 11:40:28 -0500 | [diff] [blame] | 222 | input.format = desc.format; |
Chris Forbes | fe3d497 | 2019-02-22 17:21:23 -0800 | [diff] [blame] | 223 | input.offset = desc.offset; |
| 224 | input.binding = desc.binding; |
Chris Forbes | e1cf863 | 2019-03-08 18:17:35 -0800 | [diff] [blame] | 225 | input.vertexStride = vertexStrides[desc.binding]; |
| 226 | input.instanceStride = instanceStrides[desc.binding]; |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 227 | } |
| 228 | |
Nicolas Capens | 44bd43a | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 229 | const VkPipelineInputAssemblyStateCreateInfo *inputAssemblyState = pCreateInfo->pInputAssemblyState; |
| 230 | |
| 231 | if(inputAssemblyState->flags != 0) |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 232 | { |
Nicolas Capens | 44bd43a | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 233 | // Vulkan 1.2: "flags is reserved for future use." "flags must be 0" |
| 234 | UNSUPPORTED("pCreateInfo->pInputAssemblyState->flags %d", int(pCreateInfo->pInputAssemblyState->flags)); |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 235 | } |
| 236 | |
Nicolas Capens | 44bd43a | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 237 | primitiveRestartEnable = (inputAssemblyState->primitiveRestartEnable != VK_FALSE); |
| 238 | context.topology = inputAssemblyState->topology; |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 239 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 240 | const VkPipelineViewportStateCreateInfo *viewportState = pCreateInfo->pViewportState; |
Alexis Hetu | a0a80b1 | 2019-02-15 15:56:14 -0500 | [diff] [blame] | 241 | if(viewportState) |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 242 | { |
Nicolas Capens | 44bd43a | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 243 | if(viewportState->flags != 0) |
| 244 | { |
| 245 | // Vulkan 1.2: "flags is reserved for future use." "flags must be 0" |
| 246 | UNSUPPORTED("pCreateInfo->pViewportState->flags %d", int(pCreateInfo->pViewportState->flags)); |
| 247 | } |
| 248 | |
| 249 | if((viewportState->viewportCount != 1) || |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 250 | (viewportState->scissorCount != 1)) |
Alexis Hetu | a0a80b1 | 2019-02-15 15:56:14 -0500 | [diff] [blame] | 251 | { |
Nicolas Capens | 44bd43a | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 252 | UNSUPPORTED("VkPhysicalDeviceFeatures::multiViewport"); |
Alexis Hetu | a0a80b1 | 2019-02-15 15:56:14 -0500 | [diff] [blame] | 253 | } |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 254 | |
Alexis Hetu | 428c645 | 2019-04-15 09:48:27 -0400 | [diff] [blame] | 255 | if(!hasDynamicState(VK_DYNAMIC_STATE_SCISSOR)) |
| 256 | { |
| 257 | scissor = viewportState->pScissors[0]; |
| 258 | } |
| 259 | |
| 260 | if(!hasDynamicState(VK_DYNAMIC_STATE_VIEWPORT)) |
| 261 | { |
| 262 | viewport = viewportState->pViewports[0]; |
| 263 | } |
Alexis Hetu | a0a80b1 | 2019-02-15 15:56:14 -0500 | [diff] [blame] | 264 | } |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 265 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 266 | const VkPipelineRasterizationStateCreateInfo *rasterizationState = pCreateInfo->pRasterizationState; |
Nicolas Capens | 44bd43a | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 267 | |
| 268 | if(rasterizationState->flags != 0) |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 269 | { |
Nicolas Capens | 44bd43a | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 270 | // Vulkan 1.2: "flags is reserved for future use." "flags must be 0" |
| 271 | UNSUPPORTED("pCreateInfo->pRasterizationState->flags %d", int(pCreateInfo->pRasterizationState->flags)); |
| 272 | } |
| 273 | |
| 274 | if(rasterizationState->depthClampEnable != VK_FALSE) |
| 275 | { |
| 276 | UNSUPPORTED("VkPhysicalDeviceFeatures::depthClamp"); |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 277 | } |
| 278 | |
Nicolas Capens | 8fff8c3 | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 279 | context.rasterizerDiscard = (rasterizationState->rasterizerDiscardEnable != VK_FALSE); |
Chris Forbes | d245255 | 2019-02-22 09:45:06 -0800 | [diff] [blame] | 280 | context.cullMode = rasterizationState->cullMode; |
Alexis Hetu | 72d8104 | 2019-06-10 10:23:23 -0400 | [diff] [blame] | 281 | context.frontFace = rasterizationState->frontFace; |
Ben Clayton | 2210f80 | 2019-08-12 13:55:43 +0100 | [diff] [blame] | 282 | context.polygonMode = rasterizationState->polygonMode; |
Nicolas Capens | 85035be | 2019-06-05 13:54:18 -0400 | [diff] [blame] | 283 | context.depthBias = (rasterizationState->depthBiasEnable != VK_FALSE) ? rasterizationState->depthBiasConstantFactor : 0.0f; |
| 284 | context.slopeDepthBias = (rasterizationState->depthBiasEnable != VK_FALSE) ? rasterizationState->depthBiasSlopeFactor : 0.0f; |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 285 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 286 | const VkBaseInStructure *extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(rasterizationState->pNext); |
Alexis Hetu | 23f9c25 | 2019-10-17 13:58:25 -0400 | [diff] [blame] | 287 | while(extensionCreateInfo) |
| 288 | { |
Alexis Hetu | b07147b | 2019-10-29 12:49:24 -0400 | [diff] [blame] | 289 | // Casting to a long since some structures, such as |
| 290 | // VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT |
| 291 | // are not enumerated in the official Vulkan header |
| 292 | switch((long)(extensionCreateInfo->sType)) |
Alexis Hetu | 23f9c25 | 2019-10-17 13:58:25 -0400 | [diff] [blame] | 293 | { |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 294 | case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT: |
| 295 | { |
| 296 | const VkPipelineRasterizationLineStateCreateInfoEXT *lineStateCreateInfo = reinterpret_cast<const VkPipelineRasterizationLineStateCreateInfoEXT *>(extensionCreateInfo); |
| 297 | context.lineRasterizationMode = lineStateCreateInfo->lineRasterizationMode; |
| 298 | } |
Alexis Hetu | 23f9c25 | 2019-10-17 13:58:25 -0400 | [diff] [blame] | 299 | break; |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 300 | case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT: |
| 301 | { |
| 302 | const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *provokingVertexModeCreateInfo = |
| 303 | reinterpret_cast<const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *>(extensionCreateInfo); |
| 304 | context.provokingVertexMode = provokingVertexModeCreateInfo->provokingVertexMode; |
| 305 | } |
| 306 | break; |
| 307 | default: |
| 308 | WARN("pCreateInfo->pRasterizationState->pNext sType = %s", vk::Stringify(extensionCreateInfo->sType).c_str()); |
| 309 | break; |
Alexis Hetu | 23f9c25 | 2019-10-17 13:58:25 -0400 | [diff] [blame] | 310 | } |
| 311 | |
| 312 | extensionCreateInfo = extensionCreateInfo->pNext; |
| 313 | } |
| 314 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 315 | const VkPipelineMultisampleStateCreateInfo *multisampleState = pCreateInfo->pMultisampleState; |
Alexis Hetu | a0a80b1 | 2019-02-15 15:56:14 -0500 | [diff] [blame] | 316 | if(multisampleState) |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 317 | { |
Nicolas Capens | 44bd43a | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 318 | if(multisampleState->flags != 0) |
| 319 | { |
| 320 | // Vulkan 1.2: "flags is reserved for future use." "flags must be 0" |
| 321 | UNSUPPORTED("pCreateInfo->pMultisampleState->flags %d", int(pCreateInfo->pMultisampleState->flags)); |
| 322 | } |
| 323 | |
| 324 | if(multisampleState->sampleShadingEnable != VK_FALSE) |
| 325 | { |
| 326 | UNSUPPORTED("VkPhysicalDeviceFeatures::sampleRateShading"); |
| 327 | } |
| 328 | |
| 329 | if(multisampleState->alphaToOneEnable != VK_FALSE) |
| 330 | { |
| 331 | UNSUPPORTED("VkPhysicalDeviceFeatures::alphaToOne"); |
| 332 | } |
| 333 | |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 334 | switch(multisampleState->rasterizationSamples) |
Nicolas Capens | 18c9ac4 | 2019-08-27 09:28:27 -0400 | [diff] [blame] | 335 | { |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 336 | case VK_SAMPLE_COUNT_1_BIT: |
| 337 | context.sampleCount = 1; |
| 338 | break; |
| 339 | case VK_SAMPLE_COUNT_4_BIT: |
| 340 | context.sampleCount = 4; |
| 341 | break; |
| 342 | default: |
Nicolas Capens | 865f889 | 2020-01-21 14:27:10 -0500 | [diff] [blame] | 343 | UNSUPPORTED("Unsupported sample count"); |
Chris Forbes | 1054758 | 2019-02-28 10:07:55 -0800 | [diff] [blame] | 344 | } |
| 345 | |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 346 | if(multisampleState->pSampleMask) |
Nicolas Capens | 18c9ac4 | 2019-08-27 09:28:27 -0400 | [diff] [blame] | 347 | { |
Chris Forbes | bbf5cf1 | 2019-03-06 09:00:56 -0800 | [diff] [blame] | 348 | context.sampleMask = multisampleState->pSampleMask[0]; |
Nicolas Capens | 18c9ac4 | 2019-08-27 09:28:27 -0400 | [diff] [blame] | 349 | } |
Chris Forbes | bbf5cf1 | 2019-03-06 09:00:56 -0800 | [diff] [blame] | 350 | |
Nicolas Capens | 8fff8c3 | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 351 | context.alphaToCoverage = (multisampleState->alphaToCoverageEnable != VK_FALSE); |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 352 | } |
Chris Forbes | 1054758 | 2019-02-28 10:07:55 -0800 | [diff] [blame] | 353 | else |
| 354 | { |
| 355 | context.sampleCount = 1; |
| 356 | } |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 357 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 358 | const VkPipelineDepthStencilStateCreateInfo *depthStencilState = pCreateInfo->pDepthStencilState; |
Alexis Hetu | a0a80b1 | 2019-02-15 15:56:14 -0500 | [diff] [blame] | 359 | if(depthStencilState) |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 360 | { |
Nicolas Capens | 44bd43a | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 361 | if(depthStencilState->flags != 0) |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 362 | { |
Nicolas Capens | 44bd43a | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 363 | // Vulkan 1.2: "flags is reserved for future use." "flags must be 0" |
| 364 | UNSUPPORTED("pCreateInfo->pDepthStencilState->flags %d", int(pCreateInfo->pDepthStencilState->flags)); |
| 365 | } |
| 366 | |
| 367 | if(depthStencilState->depthBoundsTestEnable != VK_FALSE) |
| 368 | { |
| 369 | UNSUPPORTED("VkPhysicalDeviceFeatures::depthBounds"); |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 370 | } |
| 371 | |
Nicolas Capens | 8fff8c3 | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 372 | context.depthBoundsTestEnable = (depthStencilState->depthBoundsTestEnable != VK_FALSE); |
| 373 | context.depthBufferEnable = (depthStencilState->depthTestEnable != VK_FALSE); |
| 374 | context.depthWriteEnable = (depthStencilState->depthWriteEnable != VK_FALSE); |
Alexis Hetu | a0a80b1 | 2019-02-15 15:56:14 -0500 | [diff] [blame] | 375 | context.depthCompareMode = depthStencilState->depthCompareOp; |
| 376 | |
Nicolas Capens | 8fff8c3 | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 377 | context.stencilEnable = (depthStencilState->stencilTestEnable != VK_FALSE); |
Alexis Hetu | a0a80b1 | 2019-02-15 15:56:14 -0500 | [diff] [blame] | 378 | if(context.stencilEnable) |
| 379 | { |
Chris Forbes | 1bd9e2f | 2019-03-18 11:41:56 -0700 | [diff] [blame] | 380 | context.frontStencil = depthStencilState->front; |
| 381 | context.backStencil = depthStencilState->back; |
Alexis Hetu | a0a80b1 | 2019-02-15 15:56:14 -0500 | [diff] [blame] | 382 | } |
| 383 | } |
| 384 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 385 | const VkPipelineColorBlendStateCreateInfo *colorBlendState = pCreateInfo->pColorBlendState; |
Alexis Hetu | a0a80b1 | 2019-02-15 15:56:14 -0500 | [diff] [blame] | 386 | if(colorBlendState) |
| 387 | { |
Nicolas Capens | 44bd43a | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 388 | if(pCreateInfo->pColorBlendState->flags != 0) |
Alexis Hetu | a0a80b1 | 2019-02-15 15:56:14 -0500 | [diff] [blame] | 389 | { |
Nicolas Capens | 44bd43a | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 390 | // Vulkan 1.2: "flags is reserved for future use." "flags must be 0" |
| 391 | UNSUPPORTED("pCreateInfo->pColorBlendState->flags %d", int(pCreateInfo->pColorBlendState->flags)); |
| 392 | } |
| 393 | |
| 394 | if(colorBlendState->logicOpEnable != VK_FALSE) |
| 395 | { |
| 396 | UNSUPPORTED("VkPhysicalDeviceFeatures::logicOp"); |
Alexis Hetu | a0a80b1 | 2019-02-15 15:56:14 -0500 | [diff] [blame] | 397 | } |
| 398 | |
Alexis Hetu | 428c645 | 2019-04-15 09:48:27 -0400 | [diff] [blame] | 399 | if(!hasDynamicState(VK_DYNAMIC_STATE_BLEND_CONSTANTS)) |
| 400 | { |
| 401 | blendConstants.r = colorBlendState->blendConstants[0]; |
| 402 | blendConstants.g = colorBlendState->blendConstants[1]; |
| 403 | blendConstants.b = colorBlendState->blendConstants[2]; |
| 404 | blendConstants.a = colorBlendState->blendConstants[3]; |
| 405 | } |
Alexis Hetu | a0a80b1 | 2019-02-15 15:56:14 -0500 | [diff] [blame] | 406 | |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 407 | for(auto i = 0u; i < colorBlendState->attachmentCount; i++) |
Chris Forbes | 558df92 | 2019-05-14 17:33:49 -0700 | [diff] [blame] | 408 | { |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 409 | const VkPipelineColorBlendAttachmentState &attachment = colorBlendState->pAttachments[i]; |
Alexis Hetu | 72d8104 | 2019-06-10 10:23:23 -0400 | [diff] [blame] | 410 | context.colorWriteMask[i] = attachment.colorWriteMask; |
Chris Forbes | 558df92 | 2019-05-14 17:33:49 -0700 | [diff] [blame] | 411 | |
Nicolas Capens | 8fff8c3 | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 412 | context.setBlendState(i, { (attachment.blendEnable != VK_FALSE), |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 413 | attachment.srcColorBlendFactor, attachment.dstColorBlendFactor, attachment.colorBlendOp, |
| 414 | attachment.srcAlphaBlendFactor, attachment.dstAlphaBlendFactor, attachment.alphaBlendOp }); |
Alexis Hetu | a0a80b1 | 2019-02-15 15:56:14 -0500 | [diff] [blame] | 415 | } |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 416 | } |
Chris Forbes | a9da772 | 2019-08-26 12:45:13 -0700 | [diff] [blame] | 417 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 418 | context.multiSampleMask = context.sampleMask & ((unsigned)0xFFFFFFFF >> (32 - context.sampleCount)); |
Alexis Hetu | 000df8b | 2018-10-24 15:22:41 -0400 | [diff] [blame] | 419 | } |
| 420 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 421 | void GraphicsPipeline::destroyPipeline(const VkAllocationCallbacks *pAllocator) |
Alexis Hetu | 000df8b | 2018-10-24 15:22:41 -0400 | [diff] [blame] | 422 | { |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 423 | vertexShader.reset(); |
| 424 | fragmentShader.reset(); |
Alexis Hetu | 000df8b | 2018-10-24 15:22:41 -0400 | [diff] [blame] | 425 | } |
| 426 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 427 | size_t GraphicsPipeline::ComputeRequiredAllocationSize(const VkGraphicsPipelineCreateInfo *pCreateInfo) |
Alexis Hetu | 000df8b | 2018-10-24 15:22:41 -0400 | [diff] [blame] | 428 | { |
| 429 | return 0; |
| 430 | } |
| 431 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 432 | void GraphicsPipeline::setShader(const VkShaderStageFlagBits &stage, const std::shared_ptr<sw::SpirvShader> spirvShader) |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 433 | { |
| 434 | switch(stage) |
| 435 | { |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 436 | case VK_SHADER_STAGE_VERTEX_BIT: |
| 437 | ASSERT(vertexShader.get() == nullptr); |
| 438 | vertexShader = spirvShader; |
| 439 | context.vertexShader = vertexShader.get(); |
| 440 | break; |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 441 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 442 | case VK_SHADER_STAGE_FRAGMENT_BIT: |
| 443 | ASSERT(fragmentShader.get() == nullptr); |
| 444 | fragmentShader = spirvShader; |
| 445 | context.pixelShader = fragmentShader.get(); |
| 446 | break; |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 447 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 448 | default: |
| 449 | UNSUPPORTED("Unsupported stage"); |
| 450 | break; |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 451 | } |
| 452 | } |
| 453 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 454 | const std::shared_ptr<sw::SpirvShader> GraphicsPipeline::getShader(const VkShaderStageFlagBits &stage) const |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 455 | { |
| 456 | switch(stage) |
| 457 | { |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 458 | case VK_SHADER_STAGE_VERTEX_BIT: |
| 459 | return vertexShader; |
| 460 | case VK_SHADER_STAGE_FRAGMENT_BIT: |
| 461 | return fragmentShader; |
| 462 | default: |
| 463 | UNSUPPORTED("Unsupported stage"); |
| 464 | return fragmentShader; |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 465 | } |
| 466 | } |
| 467 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 468 | void GraphicsPipeline::compileShaders(const VkAllocationCallbacks *pAllocator, const VkGraphicsPipelineCreateInfo *pCreateInfo, PipelineCache *pPipelineCache) |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 469 | { |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 470 | for(auto pStage = pCreateInfo->pStages; pStage != pCreateInfo->pStages + pCreateInfo->stageCount; pStage++) |
Chris Forbes | eea21ba | 2019-01-31 07:54:05 -0800 | [diff] [blame] | 471 | { |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 472 | if(pStage->flags != 0) |
Chris Forbes | d1ab73d | 2019-03-14 13:07:08 -0700 | [diff] [blame] | 473 | { |
Nicolas Capens | 44bd43a | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 474 | // Vulkan 1.2: "flags must be 0" |
| 475 | UNSUPPORTED("pStage->flags %d", int(pStage->flags)); |
Chris Forbes | d1ab73d | 2019-03-14 13:07:08 -0700 | [diff] [blame] | 476 | } |
Chris Forbes | af4ed53 | 2018-12-06 18:33:27 -0800 | [diff] [blame] | 477 | |
Nicolas Capens | 4aa4fcd | 2019-06-19 13:14:11 -0400 | [diff] [blame] | 478 | const ShaderModule *module = vk::Cast(pStage->module); |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 479 | const PipelineCache::SpirvShaderKey key(pStage->stage, pStage->pName, module->getCode(), |
| 480 | vk::Cast(pCreateInfo->renderPass), pCreateInfo->subpass, |
| 481 | pStage->pSpecializationInfo); |
Nicolas Capens | a29aa77 | 2019-06-26 00:36:28 -0400 | [diff] [blame] | 482 | auto pipelineStage = key.getPipelineStage(); |
| 483 | |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 484 | if(pPipelineCache) |
Chris Forbes | eea21ba | 2019-01-31 07:54:05 -0800 | [diff] [blame] | 485 | { |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 486 | PipelineCache &pipelineCache = *pPipelineCache; |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 487 | { |
| 488 | std::unique_lock<std::mutex> lock(pipelineCache.getShaderMutex()); |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 489 | const std::shared_ptr<sw::SpirvShader> *spirvShader = pipelineCache[key]; |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 490 | if(!spirvShader) |
| 491 | { |
Ben Clayton | 7d0ce41 | 2019-12-03 13:26:31 +0000 | [diff] [blame] | 492 | auto shader = createShader(key, module, robustBufferAccess, device->getDebuggerContext()); |
Nicolas Capens | a29aa77 | 2019-06-26 00:36:28 -0400 | [diff] [blame] | 493 | setShader(pipelineStage, shader); |
| 494 | pipelineCache.insert(key, getShader(pipelineStage)); |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 495 | } |
| 496 | else |
| 497 | { |
Nicolas Capens | a29aa77 | 2019-06-26 00:36:28 -0400 | [diff] [blame] | 498 | setShader(pipelineStage, *spirvShader); |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 499 | } |
| 500 | } |
| 501 | } |
| 502 | else |
| 503 | { |
Ben Clayton | 7d0ce41 | 2019-12-03 13:26:31 +0000 | [diff] [blame] | 504 | auto shader = createShader(key, module, robustBufferAccess, device->getDebuggerContext()); |
Nicolas Capens | a29aa77 | 2019-06-26 00:36:28 -0400 | [diff] [blame] | 505 | setShader(pipelineStage, shader); |
Chris Forbes | af4ed53 | 2018-12-06 18:33:27 -0800 | [diff] [blame] | 506 | } |
| 507 | } |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 508 | } |
| 509 | |
Alexis Hetu | c65473d | 2018-12-07 16:26:05 -0500 | [diff] [blame] | 510 | uint32_t GraphicsPipeline::computePrimitiveCount(uint32_t vertexCount) const |
| 511 | { |
Alexis Hetu | fcbb145 | 2018-11-22 15:46:28 -0500 | [diff] [blame] | 512 | switch(context.topology) |
Alexis Hetu | c65473d | 2018-12-07 16:26:05 -0500 | [diff] [blame] | 513 | { |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 514 | case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: |
| 515 | return vertexCount; |
| 516 | case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: |
| 517 | return vertexCount / 2; |
| 518 | case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: |
| 519 | return std::max<uint32_t>(vertexCount, 1) - 1; |
| 520 | case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: |
| 521 | return vertexCount / 3; |
| 522 | case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: |
| 523 | return std::max<uint32_t>(vertexCount, 2) - 2; |
| 524 | case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: |
| 525 | return std::max<uint32_t>(vertexCount, 2) - 2; |
| 526 | default: |
Nicolas Capens | 44bd43a | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 527 | UNSUPPORTED("VkPrimitiveTopology %d", int(context.topology)); |
Alexis Hetu | c65473d | 2018-12-07 16:26:05 -0500 | [diff] [blame] | 528 | } |
| 529 | |
| 530 | return 0; |
| 531 | } |
| 532 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 533 | const sw::Context &GraphicsPipeline::getContext() const |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 534 | { |
| 535 | return context; |
| 536 | } |
| 537 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 538 | const VkRect2D &GraphicsPipeline::getScissor() const |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 539 | { |
| 540 | return scissor; |
| 541 | } |
| 542 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 543 | const VkViewport &GraphicsPipeline::getViewport() const |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 544 | { |
| 545 | return viewport; |
| 546 | } |
| 547 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 548 | const sw::Color<float> &GraphicsPipeline::getBlendConstants() const |
Alexis Hetu | c0f92f2 | 2018-11-15 16:25:38 -0500 | [diff] [blame] | 549 | { |
| 550 | return blendConstants; |
| 551 | } |
| 552 | |
Alexis Hetu | 7383243 | 2019-04-11 16:43:18 -0400 | [diff] [blame] | 553 | bool GraphicsPipeline::hasDynamicState(VkDynamicState dynamicState) const |
| 554 | { |
| 555 | return (dynamicStateFlags & (1 << dynamicState)) != 0; |
| 556 | } |
| 557 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 558 | ComputePipeline::ComputePipeline(const VkComputePipelineCreateInfo *pCreateInfo, void *mem, const Device *device) |
| 559 | : Pipeline(vk::Cast(pCreateInfo->layout), device) |
Alexis Hetu | 000df8b | 2018-10-24 15:22:41 -0400 | [diff] [blame] | 560 | { |
| 561 | } |
| 562 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 563 | void ComputePipeline::destroyPipeline(const VkAllocationCallbacks *pAllocator) |
Alexis Hetu | 000df8b | 2018-10-24 15:22:41 -0400 | [diff] [blame] | 564 | { |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 565 | shader.reset(); |
| 566 | program.reset(); |
Alexis Hetu | 000df8b | 2018-10-24 15:22:41 -0400 | [diff] [blame] | 567 | } |
| 568 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 569 | size_t ComputePipeline::ComputeRequiredAllocationSize(const VkComputePipelineCreateInfo *pCreateInfo) |
Alexis Hetu | 000df8b | 2018-10-24 15:22:41 -0400 | [diff] [blame] | 570 | { |
| 571 | return 0; |
| 572 | } |
| 573 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 574 | void ComputePipeline::compileShaders(const VkAllocationCallbacks *pAllocator, const VkComputePipelineCreateInfo *pCreateInfo, PipelineCache *pPipelineCache) |
Ben Clayton | f2be26a | 2019-03-08 12:02:05 +0000 | [diff] [blame] | 575 | { |
Nicolas Capens | 4aa4fcd | 2019-06-19 13:14:11 -0400 | [diff] [blame] | 576 | auto &stage = pCreateInfo->stage; |
| 577 | const ShaderModule *module = vk::Cast(stage.module); |
Ben Clayton | f2be26a | 2019-03-08 12:02:05 +0000 | [diff] [blame] | 578 | |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 579 | ASSERT(shader.get() == nullptr); |
| 580 | ASSERT(program.get() == nullptr); |
Ben Clayton | f2be26a | 2019-03-08 12:02:05 +0000 | [diff] [blame] | 581 | |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 582 | const PipelineCache::SpirvShaderKey shaderKey( |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 583 | stage.stage, stage.pName, module->getCode(), nullptr, 0, stage.pSpecializationInfo); |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 584 | if(pPipelineCache) |
| 585 | { |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 586 | PipelineCache &pipelineCache = *pPipelineCache; |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 587 | { |
| 588 | std::unique_lock<std::mutex> lock(pipelineCache.getShaderMutex()); |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 589 | const std::shared_ptr<sw::SpirvShader> *spirvShader = pipelineCache[shaderKey]; |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 590 | if(!spirvShader) |
| 591 | { |
Ben Clayton | 7d0ce41 | 2019-12-03 13:26:31 +0000 | [diff] [blame] | 592 | shader = createShader(shaderKey, module, robustBufferAccess, device->getDebuggerContext()); |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 593 | pipelineCache.insert(shaderKey, shader); |
| 594 | } |
| 595 | else |
| 596 | { |
| 597 | shader = *spirvShader; |
| 598 | } |
| 599 | } |
Ben Clayton | f2be26a | 2019-03-08 12:02:05 +0000 | [diff] [blame] | 600 | |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 601 | { |
| 602 | const PipelineCache::ComputeProgramKey programKey(shader.get(), layout); |
| 603 | std::unique_lock<std::mutex> lock(pipelineCache.getProgramMutex()); |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 604 | const std::shared_ptr<sw::ComputeProgram> *computeProgram = pipelineCache[programKey]; |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 605 | if(!computeProgram) |
| 606 | { |
| 607 | program = createProgram(programKey); |
| 608 | pipelineCache.insert(programKey, program); |
| 609 | } |
| 610 | else |
| 611 | { |
| 612 | program = *computeProgram; |
| 613 | } |
| 614 | } |
| 615 | } |
| 616 | else |
| 617 | { |
Ben Clayton | 7d0ce41 | 2019-12-03 13:26:31 +0000 | [diff] [blame] | 618 | shader = createShader(shaderKey, module, robustBufferAccess, device->getDebuggerContext()); |
Alexis Hetu | 52edb17 | 2019-06-26 10:17:18 -0400 | [diff] [blame] | 619 | const PipelineCache::ComputeProgramKey programKey(shader.get(), layout); |
| 620 | program = createProgram(programKey); |
| 621 | } |
Ben Clayton | f2be26a | 2019-03-08 12:02:05 +0000 | [diff] [blame] | 622 | } |
| 623 | |
Chris Forbes | 4a4c259 | 2019-05-13 08:53:36 -0700 | [diff] [blame] | 624 | void ComputePipeline::run(uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 625 | uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ, |
| 626 | vk::DescriptorSet::Bindings const &descriptorSets, |
| 627 | vk::DescriptorSet::DynamicOffsets const &descriptorDynamicOffsets, |
| 628 | sw::PushConstantStorage const &pushConstants) |
Ben Clayton | f2be26a | 2019-03-08 12:02:05 +0000 | [diff] [blame] | 629 | { |
Ben Clayton | 895df0d | 2019-05-08 08:49:58 +0100 | [diff] [blame] | 630 | ASSERT_OR_RETURN(program != nullptr); |
| 631 | program->run( |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 632 | descriptorSets, descriptorDynamicOffsets, pushConstants, |
| 633 | baseGroupX, baseGroupY, baseGroupZ, |
| 634 | groupCountX, groupCountY, groupCountZ); |
Ben Clayton | f2be26a | 2019-03-08 12:02:05 +0000 | [diff] [blame] | 635 | } |
| 636 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 637 | } // namespace vk |