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 ...@@ -112,11 +112,6 @@ namespace sw
void Context::init() void Context::init()
{ {
for(int i = 0; i < vk::MAX_BOUND_DESCRIPTOR_SETS; i++)
{
descriptorSets[i] = nullptr;
}
// Set vertex streams to null stream // Set vertex streams to null stream
for(int i = 0; i < MAX_VERTEX_INPUTS; i++) for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
{ {
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#define sw_Context_hpp #define sw_Context_hpp
#include "Vulkan/VkConfig.h" #include "Vulkan/VkConfig.h"
#include "Vulkan/VkDescriptorSet.hpp"
#include "Sampler.hpp" #include "Sampler.hpp"
#include "Stream.hpp" #include "Stream.hpp"
#include "Point.hpp" #include "Point.hpp"
...@@ -153,7 +154,8 @@ namespace sw ...@@ -153,7 +154,8 @@ namespace sw
int colorWriteActive(int index); int colorWriteActive(int index);
bool colorUsed(); bool colorUsed();
vk::DescriptorSet *descriptorSets[vk::MAX_BOUND_DESCRIPTOR_SETS]; vk::DescriptorSet::Bindings descriptorSets = {};
vk::DescriptorSet::DynamicOffsets descriptorDynamicOffsets = {};
Stream input[MAX_VERTEX_INPUTS]; Stream input[MAX_VERTEX_INPUTS];
void *indexBuffer; void *indexBuffer;
......
...@@ -28,7 +28,7 @@ namespace sw ...@@ -28,7 +28,7 @@ namespace sw
QuadRasterizer(const PixelProcessor::State &state, SpirvShader const *spirvShader); QuadRasterizer(const PixelProcessor::State &state, SpirvShader const *spirvShader);
virtual ~QuadRasterizer(); virtual ~QuadRasterizer();
virtual void generate(); void generate();
protected: protected:
Pointer<Byte> constants; Pointer<Byte> constants;
......
...@@ -388,10 +388,8 @@ namespace sw ...@@ -388,10 +388,8 @@ namespace sw
draw->setupPrimitives = setupPrimitives; draw->setupPrimitives = setupPrimitives;
draw->setupState = setupState; draw->setupState = setupState;
for(int i = 0; i < vk::MAX_BOUND_DESCRIPTOR_SETS; i++) data->descriptorSets = context->descriptorSets;
{ data->descriptorDynamicOffsets = context->descriptorDynamicOffsets;
data->descriptorSets[i] = context->descriptorSets[i];
}
for(int i = 0; i < MAX_VERTEX_INPUTS; i++) for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
{ {
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "System/MutexLock.hpp" #include "System/MutexLock.hpp"
#include "System/Thread.hpp" #include "System/Thread.hpp"
#include "Device/Config.hpp" #include "Device/Config.hpp"
#include "Vulkan/VkDescriptorSet.hpp"
#include <list> #include <list>
...@@ -114,7 +115,8 @@ namespace sw ...@@ -114,7 +115,8 @@ namespace sw
{ {
const Constants *constants; 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]; const void *input[MAX_VERTEX_INPUTS];
unsigned int stride[MAX_VERTEX_INPUTS]; unsigned int stride[MAX_VERTEX_INPUTS];
......
...@@ -45,14 +45,9 @@ namespace sw ...@@ -45,14 +45,9 @@ namespace sw
void ComputeProgram::emit() void ComputeProgram::emit()
{ {
Pointer<Pointer<Byte>> descriptorSetsIn = *Pointer<Pointer<Pointer<Byte>>>(data + OFFSET(Data, descriptorSets)); routine.descriptorSets = data + OFFSET(Data, descriptorSets);
size_t numDescriptorSets = routine.pipelineLayout->getNumDescriptorSets(); routine.descriptorDynamicOffsets = data + OFFSET(Data, descriptorDynamicOffsets);
for(unsigned int i = 0; i < numDescriptorSets; i++) routine.pushConstants = data + OFFSET(Data, pushConstants);
{
routine.descriptorSets[i] = descriptorSetsIn[i];
}
routine.pushConstants = Pointer<Byte>(data + OFFSET(Data, pushConstants));
auto &modes = shader->getModes(); auto &modes = shader->getModes();
...@@ -178,13 +173,17 @@ namespace sw ...@@ -178,13 +173,17 @@ namespace sw
} }
void ComputeProgram::run( 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) uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
{ {
auto runWorkgroup = (void(*)(void*))(routine->getEntry()); auto runWorkgroup = (void(*)(void*))(routine->getEntry());
Data data; Data data;
data.descriptorSets = descriptorSets; data.descriptorSets = descriptorSets;
data.descriptorDynamicOffsets = descriptorDynamicOffsets;
data.numWorkgroups[X] = groupCountX; data.numWorkgroups[X] = groupCountX;
data.numWorkgroups[Y] = groupCountY; data.numWorkgroups[Y] = groupCountY;
data.numWorkgroups[Z] = groupCountZ; data.numWorkgroups[Z] = groupCountZ;
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "Reactor/Reactor.hpp" #include "Reactor/Reactor.hpp"
#include "Device/Context.hpp" #include "Device/Context.hpp"
#include "Vulkan/VkDescriptorSet.hpp"
#include <functional> #include <functional>
...@@ -48,7 +49,10 @@ namespace sw ...@@ -48,7 +49,10 @@ namespace sw
// run executes the compute shader routine for all workgroups. // run executes the compute shader routine for all workgroups.
// TODO(bclayton): This probably does not belong here. Consider moving. // TODO(bclayton): This probably does not belong here. Consider moving.
static void run( 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); uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
protected: protected:
...@@ -60,7 +64,8 @@ namespace sw ...@@ -60,7 +64,8 @@ namespace sw
struct Data struct Data
{ {
void** descriptorSets; vk::DescriptorSet::Bindings descriptorSets;
vk::DescriptorSet::DynamicOffsets descriptorDynamicOffsets;
uint4 numWorkgroups; uint4 numWorkgroups;
uint4 workgroupID; uint4 workgroupID;
PushConstantStorage pushConstants; PushConstantStorage pushConstants;
......
...@@ -31,6 +31,8 @@ namespace sw ...@@ -31,6 +31,8 @@ namespace sw
{ {
enableIndex = 0; enableIndex = 0;
routine.descriptorSets = data + OFFSET(DrawData, descriptorSets);
routine.descriptorDynamicOffsets = data + OFFSET(DrawData, descriptorDynamicOffsets);
routine.pushConstants = data + OFFSET(DrawData, pushConstants); routine.pushConstants = data + OFFSET(DrawData, pushConstants);
auto activeLaneMask = SIMD::Int(0xFFFFFFFF); // TODO: Control this. auto activeLaneMask = SIMD::Int(0xFFFFFFFF); // TODO: Control this.
......
...@@ -54,18 +54,6 @@ namespace sw ...@@ -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) void PixelRoutine::quad(Pointer<Byte> cBuffer[RENDERTARGETS], Pointer<Byte> &zBuffer, Pointer<Byte> &sBuffer, Int cMask[4], Int &x, Int &y)
{ {
#if PERF_PROFILE #if PERF_PROFILE
......
...@@ -31,8 +31,6 @@ namespace sw ...@@ -31,8 +31,6 @@ namespace sw
virtual ~PixelRoutine(); virtual ~PixelRoutine();
void generate() override;
protected: protected:
Float4 z[4]; // Multisampled z Float4 z[4]; // Multisampled z
Float4 w; // Used as is Float4 w; // Used as is
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "System/Math.hpp" #include "System/Math.hpp"
#include "Vulkan/VkBuffer.hpp" #include "Vulkan/VkBuffer.hpp"
#include "Vulkan/VkDebug.hpp" #include "Vulkan/VkDebug.hpp"
#include "Vulkan/VkDescriptorSet.hpp"
#include "Vulkan/VkPipelineLayout.hpp" #include "Vulkan/VkPipelineLayout.hpp"
#include "Device/Config.hpp" #include "Device/Config.hpp"
...@@ -1722,15 +1723,25 @@ namespace sw ...@@ -1722,15 +1723,25 @@ namespace sw
ASSERT(d.DescriptorSet >= 0); ASSERT(d.DescriptorSet >= 0);
ASSERT(d.Binding >= 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> bufferInfo = Pointer<Byte>(set + bindingOffset); // VkDescriptorBufferInfo*
Pointer<Byte> binding = Pointer<Byte>(set + bindingOffset); // VkDescriptorBufferInfo* Pointer<Byte> buffer = *Pointer<Pointer<Byte>>(bufferInfo + OFFSET(VkDescriptorBufferInfo, buffer)); // vk::Buffer*
Pointer<Byte> buffer = *Pointer<Pointer<Byte>>(binding + OFFSET(VkDescriptorBufferInfo, buffer)); // vk::Buffer*
Pointer<Byte> data = *Pointer<Pointer<Byte>>(buffer + vk::Buffer::DataOffset); // void* Pointer<Byte> data = *Pointer<Pointer<Byte>>(buffer + vk::Buffer::DataOffset); // void*
Int offset = *Pointer<Int>(binding + OFFSET(VkDescriptorBufferInfo, offset)); Int offset = *Pointer<Int>(bufferInfo + OFFSET(VkDescriptorBufferInfo, offset));
Pointer<Byte> address = data + offset; if (setLayout->isBindingDynamic(d.Binding))
routine->physicalPointers[resultId] = address; {
uint32_t dynamicBindingIndex =
routine->pipelineLayout->getDynamicOffsetBase(d.DescriptorSet) +
setLayout->getDynamicDescriptorOffset(d.Binding) +
arrayIndex;
offset += routine->descriptorDynamicOffsets[dynamicBindingIndex];
}
routine->physicalPointers[resultId] = data + offset;
break; break;
} }
case spv::StorageClassPushConstant: case spv::StorageClassPushConstant:
......
...@@ -660,7 +660,8 @@ namespace sw ...@@ -660,7 +660,8 @@ namespace sw
Value inputs = Value{MAX_INTERFACE_COMPONENTS}; Value inputs = Value{MAX_INTERFACE_COMPONENTS};
Value outputs = 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; Pointer<Byte> pushConstants;
Int killMask = Int{0}; Int killMask = Int{0};
......
...@@ -46,14 +46,9 @@ namespace sw ...@@ -46,14 +46,9 @@ namespace sw
As<Float4>(Int4((*Pointer<Int>(data + OFFSET(DrawData, instanceID))))); 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); 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() VertexProgram::~VertexProgram()
......
...@@ -152,7 +152,7 @@ public: ...@@ -152,7 +152,7 @@ public:
protected: protected:
void play(CommandBuffer::ExecutionState& executionState) override void play(CommandBuffer::ExecutionState& executionState) override
{ {
executionState.pipelines[pipelineBindPoint] = Cast(pipeline); executionState.pipelineState[pipelineBindPoint].pipeline = Cast(pipeline);
} }
private: private:
...@@ -171,11 +171,12 @@ public: ...@@ -171,11 +171,12 @@ public:
protected: protected:
void play(CommandBuffer::ExecutionState& executionState) override void play(CommandBuffer::ExecutionState& executionState) override
{ {
ComputePipeline* pipeline = static_cast<ComputePipeline*>( auto const &pipelineState = executionState.pipelineState[VK_PIPELINE_BIND_POINT_COMPUTE];
executionState.pipelines[VK_PIPELINE_BIND_POINT_COMPUTE]);
ComputePipeline* pipeline = static_cast<ComputePipeline*>(pipelineState.pipeline);
pipeline->run(groupCountX, groupCountY, groupCountZ, pipeline->run(groupCountX, groupCountY, groupCountZ,
MAX_BOUND_DESCRIPTOR_SETS, pipelineState.descriptorSets,
executionState.boundDescriptorSets[VK_PIPELINE_BIND_POINT_COMPUTE], pipelineState.descriptorDynamicOffsets,
executionState.pushConstants); executionState.pushConstants);
} }
...@@ -198,11 +199,12 @@ protected: ...@@ -198,11 +199,12 @@ protected:
{ {
auto cmd = reinterpret_cast<VkDispatchIndirectCommand const *>(Cast(buffer)->getOffsetPointer(offset)); auto cmd = reinterpret_cast<VkDispatchIndirectCommand const *>(Cast(buffer)->getOffsetPointer(offset));
ComputePipeline* pipeline = static_cast<ComputePipeline*>( auto const &pipelineState = executionState.pipelineState[VK_PIPELINE_BIND_POINT_COMPUTE];
executionState.pipelines[VK_PIPELINE_BIND_POINT_COMPUTE]);
ComputePipeline* pipeline = static_cast<ComputePipeline*>(pipelineState.pipeline);
pipeline->run(cmd->x, cmd->y, cmd->z, pipeline->run(cmd->x, cmd->y, cmd->z,
MAX_BOUND_DESCRIPTOR_SETS, pipelineState.descriptorSets,
executionState.boundDescriptorSets[VK_PIPELINE_BIND_POINT_COMPUTE], pipelineState.descriptorDynamicOffsets,
executionState.pushConstants); executionState.pushConstants);
} }
...@@ -304,19 +306,16 @@ struct DrawBase : public CommandBuffer::Command ...@@ -304,19 +306,16 @@ struct DrawBase : public CommandBuffer::Command
void draw(CommandBuffer::ExecutionState& executionState, bool indexed, void draw(CommandBuffer::ExecutionState& executionState, bool indexed,
uint32_t count, uint32_t instanceCount, uint32_t first, int32_t vertexOffset, uint32_t firstInstance) uint32_t count, uint32_t instanceCount, uint32_t first, int32_t vertexOffset, uint32_t firstInstance)
{ {
GraphicsPipeline* pipeline = static_cast<GraphicsPipeline*>( auto const &pipelineState = executionState.pipelineState[VK_PIPELINE_BIND_POINT_GRAPHICS];
executionState.pipelines[VK_PIPELINE_BIND_POINT_GRAPHICS]);
GraphicsPipeline* pipeline = static_cast<GraphicsPipeline*>(pipelineState.pipeline);
sw::Context context = pipeline->getContext(); sw::Context context = pipeline->getContext();
executionState.bindVertexInputs(context, vertexOffset, firstInstance); executionState.bindVertexInputs(context, vertexOffset, firstInstance);
const auto& boundDescriptorSets = executionState.boundDescriptorSets[VK_PIPELINE_BIND_POINT_GRAPHICS]; context.descriptorSets = pipelineState.descriptorSets;
for(int i = 0; i < vk::MAX_BOUND_DESCRIPTOR_SETS; i++) context.descriptorDynamicOffsets = pipelineState.descriptorDynamicOffsets;
{
context.descriptorSets[i] = reinterpret_cast<vk::DescriptorSet*>(boundDescriptorSets[i]);
}
context.pushConstants = executionState.pushConstants; context.pushConstants = executionState.pushConstants;
if (indexed) if (indexed)
...@@ -683,21 +682,38 @@ private: ...@@ -683,21 +682,38 @@ private:
struct BindDescriptorSet : public CommandBuffer::Command struct BindDescriptorSet : public CommandBuffer::Command
{ {
BindDescriptorSet(VkPipelineBindPoint pipelineBindPoint, uint32_t set, const VkDescriptorSet& descriptorSet) BindDescriptorSet(VkPipelineBindPoint pipelineBindPoint, uint32_t set, const VkDescriptorSet& descriptorSet,
: pipelineBindPoint(pipelineBindPoint), set(set), descriptorSet(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) void play(CommandBuffer::ExecutionState& executionState)
{ {
ASSERT((pipelineBindPoint < VK_PIPELINE_BIND_POINT_RANGE_SIZE) && (set < MAX_BOUND_DESCRIPTOR_SETS)); ASSERT_OR_RETURN((pipelineBindPoint < VK_PIPELINE_BIND_POINT_RANGE_SIZE) && (set < MAX_BOUND_DESCRIPTOR_SETS));
executionState.boundDescriptorSets[pipelineBindPoint][set] = descriptorSet; 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: private:
VkPipelineBindPoint pipelineBindPoint; VkPipelineBindPoint pipelineBindPoint;
uint32_t set; uint32_t set;
const VkDescriptorSet descriptorSet; const VkDescriptorSet descriptorSet;
uint32_t dynamicOffsetCount;
vk::DescriptorSet::DynamicOffsets dynamicOffsets;
}; };
struct SetPushConstants : public CommandBuffer::Command struct SetPushConstants : public CommandBuffer::Command
...@@ -974,20 +990,28 @@ void CommandBuffer::setStencilReference(VkStencilFaceFlags faceMask, uint32_t re ...@@ -974,20 +990,28 @@ void CommandBuffer::setStencilReference(VkStencilFaceFlags faceMask, uint32_t re
UNIMPLEMENTED("setStencilReference"); 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 firstSet, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets,
uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets) uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets)
{ {
ASSERT(state == RECORDING); ASSERT(state == RECORDING);
if(dynamicOffsetCount > 0)
{
UNIMPLEMENTED("bindDescriptorSets");
}
for(uint32_t i = 0; i < descriptorSetCount; i++) 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 @@ ...@@ -17,6 +17,7 @@
#include "VkConfig.h" #include "VkConfig.h"
#include "VkObject.hpp" #include "VkObject.hpp"
#include "VkDescriptorSet.hpp"
#include "Device/Context.hpp" #include "Device/Context.hpp"
#include <memory> #include <memory>
#include <vector> #include <vector>
...@@ -123,11 +124,17 @@ public: ...@@ -123,11 +124,17 @@ public:
// TODO(sugoi): Move ExecutionState out of CommandBuffer (possibly into Device) // TODO(sugoi): Move ExecutionState out of CommandBuffer (possibly into Device)
struct ExecutionState struct ExecutionState
{ {
struct PipelineState
{
Pipeline *pipeline = nullptr;
vk::DescriptorSet::Bindings descriptorSets = {};
vk::DescriptorSet::DynamicOffsets descriptorDynamicOffsets = {};
};
sw::Renderer* renderer = nullptr; sw::Renderer* renderer = nullptr;
RenderPass* renderPass = nullptr; RenderPass* renderPass = nullptr;
Framebuffer* renderPassFramebuffer = nullptr; Framebuffer* renderPassFramebuffer = nullptr;
Pipeline* pipelines[VK_PIPELINE_BIND_POINT_RANGE_SIZE] = {}; std::array<PipelineState, VK_PIPELINE_BIND_POINT_RANGE_SIZE> pipelineState;
VkDescriptorSet boundDescriptorSets[VK_PIPELINE_BIND_POINT_RANGE_SIZE][MAX_BOUND_DESCRIPTOR_SETS] = { { VK_NULL_HANDLE } };
sw::PushConstantStorage pushConstants; sw::PushConstantStorage pushConstants;
struct VertexInputBinding struct VertexInputBinding
......
...@@ -62,6 +62,15 @@ enum ...@@ -62,6 +62,15 @@ enum
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. 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 @@ ...@@ -13,6 +13,7 @@
// limitations under the License. // limitations under the License.
#include "VkDescriptorSetLayout.hpp" #include "VkDescriptorSetLayout.hpp"
#include "VkDescriptorSet.hpp"
#include "System/Types.hpp" #include "System/Types.hpp"
#include <algorithm> #include <algorithm>
...@@ -134,7 +135,7 @@ uint32_t DescriptorSetLayout::getBindingIndex(uint32_t binding) const ...@@ -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; return 0;
} }
...@@ -164,10 +165,63 @@ void DescriptorSetLayout::initialize(VkDescriptorSet vkDescriptorSet) ...@@ -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); 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 uint8_t* DescriptorSetLayout::getOffsetPointer(DescriptorSet *descriptorSet, uint32_t binding, uint32_t arrayElement, uint32_t count, size_t* typeSize) const
......
...@@ -20,18 +20,7 @@ ...@@ -20,18 +20,7 @@
namespace vk namespace vk
{ {
class DescriptorSetLayout; class DescriptorSet;
struct DescriptorSet
{
vk::DescriptorSetLayout* layout;
uint8_t data[];
};
inline DescriptorSet* Cast(VkDescriptorSet object)
{
return reinterpret_cast<DescriptorSet*>(object);
}
class DescriptorSetLayout : public Object<DescriptorSetLayout, VkDescriptorSetLayout> class DescriptorSetLayout : public Object<DescriptorSetLayout, VkDescriptorSetLayout>
{ {
...@@ -47,15 +36,43 @@ public: ...@@ -47,15 +36,43 @@ public:
static void CopyDescriptorSet(const VkCopyDescriptorSet& descriptorCopies); static void CopyDescriptorSet(const VkCopyDescriptorSet& descriptorCopies);
void initialize(VkDescriptorSet descriptorSet); void initialize(VkDescriptorSet descriptorSet);
// Returns the total size of the descriptor set in bytes.
size_t getDescriptorSetAllocationSize() const; 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; uint8_t* getOffsetPointer(DescriptorSet *descriptorSet, uint32_t binding, uint32_t arrayElement, uint32_t count, size_t* typeSize) const;
private: private:
size_t getDescriptorSetDataSize() const; size_t getDescriptorSetDataSize() const;
uint32_t getBindingIndex(uint32_t binding) const; uint32_t getBindingIndex(uint32_t binding) const;
static const uint8_t* GetInputData(const VkWriteDescriptorSet& descriptorWrites); static const uint8_t* GetInputData(const VkWriteDescriptorSet& descriptorWrites);
static bool isDynamic(VkDescriptorType type);
VkDescriptorSetLayoutCreateFlags flags; VkDescriptorSetLayoutCreateFlags flags;
uint32_t bindingCount; uint32_t bindingCount;
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
// limitations under the License. // limitations under the License.
#include "VkDescriptorUpdateTemplate.hpp" #include "VkDescriptorUpdateTemplate.hpp"
#include "VkDescriptorSet.hpp"
#include "VkDescriptorSetLayout.hpp" #include "VkDescriptorSetLayout.hpp"
#include <cstring> #include <cstring>
......
...@@ -162,9 +162,9 @@ const VkPhysicalDeviceLimits& PhysicalDevice::getLimits() const ...@@ -162,9 +162,9 @@ const VkPhysicalDeviceLimits& PhysicalDevice::getLimits() const
128, // maxPerStageResources 128, // maxPerStageResources
96, // maxDescriptorSetSamplers 96, // maxDescriptorSetSamplers
72, // maxDescriptorSetUniformBuffers 72, // maxDescriptorSetUniformBuffers
8, // maxDescriptorSetUniformBuffersDynamic MAX_DESCRIPTOR_SET_UNIFORM_BUFFERS_DYNAMIC, // maxDescriptorSetUniformBuffersDynamic
24, // maxDescriptorSetStorageBuffers 24, // maxDescriptorSetStorageBuffers
4, // maxDescriptorSetStorageBuffersDynamic MAX_DESCRIPTOR_SET_STORAGE_BUFFERS_DYNAMIC, // maxDescriptorSetStorageBuffersDynamic
96, // maxDescriptorSetSampledImages 96, // maxDescriptorSetSampledImages
24, // maxDescriptorSetStorageImages 24, // maxDescriptorSetStorageImages
4, // maxDescriptorSetInputAttachments 4, // maxDescriptorSetInputAttachments
......
...@@ -517,11 +517,13 @@ void ComputePipeline::compileShaders(const VkAllocationCallbacks* pAllocator, co ...@@ -517,11 +517,13 @@ void ComputePipeline::compileShaders(const VkAllocationCallbacks* pAllocator, co
} }
void ComputePipeline::run(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ, 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); ASSERT_OR_RETURN(routine != nullptr);
sw::ComputeProgram::run( sw::ComputeProgram::run(
routine, reinterpret_cast<void**>(descriptorSets), pushConstants, routine, descriptorSets, descriptorDynamicOffsets, pushConstants,
groupCountX, groupCountY, groupCountZ); groupCountX, groupCountY, groupCountZ);
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#define VK_PIPELINE_HPP_ #define VK_PIPELINE_HPP_
#include "VkObject.hpp" #include "VkObject.hpp"
#include "Vulkan/VkDescriptorSet.hpp"
#include "Device/Renderer.hpp" #include "Device/Renderer.hpp"
namespace sw { class SpirvShader; } namespace sw { class SpirvShader; }
...@@ -104,7 +105,9 @@ public: ...@@ -104,7 +105,9 @@ public:
void compileShaders(const VkAllocationCallbacks* pAllocator, const VkComputePipelineCreateInfo* pCreateInfo); void compileShaders(const VkAllocationCallbacks* pAllocator, const VkComputePipelineCreateInfo* pCreateInfo);
void run(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ, 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: protected:
sw::SpirvShader *shader = nullptr; sw::SpirvShader *shader = nullptr;
......
...@@ -31,6 +31,16 @@ PipelineLayout::PipelineLayout(const VkPipelineLayoutCreateInfo* pCreateInfo, vo ...@@ -31,6 +31,16 @@ PipelineLayout::PipelineLayout(const VkPipelineLayoutCreateInfo* pCreateInfo, vo
size_t pushConstantRangesSize = pCreateInfo->pushConstantRangeCount * sizeof(VkPushConstantRange); size_t pushConstantRangesSize = pCreateInfo->pushConstantRangeCount * sizeof(VkPushConstantRange);
pushConstantRanges = reinterpret_cast<VkPushConstantRange*>(hostMem); pushConstantRanges = reinterpret_cast<VkPushConstantRange*>(hostMem);
memcpy(pushConstantRanges, pCreateInfo->pPushConstantRanges, pushConstantRangesSize); 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) void PipelineLayout::destroy(const VkAllocationCallbacks* pAllocator)
...@@ -41,7 +51,8 @@ void PipelineLayout::destroy(const VkAllocationCallbacks* pAllocator) ...@@ -41,7 +51,8 @@ void PipelineLayout::destroy(const VkAllocationCallbacks* pAllocator)
size_t PipelineLayout::ComputeRequiredAllocationSize(const VkPipelineLayoutCreateInfo* pCreateInfo) size_t PipelineLayout::ComputeRequiredAllocationSize(const VkPipelineLayoutCreateInfo* pCreateInfo)
{ {
return (pCreateInfo->setLayoutCount * sizeof(DescriptorSetLayout*)) + return (pCreateInfo->setLayoutCount * sizeof(DescriptorSetLayout*)) +
(pCreateInfo->pushConstantRangeCount * sizeof(VkPushConstantRange)); (pCreateInfo->pushConstantRangeCount * sizeof(VkPushConstantRange)) +
(pCreateInfo->setLayoutCount * sizeof(uint32_t)); // dynamicOffsetBases
} }
size_t PipelineLayout::getNumDescriptorSets() const size_t PipelineLayout::getNumDescriptorSets() const
...@@ -49,10 +60,16 @@ size_t PipelineLayout::getNumDescriptorSets() const ...@@ -49,10 +60,16 @@ size_t PipelineLayout::getNumDescriptorSets() const
return setLayoutCount; 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); ASSERT(descriptorSet < setLayoutCount);
return setLayouts[descriptorSet]->getBindingOffset(binding); return dynamicOffsetBases[descriptorSet];
} }
} // namespace vk } // namespace vk
...@@ -30,13 +30,18 @@ public: ...@@ -30,13 +30,18 @@ public:
static size_t ComputeRequiredAllocationSize(const VkPipelineLayoutCreateInfo* pCreateInfo); static size_t ComputeRequiredAllocationSize(const VkPipelineLayoutCreateInfo* pCreateInfo);
size_t getNumDescriptorSets() const; 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: private:
uint32_t setLayoutCount = 0; uint32_t setLayoutCount = 0;
DescriptorSetLayout** setLayouts = nullptr; DescriptorSetLayout** setLayouts = nullptr;
uint32_t pushConstantRangeCount = 0; uint32_t pushConstantRangeCount = 0;
VkPushConstantRange* pushConstantRanges = nullptr; VkPushConstantRange* pushConstantRanges = nullptr;
uint32_t* dynamicOffsetBases = nullptr; // Base offset per set layout.
}; };
static inline PipelineLayout* Cast(VkPipelineLayout object) 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