Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First Timeline Semaphore use #158

Open
wants to merge 17 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ option(avk_toolkit_BuildTextureCubemap "Build example: texture_cubemap." OFF)
option(avk_toolkit_BuildVertexBuffers "Build example: vertex_buffers." OFF)
option(avk_toolkit_BuildMultipleQueues "Build example: multiple_queues." OFF)
option(avk_toolkit_BuildPresentFromCompute "Build example: present_from_compute." OFF)
option(avk_toolkit_BuildParticles "Build example: particles." OFF)

if (avk_toolkit_BuildExamples)
set(avk_toolkit_BuildHelloWorld ON)
Expand All @@ -70,6 +71,7 @@ if (avk_toolkit_BuildExamples)
set(avk_toolkit_BuildVertexBuffers ON)
set(avk_toolkit_BuildMultipleQueues ON)
set(avk_toolkit_BuildPresentFromCompute ON)
set(avk_toolkit_BuildParticles ON)
endif()

# ---------------------- Auto-Vk-Toolkit Framework ------------------------
Expand Down Expand Up @@ -290,3 +292,8 @@ endif()
if (avk_toolkit_BuildPresentFromCompute)
add_subdirectory(examples/present_from_compute)
endif()

## particles
if (avk_toolkit_BuildParticles)
add_subdirectory(examples/particles)
endif()
2 changes: 1 addition & 1 deletion auto_vk
19 changes: 19 additions & 0 deletions auto_vk_toolkit/include/context_vulkan.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,25 @@ namespace avk

avk::semaphore record_and_submit_with_semaphore(std::vector<avk::recorded_commands_t> aRecordedCommandsAndSyncInstructions, const avk::queue& aQueue, avk::stage::pipeline_stage_flags aSrcSignalStage, vk::CommandBufferUsageFlags aUsageFlags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit);

/** @brief Records and submits commands to a queue together with a newly created timeline semaphore, which is signaled upon completion.
* @param aRecordedCommandsAndSyncInstructions List of commands to record and submit.
* @param aQueue The queue to submit the commands to.
* @param aSrcSignalStage Defines in which stage it is safe to signal the created timeline semaphore.
* @param aSignalValue The value to SIGNAL the timeline semaphore to.
* @param aInitialValue (optional) The value to INITIALIZE the newly created timeline semaphore with.
* @param aUsageFlags (optional) CommandBuffer usage flags.
* @return The newly created timeline semaphore.
*/
Comment on lines +183 to +190
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @param aRecordedCommandsAndSyncInstructions List of commands to record and submit.
* @param aQueue The queue to submit the commands to.
* @param aSrcSignalStage Defines in which stage it is safe to signal the created timeline semaphore.
* @param aSignalValue The value to SIGNAL the timeline semaphore to.
* @param aInitialValue (optional) The value to INITIALIZE the newly created timeline semaphore with.
* @param aUsageFlags (optional) CommandBuffer usage flags.
* @return The newly created timeline semaphore.
*/
* @param aRecordedCommandsAndSyncInstructions List of commands to record and submit.
* @param aQueue The queue to submit the commands to.
* @param aSrcSignalStage Defines in which stage it is safe to signal the created timeline semaphore.
* @param aSignalValue The value to SIGNAL the timeline semaphore to.
* @param aInitialValue (optional) The value to INITIALIZE the newly created timeline semaphore with.
* @param aUsageFlags (optional) CommandBuffer usage flags.
* @return The newly created timeline semaphore.
*/

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add spaces before the *, so that all * are vertically aligned!

avk::semaphore record_and_submit_with_timeline_semaphore(std::vector<avk::recorded_commands_t> aRecordedCommandsAndSyncInstructions, const avk::queue& aQueue, avk::stage::pipeline_stage_flags aSrcSignalStage, uint64_t aSignalValue, uint64_t aInitialValue = 0, vk::CommandBufferUsageFlags aUsageFlags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit);

/** @brief Records and submits commands to a queue together with the given timeline semaphore, which is signaled upon completion.
* @param aRecordedCommandsAndSyncInstructions List of commands to record and submit.
* @param aQueue The queue to submit the commands to.
* @param aSignalInfo Used to specify the timeline semaphore, after which stage it's supposed to be triggered, and to which value it should be set.
* @param aUsageFlags (optional) CommandBuffer usage flags.
*/
void record_and_submit_with_timeline_semaphore(std::vector<avk::recorded_commands_t> aRecordedCommandsAndSyncInstructions, const avk::queue& aQueue, avk::semaphore_signal_info aSignalInfo, vk::CommandBufferUsageFlags aUsageFlags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit);

avk::fence record_and_submit_with_fence(std::vector<avk::recorded_commands_t> aRecordedCommandsAndSyncInstructions, const avk::queue& aQueue, vk::CommandBufferUsageFlags aUsageFlags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit);

