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

iOS runtime fixes #1173

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 13 additions & 10 deletions app/ios/ViewController.mm
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ - (void)viewDidLoad {
argv[i] = s.UTF8String;
}

self.vulkan_view.contentScaleFactor = UIScreen.mainScreen.nativeScale;

context = create_platform_context((int)args.count, const_cast<char**>(argv));
_context = (vkb::IosPlatformContext*)context.get();
_context->view = self.vulkan_view;
Expand All @@ -58,16 +60,17 @@ - (void)viewDidLoad {

-(void) renderLoop {
if(!_displayLink.isPaused && [UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
_code = ((vkb::IosPlatform*)_context->userPlatform)->main_loop_frame();
}
}
if(_code == vkb::ExitCode::Success) {
_code = ((vkb::IosPlatform*)_context->userPlatform)->main_loop_frame();
}
else {
// On ExitCode error, remove displayLink from run loop and terminate any active sample or batch run
[_displayLink invalidate];
((vkb::IosPlatform*)_context->userPlatform)->terminate(_code);

- (void)dealloc {
[_displayLink invalidate];
[_displayLink release];
((vkb::IosPlatform*)_context->userPlatform)->terminate(_code);

[self.vulkan_view release];
[super dealloc];
// Not typically allowed for iOS apps, but exit here given this is an Xcode-controlled dev application
exit(0);
}
}
}
@end
1 change: 1 addition & 0 deletions framework/api_vulkan_sample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ void ApiVulkanSample::update(float delta_time)
view_changed();
}

assert(has_render_context());
render(delta_time);
camera.update(delta_time);
if (camera.moving())
Expand Down
47 changes: 36 additions & 11 deletions framework/gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -440,21 +440,21 @@ bool Gui::update_buffers()
return updated;
}

void Gui::update_buffers(CommandBuffer &command_buffer, RenderFrame &render_frame)
BufferAllocationC Gui::update_buffers(CommandBuffer &command_buffer)
SRSaunders marked this conversation as resolved.
Show resolved Hide resolved
{
ImDrawData *draw_data = ImGui::GetDrawData();

if (!draw_data)
{
return;
return BufferAllocationC{};
}

size_t vertex_buffer_size = draw_data->TotalVtxCount * sizeof(ImDrawVert);
size_t index_buffer_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx);

if ((vertex_buffer_size == 0) || (index_buffer_size == 0))
{
return;
return BufferAllocationC{};
}

std::vector<uint8_t> vertex_data(vertex_buffer_size);
Expand All @@ -478,6 +478,8 @@ void Gui::update_buffers(CommandBuffer &command_buffer, RenderFrame &render_fram
index_allocation.update(index_data);

command_buffer.bind_index_buffer(index_allocation.get_buffer(), index_allocation.get_offset(), VK_INDEX_TYPE_UINT16);

return vertex_allocation;
}

void Gui::resize(const uint32_t width, const uint32_t height) const
Expand Down Expand Up @@ -580,16 +582,25 @@ void Gui::draw(CommandBuffer &command_buffer)
// Push constants
command_buffer.push_constants(push_transform);

std::vector<std::reference_wrapper<const vkb::core::BufferC>> vertex_buffers;
std::vector<vk::DeviceSize> vertex_offsets;

