Commit a195abb4 by Nicolas Capens Committed by Nicolas Capens

Implement cubemap sampling

This still uses the legacy approach with 6 pointers per mipmap level for each cube face. Will be refactored to use a single pointer to access faces as consecutive layers. Bug: b/129523279 Tests: dEQP-VK.texture.filtering.cube.formats.r8g8b8a8_unorm.* Change-Id: I1f59f121d2989e0ba79eb3441529b812a8d9111a Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/29969 Presubmit-Ready: Nicolas Capens <nicolascapens@google.com> Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarChris Forbes <chrisforbes@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
parent a5f4eb6d
......@@ -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, 0);
data->colorBuffer[index] = (unsigned int*)context->renderTarget[index]->getOffsetPointer({0, 0, 0}, VK_IMAGE_ASPECT_COLOR_BIT, 0, 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, 0);
data->depthBuffer = (float*)context->depthBuffer->getOffsetPointer({0, 0, 0}, VK_IMAGE_ASPECT_DEPTH_BIT, 0, 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, 0);
data->stencilBuffer = (unsigned char*)context->stencilBuffer->getOffsetPointer({0, 0, 0}, VK_IMAGE_ASPECT_STENCIL_BIT, 0, 0);
data->stencilPitchB = context->stencilBuffer->rowPitchBytes(VK_IMAGE_ASPECT_STENCIL_BIT, 0);
data->stencilSliceB = context->stencilBuffer->slicePitchBytes(VK_IMAGE_ASPECT_STENCIL_BIT, 0);
}
......
......@@ -24,16 +24,17 @@ namespace
{
switch(swizzle)
{
case VK_COMPONENT_SWIZZLE_R: f = c.x; break;
case VK_COMPONENT_SWIZZLE_G: f = c.y; break;
case VK_COMPONENT_SWIZZLE_B: f = c.z; break;
case VK_COMPONENT_SWIZZLE_A: f = c.w; break;
case VK_COMPONENT_SWIZZLE_ZERO: f = sw::Float4(0.0f, 0.0f, 0.0f, 0.0f); break;
case VK_COMPONENT_SWIZZLE_R: f = c.x; break;
case VK_COMPONENT_SWIZZLE_G: f = c.y; break;
case VK_COMPONENT_SWIZZLE_B: f = c.z; break;
case VK_COMPONENT_SWIZZLE_A: f = c.w; break;
case VK_COMPONENT_SWIZZLE_ZERO: f = sw::Float4(0.0f, 0.0f, 0.0f, 0.0f); break;
case VK_COMPONENT_SWIZZLE_ONE:
if (integer)
{
f = rr::As<sw::Float4>(sw::Int4(1.0f, 1.0f, 1.0f, 1.0f));
} else
f = rr::As<sw::Float4>(sw::Int4(1, 1, 1, 1));
}
else
{
f = sw::Float4(1.0f, 1.0f, 1.0f, 1.0f);
}
......@@ -127,7 +128,7 @@ namespace sw
{
Vector4s cs = sampleFilter(texture, uuuu, vvvv, wwww, offset, lod, anisotropy, uDelta, vDelta, face, function);
if(state.textureFormat == VK_FORMAT_R5G6B5_UNORM_PACK16)
if(state.textureFormat == VK_FORMAT_R5G6B5_UNORM_PACK16)
{
c.x = Float4(As<UShort4>(cs.x)) * Float4(1.0f / 0xF800);
c.y = Float4(As<UShort4>(cs.y)) * Float4(1.0f / 0xFC00);
......
......@@ -879,7 +879,7 @@ namespace sw
static sw::TextureType convertTextureType(VkImageViewType imageViewType);
static sw::FilterType convertFilterMode(const vk::Sampler *sampler);
static sw::MipmapType convertMipmapMode(const vk::Sampler *sampler);
static sw::AddressingMode convertAddressingMode(VkSamplerAddressMode);
static sw::AddressingMode convertAddressingMode(VkSamplerAddressMode addressMode, VkImageViewType imageViewType);
};
class SpirvRoutine
......
......@@ -43,6 +43,7 @@ SpirvShader::ImageSampler *SpirvShader::getImageSamplerImplicitLod(const vk::Ima
{
return getImageSampler(Implicit, imageView, sampler);
}
SpirvShader::ImageSampler *SpirvShader::getImageSamplerExplicitLod(const vk::ImageView *imageView, const vk::Sampler *sampler)
{
return getImageSampler(Lod, imageView, sampler);
......@@ -83,9 +84,9 @@ void SpirvShader::emitSamplerFunction(
samplerState.textureFormat = imageView->getFormat();
samplerState.textureFilter = convertFilterMode(sampler);
samplerState.addressingModeU = convertAddressingMode(sampler->addressModeU);
samplerState.addressingModeV = convertAddressingMode(sampler->addressModeV);
samplerState.addressingModeW = convertAddressingMode(sampler->addressModeW);
samplerState.addressingModeU = convertAddressingMode(sampler->addressModeU, imageView->getType());
samplerState.addressingModeV = convertAddressingMode(sampler->addressModeV, imageView->getType());
samplerState.addressingModeW = convertAddressingMode(sampler->addressModeW, imageView->getType());
samplerState.mipmapFilter = convertMipmapMode(sampler);
samplerState.sRGB = imageView->getFormat().isSRGBformat();
samplerState.swizzle = imageView->getComponentMapping();
......@@ -102,8 +103,7 @@ void SpirvShader::emitSamplerFunction(
SamplerCore s(constants, samplerState);
Pointer<Byte> texture = image + OFFSET(vk::SampledImageDescriptor, texture); // sw::Texture*
SIMD::Float uv[2];
SIMD::Float w(0); // TODO(b/129523279)
SIMD::Float uvw[3];
SIMD::Float q(0); // TODO(b/129523279)
SIMD::Float bias(0);
Vector4f dsx; // TODO(b/129523279)
......@@ -111,22 +111,31 @@ void SpirvShader::emitSamplerFunction(
Vector4f offset; // TODO(b/129523279)
SamplerFunction samplerFunction = { samplerMethod, None }; // TODO(b/129523279)
// TODO(b/129523279): Currently 1D textures are treated as 2D by setting the second coordinate to 0.
// Implement optimized 1D sampling.
uv[1] = SIMD::Float(0);
int coordinateCount = 0;
switch(imageView->getType())
{
case VK_IMAGE_VIEW_TYPE_1D: coordinateCount = 1; break;
case VK_IMAGE_VIEW_TYPE_2D: coordinateCount = 2; break;
case VK_IMAGE_VIEW_TYPE_1D: coordinateCount = 1; break;
case VK_IMAGE_VIEW_TYPE_2D: coordinateCount = 2; break;
// case VK_IMAGE_VIEW_TYPE_3D: coordinateCount = 3; break;
case VK_IMAGE_VIEW_TYPE_CUBE: coordinateCount = 3; break;
// case VK_IMAGE_VIEW_TYPE_1D_ARRAY: coordinateCount = 2; break;
// case VK_IMAGE_VIEW_TYPE_2D_ARRAY: coordinateCount = 3; break;
// case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: coordinateCount = 4; break;
default:
UNIMPLEMENTED("imageView type %d", imageView->getType());
}
for(int i = 0; i < coordinateCount; i++)
{
uv[i] = in[i];
uvw[i] = in[i];
}
// TODO(b/129523279): Currently 1D textures are treated as 2D by setting the second coordinate to 0.
// Implement optimized 1D sampling.
If(imageView->getType() == VK_IMAGE_VIEW_TYPE_1D ||
imageView->getType() == VK_IMAGE_VIEW_TYPE_1D_ARRAY)
{
uvw[1] = SIMD::Float(0);
}
if(samplerMethod == Lod)
......@@ -136,7 +145,7 @@ void SpirvShader::emitSamplerFunction(
bias = in[coordinateCount];
}
Vector4f sample = s.sampleTexture(texture, uv[0], uv[1], w, q, bias, dsx, dsy, offset, samplerFunction);
Vector4f sample = s.sampleTexture(texture, uvw[0], uvw[1], uvw[2], q, bias, dsx, dsy, offset, samplerFunction);
Pointer<SIMD::Float> rgba = out;
rgba[0] = sample.x;
......@@ -152,7 +161,7 @@ sw::TextureType SpirvShader::convertTextureType(VkImageViewType imageViewType)
case VK_IMAGE_VIEW_TYPE_1D: return TEXTURE_1D;
case VK_IMAGE_VIEW_TYPE_2D: return TEXTURE_2D;
// case VK_IMAGE_VIEW_TYPE_3D: return TEXTURE_3D;
// case VK_IMAGE_VIEW_TYPE_CUBE: return TEXTURE_CUBE;
case VK_IMAGE_VIEW_TYPE_CUBE: return TEXTURE_CUBE;
// case VK_IMAGE_VIEW_TYPE_1D_ARRAY: return TEXTURE_1D_ARRAY;
// case VK_IMAGE_VIEW_TYPE_2D_ARRAY: return TEXTURE_2D_ARRAY;
// case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: return TEXTURE_CUBE_ARRAY;
......@@ -204,8 +213,29 @@ sw::MipmapType SpirvShader::convertMipmapMode(const vk::Sampler *sampler)
}
}
sw::AddressingMode SpirvShader::convertAddressingMode(VkSamplerAddressMode addressMode)
sw::AddressingMode SpirvShader::convertAddressingMode(VkSamplerAddressMode addressMode, VkImageViewType imageViewType)
{
// Vulkan 1.1 spec:
// "Cube images ignore the wrap modes specified in the sampler. Instead, if VK_FILTER_NEAREST is used within a mip level then
// 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
// is performed as described earlier in the Cube map edge handling section."
// This corresponds with our 'seamless' addressing mode.
switch(imageViewType)
{
case VK_IMAGE_VIEW_TYPE_CUBE:
case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
return ADDRESSING_SEAMLESS;
case VK_IMAGE_VIEW_TYPE_1D:
case VK_IMAGE_VIEW_TYPE_2D:
// case VK_IMAGE_VIEW_TYPE_3D:
// case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
// case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
break;
default:
UNIMPLEMENTED("imageViewType %d", imageViewType);
return ADDRESSING_WRAP;
}
switch(addressMode)
{
case VK_SAMPLER_ADDRESS_MODE_REPEAT: return ADDRESSING_WRAP;
......
......@@ -301,12 +301,26 @@ void DescriptorSetLayout::WriteDescriptorSet(DescriptorSet *dstSet, VkDescriptor
int level = mipmapLevel - baseLevel; // Level within the image view
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, level);
sw::Mipmap &mipmap = texture->mipmap[mipmapLevel];
mipmap.buffer[0] = buffer;
if(imageView->getType() == VK_IMAGE_VIEW_TYPE_CUBE)
{
for(int face = 0; face < 6; face++)
{
// Obtain the pointer to the corner of the level including the border, for seamless sampling.
// This is taken into account in the sampling routine, which can't handle negative texel coordinates.
VkOffset3D offset = {-1, -1, 0};
// TODO(b/129523279): Implement as 6 consecutive layers instead of separate pointers.
mipmap.buffer[face] = imageView->getOffsetPointer(offset, aspect, level, face);
}
}
else
{
VkOffset3D offset = {0, 0, 0};
mipmap.buffer[0] = imageView->getOffsetPointer(offset, aspect, level, 0);
}
VkExtent3D extent = imageView->getMipLevelExtent(level);
Format format = imageView->getFormat();
......@@ -445,7 +459,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, 0);
descriptor[i].ptr = imageView->getOffsetPointer({0, 0, 0}, VK_IMAGE_ASPECT_COLOR_BIT, 0, 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
......
......@@ -171,7 +171,7 @@ void ImageView::resolve(ImageView* resolveAttachment)
image->copyTo(*(resolveAttachment->image), region);
}
void *ImageView::getOffsetPointer(const VkOffset3D& offset, VkImageAspectFlagBits aspect, uint32_t mipLevel) const
void *ImageView::getOffsetPointer(const VkOffset3D& offset, VkImageAspectFlagBits aspect, uint32_t mipLevel, uint32_t layer) const
{
ASSERT(mipLevel < subresourceRange.levelCount);
......@@ -179,7 +179,7 @@ void *ImageView::getOffsetPointer(const VkOffset3D& offset, VkImageAspectFlagBit
{
static_cast<VkImageAspectFlags>(aspect),
subresourceRange.baseMipLevel + mipLevel,
subresourceRange.baseArrayLayer,
subresourceRange.baseArrayLayer + layer,
subresourceRange.layerCount
};
return image->getTexelPointer(offset, imageSubresourceLayers);
......
......@@ -46,7 +46,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, uint32_t mipLevel) const;
void *getOffsetPointer(const VkOffset3D& offset, VkImageAspectFlagBits aspect, uint32_t mipLevel, uint32_t layer) 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