1*03ce13f7SAndroid Build Coastguard Worker // Copyright 2019 The SwiftShader Authors. All Rights Reserved.
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*03ce13f7SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*03ce13f7SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*03ce13f7SAndroid Build Coastguard Worker //
7*03ce13f7SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
8*03ce13f7SAndroid Build Coastguard Worker //
9*03ce13f7SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*03ce13f7SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*03ce13f7SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*03ce13f7SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*03ce13f7SAndroid Build Coastguard Worker // limitations under the License.
14*03ce13f7SAndroid Build Coastguard Worker
15*03ce13f7SAndroid Build Coastguard Worker #include "SpirvShader.hpp"
16*03ce13f7SAndroid Build Coastguard Worker
17*03ce13f7SAndroid Build Coastguard Worker #include "SamplerCore.hpp"
18*03ce13f7SAndroid Build Coastguard Worker #include "Device/Config.hpp"
19*03ce13f7SAndroid Build Coastguard Worker #include "System/Debug.hpp"
20*03ce13f7SAndroid Build Coastguard Worker #include "System/Math.hpp"
21*03ce13f7SAndroid Build Coastguard Worker #include "Vulkan/VkDescriptorSetLayout.hpp"
22*03ce13f7SAndroid Build Coastguard Worker #include "Vulkan/VkDevice.hpp"
23*03ce13f7SAndroid Build Coastguard Worker #include "Vulkan/VkImageView.hpp"
24*03ce13f7SAndroid Build Coastguard Worker #include "Vulkan/VkSampler.hpp"
25*03ce13f7SAndroid Build Coastguard Worker
26*03ce13f7SAndroid Build Coastguard Worker #include <spirv/unified1/spirv.hpp>
27*03ce13f7SAndroid Build Coastguard Worker
28*03ce13f7SAndroid Build Coastguard Worker #include <climits>
29*03ce13f7SAndroid Build Coastguard Worker #include <mutex>
30*03ce13f7SAndroid Build Coastguard Worker
31*03ce13f7SAndroid Build Coastguard Worker namespace sw {
32*03ce13f7SAndroid Build Coastguard Worker
getImageSampler(const vk::Device * device,uint32_t signature,uint32_t samplerId,uint32_t imageViewId)33*03ce13f7SAndroid Build Coastguard Worker SpirvEmitter::ImageSampler *SpirvEmitter::getImageSampler(const vk::Device *device, uint32_t signature, uint32_t samplerId, uint32_t imageViewId)
34*03ce13f7SAndroid Build Coastguard Worker {
35*03ce13f7SAndroid Build Coastguard Worker ImageInstructionSignature instruction(signature);
36*03ce13f7SAndroid Build Coastguard Worker ASSERT(imageViewId != 0 && (samplerId != 0 || instruction.samplerMethod == Fetch || instruction.samplerMethod == Write));
37*03ce13f7SAndroid Build Coastguard Worker ASSERT(device);
38*03ce13f7SAndroid Build Coastguard Worker
39*03ce13f7SAndroid Build Coastguard Worker vk::Device::SamplingRoutineCache::Key key = { signature, samplerId, imageViewId };
40*03ce13f7SAndroid Build Coastguard Worker
41*03ce13f7SAndroid Build Coastguard Worker auto createSamplingRoutine = [device](const vk::Device::SamplingRoutineCache::Key &key) {
42*03ce13f7SAndroid Build Coastguard Worker ImageInstructionSignature instruction(key.instruction);
43*03ce13f7SAndroid Build Coastguard Worker const vk::Identifier::State imageViewState = vk::Identifier(key.imageView).getState();
44*03ce13f7SAndroid Build Coastguard Worker const vk::SamplerState *vkSamplerState = (key.sampler != 0) ? device->findSampler(key.sampler) : nullptr;
45*03ce13f7SAndroid Build Coastguard Worker
46*03ce13f7SAndroid Build Coastguard Worker auto type = imageViewState.imageViewType;
47*03ce13f7SAndroid Build Coastguard Worker auto samplerMethod = static_cast<SamplerMethod>(instruction.samplerMethod);
48*03ce13f7SAndroid Build Coastguard Worker
49*03ce13f7SAndroid Build Coastguard Worker Sampler samplerState = {};
50*03ce13f7SAndroid Build Coastguard Worker samplerState.textureType = type;
51*03ce13f7SAndroid Build Coastguard Worker ASSERT(instruction.coordinates >= samplerState.dimensionality()); // "It may be a vector larger than needed, but all unused components appear after all used components."
52*03ce13f7SAndroid Build Coastguard Worker samplerState.textureFormat = imageViewState.format;
53*03ce13f7SAndroid Build Coastguard Worker
54*03ce13f7SAndroid Build Coastguard Worker samplerState.addressingModeU = convertAddressingMode(0, vkSamplerState, type);
55*03ce13f7SAndroid Build Coastguard Worker samplerState.addressingModeV = convertAddressingMode(1, vkSamplerState, type);
56*03ce13f7SAndroid Build Coastguard Worker samplerState.addressingModeW = convertAddressingMode(2, vkSamplerState, type);
57*03ce13f7SAndroid Build Coastguard Worker
58*03ce13f7SAndroid Build Coastguard Worker samplerState.mipmapFilter = convertMipmapMode(vkSamplerState);
59*03ce13f7SAndroid Build Coastguard Worker samplerState.swizzle = imageViewState.mapping;
60*03ce13f7SAndroid Build Coastguard Worker samplerState.gatherComponent = instruction.gatherComponent;
61*03ce13f7SAndroid Build Coastguard Worker
62*03ce13f7SAndroid Build Coastguard Worker if(vkSamplerState)
63*03ce13f7SAndroid Build Coastguard Worker {
64*03ce13f7SAndroid Build Coastguard Worker samplerState.textureFilter = convertFilterMode(vkSamplerState, type, samplerMethod);
65*03ce13f7SAndroid Build Coastguard Worker samplerState.border = vkSamplerState->borderColor;
66*03ce13f7SAndroid Build Coastguard Worker samplerState.customBorder = vkSamplerState->customBorderColor;
67*03ce13f7SAndroid Build Coastguard Worker
68*03ce13f7SAndroid Build Coastguard Worker samplerState.mipmapFilter = convertMipmapMode(vkSamplerState);
69*03ce13f7SAndroid Build Coastguard Worker samplerState.highPrecisionFiltering = vkSamplerState->highPrecisionFiltering;
70*03ce13f7SAndroid Build Coastguard Worker
71*03ce13f7SAndroid Build Coastguard Worker samplerState.compareEnable = (vkSamplerState->compareEnable != VK_FALSE);
72*03ce13f7SAndroid Build Coastguard Worker samplerState.compareOp = vkSamplerState->compareOp;
73*03ce13f7SAndroid Build Coastguard Worker samplerState.unnormalizedCoordinates = (vkSamplerState->unnormalizedCoordinates != VK_FALSE);
74*03ce13f7SAndroid Build Coastguard Worker
75*03ce13f7SAndroid Build Coastguard Worker samplerState.ycbcrModel = vkSamplerState->ycbcrModel;
76*03ce13f7SAndroid Build Coastguard Worker samplerState.studioSwing = vkSamplerState->studioSwing;
77*03ce13f7SAndroid Build Coastguard Worker samplerState.swappedChroma = vkSamplerState->swappedChroma;
78*03ce13f7SAndroid Build Coastguard Worker samplerState.chromaFilter = vkSamplerState->chromaFilter == VK_FILTER_LINEAR ? FILTER_LINEAR : FILTER_POINT;
79*03ce13f7SAndroid Build Coastguard Worker samplerState.chromaXOffset = vkSamplerState->chromaXOffset;
80*03ce13f7SAndroid Build Coastguard Worker samplerState.chromaYOffset = vkSamplerState->chromaYOffset;
81*03ce13f7SAndroid Build Coastguard Worker
82*03ce13f7SAndroid Build Coastguard Worker samplerState.mipLodBias = vkSamplerState->mipLodBias;
83*03ce13f7SAndroid Build Coastguard Worker samplerState.maxAnisotropy = vkSamplerState->maxAnisotropy;
84*03ce13f7SAndroid Build Coastguard Worker samplerState.minLod = vkSamplerState->minLod;
85*03ce13f7SAndroid Build Coastguard Worker samplerState.maxLod = vkSamplerState->maxLod;
86*03ce13f7SAndroid Build Coastguard Worker
87*03ce13f7SAndroid Build Coastguard Worker // If there's a single mip level and filtering doesn't depend on the LOD level,
88*03ce13f7SAndroid Build Coastguard Worker // the sampler will need to compute the LOD to produce the proper result.
89*03ce13f7SAndroid Build Coastguard Worker // Otherwise, it can be ignored.
90*03ce13f7SAndroid Build Coastguard Worker // We can skip the LOD computation for all modes, except LOD query,
91*03ce13f7SAndroid Build Coastguard Worker // where we have to return the proper value even if nothing else requires it.
92*03ce13f7SAndroid Build Coastguard Worker if(imageViewState.singleMipLevel &&
93*03ce13f7SAndroid Build Coastguard Worker (samplerState.textureFilter != FILTER_MIN_POINT_MAG_LINEAR) &&
94*03ce13f7SAndroid Build Coastguard Worker (samplerState.textureFilter != FILTER_MIN_LINEAR_MAG_POINT) &&
95*03ce13f7SAndroid Build Coastguard Worker (samplerMethod != Query))
96*03ce13f7SAndroid Build Coastguard Worker {
97*03ce13f7SAndroid Build Coastguard Worker samplerState.minLod = 0.0f;
98*03ce13f7SAndroid Build Coastguard Worker samplerState.maxLod = 0.0f;
99*03ce13f7SAndroid Build Coastguard Worker }
100*03ce13f7SAndroid Build Coastguard Worker }
101*03ce13f7SAndroid Build Coastguard Worker else if(samplerMethod == Fetch)
102*03ce13f7SAndroid Build Coastguard Worker {
103*03ce13f7SAndroid Build Coastguard Worker // OpImageFetch does not take a sampler descriptor, but for VK_EXT_image_robustness
104*03ce13f7SAndroid Build Coastguard Worker // requires replacing invalid texels with zero.
105*03ce13f7SAndroid Build Coastguard Worker // TODO(b/162327166): Only perform bounds checks when VK_EXT_image_robustness is enabled.
106*03ce13f7SAndroid Build Coastguard Worker samplerState.border = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
107*03ce13f7SAndroid Build Coastguard Worker
108*03ce13f7SAndroid Build Coastguard Worker // If there's a single mip level we can skip LOD computation.
109*03ce13f7SAndroid Build Coastguard Worker if(imageViewState.singleMipLevel)
110*03ce13f7SAndroid Build Coastguard Worker {
111*03ce13f7SAndroid Build Coastguard Worker samplerState.minLod = 0.0f;
112*03ce13f7SAndroid Build Coastguard Worker samplerState.maxLod = 0.0f;
113*03ce13f7SAndroid Build Coastguard Worker }
114*03ce13f7SAndroid Build Coastguard Worker // Otherwise make sure LOD is clamped for robustness
115*03ce13f7SAndroid Build Coastguard Worker else
116*03ce13f7SAndroid Build Coastguard Worker {
117*03ce13f7SAndroid Build Coastguard Worker samplerState.minLod = imageViewState.minLod;
118*03ce13f7SAndroid Build Coastguard Worker samplerState.maxLod = imageViewState.maxLod;
119*03ce13f7SAndroid Build Coastguard Worker }
120*03ce13f7SAndroid Build Coastguard Worker }
121*03ce13f7SAndroid Build Coastguard Worker else if(samplerMethod == Write)
122*03ce13f7SAndroid Build Coastguard Worker {
123*03ce13f7SAndroid Build Coastguard Worker return emitWriteRoutine(instruction, samplerState);
124*03ce13f7SAndroid Build Coastguard Worker }
125*03ce13f7SAndroid Build Coastguard Worker else
126*03ce13f7SAndroid Build Coastguard Worker ASSERT(false);
127*03ce13f7SAndroid Build Coastguard Worker
128*03ce13f7SAndroid Build Coastguard Worker return emitSamplerRoutine(instruction, samplerState);
129*03ce13f7SAndroid Build Coastguard Worker };
130*03ce13f7SAndroid Build Coastguard Worker
131*03ce13f7SAndroid Build Coastguard Worker vk::Device::SamplingRoutineCache *cache = device->getSamplingRoutineCache();
132*03ce13f7SAndroid Build Coastguard Worker auto routine = cache->getOrCreate(key, createSamplingRoutine);
133*03ce13f7SAndroid Build Coastguard Worker
134*03ce13f7SAndroid Build Coastguard Worker return (ImageSampler *)(routine->getEntry());
135*03ce13f7SAndroid Build Coastguard Worker }
136*03ce13f7SAndroid Build Coastguard Worker
emitWriteRoutine(ImageInstructionSignature instruction,const Sampler & samplerState)137*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<rr::Routine> SpirvEmitter::emitWriteRoutine(ImageInstructionSignature instruction, const Sampler &samplerState)
138*03ce13f7SAndroid Build Coastguard Worker {
139*03ce13f7SAndroid Build Coastguard Worker // TODO(b/129523279): Hold a separate mutex lock for the sampler being built.
140*03ce13f7SAndroid Build Coastguard Worker rr::Function<Void(Pointer<Byte>, Pointer<SIMD::Float>, Pointer<SIMD::Float>, Pointer<Byte>)> function;
141*03ce13f7SAndroid Build Coastguard Worker {
142*03ce13f7SAndroid Build Coastguard Worker Pointer<Byte> descriptor = function.Arg<0>();
143*03ce13f7SAndroid Build Coastguard Worker Pointer<SIMD::Float> coord = function.Arg<1>();
144*03ce13f7SAndroid Build Coastguard Worker Pointer<SIMD::Float> texelAndMask = function.Arg<2>();
145*03ce13f7SAndroid Build Coastguard Worker Pointer<Byte> constants = function.Arg<3>();
146*03ce13f7SAndroid Build Coastguard Worker
147*03ce13f7SAndroid Build Coastguard Worker WriteImage(instruction, descriptor, coord, texelAndMask, samplerState.textureFormat);
148*03ce13f7SAndroid Build Coastguard Worker }
149*03ce13f7SAndroid Build Coastguard Worker
150*03ce13f7SAndroid Build Coastguard Worker return function("sampler");
151*03ce13f7SAndroid Build Coastguard Worker }
152*03ce13f7SAndroid Build Coastguard Worker
emitSamplerRoutine(ImageInstructionSignature instruction,const Sampler & samplerState)153*03ce13f7SAndroid Build Coastguard Worker std::shared_ptr<rr::Routine> SpirvEmitter::emitSamplerRoutine(ImageInstructionSignature instruction, const Sampler &samplerState)
154*03ce13f7SAndroid Build Coastguard Worker {
155*03ce13f7SAndroid Build Coastguard Worker // TODO(b/129523279): Hold a separate mutex lock for the sampler being built.
156*03ce13f7SAndroid Build Coastguard Worker rr::Function<Void(Pointer<Byte>, Pointer<SIMD::Float>, Pointer<SIMD::Float>, Pointer<Byte>)> function;
157*03ce13f7SAndroid Build Coastguard Worker {
158*03ce13f7SAndroid Build Coastguard Worker Pointer<Byte> texture = function.Arg<0>();
159*03ce13f7SAndroid Build Coastguard Worker Pointer<SIMD::Float> in = function.Arg<1>();
160*03ce13f7SAndroid Build Coastguard Worker Pointer<SIMD::Float> out = function.Arg<2>();
161*03ce13f7SAndroid Build Coastguard Worker Pointer<Byte> constants = function.Arg<3>();
162*03ce13f7SAndroid Build Coastguard Worker
163*03ce13f7SAndroid Build Coastguard Worker SIMD::Float uvwa[4];
164*03ce13f7SAndroid Build Coastguard Worker SIMD::Float dRef;
165*03ce13f7SAndroid Build Coastguard Worker SIMD::Float lodOrBias; // Explicit level-of-detail, or bias added to the implicit level-of-detail (depending on samplerMethod).
166*03ce13f7SAndroid Build Coastguard Worker SIMD::Float dsx[4];
167*03ce13f7SAndroid Build Coastguard Worker SIMD::Float dsy[4];
168*03ce13f7SAndroid Build Coastguard Worker SIMD::Int offset[4];
169*03ce13f7SAndroid Build Coastguard Worker SIMD::Int sampleId;
170*03ce13f7SAndroid Build Coastguard Worker SamplerFunction samplerFunction = instruction.getSamplerFunction();
171*03ce13f7SAndroid Build Coastguard Worker
172*03ce13f7SAndroid Build Coastguard Worker uint32_t i = 0;
173*03ce13f7SAndroid Build Coastguard Worker for(; i < instruction.coordinates; i++)
174*03ce13f7SAndroid Build Coastguard Worker {
175*03ce13f7SAndroid Build Coastguard Worker uvwa[i] = in[i];
176*03ce13f7SAndroid Build Coastguard Worker }
177*03ce13f7SAndroid Build Coastguard Worker
178*03ce13f7SAndroid Build Coastguard Worker if(instruction.isDref())
179*03ce13f7SAndroid Build Coastguard Worker {
180*03ce13f7SAndroid Build Coastguard Worker dRef = in[i];
181*03ce13f7SAndroid Build Coastguard Worker i++;
182*03ce13f7SAndroid Build Coastguard Worker }
183*03ce13f7SAndroid Build Coastguard Worker
184*03ce13f7SAndroid Build Coastguard Worker if(instruction.samplerMethod == Lod || instruction.samplerMethod == Bias || instruction.samplerMethod == Fetch)
185*03ce13f7SAndroid Build Coastguard Worker {
186*03ce13f7SAndroid Build Coastguard Worker lodOrBias = in[i];
187*03ce13f7SAndroid Build Coastguard Worker i++;
188*03ce13f7SAndroid Build Coastguard Worker }
189*03ce13f7SAndroid Build Coastguard Worker else if(instruction.samplerMethod == Grad)
190*03ce13f7SAndroid Build Coastguard Worker {
191*03ce13f7SAndroid Build Coastguard Worker for(uint32_t j = 0; j < instruction.grad; j++, i++)
192*03ce13f7SAndroid Build Coastguard Worker {
193*03ce13f7SAndroid Build Coastguard Worker dsx[j] = in[i];
194*03ce13f7SAndroid Build Coastguard Worker }
195*03ce13f7SAndroid Build Coastguard Worker
196*03ce13f7SAndroid Build Coastguard Worker for(uint32_t j = 0; j < instruction.grad; j++, i++)
197*03ce13f7SAndroid Build Coastguard Worker {
198*03ce13f7SAndroid Build Coastguard Worker dsy[j] = in[i];
199*03ce13f7SAndroid Build Coastguard Worker }
200*03ce13f7SAndroid Build Coastguard Worker }
201*03ce13f7SAndroid Build Coastguard Worker
202*03ce13f7SAndroid Build Coastguard Worker for(uint32_t j = 0; j < instruction.offset; j++, i++)
203*03ce13f7SAndroid Build Coastguard Worker {
204*03ce13f7SAndroid Build Coastguard Worker offset[j] = As<SIMD::Int>(in[i]);
205*03ce13f7SAndroid Build Coastguard Worker }
206*03ce13f7SAndroid Build Coastguard Worker
207*03ce13f7SAndroid Build Coastguard Worker if(instruction.sample)
208*03ce13f7SAndroid Build Coastguard Worker {
209*03ce13f7SAndroid Build Coastguard Worker sampleId = As<SIMD::Int>(in[i]);
210*03ce13f7SAndroid Build Coastguard Worker }
211*03ce13f7SAndroid Build Coastguard Worker
212*03ce13f7SAndroid Build Coastguard Worker SamplerCore s(constants, samplerState, samplerFunction);
213*03ce13f7SAndroid Build Coastguard Worker
214*03ce13f7SAndroid Build Coastguard Worker // For explicit-lod instructions the LOD can be different per SIMD lane. SamplerCore currently assumes
215*03ce13f7SAndroid Build Coastguard Worker // a single LOD per four elements, so we sample the image again for each LOD separately.
216*03ce13f7SAndroid Build Coastguard Worker // TODO(b/133868964) Pass down 4 component lodOrBias, dsx, and dsy to sampleTexture
217*03ce13f7SAndroid Build Coastguard Worker if(samplerFunction.method == Lod || samplerFunction.method == Grad ||
218*03ce13f7SAndroid Build Coastguard Worker samplerFunction.method == Bias || samplerFunction.method == Fetch)
219*03ce13f7SAndroid Build Coastguard Worker {
220*03ce13f7SAndroid Build Coastguard Worker // Only perform per-lane sampling if LOD diverges or we're doing Grad sampling.
221*03ce13f7SAndroid Build Coastguard Worker Bool perLaneSampling = (samplerFunction.method == Grad) || Divergent(As<SIMD::Int>(lodOrBias));
222*03ce13f7SAndroid Build Coastguard Worker auto lod = Pointer<Float>(&lodOrBias);
223*03ce13f7SAndroid Build Coastguard Worker Int i = 0;
224*03ce13f7SAndroid Build Coastguard Worker Do
225*03ce13f7SAndroid Build Coastguard Worker {
226*03ce13f7SAndroid Build Coastguard Worker SIMD::Float dPdx;
227*03ce13f7SAndroid Build Coastguard Worker SIMD::Float dPdy;
228*03ce13f7SAndroid Build Coastguard Worker dPdx.x = Pointer<Float>(&dsx[0])[i];
229*03ce13f7SAndroid Build Coastguard Worker dPdx.y = Pointer<Float>(&dsx[1])[i];
230*03ce13f7SAndroid Build Coastguard Worker dPdx.z = Pointer<Float>(&dsx[2])[i];
231*03ce13f7SAndroid Build Coastguard Worker
232*03ce13f7SAndroid Build Coastguard Worker dPdy.x = Pointer<Float>(&dsy[0])[i];
233*03ce13f7SAndroid Build Coastguard Worker dPdy.y = Pointer<Float>(&dsy[1])[i];
234*03ce13f7SAndroid Build Coastguard Worker dPdy.z = Pointer<Float>(&dsy[2])[i];
235*03ce13f7SAndroid Build Coastguard Worker
236*03ce13f7SAndroid Build Coastguard Worker SIMD::Float4 sample = s.sampleTexture(texture, uvwa, dRef, lod[i], dPdx, dPdy, offset, sampleId);
237*03ce13f7SAndroid Build Coastguard Worker
238*03ce13f7SAndroid Build Coastguard Worker If(perLaneSampling)
239*03ce13f7SAndroid Build Coastguard Worker {
240*03ce13f7SAndroid Build Coastguard Worker Pointer<Float> rgba = out;
241*03ce13f7SAndroid Build Coastguard Worker rgba[0 * SIMD::Width + i] = Pointer<Float>(&sample.x)[i];
242*03ce13f7SAndroid Build Coastguard Worker rgba[1 * SIMD::Width + i] = Pointer<Float>(&sample.y)[i];
243*03ce13f7SAndroid Build Coastguard Worker rgba[2 * SIMD::Width + i] = Pointer<Float>(&sample.z)[i];
244*03ce13f7SAndroid Build Coastguard Worker rgba[3 * SIMD::Width + i] = Pointer<Float>(&sample.w)[i];
245*03ce13f7SAndroid Build Coastguard Worker i++;
246*03ce13f7SAndroid Build Coastguard Worker }
247*03ce13f7SAndroid Build Coastguard Worker Else
248*03ce13f7SAndroid Build Coastguard Worker {
249*03ce13f7SAndroid Build Coastguard Worker Pointer<SIMD::Float> rgba = out;
250*03ce13f7SAndroid Build Coastguard Worker rgba[0] = sample.x;
251*03ce13f7SAndroid Build Coastguard Worker rgba[1] = sample.y;
252*03ce13f7SAndroid Build Coastguard Worker rgba[2] = sample.z;
253*03ce13f7SAndroid Build Coastguard Worker rgba[3] = sample.w;
254*03ce13f7SAndroid Build Coastguard Worker i = SIMD::Width;
255*03ce13f7SAndroid Build Coastguard Worker }
256*03ce13f7SAndroid Build Coastguard Worker }
257*03ce13f7SAndroid Build Coastguard Worker Until(i == SIMD::Width);
258*03ce13f7SAndroid Build Coastguard Worker }
259*03ce13f7SAndroid Build Coastguard Worker else
260*03ce13f7SAndroid Build Coastguard Worker {
261*03ce13f7SAndroid Build Coastguard Worker Float lod = Float(lodOrBias.x);
262*03ce13f7SAndroid Build Coastguard Worker SIMD::Float4 sample = s.sampleTexture(texture, uvwa, dRef, lod, (dsx[0]), (dsy[0]), offset, sampleId);
263*03ce13f7SAndroid Build Coastguard Worker
264*03ce13f7SAndroid Build Coastguard Worker Pointer<SIMD::Float> rgba = out;
265*03ce13f7SAndroid Build Coastguard Worker rgba[0] = sample.x;
266*03ce13f7SAndroid Build Coastguard Worker rgba[1] = sample.y;
267*03ce13f7SAndroid Build Coastguard Worker rgba[2] = sample.z;
268*03ce13f7SAndroid Build Coastguard Worker rgba[3] = sample.w;
269*03ce13f7SAndroid Build Coastguard Worker }
270*03ce13f7SAndroid Build Coastguard Worker }
271*03ce13f7SAndroid Build Coastguard Worker
272*03ce13f7SAndroid Build Coastguard Worker return function("sampler");
273*03ce13f7SAndroid Build Coastguard Worker }
274*03ce13f7SAndroid Build Coastguard Worker
convertFilterMode(const vk::SamplerState * samplerState,VkImageViewType imageViewType,SamplerMethod samplerMethod)275*03ce13f7SAndroid Build Coastguard Worker sw::FilterType SpirvEmitter::convertFilterMode(const vk::SamplerState *samplerState, VkImageViewType imageViewType, SamplerMethod samplerMethod)
276*03ce13f7SAndroid Build Coastguard Worker {
277*03ce13f7SAndroid Build Coastguard Worker if(samplerMethod == Gather)
278*03ce13f7SAndroid Build Coastguard Worker {
279*03ce13f7SAndroid Build Coastguard Worker return FILTER_GATHER;
280*03ce13f7SAndroid Build Coastguard Worker }
281*03ce13f7SAndroid Build Coastguard Worker
282*03ce13f7SAndroid Build Coastguard Worker if(samplerMethod == Fetch)
283*03ce13f7SAndroid Build Coastguard Worker {
284*03ce13f7SAndroid Build Coastguard Worker return FILTER_POINT;
285*03ce13f7SAndroid Build Coastguard Worker }
286*03ce13f7SAndroid Build Coastguard Worker
287*03ce13f7SAndroid Build Coastguard Worker if(samplerState->anisotropyEnable != VK_FALSE)
288*03ce13f7SAndroid Build Coastguard Worker {
289*03ce13f7SAndroid Build Coastguard Worker if(imageViewType == VK_IMAGE_VIEW_TYPE_2D || imageViewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY)
290*03ce13f7SAndroid Build Coastguard Worker {
291*03ce13f7SAndroid Build Coastguard Worker if(samplerMethod != Lod) // TODO(b/162926129): Support anisotropic filtering with explicit LOD.
292*03ce13f7SAndroid Build Coastguard Worker {
293*03ce13f7SAndroid Build Coastguard Worker return FILTER_ANISOTROPIC;
294*03ce13f7SAndroid Build Coastguard Worker }
295*03ce13f7SAndroid Build Coastguard Worker }
296*03ce13f7SAndroid Build Coastguard Worker }
297*03ce13f7SAndroid Build Coastguard Worker
298*03ce13f7SAndroid Build Coastguard Worker switch(samplerState->magFilter)
299*03ce13f7SAndroid Build Coastguard Worker {
300*03ce13f7SAndroid Build Coastguard Worker case VK_FILTER_NEAREST:
301*03ce13f7SAndroid Build Coastguard Worker switch(samplerState->minFilter)
302*03ce13f7SAndroid Build Coastguard Worker {
303*03ce13f7SAndroid Build Coastguard Worker case VK_FILTER_NEAREST: return FILTER_POINT;
304*03ce13f7SAndroid Build Coastguard Worker case VK_FILTER_LINEAR: return FILTER_MIN_LINEAR_MAG_POINT;
305*03ce13f7SAndroid Build Coastguard Worker default:
306*03ce13f7SAndroid Build Coastguard Worker UNSUPPORTED("minFilter %d", samplerState->minFilter);
307*03ce13f7SAndroid Build Coastguard Worker return FILTER_POINT;
308*03ce13f7SAndroid Build Coastguard Worker }
309*03ce13f7SAndroid Build Coastguard Worker break;
310*03ce13f7SAndroid Build Coastguard Worker case VK_FILTER_LINEAR:
311*03ce13f7SAndroid Build Coastguard Worker switch(samplerState->minFilter)
312*03ce13f7SAndroid Build Coastguard Worker {
313*03ce13f7SAndroid Build Coastguard Worker case VK_FILTER_NEAREST: return FILTER_MIN_POINT_MAG_LINEAR;
314*03ce13f7SAndroid Build Coastguard Worker case VK_FILTER_LINEAR: return FILTER_LINEAR;
315*03ce13f7SAndroid Build Coastguard Worker default:
316*03ce13f7SAndroid Build Coastguard Worker UNSUPPORTED("minFilter %d", samplerState->minFilter);
317*03ce13f7SAndroid Build Coastguard Worker return FILTER_POINT;
318*03ce13f7SAndroid Build Coastguard Worker }
319*03ce13f7SAndroid Build Coastguard Worker break;
320*03ce13f7SAndroid Build Coastguard Worker default:
321*03ce13f7SAndroid Build Coastguard Worker break;
322*03ce13f7SAndroid Build Coastguard Worker }
323*03ce13f7SAndroid Build Coastguard Worker
324*03ce13f7SAndroid Build Coastguard Worker UNSUPPORTED("magFilter %d", samplerState->magFilter);
325*03ce13f7SAndroid Build Coastguard Worker return FILTER_POINT;
326*03ce13f7SAndroid Build Coastguard Worker }
327*03ce13f7SAndroid Build Coastguard Worker
convertMipmapMode(const vk::SamplerState * samplerState)328*03ce13f7SAndroid Build Coastguard Worker sw::MipmapType SpirvEmitter::convertMipmapMode(const vk::SamplerState *samplerState)
329*03ce13f7SAndroid Build Coastguard Worker {
330*03ce13f7SAndroid Build Coastguard Worker if(!samplerState)
331*03ce13f7SAndroid Build Coastguard Worker {
332*03ce13f7SAndroid Build Coastguard Worker return MIPMAP_POINT; // Samplerless operations (OpImageFetch) can take an integer Lod operand.
333*03ce13f7SAndroid Build Coastguard Worker }
334*03ce13f7SAndroid Build Coastguard Worker
335*03ce13f7SAndroid Build Coastguard Worker if(samplerState->ycbcrModel != VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY)
336*03ce13f7SAndroid Build Coastguard Worker {
337*03ce13f7SAndroid Build Coastguard Worker // TODO(b/151263485): Check image view level count instead.
338*03ce13f7SAndroid Build Coastguard Worker return MIPMAP_NONE;
339*03ce13f7SAndroid Build Coastguard Worker }
340*03ce13f7SAndroid Build Coastguard Worker
341*03ce13f7SAndroid Build Coastguard Worker switch(samplerState->mipmapMode)
342*03ce13f7SAndroid Build Coastguard Worker {
343*03ce13f7SAndroid Build Coastguard Worker case VK_SAMPLER_MIPMAP_MODE_NEAREST: return MIPMAP_POINT;
344*03ce13f7SAndroid Build Coastguard Worker case VK_SAMPLER_MIPMAP_MODE_LINEAR: return MIPMAP_LINEAR;
345*03ce13f7SAndroid Build Coastguard Worker default:
346*03ce13f7SAndroid Build Coastguard Worker UNSUPPORTED("mipmapMode %d", samplerState->mipmapMode);
347*03ce13f7SAndroid Build Coastguard Worker return MIPMAP_POINT;
348*03ce13f7SAndroid Build Coastguard Worker }
349*03ce13f7SAndroid Build Coastguard Worker }
350*03ce13f7SAndroid Build Coastguard Worker
convertAddressingMode(int coordinateIndex,const vk::SamplerState * samplerState,VkImageViewType imageViewType)351*03ce13f7SAndroid Build Coastguard Worker sw::AddressingMode SpirvEmitter::convertAddressingMode(int coordinateIndex, const vk::SamplerState *samplerState, VkImageViewType imageViewType)
352*03ce13f7SAndroid Build Coastguard Worker {
353*03ce13f7SAndroid Build Coastguard Worker switch(imageViewType)
354*03ce13f7SAndroid Build Coastguard Worker {
355*03ce13f7SAndroid Build Coastguard Worker case VK_IMAGE_VIEW_TYPE_1D:
356*03ce13f7SAndroid Build Coastguard Worker case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
357*03ce13f7SAndroid Build Coastguard Worker if(coordinateIndex >= 1)
358*03ce13f7SAndroid Build Coastguard Worker {
359*03ce13f7SAndroid Build Coastguard Worker return ADDRESSING_UNUSED;
360*03ce13f7SAndroid Build Coastguard Worker }
361*03ce13f7SAndroid Build Coastguard Worker break;
362*03ce13f7SAndroid Build Coastguard Worker case VK_IMAGE_VIEW_TYPE_2D:
363*03ce13f7SAndroid Build Coastguard Worker case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
364*03ce13f7SAndroid Build Coastguard Worker if(coordinateIndex == 2)
365*03ce13f7SAndroid Build Coastguard Worker {
366*03ce13f7SAndroid Build Coastguard Worker return ADDRESSING_UNUSED;
367*03ce13f7SAndroid Build Coastguard Worker }
368*03ce13f7SAndroid Build Coastguard Worker break;
369*03ce13f7SAndroid Build Coastguard Worker
370*03ce13f7SAndroid Build Coastguard Worker case VK_IMAGE_VIEW_TYPE_3D:
371*03ce13f7SAndroid Build Coastguard Worker break;
372*03ce13f7SAndroid Build Coastguard Worker
373*03ce13f7SAndroid Build Coastguard Worker case VK_IMAGE_VIEW_TYPE_CUBE:
374*03ce13f7SAndroid Build Coastguard Worker case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
375*03ce13f7SAndroid Build Coastguard Worker if(coordinateIndex <= 1) // Cube faces themselves are addressed as 2D images.
376*03ce13f7SAndroid Build Coastguard Worker {
377*03ce13f7SAndroid Build Coastguard Worker // Vulkan 1.1 spec:
378*03ce13f7SAndroid Build Coastguard Worker // "Cube images ignore the wrap modes specified in the sampler. Instead, if VK_FILTER_NEAREST is used within a mip level then
379*03ce13f7SAndroid Build Coastguard Worker // VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE is used, and if VK_FILTER_LINEAR is used within a mip level then sampling at the edges
380*03ce13f7SAndroid Build Coastguard Worker // is performed as described earlier in the Cube map edge handling section."
381*03ce13f7SAndroid Build Coastguard Worker // This corresponds with our 'SEAMLESS' addressing mode.
382*03ce13f7SAndroid Build Coastguard Worker return ADDRESSING_SEAMLESS;
383*03ce13f7SAndroid Build Coastguard Worker }
384*03ce13f7SAndroid Build Coastguard Worker else // coordinateIndex == 2
385*03ce13f7SAndroid Build Coastguard Worker {
386*03ce13f7SAndroid Build Coastguard Worker // The cube face is an index into 2D array layers.
387*03ce13f7SAndroid Build Coastguard Worker return ADDRESSING_CUBEFACE;
388*03ce13f7SAndroid Build Coastguard Worker }
389*03ce13f7SAndroid Build Coastguard Worker break;
390*03ce13f7SAndroid Build Coastguard Worker
391*03ce13f7SAndroid Build Coastguard Worker default:
392*03ce13f7SAndroid Build Coastguard Worker UNSUPPORTED("imageViewType %d", imageViewType);
393*03ce13f7SAndroid Build Coastguard Worker return ADDRESSING_WRAP;
394*03ce13f7SAndroid Build Coastguard Worker }
395*03ce13f7SAndroid Build Coastguard Worker
396*03ce13f7SAndroid Build Coastguard Worker if(!samplerState)
397*03ce13f7SAndroid Build Coastguard Worker {
398*03ce13f7SAndroid Build Coastguard Worker // OpImageFetch does not take a sampler descriptor, but still needs a valid
399*03ce13f7SAndroid Build Coastguard Worker // addressing mode that prevents out-of-bounds accesses:
400*03ce13f7SAndroid Build Coastguard Worker // "The value returned by a read of an invalid texel is undefined, unless that
401*03ce13f7SAndroid Build Coastguard Worker // read operation is from a buffer resource and the robustBufferAccess feature
402*03ce13f7SAndroid Build Coastguard Worker // is enabled. In that case, an invalid texel is replaced as described by the
403*03ce13f7SAndroid Build Coastguard Worker // robustBufferAccess feature." - Vulkan 1.1
404*03ce13f7SAndroid Build Coastguard Worker
405*03ce13f7SAndroid Build Coastguard Worker // VK_EXT_image_robustness requires nullifying out-of-bounds accesses.
406*03ce13f7SAndroid Build Coastguard Worker // ADDRESSING_BORDER causes texel replacement to be performed.
407*03ce13f7SAndroid Build Coastguard Worker // TODO(b/162327166): Only perform bounds checks when VK_EXT_image_robustness is enabled.
408*03ce13f7SAndroid Build Coastguard Worker return ADDRESSING_BORDER;
409*03ce13f7SAndroid Build Coastguard Worker }
410*03ce13f7SAndroid Build Coastguard Worker
411*03ce13f7SAndroid Build Coastguard Worker VkSamplerAddressMode addressMode = VK_SAMPLER_ADDRESS_MODE_REPEAT;
412*03ce13f7SAndroid Build Coastguard Worker switch(coordinateIndex)
413*03ce13f7SAndroid Build Coastguard Worker {
414*03ce13f7SAndroid Build Coastguard Worker case 0: addressMode = samplerState->addressModeU; break;
415*03ce13f7SAndroid Build Coastguard Worker case 1: addressMode = samplerState->addressModeV; break;
416*03ce13f7SAndroid Build Coastguard Worker case 2: addressMode = samplerState->addressModeW; break;
417*03ce13f7SAndroid Build Coastguard Worker default: UNSUPPORTED("coordinateIndex: %d", coordinateIndex);
418*03ce13f7SAndroid Build Coastguard Worker }
419*03ce13f7SAndroid Build Coastguard Worker
420*03ce13f7SAndroid Build Coastguard Worker switch(addressMode)
421*03ce13f7SAndroid Build Coastguard Worker {
422*03ce13f7SAndroid Build Coastguard Worker case VK_SAMPLER_ADDRESS_MODE_REPEAT: return ADDRESSING_WRAP;
423*03ce13f7SAndroid Build Coastguard Worker case VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT: return ADDRESSING_MIRROR;
424*03ce13f7SAndroid Build Coastguard Worker case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE: return ADDRESSING_CLAMP;
425*03ce13f7SAndroid Build Coastguard Worker case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER: return ADDRESSING_BORDER;
426*03ce13f7SAndroid Build Coastguard Worker case VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE: return ADDRESSING_MIRRORONCE;
427*03ce13f7SAndroid Build Coastguard Worker default:
428*03ce13f7SAndroid Build Coastguard Worker UNSUPPORTED("addressMode %d", addressMode);
429*03ce13f7SAndroid Build Coastguard Worker return ADDRESSING_WRAP;
430*03ce13f7SAndroid Build Coastguard Worker }
431*03ce13f7SAndroid Build Coastguard Worker }
432*03ce13f7SAndroid Build Coastguard Worker
433*03ce13f7SAndroid Build Coastguard Worker } // namespace sw
434