Commit 225a1301 by Ben Clayton

Implement dynamic buffer offsets.

Tests: *dynamic* Bug: b/126330097 Change-Id: I7e4f7e3d921acb72878b7728216415ba66f63ec7 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/28249Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Tested-by: 's avatarBen Clayton <bclayton@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
parent fcbb1450
......@@ -112,11 +112,6 @@ namespace sw
void Context::init()
{
for(int i = 0; i < vk::MAX_BOUND_DESCRIPTOR_SETS; i++)
{
descriptorSets[i] = nullptr;
}
// Set vertex streams to null stream
for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
{
......
......@@ -16,6 +16,7 @@
#define sw_Context_hpp
#include "Vulkan/VkConfig.h"
#include "Vulkan/VkDescriptorSet.hpp"
#include "Sampler.hpp"
#include "Stream.hpp"
#include "Point.hpp"
......@@ -153,7 +154,8 @@ namespace sw
int colorWriteActive(int index);
bool colorUsed();
vk::DescriptorSet *descriptorSets[vk::MAX_BOUND_DESCRIPTOR_SETS];
vk::DescriptorSet::Bindings descriptorSets = {};
vk::DescriptorSet::DynamicOffsets descriptorDynamicOffsets = {};
Stream input[MAX_VERTEX_INPUTS];
void *indexBuffer;
......
......@@ -28,7 +28,7 @@ namespace sw
QuadRasterizer(const PixelProcessor::State &state, SpirvShader const *spirvShader);
virtual ~QuadRasterizer();
virtual void generate();
void generate();
protected:
Pointer<Byte> constants;
......
......@@ -388,10 +388,8 @@ namespace sw
draw->setupPrimitives = setupPrimitives;
draw->setupState = setupState;
for(int i = 0; i < vk::MAX_BOUND_DESCRIPTOR_SETS; i++)
{
data->descriptorSets[i] = context->descriptorSets[i];
}
data->descriptorSets = context->descriptorSets;
data->descriptorDynamicOffsets = context->descriptorDynamicOffsets;
for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
{
......
......@@ -23,6 +23,7 @@
#include "System/MutexLock.hpp"
#include "System/Thread.hpp"
#include "Device/Config.hpp"
#include "Vulkan/VkDescriptorSet.hpp"
#include <list>
......@@ -114,7 +115,8 @@ namespace sw
{
const Constants *constants;
vk::DescriptorSet *descriptorSets[vk::MAX_BOUND_DESCRIPTOR_SETS];
vk::DescriptorSet::Bindings descriptorSets = {};
vk::DescriptorSet::DynamicOffsets descriptorDynamicOffsets = {};
const void *input[MAX_VERTEX_INPUTS];
unsigned int stride[MAX_VERTEX_INPUTS];
......
......@@ -45,14 +45,9 @@ namespace sw
void ComputeProgram::emit()
{
Pointer<Pointer<Byte>> descriptorSetsIn = *Pointer<Pointer<Pointer<Byte>>>(data + OFFSET(Data, descriptorSets));
size_t numDescriptorSets = routine.pipelineLayout->getNumDescriptorSets();
for(unsigned int i = 0; i < numDescriptorSets; i++)
{
routine.descriptorSets[i] = descriptorSetsIn[i];
}
routine.pushConstants = Pointer<Byte>(data + OFFSET(Data, pushConstants));
routine.descriptorSets = data + OFFSET(Data, descriptorSets);
routine.descriptorDynamicOffsets = data + OFFSET(Data, descriptorDynamicOffsets);
routine.pushConstants = data + OFFSET(Data, pushConstants);
auto &modes = shader->getModes();
......@@ -178,13 +173,17 @@ namespace sw
}
void ComputeProgram::run(
Routine *routine, void** descriptorSets, PushConstantStorage const &pushConstants,
Routine *routine,
vk::DescriptorSet::Bindings const &descriptorSets,
vk::DescriptorSet::DynamicOffsets const &descriptorDynamicOffsets,
PushConstantStorage const &pushConstants,
uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
{
auto runWorkgroup = (void(*)(void*))(routine->getEntry());
Data data;
data.descriptorSets = descriptorSets;
data.descriptorDynamicOffsets = descriptorDynamicOffsets;
data.numWorkgroups[X] = groupCountX;
data.numWorkgroups[Y] = groupCountY;
data.numWorkgroups[Z] = groupCountZ;
......
......@@ -19,6 +19,7 @@
#include "Reactor/Reactor.hpp"
#include "Device/Context.hpp"
#include "Vulkan/VkDescriptorSet.hpp"
#include <functional>
......@@ -48,7 +49,10 @@ namespace sw
// run executes the compute shader routine for all workgroups.
// TODO(bclayton): This probably does not belong here. Consider moving.
static void run(
Routine *routine, void** descriptorSets, PushConstantStorage const &pushConstants,
Routine *routine,
vk::DescriptorSet::Bindings const &descriptorSetBindings,
vk::DescriptorSet::DynamicOffsets const &descriptorDynamicOffsets,
PushConstantStorage const &pushConstants,
uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
protected:
......@@ -60,7 +64,8 @@ namespace sw
struct Data
{
void** descriptorSets;
vk::DescriptorSet::Bindings descriptorSets;
vk::DescriptorSet::DynamicOffsets descriptorDynamicOffsets;
uint4 numWorkgroups;
uint4 workgroupID;
PushConstantStorage pushConstants;
......
......@@ -31,6 +31,8 @@ namespace sw
{
enableIndex = 0;
routine.descriptorSets = data + OFFSET(DrawData, descriptorSets);
routine.descriptorDynamicOffsets = data + OFFSET(DrawData, descriptorDynamicOffsets);
routine.pushConstants = data + OFFSET(DrawData, pushConstants);
auto activeLaneMask = SIMD::Int(0xFFFFFFFF); // TODO: Control this.
......
......@@ -54,18 +54,6 @@ namespace sw
{
}
void PixelRoutine::generate()
{
Pointer<Pointer<Byte>> descriptorSets = Pointer<Pointer<Byte>>(data + OFFSET(DrawData, descriptorSets));
auto numDescriptorSets = routine.pipelineLayout->getNumDescriptorSets();
for(unsigned int i = 0; i < numDescriptorSets; i++)
{
routine.descriptorSets[i] = descriptorSets[i];
}
QuadRasterizer::generate();
}
void PixelRoutine::quad(Pointer<Byte> cBuffer[RENDERTARGETS], Pointer<Byte> &zBuffer, Pointer<Byte> &sBuffer, Int cMask[4], Int &x, Int &y)
{
#if PERF_PROFILE
......
......@@ -31,8 +31,6 @@ namespace sw
virtual ~PixelRoutine();
void generate() override;
protected:
Float4 z[4]; // Multisampled z
Float4 w; // Used as is
......
......@@ -18,6 +18,7 @@
#include "System/Math.hpp"
#include "Vulkan/VkBuffer.hpp"
#include "Vulkan/VkDebug.hpp"
#include "Vulkan/VkDescriptorSet.hpp"
#include "Vulkan/VkPipelineLayout.hpp"
#include "Device/Config.hpp"
......@@ -1722,15 +1723,25 @@ namespace sw
ASSERT(d.DescriptorSet >= 0);
ASSERT(d.Binding >= 0);
size_t bindingOffset = routine->pipelineLayout->getBindingOffset(d.DescriptorSet, d.Binding);
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> set = routine->descriptorSets[d.DescriptorSet]; // DescriptorSet*
Pointer<Byte> binding = Pointer<Byte>(set + bindingOffset); // VkDescriptorBufferInfo*
Pointer<Byte> buffer = *Pointer<Pointer<Byte>>(binding + OFFSET(VkDescriptorBufferInfo, buffer)); // vk::Buffer*
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>(binding + OFFSET(VkDescriptorBufferInfo, offset));
Pointer<Byte> address = data + offset;
routine->physicalPointers[resultId] = address;
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->physicalPointers[resultId] = data + offset;
break;
}
case spv::StorageClassPushConstant:
......
......@@ -660,7 +660,8 @@ namespace sw
Value inputs = Value{MAX_INTERFACE_COMPONENTS};
Value outputs = Value{MAX_INTERFACE_COMPONENTS};
std::array<Pointer<Byte>, vk::MAX_BOUND_DESCRIPTOR_SETS> descriptorSets;
Pointer<Pointer<Byte>> descriptorSets;
Pointer<Int> descriptorDynamicOffsets;
Pointer<Byte> pushConstants;
Int killMask = Int{0};
......
......@@ -46,14 +46,9 @@ namespace sw
As<Float4>(Int4((*Pointer<Int>(data + OFFSET(DrawData, instanceID)))));
}
routine.descriptorSets = data + OFFSET(DrawData, descriptorSets);
routine.descriptorDynamicOffsets = data + OFFSET(DrawData, descriptorDynamicOffsets);
routine.pushConstants = data + OFFSET(DrawData, pushConstants);
Pointer<Pointer<Byte>> descriptorSets = Pointer<Pointer<Byte>>(data + OFFSET(DrawData, descriptorSets));
auto numDescriptorSets = routine.pipelineLayout->getNumDescriptorSets();
for(unsigned int i = 0; i < numDescriptorSets; i++)
{
routine.descriptorSets[i] = descriptorSets[i];
}
}
VertexProgram::~VertexProgram()
......
......@@ -152,7 +152,7 @@ public:
protected:
void play(CommandBuffer::ExecutionState& executionState) override
{
executionState.pipelines[pipelineBindPoint] = Cast(pipeline);
executionState.pipelineState[pipelineBindPoint].pipeline = Cast(pipeline);
}
private:
......@@ -171,11 +171,12 @@ public:
protected:
void play(CommandBuffer::ExecutionState& executionState) override
{
ComputePipeline* pipeline = static_cast<ComputePipeline*>(
executionState.pipelines[VK_PIPELINE_BIND_POINT_COMPUTE]);
auto const &pipelineState = executionState.pipelineState[VK_PIPELINE_BIND_POINT_COMPUTE];
ComputePipeline* pipeline = static_cast<ComputePipeline*>(pipelineState.pipeline);
pipeline->run(groupCountX, groupCountY, groupCountZ,
MAX_BOUND_DESCRIPTOR_SETS,
executionState.boundDescriptorSets[VK_PIPELINE_BIND_POINT_COMPUTE],
pipelineState.descriptorSets,
pipelineState.descriptorDynamicOffsets,
executionState.pushConstants);
}
......@@ -198,12 +199,13 @@ protected:
{
auto cmd = reinterpret_cast<VkDispatchIndirectCommand const *>(Cast(buffer)->getOffsetPointer(offset));
ComputePipeline* pipeline = static_cast<ComputePipeline*>(
executionState.pipelines[VK_PIPELINE_BIND_POINT_COMPUTE]);
auto const &pipelineState = executionState.pipelineState[VK_PIPELINE_BIND_POINT_COMPUTE];
ComputePipeline* pipeline = static_cast<ComputePipeline*>(pipelineState.pipeline);
pipeline->run(cmd->x, cmd->y, cmd->z,
MAX_BOUND_DESCRIPTOR_SETS,
executionState.boundDescriptorSets[VK_PIPELINE_BIND_POINT_COMPUTE],
executionState.pushConstants);
pipelineState.descriptorSets,
pipelineState.descriptorDynamicOffsets,
executionState.pushConstants);
}
private:
......@@ -304,19 +306,16 @@ struct DrawBase : public CommandBuffer::Command
void draw(CommandBuffer::ExecutionState& executionState, bool indexed,
uint32_t count, uint32_t instanceCount, uint32_t first, int32_t vertexOffset, uint32_t firstInstance)
{
GraphicsPipeline* pipeline = static_cast<GraphicsPipeline*>(
executionState.pipelines[VK_PIPELINE_BIND_POINT_GRAPHICS]);
auto const &pipelineState = executionState.pipelineState[VK_PIPELINE_BIND_POINT_GRAPHICS];
GraphicsPipeline* pipeline = static_cast<GraphicsPipeline*>(pipelineState.pipeline);
sw::Context context = pipeline->getContext();
executionState.bindVertexInputs(context, vertexOffset, firstInstance);
const auto& boundDescriptorSets = executionState.boundDescriptorSets[VK_PIPELINE_BIND_POINT_GRAPHICS];
for(int i = 0; i < vk::MAX_BOUND_DESCRIPTOR_SETS; i++)
{
context.descriptorSets[i] = reinterpret_cast<vk::DescriptorSet*>(boundDescriptorSets[i]);
}
context.descriptorSets = pipelineState.descriptorSets;
context.descriptorDynamicOffsets = pipelineState.descriptorDynamicOffsets;
context.pushConstants = executionState.pushConstants;
if (indexed)
......@@ -683,21 +682,38 @@ private:
struct BindDescriptorSet : public CommandBuffer::Command
{
BindDescriptorSet(VkPipelineBindPoint pipelineBindPoint, uint32_t set, const VkDescriptorSet& descriptorSet)
: pipelineBindPoint(pipelineBindPoint), set(set), descriptorSet(descriptorSet)
BindDescriptorSet(VkPipelineBindPoint pipelineBindPoint, uint32_t set, const VkDescriptorSet& descriptorSet,
uint32_t dynamicOffsetCount, uint32_t const *dynamicOffsets)
: pipelineBindPoint(pipelineBindPoint), set(set), descriptorSet(descriptorSet),
dynamicOffsetCount(dynamicOffsetCount)
{
for (uint32_t i = 0; i < dynamicOffsetCount; i++)
{
this->dynamicOffsets[i] = dynamicOffsets[i];
}
}
void play(CommandBuffer::ExecutionState& executionState)
{
ASSERT((pipelineBindPoint < VK_PIPELINE_BIND_POINT_RANGE_SIZE) && (set < MAX_BOUND_DESCRIPTOR_SETS));
executionState.boundDescriptorSets[pipelineBindPoint][set] = descriptorSet;
ASSERT_OR_RETURN((pipelineBindPoint < VK_PIPELINE_BIND_POINT_RANGE_SIZE) && (set < MAX_BOUND_DESCRIPTOR_SETS));
auto &pipelineState = executionState.pipelineState[pipelineBindPoint];
auto pipelineLayout = pipelineState.pipeline->getLayout();
auto dynamicOffsetBase = pipelineLayout->getDynamicOffsetBase(set);
ASSERT_OR_RETURN(dynamicOffsetBase + dynamicOffsetCount <= MAX_DESCRIPTOR_SET_COMBINED_BUFFERS_DYNAMIC);
pipelineState.descriptorSets[set] = vk::Cast(descriptorSet);
for (uint32_t i = 0; i < dynamicOffsetCount; i++)
{
pipelineState.descriptorDynamicOffsets[dynamicOffsetBase + i] = dynamicOffsets[i];
}
}
private:
VkPipelineBindPoint pipelineBindPoint;
uint32_t set;
const VkDescriptorSet descriptorSet;
uint32_t dynamicOffsetCount;
vk::DescriptorSet::DynamicOffsets dynamicOffsets;
};
struct SetPushConstants : public CommandBuffer::Command
......@@ -974,20 +990,28 @@ void CommandBuffer::setStencilReference(VkStencilFaceFlags faceMask, uint32_t re
UNIMPLEMENTED("setStencilReference");
}
void CommandBuffer::bindDescriptorSets(VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout,
void CommandBuffer::bindDescriptorSets(VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout vkLayout,
uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets,
uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets)
{
ASSERT(state == RECORDING);
if(dynamicOffsetCount > 0)
{
UNIMPLEMENTED("bindDescriptorSets");
}
for(uint32_t i = 0; i < descriptorSetCount; i++)
{
addCommand<BindDescriptorSet>(pipelineBindPoint, firstSet + i, pDescriptorSets[i]);
auto descriptorSetIndex = firstSet + i;
auto layout = vk::Cast(vkLayout);
auto setLayout = layout->getDescriptorSetLayout(descriptorSetIndex);
auto numDynamicDescriptors = setLayout->getDynamicDescriptorCount();
ASSERT(numDynamicDescriptors == 0 || pDynamicOffsets != nullptr);
ASSERT(dynamicOffsetCount >= numDynamicDescriptors);
addCommand<BindDescriptorSet>(
pipelineBindPoint, descriptorSetIndex, pDescriptorSets[i],
dynamicOffsetCount, pDynamicOffsets);
pDynamicOffsets += numDynamicDescriptors;
dynamicOffsetCount -= numDynamicDescriptors;
}
}
......
......@@ -17,6 +17,7 @@
#include "VkConfig.h"
#include "VkObject.hpp"
#include "VkDescriptorSet.hpp"
#include "Device/Context.hpp"
#include <memory>
#include <vector>
......@@ -123,11 +124,17 @@ public:
// TODO(sugoi): Move ExecutionState out of CommandBuffer (possibly into Device)
struct ExecutionState
{
struct PipelineState
{
Pipeline *pipeline = nullptr;
vk::DescriptorSet::Bindings descriptorSets = {};
vk::DescriptorSet::DynamicOffsets descriptorDynamicOffsets = {};
};
sw::Renderer* renderer = nullptr;
RenderPass* renderPass = nullptr;
Framebuffer* renderPassFramebuffer = nullptr;
Pipeline* pipelines[VK_PIPELINE_BIND_POINT_RANGE_SIZE] = {};
VkDescriptorSet boundDescriptorSets[VK_PIPELINE_BIND_POINT_RANGE_SIZE][MAX_BOUND_DESCRIPTOR_SETS] = { { VK_NULL_HANDLE } };
std::array<PipelineState, VK_PIPELINE_BIND_POINT_RANGE_SIZE> pipelineState;
sw::PushConstantStorage pushConstants;
struct VertexInputBinding
......
......@@ -62,6 +62,15 @@ enum
enum
{
MAX_DESCRIPTOR_SET_UNIFORM_BUFFERS_DYNAMIC = 8,
MAX_DESCRIPTOR_SET_STORAGE_BUFFERS_DYNAMIC = 4,
MAX_DESCRIPTOR_SET_COMBINED_BUFFERS_DYNAMIC =
MAX_DESCRIPTOR_SET_UNIFORM_BUFFERS_DYNAMIC +
MAX_DESCRIPTOR_SET_STORAGE_BUFFERS_DYNAMIC,
};
enum
{
MAX_POINT_SIZE = 1, // Large points are not supported. If/when we turn this on, must be >= 64.
};
......
// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef VK_DESCRIPTOR_SET_HPP_
#define VK_DESCRIPTOR_SET_HPP_
// Intentionally not including VkObject.hpp here due to b/127920555
#include <array>
#include <memory>
namespace vk
{
class DescriptorSetLayout;
class DescriptorSet
{
public:
using Bindings = std::array<vk::DescriptorSet*, vk::MAX_BOUND_DESCRIPTOR_SETS>;
using DynamicOffsets = std::array<uint32_t, vk::MAX_DESCRIPTOR_SET_COMBINED_BUFFERS_DYNAMIC>;
DescriptorSetLayout* layout;
uint8_t data[];
};
inline DescriptorSet* Cast(VkDescriptorSet object)
{
return reinterpret_cast<DescriptorSet*>(object);
}
} // namespace vk
#endif // VK_DESCRIPTOR_SET_HPP_
......@@ -13,6 +13,7 @@
// limitations under the License.
#include "VkDescriptorSetLayout.hpp"
#include "VkDescriptorSet.hpp"
#include "System/Types.hpp"
#include <algorithm>
......@@ -134,7 +135,7 @@ uint32_t DescriptorSetLayout::getBindingIndex(uint32_t binding) const
}
}
ASSERT(false); // Bindings should always be found
DABORT("Invalid DescriptorSetLayout binding: %d", int(binding));
return 0;
}
......@@ -164,10 +165,63 @@ void DescriptorSetLayout::initialize(VkDescriptorSet vkDescriptorSet)
}
}
size_t DescriptorSetLayout::getBindingOffset(uint32_t binding) const
size_t DescriptorSetLayout::getBindingCount() const
{
return bindingCount;
}
size_t DescriptorSetLayout::getBindingOffset(uint32_t binding, uint32_t arrayElement) const
{
uint32_t index = getBindingIndex(binding);
auto typeSize = GetDescriptorSize(bindings[index].descriptorType);
return bindingOffsets[index] + OFFSET(DescriptorSet, data[0]) + (typeSize * arrayElement);
}
bool DescriptorSetLayout::isDynamic(VkDescriptorType type)
{
return type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
}
bool DescriptorSetLayout::isBindingDynamic(uint32_t binding) const
{
uint32_t index = getBindingIndex(binding);
return bindingOffsets[index] + OFFSET(DescriptorSet, data[0]);
return isDynamic(bindings[index].descriptorType);
}
size_t DescriptorSetLayout::getDynamicDescriptorCount() const
{
size_t count = 0;
for (size_t i = 0; i < bindingCount; i++)
{
if (isDynamic(bindings[i].descriptorType))
{
count += bindings[i].descriptorCount;
}
}
return count;
}
size_t DescriptorSetLayout::getDynamicDescriptorOffset(uint32_t binding) const
{
uint32_t n = getBindingIndex(binding);
ASSERT(isDynamic(bindings[n].descriptorType));
size_t index = 0;
for (uint32_t i = 0; i < n; i++)
{
if (isDynamic(bindings[i].descriptorType))
{
index += bindings[i].descriptorCount;
}
}
return index;
}
VkDescriptorSetLayoutBinding const & DescriptorSetLayout::getBindingLayout(uint32_t binding) const
{
ASSERT(binding < bindingCount);
return bindings[binding];
}
uint8_t* DescriptorSetLayout::getOffsetPointer(DescriptorSet *descriptorSet, uint32_t binding, uint32_t arrayElement, uint32_t count, size_t* typeSize) const
......
......@@ -20,18 +20,7 @@
namespace vk
{
class DescriptorSetLayout;
struct DescriptorSet
{
vk::DescriptorSetLayout* layout;
uint8_t data[];
};
inline DescriptorSet* Cast(VkDescriptorSet object)
{
return reinterpret_cast<DescriptorSet*>(object);
}
class DescriptorSet;
class DescriptorSetLayout : public Object<DescriptorSetLayout, VkDescriptorSetLayout>
{
......@@ -47,15 +36,43 @@ public:
static void CopyDescriptorSet(const VkCopyDescriptorSet& descriptorCopies);
void initialize(VkDescriptorSet descriptorSet);
// Returns the total size of the descriptor set in bytes.
size_t getDescriptorSetAllocationSize() const;
size_t getBindingOffset(uint32_t binding) const;
// Returns the number of bindings in the descriptor set.
size_t getBindingCount() const;
// Returns the byte offset from the base address of the descriptor set for
// the given binding and array element within that binding.
size_t getBindingOffset(uint32_t binding, uint32_t arrayElement) const;
// Returns the number of descriptors across all bindings that are dynamic
// (see isBindingDynamic).
size_t getDynamicDescriptorCount() const;
// Returns the relative offset into the pipeline's dynamic offsets array for
// the given binding. This offset should be added to the base offset
// returned by PipelineLayout::getDynamicOffsetBase() to produce the
// starting index for dynamic descriptors.
size_t getDynamicDescriptorOffset(uint32_t binding) const;
// Returns true if the given binding is of type:
// VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC or
// VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC
bool isBindingDynamic(uint32_t binding) const;
// Returns the VkDescriptorSetLayoutBinding for the binding with the given
// index.
VkDescriptorSetLayoutBinding const & getBindingLayout(uint32_t binding) const;
uint8_t* getOffsetPointer(DescriptorSet *descriptorSet, uint32_t binding, uint32_t arrayElement, uint32_t count, size_t* typeSize) const;
private:
size_t getDescriptorSetDataSize() const;
uint32_t getBindingIndex(uint32_t binding) const;
static const uint8_t* GetInputData(const VkWriteDescriptorSet& descriptorWrites);
static bool isDynamic(VkDescriptorType type);
VkDescriptorSetLayoutCreateFlags flags;
uint32_t bindingCount;
......
......@@ -13,6 +13,7 @@
// limitations under the License.
#include "VkDescriptorUpdateTemplate.hpp"
#include "VkDescriptorSet.hpp"
#include "VkDescriptorSetLayout.hpp"
#include <cstring>
......
......@@ -162,9 +162,9 @@ const VkPhysicalDeviceLimits& PhysicalDevice::getLimits() const
128, // maxPerStageResources
96, // maxDescriptorSetSamplers
72, // maxDescriptorSetUniformBuffers
8, // maxDescriptorSetUniformBuffersDynamic
MAX_DESCRIPTOR_SET_UNIFORM_BUFFERS_DYNAMIC, // maxDescriptorSetUniformBuffersDynamic
24, // maxDescriptorSetStorageBuffers
4, // maxDescriptorSetStorageBuffersDynamic
MAX_DESCRIPTOR_SET_STORAGE_BUFFERS_DYNAMIC, // maxDescriptorSetStorageBuffersDynamic
96, // maxDescriptorSetSampledImages
24, // maxDescriptorSetStorageImages
4, // maxDescriptorSetInputAttachments
......
......@@ -517,11 +517,13 @@ void ComputePipeline::compileShaders(const VkAllocationCallbacks* pAllocator, co
}
void ComputePipeline::run(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ,
size_t numDescriptorSets, VkDescriptorSet *descriptorSets, sw::PushConstantStorage const &pushConstants)
vk::DescriptorSet::Bindings const &descriptorSets,
vk::DescriptorSet::DynamicOffsets const &descriptorDynamicOffsets,
sw::PushConstantStorage const &pushConstants)
{
ASSERT_OR_RETURN(routine != nullptr);
sw::ComputeProgram::run(
routine, reinterpret_cast<void**>(descriptorSets), pushConstants,
routine, descriptorSets, descriptorDynamicOffsets, pushConstants,
groupCountX, groupCountY, groupCountZ);
}
......
......@@ -16,6 +16,7 @@
#define VK_PIPELINE_HPP_
#include "VkObject.hpp"
#include "Vulkan/VkDescriptorSet.hpp"
#include "Device/Renderer.hpp"
namespace sw { class SpirvShader; }
......@@ -104,7 +105,9 @@ public:
void compileShaders(const VkAllocationCallbacks* pAllocator, const VkComputePipelineCreateInfo* pCreateInfo);
void run(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ,
size_t numDescriptorSets, VkDescriptorSet *descriptorSets, sw::PushConstantStorage const &pushConstants);
vk::DescriptorSet::Bindings const &descriptorSets,
vk::DescriptorSet::DynamicOffsets const &descriptorDynamicOffsets,
sw::PushConstantStorage const &pushConstants);
protected:
sw::SpirvShader *shader = nullptr;
......
......@@ -31,6 +31,16 @@ PipelineLayout::PipelineLayout(const VkPipelineLayoutCreateInfo* pCreateInfo, vo
size_t pushConstantRangesSize = pCreateInfo->pushConstantRangeCount * sizeof(VkPushConstantRange);
pushConstantRanges = reinterpret_cast<VkPushConstantRange*>(hostMem);
memcpy(pushConstantRanges, pCreateInfo->pPushConstantRanges, pushConstantRangesSize);
hostMem += pushConstantRangesSize;
dynamicOffsetBases = reinterpret_cast<uint32_t*>(hostMem);
uint32_t dynamicOffsetBase = 0;
for (uint32_t i = 0; i < setLayoutCount; i++)
{
ASSERT_OR_RETURN(dynamicOffsetBase < MAX_DESCRIPTOR_SET_COMBINED_BUFFERS_DYNAMIC);
dynamicOffsetBases[i] = dynamicOffsetBase;
dynamicOffsetBase += setLayouts[i]->getDynamicDescriptorCount();
}
}
void PipelineLayout::destroy(const VkAllocationCallbacks* pAllocator)
......@@ -41,7 +51,8 @@ void PipelineLayout::destroy(const VkAllocationCallbacks* pAllocator)
size_t PipelineLayout::ComputeRequiredAllocationSize(const VkPipelineLayoutCreateInfo* pCreateInfo)
{
return (pCreateInfo->setLayoutCount * sizeof(DescriptorSetLayout*)) +
(pCreateInfo->pushConstantRangeCount * sizeof(VkPushConstantRange));
(pCreateInfo->pushConstantRangeCount * sizeof(VkPushConstantRange)) +
(pCreateInfo->setLayoutCount * sizeof(uint32_t)); // dynamicOffsetBases
}
size_t PipelineLayout::getNumDescriptorSets() const
......@@ -49,10 +60,16 @@ size_t PipelineLayout::getNumDescriptorSets() const
return setLayoutCount;
}
size_t PipelineLayout::getBindingOffset(size_t descriptorSet, size_t binding) const
DescriptorSetLayout const* PipelineLayout::getDescriptorSetLayout(size_t descriptorSet) const
{
ASSERT(descriptorSet < setLayoutCount);
return setLayouts[descriptorSet];
}
uint32_t PipelineLayout::getDynamicOffsetBase(size_t descriptorSet) const
{
ASSERT(descriptorSet < setLayoutCount);
return setLayouts[descriptorSet]->getBindingOffset(binding);
return dynamicOffsetBases[descriptorSet];
}
} // namespace vk
......@@ -30,13 +30,18 @@ public:
static size_t ComputeRequiredAllocationSize(const VkPipelineLayoutCreateInfo* pCreateInfo);
size_t getNumDescriptorSets() const;
size_t getBindingOffset(size_t descriptorSet, size_t binding) const;
DescriptorSetLayout const* getDescriptorSetLayout(size_t descriptorSet) const;
// Returns the starting index into the pipeline's dynamic offsets array for
// the given descriptor set.
uint32_t getDynamicOffsetBase(size_t descriptorSet) const;
private:
uint32_t setLayoutCount = 0;
DescriptorSetLayout** setLayouts = nullptr;
uint32_t pushConstantRangeCount = 0;
VkPushConstantRange* pushConstantRanges = nullptr;
uint32_t* dynamicOffsetBases = nullptr; // Base offset per set layout.
};
static inline PipelineLayout* Cast(VkPipelineLayout 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