Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add push constants #7817

Merged
merged 8 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 7 additions & 1 deletion filament/backend/include/backend/DriverEnums.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

#include <array> // FIXME: STL headers are not allowed in public headers
#include <type_traits> // FIXME: STL headers are not allowed in public headers
#include <variant> // FIXME: STL headers are not allowed in public headers

#include <stddef.h>
#include <stdint.h>
Expand Down Expand Up @@ -91,12 +92,15 @@ static constexpr uint64_t SWAP_CHAIN_HAS_STENCIL_BUFFER = SWAP_CHAIN_CON
*/
static constexpr uint64_t SWAP_CHAIN_CONFIG_PROTECTED_CONTENT = 0x40;


static constexpr size_t MAX_VERTEX_ATTRIBUTE_COUNT = 16; // This is guaranteed by OpenGL ES.
static constexpr size_t MAX_SAMPLER_COUNT = 62; // Maximum needed at feature level 3.
static constexpr size_t MAX_VERTEX_BUFFER_COUNT = 16; // Max number of bound buffer objects.
static constexpr size_t MAX_SSBO_COUNT = 4; // This is guaranteed by OpenGL ES.

static constexpr size_t MAX_PUSH_CONSTANT_COUNT = 32; // Vulkan 1.1 spec allows for 128-byte
// of push constant (we assume 4-byte
// types).

