Commit 97da7826 by Nicolas Capens Committed by Nicolas Capens

Pass a separate sampler pointer to the sampling routine

Previously only the texture pointer was passed to the sampling routine, containing some sampler data which is (still) wrongly assumed to come from a combined image-view and sampler descriptor. This change will allow splitting them up correctly. Also refactor getImageSampler to not start the Reactor function generation, moving it entirely into emitSamplerFunction so that the latter only has to be passed the pointers to the descriptor state that will affect the code that's generated. Name all the parameters according to their actual type. Clamp sampler LOD on construction so we don't have to deal with it any more later. Bug: b/129523279 Test: dEQP-VK.glsl.texture_functions.* Test: dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.* Change-Id: Id3a9f12f379cf65741198b732fe387ec6e24dd86 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/30350 Presubmit-Ready: Nicolas Capens <nicolascapens@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarChris Forbes <chrisforbes@google.com>
parent 20aab4e9
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "PixelRoutine.hpp" #include "PixelRoutine.hpp"
#include "Constants.hpp" #include "Constants.hpp"
#include "Vulkan/VkSampler.hpp"
#include "Vulkan/VkDebug.hpp" #include "Vulkan/VkDebug.hpp"
namespace namespace
...@@ -50,7 +51,7 @@ namespace sw ...@@ -50,7 +51,7 @@ namespace sw
{ {
} }
Vector4f SamplerCore::sampleTexture(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Float4 &lodOrBias, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function) Vector4f SamplerCore::sampleTexture(Pointer<Byte> &texture, Pointer<Byte> &sampler, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Float4 &lodOrBias, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function)
{ {
Vector4f c; Vector4f c;
......
...@@ -60,7 +60,7 @@ namespace sw ...@@ -60,7 +60,7 @@ namespace sw
public: public:
SamplerCore(Pointer<Byte> &constants, const Sampler::State &state); SamplerCore(Pointer<Byte> &constants, const Sampler::State &state);
Vector4f sampleTexture(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Float4 &lodOrBias, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function); Vector4f sampleTexture(Pointer<Byte> &texture, Pointer<Byte> &sampler, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Float4 &lodOrBias, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function);
private: private:
void border(Short4 &mask, Float4 &coordinates); void border(Short4 &mask, Float4 &coordinates);
......
...@@ -4564,8 +4564,9 @@ namespace sw ...@@ -4564,8 +4564,9 @@ namespace sw
auto coordinate = GenericValue(this, state->routine, coordinateId); auto coordinate = GenericValue(this, state->routine, coordinateId);
auto &coordinateType = getType(coordinate.type); auto &coordinateType = getType(coordinate.type);
auto sampler = *Pointer<Pointer<Byte>>(samplerDescriptor + OFFSET(vk::SampledImageDescriptor, sampler)); // vk::Sampler* Pointer<Byte> sampler = samplerDescriptor + OFFSET(vk::SampledImageDescriptor, sampler); // vk::Sampler*
auto imageView = *Pointer<Pointer<Byte>>(imageDescriptor + OFFSET(vk::SampledImageDescriptor, imageView)); // vk::ImageView* Pointer<Byte> imageView = *Pointer<Pointer<Byte>>(imageDescriptor + OFFSET(vk::SampledImageDescriptor, imageView)); // vk::ImageView*
Pointer<Byte> texture = imageDescriptor + OFFSET(vk::SampledImageDescriptor, texture); // sw::Texture*
uint32_t imageOperands = spv::ImageOperandsMaskNone; uint32_t imageOperands = spv::ImageOperandsMaskNone;
bool lodOrBias = false; bool lodOrBias = false;
...@@ -4698,7 +4699,7 @@ namespace sw ...@@ -4698,7 +4699,7 @@ namespace sw
auto samplerFunc = Call(getImageSampler, instruction.parameters, imageView, sampler); auto samplerFunc = Call(getImageSampler, instruction.parameters, imageView, sampler);
Array<SIMD::Float> out(4); Array<SIMD::Float> out(4);
Call<ImageSampler>(samplerFunc, imageDescriptor, &in[0], &out[0], state->routine->constants); Call<ImageSampler>(samplerFunc, texture, sampler, &in[0], &out[0], state->routine->constants);
for (int i = 0; i < 4; i++) { result.move(i, out[i]); } for (int i = 0; i < 4; i++) { result.move(i, out[i]); }
......
...@@ -258,7 +258,7 @@ namespace sw ...@@ -258,7 +258,7 @@ namespace sw
using InsnStore = std::vector<uint32_t>; using InsnStore = std::vector<uint32_t>;
InsnStore insns; InsnStore insns;
using ImageSampler = void(void* image, void* uvsIn, void* texelOut, void* constants); using ImageSampler = void(void* texture, void *sampler, void* uvsIn, void* texelOut, void* constants);
using GetImageSampler = ImageSampler*(const vk::ImageView *imageView, const vk::Sampler *sampler); using GetImageSampler = ImageSampler*(const vk::ImageView *imageView, const vk::Sampler *sampler);
/* Pseudo-iterator over SPIRV instructions, designed to support range-based-for. */ /* Pseudo-iterator over SPIRV instructions, designed to support range-based-for. */
...@@ -928,10 +928,7 @@ namespace sw ...@@ -928,10 +928,7 @@ namespace sw
std::pair<SIMD::Float, SIMD::Int> Frexp(RValue<SIMD::Float> val) const; std::pair<SIMD::Float, SIMD::Int> Frexp(RValue<SIMD::Float> val) const;
static ImageSampler *getImageSampler(uint32_t instruction, const vk::ImageView *imageView, const vk::Sampler *sampler); static ImageSampler *getImageSampler(uint32_t instruction, const vk::ImageView *imageView, const vk::Sampler *sampler);
static void emitSamplerFunction( static ImageSampler *emitSamplerFunction(ImageInstruction instruction, const Sampler::State &samplerState);
ImageInstruction instruction,
const vk::ImageView *imageView, const vk::Sampler *sampler,
Pointer<Byte> image, Pointer<SIMD::Float> in, Pointer<Byte> out, Pointer<Byte> constants);
// TODO(b/129523279): Eliminate conversion and use vk::Sampler members directly. // TODO(b/129523279): Eliminate conversion and use vk::Sampler members directly.
static sw::TextureType convertTextureType(VkImageViewType imageViewType); static sw::TextureType convertTextureType(VkImageViewType imageViewType);
......
...@@ -50,25 +50,6 @@ SpirvShader::ImageSampler *SpirvShader::getImageSampler(uint32_t instruction, co ...@@ -50,25 +50,6 @@ SpirvShader::ImageSampler *SpirvShader::getImageSampler(uint32_t instruction, co
auto it = cache.find(key); auto it = cache.find(key);
if (it != cache.end()) { return it->second; } 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>)>();
Pointer<Byte> image = function.Arg<0>();
Pointer<SIMD::Float> in = function.Arg<1>();
Pointer<SIMD::Float> out = function.Arg<2>();
Pointer<Byte> constants = function.Arg<3>();
emitSamplerFunction({instruction}, imageView, sampler, image, in, out, constants);
auto fptr = reinterpret_cast<ImageSampler*>((void *)function("sampler")->getEntry());
cache.emplace(key, fptr);
return fptr;
}
void SpirvShader::emitSamplerFunction(
ImageInstruction instruction,
const vk::ImageView *imageView, const vk::Sampler *sampler,
Pointer<Byte> image, Pointer<SIMD::Float> in, Pointer<Byte> out, Pointer<Byte> constants)
{
Sampler::State samplerState = {}; Sampler::State samplerState = {};
samplerState.textureType = convertTextureType(imageView->getType()); samplerState.textureType = convertTextureType(imageView->getType());
samplerState.textureFormat = imageView->getFormat(); samplerState.textureFormat = imageView->getFormat();
...@@ -91,9 +72,25 @@ void SpirvShader::emitSamplerFunction( ...@@ -91,9 +72,25 @@ void SpirvShader::emitSamplerFunction(
ASSERT(sampler->anisotropyEnable == VK_FALSE); // TODO(b/129523279) ASSERT(sampler->anisotropyEnable == VK_FALSE); // TODO(b/129523279)
ASSERT(sampler->unnormalizedCoordinates == VK_FALSE); // TODO(b/129523279) ASSERT(sampler->unnormalizedCoordinates == VK_FALSE); // TODO(b/129523279)
auto fptr = emitSamplerFunction({instruction}, samplerState);
cache.emplace(key, fptr);
return fptr;
}
SpirvShader::ImageSampler *SpirvShader::emitSamplerFunction(ImageInstruction instruction, const Sampler::State &samplerState)
{
// TODO(b/129523279): Hold a separate mutex lock for the sampler being built.
Function<Void(Pointer<Byte>, Pointer<Byte>, Pointer<SIMD::Float>, Pointer<SIMD::Float>, Pointer<Byte>)> function;
{
Pointer<Byte> texture = function.Arg<0>();
Pointer<Byte> sampler = function.Arg<1>();
Pointer<SIMD::Float> in = function.Arg<2>();
Pointer<SIMD::Float> out = function.Arg<3>();
Pointer<Byte> constants = function.Arg<4>();
SamplerCore s(constants, samplerState); SamplerCore s(constants, samplerState);
Pointer<Byte> texture = image + OFFSET(vk::SampledImageDescriptor, texture); // sw::Texture*
SIMD::Float uvw[3]; SIMD::Float uvw[3];
SIMD::Float q(0); // TODO(b/129523279) SIMD::Float q(0); // TODO(b/129523279)
SIMD::Float lodOrBias(0); // Explicit level-of-detail, or bias added to the implicit level-of-detail (depending on samplerMethod). SIMD::Float lodOrBias(0); // Explicit level-of-detail, or bias added to the implicit level-of-detail (depending on samplerMethod).
...@@ -110,8 +107,8 @@ void SpirvShader::emitSamplerFunction( ...@@ -110,8 +107,8 @@ void SpirvShader::emitSamplerFunction(
// TODO(b/129523279): Currently 1D textures are treated as 2D by setting the second coordinate to 0. // TODO(b/129523279): Currently 1D textures are treated as 2D by setting the second coordinate to 0.
// Implement optimized 1D sampling. // Implement optimized 1D sampling.
if(imageView->getType() == VK_IMAGE_VIEW_TYPE_1D || if(samplerState.textureType == TEXTURE_1D ||
imageView->getType() == VK_IMAGE_VIEW_TYPE_1D_ARRAY) samplerState.textureType == TEXTURE_1D_ARRAY)
{ {
uvw[1] = SIMD::Float(0); uvw[1] = SIMD::Float(0);
} }
...@@ -142,13 +139,16 @@ void SpirvShader::emitSamplerFunction( ...@@ -142,13 +139,16 @@ void SpirvShader::emitSamplerFunction(
} }
} }
Vector4f sample = s.sampleTexture(texture, uvw[0], uvw[1], uvw[2], q, lodOrBias, dsx, dsy, offset, samplerFunction); Vector4f sample = s.sampleTexture(texture, sampler, uvw[0], uvw[1], uvw[2], q, lodOrBias, dsx, dsy, offset, samplerFunction);
Pointer<SIMD::Float> rgba = out; Pointer<SIMD::Float> rgba = out;
rgba[0] = sample.x; rgba[0] = sample.x;
rgba[1] = sample.y; rgba[1] = sample.y;
rgba[2] = sample.z; rgba[2] = sample.z;
rgba[3] = sample.w; rgba[3] = sample.w;
}
return (ImageSampler*)function("sampler")->getEntry();
} }
sw::TextureType SpirvShader::convertTextureType(VkImageViewType imageViewType) sw::TextureType SpirvShader::convertTextureType(VkImageViewType imageViewType)
......
...@@ -258,12 +258,12 @@ uint8_t* DescriptorSetLayout::getOffsetPointer(DescriptorSet *descriptorSet, uin ...@@ -258,12 +258,12 @@ uint8_t* DescriptorSetLayout::getOffsetPointer(DescriptorSet *descriptorSet, uin
void SampledImageDescriptor::updateSampler(const vk::Sampler *sampler) void SampledImageDescriptor::updateSampler(const vk::Sampler *sampler)
{ {
this->sampler = sampler;
if (sampler) if (sampler)
{ {
texture.minLod = sw::clamp(sampler->minLod, 0.0f, (float) (sw::MAX_TEXTURE_LOD)); memcpy(&this->sampler, sampler, sizeof(*sampler));
texture.maxLod = sw::clamp(sampler->maxLod, 0.0f, (float) (sw::MAX_TEXTURE_LOD));
texture.minLod = sampler->minLod;
texture.maxLod = sampler->maxLod;
} }
} }
......
...@@ -32,9 +32,9 @@ struct alignas(16) SampledImageDescriptor ...@@ -32,9 +32,9 @@ struct alignas(16) SampledImageDescriptor
void updateSampler(const vk::Sampler *sampler); void updateSampler(const vk::Sampler *sampler);
// TODO(b/129523279): Minimize to the data actually needed. // TODO(b/129523279): Minimize to the data actually needed.
const vk::Sampler *sampler; vk::Sampler sampler;
const vk::ImageView *imageView;
const vk::ImageView *imageView;
alignas(16) sw::Texture texture; alignas(16) sw::Texture texture;
}; };
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
#define VK_SAMPLER_HPP_ #define VK_SAMPLER_HPP_
#include "VkDevice.hpp" #include "VkDevice.hpp"
#include "Device/Config.hpp"
#include "System/Math.hpp"
#include <atomic> #include <atomic>
...@@ -37,8 +39,8 @@ public: ...@@ -37,8 +39,8 @@ public:
maxAnisotropy(pCreateInfo->maxAnisotropy), maxAnisotropy(pCreateInfo->maxAnisotropy),
compareEnable(pCreateInfo->compareEnable), compareEnable(pCreateInfo->compareEnable),
compareOp(pCreateInfo->compareOp), compareOp(pCreateInfo->compareOp),
minLod(pCreateInfo->minLod), minLod(ClampLod(pCreateInfo->minLod)),
maxLod(pCreateInfo->maxLod), maxLod(ClampLod(pCreateInfo->maxLod)),
borderColor(pCreateInfo->borderColor), borderColor(pCreateInfo->borderColor),
unnormalizedCoordinates(pCreateInfo->unnormalizedCoordinates) unnormalizedCoordinates(pCreateInfo->unnormalizedCoordinates)
{ {
...@@ -51,6 +53,12 @@ public: ...@@ -51,6 +53,12 @@ public:
return 0; return 0;
} }
// Prevents accessing mipmap levels out of range.
static float ClampLod(float lod)
{
return sw::clamp(lod, 0.0f, (float)(sw::MAX_TEXTURE_LOD));
}
const uint32_t id = nextID++; const uint32_t id = nextID++;
const VkFilter magFilter = VK_FILTER_NEAREST; const VkFilter magFilter = VK_FILTER_NEAREST;
const VkFilter minFilter = VK_FILTER_NEAREST; const VkFilter minFilter = VK_FILTER_NEAREST;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment