Commit 7d867277 by Nicolas Capens Committed by Nicolas Capens

Implement basic SPIR-V texture sampling

Replaces VkDescriptorImageInfo with a more concrete SampledImageDescriptor, which contains an sw::Texture that SamplerCore uses. The parameters can be looked up statically only because the shaderSampledImageArrayDynamicIndexing feature is currently not supported. Bug b/129523279 Test: dEQP-VK.texture.filtering.2d.formats.r8g8b8a8_unorm.nearest Change-Id: I619b5b48b2b4552d9bfc70b087df2c31eabb49ea Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/28434 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 avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarBen Clayton <bclayton@google.com>
parent 98e6b968
...@@ -510,8 +510,8 @@ namespace sw ...@@ -510,8 +510,8 @@ namespace sw
{ {
VkOffset3D offset = { 0, 0, static_cast<int32_t>(context->renderTargetLayer[index]) }; VkOffset3D offset = { 0, 0, static_cast<int32_t>(context->renderTargetLayer[index]) };
data->colorBuffer[index] = (unsigned int*)context->renderTarget[index]->getOffsetPointer(offset, VK_IMAGE_ASPECT_COLOR_BIT); data->colorBuffer[index] = (unsigned int*)context->renderTarget[index]->getOffsetPointer(offset, VK_IMAGE_ASPECT_COLOR_BIT);
data->colorPitchB[index] = context->renderTarget[index]->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT); 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); data->colorSliceB[index] = context->renderTarget[index]->slicePitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0);
} }
} }
...@@ -522,16 +522,16 @@ namespace sw ...@@ -522,16 +522,16 @@ namespace sw
{ {
VkOffset3D offset = { 0, 0, static_cast<int32_t>(context->depthBufferLayer) }; VkOffset3D offset = { 0, 0, static_cast<int32_t>(context->depthBufferLayer) };
data->depthBuffer = (float*)context->depthBuffer->getOffsetPointer(offset, VK_IMAGE_ASPECT_DEPTH_BIT); data->depthBuffer = (float*)context->depthBuffer->getOffsetPointer(offset, VK_IMAGE_ASPECT_DEPTH_BIT);
data->depthPitchB = context->depthBuffer->rowPitchBytes(VK_IMAGE_ASPECT_DEPTH_BIT); data->depthPitchB = context->depthBuffer->rowPitchBytes(VK_IMAGE_ASPECT_DEPTH_BIT, 0);
data->depthSliceB = context->depthBuffer->slicePitchBytes(VK_IMAGE_ASPECT_DEPTH_BIT); data->depthSliceB = context->depthBuffer->slicePitchBytes(VK_IMAGE_ASPECT_DEPTH_BIT, 0);
} }
if(draw->stencilBuffer) if(draw->stencilBuffer)
{ {
VkOffset3D offset = { 0, 0, static_cast<int32_t>(context->stencilBufferLayer) }; VkOffset3D offset = { 0, 0, static_cast<int32_t>(context->stencilBufferLayer) };
data->stencilBuffer = (unsigned char*)context->stencilBuffer->getOffsetPointer(offset, VK_IMAGE_ASPECT_STENCIL_BIT); data->stencilBuffer = (unsigned char*)context->stencilBuffer->getOffsetPointer(offset, VK_IMAGE_ASPECT_STENCIL_BIT);
data->stencilPitchB = context->stencilBuffer->rowPitchBytes(VK_IMAGE_ASPECT_STENCIL_BIT); data->stencilPitchB = context->stencilBuffer->rowPitchBytes(VK_IMAGE_ASPECT_STENCIL_BIT, 0);
data->stencilSliceB = context->stencilBuffer->slicePitchBytes(VK_IMAGE_ASPECT_STENCIL_BIT); data->stencilSliceB = context->stencilBuffer->slicePitchBytes(VK_IMAGE_ASPECT_STENCIL_BIT, 0);
} }
} }
......
...@@ -56,13 +56,13 @@ namespace sw ...@@ -56,13 +56,13 @@ namespace sw
float4 heightLOD; float4 heightLOD;
float4 depthLOD; float4 depthLOD;
word4 borderColor4[4]; word4 borderColor4[4]; // FIXME(b/129523279): Part of Vulkan sampler.
float4 borderColorF[4]; float4 borderColorF[4]; // FIXME(b/129523279): Part of Vulkan sampler.
float maxAnisotropy; float maxAnisotropy; // FIXME(b/129523279): Part of Vulkan sampler.
int baseLevel; int baseLevel;
int maxLevel; int maxLevel;
float minLod; float minLod; // FIXME(b/129523279): Part of Vulkan sampler.
float maxLod; float maxLod; // FIXME(b/129523279): Part of Vulkan sampler.
}; };
enum SamplerType enum SamplerType
......
...@@ -227,7 +227,7 @@ namespace sw ...@@ -227,7 +227,7 @@ namespace sw
return c; return c;
} }
Vector4f SamplerCore::sampleTexture(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Float4 &bias, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function) Vector4f SamplerCore::sampleTextureF(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Float4 &bias, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function)
{ {
Vector4f c; Vector4f c;
......
...@@ -51,7 +51,7 @@ namespace sw ...@@ -51,7 +51,7 @@ namespace sw
SamplerCore(Pointer<Byte> &constants, const Sampler::State &state); SamplerCore(Pointer<Byte> &constants, const Sampler::State &state);
Vector4s sampleTexture(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Float4 &bias, Vector4f &dsx, Vector4f &dsy); Vector4s sampleTexture(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Float4 &bias, Vector4f &dsx, Vector4f &dsy);
Vector4f sampleTexture(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Float4 &bias, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function); 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); static Vector4f textureSize(Pointer<Byte> &mipmap, Float4 &lod);
private: private:
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "SpirvShader.hpp" #include "SpirvShader.hpp"
#include "SamplerCore.hpp"
#include "System/Math.hpp" #include "System/Math.hpp"
#include "Vulkan/VkBuffer.hpp" #include "Vulkan/VkBuffer.hpp"
#include "Vulkan/VkDebug.hpp" #include "Vulkan/VkDebug.hpp"
...@@ -27,6 +28,7 @@ ...@@ -27,6 +28,7 @@
#ifdef Bool #ifdef Bool
#undef Bool // b/127920555 #undef Bool // b/127920555
#undef None
#endif #endif
namespace namespace
...@@ -338,6 +340,12 @@ namespace sw ...@@ -338,6 +340,12 @@ namespace sw
break; // Correctly handled. break; // Correctly handled.
case spv::StorageClassUniformConstant: case spv::StorageClassUniformConstant:
// This storage class is for data stored within the descriptor itself,
// unlike StorageClassUniform which contains handles to buffers.
// For Vulkan it corresponds with samplers, images, or combined image samplers.
object.kind = Object::Kind::SampledImage;
break;
case spv::StorageClassWorkgroup: case spv::StorageClassWorkgroup:
case spv::StorageClassCrossWorkgroup: case spv::StorageClassCrossWorkgroup:
case spv::StorageClassGeneric: case spv::StorageClassGeneric:
...@@ -470,9 +478,12 @@ namespace sw ...@@ -470,9 +478,12 @@ namespace sw
break; break;
case spv::OpFConvert: case spv::OpFConvert:
UNIMPLEMENTED("No valid uses for OpFConvert until we support multiple bit widths enabled by features such as Float16/Float64 etc.");
break;
case spv::OpSConvert: case spv::OpSConvert:
case spv::OpUConvert: case spv::OpUConvert:
UNIMPLEMENTED("No valid uses for Op*Convert until we support multiple bit widths"); UNIMPLEMENTED("No valid uses for Op*Convert until we support multiple bit widths enabled by features such as Int16/Int64 etc.");
break; break;
case spv::OpLoad: case spv::OpLoad:
...@@ -597,18 +608,10 @@ namespace sw ...@@ -597,18 +608,10 @@ namespace sw
case spv::OpFwidthFine: case spv::OpFwidthFine:
case spv::OpAtomicLoad: case spv::OpAtomicLoad:
case spv::OpPhi: case spv::OpPhi:
// Instructions that yield an intermediate value or divergent case spv::OpImageSampleImplicitLod:
// pointer // Instructions that yield an intermediate value or divergent pointer
{ DefineResult(insn);
Type::ID typeId = insn.word(1);
Object::ID resultId = insn.word(2);
auto &object = defs[resultId];
object.type = typeId;
object.kind = (getType(typeId).opcode() == spv::OpTypePointer)
? Object::Kind::DivergentPointer : Object::Kind::Intermediate;
object.definition = insn;
break; break;
}
case spv::OpStore: case spv::OpStore:
case spv::OpAtomicStore: case spv::OpAtomicStore:
...@@ -1852,6 +1855,8 @@ namespace sw ...@@ -1852,6 +1855,8 @@ namespace sw
case spv::OpTypeStruct: case spv::OpTypeStruct:
case spv::OpTypePointer: case spv::OpTypePointer:
case spv::OpTypeFunction: case spv::OpTypeFunction:
case spv::OpTypeImage:
case spv::OpTypeSampledImage:
case spv::OpExecutionMode: case spv::OpExecutionMode:
case spv::OpMemoryModel: case spv::OpMemoryModel:
case spv::OpFunction: case spv::OpFunction:
...@@ -2056,6 +2061,9 @@ namespace sw ...@@ -2056,6 +2061,9 @@ namespace sw
case spv::OpKill: case spv::OpKill:
return EmitKill(insn, state); return EmitKill(insn, state);
case spv::OpImageSampleImplicitLod:
return EmitImageSampleImplicitLod(insn, state);
default: default:
UNIMPLEMENTED("opcode: %s", OpcodeName(opcode).c_str()); UNIMPLEMENTED("opcode: %s", OpcodeName(opcode).c_str());
break; break;
...@@ -2095,6 +2103,20 @@ namespace sw ...@@ -2095,6 +2103,20 @@ namespace sw
routine->createPointer(resultId, &routine->getVariable(resultId)[0]); routine->createPointer(resultId, &routine->getVariable(resultId)[0]);
break; break;
} }
case spv::StorageClassUniformConstant:
{
const auto &d = descriptorDecorations.at(resultId);
ASSERT(d.DescriptorSet >= 0);
ASSERT(d.Binding >= 0);
uint32_t arrayIndex = 0; // TODO(b/129523279)
auto setLayout = routine->pipelineLayout->getDescriptorSetLayout(d.DescriptorSet);
size_t bindingOffset = setLayout->getBindingOffset(d.Binding, arrayIndex);
Pointer<Byte> set = routine->descriptorSets[d.DescriptorSet]; // DescriptorSet*
Pointer<Byte> binding = Pointer<Byte>(set + bindingOffset); // SampledImageDescriptor*
routine->createPointer(resultId, binding);
break;
}
case spv::StorageClassUniform: case spv::StorageClassUniform:
case spv::StorageClassStorageBuffer: case spv::StorageClassStorageBuffer:
{ {
...@@ -2133,6 +2155,16 @@ namespace sw ...@@ -2133,6 +2155,16 @@ namespace sw
ASSERT(Type::ID(insn.word(1)) == result.type); ASSERT(Type::ID(insn.word(1)) == result.type);
ASSERT(!atomic || getType(getType(pointer.type).element).opcode() == spv::OpTypeInt); // Vulkan 1.1: "Atomic instructions must declare a scalar 32-bit integer type, for the value pointed to by Pointer." ASSERT(!atomic || getType(getType(pointer.type).element).opcode() == spv::OpTypeInt); // Vulkan 1.1: "Atomic instructions must declare a scalar 32-bit integer type, for the value pointed to by Pointer."
if(pointer.kind == Object::Kind::SampledImage)
{
// Just propagate the pointer.
// TODO(b/129523279)
auto &ptr = routine->getPointer(pointerId);
routine->createPointer(resultId, ptr);
return EmitResult::Continue;
}
if(atomic) if(atomic)
{ {
Object::ID semanticsId = insn.word(5); Object::ID semanticsId = insn.word(5);
...@@ -4125,6 +4157,86 @@ namespace sw ...@@ -4125,6 +4157,86 @@ namespace sw
return EmitResult::Continue; return EmitResult::Continue;
} }
SpirvShader::EmitResult SpirvShader::EmitImageSampleImplicitLod(InsnIterator insn, EmitState *state) const
{
Type::ID resultTypeId = insn.word(1);
Object::ID resultId = insn.word(2);
Object::ID sampledImageId = insn.word(3);
Object::ID coordinateId = insn.word(4);
auto &resultType = getType(resultTypeId);
auto &result = state->routine->createIntermediate(resultId, resultType.sizeInComponents);
auto &sampledImage = state->routine->getPointer(sampledImageId);
auto coordinate = GenericValue(this, state->routine, coordinateId);
Pointer<Byte> constants; // FIXME(b/129523279)
const DescriptorDecorations &d = descriptorDecorations.at(sampledImageId);
uint32_t arrayIndex = 0; // TODO(b/129523279)
auto setLayout = state->routine->pipelineLayout->getDescriptorSetLayout(d.DescriptorSet);
size_t bindingOffset = setLayout->getBindingOffset(d.Binding, arrayIndex);
const uint8_t *p = reinterpret_cast<const uint8_t*>(state->descriptorSets[d.DescriptorSet]) + bindingOffset;
const auto *t = reinterpret_cast<const vk::SampledImageDescriptor*>(p);
Sampler::State samplerState;
samplerState.textureType = TEXTURE_2D; ASSERT(t->imageView->getType() == VK_IMAGE_VIEW_TYPE_2D); // TODO(b/129523279)
samplerState.textureFormat = t->imageView->getFormat();
samplerState.textureFilter = FILTER_POINT; ASSERT(t->sampler->magFilter == VK_FILTER_NEAREST); ASSERT(t->sampler->minFilter == VK_FILTER_NEAREST); // TODO(b/129523279)
samplerState.addressingModeU = ADDRESSING_WRAP; ASSERT(t->sampler->addressModeU == VK_SAMPLER_ADDRESS_MODE_REPEAT); // TODO(b/129523279)
samplerState.addressingModeV = ADDRESSING_WRAP; ASSERT(t->sampler->addressModeV == VK_SAMPLER_ADDRESS_MODE_REPEAT); // TODO(b/129523279)
samplerState.addressingModeW = ADDRESSING_WRAP; ASSERT(t->sampler->addressModeW == VK_SAMPLER_ADDRESS_MODE_REPEAT); // TODO(b/129523279)
samplerState.mipmapFilter = MIPMAP_POINT; ASSERT(t->sampler->mipmapMode == VK_SAMPLER_MIPMAP_MODE_NEAREST); // TODO(b/129523279)
samplerState.sRGB = false; ASSERT(t->imageView->getFormat().isSRGBformat() == false); // TODO(b/129523279)
samplerState.swizzleR = SWIZZLE_RED; ASSERT(t->imageView->getComponentMapping().r == VK_COMPONENT_SWIZZLE_R); // TODO(b/129523279)
samplerState.swizzleG = SWIZZLE_GREEN; ASSERT(t->imageView->getComponentMapping().g == VK_COMPONENT_SWIZZLE_G); // TODO(b/129523279)
samplerState.swizzleB = SWIZZLE_BLUE; ASSERT(t->imageView->getComponentMapping().b == VK_COMPONENT_SWIZZLE_B); // TODO(b/129523279)
samplerState.swizzleA = SWIZZLE_ALPHA; ASSERT(t->imageView->getComponentMapping().a == VK_COMPONENT_SWIZZLE_A); // TODO(b/129523279)
samplerState.highPrecisionFiltering = false;
samplerState.compare = COMPARE_BYPASS; ASSERT(t->sampler->compareEnable == VK_FALSE); // TODO(b/129523279)
// minLod // TODO(b/129523279)
// maxLod // TODO(b/129523279)
// borderColor // TODO(b/129523279)
ASSERT(t->sampler->mipLodBias == 0.0f); // TODO(b/129523279)
ASSERT(t->sampler->anisotropyEnable == VK_FALSE); // TODO(b/129523279)
ASSERT(t->sampler->unnormalizedCoordinates == VK_FALSE); // TODO(b/129523279)
SamplerCore sampler(constants, samplerState);
Pointer<Byte> texture = sampledImage + OFFSET(vk::SampledImageDescriptor, texture); // sw::Texture*
SIMD::Float u = coordinate.Float(0);
SIMD::Float v = coordinate.Float(1);
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 = sampler.sampleTextureF(texture, u, v, w, q, bias, dsx, dsy, offset, samplerFunction);
if(getType(resultType.element).opcode() == spv::OpTypeFloat)
{
result.move(0, sample.x);
result.move(1, sample.y);
result.move(2, sample.z);
result.move(3, sample.w);
}
else
{
// TODO(b/129523279): Add a Sampler::sampleTextureI() method.
result.move(0, As<SIMD::Int>(sample.x * SIMD::Float(0xFF)));
result.move(1, As<SIMD::Int>(sample.y * SIMD::Float(0xFF)));
result.move(2, As<SIMD::Int>(sample.z * SIMD::Float(0xFF)));
result.move(3, As<SIMD::Int>(sample.w * SIMD::Float(0xFF)));
}
return EmitResult::Continue;
}
void SpirvShader::emitEpilog(SpirvRoutine *routine) const void SpirvShader::emitEpilog(SpirvRoutine *routine) const
{ {
for (auto insn : *this) for (auto insn : *this)
......
...@@ -283,6 +283,9 @@ namespace sw ...@@ -283,6 +283,9 @@ namespace sw
// A pointer to a vk::DescriptorSet*. // A pointer to a vk::DescriptorSet*.
// Pointer held by SpirvRoutine::pointers. // Pointer held by SpirvRoutine::pointers.
DescriptorSet, DescriptorSet,
// Pointer to an image/sampler descriptor.
SampledImage,
}; };
Kind kind = Kind::Unknown; Kind kind = Kind::Unknown;
...@@ -719,6 +722,7 @@ namespace sw ...@@ -719,6 +722,7 @@ namespace sw
EmitResult EmitReturn(InsnIterator insn, EmitState *state) const; EmitResult EmitReturn(InsnIterator insn, EmitState *state) const;
EmitResult EmitKill(InsnIterator insn, EmitState *state) const; EmitResult EmitKill(InsnIterator insn, EmitState *state) const;
EmitResult EmitPhi(InsnIterator insn, EmitState *state) const; EmitResult EmitPhi(InsnIterator insn, EmitState *state) const;
EmitResult EmitImageSampleImplicitLod(InsnIterator insn, EmitState *state) const;
// OpcodeName() returns the name of the opcode op. // OpcodeName() returns the name of the opcode op.
// If NDEBUG is defined, then OpcodeName() will only return the numerical code. // If NDEBUG is defined, then OpcodeName() will only return the numerical code.
......
...@@ -13,7 +13,10 @@ ...@@ -13,7 +13,10 @@
// limitations under the License. // limitations under the License.
#include "VkDescriptorSetLayout.hpp" #include "VkDescriptorSetLayout.hpp"
#include "VkDescriptorSet.hpp" #include "VkDescriptorSet.hpp"
#include "VkSampler.hpp"
#include "VkImageView.hpp"
#include "System/Types.hpp" #include "System/Types.hpp"
#include <algorithm> #include <algorithm>
...@@ -90,6 +93,7 @@ size_t DescriptorSetLayout::GetDescriptorSize(VkDescriptorType type) ...@@ -90,6 +93,7 @@ size_t DescriptorSetLayout::GetDescriptorSize(VkDescriptorType type)
case VK_DESCRIPTOR_TYPE_SAMPLER: case VK_DESCRIPTOR_TYPE_SAMPLER:
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
return sizeof(SampledImageDescriptor);
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
return sizeof(VkDescriptorImageInfo); return sizeof(VkDescriptorImageInfo);
...@@ -153,8 +157,8 @@ void DescriptorSetLayout::initialize(VkDescriptorSet vkDescriptorSet) ...@@ -153,8 +157,8 @@ void DescriptorSetLayout::initialize(VkDescriptorSet vkDescriptorSet)
{ {
for(uint32_t j = 0; j < bindings[i].descriptorCount; j++) for(uint32_t j = 0; j < bindings[i].descriptorCount; j++)
{ {
VkDescriptorImageInfo* imageInfo = reinterpret_cast<VkDescriptorImageInfo*>(mem); SampledImageDescriptor* imageSamplerDescriptor = reinterpret_cast<SampledImageDescriptor*>(mem);
imageInfo->sampler = bindings[i].pImmutableSamplers[j]; imageSamplerDescriptor->sampler = vk::Cast(bindings[i].pImmutableSamplers[j]);
mem += typeSize; mem += typeSize;
} }
} }
...@@ -233,25 +237,25 @@ uint8_t* DescriptorSetLayout::getOffsetPointer(DescriptorSet *descriptorSet, uin ...@@ -233,25 +237,25 @@ uint8_t* DescriptorSetLayout::getOffsetPointer(DescriptorSet *descriptorSet, uin
return &descriptorSet->data[byteOffset]; return &descriptorSet->data[byteOffset];
} }
const uint8_t* DescriptorSetLayout::GetInputData(const VkWriteDescriptorSet& descriptorWrites) const uint8_t* DescriptorSetLayout::GetInputData(const VkWriteDescriptorSet& writeDescriptorSet)
{ {
switch(descriptorWrites.descriptorType) switch(writeDescriptorSet.descriptorType)
{ {
case VK_DESCRIPTOR_TYPE_SAMPLER: case VK_DESCRIPTOR_TYPE_SAMPLER:
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
return reinterpret_cast<const uint8_t*>(descriptorWrites.pImageInfo); return reinterpret_cast<const uint8_t*>(writeDescriptorSet.pImageInfo);
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
return reinterpret_cast<const uint8_t*>(descriptorWrites.pTexelBufferView); return reinterpret_cast<const uint8_t*>(writeDescriptorSet.pTexelBufferView);
break; break;
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
return reinterpret_cast<const uint8_t*>(descriptorWrites.pBufferInfo); return reinterpret_cast<const uint8_t*>(writeDescriptorSet.pBufferInfo);
break; break;
default: default:
UNIMPLEMENTED("descriptorType"); UNIMPLEMENTED("descriptorType");
...@@ -259,24 +263,186 @@ const uint8_t* DescriptorSetLayout::GetInputData(const VkWriteDescriptorSet& des ...@@ -259,24 +263,186 @@ const uint8_t* DescriptorSetLayout::GetInputData(const VkWriteDescriptorSet& des
} }
} }
void DescriptorSetLayout::WriteDescriptorSet(const VkWriteDescriptorSet& descriptorWrites) void DescriptorSetLayout::WriteDescriptorSet(const VkWriteDescriptorSet& writeDescriptorSet)
{ {
DescriptorSet* dstSet = vk::Cast(descriptorWrites.dstSet); DescriptorSet* dstSet = vk::Cast(writeDescriptorSet.dstSet);
DescriptorSetLayout* dstLayout = dstSet->layout; DescriptorSetLayout* dstLayout = dstSet->layout;
ASSERT(dstLayout); ASSERT(dstLayout);
ASSERT(dstLayout->bindings[dstLayout->getBindingIndex(descriptorWrites.dstBinding)].descriptorType == descriptorWrites.descriptorType); ASSERT(dstLayout->bindings[dstLayout->getBindingIndex(writeDescriptorSet.dstBinding)].descriptorType == writeDescriptorSet.descriptorType);
size_t typeSize = 0; size_t typeSize = 0;
uint8_t* memToWrite = dstLayout->getOffsetPointer(dstSet, descriptorWrites.dstBinding, descriptorWrites.dstArrayElement, descriptorWrites.descriptorCount, &typeSize); uint8_t* memToWrite = dstLayout->getOffsetPointer(dstSet, writeDescriptorSet.dstBinding, writeDescriptorSet.dstArrayElement, writeDescriptorSet.descriptorCount, &typeSize);
if(writeDescriptorSet.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
{
SampledImageDescriptor *imageSampler = reinterpret_cast<SampledImageDescriptor*>(memToWrite);
for(uint32_t i = 0; i < writeDescriptorSet.descriptorCount; i++)
{
vk::Sampler *sampler = vk::Cast(writeDescriptorSet.pImageInfo[i].sampler);
vk::ImageView *imageView = vk::Cast(writeDescriptorSet.pImageInfo[i].imageView);
imageSampler[i].sampler = sampler;
imageSampler[i].imageView = imageView;
sw::Texture *texture = &imageSampler[i].texture;
memset(texture, 0, sizeof(sw::Texture)); // TODO(b/129523279): eliminate
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);
VkOffset3D offset = {0, 0, 0};
VkImageAspectFlagBits aspect = VK_IMAGE_ASPECT_COLOR_BIT;
void *buffer = imageView->getOffsetPointer(offset, aspect);
sw::Mipmap &mipmap = texture->mipmap[mipmapLevel];
mipmap.buffer[0] = buffer;
VkExtent3D extent = imageView->getMipLevelExtent(level);
Format format = imageView->getFormat();
int width = extent.width;
int height = extent.height;
int depth = extent.depth;
int pitchP = imageView->rowPitchBytes(aspect, level) / format.bytes();
int sliceP = imageView->slicePitchBytes(aspect, level) / format.bytes();
float exp2LOD = 1.0f;
if(mipmapLevel == 0)
{
texture->widthHeightLOD[0] = width * exp2LOD;
texture->widthHeightLOD[1] = width * exp2LOD;
texture->widthHeightLOD[2] = height * exp2LOD;
texture->widthHeightLOD[3] = height * exp2LOD;
texture->widthLOD[0] = width * exp2LOD;
texture->widthLOD[1] = width * exp2LOD;
texture->widthLOD[2] = width * exp2LOD;
texture->widthLOD[3] = width * exp2LOD;
texture->heightLOD[0] = height * exp2LOD;
texture->heightLOD[1] = height * exp2LOD;
texture->heightLOD[2] = height * exp2LOD;
texture->heightLOD[3] = height * exp2LOD;
texture->depthLOD[0] = depth * exp2LOD;
texture->depthLOD[1] = depth * exp2LOD;
texture->depthLOD[2] = depth * exp2LOD;
texture->depthLOD[3] = depth * exp2LOD;
}
if(format.isFloatFormat())
{
mipmap.fWidth[0] = (float)width / 65536.0f;
mipmap.fWidth[1] = (float)width / 65536.0f;
mipmap.fWidth[2] = (float)width / 65536.0f;
mipmap.fWidth[3] = (float)width / 65536.0f;
mipmap.fHeight[0] = (float)height / 65536.0f;
mipmap.fHeight[1] = (float)height / 65536.0f;
mipmap.fHeight[2] = (float)height / 65536.0f;
mipmap.fHeight[3] = (float)height / 65536.0f;
mipmap.fDepth[0] = (float)depth / 65536.0f;
mipmap.fDepth[1] = (float)depth / 65536.0f;
mipmap.fDepth[2] = (float)depth / 65536.0f;
mipmap.fDepth[3] = (float)depth / 65536.0f;
}
short halfTexelU = 0x8000 / width;
short halfTexelV = 0x8000 / height;
short halfTexelW = 0x8000 / depth;
mipmap.uHalf[0] = halfTexelU;
mipmap.uHalf[1] = halfTexelU;
mipmap.uHalf[2] = halfTexelU;
mipmap.uHalf[3] = halfTexelU;
mipmap.vHalf[0] = halfTexelV;
mipmap.vHalf[1] = halfTexelV;
mipmap.vHalf[2] = halfTexelV;
mipmap.vHalf[3] = halfTexelV;
mipmap.wHalf[0] = halfTexelW;
mipmap.wHalf[1] = halfTexelW;
mipmap.wHalf[2] = halfTexelW;
mipmap.wHalf[3] = halfTexelW;
mipmap.width[0] = width;
mipmap.width[1] = width;
mipmap.width[2] = width;
mipmap.width[3] = width;
mipmap.height[0] = height;
mipmap.height[1] = height;
mipmap.height[2] = height;
mipmap.height[3] = height;
mipmap.depth[0] = depth;
mipmap.depth[1] = depth;
mipmap.depth[2] = depth;
mipmap.depth[3] = depth;
mipmap.onePitchP[0] = 1;
mipmap.onePitchP[1] = pitchP;
mipmap.onePitchP[2] = 1;
mipmap.onePitchP[3] = pitchP;
mipmap.pitchP[0] = pitchP;
mipmap.pitchP[1] = pitchP;
mipmap.pitchP[2] = pitchP;
mipmap.pitchP[3] = pitchP;
mipmap.sliceP[0] = sliceP;
mipmap.sliceP[1] = sliceP;
mipmap.sliceP[2] = sliceP;
mipmap.sliceP[3] = sliceP;
// TODO(b/129523279)
if(false/*format == FORMAT_YV12_BT601 ||
format == FORMAT_YV12_BT709 ||
format == FORMAT_YV12_JFIF*/)
{
unsigned int YStride = pitchP;
unsigned int YSize = YStride * height;
unsigned int CStride = sw::align<16>(YStride / 2);
unsigned int CSize = CStride * height / 2;
mipmap.buffer[1] = (sw::byte*)mipmap.buffer[0] + YSize;
mipmap.buffer[2] = (sw::byte*)mipmap.buffer[1] + CSize;
texture->mipmap[1].width[0] = width / 2;
texture->mipmap[1].width[1] = width / 2;
texture->mipmap[1].width[2] = width / 2;
texture->mipmap[1].width[3] = width / 2;
texture->mipmap[1].height[0] = height / 2;
texture->mipmap[1].height[1] = height / 2;
texture->mipmap[1].height[2] = height / 2;
texture->mipmap[1].height[3] = height / 2;
texture->mipmap[1].onePitchP[0] = 1;
texture->mipmap[1].onePitchP[1] = CStride;
texture->mipmap[1].onePitchP[2] = 1;
texture->mipmap[1].onePitchP[3] = CStride;
}
}
}
}
else
{
// If the dstBinding has fewer than descriptorCount array elements remaining // If the dstBinding has fewer than descriptorCount array elements remaining
// starting from dstArrayElement, then the remainder will be used to update // starting from dstArrayElement, then the remainder will be used to update
// the subsequent binding - dstBinding+1 starting at array element zero. If // the subsequent binding - dstBinding+1 starting at array element zero. If
// a binding has a descriptorCount of zero, it is skipped. This behavior // a binding has a descriptorCount of zero, it is skipped. This behavior
// applies recursively, with the update affecting consecutive bindings as // applies recursively, with the update affecting consecutive bindings as
// needed to update all descriptorCount descriptors. // needed to update all descriptorCount descriptors.
size_t writeSize = typeSize * descriptorWrites.descriptorCount; size_t writeSize = typeSize * writeDescriptorSet.descriptorCount;
memcpy(memToWrite, DescriptorSetLayout::GetInputData(descriptorWrites), writeSize); memcpy(memToWrite, DescriptorSetLayout::GetInputData(writeDescriptorSet), writeSize);
}
} }
void DescriptorSetLayout::CopyDescriptorSet(const VkCopyDescriptorSet& descriptorCopies) void DescriptorSetLayout::CopyDescriptorSet(const VkCopyDescriptorSet& descriptorCopies)
......
...@@ -17,11 +17,25 @@ ...@@ -17,11 +17,25 @@
#include "VkObject.hpp" #include "VkObject.hpp"
#include "Vulkan/VkSampler.hpp"
#include "Vulkan/VkImageView.hpp"
#include "Device/Sampler.hpp"
namespace vk namespace vk
{ {
class DescriptorSet; class DescriptorSet;
// TODO(b/129523279): Move to the Device or Pipeline layer.
struct SampledImageDescriptor
{
// TODO(b/129523279): Minimize to the data actually needed.
vk::Sampler *sampler;
vk::ImageView *imageView;
sw::Texture texture;
};
class DescriptorSetLayout : public Object<DescriptorSetLayout, VkDescriptorSetLayout> class DescriptorSetLayout : public Object<DescriptorSetLayout, VkDescriptorSetLayout>
{ {
public: public:
......
...@@ -144,7 +144,6 @@ bool Format::isSRGBformat() const ...@@ -144,7 +144,6 @@ bool Format::isSRGBformat() const
bool Format::isSRGBreadable() const bool Format::isSRGBreadable() const
{ {
// Keep in sync with Capabilities::isSRGBreadable
switch(format) switch(format)
{ {
case VK_FORMAT_B8G8R8A8_UNORM: case VK_FORMAT_B8G8R8A8_UNORM:
...@@ -160,7 +159,6 @@ bool Format::isSRGBreadable() const ...@@ -160,7 +159,6 @@ bool Format::isSRGBreadable() const
bool Format::isSRGBwritable() const bool Format::isSRGBwritable() const
{ {
// Keep in sync with Capabilities::isSRGBwritable
switch(format) switch(format)
{ {
case VK_FORMAT_UNDEFINED: case VK_FORMAT_UNDEFINED:
......
...@@ -36,23 +36,28 @@ public: ...@@ -36,23 +36,28 @@ public:
void clear(const VkClearValue& clearValue, VkImageAspectFlags aspectMask, const VkClearRect& renderArea); void clear(const VkClearValue& clearValue, VkImageAspectFlags aspectMask, const VkClearRect& renderArea);
void resolve(ImageView* resolveAttachment); void resolve(ImageView* resolveAttachment);
VkImageViewType getType() const { return viewType; }
Format getFormat() const { return format; } Format getFormat() const { return format; }
int getSampleCount() const { return image->getSampleCountFlagBits(); } int getSampleCount() const { return image->getSampleCountFlagBits(); }
int rowPitchBytes(VkImageAspectFlagBits aspect) const { return image->rowPitchBytes(aspect, subresourceRange.baseMipLevel); } int rowPitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel) const { return image->rowPitchBytes(aspect, subresourceRange.baseMipLevel + mipLevel); }
int slicePitchBytes(VkImageAspectFlagBits aspect) const { return image->slicePitchBytes(aspect, subresourceRange.baseMipLevel); } int slicePitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel) const { return image->slicePitchBytes(aspect, subresourceRange.baseMipLevel + mipLevel); }
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) const;
bool hasDepthAspect() const { return (subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0; } bool hasDepthAspect() const { return (subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0; }
bool hasStencilAspect() const { return (subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0; } bool hasStencilAspect() const { return (subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0; }
const VkComponentMapping &getComponentMapping() const { return components; }
const VkImageSubresourceRange &getSubresourceRange() const { return subresourceRange; }
private: private:
bool imageTypesMatch(VkImageType imageType) const; bool imageTypesMatch(VkImageType imageType) const;
Image* image = nullptr; Image *const image = nullptr;
VkImageViewType viewType = VK_IMAGE_VIEW_TYPE_2D; const VkImageViewType viewType = VK_IMAGE_VIEW_TYPE_2D;
Format format; const Format format;
VkComponentMapping components = {}; const VkComponentMapping components = {};
VkImageSubresourceRange subresourceRange = {}; const VkImageSubresourceRange subresourceRange = {};
}; };
static inline ImageView* Cast(VkImageView object) static inline ImageView* Cast(VkImageView object)
......
...@@ -49,22 +49,21 @@ public: ...@@ -49,22 +49,21 @@ public:
return 0; return 0;
} }
private: const VkFilter magFilter = VK_FILTER_NEAREST;
VkFilter magFilter = VK_FILTER_NEAREST; const VkFilter minFilter = VK_FILTER_NEAREST;
VkFilter minFilter = VK_FILTER_NEAREST; const VkSamplerMipmapMode mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
VkSamplerMipmapMode mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; const VkSamplerAddressMode addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
VkSamplerAddressMode addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; const VkSamplerAddressMode addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
VkSamplerAddressMode addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; const VkSamplerAddressMode addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
VkSamplerAddressMode addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; const float mipLodBias = 0.0f;
float mipLodBias = 0.0f; const VkBool32 anisotropyEnable = VK_FALSE;
VkBool32 anisotropyEnable = VK_FALSE; const float maxAnisotropy = 0.0f;
float maxAnisotropy = 0.0f; const VkBool32 compareEnable = VK_FALSE;
VkBool32 compareEnable = VK_FALSE; const VkCompareOp compareOp = VK_COMPARE_OP_NEVER;
VkCompareOp compareOp = VK_COMPARE_OP_NEVER; const float minLod = 0.0f;
float minLod = 0.0f; const float maxLod = 0.0f;
float maxLod = 0.0f; const VkBorderColor borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
VkBorderColor borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; const VkBool32 unnormalizedCoordinates = VK_FALSE;
VkBool32 unnormalizedCoordinates = VK_FALSE;
}; };
static inline Sampler* Cast(VkSampler object) static inline Sampler* Cast(VkSampler object)
......
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