Sign in to follow this  

Vulkan Vulkan UI rendering

Recommended Posts

I'm working on a UI that uses Vulkan for rendering.  I've come across a conundrum of sorts.  The general structure as it stands is:

- Window class handles interfacing with OS.  Each Window contains a number of Frame's (5-10'ish range, not a large number).

- Frame classes serve as containers for controls.  Frame's are mostly there to facilitate different rendering techniques (different shaders, descriptors sets, etc...), as well as differences in update frequency.

- Controls, the buttons, menus, etc... you actually see/work with, are contained in Frame's.

I had ideas for 3 different ways to approach this:

1) Have each Frame record a secondary command buffer.  To render the Window a primary commmand buffer would be created executing the secondary buffers within a render pass.  That way I'd only have to update the secondary command buffers when their corresponding Frame changes, the Frame secondary buffers would be VkFrameBuffer independent, and leads itself to easy multi-threading.  The downside is that the entire window would need to be rendered every frame.  For a video game this isn't a problem, but for apps/utilities this is unnecessary most of the time.

2) Store a 'dirty' rect/area.  When rendering simply create one large primary framebuffer that contains all necessary rendering.  This has the advantage of only rendering what actually changes, but means there would be almost no re-use of the command buffers.  Every change would almost always necessitate a completely new command buffer.

3) Have each Frame create its own primary command buffer.  This would make 'dirty' rect/area updates relatively easy, as well as allow command buffer reuse for some situations.  The downside is there would still be much less command buffer reuse than option 1, and rendering would not occur within a single render pass.  The docs aren't entirely clear, and since each GPU is different, its hard to gauge how much slower splitting the rendering across 5-10 separate command buffers/render passes would be than having one large one.

How would you guys go about this?  What method is better and/or what are you guys using?

Share this post


Link to post
Share on other sites

I question the need to only render a small portion of the UI at a time. Maybe it was useful back in the day before we had hardware acceleration and blitting pixels in the CPU was slow, but if you're using hardware accelerated rendering...I don't really think it's a problem redrawing the whole UI when something changes.

I did a small immediate mode UI for a basic map editor in opengl. I filled an array of all the vertices, copied them to the VBO, and rendered everything....every frame (and this was split up into multiple draw calls if the scissor rect changed). There was very little performance hit (everything, including the map itself, was being push out in <1ms iirc). In a UI that isn't limted to real time framerate of a video game..it's even less of a problem since acceptable delay is much more lenient. So if it takes 5 or even 10 ms to render your whole UI, it wouldn't cause noticeable lag in your application's usage.  

Edited by CirdanValen

Share this post


Link to post
Share on other sites

On desktop GPU's, you obviously have a lot of power at your disposal, also if your UI has transparent portions you are of course going to have to re-draw the entire thing.  For mobile though, wouldn't it make sense to try to cut back updates?

I guess you have a CPU/GPU tradeoff.  If I re-create the command buffer each frame, I put more stress on the CPU but can get optimal GPU usage.  If I cache the command buffers I can reduce stress on the CPU, but potentially increase GPU stress.  At this point I'm leaning towards recreating the command buffer each frame (#2 above).

Share this post