// If a render context is used, then use the frames buffer pools to allocate GUI vertex/index data from
if (!explicit_update)
{
update_buffers(command_buffer, sample.get_render_context().get_active_frame());
// Save vertex buffer allocation in case we need to rebind with vertex_offset, e.g. for iOS Simulator
auto vertex_allocation = update_buffers(command_buffer);
if (!vertex_allocation.empty())
{
vertex_buffers.push_back(vertex_allocation.get_buffer());
vertex_offsets.push_back(vertex_allocation.get_offset());
}
}
else
{
std::vector<std::reference_wrapper<const vkb::core::BufferC>> buffers;
buffers.push_back(*vertex_buffer);
command_buffer.bind_vertex_buffers(0, buffers, {0});
vertex_buffers.push_back(*vertex_buffer);
vertex_offsets.push_back(0);
command_buffer.bind_vertex_buffers(0, vertex_buffers, vertex_offsets);

command_buffer.bind_index_buffer(*index_buffer, 0, VK_INDEX_TYPE_UINT16);
}
Expand Down Expand Up @@ -647,7 +658,16 @@ void Gui::draw(CommandBuffer &command_buffer)
command_buffer.draw_indexed(cmd->ElemCount, 1, index_offset, vertex_offset, 0);
index_offset += cmd->ElemCount;
}
#if defined(PLATFORM__MACOS) && TARGET_OS_IOS && TARGET_OS_SIMULATOR
// iOS Simulator does not support vkCmdDrawIndexed() with vertex_offset > 0, so rebind vertex buffer instead
if (!vertex_offsets.empty())
{
vertex_offsets.back() += cmd_list->VtxBuffer.Size * sizeof(ImDrawVert);
command_buffer.bind_vertex_buffers(0, vertex_buffers, vertex_offsets);
}
#else
vertex_offset += cmd_list->VtxBuffer.Size;
#endif
}
}

Expand Down Expand Up @@ -677,10 +697,9 @@ void Gui::draw(VkCommandBuffer command_buffer)
push_transform = glm::scale(push_transform, glm::vec3(2.0f / io.DisplaySize.x, 2.0f / io.DisplaySize.y, 0.0f));
vkCmdPushConstants(command_buffer, pipeline_layout->get_handle(), VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &push_transform);

VkDeviceSize offsets[1] = {0};

VkBuffer vertex_buffer_handle = vertex_buffer->get_handle();
vkCmdBindVertexBuffers(command_buffer, 0, 1, &vertex_buffer_handle, offsets);
VkDeviceSize vertex_offsets[1] = {0};
VkBuffer vertex_buffer_handle = vertex_buffer->get_handle();
vkCmdBindVertexBuffers(command_buffer, 0, 1, &vertex_buffer_handle, vertex_offsets);

VkBuffer index_buffer_handle = index_buffer->get_handle();
vkCmdBindIndexBuffer(command_buffer, index_buffer_handle, 0, VK_INDEX_TYPE_UINT16);
Expand All @@ -701,7 +720,13 @@ void Gui::draw(VkCommandBuffer command_buffer)
vkCmdDrawIndexed(command_buffer, cmd->ElemCount, 1, index_offset, vertex_offset, 0);
index_offset += cmd->ElemCount;
}
#if defined(PLATFORM__MACOS) && TARGET_OS_IOS && TARGET_OS_SIMULATOR
// iOS Simulator does not support vkCmdDrawIndexed() with vertex_offset > 0, so rebind vertex buffer instead
vertex_offsets[0] += cmd_list->VtxBuffer.Size * sizeof(ImDrawVert);
vkCmdBindVertexBuffers(command_buffer, 0, 1, &vertex_buffer_handle, vertex_offsets);
#else
vertex_offset += cmd_list->VtxBuffer.Size;
#endif
}
}

Expand Down
5 changes: 3 additions & 2 deletions framework/gui.h
Original file line number Diff line number Diff line change
Expand Up @@ -256,9 +256,10 @@ class Gui

/**
* @brief Updates Vulkan buffers
* @param frame Frame to render into
* @param command_buffer Command buffer to draw into
* @return Vertex buffer allocation
*/
void update_buffers(CommandBuffer &command_buffer, RenderFrame &render_frame);
BufferAllocationC update_buffers(CommandBuffer &command_buffer);

static const double press_time_ms;

Expand Down
1 change: 1 addition & 0 deletions framework/hpp_api_vulkan_sample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ void HPPApiVulkanSample::update(float delta_time)
view_changed();
}