public: // TODO: private
Expand Down
19 changes: 19 additions & 0 deletions auto_vk_toolkit/src/context_vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,25 @@ namespace avk
return sem;
}

avk::semaphore context_vulkan::record_and_submit_with_timeline_semaphore(std::vector<avk::recorded_commands_t> aRecordedCommandsAndSyncInstructions, const avk::queue& aQueue, avk::stage::pipeline_stage_flags aSrcSignalStage, uint64_t aSignalValue, uint64_t aInitialValue, vk::CommandBufferUsageFlags aUsageFlags) {
auto sem = create_timeline_semaphore(aInitialValue);
record_and_submit_with_timeline_semaphore(std::move(aRecordedCommandsAndSyncInstructions), aQueue, aSrcSignalStage >> (sem = aSignalValue), aUsageFlags);
return sem;
}

void context_vulkan::record_and_submit_with_timeline_semaphore(std::vector<avk::recorded_commands_t> aRecordedCommandsAndSyncInstructions, const avk::queue& aQueue, avk::semaphore_signal_info aSignalInfo, vk::CommandBufferUsageFlags aUsageFlags) {
auto& cmdPool = get_command_pool_for_single_use_command_buffers(aQueue);
auto cmdBfr = cmdPool->alloc_command_buffer(aUsageFlags);

record(std::move(aRecordedCommandsAndSyncInstructions))
.into_command_buffer(cmdBfr)
.then_submit_to(aQueue)
.signaling_upon_completion(aSignalInfo)
.submit();

aSignalInfo.mSignalSemaphore.get().handle_lifetime_of(std::move(cmdBfr), aSignalInfo.mValue);
}

avk::fence context_vulkan::record_and_submit_with_fence(std::vector<avk::recorded_commands_t> aRecordedCommandsAndSyncInstructions, const avk::queue& aQueue, vk::CommandBufferUsageFlags aUsageFlags)
{
auto& cmdPool = get_command_pool_for_single_use_command_buffers(aQueue);
Expand Down
15 changes: 9 additions & 6 deletions examples/model_loader/source/model_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,15 @@ class model_loader_app : public avk::invokee
auto idxFillCmd = newElement.mIndexBuffer->fill(newElement.mIndices.data(), 0);

// Submit all the fill commands to the queue:
auto fence = avk::context().record_and_submit_with_fence({
auto timelineSemaphore = avk::context().record_and_submit_with_timeline_semaphore({
std::move(posFillCmd),
std::move(tcoFillCmd),
std::move(nrmFillCmd),
std::move(idxFillCmd)
// ^ No need for any synchronization in-between, because the commands do not depend on each other.
}, *mQueue);
}, *mQueue, avk::stage::all_transfer, 1);
// Wait on the host until the device is done:
fence->wait_until_signalled();
timelineSemaphore->wait_until_signaled(1);
}

// For all the different materials, transfer them in structs which are well
Expand All @@ -139,11 +139,11 @@ class model_loader_app : public avk::invokee
);

// Submit the commands material commands and the materials buffer fill to the device:
auto matFence = avk::context().record_and_submit_with_fence({
auto matTSemaphore = avk::context().record_and_submit_with_timeline_semaphore({
std::move(materialCommands),
mMaterialBuffer->fill(gpuMaterials.data(), 0)
}, *mQueue);
matFence->wait_until_signalled();
}, *mQueue, avk::stage::all_commands, 1);
matTSemaphore->wait_until_signaled(1);