// Per feature level caps
// Use (int)FeatureLevel to index this array
static constexpr struct {
Expand Down Expand Up @@ -1219,6 +1223,8 @@ struct StencilState {
uint8_t padding = 0;
};

using PushConstantVariant = std::variant<int32_t, float, bool>;

static_assert(sizeof(StencilState::StencilOperations) == 5u,
"StencilOperations size not what was intended");

Expand Down
13 changes: 13 additions & 0 deletions filament/backend/include/backend/Program.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ class Program {
Program& specializationConstants(
utils::FixedCapacityVector<SpecializationConstant> specConstants) noexcept;

Program& pushConstants(ShaderStage stage,
utils::FixedCapacityVector<char const*> constants) noexcept;
poweifeng marked this conversation as resolved.
Show resolved Hide resolved

Program& cacheId(uint64_t cacheId) noexcept;

Program& multiview(bool multiview) noexcept;
Expand Down Expand Up @@ -148,6 +151,15 @@ class Program {
return mSpecializationConstants;
}

utils::FixedCapacityVector<char const*> const& getPushConstants(
ShaderStage stage) const noexcept {
return mPushConstants[static_cast<uint8_t>(stage)];
}

utils::FixedCapacityVector<char const*>& getPushConstants(ShaderStage stage) noexcept {
return mPushConstants[static_cast<uint8_t>(stage)];
}

uint64_t getCacheId() const noexcept { return mCacheId; }

bool isMultiview() const noexcept { return mMultiview; }
Expand All @@ -165,6 +177,7 @@ class Program {
uint64_t mCacheId{};
utils::Invocable<utils::io::ostream&(utils::io::ostream& out)> mLogger;
utils::FixedCapacityVector<SpecializationConstant> mSpecializationConstants;
std::array<utils::FixedCapacityVector<char const*>, SHADER_TYPE_COUNT> mPushConstants;
utils::FixedCapacityVector<std::pair<utils::CString, uint8_t>> mAttributes;
std::array<UniformInfo, Program::UNIFORM_BINDING_COUNT> mBindingUniformInfo;
CompilerPriorityQueue mPriorityQueue = CompilerPriorityQueue::HIGH;
Expand Down
5 changes: 5 additions & 0 deletions filament/backend/include/private/backend/DriverAPI.inc
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,11 @@ DECL_DRIVER_API_N(bindSamplers,
uint32_t, index,
backend::SamplerGroupHandle, sbh)

DECL_DRIVER_API_N(setPushConstant,
backend::ShaderStage, stage,
uint8_t, index,
backend::PushConstantVariant, value)
poweifeng marked this conversation as resolved.
Show resolved Hide resolved

DECL_DRIVER_API_N(insertEventMarker,
const char*, string,
uint32_t, len = 0)
Expand Down
6 changes: 6 additions & 0 deletions filament/backend/src/Program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ Program& Program::specializationConstants(
return *this;
}

Program& Program::pushConstants(ShaderStage stage,
utils::FixedCapacityVector<char const*> constants) noexcept {
mPushConstants[static_cast<uint8_t>(stage)] = constants;
poweifeng marked this conversation as resolved.
Show resolved Hide resolved
return *this;
}

Program& Program::cacheId(uint64_t cacheId) noexcept {
mCacheId = cacheId;
return *this;
Expand Down
3 changes: 3 additions & 0 deletions filament/backend/src/metal/MetalDriver.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1241,6 +1241,9 @@
mContext->samplerBindings[index] = sb;
}

void MetalDriver::setPushConstant(backend::ShaderStage stage, uint8_t index,
backend::PushConstantVariant value) {}

void MetalDriver::insertEventMarker(const char* string, uint32_t len) {

}
Expand Down
4 changes: 4 additions & 0 deletions filament/backend/src/noop/NoopDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,10 @@ void NoopDriver::unbindBuffer(BufferObjectBinding bindingType, uint32_t index) {
void NoopDriver::bindSamplers(uint32_t index, Handle<HwSamplerGroup> sbh) {
}

void NoopDriver::setPushConstant(backend::ShaderStage stage, uint8_t index,
backend::PushConstantVariant value) {
}

void NoopDriver::insertEventMarker(char const* string, uint32_t len) {
}

Expand Down
4 changes: 4 additions & 0 deletions filament/backend/src/opengl/OpenGLDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,10 @@ void OpenGLDriver::bindSampler(GLuint unit, GLuint sampler) noexcept {
mContext.bindSampler(unit, sampler);
}

void OpenGLDriver::setPushConstant(backend::ShaderStage stage, uint8_t index,
backend::PushConstantVariant value) {
poweifeng marked this conversation as resolved.
Show resolved Hide resolved
}

void OpenGLDriver::bindTexture(GLuint unit, GLTexture const* t) noexcept {
assert_invariant(t != nullptr);
mContext.bindTexture(unit, t->gl.target, t->gl.id);
Expand Down
20 changes: 17 additions & 3 deletions filament/backend/src/vulkan/VulkanDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,8 @@ VulkanDriver::VulkanDriver(VulkanPlatform* platform, VulkanContext const& contex
mDescriptorSetManager.setPlaceHolders(mSamplerCache.getSampler({}), mEmptyTexture,
mEmptyBufferObject);

mGetPipelineFunction = [this](VulkanDescriptorSetLayoutList const& layouts) {
return mPipelineLayoutCache.getLayout(layouts);
mGetPipelineFunction = [this](VulkanDescriptorSetLayoutList const& layouts, VulkanProgram* program) {
return mPipelineLayoutCache.getLayout(layouts, program);
};
}

Expand Down Expand Up @@ -1572,6 +1572,14 @@ void VulkanDriver::bindSamplers(uint32_t index, Handle<HwSamplerGroup> sbh) {
mSamplerBindings[index] = hwsb;
}

void VulkanDriver::setPushConstant(backend::ShaderStage stage, uint8_t index,
backend::PushConstantVariant value) {
assert_invariant(mBoundPipeline.program && "Expect a program when writing to push constants");
VulkanCommands* commands = &mCommands;
mBoundPipeline.program->writePushConstant(commands, mBoundPipeline.pipelineLayout, stage, index,
value);
}

void VulkanDriver::insertEventMarker(char const* string, uint32_t len) {
#if FVK_ENABLED(FVK_DEBUG_GROUP_MARKERS)
mCommands.insertEventMarker(string, len);
Expand Down Expand Up @@ -1857,7 +1865,13 @@ void VulkanDriver::bindPipeline(PipelineState pipelineState) {
mDescriptorSetManager.updateSampler({}, binding, texture, vksampler);
}

mPipelineCache.bindLayout(mDescriptorSetManager.bind(commands, program, mGetPipelineFunction));
auto const pipelineLayout = mDescriptorSetManager.bind(commands, program, mGetPipelineFunction);
mBoundPipeline = {
.program = program,
.pipelineLayout = pipelineLayout,
};

mPipelineCache.bindLayout(pipelineLayout);
mPipelineCache.bindPipeline(commands);
FVK_SYSTRACE_END();
}
Expand Down
7 changes: 7 additions & 0 deletions filament/backend/src/vulkan/VulkanDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,13 @@ class VulkanDriver final : public DriverBase {

VulkanDescriptorSetManager::GetPipelineLayoutFunction mGetPipelineFunction;

// This is necessary for us to write to push constants after binding a pipeline.
struct BoundPipeline {
VulkanProgram* program;
VkPipelineLayout pipelineLayout;
};
BoundPipeline mBoundPipeline = {};

RenderPassFboBundle mRenderPassFboInfo;

bool const mIsSRGBSwapChainSupported;
Expand Down
52 changes: 47 additions & 5 deletions filament/backend/src/vulkan/VulkanHandles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,27 +112,69 @@ inline VkDescriptorSetLayout createDescriptorSetLayout(VkDevice device,
return layout;
}

inline VkShaderStageFlags getVkStage(backend::ShaderStage stage) {
switch(stage) {
case backend::ShaderStage::VERTEX:
return VK_SHADER_STAGE_VERTEX_BIT;
case backend::ShaderStage::FRAGMENT:
return VK_SHADER_STAGE_FRAGMENT_BIT;
case backend::ShaderStage::COMPUTE:
PANIC_POSTCONDITION("Unsupported stage");
}
}

} // anonymous namespace


VulkanDescriptorSetLayout::VulkanDescriptorSetLayout(VkDevice device, VkDescriptorSetLayoutCreateInfo const& info,
Bitmask const& bitmask)
VulkanDescriptorSetLayout::VulkanDescriptorSetLayout(VkDevice device,
VkDescriptorSetLayoutCreateInfo const& info, Bitmask const& bitmask)
: VulkanResource(VulkanResourceType::DESCRIPTOR_SET_LAYOUT),
mDevice(device),
vklayout(createDescriptorSetLayout(device, info)),
bitmask(bitmask),
bindings(getBindings(bitmask)),
count(Count::fromLayoutBitmask(bitmask)) {
}
count(Count::fromLayoutBitmask(bitmask)) {}

VulkanDescriptorSetLayout::~VulkanDescriptorSetLayout() {
vkDestroyDescriptorSetLayout(mDevice, vklayout, VKALLOC);
}

PushConstantDescription::PushConstantDescription(backend::Program const& program) noexcept {
mRangeCount = 0;
for (auto stage : { ShaderStage::VERTEX, ShaderStage::FRAGMENT, ShaderStage::COMPUTE }) {
auto const& names = program.getPushConstants(stage);
if (names.empty()) {
continue;
}
mRanges[mRangeCount++] = {
.stageFlags = getVkStage(stage),
.offset = 0,
.size = (uint32_t) names.size() * 4,
poweifeng marked this conversation as resolved.
Show resolved Hide resolved
};
}
}

void PushConstantDescription::write(VulkanCommands* commands, VkPipelineLayout layout,
backend::ShaderStage stage, uint8_t index, backend::PushConstantVariant const& value) {
VulkanCommandBuffer* cmdbuf = &(commands->get());
uint32_t binaryValue = 0;
if (std::holds_alternative<bool>(value)) {
bool const bval = std::get<bool>(value);
binaryValue = static_cast<uint32_t const>(bval ? VK_TRUE : VK_FALSE);
} else if (std::holds_alternative<float>(value)) {
float const fval = std::get<float>(value);
binaryValue = *reinterpret_cast<uint32_t const*>(&fval);
} else {
int const ival = std::get<int>(value);
binaryValue = *reinterpret_cast<uint32_t const*>(&ival);
}
vkCmdPushConstants(cmdbuf->buffer(), layout, getVkStage(stage), index * 4, 4, &binaryValue);
poweifeng marked this conversation as resolved.
Show resolved Hide resolved
}

VulkanProgram::VulkanProgram(VkDevice device, Program const& builder) noexcept
: HwProgram(builder.getName()),
VulkanResource(VulkanResourceType::PROGRAM),
mInfo(new PipelineInfo()),
mInfo(new PipelineInfo(builder)),
poweifeng marked this conversation as resolved.
Show resolved Hide resolved
mDevice(device) {

constexpr uint8_t UBO_MODULE_OFFSET = (sizeof(UniformBufferBitmask) * 8) / MAX_SHADER_MODULES;
Expand Down
44 changes: 39 additions & 5 deletions filament/backend/src/vulkan/VulkanHandles.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@
#include "VulkanTexture.h"
#include "VulkanUtility.h"

#include "private/backend/SamplerGroup.h"
#include "utils/FixedCapacityVector.h"
#include "vulkan/vulkan_core.h"
#include <private/backend/SamplerGroup.h>
#include <backend/Program.h>

#include <utils/FixedCapacityVector.h>
#include <utils/Mutex.h>
#include <utils/StructureOfArrays.h>

Expand Down Expand Up @@ -180,6 +180,24 @@ struct VulkanDescriptorSet : public VulkanResource {
using VulkanDescriptorSetList = std::array<Handle<VulkanDescriptorSet>,
VulkanDescriptorSetLayout::UNIQUE_DESCRIPTOR_SET_COUNT>;

using PushConstantNameArray = utils::FixedCapacityVector<char const*>;
using PushConstantNameByStage = std::array<PushConstantNameArray, Program::SHADER_TYPE_COUNT>;

struct PushConstantDescription {
explicit PushConstantDescription(backend::Program const& program) noexcept;

VkPushConstantRange const* getVkRanges() const noexcept { return mRanges; }

uint32_t getVkRangeCount() const noexcept { return mRangeCount; }

void write(VulkanCommands* commands, VkPipelineLayout layout, backend::ShaderStage stage,
uint8_t index, backend::PushConstantVariant const& value);

private:
VkPushConstantRange mRanges[Program::SHADER_TYPE_COUNT];
uint32_t mRangeCount;
};

struct VulkanProgram : public HwProgram, VulkanResource {

using BindingList = CappedArray<uint16_t, MAX_SAMPLER_COUNT>;
Expand Down Expand Up @@ -212,6 +230,19 @@ struct VulkanProgram : public HwProgram, VulkanResource {
VulkanDescriptorSetLayout::UNIQUE_DESCRIPTOR_SET_COUNT>;
inline LayoutDescriptionList const& getLayoutDescriptionList() const { return mInfo->layouts; }

inline uint32_t getPushConstantRangeCount() const {
return mInfo->pushConstantDescription.getVkRangeCount();
}

inline VkPushConstantRange const* getPushConstantRanges() const {
return mInfo->pushConstantDescription.getVkRanges();
}

inline void writePushConstant(VulkanCommands* commands, VkPipelineLayout layout,
backend::ShaderStage stage, uint8_t index, backend::PushConstantVariant const& value) {
mInfo->pushConstantDescription.write(commands, layout, stage, index, value);
}

#if FVK_ENABLED_DEBUG_SAMPLER_NAME
inline utils::FixedCapacityVector<std::string> const& getBindingToName() const {
return mInfo->bindingToName;
Expand All @@ -224,8 +255,9 @@ struct VulkanProgram : public HwProgram, VulkanResource {

private:
struct PipelineInfo {
PipelineInfo()
: bindingToSamplerIndex(MAX_SAMPLER_COUNT, 0xffff)
explicit PipelineInfo(backend::Program const& program) noexcept
: bindingToSamplerIndex(MAX_SAMPLER_COUNT, 0xffff),
pushConstantDescription(program)
#if FVK_ENABLED_DEBUG_SAMPLER_NAME
, bindingToName(MAX_SAMPLER_COUNT, "")
#endif
Expand All @@ -241,6 +273,8 @@ struct VulkanProgram : public HwProgram, VulkanResource {
// descset::DescriptorSetLayout layout;
LayoutDescriptionList layouts;

PushConstantDescription pushConstantDescription;

#if FVK_ENABLED_DEBUG_SAMPLER_NAME
// We store the sampler name mapped from binding index (only for debug purposes).
utils::FixedCapacityVector<std::string> bindingToName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -879,7 +879,7 @@ class VulkanDescriptorSetManager::Impl {
vkUpdateDescriptorSets(mDevice, nwrites, descriptorWrites, 0, nullptr);
}

VkPipelineLayout const pipelineLayout = getPipelineLayoutFn(outLayouts);
VkPipelineLayout const pipelineLayout = getPipelineLayoutFn(outLayouts, program);
VkCommandBuffer const cmdbuffer = commands->buffer();

BoundState state{};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ class VulkanDescriptorSetManager {
public:
static constexpr uint8_t UNIQUE_DESCRIPTOR_SET_COUNT =
VulkanDescriptorSetLayout::UNIQUE_DESCRIPTOR_SET_COUNT;
using GetPipelineLayoutFunction =
std::function<VkPipelineLayout(VulkanDescriptorSetLayoutList const&)>;
using GetPipelineLayoutFunction = std::function<VkPipelineLayout(
VulkanDescriptorSetLayoutList const&, VulkanProgram* program)>;

VulkanDescriptorSetManager(VkDevice device, VulkanResourceAllocator* resourceAllocator);

Expand Down Expand Up @@ -108,3 +108,4 @@ class VulkanDescriptorSetManager {
}// namespace filament::backend

#endif// TNT_FILAMENT_BACKEND_CACHING_VULKANDESCRIPTORSETMANAGER_H