assert(has_render_context());
render(delta_time);
camera.update(delta_time);
if (camera.moving())
Expand Down
43 changes: 35 additions & 8 deletions framework/hpp_gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -407,14 +407,14 @@ bool HPPGui::update_buffers()
return updated;
}

void HPPGui::update_buffers(vkb::core::HPPCommandBuffer &command_buffer) const
BufferAllocationCpp HPPGui::update_buffers(vkb::core::HPPCommandBuffer &command_buffer) const
SRSaunders marked this conversation as resolved.
Show resolved Hide resolved
{
ImDrawData *draw_data = ImGui::GetDrawData();
vkb::rendering::HPPRenderFrame &render_frame = sample.get_render_context().get_active_frame();

if (!draw_data || (draw_data->TotalVtxCount == 0) || (draw_data->TotalIdxCount == 0))
{
return;
return BufferAllocationCpp{};
}

size_t vertex_buffer_size = draw_data->TotalVtxCount * sizeof(ImDrawVert);
Expand All @@ -439,6 +439,8 @@ void HPPGui::update_buffers(vkb::core::HPPCommandBuffer &command_buffer) const
index_allocation.update(index_data);

command_buffer.bind_index_buffer(index_allocation.get_buffer(), index_allocation.get_offset(), vk::IndexType::eUint16);

return vertex_allocation;
}

void HPPGui::resize(uint32_t width, uint32_t height) const
Expand Down Expand Up @@ -537,16 +539,25 @@ void HPPGui::draw(vkb::core::HPPCommandBuffer &command_buffer)
// Push constants
command_buffer.push_constants(push_transform);

std::vector<std::reference_wrapper<const vkb::core::BufferCpp>> vertex_buffers;
std::vector<vk::DeviceSize> vertex_offsets;

// If a render context is used, then use the frames buffer pools to allocate GUI vertex/index data from
if (!explicit_update)
{
update_buffers(command_buffer);
// Save vertex buffer allocation in case we need to rebind with vertex_offset, e.g. for iOS Simulator
auto vertex_allocation = update_buffers(command_buffer);
if (!vertex_allocation.empty())
{
vertex_buffers.push_back(vertex_allocation.get_buffer());
vertex_offsets.push_back(vertex_allocation.get_offset());
}
}
else
{
std::vector<std::reference_wrapper<const vkb::core::BufferCpp>> buffers;
buffers.push_back(*vertex_buffer);
command_buffer.bind_vertex_buffers(0, buffers, {0});
vertex_buffers.push_back(*vertex_buffer);
vertex_offsets.push_back(0);
command_buffer.bind_vertex_buffers(0, vertex_buffers, vertex_offsets);

command_buffer.bind_index_buffer(*index_buffer, 0, vk::IndexType::eUint16);
}
Expand Down Expand Up @@ -604,7 +615,16 @@ void HPPGui::draw(vkb::core::HPPCommandBuffer &command_buffer)
command_buffer.draw_indexed(cmd->ElemCount, 1, index_offset, vertex_offset, 0);
index_offset += cmd->ElemCount;
}
#if defined(PLATFORM__MACOS) && TARGET_OS_IOS && TARGET_OS_SIMULATOR
// iOS Simulator does not support vkCmdDrawIndexed() with vertex_offset > 0, so rebind vertex buffer instead
if (!vertex_offsets.empty())
{
vertex_offsets.back() += cmd_list->VtxBuffer.Size * sizeof(ImDrawVert);
command_buffer.bind_vertex_buffers(0, vertex_buffers, vertex_offsets);
}
#else
vertex_offset += cmd_list->VtxBuffer.Size;
#endif
}
}