Link to post
Share on other sites
I don't have a truly "scientific, fact-based" answer for you, but my approach is "just draw it all", and I believe that is a good one. Why? For one reason it's simple. Simple is good. I'm stupid, and the simpler it is the fewer mistakes I make, the fewer time I spend tearing my hair. And then, the single one dominating thing on a GPU which never seems to get significantly better over the years is ROP and since you are (presumably) not writing to the screen buffer directly but use double-buffering (I wouldn't even know how to do something different with Vulkan anyway, but maybe that is possible) this means that you have to write every pixel one way or the other. Which of course means you ROP every pixel, whether you burn extra GPU memory (which is [i]not necessarily abundant[/i] on a mobile device) to save a few vertex shader cycles or not. That, and let's assume you could indeed only write the pixels that change. This would mean you can no longer pass the "undefined" and "don't care" flags to Vulkan (because you [i]do care[/i] about the previous contents, and it must be well-defined!), which presumably means the driver has to keep data from the previous frame around longer and change write-and-forget operations to read-modify-write. Or something, whatever. In any case, my bet is it will not come for free.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Similar Content

    • By HateWork
      Hello guys,
      My math is failing and can't get my orthographic projection matrix to work in Vulkan 1.0 (my implementation works great in D3D11 and D3D12). Specifically, there's nothing being drawn on the screen when using an ortho matrix but my perspective projection matrix work fantastic!
      I use glm with defines GLM_FORCE_LEFT_HANDED and GLM_FORCE_DEPTH_ZERO_TO_ONE (to handle 0 to 1 depth).
      This is how i define my matrices:
      m_projection_matrix = glm::perspective(glm::radians(fov), aspect_ratio, 0.1f, 100.0f); m_ortho_matrix = glm::ortho(0.0f, (float)width, (float)height, 0.0f, 0.1f, 100.0f); // I also tried 0.0f and 1.0f for depth near and far, the same I set and work for D3D but in Vulkan it doesn't work either. Then I premultiply both matrices with a "fix matrix" to invert the Y axis:
      glm::mat4 matrix_fix = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; m_projection_matrix = m_projection_matrix * matrix_fix; m_ortho_matrix = m_ortho_matrix * matrix_fix; This fix matrix works good in tandem with GLM_FORCE_DEPTH_ZERO_TO_ONE.
      Model/World matrix is the identity matrix:
      glm::mat4 m_world_matrix(1.0f); Then finally this is how i set my view matrix:
      // Yes, I use Euler angles (don't bring the gimbal lock topic here, lol). They work great with my cameras in D3D too! m_view_matrix = glm::yawPitchRoll(glm::radians(m_rotation.y), glm::radians(m_rotation.x), glm::radians(m_rotation.z)); m_view_matrix = glm::translate(m_view_matrix, -m_position); That's all guys, in my shaders I correctly multiply all 3 matrices with the position vector and as I said, the perspective matrix works really good but my ortho matrix displays no geometry.
      EDIT: My vertex data is also on the right track, I use the same geometry in D3D and it works great: 256.0f units means 256 points/dots/pixels wide.
      What could I possibly be doing wrong or missing?
      Big thanks guys any help would be greatly appreciated. Keep on coding, cheers.
       
    • By TheSargKyle
      My team and I are developing a game engine! We would like as much help as possible. The project is currently hobby only, but pay will be appropriately rolled out to those who work on the engine. people we are looking for are:
      Network Programmer Artist For User Interface Physics Programmer Graphics Programmer Prerequisites wanted, but not needed, are: 
      Intermediate C++ knowledge 1 Yr in Game development Industry Thank you for your intrest in the project. You can contact me at my email: thesargkyle@gmail.com or my discord: TheSargKyle#8978
    • By L. Spiro
      Home: https://www.khronos.org/vulkan/
      SDK: http://lunarg.com/vulkan-sdk/
       
      AMD drivers: http://gpuopen.com/gaming-product/vulkan/ (Note that Vulkan support is now part of AMD’s official drivers, so simply getting the latest drivers for your card should give you Vulkan support.)
      NVIDIA drivers: https://developer.nvidia.com/vulkan-driver (Note that Vulkan support is now part of NVIDIA’s official drivers, so simply getting the latest drivers for your card should give you Vulkan support.)
      Intel drivers: http://blogs.intel.com/evangelists/2016/02/16/intel-open-source-graphics-drivers-now-support-vulkan/
       
      Quick reference: https://www.khronos.org/registry/vulkan/specs/1.0/refguide/Vulkan-1.0-web.pdf
      References: https://www.khronos.org/registry/vulkan/specs/1.0/apispec.html
      https://matthewwellings.com/blog/the-new-vulkan-coordinate-system/
       
      GLSL-to-SPIR-V: https://github.com/KhronosGroup/glslang

      Sample code: https://github.com/LunarG/VulkanSamples
      https://github.com/SaschaWillems/Vulkan
      https://github.com/nvpro-samples
      https://github.com/nvpro-samples/gl_vk_chopper
      https://github.com/nvpro-samples/gl_vk_threaded_cadscene
      https://github.com/nvpro-samples/gl_vk_bk3dthreaded
      https://github.com/nvpro-samples/gl_vk_supersampled
      https://github.com/McNopper/Vulkan
      https://github.com/GPUOpen-LibrariesAndSDKs/HelloVulkan
       
      C++: https://github.com/nvpro-pipeline/vkcpp
      https://developer.nvidia.com/open-source-vulkan-c-api

      Getting started: https://vulkan-tutorial.com/
      https://renderdoc.org/vulkan-in-30-minutes.html
      https://www.khronos.org/news/events/vulkan-webinar
      https://developer.nvidia.com/engaging-voyage-vulkan
      https://developer.nvidia.com/vulkan-shader-resource-binding
      https://developer.nvidia.com/vulkan-memory-management
      https://developer.nvidia.com/opengl-vulkan
      https://github.com/vinjn/awesome-vulkan

      Videos: https://www.youtube.com/playlist?list=PLYO7XTAX41FPg08uM_bgPE9HLgDAyzDaZ

      Utilities: https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator (AMD Memory allocator.)
      https://github.com/GPUOpen-LibrariesAndSDKs/Anvil (AMD Miniature Vulkan engine/framework.)

       
      L. Spiro
    • By hiya83
      (Posted this in graphics forum too, which was perhaps the wrong forum for it)
      Hey, I was wondering if on mobile development (Android mainly but iOS as well if you know of it), if there is a GPUView equivalent for whole system debugging so we can figure out if the CPU/GPU are being pipelined efficiently, if there are bubbles, etc. Also slightly tangent question, but do mobile GPU's have a DMA engine exposed as a dedicated Transfer Queue for Vulkan?
      Thanks!
    • By hiya83
      Hey, I was wondering if on mobile development (Android mainly but iOS as well if you know of it), if there is a GPUView equivalent for whole system debugging so we can figure out if the CPU/GPU are being pipelined efficiently, if there are bubbles, etc. Also slightly tangent question, but do mobile GPU's have a DMA engine exposed as a dedicated Transfer Queue for Vulkan?
  • Popular Now