Fixes bug with crashing at random times due to texture IDX going to the moon

This commit is contained in:
2024-03-11 01:07:21 -04:00
parent 5cf85f3a7d
commit bfe0da9c21
10 changed files with 66 additions and 82 deletions

View File

@@ -1,11 +1,12 @@
#version 450
#extension GL_EXT_nonuniform_qualifier: enable
#extension GL_EXT_debug_printf: enable
layout (location = 0) in vec3 in_normal;
layout (location = 1) in vec3 in_color;
layout (location = 2) in vec3 in_world_pos;
layout (location = 3) in vec2 in_tex_coord;
layout (location = 4) in flat int in_tex_idx;
layout (location = 4) in flat uint in_tex_idx;
layout (location = 0) out vec4 out_color;
layout (location = 1) out vec4 out_position;

View File

@@ -1,4 +1,5 @@
#version 450
#extension GL_EXT_debug_printf: enable
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
@@ -6,13 +7,13 @@ layout (location = 2) in vec3 normal;
layout (location = 3) in vec2 uv;
layout (location = 4) in mat4 instance_model_matrix; // 4, 5, 6, 7
layout (location = 8) in int in_texture_id;
layout (location = 8) in uint in_texture_id;
layout (location = 0) out vec3 out_normal;
layout (location = 1) out vec3 out_color;
layout (location = 2) out vec3 out_world_pos;
layout (location = 3) out vec2 out_tex_coord;
layout (location = 4) out int out_texture_idx;
layout (location = 4) out uint out_texture_idx;
layout (set = 0, binding = 0) uniform CameraInfo {
mat4 projection;

View File

@@ -51,18 +51,24 @@ namespace fgl::engine
void BufferSuballocation::flush( vk::DeviceSize beg, vk::DeviceSize end )
{
assert( beg < end );
assert( m_handle != nullptr );
assert( m_handle->mapped != nullptr && "BufferSuballocationT::flush() called before map()" );
assert( end <= this->m_byte_size );
vk::MappedMemoryRange range {};
range.memory = m_handle->buffer.getMemory();
range.offset = m_offset + beg;
const vk::DeviceSize min_atom_size { Device::getInstance().m_properties.limits.nonCoherentAtomSize };
const auto size { end - beg };
const vk::DeviceSize size { end - beg };
assert( size > 0 );
range.size = align( size, min_atom_size );
assert( range.size > 0 );
if ( range.size > m_byte_size ) range.size = VK_WHOLE_SIZE;
if ( Device::getInstance().device().flushMappedMemoryRanges( 1, &range ) != vk::Result::eSuccess )

View File

@@ -42,14 +42,12 @@ namespace fgl::engine
public:
//! Returns the total byte capacity of the buffer
[[nodiscard]] std::size_t byteCapacity() const noexcept { return m_count * m_stride; }
//! Returns the offset count from the start of the buffer to the first element
[[nodiscard]] std::uint32_t getOffsetCount() const
{
assert( !std::isnan( m_count ) );
assert( !std::isnan( m_stride ) );
assert( m_count * m_stride == this->bytesize() );
assert( m_offset % m_stride == 0 && "Offset must be aligned from the stride" );
return static_cast< std::uint32_t >( this->m_offset / m_stride );
@@ -58,10 +56,16 @@ namespace fgl::engine
[[nodiscard]] std::uint32_t stride() const noexcept
{
assert( !std::isnan( m_stride ) );
assert( m_count * m_stride <= this->bytesize() );
return m_stride;
}
[[nodiscard]] std::uint32_t size() const noexcept { return m_count; }
[[nodiscard]] std::uint32_t size() const noexcept
{
assert( !std::isnan( m_count ) );
assert( m_count * m_stride <= this->bytesize() );
return m_count;
}
void resize( const std::uint32_t count )
{

View File

@@ -20,8 +20,6 @@ namespace fgl::engine
template < typename T >
class HostVector final : public BufferVector
{
std::uint32_t m_used { 0 };
public:
using value_type = T;
@@ -32,15 +30,7 @@ namespace fgl::engine
HostVector& operator=( HostVector&& ) = delete;
HostVector( HostVector&& other ) = delete;
HostVector( Buffer& buffer, const std::uint32_t count = 1 ) :
BufferVector( buffer, count, sizeof( T ) ),
m_used( count )
{}
std::uint32_t capacity() const { return BufferVector::size(); }
//! Returns the number of T currently used
std::uint32_t size() const { return m_used; }
HostVector( Buffer& buffer, const std::uint32_t count = 1 ) : BufferVector( buffer, count, sizeof( T ) ) {}
HostVector( Buffer& buffer, const std::vector< T >& vec ) :
HostVector( buffer, static_cast< std::uint32_t >( vec.size() ) )
@@ -55,13 +45,10 @@ namespace fgl::engine
this->flush();
}
void flush() { this->flushRange( 0, m_used ); }
void flush() { this->flushRange( 0, size() ); }
void flushRange( const std::uint32_t start_idx, const std::uint32_t end_idx )
{
if ( this->m_count == 0 ) [[unlikely]]
return;
assert(
start_idx < this->m_count && "BufferSuballocationVector::flushRange start_idx index out of bounds" );
assert( end_idx <= this->m_count && "BufferSuballocationVector::flushRange end_idx index out of bounds" );
@@ -77,13 +64,13 @@ namespace fgl::engine
const auto count { end_idx - start_idx };
assert( count > 0 && "Count must be larger then 0" );
assert( count <= m_count );
BufferSuballocation::flush( start_idx * this->m_stride, count * this->m_stride );
BufferSuballocation::flush( start_idx * this->m_stride, end_idx * this->m_stride );
}
HostVector& operator=( const std::vector< T >& vec )
{
m_used = static_cast< decltype( m_used ) >( vec.size() );
if ( this->m_stride == sizeof( T ) )
{
std::memcpy( this->ptr(), vec.data(), vec.size() * sizeof( T ) );
@@ -96,15 +83,6 @@ namespace fgl::engine
return *this;
}
void push_back( const T& t )
{
if ( capacity <= m_used + 1 ) resize( m_used + 1 );
assert( capacity >= m_used + 1 );
*this[ m_used++ ] = t;
}
~HostVector() {}
};

View File

@@ -64,12 +64,6 @@ namespace fgl::engine
//! Returns the bounding box in model space
const OrientedBoundingBox< CoordinateSpace::Model >& getBoundingBox() const { return m_bounding_box; }
OrientedBoundingBox< CoordinateSpace::World > getBoundingBox( const Matrix< MatrixType::ModelToWorld > matrix )
const
{
return matrix * m_bounding_box;
}
std::vector< Primitive > m_primitives {};
std::vector< vk::DrawIndexedIndirectCommand > getDrawCommand( const std::uint32_t index ) const;

View File

@@ -44,9 +44,9 @@ namespace fgl::engine
attribute_descriptions.emplace_back( 6, 1, vk::Format::eR32G32B32A32Sfloat, 2 * sizeof( glm::vec4 ) );
attribute_descriptions.emplace_back( 7, 1, vk::Format::eR32G32B32A32Sfloat, 3 * sizeof( glm::vec4 ) );
attribute_descriptions.emplace_back( 8, 1, vk::Format::eR32Sint, 4 * sizeof( glm::vec4 ) );
attribute_descriptions.emplace_back( 8, 1, vk::Format::eR32Uint, 4 * sizeof( glm::vec4 ) );
static_assert( 4 * sizeof( glm::vec4 ) + sizeof( int ) == sizeof( ModelMatrixInfo ) );
static_assert( 4 * sizeof( glm::vec4 ) + sizeof( unsigned int ) == sizeof( ModelMatrixInfo ) );
return attribute_descriptions;
}

View File

@@ -19,7 +19,9 @@ static VKAPI_ATTR vk::Bool32 VKAPI_CALL debugCallback(
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
[[maybe_unused]] void* pUserData )
{
if ( pCallbackData->flags & VkDebugUtilsMessageSeverityFlagBitsEXT::VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT )
if ( pCallbackData->flags
& ( VkDebugUtilsMessageSeverityFlagBitsEXT::VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT
| VkDebugUtilsMessageSeverityFlagBitsEXT::VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT ) )
throw std::runtime_error( pCallbackData->pMessage );
else
std::cout << pCallbackData->pMessage << std::endl;
@@ -124,7 +126,7 @@ namespace fgl::engine
appInfo.applicationVersion = VK_MAKE_VERSION( 1, 0, 0 );
appInfo.pEngineName = "titor";
appInfo.engineVersion = VK_MAKE_VERSION( 1, 0, 0 );
appInfo.apiVersion = VK_API_VERSION_1_2;
appInfo.apiVersion = VK_API_VERSION_1_3;
vk::InstanceCreateInfo createInfo {};
createInfo.pApplicationInfo = &appInfo;

View File

@@ -143,8 +143,9 @@ namespace fgl::engine
auto& [ itter_key, pair ] = *itter;
auto& [ existing_cmd, model_matrix ] = pair;
existing_cmd.instanceCount++;
existing_cmd.instanceCount += 1;
model_matrix.emplace_back( matrix_info );
assert( model_matrix.size() == existing_cmd.instanceCount );
}
else
{
@@ -159,6 +160,7 @@ namespace fgl::engine
std::vector< ModelMatrixInfo > matrix_infos {};
matrix_infos.reserve( 1024 );
matrix_infos.emplace_back( matrix_info );
draw_pairs.emplace( key, std::make_pair( cmd, std::move( matrix_infos ) ) );
}
}
@@ -178,8 +180,8 @@ namespace fgl::engine
return;
}
std::vector< vk::DrawIndexedIndirectCommand > draw_commands;
std::vector< ModelMatrixInfo > model_matrices;
std::vector< vk::DrawIndexedIndirectCommand > draw_commands {};
std::vector< ModelMatrixInfo > model_matrices {};
draw_commands.reserve( draw_pairs.size() );
model_matrices.reserve( draw_pairs.size() * 2 );
@@ -188,52 +190,50 @@ namespace fgl::engine
for ( auto& [ key, pair ] : draw_pairs )
{
auto cmd { pair.first };
assert( cmd != vk::DrawIndexedIndirectCommand() );
cmd.firstInstance = static_cast< std::uint32_t >( model_matrices.size() );
auto matricies { std::move( pair.second ) };
assert( cmd.instanceCount == pair.second.size() );
assert( pair.second.size() > 0 );
draw_commands.emplace_back( cmd );
model_matrices.insert( model_matrices.end(), matricies.begin(), matricies.end() );
model_matrices.insert( model_matrices.end(), pair.second.begin(), pair.second.end() );
}
TracyCZoneEnd( filter_zone_TRACY );
TracyCZoneN( draw_zone_TRACY, "Submit draw data", true );
auto& draw_parameter_buffer { m_draw_parameter_buffers[ info.frame_idx ] };
if ( draw_parameter_buffer == nullptr || draw_parameter_buffer->capacity() < draw_commands.size() )
{
draw_parameter_buffer =
std::make_unique< DrawParameterBufferSuballocation >( info.draw_parameter_buffer, draw_commands );
}
else
{
//Simply set and flush
*draw_parameter_buffer = draw_commands;
}
const auto& draw_params { draw_parameter_buffer };
assert( draw_params->size() == draw_commands.size() );
TracyCZoneEnd( draw_zone_TRACY );
draw_parameter_buffer->flush();
//Setup model matrix info buffers
auto& model_matrix_info_buffer { m_model_matrix_info_buffers[ info.frame_idx ] };
if ( model_matrix_info_buffer == nullptr || model_matrix_info_buffer->capacity() < model_matrices.size() )
{
model_matrix_info_buffer = std::make_unique<
ModelMatrixInfoBufferSuballocation >( info.model_matrix_info_buffer, model_matrices );
}
else
{
//We can re-use this buffer since it's of a proper size.
*model_matrix_info_buffer = model_matrices;
}
assert( model_matrix_info_buffer->size() == model_matrices.size() );
model_matrix_info_buffer =
std::make_unique< ModelMatrixInfoBufferSuballocation >( info.model_matrix_info_buffer, model_matrices );
model_matrix_info_buffer->flush();
const auto& model_matricies_suballoc { model_matrix_info_buffer };
for ( const auto& model_matrix : model_matrices )
{
assert( model_matrix.texture_idx <= 100 );
}
assert( model_matrix_info_buffer->size() == model_matrices.size() );
// Setup draw parameter buffer
TracyCZoneN( draw_zone_TRACY, "Submit draw data", true );
auto& draw_parameter_buffer { m_draw_parameter_buffers[ info.frame_idx ] };
draw_parameter_buffer =
std::make_unique< DrawParameterBufferSuballocation >( info.draw_parameter_buffer, draw_commands );
const auto& draw_params { draw_parameter_buffer };
assert( draw_params->size() == draw_commands.size() );
assert( draw_params->stride() == sizeof( vk::DrawIndexedIndirectCommand ) );
TracyCZoneEnd( draw_zone_TRACY );
draw_parameter_buffer->flush();
const std::vector< vk::Buffer > vertex_buffers { m_vertex_buffer->getVkBuffer(),
model_matricies_suballoc->getVkBuffer() };

View File

@@ -39,8 +39,6 @@ namespace fgl::engine
const auto data_c { stbi_load( path_str.data(), &x, &y, &channels, 4 ) };
std::cout << "Loaded image with " << x << "x" << y << "\n\tImage had " << channels << " channels" << std::endl;
std::vector< unsigned char > data {};
data.resize( x * y * 4 );