Nicolas Capens | 68a8238 | 2018-10-02 13:16:55 -0400 | [diff] [blame] | 1 | // Copyright 2016 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 | #ifndef sw_Blitter_hpp |
| 16 | #define sw_Blitter_hpp |
| 17 | |
Ben Clayton | eea9d35 | 2019-08-29 01:05:14 +0100 | [diff] [blame] | 18 | #include "Memset.hpp" |
Nicolas Capens | 68a8238 | 2018-10-02 13:16:55 -0400 | [diff] [blame] | 19 | #include "RoutineCache.hpp" |
| 20 | #include "Reactor/Reactor.hpp" |
Antonio Maiorano | 42fd159 | 2020-04-27 11:30:40 -0400 | [diff] [blame] | 21 | #include "Vulkan/VkFormat.hpp" |
Nicolas Capens | 68a8238 | 2018-10-02 13:16:55 -0400 | [diff] [blame] | 22 | |
Ben Clayton | 377573c | 2020-04-03 20:36:40 +0100 | [diff] [blame] | 23 | #include "marl/mutex.h" |
| 24 | #include "marl/tsa.h" |
| 25 | |
Nicolas Capens | 302a972 | 2019-06-21 12:07:42 -0400 | [diff] [blame] | 26 | #include <cstring> |
Nicolas Capens | 68a8238 | 2018-10-02 13:16:55 -0400 | [diff] [blame] | 27 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 28 | namespace vk { |
Alexis Hetu | 3364227 | 2019-03-01 11:55:59 -0500 | [diff] [blame] | 29 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 30 | class Image; |
| 31 | class Buffer; |
| 32 | |
| 33 | } // namespace vk |
| 34 | |
| 35 | namespace sw { |
| 36 | |
| 37 | class Blitter |
Nicolas Capens | 68a8238 | 2018-10-02 13:16:55 -0400 | [diff] [blame] | 38 | { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 39 | struct Options |
Nicolas Capens | 68a8238 | 2018-10-02 13:16:55 -0400 | [diff] [blame] | 40 | { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 41 | explicit Options() = default; |
| 42 | explicit Options(bool filter, bool allowSRGBConversion) |
Ben Clayton | fccfc56 | 2019-12-17 20:37:31 +0000 | [diff] [blame] | 43 | : writeMask(0xF) |
| 44 | , clearOperation(false) |
| 45 | , filter(filter) |
| 46 | , allowSRGBConversion(allowSRGBConversion) |
| 47 | , clampToEdge(false) |
| 48 | {} |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 49 | explicit Options(unsigned int writeMask) |
Ben Clayton | fccfc56 | 2019-12-17 20:37:31 +0000 | [diff] [blame] | 50 | : writeMask(writeMask) |
| 51 | , clearOperation(true) |
| 52 | , filter(false) |
| 53 | , allowSRGBConversion(true) |
| 54 | , clampToEdge(false) |
| 55 | {} |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 56 | |
| 57 | union |
Nicolas Capens | 68a8238 | 2018-10-02 13:16:55 -0400 | [diff] [blame] | 58 | { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 59 | struct |
Nicolas Capens | 68a8238 | 2018-10-02 13:16:55 -0400 | [diff] [blame] | 60 | { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 61 | bool writeRed : 1; |
| 62 | bool writeGreen : 1; |
| 63 | bool writeBlue : 1; |
| 64 | bool writeAlpha : 1; |
Nicolas Capens | 68a8238 | 2018-10-02 13:16:55 -0400 | [diff] [blame] | 65 | }; |
| 66 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 67 | unsigned char writeMask; |
Nicolas Capens | 68a8238 | 2018-10-02 13:16:55 -0400 | [diff] [blame] | 68 | }; |
| 69 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 70 | bool clearOperation : 1; |
| 71 | bool filter : 1; |
| 72 | bool allowSRGBConversion : 1; |
| 73 | bool clampToEdge : 1; |
Nicolas Capens | 68a8238 | 2018-10-02 13:16:55 -0400 | [diff] [blame] | 74 | }; |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 75 | |
| 76 | struct State : Memset<State>, Options |
| 77 | { |
Ben Clayton | fccfc56 | 2019-12-17 20:37:31 +0000 | [diff] [blame] | 78 | State() |
| 79 | : Memset(this, 0) |
| 80 | {} |
| 81 | State(const Options &options) |
| 82 | : Memset(this, 0) |
| 83 | , Options(options) |
| 84 | {} |
| 85 | State(vk::Format sourceFormat, vk::Format destFormat, int srcSamples, int destSamples, const Options &options) |
| 86 | : Memset(this, 0) |
| 87 | , Options(options) |
| 88 | , sourceFormat(sourceFormat) |
| 89 | , destFormat(destFormat) |
| 90 | , srcSamples(srcSamples) |
| 91 | , destSamples(destSamples) |
| 92 | {} |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 93 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 94 | vk::Format sourceFormat; |
| 95 | vk::Format destFormat; |
| 96 | int srcSamples = 0; |
| 97 | int destSamples = 0; |
Alexis Hetu | 18daa81 | 2020-03-11 17:06:53 -0400 | [diff] [blame] | 98 | bool filter3D = false; |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 99 | }; |
Ben Clayton | ac43aa7 | 2020-04-04 00:48:13 +0100 | [diff] [blame] | 100 | friend std::hash<Blitter::State>; |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 101 | |
| 102 | struct BlitData |
| 103 | { |
| 104 | void *source; |
| 105 | void *dest; |
| 106 | int sPitchB; |
| 107 | int dPitchB; |
| 108 | int sSliceB; |
| 109 | int dSliceB; |
| 110 | |
| 111 | float x0; |
| 112 | float y0; |
Alexis Hetu | 18daa81 | 2020-03-11 17:06:53 -0400 | [diff] [blame] | 113 | float z0; |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 114 | float w; |
| 115 | float h; |
Alexis Hetu | 18daa81 | 2020-03-11 17:06:53 -0400 | [diff] [blame] | 116 | float d; |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 117 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 118 | int x0d; |
| 119 | int x1d; |
Alexis Hetu | 18daa81 | 2020-03-11 17:06:53 -0400 | [diff] [blame] | 120 | int y0d; |
| 121 | int y1d; |
| 122 | int z0d; |
| 123 | int z1d; |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 124 | |
| 125 | int sWidth; |
| 126 | int sHeight; |
Alexis Hetu | 18daa81 | 2020-03-11 17:06:53 -0400 | [diff] [blame] | 127 | int sDepth; |
| 128 | |
| 129 | bool filter3D; |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 130 | }; |
| 131 | |
| 132 | struct CubeBorderData |
| 133 | { |
| 134 | void *layers; |
| 135 | int pitchB; |
| 136 | uint32_t layerSize; |
| 137 | uint32_t dim; |
| 138 | }; |
| 139 | |
| 140 | public: |
| 141 | Blitter(); |
| 142 | virtual ~Blitter(); |
| 143 | |
Ben Clayton | fccfc56 | 2019-12-17 20:37:31 +0000 | [diff] [blame] | 144 | void clear(void *pixel, vk::Format format, vk::Image *dest, const vk::Format &viewFormat, const VkImageSubresourceRange &subresourceRange, const VkRect2D *renderArea = nullptr); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 145 | |
| 146 | void blit(const vk::Image *src, vk::Image *dst, VkImageBlit region, VkFilter filter); |
| 147 | void blitToBuffer(const vk::Image *src, VkImageSubresourceLayers subresource, VkOffset3D offset, VkExtent3D extent, uint8_t *dst, int bufferRowPitch, int bufferSlicePitch); |
| 148 | void blitFromBuffer(const vk::Image *dst, VkImageSubresourceLayers subresource, VkOffset3D offset, VkExtent3D extent, uint8_t *src, int bufferRowPitch, int bufferSlicePitch); |
| 149 | |
Ben Clayton | fccfc56 | 2019-12-17 20:37:31 +0000 | [diff] [blame] | 150 | void updateBorders(vk::Image *image, const VkImageSubresourceLayers &subresourceLayers); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 151 | |
| 152 | private: |
Ben Clayton | fccfc56 | 2019-12-17 20:37:31 +0000 | [diff] [blame] | 153 | enum Edge |
| 154 | { |
| 155 | TOP, |
| 156 | BOTTOM, |
| 157 | RIGHT, |
| 158 | LEFT |
| 159 | }; |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 160 | |
Ben Clayton | fccfc56 | 2019-12-17 20:37:31 +0000 | [diff] [blame] | 161 | bool fastClear(void *pixel, vk::Format format, vk::Image *dest, const vk::Format &viewFormat, const VkImageSubresourceRange &subresourceRange, const VkRect2D *renderArea); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 162 | |
| 163 | Float4 readFloat4(Pointer<Byte> element, const State &state); |
| 164 | void write(Float4 &color, Pointer<Byte> element, const State &state); |
| 165 | Int4 readInt4(Pointer<Byte> element, const State &state); |
| 166 | void write(Int4 &color, Pointer<Byte> element, const State &state); |
| 167 | static void ApplyScaleAndClamp(Float4 &value, const State &state, bool preScaled = false); |
| 168 | static Int ComputeOffset(Int &x, Int &y, Int &pitchB, int bytes); |
Alexis Hetu | 18daa81 | 2020-03-11 17:06:53 -0400 | [diff] [blame] | 169 | static Int ComputeOffset(Int &x, Int &y, Int &z, Int &sliceB, Int &pitchB, int bytes); |
Nicolas Capens | 2883de9 | 2020-01-27 14:58:14 -0500 | [diff] [blame] | 170 | static Float4 LinearToSRGB(const Float4 &color); |
| 171 | static Float4 sRGBtoLinear(const Float4 &color); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 172 | |
Ben Clayton | fccfc56 | 2019-12-17 20:37:31 +0000 | [diff] [blame] | 173 | using BlitFunction = FunctionT<void(const BlitData *)>; |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 174 | using BlitRoutineType = BlitFunction::RoutineType; |
| 175 | BlitRoutineType getBlitRoutine(const State &state); |
| 176 | BlitRoutineType generate(const State &state); |
Alexis Hetu | 18daa81 | 2020-03-11 17:06:53 -0400 | [diff] [blame] | 177 | Float4 sample(Pointer<Byte> &source, Float &x, Float &y, Float &z, |
| 178 | Int &sWidth, Int &sHeight, Int &sDepth, |
| 179 | Int &sSliceB, Int &sPitchB, const State &state); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 180 | |
Ben Clayton | fccfc56 | 2019-12-17 20:37:31 +0000 | [diff] [blame] | 181 | using CornerUpdateFunction = FunctionT<void(const CubeBorderData *)>; |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 182 | using CornerUpdateRoutineType = CornerUpdateFunction::RoutineType; |
| 183 | CornerUpdateRoutineType getCornerUpdateRoutine(const State &state); |
Ben Clayton | fccfc56 | 2019-12-17 20:37:31 +0000 | [diff] [blame] | 184 | CornerUpdateRoutineType generateCornerUpdate(const State &state); |
| 185 | void computeCubeCorner(Pointer<Byte> &layer, Int &x0, Int &x1, Int &y0, Int &y1, Int &pitchB, const State &state); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 186 | |
Ben Clayton | fccfc56 | 2019-12-17 20:37:31 +0000 | [diff] [blame] | 187 | void copyCubeEdge(vk::Image *image, |
| 188 | const VkImageSubresourceLayers &dstSubresourceLayers, Edge dstEdge, |
| 189 | const VkImageSubresourceLayers &srcSubresourceLayers, Edge srcEdge); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 190 | |
Ben Clayton | 377573c | 2020-04-03 20:36:40 +0100 | [diff] [blame] | 191 | marl::mutex blitMutex; |
| 192 | RoutineCache<State, BlitFunction::CFunctionType> blitCache GUARDED_BY(blitMutex); |
| 193 | |
| 194 | marl::mutex cornerUpdateMutex; |
| 195 | RoutineCache<State, CornerUpdateFunction::CFunctionType> cornerUpdateCache GUARDED_BY(cornerUpdateMutex); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 196 | }; |
| 197 | |
| 198 | } // namespace sw |
Nicolas Capens | 68a8238 | 2018-10-02 13:16:55 -0400 | [diff] [blame] | 199 | |
Ben Clayton | ac43aa7 | 2020-04-04 00:48:13 +0100 | [diff] [blame] | 200 | namespace std { |
| 201 | |
| 202 | template<> |
| 203 | struct hash<sw::Blitter::State> |
| 204 | { |
| 205 | uint64_t operator()(const sw::Blitter::State &state) const |
| 206 | { |
| 207 | uint64_t hash = state.sourceFormat; |
| 208 | hash = hash * 31 + state.destFormat; |
| 209 | hash = hash * 31 + state.srcSamples; |
| 210 | hash = hash * 31 + state.destSamples; |
| 211 | hash = hash * 31 + state.filter3D; |
| 212 | return hash; |
| 213 | } |
| 214 | }; |
| 215 | |
| 216 | } // namespace std |
| 217 | |
Ben Clayton | fccfc56 | 2019-12-17 20:37:31 +0000 | [diff] [blame] | 218 | #endif // sw_Blitter_hpp |