mirror of https://github.com/auygun/kaliber.git
Support for multiple texture bindings for Vulkan.
This commit is contained in:
parent
3a5572c8d0
commit
03776c643e
|
@ -12,10 +12,9 @@ UNIFORM_BEGIN
|
||||||
UNIFORM_V(vec2 tex_scale)
|
UNIFORM_V(vec2 tex_scale)
|
||||||
UNIFORM_V(mat4 projection)
|
UNIFORM_V(mat4 projection)
|
||||||
UNIFORM_F(vec4 color)
|
UNIFORM_F(vec4 color)
|
||||||
UNIFORM_S(sampler2D texture_0)
|
|
||||||
UNIFORM_END
|
UNIFORM_END
|
||||||
|
|
||||||
SAMPLER(sampler2D texture_0)
|
SAMPLER(0, sampler2D texture_0)
|
||||||
|
|
||||||
FRAG_COLOR_OUT(frag_color)
|
FRAG_COLOR_OUT(frag_color)
|
||||||
|
|
||||||
|
|
|
@ -387,7 +387,8 @@ void RendererVulkan::DestroyTexture(std::shared_ptr<void> impl_data) {
|
||||||
|
|
||||||
void RendererVulkan::ActivateTexture(std::shared_ptr<void> impl_data) {
|
void RendererVulkan::ActivateTexture(std::shared_ptr<void> impl_data) {
|
||||||
auto texture = reinterpret_cast<TextureVulkan*>(impl_data.get());
|
auto texture = reinterpret_cast<TextureVulkan*>(impl_data.get());
|
||||||
penging_descriptor_set_ = std::get<0>(texture->desc_set);
|
// Keep as pengind and bind later in ActivateShader.
|
||||||
|
penging_descriptor_sets_[/*TODO*/0] = std::get<0>(texture->desc_set);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererVulkan::CreateShader(std::shared_ptr<void> impl_data,
|
void RendererVulkan::CreateShader(std::shared_ptr<void> impl_data,
|
||||||
|
@ -579,14 +580,15 @@ void RendererVulkan::ActivateShader(std::shared_ptr<void> impl_data) {
|
||||||
vkCmdBindPipeline(frames_[current_frame_].draw_command_buffer,
|
vkCmdBindPipeline(frames_[current_frame_].draw_command_buffer,
|
||||||
VK_PIPELINE_BIND_POINT_GRAPHICS, shader->pipeline);
|
VK_PIPELINE_BIND_POINT_GRAPHICS, shader->pipeline);
|
||||||
}
|
}
|
||||||
if (shader->use_desc_set &&
|
for (int i = 0; i < shader->desc_set_count; ++i) {
|
||||||
active_descriptor_set_ != penging_descriptor_set_) {
|
if (active_descriptor_sets_[i] != penging_descriptor_sets_[i]) {
|
||||||
active_descriptor_set_ = penging_descriptor_set_;
|
active_descriptor_sets_[i] = penging_descriptor_sets_[i];
|
||||||
|
vkCmdBindDescriptorSets(frames_[current_frame_].draw_command_buffer,
|
||||||
vkCmdBindDescriptorSets(frames_[current_frame_].draw_command_buffer,
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
shader->pipeline_layout, 0, 1,
|
||||||
shader->pipeline_layout, 0, 1,
|
&active_descriptor_sets_[i], 0, nullptr);
|
||||||
&active_descriptor_set_, 0, nullptr);
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -629,9 +631,11 @@ void RendererVulkan::SetUniform(std::shared_ptr<void> impl_data,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
int val) {
|
int val) {
|
||||||
auto shader = reinterpret_cast<ShaderVulkan*>(impl_data.get());
|
auto shader = reinterpret_cast<ShaderVulkan*>(impl_data.get());
|
||||||
// Unlike OpenGL, no need to set a uniform for sampler.
|
for (auto& sampler_name : shader->sampler_uniform_names) {
|
||||||
if (name != shader->sampler_uniform_name)
|
if (name == sampler_name)
|
||||||
SetUniformInternal(shader, name, val);
|
return;
|
||||||
|
}
|
||||||
|
SetUniformInternal(shader, name, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererVulkan::UploadUniforms(std::shared_ptr<void> impl_data) {
|
void RendererVulkan::UploadUniforms(std::shared_ptr<void> impl_data) {
|
||||||
|
@ -722,8 +726,8 @@ bool RendererVulkan::InitializeInternal() {
|
||||||
// Begin the first command buffer for the first frame.
|
// Begin the first command buffer for the first frame.
|
||||||
BeginFrame();
|
BeginFrame();
|
||||||
|
|
||||||
// In this simple engine we use only one descriptor set that is for textures.
|
// In this simple engine we use only one descriptor set layout that is for
|
||||||
// We use push contants for everything else.
|
// textures. We use push contants for everything else.
|
||||||
VkDescriptorSetLayoutBinding ds_layout_binding;
|
VkDescriptorSetLayoutBinding ds_layout_binding;
|
||||||
ds_layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
ds_layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
ds_layout_binding.descriptorCount = 1;
|
ds_layout_binding.descriptorCount = 1;
|
||||||
|
@ -1540,14 +1544,8 @@ bool RendererVulkan::CreatePipelineLayout(ShaderVulkan* shader) {
|
||||||
DLOG << __func__ << " binding_count: " << binding_count;
|
DLOG << __func__ << " binding_count: " << binding_count;
|
||||||
|
|
||||||
if (binding_count > 0) {
|
if (binding_count > 0) {
|
||||||
if (binding_count > 1) {
|
// Collect binding names and validate that only COMBINED_IMAGE_SAMPLER
|
||||||
DLOG << "SPIR-V reflection found " << binding_count
|
// desriptor type is used.
|
||||||
<< " descriptor bindings in fragment shader. Only one descriptor "
|
|
||||||
"binding is suported.";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate that the desriptor type is COMBINED_IMAGE_SAMPLER.
|
|
||||||
std::vector<SpvReflectDescriptorBinding*> bindings;
|
std::vector<SpvReflectDescriptorBinding*> bindings;
|
||||||
bindings.resize(binding_count);
|
bindings.resize(binding_count);
|
||||||
result = spvReflectEnumerateDescriptorBindings(
|
result = spvReflectEnumerateDescriptorBindings(
|
||||||
|
@ -1559,23 +1557,37 @@ bool RendererVulkan::CreatePipelineLayout(ShaderVulkan* shader) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SpvReflectDescriptorBinding& binding = *bindings[0];
|
for (int i = 0; i < binding_count; ++i) {
|
||||||
|
const SpvReflectDescriptorBinding& binding = *bindings[i];
|
||||||
|
|
||||||
DLOG << __func__ << " name: " << binding.name
|
DLOG << __func__ << " name: " << binding.name
|
||||||
<< " descriptor_type: " << binding.descriptor_type
|
<< " descriptor_type: " << binding.descriptor_type
|
||||||
<< " set: " << binding.set << " binding: " << binding.binding;
|
<< " set: " << binding.set << " binding: " << binding.binding;
|
||||||
|
|
||||||
if (binding.descriptor_type !=
|
if (binding.binding > 0) {
|
||||||
SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
|
DLOG << "SPIR-V reflection found " << binding_count
|
||||||
DLOG << "SPIR-V reflection found descriptor type "
|
<< " bindings in vertex shader. Only one binding per set is "
|
||||||
<< binding.descriptor_type
|
"supported";
|
||||||
<< " in fragment shader. Only COMBINED_IMAGE_SAMPLER type is "
|
break;
|
||||||
"supported.";
|
}
|
||||||
break;
|
|
||||||
|
if (binding.descriptor_type !=
|
||||||
|
SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
|
||||||
|
DLOG << "SPIR-V reflection found descriptor type "
|
||||||
|
<< binding.descriptor_type
|
||||||
|
<< " in fragment shader. Only COMBINED_IMAGE_SAMPLER type is "
|
||||||
|
"supported.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
shader->sampler_uniform_names.push_back(binding.name);
|
||||||
|
shader->desc_set_count++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
shader->sampler_uniform_name = binding.name;
|
if (active_descriptor_sets_.size() < shader->desc_set_count) {
|
||||||
shader->use_desc_set = true;
|
active_descriptor_sets_.resize(shader->desc_set_count);
|
||||||
|
penging_descriptor_sets_.resize(shader->desc_set_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse push constants.
|
// Parse push constants.
|
||||||
|
@ -1657,7 +1669,10 @@ bool RendererVulkan::CreatePipelineLayout(ShaderVulkan* shader) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VkDescriptorSetLayout desc_set_layout = descriptor_set_layout_;
|
// Use the same layout for all decriptor sets.
|
||||||
|
std::vector<VkDescriptorSetLayout> desc_set_layouts;
|
||||||
|
for (int i = 0; i < binding_count; ++i)
|
||||||
|
desc_set_layouts.push_back(descriptor_set_layout_);
|
||||||
|
|
||||||
VkPipelineLayoutCreateInfo pipeline_layout_create_info;
|
VkPipelineLayoutCreateInfo pipeline_layout_create_info;
|
||||||
pipeline_layout_create_info.sType =
|
pipeline_layout_create_info.sType =
|
||||||
|
@ -1665,8 +1680,8 @@ bool RendererVulkan::CreatePipelineLayout(ShaderVulkan* shader) {
|
||||||
pipeline_layout_create_info.pNext = nullptr;
|
pipeline_layout_create_info.pNext = nullptr;
|
||||||
pipeline_layout_create_info.flags = 0;
|
pipeline_layout_create_info.flags = 0;
|
||||||
if (binding_count > 0) {
|
if (binding_count > 0) {
|
||||||
pipeline_layout_create_info.setLayoutCount = 1;
|
pipeline_layout_create_info.setLayoutCount = binding_count;
|
||||||
pipeline_layout_create_info.pSetLayouts = &desc_set_layout;
|
pipeline_layout_create_info.pSetLayouts = desc_set_layouts.data();
|
||||||
} else {
|
} else {
|
||||||
pipeline_layout_create_info.setLayoutCount = 0;
|
pipeline_layout_create_info.setLayoutCount = 0;
|
||||||
pipeline_layout_create_info.pSetLayouts = nullptr;
|
pipeline_layout_create_info.pSetLayouts = nullptr;
|
||||||
|
@ -1780,8 +1795,10 @@ void RendererVulkan::SwapBuffers() {
|
||||||
current_frame_ = (current_frame_ + 1) % frames_.size();
|
current_frame_ = (current_frame_ + 1) % frames_.size();
|
||||||
|
|
||||||
active_pipeline_ = VK_NULL_HANDLE;
|
active_pipeline_ = VK_NULL_HANDLE;
|
||||||
active_descriptor_set_ = VK_NULL_HANDLE;
|
for (auto& ds : active_descriptor_sets_)
|
||||||
penging_descriptor_set_ = VK_NULL_HANDLE;
|
ds = VK_NULL_HANDLE;
|
||||||
|
for (auto& ds : penging_descriptor_sets_)
|
||||||
|
ds = VK_NULL_HANDLE;
|
||||||
|
|
||||||
BeginFrame();
|
BeginFrame();
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,8 +113,8 @@ class RendererVulkan : public Renderer {
|
||||||
std::unordered_map<std::string, std::array<size_t, 2>> variables;
|
std::unordered_map<std::string, std::array<size_t, 2>> variables;
|
||||||
std::unique_ptr<char[]> push_constants;
|
std::unique_ptr<char[]> push_constants;
|
||||||
size_t push_constants_size = 0;
|
size_t push_constants_size = 0;
|
||||||
std::string sampler_uniform_name;
|
std::vector<std::string> sampler_uniform_names;
|
||||||
bool use_desc_set = false;
|
int desc_set_count = 0;
|
||||||
std::vector<uint8_t> spirv_vertex;
|
std::vector<uint8_t> spirv_vertex;
|
||||||
std::vector<uint8_t> spirv_fragment;
|
std::vector<uint8_t> spirv_fragment;
|
||||||
VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
|
VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
|
||||||
|
@ -172,8 +172,8 @@ class RendererVulkan : public Renderer {
|
||||||
|
|
||||||
std::vector<std::unique_ptr<DescPool>> desc_pools_;
|
std::vector<std::unique_ptr<DescPool>> desc_pools_;
|
||||||
VkDescriptorSetLayout descriptor_set_layout_ = VK_NULL_HANDLE;
|
VkDescriptorSetLayout descriptor_set_layout_ = VK_NULL_HANDLE;
|
||||||
VkDescriptorSet active_descriptor_set_ = VK_NULL_HANDLE;
|
std::vector<VkDescriptorSet> active_descriptor_sets_;
|
||||||
VkDescriptorSet penging_descriptor_set_ = VK_NULL_HANDLE;
|
std::vector<VkDescriptorSet> penging_descriptor_sets_;
|
||||||
|
|
||||||
VkSampler sampler_ = VK_NULL_HANDLE;
|
VkSampler sampler_ = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
|
|
@ -37,9 +37,8 @@ const char kFragmentShaderMacros[] = R"(
|
||||||
#define UNIFORM_BEGIN layout(push_constant) uniform Params {
|
#define UNIFORM_BEGIN layout(push_constant) uniform Params {
|
||||||
#define UNIFORM_V(X) X;
|
#define UNIFORM_V(X) X;
|
||||||
#define UNIFORM_F(X) X;
|
#define UNIFORM_F(X) X;
|
||||||
#define UNIFORM_S(X)
|
|
||||||
#define UNIFORM_END } params;
|
#define UNIFORM_END } params;
|
||||||
#define SAMPLER(X) layout(set = 0, binding = 0) uniform X;
|
#define SAMPLER(N, X) layout(set = N, binding = 0) uniform X;
|
||||||
#define IN(X) layout(location = X) in
|
#define IN(X) layout(location = X) in
|
||||||
#define OUT(X) layout(location = X) out
|
#define OUT(X) layout(location = X) out
|
||||||
#define FRAG_COLOR_OUT(X) layout(location = 0) out vec4 X;
|
#define FRAG_COLOR_OUT(X) layout(location = 0) out vec4 X;
|
||||||
|
@ -50,9 +49,8 @@ const char kFragmentShaderMacros[] = R"(
|
||||||
#define UNIFORM_BEGIN
|
#define UNIFORM_BEGIN
|
||||||
#define UNIFORM_V(X)
|
#define UNIFORM_V(X)
|
||||||
#define UNIFORM_F(X) uniform X;
|
#define UNIFORM_F(X) uniform X;
|
||||||
#define UNIFORM_S(X) uniform X;
|
|
||||||
#define UNIFORM_END
|
#define UNIFORM_END
|
||||||
#define SAMPLER(X)
|
#define SAMPLER(N, X) uniform X;
|
||||||
#define IN(X) varying
|
#define IN(X) varying
|
||||||
#define OUT(X) varying
|
#define OUT(X) varying
|
||||||
#define FRAG_COLOR_OUT(X)
|
#define FRAG_COLOR_OUT(X)
|
||||||
|
|
Loading…
Reference in New Issue