Commit 9e73510a by Nicolas Capens Committed by Nicolas Capens

Implement basic sampler parameters

- Implement support for mipmapping: Involved fixing retrieving correct texel pointers for each mip level. - Implement addressing mode. - Implement filter mode. - Removed textureSize(). We already have an implementation of OpImageQuerySize which doesn't require the sampling code. For now, these parameters are converted to the legacy sampler enum values to avoid a big refactoring which may break functionality before we pass the tests. Future changes will eliminate them in favor of using the Vulkan sampler parameters directly. Bug: b/129523279 Test: dEQP-VK.texture.filtering.2d.formats.r8g8b8a8_unorm.* Test: dEQP-VK.pipeline.sampler.view_type.2d.format.r8g8b8a8_unorm.* Change-Id: I313e598ae61c0016a5a929bf5c1a53b66b3ff0d1 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/29770Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarBen Clayton <bclayton@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com>
parent ef6152eb
......@@ -504,7 +504,7 @@ namespace sw
if(draw->renderTarget[index])
{
data->colorBuffer[index] = (unsigned int*)context->renderTarget[index]->getOffsetPointer({0, 0, 0}, VK_IMAGE_ASPECT_COLOR_BIT);
data->colorBuffer[index] = (unsigned int*)context->renderTarget[index]->getOffsetPointer({0, 0, 0}, VK_IMAGE_ASPECT_COLOR_BIT, 0);
data->colorPitchB[index] = context->renderTarget[index]->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0);
data->colorSliceB[index] = context->renderTarget[index]->slicePitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0);
}
......@@ -515,14 +515,14 @@ namespace sw
if(draw->depthBuffer)
{
data->depthBuffer = (float*)context->depthBuffer->getOffsetPointer({0, 0, 0}, VK_IMAGE_ASPECT_DEPTH_BIT);
data->depthBuffer = (float*)context->depthBuffer->getOffsetPointer({0, 0, 0}, VK_IMAGE_ASPECT_DEPTH_BIT, 0);
data->depthPitchB = context->depthBuffer->rowPitchBytes(VK_IMAGE_ASPECT_DEPTH_BIT, 0);
data->depthSliceB = context->depthBuffer->slicePitchBytes(VK_IMAGE_ASPECT_DEPTH_BIT, 0);
}
if(draw->stencilBuffer)
{
data->stencilBuffer = (unsigned char*)context->stencilBuffer->getOffsetPointer({0, 0, 0}, VK_IMAGE_ASPECT_STENCIL_BIT);
data->stencilBuffer = (unsigned char*)context->stencilBuffer->getOffsetPointer({0, 0, 0}, VK_IMAGE_ASPECT_STENCIL_BIT, 0);
data->stencilPitchB = context->stencilBuffer->rowPitchBytes(VK_IMAGE_ASPECT_STENCIL_BIT, 0);
data->stencilSliceB = context->stencilBuffer->slicePitchBytes(VK_IMAGE_ASPECT_STENCIL_BIT, 0);
}
......
......@@ -68,11 +68,8 @@ namespace sw
compare = COMPARE_BYPASS;
texture.LOD = 0.0f;
exp2LOD = 1.0f;
texture.baseLevel = 0;
texture.maxLevel = 1000;
texture.maxLod = MAX_TEXTURE_LOD;
texture.minLod = 0;
}
......@@ -346,16 +343,6 @@ namespace sw
this->compare = compare;
}
void Sampler::setBaseLevel(int baseLevel)
{
texture.baseLevel = baseLevel;
}
void Sampler::setMaxLevel(int maxLevel)
{
texture.maxLevel = maxLevel;
}
void Sampler::setMinLod(float minLod)
{
texture.minLod = clamp(minLod, 0.0f, (float)(MAX_TEXTURE_LOD));
......@@ -378,7 +365,6 @@ namespace sw
void Sampler::setMipmapLOD(float LOD)
{
texture.LOD = LOD;
exp2LOD = exp2(LOD);
}
......
......@@ -50,7 +50,6 @@ namespace sw
{
Mipmap mipmap[MIPMAP_LEVELS];
float LOD;
float4 widthHeightLOD;
float4 widthLOD;
float4 heightLOD;
......@@ -59,8 +58,6 @@ namespace sw
word4 borderColor4[4]; // FIXME(b/129523279): Part of Vulkan sampler.
float4 borderColorF[4]; // FIXME(b/129523279): Part of Vulkan sampler.
float maxAnisotropy; // FIXME(b/129523279): Part of Vulkan sampler.
int baseLevel;
int maxLevel;
float minLod; // FIXME(b/129523279): Part of Vulkan sampler.
float maxLod; // FIXME(b/129523279): Part of Vulkan sampler.
};
......@@ -195,8 +192,6 @@ namespace sw
void setSwizzleB(SwizzleType swizzleB);
void setSwizzleA(SwizzleType swizzleA);
void setCompareFunc(CompareFunc compare);
void setBaseLevel(int baseLevel);
void setMaxLevel(int maxLevel);
void setMinLod(float minLod);
void setMaxLod(float maxLod);
......
......@@ -255,22 +255,6 @@ namespace sw
return c;
}
Vector4f SamplerCore::textureSize(Pointer<Byte> &texture, Float4 &lod)
{
Vector4f size;
for(int i = 0; i < 4; ++i)
{
Int baseLevel = *Pointer<Int>(texture + OFFSET(Texture, baseLevel));
Pointer<Byte> mipmap = texture + OFFSET(Texture, mipmap) + (As<Int>(Extract(lod, i)) + baseLevel) * sizeof(Mipmap);
size.x = Insert(size.x, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, width)))), i);
size.y = Insert(size.y, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, height)))), i);
size.z = Insert(size.z, As<Float>(Int(*Pointer<Short>(mipmap + OFFSET(Mipmap, depth)))), i);
}
return size;
}
void SamplerCore::border(Short4 &mask, Float4 &coordinates)
{
Int4 border = As<Int4>(CmpLT(Abs(coordinates - Float4(0.5f)), Float4(0.5f)));
......@@ -1152,7 +1136,7 @@ namespace sw
duvdxy = Float4(dudxy.xz, dvdxy.xz);
}
// Scale by texture dimensions and global LOD.
// Scale by texture dimensions and sampler LOD bias.
Float4 dUVdxy = duvdxy * *Pointer<Float4>(texture + OFFSET(Texture,widthHeightLOD));
Float4 dUV2dxy = dUVdxy * dUVdxy;
......@@ -1948,6 +1932,7 @@ namespace sw
if(state.mipmapFilter == MIPMAP_POINT)
{
// TODO: Preferred formula is ceil(lod + 0.5) - 1
ilod = RoundInt(lod);
}
else // MIPMAP_LINEAR
......
......@@ -51,7 +51,6 @@ namespace sw
SamplerCore(Pointer<Byte> &constants, const Sampler::State &state);
Vector4f sampleTextureF(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Float4 &bias, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function);
static Vector4f textureSize(Pointer<Byte> &mipmap, Float4 &lod);
private:
Vector4s sampleTexture(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Float4 &bias, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function);
......
......@@ -23,6 +23,7 @@
#include "Vulkan/VkDescriptorSet.hpp"
#include "Common/Types.hpp"
#include "Device/Config.hpp"
#include "Device/Sampler.hpp"
#include <spirv/unified1/spirv.hpp>
......@@ -854,10 +855,15 @@ namespace sw
using ImageSampler = void(void* image, void* uvsIn, void* texelOut);
static ImageSampler *getImageSampler(vk::ImageView *imageView, vk::Sampler *sampler);
static ImageSampler *getImageSampler(const vk::ImageView *imageView, const vk::Sampler *sampler);
static void emitSamplerFunction(
vk::ImageView *imageView, vk::Sampler *sampler,
const vk::ImageView *imageView, const vk::Sampler *sampler,
Pointer<Byte> image, Pointer<SIMD::Float> in, Pointer<Byte> out);
// TODO(b/129523279): Eliminate conversion and use vk::Sampler members directly.
static sw::FilterType convertFilterMode(const vk::Sampler *sampler);
static sw::MipmapType convertMipmapMode(const vk::Sampler *sampler);
static sw::AddressingMode convertAddressingMode(VkSamplerAddressMode);
};
class SpirvRoutine
......
......@@ -248,8 +248,9 @@ uint8_t* DescriptorSetLayout::getOffsetPointer(DescriptorSet *descriptorSet, uin
void DescriptorSetLayout::WriteDescriptorSet(DescriptorSet *dstSet, VkDescriptorUpdateTemplateEntry const &entry, char const *src)
{
DescriptorSetLayout* dstLayout = dstSet->layout;
auto &binding = dstLayout->bindings[dstLayout->getBindingIndex(entry.dstBinding)];
ASSERT(dstLayout);
ASSERT(dstLayout->bindings[dstLayout->getBindingIndex(entry.dstBinding)].descriptorType == entry.descriptorType);
ASSERT(binding.descriptorType == entry.descriptorType);
size_t typeSize = 0;
uint8_t* memToWrite = dstLayout->getOffsetPointer(dstSet, entry.dstBinding, entry.dstArrayElement, entry.descriptorCount, &typeSize);
......@@ -261,26 +262,36 @@ void DescriptorSetLayout::WriteDescriptorSet(DescriptorSet *dstSet, VkDescriptor
for(uint32_t i = 0; i < entry.descriptorCount; i++)
{
auto update = reinterpret_cast<VkDescriptorImageInfo const *>(src + entry.offset + entry.stride * i);
vk::Sampler *sampler = vk::Cast(update->sampler);
vk::ImageView *imageView = vk::Cast(update->imageView);
sw::Texture *texture = &imageSampler[i].texture;
imageSampler[i].sampler = sampler;
imageSampler[i].imageView = imageView;
// "All consecutive bindings updated via a single VkWriteDescriptorSet structure, except those with a
// descriptorCount of zero, must all either use immutable samplers or must all not use immutable samplers."
if(!binding.pImmutableSamplers)
{
vk::Sampler *sampler = vk::Cast(update->sampler);
imageSampler[i].sampler = sampler;
texture->minLod = sw::clamp(sampler->minLod, 0.0f, (float)(sw::MAX_TEXTURE_LOD));
texture->maxLod = sw::clamp(sampler->maxLod, 0.0f, (float)(sw::MAX_TEXTURE_LOD));
}
sw::Texture *texture = &imageSampler[i].texture;
memset(texture, 0, sizeof(sw::Texture)); // TODO(b/129523279): eliminate
imageSampler[i].imageView = imageView;
auto &subresourceRange = imageView->getSubresourceRange();
int baseLevel = subresourceRange.baseMipLevel;
for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++)
{
int level = mipmapLevel - baseLevel; // Level within the image view
level = sw::clamp(level, 0, (int)subresourceRange.levelCount);
level = sw::clamp(level, 0, (int)subresourceRange.levelCount - 1);
VkOffset3D offset = {0, 0, 0};
VkImageAspectFlagBits aspect = VK_IMAGE_ASPECT_COLOR_BIT;
void *buffer = imageView->getOffsetPointer(offset, aspect);
void *buffer = imageView->getOffsetPointer(offset, aspect, level);
sw::Mipmap &mipmap = texture->mipmap[mipmapLevel];
mipmap.buffer[0] = buffer;
......@@ -422,7 +433,7 @@ void DescriptorSetLayout::WriteDescriptorSet(DescriptorSet *dstSet, VkDescriptor
{
auto update = reinterpret_cast<VkDescriptorImageInfo const *>(src + entry.offset + entry.stride * i);
auto imageView = Cast(update->imageView);
descriptor[i].ptr = imageView->getOffsetPointer({0, 0, 0}, VK_IMAGE_ASPECT_COLOR_BIT);
descriptor[i].ptr = imageView->getOffsetPointer({0, 0, 0}, VK_IMAGE_ASPECT_COLOR_BIT, 0);
descriptor[i].extent = imageView->getMipLevelExtent(0);
descriptor[i].rowPitchBytes = imageView->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0);
descriptor[i].slicePitchBytes = imageView->getSubresourceRange().layerCount > 1
......
......@@ -144,12 +144,14 @@ void ImageView::resolve(ImageView* resolveAttachment)
image->copyTo(*(resolveAttachment->image), region);
}
void *ImageView::getOffsetPointer(const VkOffset3D& offset, VkImageAspectFlagBits aspect) const
void *ImageView::getOffsetPointer(const VkOffset3D& offset, VkImageAspectFlagBits aspect, uint32_t mipLevel) const
{
ASSERT(mipLevel < subresourceRange.levelCount);
VkImageSubresourceLayers imageSubresourceLayers =
{
static_cast<VkImageAspectFlags>(aspect),
subresourceRange.baseMipLevel,
subresourceRange.baseMipLevel + mipLevel,
subresourceRange.baseArrayLayer,
subresourceRange.layerCount
};
......
......@@ -44,7 +44,7 @@ public:
int layerPitchBytes(VkImageAspectFlagBits aspect) const { return static_cast<int>(image->getLayerSize(aspect)); }
VkExtent3D getMipLevelExtent(uint32_t mipLevel) const { return image->getMipLevelExtent(subresourceRange.baseMipLevel + mipLevel); }
void *getOffsetPointer(const VkOffset3D& offset, VkImageAspectFlagBits aspect) const;
void *getOffsetPointer(const VkOffset3D& offset, VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
bool hasDepthAspect() const { return (subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0; }
bool hasStencilAspect() const { return (subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0; }
......
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