Chris Forbes | af4ed53 | 2018-12-06 18:33:27 -0800 | [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 <spirv/unified1/spirv.hpp> |
| 16 | #include "SpirvShader.hpp" |
| 17 | #include "System/Math.hpp" |
| 18 | #include "System/Debug.hpp" |
| 19 | #include "Device/Config.hpp" |
| 20 | |
| 21 | namespace sw |
| 22 | { |
| 23 | volatile int SpirvShader::serialCounter = 1; // Start at 1, 0 is invalid shader. |
| 24 | |
| 25 | SpirvShader::SpirvShader(InsnStore const &insns) : insns{insns}, serialID{serialCounter++}, modes{} |
| 26 | { |
| 27 | // Simplifying assumptions (to be satisfied by earlier transformations) |
| 28 | // - There is exactly one extrypoint in the module, and it's the one we want |
| 29 | // - Input / Output interface blocks, builtin or otherwise, have been split. |
| 30 | // - The only input/output OpVariables present are those used by the entrypoint |
| 31 | |
Chris Forbes | 4a979dc | 2019-01-17 09:36:46 -0800 | [diff] [blame^] | 32 | for (auto insn : *this) |
| 33 | { |
| 34 | switch (insn.opcode()) |
| 35 | { |
| 36 | case spv::OpExecutionMode: |
| 37 | ProcessExecutionMode(insn); |
| 38 | break; |
Chris Forbes | af4ed53 | 2018-12-06 18:33:27 -0800 | [diff] [blame] | 39 | |
Chris Forbes | 4a979dc | 2019-01-17 09:36:46 -0800 | [diff] [blame^] | 40 | case spv::OpTypeVoid: |
| 41 | case spv::OpTypeBool: |
| 42 | case spv::OpTypeInt: |
| 43 | case spv::OpTypeFloat: |
| 44 | case spv::OpTypeVector: |
| 45 | case spv::OpTypeMatrix: |
| 46 | case spv::OpTypeImage: |
| 47 | case spv::OpTypeSampler: |
| 48 | case spv::OpTypeSampledImage: |
| 49 | case spv::OpTypeArray: |
| 50 | case spv::OpTypeRuntimeArray: |
| 51 | case spv::OpTypeStruct: |
| 52 | case spv::OpTypePointer: |
| 53 | case spv::OpTypeFunction: |
| 54 | { |
| 55 | auto resultId = insn.word(1); |
| 56 | auto &object = defs[resultId]; |
| 57 | object.kind = Object::Kind::Type; |
| 58 | object.definition = insn; |
| 59 | break; |
| 60 | } |
Chris Forbes | 296aa25 | 2018-12-27 11:48:21 -0800 | [diff] [blame] | 61 | |
Chris Forbes | 4a979dc | 2019-01-17 09:36:46 -0800 | [diff] [blame^] | 62 | case spv::OpVariable: |
| 63 | { |
| 64 | auto typeId = insn.word(1); |
| 65 | auto resultId = insn.word(2); |
| 66 | auto storageClass = static_cast<spv::StorageClass>(insn.word(3)); |
| 67 | if (insn.wordCount() > 4) |
| 68 | UNIMPLEMENTED("Variable initializers not yet supported"); |
Chris Forbes | 296aa25 | 2018-12-27 11:48:21 -0800 | [diff] [blame] | 69 | |
Chris Forbes | 4a979dc | 2019-01-17 09:36:46 -0800 | [diff] [blame^] | 70 | auto &object = defs[resultId]; |
| 71 | object.kind = Object::Kind::Variable; |
| 72 | object.definition = insn; |
| 73 | object.storageClass = storageClass; |
| 74 | break; |
| 75 | } |
Chris Forbes | 296aa25 | 2018-12-27 11:48:21 -0800 | [diff] [blame] | 76 | |
Chris Forbes | 4a979dc | 2019-01-17 09:36:46 -0800 | [diff] [blame^] | 77 | default: |
| 78 | break; // This is OK, these passes are intentionally partial |
Chris Forbes | af4ed53 | 2018-12-06 18:33:27 -0800 | [diff] [blame] | 79 | } |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | void SpirvShader::ProcessExecutionMode(InsnIterator insn) |
| 84 | { |
| 85 | auto mode = static_cast<spv::ExecutionMode>(insn.word(2)); |
Chris Forbes | 4a979dc | 2019-01-17 09:36:46 -0800 | [diff] [blame^] | 86 | switch (mode) |
| 87 | { |
| 88 | case spv::ExecutionModeEarlyFragmentTests: |
| 89 | modes.EarlyFragmentTests = true; |
| 90 | break; |
| 91 | case spv::ExecutionModeDepthReplacing: |
| 92 | modes.DepthReplacing = true; |
| 93 | break; |
| 94 | case spv::ExecutionModeDepthGreater: |
| 95 | modes.DepthGreater = true; |
| 96 | break; |
| 97 | case spv::ExecutionModeDepthLess: |
| 98 | modes.DepthLess = true; |
| 99 | break; |
| 100 | case spv::ExecutionModeDepthUnchanged: |
| 101 | modes.DepthUnchanged = true; |
| 102 | break; |
| 103 | case spv::ExecutionModeLocalSize: |
| 104 | modes.LocalSizeX = insn.word(3); |
| 105 | modes.LocalSizeZ = insn.word(5); |
| 106 | modes.LocalSizeY = insn.word(4); |
| 107 | break; |
| 108 | case spv::ExecutionModeOriginUpperLeft: |
| 109 | // This is always the case for a Vulkan shader. Do nothing. |
| 110 | break; |
| 111 | default: |
| 112 | UNIMPLEMENTED("No other execution modes are permitted"); |
Chris Forbes | af4ed53 | 2018-12-06 18:33:27 -0800 | [diff] [blame] | 113 | } |
| 114 | } |
| 115 | } |