blob: 2e6f946f5538241799561b9f89e21d3368521bb7 [file] [log] [blame]
Nicolas Capens68a82382018-10-02 13:16:55 -04001// 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 Claytoneea9d352019-08-29 01:05:14 +010018#include "Memset.hpp"
Nicolas Capens68a82382018-10-02 13:16:55 -040019#include "RoutineCache.hpp"
20#include "Reactor/Reactor.hpp"
Antonio Maiorano42fd1592020-04-27 11:30:40 -040021#include "Vulkan/VkFormat.hpp"
Nicolas Capens68a82382018-10-02 13:16:55 -040022
Ben Clayton377573c2020-04-03 20:36:40 +010023#include "marl/mutex.h"
24#include "marl/tsa.h"
25
Nicolas Capens302a9722019-06-21 12:07:42 -040026#include <cstring>
Nicolas Capens68a82382018-10-02 13:16:55 -040027
Nicolas Capens157ba262019-12-10 17:49:14 -050028namespace vk {
Alexis Hetu33642272019-03-01 11:55:59 -050029
Nicolas Capens157ba262019-12-10 17:49:14 -050030class Image;
31class Buffer;
32
33} // namespace vk
34
35namespace sw {
36
37class Blitter
Nicolas Capens68a82382018-10-02 13:16:55 -040038{
Nicolas Capens157ba262019-12-10 17:49:14 -050039 struct Options
Nicolas Capens68a82382018-10-02 13:16:55 -040040 {
Nicolas Capens157ba262019-12-10 17:49:14 -050041 explicit Options() = default;
42 explicit Options(bool filter, bool allowSRGBConversion)
Ben Claytonfccfc562019-12-17 20:37:31 +000043 : writeMask(0xF)
44 , clearOperation(false)
45 , filter(filter)
46 , allowSRGBConversion(allowSRGBConversion)
47 , clampToEdge(false)
48 {}
Nicolas Capens157ba262019-12-10 17:49:14 -050049 explicit Options(unsigned int writeMask)
Ben Claytonfccfc562019-12-17 20:37:31 +000050 : writeMask(writeMask)
51 , clearOperation(true)
52 , filter(false)
53 , allowSRGBConversion(true)
54 , clampToEdge(false)
55 {}
Nicolas Capens157ba262019-12-10 17:49:14 -050056
57 union
Nicolas Capens68a82382018-10-02 13:16:55 -040058 {
Nicolas Capens157ba262019-12-10 17:49:14 -050059 struct
Nicolas Capens68a82382018-10-02 13:16:55 -040060 {
Nicolas Capens157ba262019-12-10 17:49:14 -050061 bool writeRed : 1;
62 bool writeGreen : 1;
63 bool writeBlue : 1;
64 bool writeAlpha : 1;
Nicolas Capens68a82382018-10-02 13:16:55 -040065 };
66
Nicolas Capens157ba262019-12-10 17:49:14 -050067 unsigned char writeMask;
Nicolas Capens68a82382018-10-02 13:16:55 -040068 };
69
Nicolas Capens157ba262019-12-10 17:49:14 -050070 bool clearOperation : 1;
71 bool filter : 1;
72 bool allowSRGBConversion : 1;
73 bool clampToEdge : 1;
Nicolas Capens68a82382018-10-02 13:16:55 -040074 };
Nicolas Capens157ba262019-12-10 17:49:14 -050075
76 struct State : Memset<State>, Options
77 {
Ben Claytonfccfc562019-12-17 20:37:31 +000078 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 Capens157ba262019-12-10 17:49:14 -050093
Nicolas Capens157ba262019-12-10 17:49:14 -050094 vk::Format sourceFormat;
95 vk::Format destFormat;
96 int srcSamples = 0;
97 int destSamples = 0;
Alexis Hetu18daa812020-03-11 17:06:53 -040098 bool filter3D = false;
Nicolas Capens157ba262019-12-10 17:49:14 -050099 };
Ben Claytonac43aa72020-04-04 00:48:13 +0100100 friend std::hash<Blitter::State>;
Nicolas Capens157ba262019-12-10 17:49:14 -0500101
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 Hetu18daa812020-03-11 17:06:53 -0400113 float z0;
Nicolas Capens157ba262019-12-10 17:49:14 -0500114 float w;
115 float h;
Alexis Hetu18daa812020-03-11 17:06:53 -0400116 float d;
Nicolas Capens157ba262019-12-10 17:49:14 -0500117
Nicolas Capens157ba262019-12-10 17:49:14 -0500118 int x0d;
119 int x1d;
Alexis Hetu18daa812020-03-11 17:06:53 -0400120 int y0d;
121 int y1d;
122 int z0d;
123 int z1d;
Nicolas Capens157ba262019-12-10 17:49:14 -0500124
125 int sWidth;
126 int sHeight;
Alexis Hetu18daa812020-03-11 17:06:53 -0400127 int sDepth;
128
129 bool filter3D;
Nicolas Capens157ba262019-12-10 17:49:14 -0500130 };
131
132 struct CubeBorderData
133 {
134 void *layers;
135 int pitchB;
136 uint32_t layerSize;
137 uint32_t dim;
138 };
139
140public:
141 Blitter();
142 virtual ~Blitter();
143
Ben Claytonfccfc562019-12-17 20:37:31 +0000144 void clear(void *pixel, vk::Format format, vk::Image *dest, const vk::Format &viewFormat, const VkImageSubresourceRange &subresourceRange, const VkRect2D *renderArea = nullptr);
Nicolas Capens157ba262019-12-10 17:49:14 -0500145
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 Claytonfccfc562019-12-17 20:37:31 +0000150 void updateBorders(vk::Image *image, const VkImageSubresourceLayers &subresourceLayers);
Nicolas Capens157ba262019-12-10 17:49:14 -0500151
152private:
Ben Claytonfccfc562019-12-17 20:37:31 +0000153 enum Edge
154 {
155 TOP,
156 BOTTOM,
157 RIGHT,
158 LEFT
159 };
Nicolas Capens157ba262019-12-10 17:49:14 -0500160
Ben Claytonfccfc562019-12-17 20:37:31 +0000161 bool fastClear(void *pixel, vk::Format format, vk::Image *dest, const vk::Format &viewFormat, const VkImageSubresourceRange &subresourceRange, const VkRect2D *renderArea);
Nicolas Capens157ba262019-12-10 17:49:14 -0500162
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 Hetu18daa812020-03-11 17:06:53 -0400169 static Int ComputeOffset(Int &x, Int &y, Int &z, Int &sliceB, Int &pitchB, int bytes);
Nicolas Capens2883de92020-01-27 14:58:14 -0500170 static Float4 LinearToSRGB(const Float4 &color);
171 static Float4 sRGBtoLinear(const Float4 &color);
Nicolas Capens157ba262019-12-10 17:49:14 -0500172
Ben Claytonfccfc562019-12-17 20:37:31 +0000173 using BlitFunction = FunctionT<void(const BlitData *)>;
Nicolas Capens157ba262019-12-10 17:49:14 -0500174 using BlitRoutineType = BlitFunction::RoutineType;
175 BlitRoutineType getBlitRoutine(const State &state);
176 BlitRoutineType generate(const State &state);
Alexis Hetu18daa812020-03-11 17:06:53 -0400177 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 Capens157ba262019-12-10 17:49:14 -0500180
Ben Claytonfccfc562019-12-17 20:37:31 +0000181 using CornerUpdateFunction = FunctionT<void(const CubeBorderData *)>;
Nicolas Capens157ba262019-12-10 17:49:14 -0500182 using CornerUpdateRoutineType = CornerUpdateFunction::RoutineType;
183 CornerUpdateRoutineType getCornerUpdateRoutine(const State &state);
Ben Claytonfccfc562019-12-17 20:37:31 +0000184 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 Capens157ba262019-12-10 17:49:14 -0500186
Ben Claytonfccfc562019-12-17 20:37:31 +0000187 void copyCubeEdge(vk::Image *image,
188 const VkImageSubresourceLayers &dstSubresourceLayers, Edge dstEdge,
189 const VkImageSubresourceLayers &srcSubresourceLayers, Edge srcEdge);
Nicolas Capens157ba262019-12-10 17:49:14 -0500190
Ben Clayton377573c2020-04-03 20:36:40 +0100191 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 Capens157ba262019-12-10 17:49:14 -0500196};
197
198} // namespace sw
Nicolas Capens68a82382018-10-02 13:16:55 -0400199
Ben Claytonac43aa72020-04-04 00:48:13 +0100200namespace std {
201
202template<>
203struct 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 Claytonfccfc562019-12-17 20:37:31 +0000218#endif // sw_Blitter_hpp