Compare commits

...

2 Commits

19 changed files with 667 additions and 482 deletions

View File

@ -78,8 +78,8 @@
"stream": {
"tag": "worldspawn",
"player": "info_player_spawn",
"enabled": "auto",
"radius": 32,
"enabled": true, // "auto",
"radius": 16,
"every": 1
}
}

View File

@ -17,7 +17,7 @@
}
},
"graph": {
"initial buffer elements": 256
"initial buffer elements": 128
},
"ext": {
"opengl": {

View File

@ -1 +1 @@
vulkan
opengl

View File

@ -161,7 +161,7 @@ namespace uf {
void UF_API initialize( uf::Object&, size_t = uf::graph::initialBufferElements );
void UF_API initialize( pod::Graph::Storage&, size_t = uf::graph::initialBufferElements );
void UF_API tick( uf::Object& );
void UF_API tick( pod::Graph::Storage& );
bool UF_API tick( pod::Graph::Storage& );
void UF_API render( uf::Object& );
void UF_API render( pod::Graph::Storage& );
void UF_API destroy( uf::Object&, bool soft = false );

View File

@ -13,6 +13,7 @@ namespace ext {
struct Device;
struct UF_API Buffer {
bool aliased = false;
Device* device;
GLuint buffer = 0;

View File

@ -38,6 +38,10 @@ namespace ext {
} textures, buffers;
struct {
uf::stl::vector<Buffer> buffers;
} transient;
void initialize();
void destroy();

View File

@ -7,7 +7,7 @@
namespace ext {
namespace opengl {
struct UF_API RenderMode {
struct UF_API RenderMode : public Buffers {
bool execute = false;
bool executed = false;
bool rebuild = false;

View File

@ -110,6 +110,11 @@ namespace ext {
void destroy();
bool validate();
bool hasBuffer( const uf::stl::string& name );
void aliasBuffer( const Metadata::BufferDescriptor& descriptor );
void aliasBuffer( const ext::opengl::Buffer& buffer );
void aliasBuffer( const uf::stl::string& name, const ext::opengl::Buffer& = {}, const ext::opengl::RenderMode* renderMode = NULL, GLenum = 0 );
bool hasUniform( const uf::stl::string& name ) const;
Buffer& getUniformBuffer( const uf::stl::string& name );

View File

@ -144,6 +144,7 @@ namespace ext {
bool hasBuffer( const uf::stl::string& name );
void aliasBuffer( const Metadata::BufferDescriptor& descriptor );
void aliasBuffer( const ext::vulkan::Buffer& buffer );
void aliasBuffer( const uf::stl::string& name, const ext::vulkan::Buffer& = {}, const ext::vulkan::RenderMode* renderMode = NULL, VkBufferUsageFlags = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT );
bool hasUniform( const uf::stl::string& name ) const;

File diff suppressed because it is too large Load Diff

View File

@ -12,15 +12,14 @@ ext::opengl::Buffer ext::opengl::Buffer::alias() const {
return buffer;
}
void ext::opengl::Buffer::aliasBuffer( const ext::opengl::Buffer& buffer ) {
*this = {
.device = NULL,
.buffer = buffer.buffer,
.descriptor = buffer.descriptor,
.size = buffer.size,
.alignment = buffer.alignment,
.usage = buffer.usage,
.allocationInfo = buffer.allocationInfo,
};
this->aliased = true;
this->device = NULL;
this->buffer = buffer.buffer;
this->descriptor = buffer.descriptor;
this->size = buffer.size;
this->alignment = buffer.alignment;
this->usage = buffer.usage;
this->allocationInfo = buffer.allocationInfo;
}
void* ext::opengl::Buffer::map( GLsizeiptr size, GLsizeiptr offset ) {
@ -52,9 +51,18 @@ void ext::opengl::Buffer::initialize( const void* data, GLsizeiptr length, GLenu
} );
if ( !alias ) this->update( data, length );
}
bool ext::opengl::Buffer::update( const void* data, GLsizeiptr len ) const {
bool ext::opengl::Buffer::update( const void* data, GLsizeiptr length ) const {
if ( !buffer || !data ) return false;
if ( len >= size ) len = size;
if ( length > allocationInfo.size ) {
UF_MSG_WARNING("Buffer update of {} exceeds buffer size of {}", length, allocationInfo.size);
auto savedUsage = usage;
Buffer& self = const_cast<Buffer&>(*this);
self.destroy(true);
self.initialize(data, length, savedUsage);
return true;
}
#if !UF_USE_OPENGL_FIXED_FUNCTION
// GPU-bound buffer
GLenum usage;
@ -74,12 +82,12 @@ bool ext::opengl::Buffer::update( const void* data, GLsizeiptr len ) const {
if ( usage & enums::Buffer::COPY ) usage = GL_DYNAMIC_COPY;
}
GL_ERROR_CHECK(glBindBuffer(GL_COPY_WRITE_BUFFER, buffer));
GL_ERROR_CHECK(glBufferData(GL_COPY_WRITE_BUFFER, len, data, usage));
GL_ERROR_CHECK(glBufferData(GL_COPY_WRITE_BUFFER, length, data, usage));
GL_ERROR_CHECK(glBindBuffer(GL_COPY_WRITE_BUFFER, 0));
#else
// CPU-bound buffer
void* pointer = device->getBuffer( buffer );
if ( pointer && pointer != data ) memcpy( pointer, data, len );
if ( pointer && pointer != data ) memcpy( pointer, data, length );
#endif
return false;
}
@ -113,7 +121,15 @@ void ext::opengl::Buffer::initialize( Device& device ) {
this->device = &device;
}
void ext::opengl::Buffer::destroy( bool defer ) {
if ( device && buffer ) device->destroyBuffer( buffer );
if ( !device || aliased ) return;
if ( defer ) {
ext::opengl::mutex.lock();
device->transient.buffers.emplace_back(*this);
ext::opengl::mutex.unlock();
} else if ( buffer ) {
device->destroyBuffer( buffer );
}
device = NULL;
buffer = NULL;
}

View File

@ -357,10 +357,43 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, const GraphicDe
auto shaders = pipeline.getShaders( material.shaders );
for ( auto shader : shaders ) {
// bind aliased buffers
for ( auto& descriptor : shader->metadata.aliases.buffers ) {
auto matches = uf::string::match(descriptor.name, R"(/^(.+?)\[(\d+)\]$/)");
auto name = matches.size() == 2 ? matches[0] : descriptor.name;
auto view = matches.size() == 2 ? stoi(matches[1]) : -1;
const ext::opengl::Buffer* buffer = &descriptor.fallback;
if ( descriptor.renderMode ) {
if ( descriptor.renderMode->hasBuffer(name) )
buffer = &descriptor.renderMode->getBuffer(name);
}/* else if ( renderMode.hasBuffer(name) ) {
buffer = &renderMode.getBuffer(name);
}*/
if ( !buffer ) continue;
if ( buffer->usage & uf::renderer::enums::Buffer::UNIFORM ) uniformBuffers.emplace_back(buffer->descriptor);
if ( buffer->usage & uf::renderer::enums::Buffer::STORAGE ) storageBuffers.emplace_back(buffer->descriptor);
}
// bind shader
for ( auto& buffer : shader->buffers ) {
if ( buffer.usage & uf::renderer::enums::Buffer::UNIFORM ) { uniformBuffers.emplace_back(buffer.descriptor); }
if ( buffer.usage & uf::renderer::enums::Buffer::STORAGE ) { storageBuffers.emplace_back(buffer.descriptor); }
}
/*
// add per-pipeline buffers
for ( auto& buffer : this->buffers ) {
if ( buffer.usage & uf::renderer::enums::Buffer::UNIFORM ) infos.uniform.emplace_back(buffer.descriptor);
if ( buffer.usage & uf::renderer::enums::Buffer::STORAGE ) infos.storage.emplace_back(buffer.descriptor);
// if ( buffer.usage & VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR ) infos.accelerationStructure.emplace_back(buffer.descriptor);
}
// add per-graphics buffers
for ( auto& buffer : graphic.buffers ) {
if ( buffer.usage & uf::renderer::enums::Buffer::UNIFORM ) infos.uniform.emplace_back(buffer.descriptor);
if ( buffer.usage & uf::renderer::enums::Buffer::STORAGE ) infos.storage.emplace_back(buffer.descriptor);
// if ( buffer.usage & VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR ) infos.accelerationStructure.emplace_back(buffer.descriptor);
}
*/
}
auto uniformBufferIt = uniformBuffers.begin();

View File

@ -410,6 +410,7 @@ void ext::opengl::render(){
#if !UF_ENV_DREAMCAST
ext::opengl::device.activateContext();
#endif
auto transient = std::move(ext::opengl::device.transient);
{
auto& scene = uf::scene::getCurrentScene();
@ -470,6 +471,11 @@ void ext::opengl::render(){
#if UF_USE_OPENVR
// if ( ext::openvr::context ) ext::openvr::postSubmit();
#endif
// cleanup in-flight buffers
for ( auto& buffer : transient.buffers ) buffer.destroy(false);
transient.buffers.clear();
ext::opengl::mutex.unlock();
}
void ext::opengl::destroy() {

View File

@ -83,6 +83,18 @@ ext::opengl::CommandBuffer& ext::opengl::RenderMode::getCommands( std::thread::i
void ext::opengl::RenderMode::createCommandBuffers( const uf::stl::vector<ext::opengl::Graphic*>& graphics ) {
}
bool ext::opengl::RenderMode::hasBuffer( const uf::stl::string& name ) const {
return metadata.buffers.count(name) > 0;
}
const ext::opengl::Buffer& ext::opengl::RenderMode::getBuffer( const uf::stl::string& name ) const {
UF_ASSERT_MSG( hasBuffer( name ), "attachment in `{}`: {} not found: {}", this->getName(), this->getType(), name );
return this->buffers[metadata.buffers.at(name)];
}
size_t ext::opengl::RenderMode::getBufferIndex( const uf::stl::string& name ) const {
return hasBuffer( name ) ? metadata.buffers.at(name) : SIZE_MAX;
}
void ext::opengl::RenderMode::bindPipelines() {
this->execute = true;
@ -172,6 +184,12 @@ void ext::opengl::RenderMode::initialize( Device& device ) {
if ( this->width > 0 ) renderTarget.width = this->width;
if ( this->height > 0 ) renderTarget.height = this->height;
}
/*
if ( !this->hasBuffer("camera") ) {
this->metadata.buffers["camera"] = this->initializeBuffer( (const void*) nullptr, sizeof(pod::Camera::Viewports), uf::renderer::enums::Buffer::UNIFORM );
}
*/
}
void ext::opengl::RenderMode::tick() {

View File

@ -116,6 +116,19 @@ bool ext::opengl::Shader::hasUniform( const uf::stl::string& name ) const {
// return metadata.definitions.uniforms.count(name) > 0;
return true;
}
void ext::opengl::Shader::aliasBuffer( const ext::opengl::Shader::Metadata::BufferDescriptor& descriptor ) {
metadata.aliases.buffers.emplace_back(descriptor);
}
// aliases by name
void ext::opengl::Shader::aliasBuffer( const uf::stl::string& name, const ext::opengl::Buffer& fallback, const ext::opengl::RenderMode* renderMode, GLenum flags ) {
return aliasBuffer({ name, fallback.alias(), renderMode, flags });
}
// aliases directly
void ext::opengl::Shader::aliasBuffer( const ext::opengl::Buffer& buffer ) {
return aliasBuffer({ "", buffer.alias(), NULL, buffer.usage });
}
ext::opengl::Buffer& ext::opengl::Shader::getUniformBuffer( const uf::stl::string& name ) {
UF_ASSERT( hasUniform(name) );
size_t uniformIndex = 0; // metadata.definitions.uniforms[name].index;

View File

@ -195,14 +195,11 @@ bool ext::vulkan::Buffer::update( const void* data, VkDeviceSize length, bool st
auto savedMemProps = memoryProperties;
auto savedAlignment = alignment;
Buffer& oldBuffer = *const_cast<Buffer*>(this);
Buffer newBuffer = {};
Buffer& self = const_cast<Buffer&>(*this);
oldBuffer.swap(newBuffer);
newBuffer.destroy(true);
oldBuffer.initialize(*device, savedAlignment);
oldBuffer.initialize(data, length, savedUsage, savedMemProps, stage);
self.destroy(true);
self.initialize(*device, savedAlignment);
self.initialize(data, length, savedUsage, savedMemProps, stage);
return true;
}

View File

@ -516,6 +516,7 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
auto& infos = INFOS.emplace_back();
uf::stl::vector<ext::vulkan::enums::Image::viewType_t> types;
// add aliased-by-name buffers
for ( auto& descriptor : shader->metadata.aliases.buffers ) {
auto matches = uf::string::match(descriptor.name, R"(/^(.+?)\[(\d+)\]$/)");
auto name = matches.size() == 2 ? matches[0] : descriptor.name;
@ -531,32 +532,32 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
if ( !buffer ) continue;
if ( buffer->usage & uf::renderer::enums::Buffer::UNIFORM ) infos.uniform.emplace_back(buffer->descriptor);
if ( buffer->usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT ) infos.storage.emplace_back(buffer->descriptor);
if ( buffer->usage & uf::renderer::enums::Buffer::STORAGE ) infos.storage.emplace_back(buffer->descriptor);
}
#if 0
// add per-rendermode buffers
for ( auto& buffer : renderMode.buffers ) {
if ( buffer.usage & uf::renderer::enums::Buffer::UNIFORM ) infos.uniform.emplace_back(buffer.descriptor);
if ( buffer.usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT ) infos.storage.emplace_back(buffer.descriptor);
if ( buffer.usage & uf::renderer::enums::Buffer::STORAGE ) infos.storage.emplace_back(buffer.descriptor);
// if ( buffer.usage & VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR ) infos.accelerationStructure.emplace_back(buffer.descriptor);
}
#endif
// add per-shader buffers
for ( auto& buffer : shader->buffers ) {
if ( buffer.usage & uf::renderer::enums::Buffer::UNIFORM ) infos.uniform.emplace_back(buffer.descriptor);
if ( buffer.usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT ) infos.storage.emplace_back(buffer.descriptor);
if ( buffer.usage & uf::renderer::enums::Buffer::STORAGE ) infos.storage.emplace_back(buffer.descriptor);
// if ( buffer.usage & VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR ) infos.accelerationStructure.emplace_back(buffer.descriptor);
}
// add per-pipeline buffers
for ( auto& buffer : this->buffers ) {
if ( buffer.usage & uf::renderer::enums::Buffer::UNIFORM ) infos.uniform.emplace_back(buffer.descriptor);
if ( buffer.usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT ) infos.storage.emplace_back(buffer.descriptor);
if ( buffer.usage & uf::renderer::enums::Buffer::STORAGE ) infos.storage.emplace_back(buffer.descriptor);
// if ( buffer.usage & VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR ) infos.accelerationStructure.emplace_back(buffer.descriptor);
}
// add per-graphics buffers
for ( auto& buffer : graphic.buffers ) {
if ( buffer.usage & uf::renderer::enums::Buffer::UNIFORM ) infos.uniform.emplace_back(buffer.descriptor);
if ( buffer.usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT ) infos.storage.emplace_back(buffer.descriptor);
if ( buffer.usage & uf::renderer::enums::Buffer::STORAGE ) infos.storage.emplace_back(buffer.descriptor);
// if ( buffer.usage & VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR ) infos.accelerationStructure.emplace_back(buffer.descriptor);
}
@ -1132,10 +1133,10 @@ void ext::vulkan::Graphic::initializeMesh( uf::Mesh& mesh, bool buffer ) {
// allocate buffers
auto previousRequestedAlignment = this->requestedAlignment;
this->requestedAlignment = 16;
PARSE_INPUT_INITIALIZE(vertex, uf::renderer::enums::Buffer::VERTEX | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT )
PARSE_INPUT_INITIALIZE(vertex, uf::renderer::enums::Buffer::VERTEX | uf::renderer::enums::Buffer::STORAGE )
PARSE_INPUT_INITIALIZE(index, uf::renderer::enums::Buffer::INDEX )
PARSE_INPUT_INITIALIZE(instance, uf::renderer::enums::Buffer::VERTEX )
PARSE_INPUT_INITIALIZE(indirect, uf::renderer::enums::Buffer::INDIRECT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT )
PARSE_INPUT_INITIALIZE(indirect, uf::renderer::enums::Buffer::INDIRECT | uf::renderer::enums::Buffer::STORAGE )
this->requestedAlignment = previousRequestedAlignment;
}
@ -1744,7 +1745,7 @@ void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vect
// UF_MSG_DEBUG("Reduced size to {}% ({} -> {} = {})", (float) (oldSize - compactedSize) / (float) (oldSize), oldSize, compactedSize, oldSize - compactedSize);
ext::vulkan::Buffer oldBuffer;
oldBuffer.initialize( NULL, tlasBufferSize, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT );
oldBuffer.initialize( NULL, tlasBufferSize, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | uf::renderer::enums::Buffer::STORAGE );
this->buffers[tlasBufferIndex].swap(oldBuffer);
tlas.buffer = this->buffers[tlasBufferIndex].alias();

View File

@ -64,7 +64,7 @@ const ext::vulkan::Buffer& ext::vulkan::RenderMode::getBuffer( const uf::stl::st
return this->buffers[metadata.buffers.at(name)];
}
size_t ext::vulkan::RenderMode::getBufferIndex( const uf::stl::string& name ) const {
return hasAttachment( name ) ? metadata.buffers.at(name) : SIZE_MAX;
return hasBuffer( name ) ? metadata.buffers.at(name) : SIZE_MAX;
}
uf::Image ext::vulkan::RenderMode::screenshot( size_t attachmentID, size_t layerID ) {

View File

@ -881,9 +881,14 @@ bool ext::vulkan::Shader::hasBuffer( const uf::stl::string& name ) {
void ext::vulkan::Shader::aliasBuffer( const ext::vulkan::Shader::Metadata::BufferDescriptor& descriptor ) {
metadata.aliases.buffers.emplace_back(descriptor);
}
// aliases by name
void ext::vulkan::Shader::aliasBuffer( const uf::stl::string& name, const ext::vulkan::Buffer& fallback, const ext::vulkan::RenderMode* renderMode, VkBufferUsageFlags flags ) {
return aliasBuffer({ name, fallback.alias(), renderMode, flags });
}
// aliases directly
void ext::vulkan::Shader::aliasBuffer( const ext::vulkan::Buffer& buffer ) {
return aliasBuffer({ "", buffer.alias(), NULL, buffer.usage });
}
bool ext::vulkan::Shader::hasUniform( const uf::stl::string& name ) const {
return metadata.definitions.uniforms.count(name) > 0;