Dynamic dispatch for image samplers
Bug: b/130746922
Change-Id: I35dfcb93c8e902d0be566fad50ae991d5490e853
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/29348
Tested-by: Ben Clayton <bclayton@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Pipeline/SpirvShaderSampling.cpp b/src/Pipeline/SpirvShaderSampling.cpp
new file mode 100644
index 0000000..e90aad0
--- /dev/null
+++ b/src/Pipeline/SpirvShaderSampling.cpp
@@ -0,0 +1,132 @@
+// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+
+#include "SpirvShader.hpp"
+
+#include "SamplerCore.hpp" // TODO: Figure out what's needed.
+#include "System/Math.hpp"
+#include "Vulkan/VkBuffer.hpp"
+#include "Vulkan/VkDebug.hpp"
+#include "Vulkan/VkDescriptorSet.hpp"
+#include "Vulkan/VkPipelineLayout.hpp"
+#include "Vulkan/VkImageView.hpp"
+#include "Vulkan/VkSampler.hpp"
+#include "Vulkan/VkDescriptorSetLayout.hpp"
+#include "Device/Config.hpp"
+
+#include <spirv/unified1/spirv.hpp>
+#include <spirv/unified1/GLSL.std.450.h>
+
+
+#include <mutex>
+
+#ifdef Bool
+#undef Bool // b/127920555
+#undef None
+#endif
+
+namespace sw {
+
+SpirvShader::ImageSampler *SpirvShader::getImageSampler(vk::ImageView *imageView, vk::Sampler *sampler)
+{
+ // TODO: Move somewhere sensible.
+ static std::unordered_map<uintptr_t, ImageSampler*> cache;
+ static std::mutex mutex;
+
+ // TODO: Don't use pointers they can be deleted and reused, combine some two
+ // unique ids.
+ auto key = reinterpret_cast<uintptr_t>(imageView) ^ reinterpret_cast<uintptr_t>(sampler);
+
+ std::unique_lock<std::mutex> lock(mutex);
+ auto it = cache.find(key);
+ if (it != cache.end()) { return it->second; }
+
+ // TODO: Hold a separate mutex lock for the sampler being built.
+ auto function = rr::Function<Void(Pointer<Byte> image, Pointer<SIMD::Float>, Pointer<SIMD::Float>)>();
+ Pointer<Byte> image = function.Arg<0>();
+ Pointer<SIMD::Float> in = function.Arg<1>();
+ Pointer<SIMD::Float> out = function.Arg<2>();
+ emitSamplerFunction(imageView, sampler, image, in, out);
+ auto fptr = reinterpret_cast<ImageSampler*>((void *)function("sampler")->getEntry());
+ cache.emplace(key, fptr);
+ return fptr;
+}
+
+void SpirvShader::emitSamplerFunction(
+ vk::ImageView *imageView, vk::Sampler *sampler,
+ Pointer<Byte> image, Pointer<SIMD::Float> in, Pointer<Byte> out)
+{
+ SIMD::Float u = in[0];
+ SIMD::Float v = in[1];
+
+ Pointer<Byte> constants; // FIXME(b/129523279)
+
+ Sampler::State samplerState;
+ samplerState.textureType = TEXTURE_2D; ASSERT(imageView->getType() == VK_IMAGE_VIEW_TYPE_2D); // TODO(b/129523279)
+ samplerState.textureFormat = imageView->getFormat();
+ samplerState.textureFilter = FILTER_POINT; ASSERT(sampler->magFilter == VK_FILTER_NEAREST); ASSERT(sampler->minFilter == VK_FILTER_NEAREST); // TODO(b/129523279)
+
+ samplerState.addressingModeU = ADDRESSING_WRAP; ASSERT(sampler->addressModeU == VK_SAMPLER_ADDRESS_MODE_REPEAT); // TODO(b/129523279)
+ samplerState.addressingModeV = ADDRESSING_WRAP; ASSERT(sampler->addressModeV == VK_SAMPLER_ADDRESS_MODE_REPEAT); // TODO(b/129523279)
+ samplerState.addressingModeW = ADDRESSING_WRAP; ASSERT(sampler->addressModeW == VK_SAMPLER_ADDRESS_MODE_REPEAT); // TODO(b/129523279)
+ samplerState.mipmapFilter = MIPMAP_POINT; ASSERT(sampler->mipmapMode == VK_SAMPLER_MIPMAP_MODE_NEAREST); // TODO(b/129523279)
+ samplerState.sRGB = false; ASSERT(imageView->getFormat().isSRGBformat() == false); // TODO(b/129523279)
+ samplerState.swizzleR = SWIZZLE_RED; ASSERT(imageView->getComponentMapping().r == VK_COMPONENT_SWIZZLE_R); // TODO(b/129523279)
+ samplerState.swizzleG = SWIZZLE_GREEN; ASSERT(imageView->getComponentMapping().g == VK_COMPONENT_SWIZZLE_G); // TODO(b/129523279)
+ samplerState.swizzleB = SWIZZLE_BLUE; ASSERT(imageView->getComponentMapping().b == VK_COMPONENT_SWIZZLE_B); // TODO(b/129523279)
+ samplerState.swizzleA = SWIZZLE_ALPHA; ASSERT(imageView->getComponentMapping().a == VK_COMPONENT_SWIZZLE_A); // TODO(b/129523279)
+ samplerState.highPrecisionFiltering = false;
+ samplerState.compare = COMPARE_BYPASS; ASSERT(sampler->compareEnable == VK_FALSE); // TODO(b/129523279)
+
+// minLod // TODO(b/129523279)
+// maxLod // TODO(b/129523279)
+// borderColor // TODO(b/129523279)
+ ASSERT(sampler->mipLodBias == 0.0f); // TODO(b/129523279)
+ ASSERT(sampler->anisotropyEnable == VK_FALSE); // TODO(b/129523279)
+ ASSERT(sampler->unnormalizedCoordinates == VK_FALSE); // TODO(b/129523279)
+
+ SamplerCore s(constants, samplerState);
+
+ Pointer<Byte> texture = image + OFFSET(vk::SampledImageDescriptor, texture); // sw::Texture*
+ SIMD::Float w(0); // TODO(b/129523279)
+ SIMD::Float q(0); // TODO(b/129523279)
+ SIMD::Float bias(0); // TODO(b/129523279)
+ Vector4f dsx; // TODO(b/129523279)
+ Vector4f dsy; // TODO(b/129523279)
+ Vector4f offset; // TODO(b/129523279)
+ SamplerFunction samplerFunction = { Implicit, None }; // ASSERT(insn.wordCount() == 5); // TODO(b/129523279)
+
+ Vector4f sample = s.sampleTextureF(texture, u, v, w, q, bias, dsx, dsy, offset, samplerFunction);
+
+ if(!vk::Format(imageView->getFormat()).isNonNormalizedInteger())
+ {
+ Pointer<SIMD::Float> rgba = out;
+ rgba[0] = sample.x;
+ rgba[1] = sample.y;
+ rgba[2] = sample.z;
+ rgba[3] = sample.w;
+ }
+ else
+ {
+ // TODO(b/129523279): Add a Sampler::sampleTextureI() method.
+ Pointer<SIMD::Int> rgba = out;
+ rgba[0] = As<SIMD::Int>(sample.x * SIMD::Float(0xFF));
+ rgba[1] = As<SIMD::Int>(sample.y * SIMD::Float(0xFF));
+ rgba[2] = As<SIMD::Int>(sample.z * SIMD::Float(0xFF));
+ rgba[3] = As<SIMD::Int>(sample.w * SIMD::Float(0xFF));
+ }
+}
+
+} // namespace sw
\ No newline at end of file