{"id":8828,"date":"2024-04-02T11:14:23","date_gmt":"2024-04-02T09:14:23","guid":{"rendered":"https:\/\/www.basyskom.de\/?p=8828"},"modified":"2024-07-18T15:21:25","modified_gmt":"2024-07-18T13:21:25","slug":"use-compute-shader-in-qt-quick","status":"publish","type":"post","link":"https:\/\/www.basyskom.de\/en\/use-compute-shader-in-qt-quick\/","title":{"rendered":"Use Compute Shader in Qt Quick"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"8828\" class=\"elementor elementor-8828\" data-elementor-post-type=\"post\">\n\t\t\t\t<div class=\"elementor-element elementor-element-3aa5a65 e-flex e-con-boxed wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no e-con e-parent\" data-id=\"3aa5a65\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t<div class=\"elementor-element elementor-element-d7a7fc4 e-flex e-con-boxed wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no e-con e-child\" data-id=\"d7a7fc4\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-b48e368 elementor-view-default elementor-widget elementor-widget-icon\" data-id=\"b48e368\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-wrapper\">\n\t\t\t<a class=\"elementor-icon\" href=\"https:\/\/github.com\/basysKom\/qtquickcomputeitem\" target=\"_blank\" rel=\"noopener\">\n\t\t\t<svg aria-hidden=\"true\" class=\"e-font-icon-svg e-fab-github\" viewBox=\"0 0 496 512\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z\"><\/path><\/svg>\t\t\t<\/a>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-1a2207f elementor-widget elementor-widget-text-editor\" data-id=\"1a2207f\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p><a href=\"https:\/\/github.com\/basysKom\/qtquickcomputeitem\" target=\"_blank\" rel=\"noopener\">Find the QtQuickComputeItem on Github<\/a><\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-ef68b4d elementor-widget elementor-widget-heading\" data-id=\"ef68b4d\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Introduction to GPU Compute Pipelines<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-ccba3da e-flex e-con-boxed wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no e-con e-child\" data-id=\"ccba3da\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-bc0ff8f elementor-widget elementor-widget-text-editor\" data-id=\"bc0ff8f\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>You may have heared about Compute pipelines as an important concept in handling complex computational tasks. But what exactly are compute pipelines?<\/p><p>At their core, these are systems designed to process data through a series of steps or stages, each specialized for a specific function. This approach not only streamlines processing but also enhances efficiency and scalability. As demand grows for faster and more efficient data processing grow, understanding the role and mechanics of compute pipelines becomes essential. They&#8217;re particularly crucial in environments where large-scale data handling and real-time processing are commonplace, such as in big data analytics, machine learning projects and high-performance computing scenarios.<\/p><p>Before we explain the QtQuickComputeItem, we\u2019ll dive into the world of compute pipelines, unraveling their necessity, structure and applications.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8e96ec8 elementor-widget elementor-widget-image\" data-id=\"8e96ec8\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img fetchpriority=\"high\" decoding=\"async\" width=\"424\" height=\"336\" src=\"https:\/\/www.basyskom.de\/wp-content\/uploads\/2024\/03\/image-2024-1-26_17-20-21.png\" class=\"attachment-large size-large wp-image-8843\" alt=\"basysKom, HMI Dienstleistung, Qt, Cloud, Azure\" srcset=\"https:\/\/www.basyskom.de\/wp-content\/uploads\/2024\/03\/image-2024-1-26_17-20-21.png 424w, https:\/\/www.basyskom.de\/wp-content\/uploads\/2024\/03\/image-2024-1-26_17-20-21-300x238.png 300w, https:\/\/www.basyskom.de\/wp-content\/uploads\/2024\/03\/image-2024-1-26_17-20-21-15x12.png 15w\" sizes=\"(max-width: 424px) 100vw, 424px\">\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-f1b3f26 elementor-widget elementor-widget-heading\" data-id=\"f1b3f26\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">The Need for Compute Pipelines<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-360fbb8 elementor-widget elementor-widget-text-editor\" data-id=\"360fbb8\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>In today&#8217;s technological realm, the complexity and volume of data processing tasks are increasing even on embedded devices. Traditional methods of handling these tasks often done on the CPU and fall short in terms of efficiency, speed and power consumption. While, on the other hand, modern embedded devices often include powerful GPUs which stays underutilized. This is where compute pipelines come into play, offering a structured solution to manage intricate computing processes running efficiently on your GPU.<\/p><p><strong>Streamlining Complex Tasks:<\/strong> The essence of a compute pipeline is its ability to break down complex processes into manageable stages. Each stage in the pipeline is designed to perform a specific task or set of tasks, allowing for more focused and efficient processing. For instance, in a machine learning workflow, different stages may include data collection, preprocessing, model training and prediction.<\/p><p><strong>Enhancing Efficiency and Productivity:<\/strong> By segmenting tasks, compute pipelines enable parallel processing. This not only speeds up the overall process but also improves resource utilization. In scenarios like video processing, scientific simulations or the processing of large datasets, the ability to process multiple data streams simultaneously is invaluable.<\/p><p><strong>Dealing with Scalability and Flexibility:<\/strong> Another significant aspect of compute pipelines is their scalability. As the volume of data or the complexity of tasks increases, pipelines can be scaled to meet these demands without a complete overhaul of the system. This adaptability makes them ideal for businesses and research environments where data requirements can change rapidly.<\/p><p>Through these capabilities, compute pipelines address the core challenges of modern computing environments. They not only offer a more efficient way to process data but also bring a paradigm shift in how we approach complex computational tasks.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-05cca38 elementor-widget elementor-widget-heading\" data-id=\"05cca38\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Components and Structure of Compute Pipelines<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-eea0bb8 elementor-widget elementor-widget-text-editor\" data-id=\"eea0bb8\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Understanding the components and structure of compute pipelines is crucial for appreciating their functionality and efficiency. Typically, a compute pipeline consists of various interconnected components, each playing a distinct role in the data processing journey.<\/p><p><strong>Key Components:<\/strong><\/p><ol><li><strong>Data Source:<\/strong> The beginning of any compute pipeline. This could be databases, live data feeds, file systems, or even real-time user input.<\/li><li><strong>Processing Stages:<\/strong> These are the heart of the pipeline. Each stage is responsible for a specific type of processing, like data cleansing, transformation, analysis, or complex algorithms. The stages are often modular, allowing for easy updates or changes as needed.<\/li><li><strong>Data Storage:<\/strong> Temporary or permanent storage components hold data between stages or after the final output. This can range from in-memory storage for fast access to more durable solutions like databases or cloud storage.<\/li><li><strong>Management and Orchestration Tools:<\/strong> Essential for coordinating the various stages, especially in pipelines with numerous or complex processes. These tools ensure data flows smoothly from one stage to another and manage resources effectively.<br \/><br \/><\/li><\/ol><p><strong>Structural Aspects:<\/strong><\/p><ul><li><strong>Sequential vs. Parallel Processing:<\/strong> While some pipelines process data sequentially (one stage after another), others operate in parallel, processing multiple data streams simultaneously.<\/li><li><strong>Scalability:<\/strong> Pipelines are designed to scale up or down, depending on the workload. This flexibility is crucial for adapting to varying data volumes or processing needs.<\/li><li><strong>Error Handling and Recovery:<\/strong> Robust compute pipelines include mechanisms to handle failures or errors at any stage, ensuring data integrity and continuous operation.<br \/><br \/><\/li><\/ul><p>By combining these components and structural considerations, compute pipelines offer a versatile and robust framework for handling diverse data processing tasks. From simple data transformation to complex analytical processes, the architecture of compute pipelines makes them indispensable tools in today&#8217;s data-driven world.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-fa19379 elementor-widget elementor-widget-heading\" data-id=\"fa19379\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Use Cases and Advantages of Compute Pipelines<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6f0dfa9 elementor-widget elementor-widget-text-editor\" data-id=\"6f0dfa9\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Compute pipelines have a wide array of applications across various industries and fields. Understanding these use cases, along with their inherent advantages, provides insight into why they are so integral in modern computing.<\/p><p><strong>Diverse Applications:<\/strong><\/p><ol><li><strong>Big Data Analytics:<\/strong> Pipelines are fundamental in managing and processing large datasets for insights, particularly in fields like marketing, finance and healthcare.<\/li><li><strong>Machine Learning Workflows:<\/strong> From data preparation to training and inference, compute pipelines streamline every stage of the machine learning lifecycle.<\/li><li><strong>Media Processing:<\/strong> In the media industry, pipelines are used for tasks such as video encoding, rendering and complex visual effects.<\/li><\/ol><p><strong>Key Advantages:<\/strong><\/p><ul><li><strong>Efficiency and Speed:<\/strong> By allowing for parallel processing and reducing redundant operations, compute pipelines significantly speed up data processing tasks.<\/li><li><strong>Scalability:<\/strong> Whether it&#8217;s handling a surge in data or expanding the scope of processing, pipelines can adapt flexibly, making them ideal for growth and change.<\/li><li><strong>Error Handling and Reliability:<\/strong> Well-designed pipelines include mechanisms for error detection and recovery, ensuring consistent and reliable data processing.<\/li><li><strong>Enhanced Collaboration and Productivity:<\/strong> Pipelines often include tools for monitoring and collaboration, which enhances team productivity and facilitates better project management.<\/li><\/ul><p>Through these use cases and benefits, compute pipelines simplify complex processes and can pave the way for further innovation and enhanced performance in a wide array of computing tasks.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-3204b86 elementor-widget elementor-widget-heading\" data-id=\"3204b86\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Conclusion on GPU Compute Pipelines<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-3b1b603 elementor-widget elementor-widget-text-editor\" data-id=\"3b1b603\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>As we\u2019ve seen throughout this first overview, compute pipelines are more than just a technical convenience; they can be a fundamental component in the modern computing landscape. Their ability to efficiently process and manage data makes them important in a world where the volume, velocity and variety of data are constantly increasing. On embedded devices they can help to utilize unused system recourses, reduce cpu load and improve performance. \u00a0<\/p><p>So, let us ask ourself, wouldn&#8217;t it be nice to use them in QtQuick? Wouldn&#8217;t it be nice to use them at the same ease as you can use a fragment shader or vertex shader?\u00a0<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c1e16b2 elementor-widget elementor-widget-heading\" data-id=\"c1e16b2\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h1 class=\"elementor-heading-title elementor-size-default\">The birth of QtQuickComputeItem<\/h1>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-75316fc elementor-widget elementor-widget-text-editor\" data-id=\"75316fc\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>For a very long time, Qt Quick has provided shader integration: You can write fragment and vertex shaders and load them with a Qt Quick ShaderEffect item (<a class=\"external-link\" href=\"https:\/\/doc.qt.io\/qt-6\/qml-qtquick-shadereffect.html\" rel=\"nofollow noopener\" target=\"_blank\">https:\/\/doc.qt.io\/qt-6\/qml-qtquick-shadereffect.html<\/a>) to your application. QML properties are seamlessly mapped to uniform inputs in the shader code. This is often used for applying graphical effects on top of ui components.<\/p><p>Our QtQuickComputeItem integrates a cross-platform interface to run a compute pipeline in a Qt Quick application, with the same ease as you can integrate a fragment or vertex shader. The QtQuickComputeItem is OpenSource and can be found in our github. Along with the items comes an example that we want to discuss here. Just go ahead to github to get startet and to try it out.<br \/>You can find a comprehensive introduction to compute shaders in the Khronos wiki (<a class=\"external-link\" href=\"https:\/\/www.khronos.org\/opengl\/wiki\/Compute_Shader\" rel=\"nofollow noopener\" target=\"_blank\">https:\/\/www.khronos.org\/opengl\/wiki\/Compute_Shader<\/a>), <span id=\"added-diff-7\" class=\"diff-html-added\"> from which we would like to quote the following paragraph:<\/span><\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-c34d8fd e-con-full e-flex wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no wpr-equal-height-no e-con e-child\" data-id=\"c34d8fd\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-34293d9 elementor-view-default elementor-widget elementor-widget-icon\" data-id=\"34293d9\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-wrapper\">\n\t\t\t<div class=\"elementor-icon\">\n\t\t\t<svg aria-hidden=\"true\" class=\"e-font-icon-svg e-fas-info-circle\" viewBox=\"0 0 512 512\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z\"><\/path><\/svg>\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-229a7f4 elementor-widget elementor-widget-text-editor\" data-id=\"229a7f4\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>The [compute] &#8220;space&#8221; that a compute shader operates on is largely abstract; it is up to each compute shader to decide what the space means. The number of compute shader executions is defined by the function used to execute the compute operation. Most important of all, compute shaders have no user-defined inputs and no outputs at all. The built-in inputs only define where in the &#8220;space&#8221; of execution a particular compute shader invocation is.<\/p><p>Therefore, if a compute shader wants to take some values as input, it is up to the shader itself to fetch that data, via texture access, arbitrary image load, shader storage blocks, or other forms of interface. Similarly, if a compute shader is to actually compute anything, it must explicitly write to an image or shader storage block.&#8221;<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-87c780e elementor-widget elementor-widget-heading\" data-id=\"87c780e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Installation of the QtQuickComputeItem<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-f0cd809 elementor-widget elementor-widget-text-editor\" data-id=\"f0cd809\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Starting is easy: Clone the <a href=\"https:\/\/github.com\/basysKom\/qtquickcomputeitem\" target=\"_blank\" rel=\"noopener\">github repo<\/a>, compile the plugin and set the environment variable with the import path:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-f077ceb elementor-widget elementor-widget-elementor-syntax-highlighter\" data-id=\"f077ceb\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"elementor-syntax-highlighter.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre><code class='language-bash'>git clone git@github.com:basysKom\/qtquickcomputeitem.git\r\nmkdir build_qtquickcomputeitem\r\ncd build_qtquickcomputeitem\r\ncmake ..\/qtquickcomputeitem\r\nmake\r\nexport QML_IMPORT_PATH=$(pwd)\/lib\/ <\/code><\/pre><script>\nif (!document.getElementById('syntaxed-prism')) {\n\tvar my_awesome_script = document.createElement('script');\n\tmy_awesome_script.setAttribute('src','https:\/\/www.basyskom.de\/wp-content\/plugins\/syntax-highlighter-for-elementor\/assets\/prism2.js');\n\tmy_awesome_script.setAttribute('id','syntaxed-prism');\n\tdocument.body.appendChild(my_awesome_script);\n} else {\n\twindow.Prism && Prism.highlightAll();\n}\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-25a2fc3 elementor-widget elementor-widget-text-editor\" data-id=\"25a2fc3\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Run one of the examples:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-65339ff elementor-widget elementor-widget-elementor-syntax-highlighter\" data-id=\"65339ff\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"elementor-syntax-highlighter.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre><code class='language-bash'>cd examples\/basic_storage\r\n.\/qmlbasicstorage <\/code><\/pre><script>\nif (!document.getElementById('syntaxed-prism')) {\n\tvar my_awesome_script = document.createElement('script');\n\tmy_awesome_script.setAttribute('src','https:\/\/www.basyskom.de\/wp-content\/plugins\/syntax-highlighter-for-elementor\/assets\/prism2.js');\n\tmy_awesome_script.setAttribute('id','syntaxed-prism');\n\tdocument.body.appendChild(my_awesome_script);\n} else {\n\twindow.Prism && Prism.highlightAll();\n}\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-5d3ff19 elementor-widget elementor-widget-text-editor\" data-id=\"5d3ff19\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>This example outputs an animated particle starfield. The starfield example is used in this blog post to demonstrate how to use the QtQuickComputeItem.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-24dcd13 elementor-widget elementor-widget-video\" data-id=\"24dcd13\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;video_type&quot;:&quot;hosted&quot;,&quot;autoplay&quot;:&quot;yes&quot;,&quot;mute&quot;:&quot;yes&quot;,&quot;loop&quot;:&quot;yes&quot;,&quot;controls&quot;:&quot;yes&quot;}\" data-widget_type=\"video.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"e-hosted-video elementor-wrapper elementor-open-inline\">\n\t\t\t\t\t<video class=\"elementor-video\" src=\"https:\/\/www.basyskom.de\/wp-content\/uploads\/2024\/03\/example_compute_item.mp4\" autoplay=\"\" loop=\"\" controls=\"\" muted=\"muted\" controlsList=\"nodownload\"><\/video>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-bb33cc4 elementor-widget elementor-widget-text-editor\" data-id=\"bb33cc4\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\tBy the way, the example used to generate the gray scott diffusion pattern can be found in examples\/grayscott_image.\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-086cfcc elementor-widget elementor-widget-heading\" data-id=\"086cfcc\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">An overview<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-355f245 elementor-widget elementor-widget-text-editor\" data-id=\"355f245\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>The QtQuickComputeItem supports both, storage buffers and images as inputs and outputs.<\/p><p>In compute shaders, the input data is partitioned into three-dimensional blocks or computation groups, each specified with dimensions in x, y and z directions. These group sizes are defined within in the shader code. The actual number of groups in each direction (x, y and z) is configured through QML properties. Prior to exploring the QML aspect, we delve into the shader part:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-1d8f5fa elementor-widget elementor-widget-elementor-syntax-highlighter\" data-id=\"1d8f5fa\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"elementor-syntax-highlighter.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre><code class='language-clike'>#version 440\r\n \r\nlayout (local_size_x = 256) in;\r\n \r\nstruct Particle\r\n{\r\n    vec4 pos;   \r\n    vec4 color;\r\n};\r\n \r\nlayout(std140, binding = 0) buffer StorageBuffer\r\n{\r\n    Particle particle[];\r\n} buf;\r\n \r\nlayout(std140, binding = 1) uniform UniformBuffer\r\n{\r\n    float speed;\r\n    uint dataCount;\r\n} ubuf;\r\n \r\nvoid main()\r\n{\r\n    uint index = gl_GlobalInvocationID.x;\r\n    if (index &lt; ubuf.dataCount) {\r\n \r\n        vec4 position = buf.particle[index].pos;\r\n \r\n        position.x += ubuf.speed;\r\n        if (position.x &gt; 1.0) {\r\n            position.x -= 2.0;\r\n        }\r\n \r\n        \/\/ update\r\n        buf.particle[index].pos = position;\r\n        buf.particle[index].color = vec4(position.z, position.z, position.z, 1.0);\r\n    }\r\n} <\/code><\/pre><script>\nif (!document.getElementById('syntaxed-prism')) {\n\tvar my_awesome_script = document.createElement('script');\n\tmy_awesome_script.setAttribute('src','https:\/\/www.basyskom.de\/wp-content\/plugins\/syntax-highlighter-for-elementor\/assets\/prism2.js');\n\tmy_awesome_script.setAttribute('id','syntaxed-prism');\n\tdocument.body.appendChild(my_awesome_script);\n} else {\n\twindow.Prism && Prism.highlightAll();\n}\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-9fcadf7 elementor-widget elementor-widget-text-editor\" data-id=\"9fcadf7\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Here the local group size is 256 in the x direction and 1 in all other directions. A single storage buffer which is bound at binding point 1 is used as input and output.<\/p><p>Each entry in the buffer consists of a position and a color. The code is just updating the x coordinate part of the position and computes a color from the depth (z) value. This results in a flowing star field:<\/p><p>A compute shader designed to process two-dimensional data, such as images, could specify its local sizes, inputs and outputs like this, for example:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-19e933e elementor-widget elementor-widget-elementor-syntax-highlighter\" data-id=\"19e933e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"elementor-syntax-highlighter.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre><code class='language-clike'>layout (local_size_x = 32, local_size_y = 32) in;\r\n \r\nlayout (binding = 1, rgba8) uniform image2D inputImage;\r\nlayout (binding = 2, rgba8) uniform image2D outputImage; <\/code><\/pre><script>\nif (!document.getElementById('syntaxed-prism')) {\n\tvar my_awesome_script = document.createElement('script');\n\tmy_awesome_script.setAttribute('src','https:\/\/www.basyskom.de\/wp-content\/plugins\/syntax-highlighter-for-elementor\/assets\/prism2.js');\n\tmy_awesome_script.setAttribute('id','syntaxed-prism');\n\tdocument.body.appendChild(my_awesome_script);\n} else {\n\twindow.Prism && Prism.highlightAll();\n}\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-d4082a5 elementor-widget elementor-widget-text-editor\" data-id=\"d4082a5\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>So, assuming an 320&#215;320 image, you would dispatch 10 workgroups in both the x and y dimensions to cover it entirely with a local size of 32&#215;32.<\/p><p>After covering the basics of writing a compute shader, we can now create the ComputeItem in QML<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4e8c5d9 elementor-widget elementor-widget-elementor-syntax-highlighter\" data-id=\"4e8c5d9\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"elementor-syntax-highlighter.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre><code class='language-clike'>ComputeItem {\r\n  id: computeItem\r\n \r\n  property real speed: 0.005\r\n  property int dataCount: 100 * 256\r\n \r\n  computeShader: &quot;:\/shaders\/computeshader.comp.qsb&quot;\r\n  dispatchX: computeItem.dataCount \/ 256\r\n \r\n  buffers: [\r\n    StorageBuffer {\r\n        id: storageBuffer\r\n         \r\n        Component.onCompleted: initBuffer()\r\n    }\r\n  ]\r\n \r\n  Component.onCompleted: computeItem.compute()\r\n \r\n} <\/code><\/pre><script>\nif (!document.getElementById('syntaxed-prism')) {\n\tvar my_awesome_script = document.createElement('script');\n\tmy_awesome_script.setAttribute('src','https:\/\/www.basyskom.de\/wp-content\/plugins\/syntax-highlighter-for-elementor\/assets\/prism2.js');\n\tmy_awesome_script.setAttribute('id','syntaxed-prism');\n\tdocument.body.appendChild(my_awesome_script);\n} else {\n\twindow.Prism && Prism.highlightAll();\n}\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c5ce303 elementor-widget elementor-widget-text-editor\" data-id=\"c5ce303\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>The computeShader property points to the shader file in qsb format (more on this later). The dispatchX, dispatchY and dispatchZ properties specify the number of working groups in each direction: In this example, 100 groups are dispatched, each with a size of 256, as defined in the compute shader. The group sizes in the y and z directions are set to 1 (the default value).<\/p><p>The speed and dataCount properties are automatically transferred to the uniform buffer. Currently only basic types such as integers, floats and boolean values are supported. Please note, that the properties have to be declared in the same order as in the uniform buffer.<\/p><p>The buffers property expects a list of StorageBuffer and ImageBuffer items, with each item corresponding to a buffer (or image) bound in the compute shader. On the C++ side the buffers are represented as QByteArrays. It is possible to initialize them with a bit of JavaScript, employing an ArrayBuffer. Here is the initBuffer method for initializing the buffer data:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-43aa092 elementor-widget elementor-widget-elementor-syntax-highlighter\" data-id=\"43aa092\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"elementor-syntax-highlighter.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre><code class='language-clike'>function initBuffer() {\r\n  const dataSize = 8 * computeItem.dataCount; \/\/ 8 entries per point: x pos, y pos, depth, unused, rgba color\r\n  const bufferSize = 4 * dataSize; \/\/ four bytes per entry\r\n \r\n  let buffer = new ArrayBuffer(bufferSize);\r\n  let view = new Float32Array(buffer);\r\n  let i = 0;\r\n  let coordXY = 0;\r\n  while(i &lt; dataSize) {\r\n    view[i + 0] = Math.random() * 2.0 - 1.0; \/\/ x\r\n        view[i + 1] = Math.random() * 2.0 - 1.0; \/\/ y\r\n        view[i + 2] = Math.random(); \/\/ depth\r\n        view[i + 3] = 0.0; \/\/ unused\r\n        \/\/ we just add a black particle here, the real particle color is set in the compute shader\r\n        view[i + 4] = 0.0; \/\/ r\r\n        view[i + 5] = 0.0; \/\/ g\r\n        view[i + 6] = 0.0; \/\/ b\r\n        view[i + 7] = 1.0; \/\/ a\r\n \r\n        i += 8;\r\n  }\r\n  storageBuffer.buffer = buffer;\r\n } <\/code><\/pre><script>\nif (!document.getElementById('syntaxed-prism')) {\n\tvar my_awesome_script = document.createElement('script');\n\tmy_awesome_script.setAttribute('src','https:\/\/www.basyskom.de\/wp-content\/plugins\/syntax-highlighter-for-elementor\/assets\/prism2.js');\n\tmy_awesome_script.setAttribute('id','syntaxed-prism');\n\tdocument.body.appendChild(my_awesome_script);\n} else {\n\twindow.Prism && Prism.highlightAll();\n}\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6237c31 elementor-widget elementor-widget-text-editor\" data-id=\"6237c31\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>The data is uploaded to and kept in the GPU memory, so it is not possible to query the positions later.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-9db2136 elementor-widget elementor-widget-heading\" data-id=\"9db2136\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Displaying the results<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-cb96520 elementor-widget elementor-widget-text-editor\" data-id=\"cb96520\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>After calling computeItem.compute(), the compute shader is executed in sync with the scene graph render loop, the positions are updated and the particle stars are flowing from left to right, from left to right, from left &#8230; What&#8217;s missing of course, is the visualisation of the result. The Qt Quick ComputeItem plugin comes with two items that are able to render the updated buffers and images to the screen: StorageBufferView is able to render storage buffers and ImageBufferView is the corresponding item for images.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-433ab94 elementor-widget elementor-widget-elementor-syntax-highlighter\" data-id=\"433ab94\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"elementor-syntax-highlighter.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre><code class='language-clike'>StorageBufferView {\r\n  id: view\r\n  focus: true\r\n  anchors.fill: parent\r\n  computeItem: computeItem\r\n  resultBuffer: storageBuffer\r\n  numberOfPoints: computeItem.dataCount\r\n  pointSize: 2.0\r\n} <\/code><\/pre><script>\nif (!document.getElementById('syntaxed-prism')) {\n\tvar my_awesome_script = document.createElement('script');\n\tmy_awesome_script.setAttribute('src','https:\/\/www.basyskom.de\/wp-content\/plugins\/syntax-highlighter-for-elementor\/assets\/prism2.js');\n\tmy_awesome_script.setAttribute('id','syntaxed-prism');\n\tdocument.body.appendChild(my_awesome_script);\n} else {\n\twindow.Prism && Prism.highlightAll();\n}\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-d362058 elementor-widget elementor-widget-text-editor\" data-id=\"d362058\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>The StorageBufferView needs to know the storageBuffer it should render and the ComputerBuffer item this storage buffer is associated to. The property numberOfPoints limits the amount of points that should be rendered, the pointSize controls the size of the particles on the screen. The renderer expects a certain format: The first two values are reserved for the x and y coordinates and have to have a length of four bytes. The next eight bytes can be used for custom data; the last 32 bytes contain the color values in rgba format.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-965e80e elementor-widget elementor-widget-heading\" data-id=\"965e80e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Baking the shader<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-eeec6bd elementor-widget elementor-widget-text-editor\" data-id=\"eeec6bd\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Due to Qt&#8217;s cross-platform nature, the shader code needs to run on platforms that are using different graphic apis (Direct3D on Windows, Metal on Apple, etc. &#8230;). Qt&#8217;s answer to the heterogenous world of shader languages is the Qt Shader Baker (qsb &#8211;\u00a0<a class=\"external-link\" href=\"https:\/\/doc.qt.io\/qt-6\/qtshadertools-qsb.html\" rel=\"nofollow noopener\" target=\"_blank\">https:\/\/doc.qt.io\/qt-6\/qtshadertools-qsb.html<\/a>). <span id=\"added-diff-10\" class=\"diff-html-added\">Shader code is written<\/span> in modern GLSL. Qsb compiles it to SPIR-V which is then transpiled to shaders for the different graphic backends (like metallib for Apple platforms). Finally, the transpiled shaders are baked into one single qsb file that can easily be loaded from QML (see the example above).<\/p><p>The baking is automated by using cmake:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-9a163de elementor-widget elementor-widget-elementor-syntax-highlighter\" data-id=\"9a163de\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"elementor-syntax-highlighter.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre><code class='language-clike'>qt6_add_shaders(${PROJECT_NAME} &quot;qmlbasicstorage_shaders&quot;\r\n    GLSL &quot;430&quot;\r\n    HLSL 50\r\n    MSL 12\r\n    BATCHABLE\r\n    PRECOMPILE\r\n    OPTIMIZED\r\n    PREFIX\r\n        &quot;\/&quot;\r\n    FILES\r\n        &quot;shaders\/computeshader.comp&quot;\r\n) <\/code><\/pre><script>\nif (!document.getElementById('syntaxed-prism')) {\n\tvar my_awesome_script = document.createElement('script');\n\tmy_awesome_script.setAttribute('src','https:\/\/www.basyskom.de\/wp-content\/plugins\/syntax-highlighter-for-elementor\/assets\/prism2.js');\n\tmy_awesome_script.setAttribute('id','syntaxed-prism');\n\tdocument.body.appendChild(my_awesome_script);\n} else {\n\twindow.Prism && Prism.highlightAll();\n}\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-49f74a0 elementor-widget elementor-widget-text-editor\" data-id=\"49f74a0\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>It&#8217;s important to set the GLSL version to at least 440 as a compute pipeline needs at least OpenGL 4.3.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-cd595cb elementor-widget elementor-widget-heading\" data-id=\"cd595cb\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Future directions<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-71013d9 elementor-widget elementor-widget-text-editor\" data-id=\"71013d9\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Compute shaders become intriguing when tasked with processing huge blocks of data, where the intention is to render the results afterward. More complex examples than the one presented in the blog post are physical simulations or preprocessing of large datasets that are going to be rendered later on.<\/p><p>In the future, it would be interesting if the ComputeShaderItem were part of a larger processing pipeline. This would introduce items responsible for data generation to initialize storage buffers and for various visualization nodes to render results. Integration into the Qt Quick ShaderEffectItem would also be intriguing, enabling the storage buffers to be directly utilized as inputs for vertex shaders.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-a764d18 elementor-widget elementor-widget-heading\" data-id=\"a764d18\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Conclusion<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8cf8369 elementor-widget elementor-widget-text-editor\" data-id=\"8cf8369\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Integrating compute shaders in Qt Quick application may still feel somewhat low-level as compute shaders are operating with abstract data that is only interpretable in context. However, leveraging the power of Qt Quick, we&#8217;ve demonstrated the ease of prototyping compute pipelines. With QML, updating uniform variables by setting customized properties and defining storage\/image buffers for shaders is seamless. We provide two rendering options, but custom visualizers can also be straightforwardly implemented if the buffers require more complex interpretation than simple particle points.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>With this blog post, we introduce the\u00a0QtQuickComputeItem\u00a0&#8211; a Qt Quick item that allows you to easily integrate compute shader into your Qt Quick Code.<br \/>\nCompute<br \/>\nShader are used to perform arbitrary computations on the GPU. For<br \/>\nexample, the screenshot below shows a Qt Quick application that<br \/>\ngenerates Gray Scott Reaction Diffusion patterns.\u00a0 The simulation is executed by a compute shader that is configured directly in QML.<\/p>","protected":false},"author":16,"featured_media":4011,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1,2,7,720,8],"tags":[716,126,255,259],"class_list":["post-8828","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-allgemein","category-blog","category-general","category-newsletter","category-qt","tag-compute-shader","tag-qml","tag-qt-6","tag-qt-quick"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.basyskom.de\/en\/wp-json\/wp\/v2\/posts\/8828","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.basyskom.de\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.basyskom.de\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.basyskom.de\/en\/wp-json\/wp\/v2\/users\/16"}],"replies":[{"embeddable":true,"href":"https:\/\/www.basyskom.de\/en\/wp-json\/wp\/v2\/comments?post=8828"}],"version-history":[{"count":58,"href":"https:\/\/www.basyskom.de\/en\/wp-json\/wp\/v2\/posts\/8828\/revisions"}],"predecessor-version":[{"id":10797,"href":"https:\/\/www.basyskom.de\/en\/wp-json\/wp\/v2\/posts\/8828\/revisions\/10797"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.basyskom.de\/en\/wp-json\/wp\/v2\/media\/4011"}],"wp:attachment":[{"href":"https:\/\/www.basyskom.de\/en\/wp-json\/wp\/v2\/media?parent=8828"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.basyskom.de\/en\/wp-json\/wp\/v2\/categories?post=8828"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.basyskom.de\/en\/wp-json\/wp\/v2\/tags?post=8828"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}