diff --git a/dependencies/Common b/dependencies/Common index 809095ff..bff72db7 160000 --- a/dependencies/Common +++ b/dependencies/Common @@ -1 +1 @@ -Subproject commit 809095ff6de45e6654b8ac42fc4af80ccfbaa60d +Subproject commit bff72db7600acf91b88aa992f1e1d49e319b96b6 diff --git a/dependencies/GLSLCommon b/dependencies/GLSLCommon index dfdda003..e1491382 160000 --- a/dependencies/GLSLCommon +++ b/dependencies/GLSLCommon @@ -1 +1 @@ -Subproject commit dfdda00347afaa7ab45cb2e73893561e3e3b62b5 +Subproject commit e14913823adf6a0c35e69e60d7f8452e6afe20e6 diff --git a/include/sge-cpp/Material.hpp b/include/sge-cpp/Material.hpp index 292d7e8f..4b201953 100644 --- a/include/sge-cpp/Material.hpp +++ b/include/sge-cpp/Material.hpp @@ -4,7 +4,7 @@ #include /* for material_t* */ #include // for SGE::Texture reference type -#include /* for std::string */ +#include // std::string_view namespace SGE { @@ -17,24 +17,40 @@ namespace SGE public: template - void set(const std::string& name, T value) + void set(const std::string_view str, T value) noexcept { - debug_log_error("Setter for this type is not defined"); + static_assert(false, "Please specialize set<> for this type"); + } + template + T get(const std::string_view str) noexcept + { + static_assert(false, "Please specialize set<> for this type"); } }; + + // Specializations for Setters + template<> - void Material::set(const std::string& name, float value); + void Material::set(const std::string_view str, float value) noexcept; template<> - void Material::set(const std::string& name, vec2_t value); + void Material::set(const std::string_view str, vec2_t value) noexcept; template<> - void Material::set(const std::string& name, vec4_t value); + void Material::set(const std::string_view str, vec4_t value) noexcept; template<> - void Material::set(const std::string& name, s32 value); + void Material::set(const std::string_view str, s32 value) noexcept; + + template<> + void Material::set(const std::string_view str, u32 value) noexcept; + + template<> + void Material::set(const std::string_view str, Texture texture) noexcept; + + // Specializations for Getters template<> - void Material::set(const std::string& name, Texture texture); + Texture Material::get(const std::string_view str) noexcept; } diff --git a/include/sge/defines.h b/include/sge/defines.h index ecefb2eb..d4f47117 100644 --- a/include/sge/defines.h +++ b/include/sge/defines.h @@ -67,18 +67,20 @@ typedef struct memory_allocator_t memory_allocator_t; # define ELSE(x) # define PARAM_IF_DEBUG(x) , x # define debug_if(x) if(x) -# define debug_else else +# define debug_else(x) else { x } # define debug_else_if(x) else debug_if(x) #else # define IF_DEBUG_MODE(x) # define ELSE(x) x # define PARAM_IF_DEBUG(x) # define debug_if(x) -# define debug_else +# define debug_else(x) # define debug_else_if(x) #endif /* GLOBAL_DEBUG */ #define IF_DEBUG(x) IF_DEBUG_MODE(x) +#define DEBUG_IF(x) debug_if(x) +#define DEBUG_ELSE(x) debug_else(x) static CAN_BE_UNUSED_FUNCTION INLINE_IF_RELEASE_MODE u32 max(u32 v1, u32 v2) { return (v1 > v2) ? v1 : v2; } diff --git a/include/sge/internal/vulkan/vulkan_buffer.h b/include/sge/internal/vulkan/vulkan_buffer.h index 46231324..b38a588e 100644 --- a/include/sge/internal/vulkan/vulkan_buffer.h +++ b/include/sge/internal/vulkan/vulkan_buffer.h @@ -78,6 +78,7 @@ typedef struct vulkan_buffer_t }; vulkan_buffer_traits_t traits; }; + IF_DEBUG (bool dbg_is_mapped;) } vulkan_buffer_t; typedef vulkan_buffer_t* vulkan_buffer_ptr_t; diff --git a/include/sge/internal/vulkan/vulkan_material.h b/include/sge/internal/vulkan/vulkan_material.h index 695d1444..9c690767 100644 --- a/include/sge/internal/vulkan/vulkan_material.h +++ b/include/sge/internal/vulkan/vulkan_material.h @@ -53,8 +53,10 @@ typedef struct vulkan_material_field_handle_t typedef struct vulkan_uniform_resource_t { - bool has_buffer; - vulkan_buffer_t buffer; + /* this is created internally in the vulkan_material_t class */ + vulkan_buffer_t* buffer; + /* pointer to texture object is cached here so that it can be returned when vulkan_material_get_texture() is called */ + vulkan_texture_t* texture; u16 index; // index of this resource in the list of resouce descriptors of this material } vulkan_uniform_resource_t; @@ -124,7 +126,7 @@ SGE_API vec3_t vulkan_material_get_vec3H(vulkan_material_t* material, vulkan_mat SGE_API vec4_t vulkan_material_get_vec4H(vulkan_material_t* material, vulkan_material_field_handle_t handle); SGE_API mat2_t vulkan_material_get_mat2H(vulkan_material_t* material, vulkan_material_field_handle_t handle); SGE_API mat4_t vulkan_material_get_mat4H(vulkan_material_t* material, vulkan_material_field_handle_t handle); -SGE_API vulkan_texture_t* vulkan_material_get_texture2dH(vulkan_material_t* material, vulkan_material_field_handle_t handle); +SGE_API vulkan_texture_t* vulkan_material_get_textureH(vulkan_material_t* material, vulkan_material_field_handle_t handle); SGE_API float vulkan_material_get_float(vulkan_material_t* material, const char* name); SGE_API int vulkan_material_get_int(vulkan_material_t* material, const char* name); @@ -134,7 +136,7 @@ SGE_API vec3_t vulkan_material_get_vec3(vulkan_material_t* material, const char* SGE_API vec4_t vulkan_material_get_vec4(vulkan_material_t* material, const char* name); SGE_API mat2_t vulkan_material_get_mat2(vulkan_material_t* material, const char* name); SGE_API mat4_t vulkan_material_get_mat4(vulkan_material_t* material, const char* name); -SGE_API vulkan_texture_t* vulkan_material_get_texture2d(vulkan_material_t* material, const char* name); +SGE_API vulkan_texture_t* vulkan_material_get_texture(vulkan_material_t* material, const char* name); /* setters */ SGE_API void vulkan_material_set_push_floatH(vulkan_material_t* material, vulkan_material_field_handle_t handle, float value); diff --git a/include/sge/internal/vulkan/vulkan_texture.h b/include/sge/internal/vulkan/vulkan_texture.h index 8add2d02..3f17c6d5 100644 --- a/include/sge/internal/vulkan/vulkan_texture.h +++ b/include/sge/internal/vulkan/vulkan_texture.h @@ -198,14 +198,34 @@ SGE_API void vulkan_texture_set_usage_stage(vulkan_texture_t* texture, vulkan_te /* uploads the data to the GPU local memory */ SGE_API void vulkan_texture_upload_data(vulkan_texture_t* texture, u32 data_count, vulkan_texture_data_t* data); +static CAN_BE_UNUSED_FUNCTION INLINE_IF_RELEASE_MODE bool vulkan_texture_is_cube(vulkan_texture_t* texture) +{ + return HAS_FLAG(texture->type, VULKAN_TEXTURE_TYPE_CUBE); +} + +static CAN_BE_UNUSED_FUNCTION INLINE_IF_RELEASE_MODE bool vulkan_texture_is_3d(vulkan_texture_t* texture) +{ + return (texture->width > 1) && (texture->height > 1) && (texture->depth > 1); +} + +static CAN_BE_UNUSED_FUNCTION INLINE_IF_RELEASE_MODE bool vulkan_texture_is_2d(vulkan_texture_t* texture) +{ + return texture->depth == 1; +} + +static CAN_BE_UNUSED_FUNCTION INLINE_IF_RELEASE_MODE bool vulkan_texture_is_1d(vulkan_texture_t* texture) +{ + return (texture->height == 1) && (texture->depth == 1); +} + static CAN_BE_UNUSED_FUNCTION INLINE_IF_RELEASE_MODE vulkan_image_view_t* vulkan_texture_get_image_views(vulkan_texture_t* texture) { - return ((texture->type & VULKAN_TEXTURE_TYPE_CUBE) == 0) ? &texture->image_view : texture->image_views; + return vulkan_texture_is_cube(texture) ? texture->image_views : &texture->image_view; } static CAN_BE_UNUSED_FUNCTION INLINE_IF_RELEASE_MODE u32 vulkan_texture_get_image_view_count(vulkan_texture_t* texture) { - return ((texture->type & VULKAN_TEXTURE_TYPE_CUBE) == 0) ? 1 : texture->image_view_count; + return vulkan_texture_is_cube(texture) ? texture->image_view_count : 1; } static CAN_BE_UNUSED_FUNCTION INLINE_IF_RELEASE_MODE vulkan_texture_usage_stage_t vulkan_texture_get_usage_stage(vulkan_texture_t* texture) { return texture->current_stage; } diff --git a/include/sge/material.h b/include/sge/material.h index 5bc699dd..896fb894 100644 --- a/include/sge/material.h +++ b/include/sge/material.h @@ -140,7 +140,7 @@ SGE_API vec3_t material_get_vec3H(material_t* material, material_field_handle_t SGE_API vec4_t material_get_vec4H(material_t* material, material_field_handle_t handle); SGE_API mat2_t material_get_mat2H(material_t* material, material_field_handle_t handle); SGE_API mat4_t material_get_mat4H(material_t* material, material_field_handle_t handle); -SGE_API texture_t* material_get_texture2dH(material_t* material, material_field_handle_t handle); +SGE_API texture_t* material_get_textureH(material_t* material, material_field_handle_t handle); SGE_API float material_get_float(material_t* material, const char* name); SGE_API int material_get_int(material_t* material, const char* name); @@ -150,6 +150,6 @@ SGE_API vec3_t material_get_vec3(material_t* material, const char* name); SGE_API vec4_t material_get_vec4(material_t* material, const char* name); SGE_API mat2_t material_get_mat2(material_t* material, const char* name); SGE_API mat4_t material_get_mat4(material_t* material, const char* name); -SGE_API texture_t* material_get_texture2d(material_t* material, const char* name); +SGE_API texture_t* material_get_texture(material_t* material, const char* name); END_CPP_COMPATIBLE diff --git a/include/sge/pygen/shaders.h b/include/sge/pygen/shaders.h index dd6394c6..9dd8eb59 100644 --- a/include/sge/pygen/shaders.h +++ b/include/sge/pygen/shaders.h @@ -3,7 +3,7 @@ /***This is computer generated file - Do not modify it***/ /* This is auto generated header file (by pygen/gen_shaders.py python script). Do not modify it directly. - * Time & Date (yy/mm/yyy) of Generation: 1h:48m:8s, 20/9/2024 + * Time & Date (yy/mm/yyy) of Generation: 11h:6m:1s, 12/12/2024 */ #pragma once diff --git a/include/sge/tests/material_get_set.h b/include/sge/tests/material_get_set.h new file mode 100644 index 00000000..3b215e9c --- /dev/null +++ b/include/sge/tests/material_get_set.h @@ -0,0 +1,36 @@ +/* + ***This is computer generated notice - Do not modify it*** + + VulkanRenderer (inclusive of its dependencies and subprojects + such as toolchains written by the same author) is a software to render + 2D & 3D geometries by writing C/C++ code and shaders. + + File: TID-48.case5.h is a part of VulkanRenderer + + Copyright (C) 2021 - 2024 Author: Ravi Prakash Singh + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +#pragma once + + +#include + +BEGIN_CPP_COMPATIBLE + +TEST_DECLARE(MATERIAL_GET_SET); + +END_CPP_COMPATIBLE diff --git a/shaders/test_shaders/material_get_set.v3dshader b/shaders/test_shaders/material_get_set.v3dshader new file mode 100644 index 00000000..36558285 --- /dev/null +++ b/shaders/test_shaders/material_get_set.v3dshader @@ -0,0 +1,128 @@ +/* + ***This is computer generated notice - Do not modify it*** + + VulkanRenderer (inclusive of its dependencies and subprojects + such as toolchains written by the same author) is a software to render + 2D & 3D geometries by writing C/C++ code and shaders. + + File: texture_sample.v3dshader is a part of VulkanRenderer + + Copyright (C) 2021 - 2024 Author: Ravi Prakash Singh + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +#sl version 2023 +#sb version 2023 + +Shader +{ + Properties + { + [Stage(fragment)] + [Set(material_set, texture0)] + uniform sampler2D albedo; + + [Stage(fragment, vertex)] + [Set(material_set, material_properties)] + uniform Parameters + { + vec4 color; + float testValue; + int testValue2; + vec3 testValue3; + } parameters; + } + + Layout + { + [Rate(per_vertex)] + [MeshLayout(sge_optimal)] + [Attribute(position)] + vec3 position; + + [Rate(per_vertex)] + [MeshLayout(sge_optimal)] + [Attribute(texcoord)] + vec2 texcoord; + } + + RenderPass + { + SubPass + { + [NoParse] + GraphicsPipeline + { + colorBlend + { + attachment + { + blendenable = true + } + } + + depthStencil + { + depthWriteEnable = true, + depthTestEnable = true + } + } + + [NoParse] + GLSL + { + #stage vertex + + #version 450 + + #include + + layout(SGE_UNIFORM_BUFFER_LAYOUT, set = CAMERA_SET, binding = CAMERA_PROPERTIES_BINDING) uniform CameraInfo cameraInfo; + layout(SGE_UNIFORM_BUFFER_LAYOUT, set = OBJECT_SET, binding = TRANSFORM_BINDING) uniform ObjectInfo objectInfo; + + layout(location = POSITION_LOCATION) in vec3 position; + layout(location = TEXCOORD_LOCATION) in vec2 texcoord; + + layout(location = 0) out vec2 _texcoord; + + void main() + { + vec4 clipPos = cameraInfo.projection * cameraInfo.view * objectInfo.transform * vec4(position, 1); + clipPos.y = -clipPos.y; + gl_Position = clipPos; + _texcoord = texcoord; + } + + #stage fragment + + #version 450 + + #include + + layout(set = MATERIAL_SET, binding = TEXTURE_BINDING0) uniform sampler2D albedo; + + layout(location = 0) in vec2 _texcoord; + layout(location = 0) out vec4 color; + + void main() + { + color = texture(albedo, _texcoord).rgba; + } + + } + } + } +} diff --git a/source/sge-cpp/Material.cpp b/source/sge-cpp/Material.cpp index 336538c7..ec07e0b3 100644 --- a/source/sge-cpp/Material.cpp +++ b/source/sge-cpp/Material.cpp @@ -3,32 +3,44 @@ namespace SGE { template<> - void Material::set(const std::string& name, float value) + void Material::set(const std::string_view name, float value) noexcept { - material_set_float(m_handle, name.c_str(), value); + material_set_float(m_handle, name.data(), value); } template<> - void Material::set(const std::string& name, vec2_t value) + void Material::set(const std::string_view name, vec2_t value) noexcept { - material_set_vec2(m_handle, name.c_str(), value); + material_set_vec2(m_handle, name.data(), value); } template<> - void Material::set(const std::string& name, vec4_t value) + void Material::set(const std::string_view name, vec4_t value) noexcept { - material_set_vec4(m_handle, name.c_str(), value); + material_set_vec4(m_handle, name.data(), value); } template<> - void Material::set(const std::string& name, s32 value) + void Material::set(const std::string_view name, s32 value) noexcept { - material_set_int(m_handle, name.c_str(), value); + material_set_int(m_handle, name.data(), value); } template<> - void Material::set(const std::string& name, Texture texture) + void Material::set(const std::string_view name, u32 value) noexcept { - material_set_texture(m_handle, name.c_str(), static_cast(texture)); + material_set_uint(m_handle, name.data(), value); + } + + template<> + void Material::set(const std::string_view name, Texture texture) noexcept + { + material_set_texture(m_handle, name.data(), static_cast(texture)); + } + + template<> + Texture Material::get(const std::string_view name) noexcept + { + return Texture { material_get_texture(m_handle, name.data()) }; } } diff --git a/source/sge/material.c b/source/sge/material.c index c85dc6eb..053c51ae 100644 --- a/source/sge/material.c +++ b/source/sge/material.c @@ -308,9 +308,9 @@ SGE_API mat4_t material_get_mat4H(material_t* material, material_field_handle_t return vulkan_material_get_mat4H(material, handle); } -SGE_API texture_t* material_get_texture2dH(material_t* material, material_field_handle_t handle) +SGE_API texture_t* material_get_textureH(material_t* material, material_field_handle_t handle) { - return vulkan_material_get_texture2dH(material, handle); + return vulkan_material_get_textureH(material, handle); } /* functions accepting strings */ @@ -399,7 +399,7 @@ SGE_API mat4_t material_get_mat4(material_t* material, const char* name) return vulkan_material_get_mat4(material, name); } -SGE_API texture_t* material_get_texture2d(material_t* material, const char* name) +SGE_API texture_t* material_get_texture(material_t* material, const char* name) { - return vulkan_material_get_texture2d(material, name); + return vulkan_material_get_texture(material, name); } diff --git a/source/sge/struct_descriptor.c b/source/sge/struct_descriptor.c index 19b190f4..2a153c94 100644 --- a/source/sge/struct_descriptor.c +++ b/source/sge/struct_descriptor.c @@ -206,10 +206,7 @@ SGE_API struct_field_handle_t struct_descriptor_get_field_handle(const struct_de AUTO field = get_field(CAST_TO(struct_descriptor_t*, descriptor), name, (ptr == NULL) ? strlen(name) : (ptr - name)); if(field == NULL) - { - debug_log_warning("Returning STRUCT_FIELD_INVALID_HANDLE, name: %s", name); return STRUCT_FIELD_INVALID_HANDLE; - } /* if this field is not a record then just return it's offset and size */ if(field->record == NULL) @@ -274,218 +271,194 @@ SGE_API u32 struct_descriptor_get_array_size(struct_descriptor_t* descriptor, co return field->array_size; } -#ifndef GLOBAL_DEBUG -# define check_precondition(descriptor, handle) -#else - static void check_precondition(struct_descriptor_t* descriptor, struct_field_handle_t handle); -#endif - #define cpy_data_from(descriptor, handle, data) __cpy_data_from(descriptor, handle, data) #define cpy_data_to(descriptor, handle, data) __cpy_data_to(descriptor, handle, data) static inline void __cpy_data_from(struct_descriptor_t* descriptor, struct_field_handle_t handle, const void* const data) { /* the struct_descriptor_t object must be mapped to some memory first */ - _debug_assert__(descriptor->ptr != NULL); - memcopyv(descriptor->ptr + BIT64_UNPACK32(handle, 1), data, u8, BIT64_UNPACK32(handle, 0)); + if(!descriptor->ptr) + { + debug_log_error("Unhandled error, Failed to copy data from source, Struct descriptor isn't mapped"); + return; + } + if(handle != STRUCT_FIELD_INVALID_HANDLE) + memcopyv(descriptor->ptr + BIT64_UNPACK32(handle, 1), data, u8, BIT64_UNPACK32(handle, 0)); + else + debug_log_error("Unhandled error, Failed to copy data from source, Struct field handle is invalid"); } static inline void __cpy_data_to(struct_descriptor_t* descriptor, struct_field_handle_t handle, void* const data) { /* the struct_descriptor_t object must be mapped to some memory first */ - _debug_assert__(descriptor->ptr != NULL); - memcopyv(data, descriptor->ptr + BIT64_UNPACK32(handle, 1), u8, BIT64_UNPACK32(handle, 0)); + if(!descriptor->ptr) + { + debug_log_error("Unhandled error, Failed to copy data at destination, Struct descriptor isn't mapped"); + return; + } + if(handle != STRUCT_FIELD_INVALID_HANDLE) + memcopyv(data, descriptor->ptr + BIT64_UNPACK32(handle, 1), u8, BIT64_UNPACK32(handle, 0)); + else + debug_log_error("Unhandled error, Failed to copy data at destination, Struct field handle is invalid"); } SGE_API void struct_descriptor_set_value(struct_descriptor_t* descriptor, struct_field_handle_t handle, const void* const in) { - check_precondition(descriptor, handle); cpy_data_from(descriptor, handle, in); } SGE_API void struct_descriptor_set_float(struct_descriptor_t* descriptor, struct_field_handle_t handle, const float* const in) { - check_precondition(descriptor, handle); __cpy_data_from(descriptor, handle, in); } SGE_API void struct_descriptor_set_int(struct_descriptor_t* descriptor, struct_field_handle_t handle, const int* const in) { - check_precondition(descriptor, handle); __cpy_data_from(descriptor, handle, in); } SGE_API void struct_descriptor_set_uint(struct_descriptor_t* descriptor, struct_field_handle_t handle, const uint* const in) { - check_precondition(descriptor, handle); __cpy_data_from(descriptor, handle, in); } SGE_API void struct_descriptor_set_vec4(struct_descriptor_t* descriptor, struct_field_handle_t handle, const float* const in) { - check_precondition(descriptor, handle); __cpy_data_from(descriptor, handle, in); } SGE_API void struct_descriptor_set_vec3(struct_descriptor_t* descriptor, struct_field_handle_t handle, const float* const in) { - check_precondition(descriptor, handle); __cpy_data_from(descriptor, handle, in); } SGE_API void struct_descriptor_set_vec2(struct_descriptor_t* descriptor, struct_field_handle_t handle, const float* const in) { - check_precondition(descriptor, handle); __cpy_data_from(descriptor, handle, in); } SGE_API void struct_descriptor_set_ivec4(struct_descriptor_t* descriptor, struct_field_handle_t handle, const int* const in) { - check_precondition(descriptor, handle); __cpy_data_from(descriptor, handle, in); } SGE_API void struct_descriptor_set_ivec3(struct_descriptor_t* descriptor, struct_field_handle_t handle, const int* const in) { - check_precondition(descriptor, handle); __cpy_data_from(descriptor, handle, in); } SGE_API void struct_descriptor_set_ivec2(struct_descriptor_t* descriptor, struct_field_handle_t handle, const int* const in) { - check_precondition(descriptor, handle); __cpy_data_from(descriptor, handle, in); } SGE_API void struct_descriptor_set_uvec4(struct_descriptor_t* descriptor, struct_field_handle_t handle, const uint* const in) { - check_precondition(descriptor, handle); __cpy_data_from(descriptor, handle, in); } SGE_API void struct_descriptor_set_uvec3(struct_descriptor_t* descriptor, struct_field_handle_t handle, const uint* const in) { - check_precondition(descriptor, handle); __cpy_data_from(descriptor, handle, in); } SGE_API void struct_descriptor_set_uvec2(struct_descriptor_t* descriptor, struct_field_handle_t handle, const uint* const in) { - check_precondition(descriptor, handle); __cpy_data_from(descriptor, handle, in); } SGE_API void struct_descriptor_set_mat4(struct_descriptor_t* descriptor, struct_field_handle_t handle, const float* const in) { - check_precondition(descriptor, handle); __cpy_data_from(descriptor, handle, in); } SGE_API void struct_descriptor_set_mat3(struct_descriptor_t* descriptor, struct_field_handle_t handle, const float* const in) { - check_precondition(descriptor, handle); __cpy_data_from(descriptor, handle, in); } SGE_API void struct_descriptor_set_mat2(struct_descriptor_t* descriptor, struct_field_handle_t handle, const float* const in) { - check_precondition(descriptor, handle); __cpy_data_from(descriptor, handle, in); } SGE_API void struct_descriptor_get_value(struct_descriptor_t* descriptor, struct_field_handle_t handle, void* const out) { - check_precondition(descriptor, handle); cpy_data_to(descriptor, handle, out); } SGE_API void struct_descriptor_get_float(struct_descriptor_t* descriptor, struct_field_handle_t handle, float* const out) { - check_precondition(descriptor, handle); __cpy_data_to(descriptor, handle, out); } SGE_API void struct_descriptor_get_int(struct_descriptor_t* descriptor, struct_field_handle_t handle, int* const out) { - check_precondition(descriptor, handle); __cpy_data_to(descriptor, handle, out); } SGE_API void struct_descriptor_get_uint(struct_descriptor_t* descriptor, struct_field_handle_t handle, uint* const out) { - check_precondition(descriptor, handle); __cpy_data_to(descriptor, handle, out); } SGE_API void struct_descriptor_get_vec4(struct_descriptor_t* descriptor, struct_field_handle_t handle, float* const out) { - check_precondition(descriptor, handle); __cpy_data_to(descriptor, handle, out); } SGE_API void struct_descriptor_get_vec3(struct_descriptor_t* descriptor, struct_field_handle_t handle, float* const out) { - check_precondition(descriptor, handle); __cpy_data_to(descriptor, handle, out); } SGE_API void struct_descriptor_get_vec2(struct_descriptor_t* descriptor, struct_field_handle_t handle, float* const out) { - check_precondition(descriptor, handle); __cpy_data_to(descriptor, handle, out); } SGE_API void struct_descriptor_get_ivec4(struct_descriptor_t* descriptor, struct_field_handle_t handle, int* const out) { - check_precondition(descriptor, handle); __cpy_data_to(descriptor, handle, out); } SGE_API void struct_descriptor_get_ivec3(struct_descriptor_t* descriptor, struct_field_handle_t handle, int* const out) { - check_precondition(descriptor, handle); __cpy_data_to(descriptor, handle, out); } SGE_API void struct_descriptor_get_ivec2(struct_descriptor_t* descriptor, struct_field_handle_t handle, int* const out) { - check_precondition(descriptor, handle); __cpy_data_to(descriptor, handle, out); } SGE_API void struct_descriptor_get_uvec4(struct_descriptor_t* descriptor, struct_field_handle_t handle, uint* const out) { - check_precondition(descriptor, handle); __cpy_data_to(descriptor, handle, out); } SGE_API void struct_descriptor_get_uvec3(struct_descriptor_t* descriptor, struct_field_handle_t handle, uint* const out) { - check_precondition(descriptor, handle); __cpy_data_to(descriptor, handle, out); } SGE_API void struct_descriptor_get_uvec2(struct_descriptor_t* descriptor, struct_field_handle_t handle, uint* const out) { - check_precondition(descriptor, handle); __cpy_data_to(descriptor, handle, out); } SGE_API void struct_descriptor_get_mat4(struct_descriptor_t* descriptor, struct_field_handle_t handle, float* const out) { - check_precondition(descriptor, handle); __cpy_data_to(descriptor, handle, out); } SGE_API void struct_descriptor_get_mat3(struct_descriptor_t* descriptor, struct_field_handle_t handle, float* const out) { - check_precondition(descriptor, handle); __cpy_data_to(descriptor, handle, out); } SGE_API void struct_descriptor_get_mat2(struct_descriptor_t* descriptor, struct_field_handle_t handle, float* const out) { - check_precondition(descriptor, handle); __cpy_data_to(descriptor, handle, out); } @@ -646,15 +619,4 @@ SGE_API struct_descriptor_t struct_descriptor_clone(struct_descriptor_t* descrip OBJECT_INIT(&clone, OBJECT_TYPE_STRUCT_DESCRIPTOR, OBJECT_NATIONALITY_EXTERNAL); _struct_descriptor_clone(descriptor, &clone); return clone; -} - - -#ifdef GLOBAL_DEBUG -static void check_precondition(struct_descriptor_t* descriptor, struct_field_handle_t handle) -{ - _debug_assert__(descriptor != NULL); - _debug_assert__(descriptor->ptr != NULL); - _debug_assert__(descriptor->fields != NULL); - // _debug_assert__(handle < descriptor->field_count); -} -#endif +} \ No newline at end of file diff --git a/source/sge/vulkan/vulkan_buffer.c b/source/sge/vulkan/vulkan_buffer.c index ef539685..904867df 100644 --- a/source/sge/vulkan/vulkan_buffer.c +++ b/source/sge/vulkan/vulkan_buffer.c @@ -122,10 +122,15 @@ SGE_API void* vulkan_buffer_map(vulkan_buffer_t* buffer) _debug_assert_wrn__(buffer->size != 0); void* ptr; vkMapMemory(buffer->renderer->logical_device->vo_handle, buffer->vo_memory, 0, buffer->size, 0, &ptr); + IF_DEBUG(buffer->dbg_is_mapped = true); return ptr; } SGE_API void vulkan_buffer_unmap(vulkan_buffer_t* buffer) { - vkUnmapMemory(buffer->renderer->logical_device->vo_handle, buffer->vo_memory); + DEBUG_IF(buffer->dbg_is_mapped) + vkUnmapMemory(buffer->renderer->logical_device->vo_handle, buffer->vo_memory); + DEBUG_ELSE( + debug_log_error("Failed to unmap vulkan buffer as it hasn't already been mapped"); + ); } diff --git a/source/sge/vulkan/vulkan_material.c b/source/sge/vulkan/vulkan_material.c index e2b1c31c..32e1947e 100644 --- a/source/sge/vulkan/vulkan_material.c +++ b/source/sge/vulkan/vulkan_material.c @@ -42,6 +42,20 @@ SGE_API vulkan_material_t* vulkan_material_new(memory_allocator_t* allocator) return material; } +static bool is_sampler_type(glsl_type_t type) +{ + switch(type) + { + case GLSL_TYPE_SAMPLER_1D: + case GLSL_TYPE_SAMPLER_2D: + case GLSL_TYPE_SAMPLER_3D: + case GLSL_TYPE_SAMPLER_CUBE: + return true; + default: + return false; + } +} + static u16 calculate_uniform_resource_count(vulkan_shader_t* shader) { _debug_assert__(shader != NULL); @@ -49,11 +63,38 @@ static u16 calculate_uniform_resource_count(vulkan_shader_t* shader) u16 count = shader->material_set_binding_count; u16 uniform_count = 0; for(u16 i = 0; i < count; i++) - if(shader->material_set_bindings[i].handle.type == GLSL_TYPE_UNIFORM_BUFFER) + { + AUTO type = shader->material_set_bindings[i].handle.type; + if((type == GLSL_TYPE_UNIFORM_BUFFER) || is_sampler_type(type)) ++uniform_count; + } return uniform_count; } +/* types of bindings which define a material, + * for example, buffer objects hold data about the material's variables + * and textures hold data about the materials' appearance + * With that concept, we do not classify subpassInput bindings as material resource. + * A material resource is something which can be set by calling one of the material setters. + + * There can be other such types but for now we only support uniform samplers, push constants, storage buffers, and uniform buffers */ +static bool is_material_resource(vulkan_shader_resource_description_t* binding) +{ + switch(binding->handle.type) + { + case GLSL_TYPE_SAMPLER_1D: + case GLSL_TYPE_SAMPLER_2D: + case GLSL_TYPE_SAMPLER_3D: + case GLSL_TYPE_SAMPLER_CUBE: + case GLSL_TYPE_PUSH_CONSTANT: + case GLSL_TYPE_UNIFORM_BUFFER: + case GLSL_TYPE_STORAGE_BUFFER: + return true; + default: + return false; + } +} + static void setup_material_resources(vulkan_material_t* material) { _debug_assert__(material->shader != NULL); @@ -66,37 +107,32 @@ static void setup_material_resources(vulkan_material_t* material) for(u16 i = 0, j = 0; i < material->shader->material_set_binding_count; i++) { vulkan_shader_resource_description_t* binding = &bindings[i]; - if(vulkan_shader_resource_description_is_attribute(binding) || binding->is_opaque || binding->is_push_constant) - continue; - - _debug_assert__(j < count); - - vulkan_uniform_resource_t* resource = &uniform_resources[j]; - j++; - if(binding->handle.type == GLSL_TYPE_UNIFORM_BUFFER) + if(is_material_resource(binding)) { + _debug_assert__(j < count); + + vulkan_uniform_resource_t* resource = &uniform_resources[j]; resource->index = i; - /* if this uniform interface block has a fixed size then create vulkan uniform buffer for it */ - if(!struct_descriptor_is_variable_sized(&binding->handle)) + if(binding->handle.type == GLSL_TYPE_UNIFORM_BUFFER) { - u32 size = struct_descriptor_sizeof(&binding->handle); - vulkan_buffer_create_info_t create_info = + /* if this uniform interface block has a fixed size then create vulkan uniform buffer for it */ + if(!struct_descriptor_is_variable_sized(&binding->handle)) { - .size = size, - .vo_usage_flags = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - .vo_memory_property_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT - }; - VULKAN_OBJECT_INIT(&resource->buffer, VULKAN_OBJECT_TYPE_BUFFER, VULKAN_OBJECT_NATIONALITY_EXTERNAL); - vulkan_buffer_create_no_alloc(material->renderer, &create_info, &resource->buffer); - resource->has_buffer = true; - vulkan_descriptor_set_write_uniform_buffer(&material->material_set, binding->binding_number, &resource->buffer); + u32 size = struct_descriptor_sizeof(&binding->handle); + vulkan_buffer_create_info_t create_info = + { + .size = size, + .vo_usage_flags = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + .vo_memory_property_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT + }; + resource->buffer = vulkan_buffer_create(material->renderer, &create_info); + vulkan_descriptor_set_write_uniform_buffer(&material->material_set, binding->binding_number, resource->buffer); + } + /* otherwise don't create vulkan uniform buffer for it */ } - /* otherwise don't create vulkan uniform buffer for it */ - } - else - { - resource->has_buffer = false; - resource->index = 0xFFFF; + else + resource->index = 0xFFFF; + j++; } } material->uniform_resources = uniform_resources; @@ -135,16 +171,16 @@ SGE_API void vulkan_material_destroy(vulkan_material_t* material) { vulkan_descriptor_set_destroy(&material->material_set); for(u16 i = 0; i < material->uniform_resource_count; i++) - if(material->uniform_resources[i].has_buffer) - vulkan_buffer_destroy(&material->uniform_resources[i].buffer); + if(material->uniform_resources[i].buffer) + vulkan_buffer_destroy(material->uniform_resources[i].buffer); } SGE_API void vulkan_material_release_resources(vulkan_material_t* material) { vulkan_descriptor_set_release_resources(&material->material_set); for(u16 i = 0; i < material->uniform_resource_count; i++) - if(material->uniform_resources[i].index != 0xFFFF) - vulkan_buffer_release_resources(&material->uniform_resources[i].buffer); + if(material->uniform_resources[i].buffer) + vulkan_buffer_release_resources(material->uniform_resources[i].buffer); if(material->uniform_resource_count != 0) memory_allocator_dealloc(material->renderer->allocator, material->uniform_resources); if(VULKAN_OBJECT_IS_INTERNAL(material)) @@ -386,17 +422,25 @@ SGE_API mat4_t vulkan_material_get_push_mat4(vulkan_material_t* material, const static void unmap_descriptor(vulkan_material_t* material, vulkan_material_field_handle_t handle) { - vulkan_buffer_t* buffer = &(material->uniform_resources[handle.uniform_index].buffer); struct_descriptor_t* descriptor = &(material->shader->material_set_bindings[handle.index].handle); - struct_descriptor_unmap(descriptor); - vulkan_buffer_unmap(buffer); + vulkan_buffer_t* buffer = material->uniform_resources[handle.uniform_index].buffer; + if(buffer) + { + struct_descriptor_unmap(descriptor); + vulkan_buffer_unmap(buffer); + } + else + debug_log_error("Failed to unmap struct descriptor as the field handle doesn't point to a valid to a valid vulkan buffer"); } static struct_descriptor_t* map_descriptor(vulkan_material_t* material, vulkan_material_field_handle_t handle) { - vulkan_buffer_t* buffer = &(material->uniform_resources[handle.uniform_index].buffer); struct_descriptor_t* descriptor = &(material->shader->material_set_bindings[handle.index].handle); - struct_descriptor_map(descriptor, vulkan_buffer_map(buffer)); + vulkan_buffer_t* buffer = material->uniform_resources[handle.uniform_index].buffer; + if(buffer) + struct_descriptor_map(descriptor, vulkan_buffer_map(buffer)); + else + debug_log_error("Failed to map struct descriptor to vulkan buffer as the field handle doesn't point to valid vulkan buffer"); return descriptor; } @@ -470,8 +514,50 @@ SGE_API void vulkan_material_set_textureH(vulkan_material_t* material, vulkan_ma { _debug_assert__(handle.index < material->shader->material_set_binding_count); vulkan_shader_resource_description_t descriptor = material->shader->material_set_bindings[handle.index]; + AUTO type = descriptor.handle.type; + if((type != GLSL_TYPE_SAMPLER_2D) && (type != GLSL_TYPE_SAMPLER_3D) && (type != GLSL_TYPE_SAMPLER_CUBE)) + { + debug_log_error("You're trying to write a texture to a non-texture type descriptor"); + return; + } + else + { + switch(type) + { + case GLSL_TYPE_SAMPLER_CUBE: + if(!vulkan_texture_is_cube(texture)) + { + debug_log_error("You're trying to write a non-cube texture to a descriptor of type sampler cube"); + return; + } + break; + case GLSL_TYPE_SAMPLER_3D: + if(!vulkan_texture_is_3d(texture)) + { + debug_log_error("You're trying to write a non-3d texture to a descriptor of type sampler 3D"); + return; + } + break; + case GLSL_TYPE_SAMPLER_2D: + if(!vulkan_texture_is_2d(texture)) + { + debug_log_error("You're trying to write a non-2d texture to a descriptor of type sampler 2D"); + return; + } + break; + case GLSL_TYPE_SAMPLER_1D: + if(!vulkan_texture_is_1d(texture)) + { + debug_log_fetal_error("You're tyring to write an invalid texture to a descriptor of type sampler 1D as none of the samplerCube, sampler3D, sampler2D, or sampler1D match"); + return; + } + break; + default: break; + } + } // _debug_assert__(descriptor.set_number < 1); //for now we are just using one descriptor set and multiple bindings vulkan_descriptor_set_write_texture(&material->material_set, descriptor.binding_number, texture); + material->uniform_resources[handle.uniform_index].texture = texture; } SGE_API float vulkan_material_get_floatH(vulkan_material_t* material, vulkan_material_field_handle_t handle) @@ -530,10 +616,11 @@ SGE_API mat4_t vulkan_material_get_mat4H(vulkan_material_t* material, vulkan_mat return value; } -SGE_API vulkan_texture_t* vulkan_material_get_texture2dH(vulkan_material_t* material, vulkan_material_field_handle_t handle) +SGE_API vulkan_texture_t* vulkan_material_get_textureH(vulkan_material_t* material, vulkan_material_field_handle_t handle) { - LOG_WRN("material_get_texture2dH isn't defined, for now it will return NULL\n"); - return NULL; + _debug_assert__(handle.index < material->shader->material_set_binding_count); + _com_assert(handle.uniform_index < material->uniform_resource_count); + return material->uniform_resources[handle.uniform_index].texture; } /* functions accepting strings */ @@ -637,9 +724,9 @@ SGE_API mat4_t vulkan_material_get_mat4(vulkan_material_t* material, const char* return vulkan_material_get_mat4H(material, vulkan_material_get_field_handle(material, name)); } -SGE_API vulkan_texture_t* vulkan_material_get_texture2d(vulkan_material_t* material, const char* name) +SGE_API vulkan_texture_t* vulkan_material_get_texture(vulkan_material_t* material, const char* name) { - return vulkan_material_get_texture2dH(material, vulkan_material_get_field_handle(material, name)); + return vulkan_material_get_textureH(material, vulkan_material_get_field_handle(material, name)); } /* returns true if 'name' has anything after '.', called field, otherwise returns false */ @@ -763,9 +850,8 @@ SGE_API void vulkan_material_set_buffer(vulkan_material_t* material, const char* .vo_usage_flags = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, .vo_memory_property_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT }; - vulkan_buffer_create_no_alloc(material->renderer, &create_info, &uniform->buffer); - buffer = &uniform->buffer; - uniform->has_buffer = true; + uniform->buffer = vulkan_buffer_create(material->renderer, &create_info); + buffer = uniform->buffer; } /* write the descriptor */ diff --git a/source/test.c b/source/test.c index 026186e1..ffd8f5bb 100644 --- a/source/test.c +++ b/source/test.c @@ -82,6 +82,8 @@ #include +#include + SGE_API test_t* test_new(memory_allocator_t* allocator) { test_t* test = memory_allocator_alloc_obj(allocator, MEMORY_ALLOCATION_TYPE_OBJ_TEST, test_t); @@ -137,6 +139,7 @@ SGE_API test_t* test_create(memory_allocator_t* allocator, const char* name) ELSE_IF(TRANSPARENT_QUEUE); ELSE_IF(SHADER_CACHE); ELSE_IF(MULTI_BUFFER); + ELSE_IF(MATERIAL_GET_SET); else { printf ( @@ -181,6 +184,7 @@ SGE_API test_t* test_create(memory_allocator_t* allocator, const char* name) "\tTRANSPARENT_QUEUE\n" "\tSHADER_CACHE\n" "\tMULTI_BUFFER\n" + "\tMATERIAL_GET_SET\n" ); exit(0); } diff --git a/source/tests/material_get_set.c b/source/tests/material_get_set.c new file mode 100644 index 00000000..0ab3c78c --- /dev/null +++ b/source/tests/material_get_set.c @@ -0,0 +1,164 @@ +/* + ***This is computer generated notice - Do not modify it*** + + VulkanRenderer (inclusive of its dependencies and subprojects + such as toolchains written by the same author) is a software to render + 2D & 3D geometries by writing C/C++ code and shaders. + + File: texture_sampling.c is a part of VulkanRenderer + + Copyright (C) 2021 - 2024 Author: Ravi Prakash Singh + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +/* + test id: MATERIAL_GET_SET + Tests the following: + material_set_texture() + material_get_texture() + */ + + +#include + +#define SGE_INCLUDE_EVERYTHING_INTERNAL +#define SGE_INCLUDE_MATH +#define SGE_INCLUDE_3D_MESH_RENDER_SYSTEM +#define SGE_INCLUDE_3D_LIGHT_SYSTEM +#define SGE_INCLUDE_CORE +#include + +TEST_DATA(MATERIAL_GET_SET) +{ + render_scene_t* scene; + + camera_t* camera; + + light_t* light; + material_t* material; + mesh_t* mesh; + render_object_t* render_object; + float angle; + float angular_speed; + + texture_t* texture; +}; + +SETUP_TEST(MATERIAL_GET_SET); + +TEST_ON_SGE_INITIALIZE(MATERIAL_GET_SET) +{ + return (renderer_initialization_data_t) + { + .window_name = "MATERIAL GET SET", + .window_width = 800, + .window_height = 800, + .is_resizable = true, + .is_fullscreen = false + }; +} + +TEST_ON_INITIALIZE(MATERIAL_GET_SET) +{ + AUTO camera_system = renderer_get_camera_system(renderer); + AUTO slib = renderer_get_shader_library(renderer); + AUTO mlib = renderer_get_material_library(renderer); + + /* create camera */ + this->camera = camera_system_getH(camera_system, + camera_system_create_camera(camera_system, CAMERA_PROJECTION_TYPE_PERSPECTIVE)); + camera_set_clear(this->camera, COLOR_GREEN, 1.0f); + camera_set_active(this->camera, true); + + /* create render scene */ + this->scene = render_scene_create_from_mask(renderer, BIT64(RENDER_QUEUE_TYPE_GEOMETRY)); + /* add the camera into the render scene */ + render_scene_add_camera(this->scene, this->camera); + + this->light = light_create(renderer, LIGHT_TYPE_DIRECTIONAL); + render_scene_add_light(this->scene, this->light); + + this->material = material_library_getH(mlib, + material_library_create_materialH(mlib, + shader_library_load_shader(slib, + "shaders/test_shaders/material_get_set.sb"), "MyMaterial")); + + this->texture = texture_load(renderer, TEXTURE_TYPE_ALBEDO, "textures/Smile.bmp"); + + material_set_texture(this->material, "albedo", this->texture); + + /* this should pass */ + _com_assert(material_get_texture(this->material, "albedo") == this->texture); + + material_set_float(this->material, "parameters.testValue", 4.56f); + /* this should pass */ + _com_assert(material_get_float(this->material, "parameters.testValue") == 4.56f); + + material_set_int(this->material, "parameters.testValue2", 455); + /* this should pass */ + _com_assert(material_get_int(this->material, "parameters.testValue2") == 455); + /* this should pass */ + _com_assert(material_get_float(this->material, "parameters.testValue") == 4.56f); + + material_set_vec3(this->material, "parameters.testValue3", vec3(4, 5, 6)); + /* this should pass */ + _com_assert(vec3_is_equal(material_get_vec3(this->material, "parameters.testValue3"), vec3(4, 5, 6))); + /* this should pass */ + _com_assert(material_get_int(this->material, "parameters.testValue2") == 455); + /* this should pass */ + _com_assert(material_get_float(this->material, "parameters.testValue") == 4.56f); + + /* error is expected here */ + material_set_texture(this->material, "parameters.testValue2", this->texture); + + /* error is expected here */ + material_set_float(this->material, "albedo", 4.5f); + + AUTO planeMeshData = mesh3d_plane(renderer->allocator, 1); + this->mesh = mesh_create(renderer, planeMeshData); + mesh3d_destroy(planeMeshData); + this->render_object = render_scene_getH(this->scene, render_scene_create_object(this->scene, RENDER_OBJECT_TYPE_MESH, RENDER_QUEUE_TYPE_GEOMETRY)); + render_object_set_material(this->render_object, this->material); + render_object_attach(this->render_object, this->mesh); + render_object_set_transform(this->render_object, mat4_mul(3, mat4_scale(1, 1, 1), mat4_rotation_z(0 DEG), mat4_translation(0.0f, 0.0f, 0))); + + + render_scene_build_queues(this->scene); + +} + +TEST_ON_TERMINATE(MATERIAL_GET_SET) +{ + texture_destroy(this->texture); + texture_release_resources(this->texture); + mesh_destroy(this->mesh); + mesh_release_resources(this->mesh); + light_destroy(this->light); + light_release_resources(this->light); + render_scene_destroy(this->scene); + render_scene_release_resources(this->scene); +} + + +TEST_ON_UPDATE(MATERIAL_GET_SET) +{ +} + +TEST_ON_RENDER(MATERIAL_GET_SET) +{ + render_scene_render(this->scene, RENDER_SCENE_ALL_QUEUES, RENDER_SCENE_CLEAR); +} +