// Create a buffer for the transformation matrices in a host coherent memory region (one for each frame in flight):
for (int i = 0; i < 10; ++i) { // Up to 10 concurrent frames can be configured through the UI.
Expand Down Expand Up @@ -468,6 +468,9 @@ int main() // <== Starting point ==
[](avk::validation_layers& config) {
config.enable_feature(vk::ValidationFeatureEnableEXT::eSynchronizationValidation);
},
[](vk::PhysicalDeviceVulkan12Features& features) {
features.setTimelineSemaphore(VK_TRUE);
},
// Pass windows:
mainWnd,
// Pass invokees:
Expand Down
13 changes: 13 additions & 0 deletions examples/particles/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
add_executable(particles
source/hello_world.cpp)
target_include_directories(particles PRIVATE ${PROJECT_NAME})
target_link_libraries(particles PRIVATE ${PROJECT_NAME})

get_target_property(particles_BINARY_DIR particles BINARY_DIR)

add_post_build_commands(particles
${PROJECT_SOURCE_DIR}/examples/particles/shaders
${particles_BINARY_DIR}/shaders
$<TARGET_FILE_DIR:particles>/assets
""
${avk_toolkit_CreateDependencySymlinks})
3 changes: 3 additions & 0 deletions examples/particles/hello_world.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# "Hello World" Example's Root Folder

This is the root directory of the "Hello World" example. It contains all the source code for the example.
10 changes: 10 additions & 0 deletions examples/particles/shaders/particle.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(location = 0) in vec3 fragColor;

layout(location = 0) out vec4 outColor;

void main() {
outColor = vec4(fragColor, 1.0);
}
42 changes: 42 additions & 0 deletions examples/particles/shaders/particle.vert
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable

#define PART_CNT 50

struct Particle {
vec3 pos;
vec3 vel;
float size;
float age;
};

layout(set = 0, binding = 0) uniform ParticleBuffer
{
Particle[PART_CNT] p;
} particleBuffer;

layout(location = 0) out vec3 fragColor;

vec2 positions[6] = vec2[](
vec2(-0.5, -0.5),
vec2(0.5, -0.5),
vec2(-0.5, 0.5),

vec2(0.5, -0.5),
vec2(0.5, 0.5),
vec2(-0.5, 0.5)
);

vec3 colors[3] = vec3[](
vec3(1.0, 0.0, 0.0),
vec3(0.0, 1.0, 0.0),
vec3(0.0, 0.0, 1.0)
);

void main() {
uint id = gl_VertexIndex / 6;
Particle p = particleBuffer.p[id];
gl_Position = vec4(positions[gl_VertexIndex % 6]*p.size*p.age + p.pos.xy /*+ vec2(id/3.,0.)*/, 0.0, 1.0);
//gl_Position += vec4(p.vel * (p.age + p.pos.z), 0.);
fragColor = colors[gl_VertexIndex % 3];
}
140 changes: 140 additions & 0 deletions examples/particles/shaders/particles.comp
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#version 450
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable

#define PARTICLE_CNT 50
#define COLLIDER_CNT 10

struct Particle {
vec3 pos;
vec3 vel;
float size;
float age;
};

struct AACube {
vec3 min;
vec3 max;
};

struct Sphere {
vec3 origin;
float radius;
};

struct Colliders {
uint cubeCount;
uint sphereCount;
AACube cubes[COLLIDER_CNT];
Sphere spheres[COLLIDER_CNT];
};

struct ParticleSystem{
vec3 origin;
float spawnRadius;
float spawnRate;
vec3 initialVelocity;
float velocityRandomization;
vec3 gravity;
float particleSize;
float particleLifetime;
};

layout (local_size_x = 1, local_size_y = 1) in;

layout(set = 0, binding = 0) buffer Particles {
Particle p[];
} particles;

layout (set = 0, binding = 1) uniform Metadata {
uint64_t runTime;
uint64_t deltaTime;
ParticleSystem systemProperties;
//Colliders colliders;
} m;


// Hash without Sine
// MIT License...
/* Copyright (c)2014 David Hoskins.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.*/

//----------------------------------------------------------------------------------------
// 1 out, 2 in...
float hash12(vec2 p)
{
vec3 p3 = fract(vec3(p.xyx) * .1031);
p3 += dot(p3, p3.yzx + 33.33);
return fract((p3.x + p3.y) * p3.z);
}

//----------------------------------------------------------------------------------------
/// 2 out, 2 in...
vec2 hash22(vec2 p)
{
vec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973));
p3 += dot(p3, p3.yzx+33.33);
return fract((p3.xx+p3.yz)*p3.zy);

}

//----------------------------------------------------------------------------------------
/// 3 out, 2 in...
vec3 hash32(vec2 p)
{
vec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973));
p3 += dot(p3, p3.yxz+33.33);
return fract((p3.xxy+p3.yzz)*p3.zyx);
}

void main() {
float rt = float(m.runTime) / 1e6;
float dt = float(m.deltaTime) / 1e6;

ParticleSystem sys = m.systemProperties;

int beginId = 0;
int endId = PARTICLE_CNT;
for(int i = beginId; i < endId; i++) {
Particle p = particles.p[i];

if(p.age > 0) {
p.vel += sys.gravity * dt;
p.pos += p.vel * dt;
p.age -= dt;
}else {
vec2 seed = vec2(rt, float(i)*0.34982);
if(hash12(seed) < sys.spawnRate * dt) {
seed = hash22(seed);
p.pos = sys.origin + normalize(hash32(seed)) * (hash12(seed) - 0.5) * 2. * sys.spawnRadius;
seed = hash22(seed);
p.vel = mix(sys.initialVelocity, (hash32(seed) - 0.5) * 2. * length(sys.initialVelocity), sys.velocityRandomization);
p.size = sys.particleSize;
p.age = sys.particleLifetime;


}else {
p.size = 0.;
}
}


particles.p[i] = p;
}
}
Loading
Loading