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