diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp index ff5d7d6cbba63..0e2a6f827dea9 100644 --- a/src/Pipeline/SpirvShader.cpp +++ b/src/Pipeline/SpirvShader.cpp @@ -15,6 +15,7 @@ #include #include "SpirvShader.hpp" #include "System/Math.hpp" +#include "Vulkan/VkBuffer.hpp" #include "Vulkan/VkDebug.hpp" #include "Vulkan/VkPipelineLayout.hpp" #include "Device/Config.hpp" @@ -154,10 +155,36 @@ namespace sw object.type = typeId; object.pointerBase = insn.word(2); // base is itself - // Register builtins - if (storageClass == spv::StorageClassInput || storageClass == spv::StorageClassOutput) + ASSERT(getType(typeId).storageClass == storageClass); + + switch (storageClass) { + case spv::StorageClassInput: + case spv::StorageClassOutput: ProcessInterfaceVariable(object); + break; + case spv::StorageClassUniform: + case spv::StorageClassStorageBuffer: + object.kind = Object::Kind::PhysicalPointer; + break; + + case spv::StorageClassPrivate: + case spv::StorageClassFunction: + break; // Correctly handled. + + case spv::StorageClassUniformConstant: + case spv::StorageClassWorkgroup: + case spv::StorageClassCrossWorkgroup: + case spv::StorageClassGeneric: + case spv::StorageClassPushConstant: + case spv::StorageClassAtomicCounter: + case spv::StorageClassImage: + UNIMPLEMENTED("StorageClass %d not yet implemented", (int)storageClass); + break; + + default: + UNREACHABLE("Unexpected StorageClass"); // See Appendix A of the Vulkan spec. + break; } break; } @@ -1036,15 +1063,43 @@ namespace sw ObjectID resultId = insn.word(2); auto &object = getObject(resultId); auto &objectTy = getType(object.type); - if (object.kind == Object::Kind::InterfaceVariable && objectTy.storageClass == spv::StorageClassInput) + switch (objectTy.storageClass) { - auto &dst = routine->getValue(resultId); - int offset = 0; - VisitInterface(resultId, - [&](Decorations const &d, AttribType type) { - auto scalarSlot = d.Location << 2 | d.Component; - dst[offset++] = routine->inputs[scalarSlot]; - }); + case spv::StorageClassInput: + { + if (object.kind == Object::Kind::InterfaceVariable) + { + auto &dst = routine->getValue(resultId); + int offset = 0; + VisitInterface(resultId, + [&](Decorations const &d, AttribType type) { + auto scalarSlot = d.Location << 2 | d.Component; + dst[offset++] = routine->inputs[scalarSlot]; + }); + } + break; + } + case spv::StorageClassUniform: + case spv::StorageClassStorageBuffer: + { + Decorations d{}; + ApplyDecorationsForId(&d, resultId); + ASSERT(d.DescriptorSet >= 0); + ASSERT(d.Binding >= 0); + + size_t bindingOffset = routine->pipelineLayout->getBindingOffset(d.DescriptorSet, d.Binding); + + Pointer set = routine->descriptorSets[d.DescriptorSet]; // DescriptorSet* + Pointer binding = Pointer(set + bindingOffset); // VkDescriptorBufferInfo* + Pointer buffer = *Pointer>(binding + OFFSET(VkDescriptorBufferInfo, buffer)); // vk::Buffer* + Pointer data = *Pointer>(buffer + vk::Buffer::DataOffset); // void* + Int offset = *Pointer(binding + OFFSET(VkDescriptorBufferInfo, offset)); + Pointer address = data + offset; + routine->physicalPointers[resultId] = address; + break; + } + default: + break; } } @@ -1061,11 +1116,9 @@ namespace sw ASSERT(getType(pointer.type).element == object.type); ASSERT(TypeID(insn.word(1)) == object.type); - if (pointerBaseTy.storageClass == spv::StorageClassImage || - pointerBaseTy.storageClass == spv::StorageClassUniform || - pointerBaseTy.storageClass == spv::StorageClassUniformConstant) + if (pointerBaseTy.storageClass == spv::StorageClassImage) { - UNIMPLEMENTED("Descriptor-backed load not yet implemented"); + UNIMPLEMENTED("StorageClassImage load not yet implemented"); } Pointer ptrBase; @@ -1125,17 +1178,9 @@ namespace sw ObjectID baseId = insn.word(3); auto &object = getObject(objectId); auto &type = getType(typeId); - auto &pointerBase = getObject(object.pointerBase); - auto &pointerBaseTy = getType(pointerBase.type); ASSERT(type.sizeInComponents == 1); ASSERT(getObject(baseId).pointerBase == object.pointerBase); - if (pointerBaseTy.storageClass == spv::StorageClassImage || - pointerBaseTy.storageClass == spv::StorageClassUniform || - pointerBaseTy.storageClass == spv::StorageClassUniformConstant) - { - UNIMPLEMENTED("Descriptor-backed OpAccessChain not yet implemented"); - } auto &dst = routine->createIntermediate(objectId, type.sizeInComponents); dst.emplace(0, As(WalkAccessChain(baseId, insn.wordCount() - 4, insn.wordPointer(4), routine))); } @@ -1151,11 +1196,9 @@ namespace sw auto &pointerBase = getObject(pointer.pointerBase); auto &pointerBaseTy = getType(pointerBase.type); - if (pointerBaseTy.storageClass == spv::StorageClassImage || - pointerBaseTy.storageClass == spv::StorageClassUniform || - pointerBaseTy.storageClass == spv::StorageClassUniformConstant) + if (pointerBaseTy.storageClass == spv::StorageClassImage) { - UNIMPLEMENTED("Descriptor-backed store not yet implemented"); + UNIMPLEMENTED("StorageClassImage store not yet implemented"); } Pointer ptrBase; diff --git a/src/Vulkan/VkBuffer.cpp b/src/Vulkan/VkBuffer.cpp index 6b120671e0e69..421a4a053d4fd 100644 --- a/src/Vulkan/VkBuffer.cpp +++ b/src/Vulkan/VkBuffer.cpp @@ -21,6 +21,8 @@ namespace vk { +const size_t Buffer::DataOffset = offsetof(Buffer, memory); + Buffer::Buffer(const VkBufferCreateInfo* pCreateInfo, void* mem) : flags(pCreateInfo->flags), size(pCreateInfo->size), usage(pCreateInfo->usage), sharingMode(pCreateInfo->sharingMode), queueFamilyIndexCount(pCreateInfo->queueFamilyIndexCount), @@ -43,21 +45,21 @@ size_t Buffer::ComputeRequiredAllocationSize(const VkBufferCreateInfo* pCreateIn const VkMemoryRequirements Buffer::getMemoryRequirements() const { VkMemoryRequirements memoryRequirements = {}; - if(usage & (VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT)) - { - memoryRequirements.alignment = vk::MIN_TEXEL_BUFFER_OFFSET_ALIGNMENT; - } - else if(usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) - { - memoryRequirements.alignment = vk::MIN_STORAGE_BUFFER_OFFSET_ALIGNMENT; - } - else if(usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) - { - memoryRequirements.alignment = vk::MIN_UNIFORM_BUFFER_OFFSET_ALIGNMENT; - } - else - { - memoryRequirements.alignment = REQUIRED_MEMORY_ALIGNMENT; + if(usage & (VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT)) + { + memoryRequirements.alignment = vk::MIN_TEXEL_BUFFER_OFFSET_ALIGNMENT; + } + else if(usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) + { + memoryRequirements.alignment = vk::MIN_STORAGE_BUFFER_OFFSET_ALIGNMENT; + } + else if(usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) + { + memoryRequirements.alignment = vk::MIN_UNIFORM_BUFFER_OFFSET_ALIGNMENT; + } + else + { + memoryRequirements.alignment = REQUIRED_MEMORY_ALIGNMENT; } memoryRequirements.memoryTypeBits = vk::MEMORY_TYPE_GENERIC_BIT; memoryRequirements.size = size; // TODO: also reserve space for a header containing diff --git a/src/Vulkan/VkBuffer.hpp b/src/Vulkan/VkBuffer.hpp index 19dfc5522a7dd..255b0f174f41c 100644 --- a/src/Vulkan/VkBuffer.hpp +++ b/src/Vulkan/VkBuffer.hpp @@ -38,6 +38,10 @@ class Buffer : public Object void update(VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* pData); void* getOffsetPointer(VkDeviceSize offset) const; + // DataOffset is the offset in bytes from the Buffer to the pointer to the + // buffer's data memory. + static const size_t DataOffset; + private: void* memory = nullptr; VkBufferCreateFlags flags = 0;