validation errors squishing, finally bothered to seamlessly handle N-buffered UBOs, fixed shadowmapping not require a constant rebuild every time the lights changed (by instead binding all shadow textures and not-so-clever tricks), some other things
This commit is contained in:
parent
226f1fb77e
commit
b3df72bfab
@ -110,7 +110,7 @@
|
||||
"invariant": {
|
||||
"default stage buffers": true,
|
||||
"default defer buffer destroy": true,
|
||||
"default command buffer immediate": false,
|
||||
"default command buffer immediate": true,
|
||||
"multithreaded recording": true
|
||||
},
|
||||
"pipelines": {
|
||||
@ -118,9 +118,9 @@
|
||||
"gui": true,
|
||||
"vsync": true, // vsync on vulkan side rather than engine-side
|
||||
"hdr": true,
|
||||
"vxgi": true,
|
||||
"vxgi": false, // to-do: fix issues
|
||||
"culling": false,
|
||||
"bloom": false,
|
||||
"bloom": true,
|
||||
"dof": false,
|
||||
"rt": false,
|
||||
"fsr": false,
|
||||
@ -175,6 +175,7 @@
|
||||
"features": [
|
||||
// 1.1
|
||||
"multiview"
|
||||
,"multiviewGeometryShader"
|
||||
//
|
||||
,"nullDescriptor"
|
||||
,"fragmentStoresAndAtomics"
|
||||
@ -192,6 +193,12 @@
|
||||
,"shaderSampledImageArrayNonUniformIndexing"
|
||||
,"shaderStorageImageArrayNonUniformIndexing"
|
||||
|
||||
,"descriptorBindingAccelerationStructureUpdateAfterBind"
|
||||
,"descriptorBindingSampledImageUpdateAfterBind"
|
||||
,"descriptorBindingStorageImageUpdateAfterBind"
|
||||
,"descriptorBindingStorageBufferUpdateAfterBind"
|
||||
,"descriptorBindingUniformBufferUpdateAfterBind"
|
||||
,"descriptorBindingPartiallyBound"
|
||||
,"descriptorIndexing"
|
||||
,"bufferDeviceAddress"
|
||||
],
|
||||
|
||||
@ -111,9 +111,11 @@ local fpsCounter = {
|
||||
time = 0,
|
||||
freq = 0.1
|
||||
}
|
||||
--[[
|
||||
text:callHook( "gui:UpdateText.%UID%", {
|
||||
string = ""
|
||||
} )
|
||||
]]
|
||||
|
||||
ent:bind( "tick", function(self)
|
||||
--[[
|
||||
@ -126,6 +128,7 @@ ent:bind( "tick", function(self)
|
||||
end
|
||||
]]
|
||||
|
||||
--[[
|
||||
if fpsCounter["time"] > fpsCounter["freq"] then
|
||||
-- update text
|
||||
text:callHook( "gui:UpdateText.%UID%", {
|
||||
@ -138,6 +141,7 @@ ent:bind( "tick", function(self)
|
||||
fpsCounter["frames"] = fpsCounter["frames"] + 1
|
||||
fpsCounter["time"] = fpsCounter["time"] + time.delta()
|
||||
end
|
||||
]]
|
||||
|
||||
|
||||
local controllerTransform = controller:getComponent("Transform")
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "HUD Overlay",
|
||||
"type": "Gui",
|
||||
"ignore": false,
|
||||
"ignore": true,
|
||||
"assets": [
|
||||
|
||||
],
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
"bias": {
|
||||
"constant": 1.25,
|
||||
"slope": 1.75,
|
||||
"shader": 0.00005 // 0.000005 //0.000000005
|
||||
"shader": 0.000005 // 0.000005 //0.000000005
|
||||
},
|
||||
"radius": [0.5, 0],
|
||||
"resolution": 1024,
|
||||
|
||||
@ -28,7 +28,7 @@ void lambert() {
|
||||
// skip if attenuation factor is too low
|
||||
// if ( Lattenuation <= LIGHT_POWER_CUTOFF ) continue;
|
||||
// ray cast if our surface is occluded from the light
|
||||
const float Lshadow = ( shadows++ < MAX_SHADOWS ) ? shadowFactor( lights[i], 0.0 ) : 1;
|
||||
const float Lshadow = shadowFactor( lights[i], 0.0 );
|
||||
// skip if our shadow factor is too low
|
||||
// if ( Lshadow <= LIGHT_POWER_CUTOFF ) continue; // in case of any divergence
|
||||
// light radiance
|
||||
|
||||
@ -35,7 +35,7 @@ void pbr() {
|
||||
// skip if attenuation factor is too low
|
||||
// if ( Lattenuation <= LIGHT_POWER_CUTOFF ) continue;
|
||||
// ray cast if our surface is occluded from the light
|
||||
const float Lshadow = ( shadows++ < MAX_SHADOWS ) ? shadowFactor( lights[i], 0.0 ) : 1;
|
||||
const float Lshadow = shadowFactor( lights[i], 0.0 );
|
||||
// skip if our shadow factor is too low
|
||||
// if ( Lshadow <= LIGHT_POWER_CUTOFF ) continue; // in case of any divergence
|
||||
// light radiance
|
||||
@ -58,7 +58,7 @@ void pbr() {
|
||||
|
||||
// final lighting
|
||||
const vec3 diffuse = mix(vec3(1.0) - F, vec3(0), surface.material.metallic) * surface.material.albedo.rgb;
|
||||
const vec3 specular = ( shadows < MAX_SHADOWS ) ? ((F * D * G) / max(EPSILON, 4.0 * cosLi * cosLo)) : vec3(0);
|
||||
const vec3 specular = (F * D * G) / max(EPSILON, 4.0 * cosLi * cosLo);
|
||||
|
||||
surface.light.rgb += (diffuse + specular) * Lr * cosLi;
|
||||
surface.light.a += lights[i].power * Lattenuation * Lshadow;
|
||||
|
||||
@ -21,6 +21,7 @@ namespace ext {
|
||||
mutable size_t address = {};
|
||||
void* mapped = nullptr;
|
||||
int32_t count = 1;
|
||||
mutable bool written = false;
|
||||
|
||||
VkBufferUsageFlags usage = 0;
|
||||
VkMemoryPropertyFlags memoryProperties = 0;
|
||||
@ -41,8 +42,8 @@ namespace ext {
|
||||
|
||||
~Buffer();
|
||||
void initialize( ext::vulkan::Device& device, size_t = {} );
|
||||
void initialize( const void*, VkDeviceSize, VkBufferUsageFlags, VkMemoryPropertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, bool = VK_DEFAULT_STAGE_BUFFERS );
|
||||
bool update( const void*, VkDeviceSize, bool = VK_DEFAULT_STAGE_BUFFERS ) const; // returns true if a reallocation occurred (to signal rebuilding command buffers)
|
||||
void initialize( const void*, VkDeviceSize, VkBufferUsageFlags, VkMemoryPropertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT );
|
||||
bool update( const void*, VkDeviceSize ) const; // returns true if a reallocation occurred (to signal rebuilding command buffers)
|
||||
void destroy(bool = VK_DEFAULT_DEFER_BUFFER_DESTROY);
|
||||
|
||||
void swap( Buffer& );
|
||||
@ -60,9 +61,9 @@ namespace ext {
|
||||
void destroy(bool = VK_DEFAULT_DEFER_BUFFER_DESTROY);
|
||||
//
|
||||
|
||||
size_t initializeBuffer( const void*, VkDeviceSize, VkBufferUsageFlags, VkMemoryPropertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, bool = VK_DEFAULT_STAGE_BUFFERS );
|
||||
bool updateBuffer( const void*, VkDeviceSize, const Buffer&, bool = VK_DEFAULT_STAGE_BUFFERS ) const;
|
||||
inline bool updateBuffer( const void* data, VkDeviceSize length, size_t index = 0, bool stage = VK_DEFAULT_STAGE_BUFFERS ) const { return updateBuffer( data, length, buffers.at(index), stage ); }
|
||||
size_t initializeBuffer( const void*, VkDeviceSize, VkBufferUsageFlags, VkMemoryPropertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT );
|
||||
bool updateBuffer( const void*, VkDeviceSize, const Buffer& ) const;
|
||||
inline bool updateBuffer( const void* data, VkDeviceSize length, size_t index = 0 ) const { return updateBuffer( data, length, buffers.at(index) ); }
|
||||
};
|
||||
|
||||
struct AccelerationStructure {
|
||||
|
||||
@ -139,12 +139,12 @@ namespace ext {
|
||||
uint32_t getQueueFamilyIndex( VkQueueFlagBits queueFlags );
|
||||
uint32_t getMemoryType( uint32_t typeBits, VkMemoryPropertyFlags properties, VkBool32 *memTypeFound = nullptr );
|
||||
|
||||
VkCommandBuffer createCommandBuffer( VkCommandBufferLevel level, QueueEnum queue, bool begin = true );
|
||||
VkCommandBuffer createCommandBuffer( VkCommandBufferLevel level, QueueEnum queue, bool begin = true, bool singleton = true );
|
||||
void flushCommandBuffer( VkCommandBuffer commandBuffer, QueueEnum queue, bool wait = VK_DEFAULT_COMMAND_BUFFER_IMMEDIATE );
|
||||
pod::Checkpoint* markCommandBuffer( VkCommandBuffer commandBuffer, pod::Checkpoint::Type type, const uf::stl::string& name, const uf::stl::string& info );
|
||||
|
||||
CommandBuffer fetchCommandBuffer( QueueEnum queue, bool waits = VK_DEFAULT_COMMAND_BUFFER_IMMEDIATE );
|
||||
CommandBuffer fetchCommandBuffer( QueueEnum queue, VkCommandBufferLevel, bool waits = VK_DEFAULT_COMMAND_BUFFER_IMMEDIATE );
|
||||
CommandBuffer fetchCommandBuffer( QueueEnum queue, bool immediate = VK_DEFAULT_COMMAND_BUFFER_IMMEDIATE );
|
||||
CommandBuffer fetchCommandBuffer( QueueEnum queue, VkCommandBufferLevel, bool immediate = VK_DEFAULT_COMMAND_BUFFER_IMMEDIATE );
|
||||
void flushCommandBuffer( CommandBuffer& commandBuffer );
|
||||
pod::Checkpoint* markCommandBuffer( CommandBuffer& commandBuffer, pod::Checkpoint::Type type, const uf::stl::string& name, const uf::stl::string& info );
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
#define VK_DEFAULT_STAGE_BUFFERS ext::vulkan::settings::defaultStageBuffers
|
||||
#define VK_DEFAULT_DEFER_BUFFER_DESTROY ext::vulkan::settings::defaultDeferBufferDestroy
|
||||
#define VK_DEFAULT_COMMAND_BUFFER_IMMEDIATE ext::vulkan::settings::defaultCommandBufferImmediate
|
||||
#define VK_UBO_USE_N_BUFFERS 0
|
||||
#define VK_UBO_USE_N_BUFFERS 1
|
||||
#define VK_USE_MULTIVIEW 1
|
||||
|
||||
namespace ext {
|
||||
|
||||
@ -578,8 +578,13 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
|
||||
.global = metadata.global,
|
||||
});
|
||||
}
|
||||
uf::stl::vector<size_t> indices(entities.size());
|
||||
std::iota(indices.begin(), indices.end(), 0);
|
||||
|
||||
// prioritize closer lights; it would be nice to also prioritize lights in view, but because of VXGI it's not really something to do
|
||||
std::sort( entities.begin(), entities.end(), [&]( LightInfo& l, LightInfo& r ){
|
||||
std::sort(indices.begin(), indices.end(), [&](size_t a, size_t b) {
|
||||
auto& l = entities[a];
|
||||
auto& r = entities[b];
|
||||
if ( l.global && !r.global ) return true;
|
||||
if ( !l.global && r.global ) return false;
|
||||
return l.distance < r.distance;
|
||||
@ -589,63 +594,89 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
|
||||
int32_t shadowCount = metadata.shadow.max; // how many shadow maps we should pass, based on range
|
||||
if ( shadowCount <= 0 ) shadowCount = std::numeric_limits<int32_t>::max();
|
||||
|
||||
// disable shadows if that light is outside our threshold
|
||||
for ( auto& info : entities ) if ( info.shadows && shadowCount-- <= 0 ) info.shadows = false;
|
||||
// iterate over sorted indices
|
||||
for ( auto idx : indices ) {
|
||||
auto& info = entities[idx];
|
||||
if ( !info.shadows ) continue;
|
||||
// outside of top-k, disable
|
||||
if ( shadowCount-- <= 0 ) info.shadows = false;
|
||||
else {
|
||||
// enable if also in-range
|
||||
auto* entity = info.entity;
|
||||
if ( entity->hasComponent<uf::renderer::RenderTargetRenderMode>() ) {
|
||||
auto& lightMetadata = entity->getComponent<ext::LightBehavior::Metadata>();
|
||||
|
||||
// bind lighting and requested shadow maps
|
||||
for ( uint32_t i = 0; i < entities.size() && storage.lights.size() < metadata.light.max; ++i ) {
|
||||
if ( lightMetadata.renderer.mode == "in-range" && shadowUpdateThreshold-- > 0 ) {
|
||||
auto& renderMode = entity->getComponent<uf::renderer::RenderTargetRenderMode>();
|
||||
renderMode.execute = true;
|
||||
renderMode.metadata.limiter.execute = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constexpr uint32_t MODE_SPLIT = 0;
|
||||
constexpr uint32_t MODE_CUBEMAP = 1;
|
||||
constexpr uint32_t MODE_SEPARATE_2DS = 2;
|
||||
|
||||
for ( uint32_t i = 0; i < entities.size(); ++i ) {
|
||||
auto& info = entities[i];
|
||||
uf::Entity* entity = info.entity;
|
||||
|
||||
if ( !info.shadows ) {
|
||||
storage.lights.emplace_back(pod::Light{
|
||||
.view = uf::matrix::identity(),
|
||||
.projection = uf::matrix::identity(),
|
||||
.position = info.position,
|
||||
.range = info.range,
|
||||
.color = info.color,
|
||||
.intensity = info.intensity,
|
||||
.type = info.type,
|
||||
.typeMap = 0,
|
||||
.indexMap = -1,
|
||||
.depthBias = info.bias,
|
||||
});
|
||||
} else {
|
||||
int32_t boundIndexMap = -1;
|
||||
int32_t boundTypeMap = 0;
|
||||
uint32_t views = 1;
|
||||
|
||||
bool hasRT = entity->hasComponent<uf::renderer::RenderTargetRenderMode>();
|
||||
if ( hasRT ) {
|
||||
auto& renderMode = entity->getComponent<uf::renderer::RenderTargetRenderMode>();
|
||||
auto& lightCamera = entity->getComponent<uf::Camera>();
|
||||
auto& lightMetadata = entity->getComponent<ext::LightBehavior::Metadata>();
|
||||
|
||||
views = renderMode.renderTarget.views;
|
||||
lightMetadata.renderer.rendered = true;
|
||||
// activate our shadow mapper if it's range-basedd
|
||||
if ( lightMetadata.renderer.mode == "in-range" && shadowUpdateThreshold-- > 0 ) {
|
||||
renderMode.execute = true;
|
||||
renderMode.metadata.limiter.execute = true;
|
||||
}
|
||||
constexpr uint32_t MODE_SPLIT = 0;
|
||||
constexpr uint32_t MODE_CUBEMAP = 1;
|
||||
constexpr uint32_t MODE_SEPARATE_2DS = 2;
|
||||
// if point light, and combining is requested
|
||||
if ( metadata.shadow.typeMap > MODE_SPLIT && renderMode.renderTarget.views == 6 ) {
|
||||
int32_t index = -1;
|
||||
// separated texture2Ds
|
||||
|
||||
if ( metadata.shadow.typeMap > MODE_SPLIT && views == 6 ) {
|
||||
// split cubemap (shouldn't actually get used)
|
||||
if ( metadata.shadow.typeMap == MODE_SEPARATE_2DS ) {
|
||||
UF_MSG_WARNING("deprecated feature used: separate Texture2Ds for shadow maps");
|
||||
index = storage.shadow2Ds.size();
|
||||
boundIndexMap = storage.shadow2Ds.size();
|
||||
boundTypeMap = MODE_SEPARATE_2DS;
|
||||
for ( auto& attachment : renderMode.renderTarget.attachments ) {
|
||||
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
|
||||
for ( size_t view = 0; view < renderMode.renderTarget.views; ++view ) {
|
||||
if (!(attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) continue;
|
||||
for ( size_t view = 0; view < views; ++view ) {
|
||||
storage.shadow2Ds.emplace_back().aliasAttachment(attachment, view);
|
||||
}
|
||||
break;
|
||||
}
|
||||
// cubemapped
|
||||
// cubemap
|
||||
} else if ( metadata.shadow.typeMap == MODE_CUBEMAP ) {
|
||||
index = storage.shadowCubes.size();
|
||||
boundIndexMap = storage.shadowCubes.size();
|
||||
boundTypeMap = MODE_CUBEMAP;
|
||||
for ( auto& attachment : renderMode.renderTarget.attachments ) {
|
||||
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
|
||||
if (!(attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) continue;
|
||||
storage.shadowCubes.emplace_back().aliasAttachment(attachment);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// separate 2D maps
|
||||
boundIndexMap = storage.shadow2Ds.size();
|
||||
for ( auto& attachment : renderMode.renderTarget.attachments ) {
|
||||
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) continue;
|
||||
if (attachment.descriptor.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) continue;
|
||||
for (size_t view = 0; view < views; ++view) {
|
||||
storage.shadow2Ds.emplace_back().aliasAttachment(attachment, view);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( storage.lights.size() < metadata.light.max ) {
|
||||
auto& lightCamera = entity->getComponent<uf::Camera>();
|
||||
|
||||
if ( !info.shadows ) boundIndexMap = -1;
|
||||
|
||||
if ( boundTypeMap > MODE_SPLIT && views == 6 ) {
|
||||
storage.lights.emplace_back(pod::Light{
|
||||
.view = lightCamera.getView(0),
|
||||
.projection = lightCamera.getProjection(0),
|
||||
@ -654,30 +685,26 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
|
||||
.color = info.color,
|
||||
.intensity = info.intensity,
|
||||
.type = info.type,
|
||||
.typeMap = metadata.shadow.typeMap,
|
||||
.indexMap = index,
|
||||
.typeMap = boundTypeMap,
|
||||
.indexMap = boundIndexMap,
|
||||
.depthBias = info.bias,
|
||||
});
|
||||
// any other shadowing light, even point lights, are split by shadow maps
|
||||
} else {
|
||||
for ( auto& attachment : renderMode.renderTarget.attachments ) {
|
||||
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
|
||||
if ( attachment.descriptor.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) continue;
|
||||
for ( size_t view = 0; view < renderMode.renderTarget.views; ++view ) {
|
||||
storage.lights.emplace_back(pod::Light{
|
||||
.view = lightCamera.getView(view),
|
||||
.projection = lightCamera.getProjection(view),
|
||||
.position = info.position,
|
||||
.range = info.range,
|
||||
.color = info.color,
|
||||
.intensity = info.intensity,
|
||||
.type = info.type,
|
||||
.typeMap = 0,
|
||||
.indexMap = storage.shadow2Ds.size(),
|
||||
.depthBias = info.bias,
|
||||
});
|
||||
storage.shadow2Ds.emplace_back().aliasAttachment(attachment, view);
|
||||
}
|
||||
for ( size_t view = 0; view < views; ++view ) {
|
||||
if ( storage.lights.size() >= metadata.light.max ) break;
|
||||
|
||||
storage.lights.emplace_back(pod::Light{
|
||||
.view = hasRT ? lightCamera.getView(view) : uf::matrix::identity(),
|
||||
.projection = hasRT ? lightCamera.getProjection(view) : uf::matrix::identity(),
|
||||
.position = info.position,
|
||||
.range = info.range,
|
||||
.color = info.color,
|
||||
.intensity = info.intensity,
|
||||
.type = info.type,
|
||||
.typeMap = 0,
|
||||
.indexMap = info.shadows ? (boundIndexMap == -1 ? -1 : boundIndexMap + view) : -1,
|
||||
.depthBias = info.bias,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1248,9 +1275,9 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, uf::renderer::Graphic
|
||||
}
|
||||
if ( shouldUpdate ) {
|
||||
// graphic.updatePipelines();
|
||||
graphic.update();
|
||||
// graphic.update();
|
||||
renderMode.rebuild = true;
|
||||
metadata.shader.invalidated = false;
|
||||
// metadata.shader.invalidated = false;
|
||||
}
|
||||
|
||||
if ( !graphic.material.hasShader(shaderType, shaderPipeline) ) {
|
||||
|
||||
@ -235,11 +235,7 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
|
||||
if ( blitter.initialized ) {
|
||||
auto descriptor = blitter.descriptor;
|
||||
//descriptor.pipeline = "lighting";
|
||||
|
||||
auto& pipeline = blitter.getPipeline( descriptor );
|
||||
auto& descriptorSet = blitter.getDescriptorSet( descriptor );
|
||||
pipeline.record( blitter, commandBuffer );
|
||||
descriptorSet.record( blitter, commandBuffer );
|
||||
blitter.record( commandBuffer, descriptor );
|
||||
}
|
||||
|
||||
// generate mipmaps
|
||||
@ -266,10 +262,7 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
|
||||
auto descriptor = blitter.descriptor;
|
||||
descriptor.pipeline = "mipmap";
|
||||
|
||||
auto& pipeline = blitter.getPipeline( descriptor );
|
||||
auto& descriptorSet = blitter.getDescriptorSet( descriptor );
|
||||
pipeline.record( blitter, commandBuffer );
|
||||
descriptorSet.record( blitter, commandBuffer );
|
||||
blitter.record( commandBuffer, descriptor );
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
@ -1961,7 +1961,7 @@ void uf::graph::reload( pod::Graph& graph, pod::Node& node ) {
|
||||
|
||||
// necessary for OpenGL because recorded descriptors have invalidated pointers
|
||||
// Vulkan doesn't care about the CPU-side mesh data
|
||||
#if UF_USE_OPENGL
|
||||
#if 1 || UF_USE_OPENGL
|
||||
uf::renderer::states::rebuild = true;
|
||||
#endif
|
||||
|
||||
|
||||
@ -553,10 +553,12 @@ void ext::gltf::load( pod::Graph& graph, const uf::stl::string& filename, const
|
||||
|
||||
auto& mesh = storage.meshes[keyName];
|
||||
auto& primitives = storage.primitives[keyName];
|
||||
|
||||
UF_MSG_DEBUG("Optimizing mesh at level {}: {}", level, keyName);
|
||||
if ( !ext::meshopt::optimize( mesh, simplify, level, print ) ) {
|
||||
UF_MSG_ERROR("Mesh optimization failed: {}", keyName );
|
||||
|
||||
if ( level ) {
|
||||
UF_MSG_DEBUG("Optimizing mesh at level {}: {}", level, keyName);
|
||||
if ( !ext::meshopt::optimize( mesh, simplify, level, print ) ) {
|
||||
UF_MSG_ERROR("Mesh optimization failed: {}", keyName );
|
||||
}
|
||||
}
|
||||
if ( lods ) {
|
||||
auto factors = ext::meshopt::computeLODs( mesh.index.count );
|
||||
|
||||
@ -23,6 +23,9 @@ namespace {
|
||||
}
|
||||
|
||||
bool ext::meshopt::optimize( uf::Mesh& mesh, float simplify, size_t o, bool verbose ) {
|
||||
if ( o == 0 ) {
|
||||
return false; // true, since theres no error technically?
|
||||
}
|
||||
if ( mesh.isInterleaved() ) {
|
||||
UF_MSG_ERROR("Optimization of interleaved meshes is currently not supported.");
|
||||
return false;
|
||||
|
||||
@ -21,6 +21,8 @@ void ext::vulkan::Buffer::swap( ext::vulkan::Buffer& buffer ) {
|
||||
std::swap(this->memoryProperties, buffer.memoryProperties);
|
||||
std::swap(this->allocation, buffer.allocation);
|
||||
std::swap(this->allocationInfo, buffer.allocationInfo);
|
||||
std::swap(this->count, buffer.count);
|
||||
std::swap(this->written, buffer.written);
|
||||
}
|
||||
ext::vulkan::Buffer ext::vulkan::Buffer::alias() const {
|
||||
ext::vulkan::Buffer buffer;
|
||||
@ -40,6 +42,8 @@ void ext::vulkan::Buffer::aliasBuffer( const ext::vulkan::Buffer& buffer ) {
|
||||
this->memoryProperties = buffer.memoryProperties;
|
||||
this->allocation = buffer.allocation;
|
||||
this->allocationInfo = buffer.allocationInfo;
|
||||
this->count = buffer.count;
|
||||
this->written = buffer.written;
|
||||
}
|
||||
|
||||
void* ext::vulkan::Buffer::map( VkDeviceSize size, VkDeviceSize offset ) {
|
||||
@ -116,10 +120,12 @@ void ext::vulkan::Buffer::destroy(bool defer) {
|
||||
// this->memoryProperties = {};
|
||||
this->allocation = {};
|
||||
this->allocationInfo = {};
|
||||
this->count = 1;
|
||||
this->written = false;
|
||||
}
|
||||
void ext::vulkan::Buffer::initialize( const void* data, VkDeviceSize length, VkBufferUsageFlags usage, VkMemoryPropertyFlags memoryProperties, bool stage ) {
|
||||
void ext::vulkan::Buffer::initialize( const void* data, VkDeviceSize length, VkBufferUsageFlags usage, VkMemoryPropertyFlags memoryProperties ) {
|
||||
if ( !device ) device = &ext::vulkan::device;
|
||||
if ( stage ) usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; // implicitly set properties
|
||||
if ( VK_DEFAULT_STAGE_BUFFERS ) usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; // implicitly set properties
|
||||
|
||||
// assume all UBOs are dynamic
|
||||
auto totalLength = length;
|
||||
@ -130,56 +136,16 @@ void ext::vulkan::Buffer::initialize( const void* data, VkDeviceSize length, VkB
|
||||
totalLength = ALIGNED_SIZE( length, this->alignment ) * this->count;
|
||||
}
|
||||
#endif
|
||||
VK_CHECK_RESULT(device->createBuffer( nullptr, totalLength, usage, memoryProperties, *this ));
|
||||
|
||||
VK_CHECK_RESULT(device->createBuffer(
|
||||
nullptr,
|
||||
totalLength,
|
||||
usage,
|
||||
memoryProperties,
|
||||
*this
|
||||
));
|
||||
|
||||
if ( length != totalLength ) {
|
||||
this->updateDescriptor( length, 0 );
|
||||
}
|
||||
|
||||
if ( data && length ) update( data, length, stage );
|
||||
|
||||
/*
|
||||
{
|
||||
uf::stl::string type;
|
||||
|
||||
if ( usage & VK_BUFFER_USAGE_TRANSFER_SRC_BIT ) type += "transfer_src,";
|
||||
if ( usage & VK_BUFFER_USAGE_TRANSFER_DST_BIT ) type += "transfer_dst,";
|
||||
if ( usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT ) type += "uniform_texel,";
|
||||
if ( usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT ) type += "storage_texel,";
|
||||
if ( usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT ) type += "uniform,";
|
||||
if ( usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT ) type += "storage,";
|
||||
if ( usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT ) type += "index,";
|
||||
if ( usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT ) type += "vertex,";
|
||||
if ( usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT ) type += "indirect,";
|
||||
if ( usage & VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR ) type += "acceleration_structure,";
|
||||
if ( usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT ) type += "address,";
|
||||
if ( usage & VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR ) type += "binding_table,";
|
||||
|
||||
UF_MSG_DEBUG("CREATING BUFFER: {}: {}({})", fmt::ptr(this->buffer), type, usage);
|
||||
}
|
||||
*/
|
||||
|
||||
this->usage = usage;
|
||||
if ( length != totalLength ) this->updateDescriptor( length, 0 );
|
||||
if ( data && length ) update( data, length );
|
||||
}
|
||||
bool ext::vulkan::Buffer::update( const void* data, VkDeviceSize length, bool stage ) const {
|
||||
bool ext::vulkan::Buffer::update( const void* data, VkDeviceSize length ) const {
|
||||
// if ( !data || !length ) return false;
|
||||
if ( !length ) return false;
|
||||
if ( !buffer ) return false;
|
||||
|
||||
VkDeviceSize offset = 0;
|
||||
#if VK_UBO_USE_N_BUFFERS
|
||||
if ( this->count == ext::vulkan::swapchain.buffers ) {
|
||||
offset = this->getOffset( states::currentBuffer );
|
||||
}
|
||||
#endif
|
||||
|
||||
// to-do: fix this because it's a thorn in my side when a mesh needs to update
|
||||
if ( length > allocationInfo.size ) {
|
||||
UF_MSG_WARNING("Buffer update of {} exceeds buffer size of {}", length, allocationInfo.size);
|
||||
@ -192,15 +158,40 @@ bool ext::vulkan::Buffer::update( const void* data, VkDeviceSize length, bool st
|
||||
|
||||
self.destroy(true);
|
||||
self.initialize(*device, savedAlignment);
|
||||
self.initialize(data, length, savedUsage, savedMemProps, stage);
|
||||
self.initialize(data, length, savedUsage, savedMemProps);
|
||||
|
||||
return true;
|
||||
}
|
||||
if ( !data ) return false;
|
||||
if ( !stage ) {
|
||||
|
||||
bool broadcast = !this->written;
|
||||
this->written = true;
|
||||
|
||||
STATIC_THREAD_LOCAL(uf::stl::vector<VkBufferCopy>, regions);
|
||||
|
||||
if ( broadcast && this->count > 1 ) {
|
||||
for ( size_t i = 0; i < this->count; i++ ) {
|
||||
auto& region = regions.emplace_back();
|
||||
region.size = length;
|
||||
region.srcOffset = 0;
|
||||
region.dstOffset = this->getOffset( i );
|
||||
}
|
||||
} else {
|
||||
auto& region = regions.emplace_back();
|
||||
region.size = length;
|
||||
region.srcOffset = 0;
|
||||
region.dstOffset = 0;
|
||||
#if VK_UBO_USE_N_BUFFERS
|
||||
if ( this->count == ext::vulkan::swapchain.buffers ) {
|
||||
region.dstOffset = this->getOffset( states::currentBuffer );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if ( !VK_DEFAULT_STAGE_BUFFERS ) {
|
||||
auto* self = const_cast<ext::vulkan::Buffer*>(this);
|
||||
void* map = self->map(length, offset);
|
||||
memcpy(map, data, length);
|
||||
void* map = self->map(length);
|
||||
for ( const auto& region : regions ) memcpy(static_cast<char*>(map) + region.dstOffset, data, length);
|
||||
self->unmap();
|
||||
return false;
|
||||
}
|
||||
@ -208,18 +199,12 @@ bool ext::vulkan::Buffer::update( const void* data, VkDeviceSize length, bool st
|
||||
ext::vulkan::Device* device = this->device ? this->device : &ext::vulkan::device;
|
||||
|
||||
Buffer staging = device->fetchTransientBuffer(
|
||||
// Buffer staging = device->createBuffer(
|
||||
data,
|
||||
length,
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
|
||||
data, length,
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
|
||||
);
|
||||
auto commandBuffer = device->fetchCommandBuffer(QueueEnum::TRANSFER); // waits on finish
|
||||
VkBufferCopy region = {};
|
||||
region.size = length;
|
||||
region.dstOffset = offset;
|
||||
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "copyBuffer" );
|
||||
vkCmdCopyBuffer(commandBuffer, staging.buffer, buffer, 1, ®ion);
|
||||
vkCmdCopyBuffer(commandBuffer, staging.buffer, buffer, regions.size(), regions.data());
|
||||
device->flushCommandBuffer(commandBuffer);
|
||||
return false;
|
||||
}
|
||||
@ -240,14 +225,14 @@ void ext::vulkan::Buffers::destroy(bool defer) {
|
||||
buffers.clear();
|
||||
}
|
||||
|
||||
size_t ext::vulkan::Buffers::initializeBuffer( const void* data, VkDeviceSize length, VkBufferUsageFlags usage, VkMemoryPropertyFlags memoryProperties, bool stage ) {
|
||||
size_t ext::vulkan::Buffers::initializeBuffer( const void* data, VkDeviceSize length, VkBufferUsageFlags usage, VkMemoryPropertyFlags memoryProperties ) {
|
||||
size_t index = buffers.size();
|
||||
auto& buffer = buffers.emplace_back();
|
||||
buffer.initialize( *device, requestedAlignment );
|
||||
buffer.initialize( data, length, usage, memoryProperties, stage );
|
||||
buffer.initialize( data, length, usage, memoryProperties );
|
||||
return index;
|
||||
}
|
||||
bool ext::vulkan::Buffers::updateBuffer( const void* data, VkDeviceSize length, const Buffer& buffer, bool stage ) const {
|
||||
return buffer.update( data, length, stage );
|
||||
bool ext::vulkan::Buffers::updateBuffer( const void* data, VkDeviceSize length, const Buffer& buffer ) const {
|
||||
return buffer.update( data, length );
|
||||
}
|
||||
#endif
|
||||
@ -609,7 +609,7 @@ uint32_t ext::vulkan::Device::getMemoryType( uint32_t typeBits, VkMemoryProperty
|
||||
UF_EXCEPTION("Vulkan error: could not find a matching memory type");
|
||||
}
|
||||
|
||||
VkCommandBuffer ext::vulkan::Device::createCommandBuffer( VkCommandBufferLevel level, QueueEnum queue, bool begin ){
|
||||
VkCommandBuffer ext::vulkan::Device::createCommandBuffer( VkCommandBufferLevel level, QueueEnum queue, bool begin, bool singleton ){
|
||||
VkCommandBufferAllocateInfo cmdBufAllocateInfo = ext::vulkan::initializers::commandBufferAllocateInfo( getCommandPool(queue), level, 1 );
|
||||
|
||||
VkCommandBuffer commandBuffer;
|
||||
@ -617,6 +617,8 @@ VkCommandBuffer ext::vulkan::Device::createCommandBuffer( VkCommandBufferLevel l
|
||||
// If requested, also start recording for the new command buffer
|
||||
if ( begin ) {
|
||||
VkCommandBufferBeginInfo cmdBufInfo = ext::vulkan::initializers::commandBufferBeginInfo();
|
||||
if ( singleton ) cmdBufInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
|
||||
VK_CHECK_RESULT( vkBeginCommandBuffer( commandBuffer, &cmdBufInfo ) );
|
||||
UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::BEGIN, "begin" );
|
||||
}
|
||||
@ -674,7 +676,7 @@ ext::vulkan::CommandBuffer ext::vulkan::Device::fetchCommandBuffer( ext::vulkan:
|
||||
return {
|
||||
.immediate = immediate,
|
||||
.queueType = queueType,
|
||||
.handle = this->createCommandBuffer( level, queueType, true ),
|
||||
.handle = this->createCommandBuffer( level, queueType, true, true ),
|
||||
.threadId = std::this_thread::get_id(),
|
||||
};
|
||||
}
|
||||
@ -1346,6 +1348,7 @@ void ext::vulkan::Device::initialize() {
|
||||
accelerationStructureFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR;
|
||||
accelerationStructureFeatures.accelerationStructure = VK_TRUE;
|
||||
// accelerationStructureFeatures.accelerationStructureHostCommands = VK_TRUE;
|
||||
accelerationStructureFeatures.descriptorBindingAccelerationStructureUpdateAfterBind = VK_TRUE;
|
||||
chain.push( &accelerationStructureFeatures );
|
||||
VK_VALIDATION_MESSAGE("Enabled feature chain: {}", "accelerationStructureFeatures" );
|
||||
}
|
||||
@ -1698,7 +1701,7 @@ void ext::vulkan::DescriptorAllocator::destroy() {
|
||||
VkDescriptorPool ext::vulkan::DescriptorAllocator::createPool() {
|
||||
VkDescriptorPoolCreateInfo poolInfo = {};
|
||||
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||
poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
|
||||
poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT | VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT;
|
||||
poolInfo.maxSets = 1000;
|
||||
poolInfo.poolSizeCount = (uint32_t) poolSizes.size();
|
||||
poolInfo.pPoolSizes = poolSizes.data();
|
||||
|
||||
@ -48,8 +48,6 @@ void ext::vulkan::Pipeline::initialize( const Graphic& graphic, const GraphicDes
|
||||
|
||||
auto shaders = graphic.material.getShaders( descriptor.pipeline );
|
||||
assert( shaders.size() > 0 );
|
||||
|
||||
uint32_t subpass = descriptor.subpass;
|
||||
|
||||
uf::stl::vector<VkDescriptorSetLayoutBinding> descriptorSetLayoutBindings;
|
||||
uf::stl::vector<VkPushConstantRange> pushConstantRanges;
|
||||
@ -61,22 +59,41 @@ void ext::vulkan::Pipeline::initialize( const Graphic& graphic, const GraphicDes
|
||||
uf::stl::vector<VkSpecializationInfo> shaderSpecializationInfos;
|
||||
uf::stl::vector<VkVertexInputBindingDescription> inputBindingDescriptions;
|
||||
uf::stl::vector<VkVertexInputAttributeDescription> attributeDescriptions;
|
||||
{
|
||||
|
||||
for ( auto* shaderPointer : shaders ) {
|
||||
auto& shader = *shaderPointer;
|
||||
descriptorSetLayoutBindings.insert( descriptorSetLayoutBindings.end(), shader.descriptorSetLayoutBindings.begin(), shader.descriptorSetLayoutBindings.end() );
|
||||
{
|
||||
uf::stl::vector<VkDescriptorBindingFlags> bindingFlags;
|
||||
|
||||
bool hasDynamicBuffer = false;
|
||||
for ( auto* shader : shaders ) {
|
||||
for ( auto& binding : shader->descriptorSetLayoutBindings ) {
|
||||
switch ( binding.descriptorType ) {
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
||||
hasDynamicBuffer = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ( auto* shader : shaders ) {
|
||||
for ( auto& binding : shader->descriptorSetLayoutBindings ) {
|
||||
descriptorSetLayoutBindings.emplace_back( binding );
|
||||
auto& flags = bindingFlags.emplace_back();
|
||||
|
||||
flags |= VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT;
|
||||
if ( !hasDynamicBuffer ) flags |= VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT;
|
||||
}
|
||||
|
||||
size_t offset = 0;
|
||||
for ( auto& pushConstant : shader.pushConstants ) {
|
||||
for ( auto& pushConstant : shader->pushConstants ) {
|
||||
size_t len = pushConstant.data().len;
|
||||
if ( len <= 0 || len > device.properties.limits.maxPushConstantsSize ) {
|
||||
VK_DEBUG_VALIDATION_MESSAGE("Invalid push constant length of {} for shader {}", len, shader.filename);
|
||||
VK_DEBUG_VALIDATION_MESSAGE("Invalid push constant length of {} for shader {}", len, shader->filename);
|
||||
// goto PIPELINE_INITIALIZATION_INVALID;
|
||||
len = device.properties.limits.maxPushConstantsSize;
|
||||
}
|
||||
pushConstantRanges.emplace_back(ext::vulkan::initializers::pushConstantRange(
|
||||
shader.descriptor.stage,
|
||||
shader->descriptor.stage,
|
||||
len,
|
||||
offset
|
||||
));
|
||||
@ -84,10 +101,19 @@ void ext::vulkan::Pipeline::initialize( const Graphic& graphic, const GraphicDes
|
||||
}
|
||||
}
|
||||
|
||||
VkDescriptorSetLayoutBindingFlagsCreateInfo layoutBindingFlags = {};
|
||||
layoutBindingFlags.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO;
|
||||
layoutBindingFlags.bindingCount = bindingFlags.size();
|
||||
layoutBindingFlags.pBindingFlags = bindingFlags.data();
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo descriptorLayout = ext::vulkan::initializers::descriptorSetLayoutCreateInfo(
|
||||
descriptorSetLayoutBindings.data(),
|
||||
descriptorSetLayoutBindings.size()
|
||||
);
|
||||
|
||||
descriptorLayout.flags |= VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT;
|
||||
descriptorLayout.pNext = &layoutBindingFlags;
|
||||
|
||||
VK_CHECK_RESULT(vkCreateDescriptorSetLayout( device, &descriptorLayout, nullptr, &descriptorSetLayout ));
|
||||
VK_REGISTER_HANDLE( descriptorSetLayout );
|
||||
|
||||
@ -189,16 +215,15 @@ void ext::vulkan::Pipeline::initialize( const Graphic& graphic, const GraphicDes
|
||||
}
|
||||
|
||||
// Compute
|
||||
for ( auto* shaderPointer : shaders ) {
|
||||
auto& shader = *shaderPointer;
|
||||
if ( shader.descriptor.stage != VK_SHADER_STAGE_COMPUTE_BIT ) continue;
|
||||
for ( auto* shader : shaders ) {
|
||||
if ( shader->descriptor.stage != VK_SHADER_STAGE_COMPUTE_BIT ) continue;
|
||||
|
||||
// Create compute shader pipelines
|
||||
VkComputePipelineCreateInfo computePipelineCreateInfo = ext::vulkan::initializers::computePipelineCreateInfo(
|
||||
pipelineLayout,
|
||||
0
|
||||
);
|
||||
computePipelineCreateInfo.stage = shader.descriptor;
|
||||
computePipelineCreateInfo.stage = shader->descriptor;
|
||||
VK_CHECK_RESULT(vkCreateComputePipelines(device, device.pipelineCache, 1, &computePipelineCreateInfo, nullptr, &pipeline));
|
||||
VK_REGISTER_HANDLE( pipeline );
|
||||
|
||||
@ -242,8 +267,6 @@ void ext::vulkan::Pipeline::initialize( const Graphic& graphic, const GraphicDes
|
||||
}
|
||||
}
|
||||
} else {
|
||||
subpass = 0;
|
||||
|
||||
VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState(
|
||||
descriptor.blend.colorWriteMask,
|
||||
descriptor.blend.enabled ? VK_TRUE : VK_FALSE
|
||||
@ -507,7 +530,9 @@ void ext::vulkan::DescriptorSet::record( const Graphic& graphic, const GraphicDe
|
||||
else continue;
|
||||
}
|
||||
|
||||
#if VK_UBO_USE_N_BUFFERS
|
||||
dynamicOffsets.insert( dynamicOffsets.end(), shader->metadata.dynamicRanges.begin(), shader->metadata.dynamicRanges.end() );
|
||||
#endif
|
||||
}
|
||||
|
||||
for ( auto& dynamicOffset : dynamicOffsets ) {
|
||||
@ -520,44 +545,7 @@ void ext::vulkan::DescriptorSet::record( const Graphic& graphic, const GraphicDe
|
||||
}
|
||||
|
||||
// Bind descriptor sets describing shader binding points
|
||||
#if VK_UBO_USE_N_BUFFERS
|
||||
vkCmdBindDescriptorSets(commandBuffer, (VkPipelineBindPoint) descriptor.bind.point, pipeline.pipelineLayout, 0, 1, &descriptorSet, dynamicOffsets.size(), dynamicOffsets.data());
|
||||
#else
|
||||
vkCmdBindDescriptorSets(commandBuffer, (VkPipelineBindPoint) descriptor.bind.point, pipeline.pipelineLayout, 0, 1, &descriptorSet, 0, nullptr);
|
||||
#endif
|
||||
|
||||
uint32_t width = descriptor.bind.width ? descriptor.bind.width : ext::vulkan::settings::width;
|
||||
uint32_t height = descriptor.bind.height ? descriptor.bind.height : ext::vulkan::settings::height;
|
||||
uint32_t depth = descriptor.bind.depth ? descriptor.bind.depth : 1;
|
||||
|
||||
if ( descriptor.bind.point == VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR ) {
|
||||
uf::renderer::vkCmdTraceRaysKHR(
|
||||
commandBuffer,
|
||||
&pipeline.sbtEntries[0],
|
||||
&pipeline.sbtEntries[1],
|
||||
&pipeline.sbtEntries[2],
|
||||
&pipeline.sbtEntries[3],
|
||||
width,
|
||||
height,
|
||||
1
|
||||
);
|
||||
} else if ( descriptor.bind.point == VK_PIPELINE_BIND_POINT_COMPUTE ) {
|
||||
for ( auto* shader : shaders ) {
|
||||
if ( shader->descriptor.stage != VK_SHADER_STAGE_COMPUTE_BIT ) continue;
|
||||
auto& localSize = shader->metadata.definitions.localSize;
|
||||
auto dispatch = pod::Vector3ui{
|
||||
std::ceil( (float) width / localSize.x ),
|
||||
std::ceil( (float) height / localSize.y ),
|
||||
std::ceil( (float) depth / localSize.z ),
|
||||
};
|
||||
|
||||
vkCmdDispatch(commandBuffer,
|
||||
dispatch.x,
|
||||
dispatch.y,
|
||||
dispatch.z
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
void ext::vulkan::DescriptorSet::update( const Graphic& graphic ) {
|
||||
return this->update( graphic, descriptor );
|
||||
@ -1637,24 +1625,32 @@ void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vect
|
||||
size_t tlasBufferIndex{};
|
||||
size_t tlasBackBufferIndex{};
|
||||
|
||||
// do not stage, because apparently vkQueueWaitIdle doesn't actually wait for the transfer to complete
|
||||
// manually copy because I can't be assed to expose an un-staged API now
|
||||
if ( !update ) {
|
||||
// do not stage, because apparently vkQueueWaitIdle doesn't actually wait for the transfer to complete
|
||||
this->requestedAlignment = 16;
|
||||
instanceIndex = this->initializeBuffer(
|
||||
instanceIndex = this->buffers.size();
|
||||
auto& buffer = this->buffers.emplace_back();
|
||||
buffer.alignment = 16;
|
||||
device.createBuffer(
|
||||
(const void*) instancesVK.data(), instancesVK.size() * sizeof(VkAccelerationStructureInstanceKHR),
|
||||
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, false
|
||||
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
buffer
|
||||
);
|
||||
this->requestedAlignment = 0;
|
||||
this->metadata.buffers["tlasInstance"] = instanceIndex;
|
||||
} else {
|
||||
if ( this->metadata.buffers.count("tlasInstance") > 0 ) {
|
||||
instanceIndex = this->metadata.buffers["tlasInstance"];
|
||||
} else UF_EXCEPTION("Buffers not found: {}", "tlasInstance");
|
||||
/*rebuild = rebuild ||*/ this->updateBuffer( (const void*) instancesVK.data(), instancesVK.size() * sizeof(VkAccelerationStructureInstanceKHR), instanceIndex, false );
|
||||
|
||||
auto& buffer = this->buffers.at(instanceIndex);
|
||||
void* map = buffer.map();
|
||||
memcpy(map, instancesVK.data(), instancesVK.size() * sizeof(VkAccelerationStructureInstanceKHR));
|
||||
buffer.unmap();
|
||||
}
|
||||
|
||||
size_t instanceBufferAddress = this->buffers[instanceIndex].getAddress();
|
||||
auto& tlas = this->accelerationStructures.tops[0];
|
||||
auto& tlas = this->accelerationStructures.tops[0];
|
||||
|
||||
{
|
||||
VkBuildAccelerationStructureFlagsKHR flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR | VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR;
|
||||
@ -1930,6 +1926,42 @@ void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, const GraphicD
|
||||
descriptorSet.record( *this, descriptor, commandBuffer, pass, draw, offset );
|
||||
|
||||
auto shaders = material.getShaders( descriptor.pipeline );
|
||||
|
||||
uint32_t width = descriptor.bind.width ? descriptor.bind.width : ext::vulkan::settings::width;
|
||||
uint32_t height = descriptor.bind.height ? descriptor.bind.height : ext::vulkan::settings::height;
|
||||
uint32_t depth = descriptor.bind.depth ? descriptor.bind.depth : 1;
|
||||
|
||||
if ( descriptor.bind.point == VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR ) {
|
||||
uf::renderer::vkCmdTraceRaysKHR(
|
||||
commandBuffer,
|
||||
&pipeline.sbtEntries[0],
|
||||
&pipeline.sbtEntries[1],
|
||||
&pipeline.sbtEntries[2],
|
||||
&pipeline.sbtEntries[3],
|
||||
width,
|
||||
height,
|
||||
1
|
||||
);
|
||||
return;
|
||||
}
|
||||
if ( descriptor.bind.point == VK_PIPELINE_BIND_POINT_COMPUTE ) {
|
||||
for ( auto* shader : shaders ) {
|
||||
if ( shader->descriptor.stage != VK_SHADER_STAGE_COMPUTE_BIT ) continue;
|
||||
auto& localSize = shader->metadata.definitions.localSize;
|
||||
auto dispatch = pod::Vector3ui{
|
||||
std::ceil( (float) width / localSize.x ),
|
||||
std::ceil( (float) height / localSize.y ),
|
||||
std::ceil( (float) depth / localSize.z ),
|
||||
};
|
||||
|
||||
vkCmdDispatch(commandBuffer,
|
||||
dispatch.x,
|
||||
dispatch.y,
|
||||
dispatch.z
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
for ( auto* shader : shaders ) {
|
||||
if ( shader->descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT ) return;
|
||||
if (
|
||||
|
||||
@ -118,10 +118,10 @@ void ext::vulkan::BaseRenderMode::render() {
|
||||
|
||||
//lockMutex( this->mostRecentCommandPoolId );
|
||||
auto& commands = getCommands( this->mostRecentCommandPoolId );
|
||||
|
||||
VK_CHECK_RESULT(swapchain.acquireNextImage(&states::currentBuffer, swapchain.presentCompleteSemaphores[0]));
|
||||
|
||||
uint32_t imageIndex;
|
||||
|
||||
VK_CHECK_RESULT(vkWaitForFences(*device, 1, &fences[states::currentBuffer], VK_TRUE, VK_DEFAULT_FENCE_TIMEOUT));
|
||||
VK_CHECK_RESULT(swapchain.acquireNextImage(&imageIndex, swapchain.presentCompleteSemaphores[states::currentBuffer]));
|
||||
VK_CHECK_RESULT(vkResetFences(*device, 1, &fences[states::currentBuffer]));
|
||||
|
||||
VkPipelineStageFlags waitStageMask[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
|
||||
@ -129,7 +129,7 @@ void ext::vulkan::BaseRenderMode::render() {
|
||||
VkSubmitInfo submitInfo = {};
|
||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
submitInfo.pWaitDstStageMask = waitStageMask;
|
||||
submitInfo.pWaitSemaphores = &swapchain.presentCompleteSemaphores[0];
|
||||
submitInfo.pWaitSemaphores = &swapchain.presentCompleteSemaphores[states::currentBuffer];
|
||||
submitInfo.waitSemaphoreCount = 1;
|
||||
submitInfo.pSignalSemaphores = &renderCompleteSemaphores[states::currentBuffer];
|
||||
submitInfo.signalSemaphoreCount = 1;
|
||||
@ -142,8 +142,7 @@ void ext::vulkan::BaseRenderMode::render() {
|
||||
VK_CHECK_QUEUE_CHECKPOINT( queue, res );
|
||||
}
|
||||
|
||||
VK_CHECK_RESULT(swapchain.queuePresent(device->getQueue( QueueEnum::PRESENT ), states::currentBuffer, renderCompleteSemaphores[states::currentBuffer]));
|
||||
|
||||
VK_CHECK_RESULT(swapchain.queuePresent(device->getQueue( QueueEnum::PRESENT ), imageIndex, renderCompleteSemaphores[states::currentBuffer]));
|
||||
#if 0
|
||||
{
|
||||
VkQueue queue = device->getQueue( QueueEnum::PRESENT );
|
||||
@ -152,6 +151,7 @@ void ext::vulkan::BaseRenderMode::render() {
|
||||
}
|
||||
#endif
|
||||
|
||||
states::currentBuffer = (states::currentBuffer + 1) % ext::vulkan::swapchain.buffers;
|
||||
this->executed = true;
|
||||
|
||||
//unlockMutex( this->mostRecentCommandPoolId );
|
||||
@ -183,9 +183,8 @@ void ext::vulkan::BaseRenderMode::createCommandBuffers( const uf::stl::vector<ex
|
||||
float width = windowSize.x; //this->width > 0 ? this->width : windowSize.x;
|
||||
float height = windowSize.y; //this->height > 0 ? this->height : windowSize.y;
|
||||
|
||||
VkCommandBufferBeginInfo cmdBufInfo = {};
|
||||
cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
cmdBufInfo.pNext = nullptr;
|
||||
VkCommandBufferBeginInfo cmdBufInfo = ext::vulkan::initializers::commandBufferBeginInfo();
|
||||
cmdBufInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
|
||||
|
||||
VkImageMemoryBarrier imageMemoryBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
|
||||
imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED
|
||||
|
||||
@ -695,9 +695,8 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
|
||||
uint32_t width = this->width > 0 ? this->width : (ext::vulkan::settings::width * this->scale);
|
||||
uint32_t height = this->height > 0 ? this->height : (ext::vulkan::settings::height * this->scale);
|
||||
|
||||
VkCommandBufferBeginInfo cmdBufInfo = {};
|
||||
cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
cmdBufInfo.pNext = nullptr;
|
||||
VkCommandBufferBeginInfo cmdBufInfo = ext::vulkan::initializers::commandBufferBeginInfo();
|
||||
cmdBufInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
|
||||
|
||||
VkImageMemoryBarrier imageMemoryBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
|
||||
imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED
|
||||
|
||||
@ -312,9 +312,8 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const uf::stl::v
|
||||
uint32_t width = this->width > 0 ? this->width : (ext::vulkan::settings::width * this->scale);
|
||||
uint32_t height = this->height > 0 ? this->height : (ext::vulkan::settings::height * this->scale);
|
||||
|
||||
VkCommandBufferBeginInfo cmdBufInfo = {};
|
||||
cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
cmdBufInfo.pNext = nullptr;
|
||||
VkCommandBufferBeginInfo cmdBufInfo = ext::vulkan::initializers::commandBufferBeginInfo();
|
||||
cmdBufInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
|
||||
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user