Expand All @@ -630,8 +650,9 @@ void HPPGui::draw(vk::CommandBuffer command_buffer) const
glm::mat4 push_transform = glm::scale(glm::translate(glm::mat4(1.0f), glm::vec3(-1.0f, -1.0f, 0.0f)), glm::vec3(2.0f / io.DisplaySize.x, 2.0f / io.DisplaySize.y, 0.0f));
command_buffer.pushConstants<glm::mat4>(pipeline_layout->get_handle(), vk::ShaderStageFlagBits::eVertex, 0, push_transform);

vk::DeviceSize offset = 0;
command_buffer.bindVertexBuffers(0, vertex_buffer->get_handle(), offset);
vk::DeviceSize vertex_offsets[1] = {0};
vk::Buffer vertex_buffer_handle = vertex_buffer->get_handle();
command_buffer.bindVertexBuffers(0, vertex_buffer_handle, vertex_offsets);

command_buffer.bindIndexBuffer(index_buffer->get_handle(), 0, vk::IndexType::eUint16);

Expand All @@ -653,7 +674,13 @@ void HPPGui::draw(vk::CommandBuffer command_buffer) const
command_buffer.drawIndexed(cmd->ElemCount, 1, index_offset, vertex_offset, 0);
index_offset += cmd->ElemCount;
}
#if defined(PLATFORM__MACOS) && TARGET_OS_IOS && TARGET_OS_SIMULATOR
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm a bit torn on "polluting" code with a special case as the iOS simulator. Can this be solved in a more elegant way? I wouldn't mind if we'd simply disable the UI on the iOS simulator instead of adding specific code for it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I debated this myself, and actually tried the UI disable route initially. However, I didn't like the experience, especially in batch mode where you really can't tell what is going on as the sample runs through its various configurations. And also in the near future I would to add gesture and key input handling for iOS and without the UI present on the Simulator that would be completely inaccessible.

The reason I like the iOS Simulator is that it is easy to run and does not require an Apple Development Certificate nor a unqiue bundle identifier for iOS. I figured this would make your project easily accessible for iOS testing without adding overhead for potential users. In addition, the Simulator allows me to try different devices that I don't own (e.g. larger screen and various generation iOS devices).

If you don't like the #ifdef special case handling, the change that I made is completely generic and could be applied to all platforms, i.e. simply don't use vertex_offset > 0 and use my rebinding code for all platforms. Not sure if you would like that but it would make the code generic. Please let me know.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe if we combine them into a new macro that's APPLE specific. Say SAMPLES_PLATFORM_APPLE or similar. I think the path of having macros is fine but there are other platforms in the Apple ecosystem that we haven't added support for yet.

// iOS Simulator does not support vkCmdDrawIndexed() with vertex_offset > 0, so rebind vertex buffer instead
vertex_offsets[0] += cmd_list->VtxBuffer.Size * sizeof(ImDrawVert);
command_buffer.bindVertexBuffers(0, vertex_buffer_handle, vertex_offsets);
#else
vertex_offset += cmd_list->VtxBuffer.Size;
#endif
}
}

Expand Down
5 changes: 3 additions & 2 deletions framework/hpp_gui.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,10 @@ class HPPGui
private:
/**
* @brief Updates Vulkan buffers
* @param frame Frame to render into
* @param command_buffer Command buffer to draw into
* @return Vertex buffer allocation
*/
void update_buffers(vkb::core::HPPCommandBuffer &command_buffer) const;
BufferAllocationCpp update_buffers(vkb::core::HPPCommandBuffer &command_buffer) const;

