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/+/29770
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Device/Renderer.cpp b/src/Device/Renderer.cpp
index 5034f36..03de441 100644
--- a/src/Device/Renderer.cpp
+++ b/src/Device/Renderer.cpp
@@ -504,7 +504,7 @@
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 @@
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);
}
diff --git a/src/Device/Sampler.cpp b/src/Device/Sampler.cpp
index 029f4c4..6f4e61b 100644
--- a/src/Device/Sampler.cpp
+++ b/src/Device/Sampler.cpp
@@ -68,11 +68,8 @@
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 @@
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 @@
void Sampler::setMipmapLOD(float LOD)
{
- texture.LOD = LOD;
exp2LOD = exp2(LOD);
}
diff --git a/src/Device/Sampler.hpp b/src/Device/Sampler.hpp
index 0013b8d..841fe70 100644
--- a/src/Device/Sampler.hpp
+++ b/src/Device/Sampler.hpp
@@ -50,7 +50,6 @@
{
Mipmap mipmap[MIPMAP_LEVELS];
- float LOD;
float4 widthHeightLOD;
float4 widthLOD;
float4 heightLOD;
@@ -59,8 +58,6 @@
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 @@
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);
diff --git a/src/Pipeline/SamplerCore.cpp b/src/Pipeline/SamplerCore.cpp
index 7469004..764bd30 100644
--- a/src/Pipeline/SamplerCore.cpp
+++ b/src/Pipeline/SamplerCore.cpp
@@ -255,22 +255,6 @@
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 @@
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 @@
if(state.mipmapFilter == MIPMAP_POINT)
{
+ // TODO: Preferred formula is ceil(lod + 0.5) - 1
ilod = RoundInt(lod);
}
else // MIPMAP_LINEAR
diff --git a/src/Pipeline/SamplerCore.hpp b/src/Pipeline/SamplerCore.hpp
index 2021c36..0ab2a1e 100644
--- a/src/Pipeline/SamplerCore.hpp
+++ b/src/Pipeline/SamplerCore.hpp
@@ -51,7 +51,6 @@
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);
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index 8361121..0d5c154 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -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 @@
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
diff --git a/src/Pipeline/SpirvShaderSampling.cpp b/src/Pipeline/SpirvShaderSampling.cpp
index e90aad0..6fc587a 100644
--- a/src/Pipeline/SpirvShaderSampling.cpp
+++ b/src/Pipeline/SpirvShaderSampling.cpp
@@ -39,94 +39,151 @@
namespace sw {
-SpirvShader::ImageSampler *SpirvShader::getImageSampler(vk::ImageView *imageView, vk::Sampler *sampler)
+SpirvShader::ImageSampler *SpirvShader::getImageSampler(const vk::ImageView *imageView, const vk::Sampler *sampler)
{
- // TODO: Move somewhere sensible.
- static std::unordered_map<uintptr_t, ImageSampler*> cache;
- static std::mutex mutex;
+ // 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);
+ // 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; }
+ 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;
+ // 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,
+ const vk::ImageView *imageView, const vk::Sampler *sampler,
Pointer<Byte> image, Pointer<SIMD::Float> in, Pointer<Byte> out)
{
- SIMD::Float u = in[0];
- SIMD::Float v = in[1];
+ SIMD::Float u = in[0];
+ SIMD::Float v = in[1];
- Pointer<Byte> constants; // FIXME(b/129523279)
+ 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)
+ Sampler::State samplerState;
+ samplerState.textureType = TEXTURE_2D; ASSERT(imageView->getType() == VK_IMAGE_VIEW_TYPE_2D); // TODO(b/129523279)
+ samplerState.textureFormat = imageView->getFormat();
+ samplerState.textureFilter = convertFilterMode(sampler);
- 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)
+ samplerState.addressingModeU = convertAddressingMode(sampler->addressModeU);
+ samplerState.addressingModeV = convertAddressingMode(sampler->addressModeV);
+ samplerState.addressingModeW = convertAddressingMode(sampler->addressModeW);
+ samplerState.mipmapFilter = convertMipmapMode(sampler);
+ 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)
+ 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);
+ 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)
+ 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);
+ 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));
- }
+ 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));
+ }
+}
+
+sw::FilterType SpirvShader::convertFilterMode(const vk::Sampler *sampler)
+{
+ switch(sampler->magFilter)
+ {
+ case VK_FILTER_NEAREST:
+ switch(sampler->minFilter)
+ {
+ case VK_FILTER_NEAREST: return FILTER_POINT;
+ case VK_FILTER_LINEAR: return FILTER_MIN_LINEAR_MAG_POINT;
+ default:
+ UNIMPLEMENTED("minFilter %d", sampler->minFilter);
+ return FILTER_POINT;
+ }
+ break;
+ case VK_FILTER_LINEAR:
+ switch(sampler->minFilter)
+ {
+ case VK_FILTER_NEAREST: return FILTER_MIN_POINT_MAG_LINEAR;
+ case VK_FILTER_LINEAR: return FILTER_LINEAR;
+ default:
+ UNIMPLEMENTED("minFilter %d", sampler->minFilter);
+ return FILTER_POINT;
+ }
+ break;
+ default:
+ UNIMPLEMENTED("magFilter %d", sampler->magFilter);
+ return FILTER_POINT;
+ }
+}
+
+sw::MipmapType SpirvShader::convertMipmapMode(const vk::Sampler *sampler)
+{
+ switch(sampler->mipmapMode)
+ {
+ case VK_SAMPLER_MIPMAP_MODE_NEAREST: return MIPMAP_POINT;
+ case VK_SAMPLER_MIPMAP_MODE_LINEAR: return MIPMAP_LINEAR;
+ default:
+ UNIMPLEMENTED("mipmapMode %d", sampler->mipmapMode);
+ return MIPMAP_POINT;
+ }
+}
+
+sw::AddressingMode SpirvShader::convertAddressingMode(VkSamplerAddressMode addressMode)
+{
+ switch(addressMode)
+ {
+ case VK_SAMPLER_ADDRESS_MODE_REPEAT: return ADDRESSING_WRAP;
+ case VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT: return ADDRESSING_MIRROR;
+ case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE: return ADDRESSING_CLAMP;
+ case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER: return ADDRESSING_BORDER;
+ case VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE: return ADDRESSING_MIRRORONCE;
+ default:
+ UNIMPLEMENTED("addressMode %d", addressMode);
+ return ADDRESSING_WRAP;
+ }
}
} // namespace sw
\ No newline at end of file
diff --git a/src/Vulkan/VkDescriptorSetLayout.cpp b/src/Vulkan/VkDescriptorSetLayout.cpp
index 8f6f602..13a30e9 100644
--- a/src/Vulkan/VkDescriptorSetLayout.cpp
+++ b/src/Vulkan/VkDescriptorSetLayout.cpp
@@ -248,8 +248,9 @@
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 @@
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);
-
- imageSampler[i].sampler = sampler;
- imageSampler[i].imageView = imageView;
-
sw::Texture *texture = &imageSampler[i].texture;
+
+ // "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));
+ }
+
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 @@
{
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
diff --git a/src/Vulkan/VkImageView.cpp b/src/Vulkan/VkImageView.cpp
index b403fb2..6e99bf7 100644
--- a/src/Vulkan/VkImageView.cpp
+++ b/src/Vulkan/VkImageView.cpp
@@ -144,12 +144,14 @@
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
};
diff --git a/src/Vulkan/VkImageView.hpp b/src/Vulkan/VkImageView.hpp
index b7ef034..e4c4d81 100644
--- a/src/Vulkan/VkImageView.hpp
+++ b/src/Vulkan/VkImageView.hpp
@@ -44,7 +44,7 @@
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; }