I have a Vulkan renderer where a new render pass is started at the beginning of each frame. Then the command buffer is passed to several modules each of which submits some draw calls and other commands. Before the draw calls are submitted, it checks whether any additional textures have to be loaded which it does, at the end of the loading process an image layout transition to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL is performed.
The problem is that the layout transition uses a vkCmdPipelineBarrier command which only allows same format for input and output ( VUID-vkCmdPipelineBarrier-oldLayout-01181 ) which makes the transition useless for me.
My only solution at the moment is to move the layout transitions to a different command buffer and submit it to the command queue separately, then retrieve the result before continuing building my command buffer, but that means I have to wait for all previous commands in the queue to finish, right?
Can you imagine a cleaner solution for performing layout transitions between different layouts during an active render pass?
Regards
My only solution at the moment is to move the layout transitions to a different command buffer and submit it to the command queue separately, then retrieve the result before continuing building my command buffer, but that means I have to wait for all previous commands in the queue to finish, right?
You're not thinking fourth dimensionally.
The order you build the command buffers in is irrelevant. What matters is the order you submit them in.
The code which is building your rendering command buffer can also be building a transfer command buffer. You write your rendering command assuming the images are in the correct layout, and you write transfer commands which put those images into the right layout after the transfer is complete. The order you write these commands is irrelevant; the only order that matters is their submission order. Put one CB before the other in that order, and (barriers willing) they will execute appropriately in that order.
The CPU never needs to wait on anything. No "results" need to be retrieved; that's the GPU's job.
Being able to do this is why you have to tell Vulkan what the layout of each image is anytime you try to use it.
Related
I was trying to reproduce a result that is similar to this video: https://www.youtube.com/watch?v=21UsMuFTN0k Specifically, I want to render the whole scene to a different texture, and put the texture inside the UI like this screenshot of the video:
The author of the video was using OpenGL to do this, and I was trying to achieve it in Vulkan instead. However, since my current program is using the third attachment to enable MSAA and rendering the whole scene using secondary command buffers, I have difficulty translating the way to do this in the video to Vulkan. I figured that I probably not only need more framebuffers, but also multiple renderpasses. Simply put, so far this is what I tried:
Begin the first renderpass, with the renderpass begin info set to a smaller render area, an offscreen renderpass, and a separate framebuffer.
Pass the offscreen renderpass and the framebuffer to an inheritance info, and pass it to secondary command buffers to do the drawing.
End the first renderpass.
Begin the second renderpass, with the renderpass begin info set to the actual size of the screen, the primary renderpass, and the primary framebuffer.
Pass the second renderpass and the framebuffer to an inheritance info, and pass it to secondary command buffers to do the drawing.
Do vkCmdExecuteCommands.
End the second renderpass.
End command buffer.
Nonetheless, when the program is executed, the validation layer shows that:
vkCmdExecuteCommands(): Cannot duplicate VkCommandBuffer 0x1c26226d2e8[] in pCommandBuffers without VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set. The Vulkan spec states: If any element of pCommandBuffers was not recorded with the VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT flag, it
must not appear more than once in pCommandBuffers
Does this mean I have to set VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT for all secondary command buffers? Or there are other ways to correct do it? Because as far as I know, setting VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT has a performance cost.
Also, if I instead try to do vkExecuteCommands in each renderpass, the validation layer will show that the command buffer has been destroyed.
I wonder what the correct way to reproduce a similar result in Vulkan is, and whether I have to separate them so that I will have to do vkQueueSubmit multiple times.
You are trying to do two RenderPasses with different Framebuffers in a single CommandBuffer.
RenderPass Execution
Execution of RenderPasses inside Graphics Queue can be Out-of-order, ie) no guarantee that the RenderPasses will be executed based on the submission order. Since, you are recording multi-passes in the same Command Buffer, it can be a problem
Synchronization Using Semaphores
Record the First RenderPass and Second RenderPass in different Command Buffers and use Semaphores to synchronize when you submit it to the queue.
Use a Semaphore to signal in vkQueueSubmit for the First RenderPass. When you submit the Second RenderPass use the semaphore in the wait slot.
Check for VKSubmitInfo in VKQueueSubmit. This is used in internal synchronization in the queue.
ImageLayout Transition
You also have to ensure that the Texture you write and read are in the correct Layouts at the appropriate RenderPasses.
First RenderPass, the texture has to in COLOR_ATTACHMENT_OPTIMAL
Second RenderPass, the texture has to in SHADER_READ_ONLY_OPTIMAL
You can use use a ImageBarrier or make the first renderpass output to transition the attachment Layout to Read_Only thus preparing early.
General Instructions
Record First Pass with a CommandBuffer, Change Final ImageLayout of Texture to SHADER_READ_ONLY_OPTIMAL(if not using ImageBarrier)
Record Second Pass with a CommandBuffer
Submit First Pass with a wait Semaphore
Submit Second Pass with a signal Semaphore
If you use ImageBarrier, you need one more semaphore and one more Command Buffer to insert into middle of the First and Second Pass.
Command_Buffer_Simultaneous_Use_Bit
Simultaneous Bit is used when you need store some commands which needs to be submitted multiple times into different queues or recorded into different primary buffers.
This is commonly used in secondary buffers to store few commands (perhaps a common procedure in many process) and to record in primary buffers as needed.
In your case it's not needed.
I'm writing a graphics program in Python and I would like to know how to make a Canvas update only on-demand; that is, stop a canvas from updating every run of the event loop and instead update only when I tell it to.
I want to do this because in my program I have a separate thread that reads graphics data from standard input to prevent blocking the event loop (given that there's no reliable, portable way to poll standard input in Python, and polling sucks anyway), but I want the screen to be updated only at intervals of a certain amount of time, not whenever the separate thread starts reading input.
You can't pause the update of the canvas without pausing the entire GUI.
A simple solution would be for you to not draw to the canvas until you're ready for the update. Instead of calling canvas commands, push those commands onto a queue. When you're ready to refresh the display, iterate over the commands and run them.
You could also do your own double-buffering, where you have two canvases. The one you are actively drawing would be behind the visible one. When you are ready to display the results, swap the stacking order of the canvases.
I am working on a big project that puts performance as a high priority. I have a little bit of experience using wxPython to create windows and dialog boxes for software, but I have no experience in getting processes to work in parallel during the course of a single program.
So basically, what I want to accomplish is the following:
I want one main class that controls the high level program. It sets up a configuration either from a config file or from user input. This much I have accomplished on my own.
I need PROCESS #1 to read in a file and a list of commands, execute the commands, and then pass the modified file to PROCESS #2 (this requires that PROCESS #2 is ready to accept new input.) Once the file is passed, PROCESS #1 would begin work on the next set of inputs and wait for PROCESS #2 to finish before the cycle repeats.
PROCESS #2 takes input from PROCESS #1 and writes output to a log file. Once the output is complete, it waits for the next set of output from PROCESS #1.
I know how to use wxTimers and the events associated with that, but what I have found is that a timer event will not execute if the program is otherwise occupied (like in the middle of a method.)
I have seen threads about "threading" and "Pool", but the terminology tends to go over my head, and I haven't gotten any of that sort of stuff to work.
If anybody can point me in the right direction, I would be greatly appreciative.
If you use threads, then I think this would be fairly easy to do. Here's what I would suggest:
Create a button (or some other widget) to execute process #1 in a thread. The thread itself will run BOTH processes. Here's some psuedo-code that might help:
# this is in your thread code:
result = self.call_process_1(args)
self.call_process_2(result)
This will allow you to start another process #1/2 with a new set of commands every time you press the button. Since the two processes are encapsulated in the thread, they don't have to wait for process #2 to finish. You will probably need to log to separate logs for the logs to make sense, but you can label the logs with a timestamp and a thread number or a uuid.
Depending on how many of these processes you need to do, you might need to look into setting up a cluster that's driven with celery or some such. But I think this is a good starting place.
There are 2 forms.
Form2 isn't auto-created.
Form2:=TForm2.Create(Application);
Form2.Show;
If to do Sleep(10000); inside any forms then another one will be frozen. How to prevent this behavior?
My problem: a big text file (3 Mb) is continuously assigned (Lines.Assign) into a text editor, so a form is frozen.
Can I use another unfrozen form (not modal) to show a progress bar (a style is pbstMarquee)?
All GUI code should be run from the main thread, and it looks like you are following that rule.
If you call Sleep then the calling thread will not execute code until the timeout elapses. If you call Sleep from the main thread, then the message queue will not be pumped until the timeout elapses. Hence the entire app appears frozen.
Why does calling Sleep from one form affect another form? Because all GUI components are served from the single message queue of the main thread. Once you stop pumping that queue, all GUI components stop receiving queued messages like WM_PAINT, WM_KEYDOWN etc.
As I understand it your problem is that your application appears hung when you are loading a 3MB text file into an edit control. That size of file doesn't sound very large to me and one obvious solution would be to find an edit control that performs the load better. For example I'm pretty sure that Notepad, Notepad++ etc. do not take steps like showing progress when loading such files. I rather suspect that those apps don't pump the queue when loading files but you just don't notice because of the short time taken.
What you don't want to happen is for you to pump your queue to keep your GUI responsive and in turn allow the user to start loading another file whilst the first one is still loading. You need to disable your UI whilst processing a load operation. A modal progress dialog is one way to do that.
If you can't switch to a better performing control, you could show a modal progress dialog and use a background thread like this. The background thread would have load the file in small chunks, say into a string list. After each chunk of the file was ready it would then call Synchronize and get the main thread to add the contents of the string list to the edit control, and then clear the string list. The thread would then continue and load the next chunk. Adding to the edit control in small chunks would allow you to keep the message queue serviced.
You could show progress in a status bar rather than a modal dialog which would be less intrusive. But just remember to disable any UI that would cause re-entrant execution.
Better load your file in a separate thread. Or you will have to create your second form in a plain WinAPI, because VCL doesn't support multithreading.
I want to be able to load/download a bunch of resources and notify the user of the file that's currently being loaded, but I can't just draw a frame after each file starts loading because v-sync will wait until it can draw a frame before it continues (bottle-necking the loads to less than 60/second).
Is there a way to check whether the device is ready to draw or not (without hacky "has 1/60th of a second passed yet?), so I can perform actions until it's ready? I don't mind if the notification skips over files that finished before it's ready to draw, but I want to maximize the speed of the loads while still being able to notify the user.
Also, I'd like to avoid disabling v-sync even temporarily because I don't want to cause a graphic card crippling 300FPS rate if the computer loads really quickly.
You don't specify which version of Direct3D you're using. With D3D9 you can pass D3DPRESENT_DONOTWAIT to your Present() call and it will return D3DERR_WASSTILLDRAWING if the hardware is busy processing or waiting for a vertical sync interval. This means if you have vsync enabled, in your main loop you can just call Present with the DONOTWAIT flag whenever you've loaded a file and load another if it returns WASSTILLDRAWING.
Note that you need to get the swap chain and call Present() on the swap chain rather than calling Present() directly on the device to be able to pass this flag to present, or you can set it in the D3DPRESENT_PARAMETERS structure when you create the device or create an IDirect3DDevice9Ex instead of an IDirect3DDevice9 device and call PresentEx() instead of Present().
This doesn't solve the problem of files that take longer than a frame to load however - your frame rate will drop if you have a file that takes a long time to process. A better solution to this problem in my opinion would be to move as much of your IO as possible to another thread (in D3D9 you will still have to create D3D resources on your main thread however) and just pass the name of the file that's currently being processed to your main / render thread to display each time you present a frame.