private:
/**
Expand Down
2 changes: 2 additions & 0 deletions framework/platform/ios/ios_window.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ class IosWindow : public Window

float get_dpi_factor() const override;

float get_content_scale_factor() const override;

std::vector<const char *> get_required_surface_extensions() const override;

VulkanView * get_vulkan_view() {return view;}
Expand Down
5 changes: 5 additions & 0 deletions framework/platform/ios/ios_window.mm
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@
return 1.0;
}

float IosWindow::get_content_scale_factor() const
{
return [[UIScreen mainScreen] nativeScale];
}

std::vector<const char *> IosWindow::get_required_surface_extensions() const
{
return {VK_EXT_METAL_SURFACE_EXTENSION_NAME};
Expand Down
12 changes: 6 additions & 6 deletions framework/platform/platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,11 @@ ExitCode Platform::main_loop_frame()
}

window->process_events();

if (window->should_close() || close_requested)
asuessenbach marked this conversation as resolved.
Show resolved Hide resolved
{
return ExitCode::Close;
}
}
catch (std::exception &e)
{
Expand All @@ -175,13 +180,8 @@ ExitCode Platform::main_loop_frame()

ExitCode Platform::main_loop()
{
if (!app_requested())
{
return ExitCode::NoSample;
}

ExitCode exit_code = ExitCode::Success;
while ((exit_code == ExitCode::Success) && !window->should_close() && !close_requested)
while (exit_code == ExitCode::Success)
{
exit_code = main_loop_frame();
}
Expand Down
10 changes: 5 additions & 5 deletions samples/api/hpp_oit_linked_lists/hpp_oit_linked_lists.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,16 @@ class HPPOITLinkedLists : public HPPApiVulkanSample
glm::uint fragment_max_count = 0U;

vk::RenderPass gather_render_pass = nullptr;
vk::Framebuffer gather_framebuffer;
vk::Framebuffer gather_framebuffer = nullptr;

vk::DescriptorSetLayout descriptor_set_layout = nullptr;
vk::DescriptorPool descriptor_pool = nullptr;
vk::DescriptorSet descriptor_set = nullptr;

vk::PipelineLayout pipeline_layout = nullptr;
vk::Pipeline gather_pipeline;
vk::Pipeline background_pipeline;
vk::Pipeline combine_pipeline;
vk::PipelineLayout pipeline_layout = nullptr;
vk::Pipeline gather_pipeline = nullptr;
vk::Pipeline background_pipeline = nullptr;
vk::Pipeline combine_pipeline = nullptr;

bool sort_fragments = true;
bool camera_auto_rotation = false;
Expand Down
12 changes: 6 additions & 6 deletions samples/api/oit_depth_peeling/oit_depth_peeling.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,12 @@ class OITDepthPeeling : public ApiVulkanSample

VkDescriptorPool descriptor_pool = VK_NULL_HANDLE;

VkPipelineLayout gather_pipeline_layout;
VkPipeline gather_first_pipeline;
VkPipeline gather_pipeline;
VkPipelineLayout combine_pipeline_layout;
VkPipeline combine_pipeline;
VkPipeline background_pipeline;
VkPipelineLayout gather_pipeline_layout = VK_NULL_HANDLE;
VkPipeline gather_first_pipeline = VK_NULL_HANDLE;
VkPipeline gather_pipeline = VK_NULL_HANDLE;
VkPipelineLayout combine_pipeline_layout = VK_NULL_HANDLE;
VkPipeline combine_pipeline = VK_NULL_HANDLE;
VkPipeline background_pipeline = VK_NULL_HANDLE;

int32_t camera_auto_rotation = false;
float background_grayscale = 0.3f;
Expand Down
8 changes: 4 additions & 4 deletions samples/api/oit_linked_lists/oit_linked_lists.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,10 @@ class OITLinkedLists : public ApiVulkanSample
VkDescriptorPool descriptor_pool = VK_NULL_HANDLE;
VkDescriptorSet descriptor_set = VK_NULL_HANDLE;

VkPipelineLayout pipeline_layout;
VkPipeline gather_pipeline;
VkPipeline background_pipeline;
VkPipeline combine_pipeline;
VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
VkPipeline gather_pipeline = VK_NULL_HANDLE;
VkPipeline background_pipeline = VK_NULL_HANDLE;
VkPipeline combine_pipeline = VK_NULL_HANDLE;

int32_t sort_fragments = true;
int32_t camera_auto_rotation = false;
Expand Down
Loading