Commit 6b511347 by Ben Clayton

SpirvShader: Implement descriptor set arrays

Introduce a new Object::Kind - DescriptorSet. This represents a pointer to a vk::DescriptorSet*, which is now dereferenced to access the buffer data in OpAccessChain or OpLoad / OpStore. This shuffling is required to handle descriptor array access as the array index is only known at OpAccessChain time. Tests: *dynamic* Bug: b/126330097 Change-Id: Id754d966d8945f4e4fcf7895ed2210ce4f6ba713 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/28391Tested-by: 's avatarBen Clayton <bclayton@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent 484e08e0
...@@ -203,6 +203,9 @@ namespace sw ...@@ -203,6 +203,9 @@ namespace sw
case spv::StorageClassUniform: case spv::StorageClassUniform:
case spv::StorageClassStorageBuffer: case spv::StorageClassStorageBuffer:
object.kind = Object::Kind::DescriptorSet;
break;
case spv::StorageClassPushConstant: case spv::StorageClassPushConstant:
case spv::StorageClassPrivate: case spv::StorageClassPrivate:
case spv::StorageClassFunction: case spv::StorageClassFunction:
...@@ -818,6 +821,33 @@ namespace sw ...@@ -818,6 +821,33 @@ namespace sw
case Object::Kind::DivergentPointer: case Object::Kind::DivergentPointer:
return std::make_pair(routine->getPointer(id), routine->getIntermediate(id).Int(0)); return std::make_pair(routine->getPointer(id), routine->getIntermediate(id).Int(0));
case Object::Kind::DescriptorSet:
{
Decorations d = {};
ApplyDecorationsForId(&d, id);
ASSERT(d.DescriptorSet >= 0);
ASSERT(d.Binding >= 0);
auto set = routine->getPointer(id);
auto setLayout = routine->pipelineLayout->getDescriptorSetLayout(d.DescriptorSet);
size_t bindingOffset = setLayout->getBindingOffset(d.Binding, arrayIndex);
Pointer<Byte> bufferInfo = Pointer<Byte>(set + bindingOffset); // VkDescriptorBufferInfo*
Pointer<Byte> buffer = *Pointer<Pointer<Byte>>(bufferInfo + OFFSET(VkDescriptorBufferInfo, buffer)); // vk::Buffer*
Pointer<Byte> data = *Pointer<Pointer<Byte>>(buffer + vk::Buffer::DataOffset); // void*
Int offset = *Pointer<Int>(bufferInfo + OFFSET(VkDescriptorBufferInfo, offset));
if (setLayout->isBindingDynamic(d.Binding))
{
uint32_t dynamicBindingIndex =
routine->pipelineLayout->getDynamicOffsetBase(d.DescriptorSet) +
setLayout->getDynamicDescriptorOffset(d.Binding) +
arrayIndex;
offset += routine->descriptorDynamicOffsets[dynamicBindingIndex];
}
return std::make_pair(data + offset, SIMD::Int(0));
}
default: default:
UNREACHABLE("Invalid pointer kind %d", int(object.kind)); UNREACHABLE("Invalid pointer kind %d", int(object.kind));
return std::make_pair(Pointer<Byte>(), SIMD::Int(0)); return std::make_pair(Pointer<Byte>(), SIMD::Int(0));
...@@ -833,9 +863,24 @@ namespace sw ...@@ -833,9 +863,24 @@ namespace sw
Decorations d = {}; Decorations d = {};
ApplyDecorationsForId(&d, baseObject.type); ApplyDecorationsForId(&d, baseObject.type);
size_t arrayIndex = 0;
if (baseObject.kind == Object::Kind::DescriptorSet)
{
auto type = getType(typeId).definition.opcode();
if (type == spv::OpTypeArray || type == spv::OpTypeRuntimeArray)
{
ASSERT(getObject(indexIds[0]).kind == Object::Kind::Constant);
arrayIndex = GetConstantInt(indexIds[0]);
numIndexes--;
indexIds++;
typeId = getType(typeId).element;
}
}
SIMD::Int dynamicOffset; SIMD::Int dynamicOffset;
Pointer<Byte> pointerBase; Pointer<Byte> pointerBase;
std::tie(pointerBase, dynamicOffset) = GetPointerToData(id, 0, routine); std::tie(pointerBase, dynamicOffset) = GetPointerToData(id, arrayIndex, routine);
int constantOffset = 0; int constantOffset = 0;
...@@ -1735,27 +1780,7 @@ namespace sw ...@@ -1735,27 +1780,7 @@ namespace sw
Decorations d{}; Decorations d{};
ApplyDecorationsForId(&d, resultId); ApplyDecorationsForId(&d, resultId);
ASSERT(d.DescriptorSet >= 0); ASSERT(d.DescriptorSet >= 0);
ASSERT(d.Binding >= 0); routine->createPointer(resultId, routine->descriptorSets[d.DescriptorSet]);
auto set = routine->descriptorSets[d.DescriptorSet]; // DescriptorSet*
auto setLayout = routine->pipelineLayout->getDescriptorSetLayout(d.DescriptorSet);
size_t arrayIndex = 0; // TODO: descriptor arrays
size_t bindingOffset = setLayout->getBindingOffset(d.Binding, arrayIndex);
Pointer<Byte> bufferInfo = Pointer<Byte>(set + bindingOffset); // VkDescriptorBufferInfo*
Pointer<Byte> buffer = *Pointer<Pointer<Byte>>(bufferInfo + OFFSET(VkDescriptorBufferInfo, buffer)); // vk::Buffer*
Pointer<Byte> data = *Pointer<Pointer<Byte>>(buffer + vk::Buffer::DataOffset); // void*
Int offset = *Pointer<Int>(bufferInfo + OFFSET(VkDescriptorBufferInfo, offset));
if (setLayout->isBindingDynamic(d.Binding))
{
uint32_t dynamicBindingIndex =
routine->pipelineLayout->getDynamicOffsetBase(d.DescriptorSet) +
setLayout->getDynamicDescriptorOffset(d.Binding) +
arrayIndex;
offset += routine->descriptorDynamicOffsets[dynamicBindingIndex];
}
routine->createPointer(resultId, data + offset);
break; break;
} }
case spv::StorageClassPushConstant: case spv::StorageClassPushConstant:
......
...@@ -263,6 +263,10 @@ namespace sw ...@@ -263,6 +263,10 @@ namespace sw
// Pointer held by SpirvRoutine::pointers // Pointer held by SpirvRoutine::pointers
NonDivergentPointer, NonDivergentPointer,
// A pointer to a vk::DescriptorSet*.
// Pointer held by SpirvRoutine::pointers.
DescriptorSet,
} kind = Kind::Unknown; } kind = Kind::Unknown;
}; };
...@@ -560,6 +564,7 @@ namespace sw ...@@ -560,6 +564,7 @@ namespace sw
// Returns a base pointer and per-lane offset to the underlying data for // Returns a base pointer and per-lane offset to the underlying data for
// the given pointer object. Handles objects of the following kinds: // the given pointer object. Handles objects of the following kinds:
// • DescriptorSet
// • DivergentPointer // • DivergentPointer
// • InterfaceVariable // • InterfaceVariable
// • NonDivergentPointer // • NonDivergentPointer
......
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