Add texture mapping

This commit is contained in:
Benau 2022-07-21 12:26:06 +08:00
parent fec21afc8e
commit 3d0d666e09
14 changed files with 264 additions and 33 deletions

View File

@ -1,8 +1,13 @@
layout(location = 0) in vec4 f_vertex_color; layout(location = 0) in vec4 f_vertex_color;
layout(location = 1) in vec2 f_uv;
layout(location = 2) flat in int f_material_id;
layout(location = 0) out vec4 o_color; layout(location = 0) out vec4 o_color;
#include "utils/sample_mesh_texture.h"
void main() void main()
{ {
o_color = f_vertex_color; vec3 mixed_color = sampleMeshTexture0(f_material_id, f_uv).xyz * f_vertex_color.xyz;
o_color = vec4(mixed_color, 1.0);
} }

View File

@ -1,4 +1,4 @@
layout(std140, set = 0, binding = 0) uniform CameraBuffer layout(std140, set = 1, binding = 0) uniform CameraBuffer
{ {
mat4 m_view_matrix; mat4 m_view_matrix;
mat4 m_projection_matrix; mat4 m_projection_matrix;
@ -10,9 +10,12 @@ layout(std140, set = 0, binding = 0) uniform CameraBuffer
struct ObjectData struct ObjectData
{ {
mat4 m_model; mat4 m_model;
int m_skinning_offest;
int m_material_id;
vec2 m_texture_trans;
}; };
layout(std140, set = 0, binding = 1) readonly buffer ObjectBuffer layout(std140, set = 1, binding = 1) readonly buffer ObjectBuffer
{ {
ObjectData m_objects[]; ObjectData m_objects[];
} u_object_buffer; } u_object_buffer;
@ -27,6 +30,8 @@ layout(location = 6) in ivec4 v_joint;
layout(location = 7) in vec4 v_weight; layout(location = 7) in vec4 v_weight;
layout(location = 0) out vec4 f_vertex_color; layout(location = 0) out vec4 f_vertex_color;
layout(location = 1) out vec2 f_uv;
layout(location = 2) flat out int f_material_id;
void main() void main()
{ {
@ -34,4 +39,6 @@ void main()
gl_Position = u_camera.m_projection_view_matrix * model_matrix * gl_Position = u_camera.m_projection_view_matrix * model_matrix *
vec4(v_position, 1.0); vec4(v_position, 1.0);
f_vertex_color = v_color.zyxw; f_vertex_color = v_color.zyxw;
f_uv = v_uv;
f_material_id = u_object_buffer.m_objects[gl_InstanceIndex].m_material_id;
} }

View File

@ -0,0 +1,87 @@
#ifdef BIND_MESH_TEXTURES_AT_ONCE
layout(binding = 0) uniform sampler2D f_mesh_textures[SAMPLER_SIZE * TOTAL_MESH_TEXTURE_LAYER];
vec4 sampleMeshTexture0(int material_id, vec2 uv)
{
return texture(f_mesh_textures[(TOTAL_MESH_TEXTURE_LAYER * material_id) + 0], uv);
}
vec4 sampleMeshTexture1(int material_id, vec2 uv)
{
return texture(f_mesh_textures[(TOTAL_MESH_TEXTURE_LAYER * material_id) + 1], uv);
}
vec4 sampleMeshTexture2(int material_id, vec2 uv)
{
return texture(f_mesh_textures[(TOTAL_MESH_TEXTURE_LAYER * material_id) + 2], uv);
}
vec4 sampleMeshTexture3(int material_id, vec2 uv)
{
return texture(f_mesh_textures[(TOTAL_MESH_TEXTURE_LAYER * material_id) + 3], uv);
}
vec4 sampleMeshTexture4(int material_id, vec2 uv)
{
return texture(f_mesh_textures[(TOTAL_MESH_TEXTURE_LAYER * material_id) + 4], uv);
}
vec4 sampleMeshTexture5(int material_id, vec2 uv)
{
return texture(f_mesh_textures[(TOTAL_MESH_TEXTURE_LAYER * material_id) + 5], uv);
}
vec4 sampleMeshTexture6(int material_id, vec2 uv)
{
return texture(f_mesh_textures[(TOTAL_MESH_TEXTURE_LAYER * material_id) + 6], uv);
}
vec4 sampleMeshTexture7(int material_id, vec2 uv)
{
return texture(f_mesh_textures[(TOTAL_MESH_TEXTURE_LAYER * material_id) + 7], uv);
}
#else
layout(binding = 0) uniform sampler2D f_mesh_textures[TOTAL_MESH_TEXTURE_LAYER];
vec4 sampleMeshTexture0(int material_id, vec2 uv)
{
return texture(f_mesh_textures[0], uv);
}
vec4 sampleMeshTexture1(int material_id, vec2 uv)
{
return texture(f_mesh_textures[1], uv);
}
#ifdef PBR_ENABLED
vec4 sampleMeshTexture2(int material_id, vec2 uv)
{
return texture(f_mesh_textures[2], uv);
}
vec4 sampleMeshTexture3(int material_id, vec2 uv)
{
return texture(f_mesh_textures[3], uv);
}
vec4 sampleMeshTexture4(int material_id, vec2 uv)
{
return texture(f_mesh_textures[4], uv);
}
vec4 sampleMeshTexture5(int material_id, vec2 uv)
{
return texture(f_mesh_textures[5], uv);
}
vec4 sampleMeshTexture6(int material_id, vec2 uv)
{
return texture(f_mesh_textures[6], uv);
}
vec4 sampleMeshTexture7(int material_id, vec2 uv)
{
return texture(f_mesh_textures[7], uv);
}
#endif
#endif

View File

@ -25,6 +25,7 @@ namespace GE
{ {
class GEVulkanDepthTexture; class GEVulkanDepthTexture;
class GEVulkanMeshCache; class GEVulkanMeshCache;
class GEVulkanTextureDescriptor;
enum GEVulkanSampler : unsigned enum GEVulkanSampler : unsigned
{ {
GVS_MIN = 0, GVS_MIN = 0,
@ -343,6 +344,8 @@ namespace GE
VkFormatFeatureFlags features); VkFormatFeatureFlags features);
VmaAllocator getVmaAllocator() const { return m_vk->allocator; } VmaAllocator getVmaAllocator() const { return m_vk->allocator; }
GEVulkanMeshCache* getVulkanMeshCache() const; GEVulkanMeshCache* getVulkanMeshCache() const;
GEVulkanTextureDescriptor* getMeshTextureDescriptor() const
{ return m_mesh_texture_descriptor; }
private: private:
struct SwapChainSupportDetails struct SwapChainSupportDetails
{ {
@ -469,6 +472,7 @@ namespace GE
IrrlichtDevice* m_irrlicht_device; IrrlichtDevice* m_irrlicht_device;
GEVulkanDepthTexture* m_depth_texture; GEVulkanDepthTexture* m_depth_texture;
GEVulkanTextureDescriptor* m_mesh_texture_descriptor;
void createInstance(SDL_Window* window); void createInstance(SDL_Window* window);
void findPhysicalDevice(); void findPhysicalDevice();

View File

@ -45,6 +45,8 @@ public:
const irr::core::vector3df& scale = irr::core::vector3df(1.0f, 1.0f, 1.0f), const irr::core::vector3df& scale = irr::core::vector3df(1.0f, 1.0f, 1.0f),
bool alsoAddIfMeshPointerZero = false); bool alsoAddIfMeshPointerZero = false);
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
virtual void clear();
// ------------------------------------------------------------------------
virtual void drawAll(irr::u32 flags = 0xFFFFFFFF); virtual void drawAll(irr::u32 flags = 0xFFFFFFFF);
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
virtual irr::u32 registerNodeForRendering(irr::scene::ISceneNode* node, virtual irr::u32 registerNodeForRendering(irr::scene::ISceneNode* node,

View File

@ -54,6 +54,13 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
~GEVulkanTextureDescriptor(); ~GEVulkanTextureDescriptor();
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void clear()
{
m_texture_list.clear();
m_needs_update_descriptor = true;
m_recreate_next_frame = false;
}
// ------------------------------------------------------------------------
void handleDeletedTextures() void handleDeletedTextures()
{ {
bool has_deleted_image_view = false; bool has_deleted_image_view = false;
@ -69,11 +76,7 @@ public:
} }
} }
if (has_deleted_image_view || m_recreate_next_frame) if (has_deleted_image_view || m_recreate_next_frame)
{ clear();
m_texture_list.clear();
m_needs_update_descriptor = true;
m_recreate_next_frame = false;
}
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
int getTextureID(const irr::video::ITexture** list); int getTextureID(const irr::video::ITexture** list);

View File

@ -7,12 +7,25 @@
#include "ge_vulkan_camera_scene_node.hpp" #include "ge_vulkan_camera_scene_node.hpp"
#include "ge_vulkan_driver.hpp" #include "ge_vulkan_driver.hpp"
#include "ge_vulkan_dynamic_buffer.hpp" #include "ge_vulkan_dynamic_buffer.hpp"
#include "ge_vulkan_features.hpp"
#include "ge_vulkan_mesh_cache.hpp" #include "ge_vulkan_mesh_cache.hpp"
#include "ge_vulkan_mesh_scene_node.hpp" #include "ge_vulkan_mesh_scene_node.hpp"
#include "ge_vulkan_shader_manager.hpp" #include "ge_vulkan_shader_manager.hpp"
#include "ge_vulkan_texture_descriptor.hpp"
namespace GE namespace GE
{ {
// ============================================================================
ObjectData::ObjectData(irr::scene::ISceneNode* node, int material_id)
{
memcpy(m_mat_1, node->getAbsoluteTransformation().pointer(),
sizeof(irr::core::matrix4));
m_skinning_offset = -1;
m_material_id = material_id;
m_texture_trans[0] = 0.0f;
m_texture_trans[1] = 0.0f;
} // ObjectData
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
GEVulkanDrawCall::GEVulkanDrawCall() GEVulkanDrawCall::GEVulkanDrawCall()
{ {
@ -29,6 +42,7 @@ GEVulkanDrawCall::GEVulkanDrawCall()
m_descriptor_pool = VK_NULL_HANDLE; m_descriptor_pool = VK_NULL_HANDLE;
m_graphics_pipeline = VK_NULL_HANDLE; m_graphics_pipeline = VK_NULL_HANDLE;
m_pipeline_layout = VK_NULL_HANDLE; m_pipeline_layout = VK_NULL_HANDLE;
m_texture_descriptor = getVKDriver()->getMeshTextureDescriptor();
} // GEVulkanDrawCall } // GEVulkanDrawCall
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -86,11 +100,26 @@ void GEVulkanDrawCall::generate()
unsigned accumulated_instance = 0; unsigned accumulated_instance = 0;
for (auto& p : m_visible_nodes) for (auto& p : m_visible_nodes)
{ {
irr::video::SMaterial& m = p.first->getMaterial();
std::array<const irr::video::ITexture*, 8> textures =
{{
m.TextureLayer[0].Texture,
m.TextureLayer[1].Texture,
m.TextureLayer[2].Texture,
m.TextureLayer[3].Texture,
m.TextureLayer[4].Texture,
m.TextureLayer[5].Texture,
m.TextureLayer[6].Texture,
m.TextureLayer[7].Texture
}};
const irr::video::ITexture** list = &textures[0];
const int material_id = m_texture_descriptor->getTextureID(list);
m_materials.push_back(material_id);
unsigned visible_count = p.second.size(); unsigned visible_count = p.second.size();
if (visible_count != 0) if (visible_count != 0)
{ {
for (auto* node : p.second) for (auto* node : p.second)
m_visible_trans.push_back(node->getAbsoluteTransformation()); m_visible_objects.emplace_back(node, material_id);
VkDrawIndexedIndirectCommand cmd; VkDrawIndexedIndirectCommand cmd;
cmd.indexCount = p.first->getIndexCount(); cmd.indexCount = p.first->getIndexCount();
cmd.instanceCount = visible_count; cmd.instanceCount = visible_count;
@ -110,7 +139,8 @@ void GEVulkanDrawCall::prepare(GEVulkanCameraSceneNode* cam)
{ {
m_visible_nodes.clear(); m_visible_nodes.clear();
m_cmds.clear(); m_cmds.clear();
m_visible_trans.clear(); m_visible_objects.clear();
m_materials.clear();
m_culling_tool->init(cam); m_culling_tool->init(cam);
} // prepare } // prepare
@ -192,10 +222,16 @@ void GEVulkanDrawCall::createVulkanData()
} }
// m_pipeline_layout // m_pipeline_layout
std::array<VkDescriptorSetLayout, 2> all_layouts =
{{
*m_texture_descriptor->getDescriptorSetLayout(),
m_data_layout
}};
VkPipelineLayoutCreateInfo pipeline_layout_info = {}; VkPipelineLayoutCreateInfo pipeline_layout_info = {};
pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipeline_layout_info.setLayoutCount = 1; pipeline_layout_info.setLayoutCount = all_layouts.size();
pipeline_layout_info.pSetLayouts = &m_data_layout; pipeline_layout_info.pSetLayouts = all_layouts.data();
result = vkCreatePipelineLayout(vk->getDevice(), &pipeline_layout_info, result = vkCreatePipelineLayout(vk->getDevice(), &pipeline_layout_info,
NULL, &m_pipeline_layout); NULL, &m_pipeline_layout);
@ -366,13 +402,13 @@ void GEVulkanDrawCall::createVulkanData()
if (result != VK_SUCCESS) if (result != VK_SUCCESS)
throw std::runtime_error("vkCreateGraphicsPipelines failed"); throw std::runtime_error("vkCreateGraphicsPipelines failed");
size_t size = m_visible_trans.size(); size_t size = m_visible_objects.size();
if (m_visible_trans.empty()) if (m_visible_objects.empty())
size = 100; size = 100;
m_dynamic_data = new GEVulkanDynamicBuffer(GVDBT_GPU_RAM, m_dynamic_data = new GEVulkanDynamicBuffer(GVDBT_GPU_RAM,
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
(sizeof(irr::core::matrix4) * size) + sizeof(GEVulkanCameraUBO)); (sizeof(ObjectData) * size) + sizeof(GEVulkanCameraUBO));
} // createVulkanData } // createVulkanData
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -385,7 +421,7 @@ void GEVulkanDrawCall::uploadDynamicData(GEVulkanDriver* vk,
const VkPhysicalDeviceLimits& limit = const VkPhysicalDeviceLimits& limit =
vk->getPhysicalDeviceProperties().limits; vk->getPhysicalDeviceProperties().limits;
const size_t object_data_size = const size_t object_data_size =
sizeof(irr::core::matrix4) * m_visible_trans.size(); sizeof(ObjectData) * m_visible_objects.size();
size_t ubo_alignment = limit.minUniformBufferOffsetAlignment; size_t ubo_alignment = limit.minUniformBufferOffsetAlignment;
size_t ubo_padding = 0; size_t ubo_padding = 0;
if (ubo_alignment > 0) if (ubo_alignment > 0)
@ -393,7 +429,7 @@ void GEVulkanDrawCall::uploadDynamicData(GEVulkanDriver* vk,
m_object_data_padded_size = object_data_size + ubo_padding; m_object_data_padded_size = object_data_size + ubo_padding;
std::vector<std::pair<void*, size_t> > data; std::vector<std::pair<void*, size_t> > data;
data.emplace_back((void*)m_visible_trans.data(), object_data_size); data.emplace_back((void*)m_visible_objects.data(), object_data_size);
if (ubo_padding > 0) if (ubo_padding > 0)
data.emplace_back((void*)m_object_data_padding, ubo_padding); data.emplace_back((void*)m_object_data_padding, ubo_padding);
data.emplace_back(cam->getUBOData(), sizeof(GEVulkanCameraUBO)); data.emplace_back(cam->getUBOData(), sizeof(GEVulkanCameraUBO));
@ -455,11 +491,20 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam)
vkUpdateDescriptorSets(vk->getDevice(), data_set.size(), data_set.data(), vkUpdateDescriptorSets(vk->getDevice(), data_set.size(), data_set.data(),
0, NULL); 0, NULL);
m_texture_descriptor->updateDescriptor();
vkCmdBindPipeline(vk->getCurrentCommandBuffer(), vkCmdBindPipeline(vk->getCurrentCommandBuffer(),
VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphics_pipeline); VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphics_pipeline);
if (GEVulkanFeatures::supportsBindMeshTexturesAtOnce())
{
vkCmdBindDescriptorSets(vk->getCurrentCommandBuffer(), vkCmdBindDescriptorSets(vk->getCurrentCommandBuffer(),
VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout, 0, 1, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout, 0, 1,
m_texture_descriptor->getDescriptorSet(), 0, NULL);
}
vkCmdBindDescriptorSets(vk->getCurrentCommandBuffer(),
VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout, 1, 1,
&m_data_descriptor_sets[cur_frame], 0, NULL); &m_data_descriptor_sets[cur_frame], 0, NULL);
VkDeviceSize offsets[] = {0}; VkDeviceSize offsets[] = {0};
@ -488,8 +533,16 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam)
scissor.extent.height = vp.height; scissor.extent.height = vp.height;
vkCmdSetScissor(vk->getCurrentCommandBuffer(), 0, 1, &scissor); vkCmdSetScissor(vk->getCurrentCommandBuffer(), 0, 1, &scissor);
for (VkDrawIndexedIndirectCommand& cmd : m_cmds) for (unsigned i = 0; i < m_cmds.size(); i++)
{ {
if (!GEVulkanFeatures::supportsBindMeshTexturesAtOnce())
{
vkCmdBindDescriptorSets(vk->getCurrentCommandBuffer(),
VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout, 0, 1,
&m_texture_descriptor->getDescriptorSet()[m_materials[i]], 0,
NULL);
}
const VkDrawIndexedIndirectCommand& cmd = m_cmds[i];
vkCmdDrawIndexed(vk->getCurrentCommandBuffer(), cmd.indexCount, vkCmdDrawIndexed(vk->getCurrentCommandBuffer(), cmd.indexCount,
cmd.instanceCount, cmd.firstIndex, cmd.vertexOffset, cmd.instanceCount, cmd.firstIndex, cmd.vertexOffset,
cmd.firstInstance); cmd.firstInstance);

View File

@ -20,6 +20,20 @@ class GESPMBuffer;
class GEVulkanCameraSceneNode; class GEVulkanCameraSceneNode;
class GEVulkanDriver; class GEVulkanDriver;
class GEVulkanDynamicBuffer; class GEVulkanDynamicBuffer;
class GEVulkanTextureDescriptor;
struct ObjectData
{
float m_mat_1[4];
float m_mat_2[4];
float m_mat_3[4];
float m_mat_4[4];
int m_skinning_offset;
int m_material_id;
float m_texture_trans[2];
// ------------------------------------------------------------------------
ObjectData(irr::scene::ISceneNode* node, int material_id);
};
class GEVulkanDrawCall class GEVulkanDrawCall
{ {
@ -30,7 +44,7 @@ private:
std::vector<VkDrawIndexedIndirectCommand> m_cmds; std::vector<VkDrawIndexedIndirectCommand> m_cmds;
std::vector<irr::core::matrix4> m_visible_trans; std::vector<ObjectData> m_visible_objects;
GEVulkanDynamicBuffer* m_dynamic_data; GEVulkanDynamicBuffer* m_dynamic_data;
@ -48,6 +62,9 @@ private:
VkPipeline m_graphics_pipeline; VkPipeline m_graphics_pipeline;
std::vector<int> m_materials;
GEVulkanTextureDescriptor* m_texture_descriptor;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void createVulkanData(); void createVulkanData();
public: public:

View File

@ -11,7 +11,7 @@
#include "ge_vulkan_mesh_cache.hpp" #include "ge_vulkan_mesh_cache.hpp"
#include "ge_vulkan_scene_manager.hpp" #include "ge_vulkan_scene_manager.hpp"
#include "ge_vulkan_shader_manager.hpp" #include "ge_vulkan_shader_manager.hpp"
#include "ge_vulkan_texture.hpp" #include "ge_vulkan_texture_descriptor.hpp"
#include "ISceneManager.h" #include "ISceneManager.h"
#include "IrrlichtDevice.h" #include "IrrlichtDevice.h"
@ -490,7 +490,7 @@ GEVulkanDriver::GEVulkanDriver(const SIrrlichtCreationParameters& params,
IrrlichtDevice* device) IrrlichtDevice* device)
: CNullDriver(io, core::dimension2d<u32>(0, 0)), : CNullDriver(io, core::dimension2d<u32>(0, 0)),
m_params(params), m_irrlicht_device(device), m_params(params), m_irrlicht_device(device),
m_depth_texture(NULL) m_depth_texture(NULL), m_mesh_texture_descriptor(NULL)
{ {
m_vk.reset(new VK()); m_vk.reset(new VK());
m_physical_device = VK_NULL_HANDLE; m_physical_device = VK_NULL_HANDLE;
@ -622,6 +622,10 @@ GEVulkanDriver::GEVulkanDriver(const SIrrlichtCreationParameters& params,
GE::setVideoDriver(this); GE::setVideoDriver(this);
createUnicolorTextures(); createUnicolorTextures();
GEVulkan2dRenderer::init(this); GEVulkan2dRenderer::init(this);
m_mesh_texture_descriptor = new GEVulkanTextureDescriptor(
GEVulkanShaderManager::getSamplerSize(),
GEVulkanShaderManager::getMeshTextureLayer(),
GEVulkanFeatures::supportsBindMeshTexturesAtOnce());
GEVulkanFeatures::printStats(); GEVulkanFeatures::printStats();
} }
catch (std::exception& e) catch (std::exception& e)
@ -666,6 +670,7 @@ void GEVulkanDriver::destroyVulkan()
if (m_irrlicht_device->getSceneManager() && if (m_irrlicht_device->getSceneManager() &&
m_irrlicht_device->getSceneManager()->getMeshCache()) m_irrlicht_device->getSceneManager()->getMeshCache())
getVulkanMeshCache()->destroy(); getVulkanMeshCache()->destroy();
delete m_mesh_texture_descriptor;
GEVulkan2dRenderer::destroy(); GEVulkan2dRenderer::destroy();
GEVulkanShaderManager::destroy(); GEVulkanShaderManager::destroy();
@ -2220,6 +2225,7 @@ VkFormat GEVulkanDriver::findSupportedFormat(const std::vector<VkFormat>& candid
void GEVulkanDriver::handleDeletedTextures() void GEVulkanDriver::handleDeletedTextures()
{ {
GEVulkan2dRenderer::handleDeletedTextures(); GEVulkan2dRenderer::handleDeletedTextures();
m_mesh_texture_descriptor->handleDeletedTextures();
} // handleDeletedTextures } // handleDeletedTextures
} }

View File

@ -3,6 +3,7 @@
#include "ge_vulkan_driver.hpp" #include "ge_vulkan_driver.hpp"
#include "ge_vulkan_shader_manager.hpp" #include "ge_vulkan_shader_manager.hpp"
#include <algorithm>
#include <set> #include <set>
#include <string> #include <string>
#include <vector> #include <vector>
@ -21,6 +22,7 @@ bool g_supports_r8_blit = false;
bool g_supports_descriptor_indexing = false; bool g_supports_descriptor_indexing = false;
bool g_supports_non_uniform_indexing = false; bool g_supports_non_uniform_indexing = false;
bool g_supports_partially_bound = false; bool g_supports_partially_bound = false;
uint32_t g_max_sampler_supported = 0;
} // GEVulkanFeatures } // GEVulkanFeatures
// ============================================================================ // ============================================================================
@ -34,14 +36,15 @@ void GEVulkanFeatures::init(GEVulkanDriver* vk)
// https://vulkan.gpuinfo.org/displaydevicelimit.php?name=maxPerStageDescriptorSamplers&platform=all // https://vulkan.gpuinfo.org/displaydevicelimit.php?name=maxPerStageDescriptorSamplers&platform=all
// https://vulkan.gpuinfo.org/displaydevicelimit.php?name=maxPerStageDescriptorSampledImages&platform=all // https://vulkan.gpuinfo.org/displaydevicelimit.php?name=maxPerStageDescriptorSampledImages&platform=all
// We decide 256 (GEVulkanShaderManager::getSamplerSize()) based on those infos // We decide 256 (GEVulkanShaderManager::getSamplerSize()) based on those infos
g_max_sampler_supported = std::min(
{
limit.maxDescriptorSetSamplers,
limit.maxDescriptorSetSampledImages,
limit.maxPerStageDescriptorSamplers,
limit.maxPerStageDescriptorSampledImages
});
const unsigned max_sampler_size = GEVulkanShaderManager::getSamplerSize(); const unsigned max_sampler_size = GEVulkanShaderManager::getSamplerSize();
if (limit.maxDescriptorSetSamplers < max_sampler_size) if (max_sampler_size > g_max_sampler_supported)
g_supports_bind_textures_at_once = false;
if (limit.maxDescriptorSetSampledImages < max_sampler_size)
g_supports_bind_textures_at_once = false;
if (limit.maxPerStageDescriptorSamplers < max_sampler_size)
g_supports_bind_textures_at_once = false;
if (limit.maxPerStageDescriptorSampledImages < max_sampler_size)
g_supports_bind_textures_at_once = false; g_supports_bind_textures_at_once = false;
if (vk->getPhysicalDeviceFeatures().shaderSampledImageArrayDynamicIndexing == VK_FALSE) if (vk->getPhysicalDeviceFeatures().shaderSampledImageArrayDynamicIndexing == VK_FALSE)
{ {
@ -107,11 +110,15 @@ void GEVulkanFeatures::init(GEVulkanDriver* vk)
if (props2.sType == if (props2.sType ==
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES) VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES)
{ {
g_max_sampler_supported = std::min(
{
props2.maxPerStageDescriptorUpdateAfterBindSamplers,
props2.maxPerStageDescriptorUpdateAfterBindSampledImages,
props2.maxDescriptorSetUpdateAfterBindSamplers,
props2.maxDescriptorSetUpdateAfterBindSampledImages
});
g_supports_bind_textures_at_once = g_supports_bind_textures_at_once =
props2.maxPerStageDescriptorUpdateAfterBindSamplers > max_sampler_size && g_max_sampler_supported >= max_sampler_size;
props2.maxPerStageDescriptorUpdateAfterBindSampledImages > max_sampler_size &&
props2.maxDescriptorSetUpdateAfterBindSamplers > max_sampler_size &&
props2.maxDescriptorSetUpdateAfterBindSampledImages > max_sampler_size;
} }
} }
} // init } // init
@ -122,6 +129,9 @@ void GEVulkanFeatures::printStats()
os::Printer::log( os::Printer::log(
"Vulkan can bind textures at once in shader", "Vulkan can bind textures at once in shader",
g_supports_bind_textures_at_once ? "true" : "false"); g_supports_bind_textures_at_once ? "true" : "false");
os::Printer::log(
"Vulkan can bind mesh textures at once in shader",
supportsBindMeshTexturesAtOnce() ? "true" : "false");
os::Printer::log( os::Printer::log(
"Vulkan supports linear blitting for rgba8", "Vulkan supports linear blitting for rgba8",
g_supports_rgba8_blit ? "true" : "false"); g_supports_rgba8_blit ? "true" : "false");
@ -182,4 +192,14 @@ bool GEVulkanFeatures::supportsPartiallyBound()
return g_supports_partially_bound; return g_supports_partially_bound;
} // supportsPartiallyBound } // supportsPartiallyBound
// ----------------------------------------------------------------------------
bool GEVulkanFeatures::supportsBindMeshTexturesAtOnce()
{
if (!g_supports_bind_textures_at_once)
return false;
const unsigned sampler_count = GEVulkanShaderManager::getSamplerSize() *
GEVulkanShaderManager::getMeshTextureLayer();
return g_max_sampler_supported >= sampler_count;
} // supportsBindMeshTexturesAtOnce
} }

View File

@ -26,6 +26,8 @@ bool supportsNonUniformIndexing();
bool supportsDifferentTexturePerDraw(); bool supportsDifferentTexturePerDraw();
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
bool supportsPartiallyBound(); bool supportsPartiallyBound();
// ----------------------------------------------------------------------------
bool supportsBindMeshTexturesAtOnce();
}; // GEVulkanFeatures }; // GEVulkanFeatures
} }

View File

@ -6,8 +6,10 @@
#include "ge_vulkan_animated_mesh_scene_node.hpp" #include "ge_vulkan_animated_mesh_scene_node.hpp"
#include "ge_vulkan_camera_scene_node.hpp" #include "ge_vulkan_camera_scene_node.hpp"
#include "ge_vulkan_draw_call.hpp" #include "ge_vulkan_draw_call.hpp"
#include "ge_vulkan_driver.hpp"
#include "ge_vulkan_mesh_cache.hpp" #include "ge_vulkan_mesh_cache.hpp"
#include "ge_vulkan_mesh_scene_node.hpp" #include "ge_vulkan_mesh_scene_node.hpp"
#include "ge_vulkan_texture_descriptor.hpp"
namespace GE namespace GE
{ {
@ -28,6 +30,14 @@ GEVulkanSceneManager::~GEVulkanSceneManager()
{ {
} // ~GEVulkanSceneManager } // ~GEVulkanSceneManager
// ----------------------------------------------------------------------------
void GEVulkanSceneManager::clear()
{
irr::scene::CSceneManager::clear();
static_cast<GEVulkanDriver*>(getVideoDriver())
->getMeshTextureDescriptor()->clear();
} // clear
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
irr::scene::ICameraSceneNode* GEVulkanSceneManager::addCameraSceneNode( irr::scene::ICameraSceneNode* GEVulkanSceneManager::addCameraSceneNode(
irr::scene::ISceneNode* parent, irr::scene::ISceneNode* parent,

View File

@ -21,6 +21,10 @@ GEVulkanDriver* g_vk = NULL;
irr::io::IFileSystem* g_file_system = NULL; irr::io::IFileSystem* g_file_system = NULL;
std::string g_predefines = ""; std::string g_predefines = "";
// More when PBR is used later
uint32_t g_mesh_texture_layer = 2;
uint32_t g_sampler_size = 256; uint32_t g_sampler_size = 256;
std::map<std::string, VkShaderModule> g_shaders; std::map<std::string, VkShaderModule> g_shaders;
@ -109,8 +113,11 @@ void GEVulkanShaderManager::init(GEVulkanDriver* vk)
std::ostringstream oss; std::ostringstream oss;
oss << "#version 450\n"; oss << "#version 450\n";
oss << "#define SAMPLER_SIZE " << g_sampler_size << "\n"; oss << "#define SAMPLER_SIZE " << g_sampler_size << "\n";
oss << "#define TOTAL_MESH_TEXTURE_LAYER " << g_mesh_texture_layer << "\n";
if (GEVulkanFeatures::supportsBindTexturesAtOnce()) if (GEVulkanFeatures::supportsBindTexturesAtOnce())
oss << "#define BIND_TEXTURES_AT_ONCE\n"; oss << "#define BIND_TEXTURES_AT_ONCE\n";
if (GEVulkanFeatures::supportsBindMeshTexturesAtOnce())
oss << "#define BIND_MESH_TEXTURES_AT_ONCE\n";
if (GEVulkanFeatures::supportsDifferentTexturePerDraw()) if (GEVulkanFeatures::supportsDifferentTexturePerDraw())
{ {
@ -222,6 +229,12 @@ unsigned GEVulkanShaderManager::getSamplerSize()
return g_sampler_size; return g_sampler_size;
} // getSamplerSize } // getSamplerSize
// ----------------------------------------------------------------------------
unsigned GEVulkanShaderManager::getMeshTextureLayer()
{
return g_mesh_texture_layer;
} // getMeshTextureLayer
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
VkShaderModule GEVulkanShaderManager::getShader(const std::string& filename) VkShaderModule GEVulkanShaderManager::getShader(const std::string& filename)
{ {

View File

@ -22,6 +22,8 @@ VkShaderModule getShader(const std::string& filename);
VkShaderModule loadShader(shaderc_shader_kind, const std::string&); VkShaderModule loadShader(shaderc_shader_kind, const std::string&);
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
unsigned getSamplerSize(); unsigned getSamplerSize();
// ----------------------------------------------------------------------------
unsigned getMeshTextureLayer();
}; // GEVulkanShaderManager }; // GEVulkanShaderManager
} }