Separate push constants can now be sent to vertex and fragment stages.
This commit is contained in:
@@ -112,17 +112,17 @@ const char *KRPipeline::KRENGINE_UNIFORM_NAMES[] = {
|
|||||||
|
|
||||||
KRPipeline::KRPipeline(KRContext& context, KRSurface& surface, const PipelineInfo& info, const char* szKey, const std::vector<KRShader*>& shaders, uint32_t vertexAttributes, ModelFormat modelFormat)
|
KRPipeline::KRPipeline(KRContext& context, KRSurface& surface, const PipelineInfo& info, const char* szKey, const std::vector<KRShader*>& shaders, uint32_t vertexAttributes, ModelFormat modelFormat)
|
||||||
: KRContextObject(context)
|
: KRContextObject(context)
|
||||||
, m_pushConstantBuffer(nullptr)
|
|
||||||
, m_pushConstantBufferSize(0)
|
|
||||||
{
|
{
|
||||||
for (int i = 0; i < static_cast<int>(ShaderStages::shaderStageCount); i++) {
|
for (PushConstantStageInfo& pushConstants : m_pushConstants) {
|
||||||
memset(m_pushConstants[i].size, 0, kUniformCount);
|
pushConstants.buffer = nullptr;
|
||||||
memset(m_pushConstants[i].offset, 0, kUniformCount * sizeof(int));
|
pushConstants.bufferSize = 0;
|
||||||
|
memset(pushConstants.size, 0, kUniformCount);
|
||||||
|
memset(pushConstants.offset, 0, kUniformCount * sizeof(int));
|
||||||
|
pushConstants.layout = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pipelineLayout = nullptr;
|
m_pipelineLayout = nullptr;
|
||||||
m_graphicsPipeline = nullptr;
|
m_graphicsPipeline = nullptr;
|
||||||
m_pushConstantsLayout = nullptr;
|
|
||||||
|
|
||||||
std::unique_ptr<KRDevice>& device = surface.getDevice();
|
std::unique_ptr<KRDevice>& device = surface.getDevice();
|
||||||
// TODO - Handle device removal
|
// TODO - Handle device removal
|
||||||
@@ -189,32 +189,12 @@ KRPipeline::KRPipeline(KRContext& context, KRSurface& surface, const PipelineInf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i=0; i<reflection->push_constant_block_count; i++) {
|
initPushConstantStage(ShaderStages::vertex, reflection);
|
||||||
const SpvReflectBlockVariable& block = reflection->push_constant_blocks[i];
|
|
||||||
if (stricmp(block.name, "constants") == 0) {
|
|
||||||
if (block.size > 0) {
|
|
||||||
m_pushConstantBuffer = (__uint8_t*)malloc(block.size);
|
|
||||||
memset(m_pushConstantBuffer, 0, block.size);
|
|
||||||
m_pushConstantBufferSize = block.size;
|
|
||||||
|
|
||||||
// Get push constant offsets
|
|
||||||
for (int iUniform = 0; iUniform < kUniformCount; iUniform++) {
|
|
||||||
for (int iMember = 0; iMember < block.member_count; iMember++) {
|
|
||||||
const SpvReflectBlockVariable& member = block.members[iMember];
|
|
||||||
if (stricmp(KRENGINE_UNIFORM_NAMES[iUniform], member.name) == 0)
|
|
||||||
{
|
|
||||||
m_pushConstants[0].offset[iUniform] = member.offset;
|
|
||||||
m_pushConstants[0].size[iUniform] = member.size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (shader->getSubExtension().compare("frag") == 0) {
|
else if (shader->getSubExtension().compare("frag") == 0) {
|
||||||
stageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
stageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
|
initPushConstantStage(ShaderStages::fragment, reflection);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// failed! TODO - Error handling
|
// failed! TODO - Error handling
|
||||||
@@ -371,25 +351,44 @@ KRPipeline::KRPipeline(KRContext& context, KRSurface& surface, const PipelineInf
|
|||||||
// failed! TODO - Error handling
|
// failed! TODO - Error handling
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_pushConstantBuffer) {
|
int iStage = 0;
|
||||||
VkPipelineLayoutCreateInfo pushConstantsLayoutInfo{};
|
for (PushConstantStageInfo& pushConstants : m_pushConstants) {
|
||||||
pushConstantsLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
if (pushConstants.buffer) {
|
||||||
pushConstantsLayoutInfo.setLayoutCount = 0;
|
VkPipelineLayoutCreateInfo pushConstantsLayoutInfo{};
|
||||||
pushConstantsLayoutInfo.pSetLayouts = nullptr;
|
pushConstantsLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||||
pushConstantsLayoutInfo.pushConstantRangeCount = 0;
|
pushConstantsLayoutInfo.setLayoutCount = 0;
|
||||||
pushConstantsLayoutInfo.pPushConstantRanges = nullptr;
|
pushConstantsLayoutInfo.pSetLayouts = nullptr;
|
||||||
|
pushConstantsLayoutInfo.pushConstantRangeCount = 0;
|
||||||
|
pushConstantsLayoutInfo.pPushConstantRanges = nullptr;
|
||||||
|
|
||||||
// TODO - We need to support push constants for other shader stages
|
// TODO - We need to support push constants for other shader stages
|
||||||
VkPushConstantRange push_constant{};
|
VkPushConstantRange push_constant{};
|
||||||
push_constant.offset = 0;
|
push_constant.offset = 0;
|
||||||
push_constant.size = m_pushConstantBufferSize;
|
push_constant.size = pushConstants.bufferSize;
|
||||||
push_constant.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
|
||||||
pushConstantsLayoutInfo.pPushConstantRanges = &push_constant;
|
|
||||||
pushConstantsLayoutInfo.pushConstantRangeCount = 1;
|
|
||||||
|
|
||||||
if (vkCreatePipelineLayout(device->m_logicalDevice, &pushConstantsLayoutInfo, nullptr, &m_pushConstantsLayout) != VK_SUCCESS) {
|
switch (static_cast<ShaderStages>(iStage)) {
|
||||||
// failed! TODO - Error handling
|
case ShaderStages::vertex:
|
||||||
|
push_constant.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
|
break;
|
||||||
|
case ShaderStages::fragment:
|
||||||
|
push_constant.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
|
break;
|
||||||
|
case ShaderStages::geometry:
|
||||||
|
push_constant.stageFlags = VK_SHADER_STAGE_GEOMETRY_BIT;
|
||||||
|
break;
|
||||||
|
case ShaderStages::compute:
|
||||||
|
push_constant.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pushConstantsLayoutInfo.pPushConstantRanges = &push_constant;
|
||||||
|
pushConstantsLayoutInfo.pushConstantRangeCount = 1;
|
||||||
|
|
||||||
|
if (vkCreatePipelineLayout(device->m_logicalDevice, &pushConstantsLayoutInfo, nullptr, &pushConstants.layout) != VK_SUCCESS) {
|
||||||
|
// failed! TODO - Error handling
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
iStage++;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkPipelineDepthStencilStateCreateInfo depthStencil{};
|
VkPipelineDepthStencilStateCreateInfo depthStencil{};
|
||||||
@@ -462,16 +461,46 @@ KRPipeline::~KRPipeline() {
|
|||||||
if (m_pipelineLayout) {
|
if (m_pipelineLayout) {
|
||||||
// TODO: vkDestroyPipelineLayout(device, m_pipelineLayout, nullptr);
|
// TODO: vkDestroyPipelineLayout(device, m_pipelineLayout, nullptr);
|
||||||
}
|
}
|
||||||
if (m_pushConstantsLayout) {
|
for (PushConstantStageInfo& pushConstants : m_pushConstants) {
|
||||||
// TODO: vkDestroyPipelineLayout(device, m_pushConstantsLayout, nullptr);
|
if (pushConstants.layout) {
|
||||||
|
// TODO: vkDestroyPipelineLayout(device, pushConstants.layout, nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(getContext().getPipelineManager()->m_active_pipeline == this) {
|
if(getContext().getPipelineManager()->m_active_pipeline == this) {
|
||||||
getContext().getPipelineManager()->m_active_pipeline = NULL;
|
getContext().getPipelineManager()->m_active_pipeline = NULL;
|
||||||
}
|
}
|
||||||
if (m_pushConstantBuffer) {
|
if (m_pushConstants[0].buffer) {
|
||||||
delete m_pushConstantBuffer;
|
delete m_pushConstants[0].buffer;
|
||||||
m_pushConstantBuffer = nullptr;
|
m_pushConstants[0].buffer = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KRPipeline::initPushConstantStage(ShaderStages stage, const SpvReflectShaderModule* reflection)
|
||||||
|
{
|
||||||
|
PushConstantStageInfo& pushConstants = m_pushConstants[static_cast<int>(stage)];
|
||||||
|
for (int i = 0; i < reflection->push_constant_block_count; i++) {
|
||||||
|
const SpvReflectBlockVariable& block = reflection->push_constant_blocks[i];
|
||||||
|
if (stricmp(block.name, "constants") == 0) {
|
||||||
|
if (block.size > 0) {
|
||||||
|
pushConstants.buffer = (__uint8_t*)malloc(block.size);
|
||||||
|
memset(pushConstants.buffer, 0, block.size);
|
||||||
|
pushConstants.bufferSize = block.size;
|
||||||
|
|
||||||
|
// Get push constant offsets
|
||||||
|
for (int iUniform = 0; iUniform < kUniformCount; iUniform++) {
|
||||||
|
for (int iMember = 0; iMember < block.member_count; iMember++) {
|
||||||
|
const SpvReflectBlockVariable& member = block.members[iMember];
|
||||||
|
if (stricmp(KRENGINE_UNIFORM_NAMES[iUniform], member.name) == 0)
|
||||||
|
{
|
||||||
|
pushConstants.offset[iUniform] = member.offset;
|
||||||
|
pushConstants.size[iUniform] = member.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,7 +518,7 @@ void KRPipeline::setUniform(Uniform location, float value)
|
|||||||
{
|
{
|
||||||
for (PushConstantStageInfo& stageConstants : m_pushConstants) {
|
for (PushConstantStageInfo& stageConstants : m_pushConstants) {
|
||||||
if (stageConstants.size[static_cast<size_t>(location)] == sizeof(value)) {
|
if (stageConstants.size[static_cast<size_t>(location)] == sizeof(value)) {
|
||||||
float* constant = (float*)(m_pushConstantBuffer + stageConstants.offset[static_cast<size_t>(location)]);
|
float* constant = (float*)(m_pushConstants[0].buffer + stageConstants.offset[static_cast<size_t>(location)]);
|
||||||
*constant = value;
|
*constant = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -500,7 +529,7 @@ void KRPipeline::setUniform(Uniform location, int value)
|
|||||||
{
|
{
|
||||||
for (PushConstantStageInfo& stageConstants : m_pushConstants) {
|
for (PushConstantStageInfo& stageConstants : m_pushConstants) {
|
||||||
if (stageConstants.size[static_cast<size_t>(location)] == sizeof(value)) {
|
if (stageConstants.size[static_cast<size_t>(location)] == sizeof(value)) {
|
||||||
int* constant = (int*)(m_pushConstantBuffer + stageConstants.offset[static_cast<size_t>(location)]);
|
int* constant = (int*)(m_pushConstants[0].buffer + stageConstants.offset[static_cast<size_t>(location)]);
|
||||||
*constant = value;
|
*constant = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -510,7 +539,7 @@ void KRPipeline::setUniform(Uniform location, const Vector2 &value)
|
|||||||
{
|
{
|
||||||
for (PushConstantStageInfo& stageConstants : m_pushConstants) {
|
for (PushConstantStageInfo& stageConstants : m_pushConstants) {
|
||||||
if (stageConstants.size[static_cast<size_t>(location)] == sizeof(value)) {
|
if (stageConstants.size[static_cast<size_t>(location)] == sizeof(value)) {
|
||||||
Vector2* constant = (Vector2*)(m_pushConstantBuffer + stageConstants.offset[static_cast<size_t>(location)]);
|
Vector2* constant = (Vector2*)(m_pushConstants[0].buffer + stageConstants.offset[static_cast<size_t>(location)]);
|
||||||
*constant = value;
|
*constant = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -519,7 +548,7 @@ void KRPipeline::setUniform(Uniform location, const Vector3 &value)
|
|||||||
{
|
{
|
||||||
for (PushConstantStageInfo& stageConstants : m_pushConstants) {
|
for (PushConstantStageInfo& stageConstants : m_pushConstants) {
|
||||||
if (stageConstants.size[static_cast<size_t>(location)] == sizeof(value)) {
|
if (stageConstants.size[static_cast<size_t>(location)] == sizeof(value)) {
|
||||||
Vector3* constant = (Vector3*)(m_pushConstantBuffer + stageConstants.offset[static_cast<size_t>(location)]);
|
Vector3* constant = (Vector3*)(m_pushConstants[0].buffer + stageConstants.offset[static_cast<size_t>(location)]);
|
||||||
*constant = value;
|
*constant = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -529,7 +558,7 @@ void KRPipeline::setUniform(Uniform location, const Vector4 &value)
|
|||||||
{
|
{
|
||||||
for (PushConstantStageInfo& stageConstants : m_pushConstants) {
|
for (PushConstantStageInfo& stageConstants : m_pushConstants) {
|
||||||
if (stageConstants.size[static_cast<size_t>(location)] == sizeof(value)) {
|
if (stageConstants.size[static_cast<size_t>(location)] == sizeof(value)) {
|
||||||
Vector4* constant = (Vector4*)(m_pushConstantBuffer + stageConstants.offset[static_cast<size_t>(location)]);
|
Vector4* constant = (Vector4*)(m_pushConstants[0].buffer + stageConstants.offset[static_cast<size_t>(location)]);
|
||||||
*constant = value;
|
*constant = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -539,7 +568,7 @@ void KRPipeline::setUniform(Uniform location, const Matrix4 &value)
|
|||||||
{
|
{
|
||||||
for (PushConstantStageInfo& stageConstants : m_pushConstants) {
|
for (PushConstantStageInfo& stageConstants : m_pushConstants) {
|
||||||
if (stageConstants.size[static_cast<size_t>(location)] == sizeof(value)) {
|
if (stageConstants.size[static_cast<size_t>(location)] == sizeof(value)) {
|
||||||
Matrix4* constant = (Matrix4*)(m_pushConstantBuffer + m_pushConstants[0].offset[static_cast<size_t>(location)]);
|
Matrix4* constant = (Matrix4*)(m_pushConstants[0].buffer + m_pushConstants[0].offset[static_cast<size_t>(location)]);
|
||||||
*constant = value;
|
*constant = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -745,8 +774,10 @@ bool KRPipeline::bind(VkCommandBuffer& commandBuffer, KRCamera &camera, const KR
|
|||||||
setUniform(Uniform::render_frame, 1);
|
setUniform(Uniform::render_frame, 1);
|
||||||
setUniform(Uniform::volumetric_environment_frame, 2);
|
setUniform(Uniform::volumetric_environment_frame, 2);
|
||||||
|
|
||||||
if(m_pushConstantBuffer) {
|
for (PushConstantStageInfo& pushConstants : m_pushConstants) {
|
||||||
vkCmdPushConstants(commandBuffer, m_pushConstantsLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, m_pushConstantBufferSize, m_pushConstantBuffer);
|
if (pushConstants.buffer) {
|
||||||
|
vkCmdPushConstants(commandBuffer, pushConstants.layout, VK_SHADER_STAGE_VERTEX_BIT, 0, pushConstants.bufferSize, pushConstants.buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsPipeline);
|
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsPipeline);
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ class KRSurface;
|
|||||||
class KRRenderPass;
|
class KRRenderPass;
|
||||||
|
|
||||||
enum class ModelFormat : __uint8_t;
|
enum class ModelFormat : __uint8_t;
|
||||||
|
struct SpvReflectShaderModule;
|
||||||
|
|
||||||
enum class CullMode : uint32_t {
|
enum class CullMode : uint32_t {
|
||||||
kCullBack = 0,
|
kCullBack = 0,
|
||||||
@@ -315,16 +316,16 @@ private:
|
|||||||
{
|
{
|
||||||
int offset[kUniformCount];
|
int offset[kUniformCount];
|
||||||
__uint8_t size[kUniformCount];
|
__uint8_t size[kUniformCount];
|
||||||
|
uint8_t* buffer;
|
||||||
|
int bufferSize;
|
||||||
|
VkPipelineLayout layout;
|
||||||
};
|
};
|
||||||
PushConstantStageInfo m_pushConstants[static_cast<size_t>(ShaderStages::shaderStageCount)];
|
PushConstantStageInfo m_pushConstants[static_cast<size_t>(ShaderStages::shaderStageCount)];
|
||||||
|
|
||||||
uint8_t* m_pushConstantBuffer;
|
|
||||||
int m_pushConstantBufferSize;
|
|
||||||
|
|
||||||
char m_szKey[256];
|
char m_szKey[256];
|
||||||
|
|
||||||
VkPipelineLayout m_pipelineLayout;
|
VkPipelineLayout m_pipelineLayout;
|
||||||
VkPipeline m_graphicsPipeline;
|
VkPipeline m_graphicsPipeline;
|
||||||
VkPipelineLayout m_pushConstantsLayout;
|
|
||||||
|
|
||||||
|
void initPushConstantStage(ShaderStages stage, const SpvReflectShaderModule* reflection);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user