I have multiple "renderers" which should draw to the same attachment (swap chain image to be precise). I don't know the number of such renderers beforehand so I can't use subpasses. This is how I wanted to implement it:
VkCommandBuffer cb{...}; // get current "main" command buffer
for(auto r : renderers)
{
VkRenderPassBeginInfo renderPassBeginInfo{get_render_pass_begin_info(...)};
vkCmdBeginRenderPass(cb, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
array<VkCommandBuffer, 2> buffs{r->getCommandBuffers()}; // renderer build two secondary command buffers...
vkCmdExecuteCommands(cb, 1, buffs[0]); // first should be used in a render pass
vkCmdEndRenderPass(cb);
vkCmdExecuteCommands(cb, 1, buffs[1]); // second should be used ooutside of a render pass
}
The problem here is that each new call to vkCmdBeginRenderPass clears the target. This happens because the attachment was created with loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR because I need to clear it (but only once).
The solution in my case would be to move vkCmdBeginRenderPass and vkCmdEndRenderPass outside of the loop, but in this case, I need to "collect" all secondary command buffers that can't be used inside a render pass and execute them later.
But since the concept of render passes doesn't go into my head I wonder if there may be a way to keep the attachment's data between render passes?
You could stop clearing the attachments on load. Just manually clear them, either before the render pass begins or at the start of the first subpass.
That being said, render passes are not cheap, and this is really not the way to use them. The correct solution is to restructure your rendering code so that you only need a single render pass.
Related
So I have my Q and E set to control a Camera that is fixed in 8 directions. The problem is when I call Input.is_action_just_pressed() it sets true two times, so it does its content twice.
This is what it does with the counter:
0 0 0 0 1 1 2 2 2 2
How can I fix thix?
if Input.is_action_just_pressed("camera_right", true):
if cardinal_count < cardinal_index.size() - 1:
cardinal_count += 1
else:
cardinal_count = 0
emit_signal("cardinal_count_changed", cardinal_count)
On _process or _physics_process
Your code should work correctly - without reporting twice - if it is running in _process or _physics_process.
This is because is_action_just_pressed will return if the action was pressed in the current frame. By default that means graphics frame, but the method actually detect if it is being called in the physics frame or graphic frame, as you can see in its source code. And by design you only get one call of _process per graphics frame, and one call of _physics_process per physics frame.
On _input
However, if you are running the code in _input, remember you will get a call of _input for every input event. And there can be multiple in a single frame. Thus, there can be multiple calls of _input where is_action_just_pressed. That is because they are in the same frame (graphics frame, which is the default).
Now, let us look at the proposed solution (from comments):
if event is InputEventKey:
if Input.is_action_just_pressed("camera_right", true) and not event.is_echo():
# whatever
pass
It is testing if the "camera_right" action was pressed in the current graphics frame. But it could be a different input event that one being currently processed (event).
Thus, you can fool this code. Press the key configured to "camera_right" and something else at the same time (or fast enough to be in the same frame), and the execution will enter there twice. Which is what we are trying to avoid.
To avoid it correctly, you need to check that the current event is the action you are interested in. Which you can do with event.is_action("camera_right"). Now, you have a choice. You can do this:
if event.is_action("camera_right") and event.is_pressed() and not event.is_echo():
# whatever
pass
Which is what I would suggest. It checks that it is the correct action, that it is a press (not a release) event, and it is not an echo (which are form keyboard repetition).
Or you could do this:
if event.is_action("camera_right") and Input.is_action_just_pressed("camera_right", true) and not event.is_echo():
# whatever
pass
Which I'm not suggesting because: first, it is longer; and second, is_action_just_pressed is really not meant to be used in _input. Since is_action_just_pressed is tied to the concept of a frame. The design of is_action_just_pressed is intended to work with _process or _physics_process, NOT _input.
So, apparently theres a built in method for echo detection:
is_echo()
Im closing this.
I've encountered the same issue and in my case it was down to the fact that my scene (the one containing the Input.is_action_just_pressed check) was placed in the scene tree, and was also autoloaded, which meant that the input was picked up from both locations and executed twice.
I took it out as an autoload and Input.is_action_just_pressed is now triggered once per input.
I think the question is clear, but in case the answer is no I'll describe the conundrum I have:
Minimal setup so a single render pass with a single subpass. Two attachments: color and depth, rendering a cube. The Depth attachment layouts (initial, mid, final) are:
VK_IMAGE_LAYOUT_UNDEFINED
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
So there's one automatic layout transition. I know that because of my .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, I'll get a write-after-write warning If I don't make it visible. So I'll use this subpass dependency:
constexpr VkSubpassDependency in_dependency{
.srcSubpass = VK_SUBPASS_EXTERNAL,
.dstSubpass = 0,
.srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
.srcAccessMask = 0,
.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
};
This targets the early fragment test because that's where the depth att gets clear-loaded. But: Don't I also need to include the _READ_BIT in my .dstAccessMask? Sync validation doesn't seem to care, but I think I do unless I missed some rule about the write visibility implying a read visibility?
In case there is such a thing, a pointer to the spec would be nice.
WRITE does not include READ. This is simply a matter of the operation in question.
Clearing an image uses the WRITE access mode. It does not use the READ access mode. So there's is no further hazard as far as clearing is concerned.
Once the image is cleared, the subpass can begin executing. Since subpass execution happens-after the clearing operation, there's no need for any further dependency.
Standard usage of Barriers is relatively straightforward, but I was wondering what is the behavior of two (or more) overlapping Image Barriers (especially with respect to their side effect -- the layout transition). E.g. (pseudocode):
begin( commandBuffer );
1: write( image );
2: imageBarrier(
image,
src=STAGE_FRAGMENT(from the write at 1:),
dst=STAGE_FRAGMENT(intended for read in FS of read at 4:),
appropriate src and dst access flags,
newLayout=A
);
3: imageBarrier(
image,
src=STAGE_FRAGMENT(from the write at 1:),
dst=STAGE_TRANSFER(intended for read by transfer of readT at 5:),
appropriate src and dst access flags,
newLayout=B
);
4: read( image ); // through vkCmdDraw -- expects layout A
5: readT( image ); // different kind of read through Transfer -- expects layout B
end( commandBuffer );
Is this even legal? (can you back it up by spec quote?)
What is the image layout at each point of the program?
For completeness, what is the proper/best way to write this (one producer, two consumers situation)? (Swap lines 3: and 4: and make it Read-Read dependency?)
An image cannot assume multiple layouts simultaneously. In the case of the code you suggested above, since the two barriers have no dependencies on each other, one would happen before the other, but the order is not specified. So the layout of the image afterwards would be one or the other. Which means one of the two reading operations is going to fail.
If you have two operations that use the image from two different layouts, then one of those operations must execute before the other, since they both cannot read the image in the layout they need to. And therefore, there must be an execution dependency between them:
1: write( image );
2: imageBarrier( image, src=COLOR_ATTACHMENT_OUT, dst=FRAGMENT_SHADER, newLayout=A );
3: read( image ); // e.g. through vkCmdDraw -- expects layout A
4: imageBarrier( image, src=FRAGMENT_SHADER, dst=TRANSFER, newLayout=B );
5: readT( image ); // different kind of read e.g. Transfer -- expects layout B
The dependency in #4 says that the layout transition and later TRANSFER commands will not occur until all previous FRAGMENT_SHADER operations have completed.
make it Read-Read dependency
It's not a "Read-Read dependency". A layout transition modifies the image (theoretically at any rate), just as surely as if you had written values to the image directly. So logically what you have is "I need to read from it in the FS. After that, I have to transition it to a new layout. After that, I need to read from it in a transfer operation".
It's a "Read-Write-Read dependency." The middle part needs to wait until the first read is done, but the second read can't happen until the middle part is finished. You need an execution dependency with an associated image memory barrier&layout transition.
I'm running an update() method n times per second to "update" the keyboard input from the user so I can read it later in the logic part of the program. So I find two ways of implementing this in the SDL Docs and I'm not sure which one should I use.
1; Loop for all events using SDL_PollEvent searching for key down/up events and saving the key states in a map so I can check for each key state in the logic of the program.
Note: Alternatively, I can also use SDL_PeepEvents instead of SDL_PollEvent to take only the event types that matter; so, it would not "thrown away" the events on the queue.
std::map<int, bool> keyboard; // Saves the state(true=pressed; false=released) of each SDL_Key.
void update()
{
SDL_Event event;
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_KEYDOWN:
keyboard[event.key.keysym.sym] = false;
break;
case SDL_KEYUP:
keyboard[event.key.keysym.sym] = true;
break;
}
}
}
2; Taking a snapshot from the keyboard each frame so I can read it easily.
Uint8* keyboard;
void update()
{
SDL_PumpEvents();
keyboard = SDL_GetKeyState(NULL);
}
With any of above implementations I can read keyboard just like this:
if (key_map[SDLK_Return]) printf("Return has been pressed.");
Also, is there another way to do so?
I prefer to do a variation of 1, where I fill three arrays, indicating not only the current state, but also which keys just went down and which keys just went up. This allows me to easily check for those events in code (without comparing to the previous snapshot), but, most importantly, it won't miss events that last less than a frame. For example, if your game is running at 10 fps due to a slow machine, the user might press and release an important key between two calls of your update routine, and then your system will never register it. This is extremely frustrating.
SDL also sends key events when the key is held down, which allow you to have multiple key down events for each key up. I find this particularly useful when implementing keyboard scrolling through a list of items, e.g. a keyboard-controlled menu.
You should use solution 2.
Why? As SDL_GetKeyState() docs point out, before using it you are expected to call SDL_PumpEvents() to update the state array.
When you are calling SDL_PollEvent(), it implicitly calls SDL_PumpEvents(). So, it basically updates the array for SDL_GetKeyState() anyway. By parsing these events manually, you just create a second array (well, actually a much slower map) holding the same information which SDL already collected for you.
So, I would dare say that first solution means doing the same thing twice. And if you ever decide to support things such as repeated keystrokes (SDL_EnableKeyRepeat()), you'll be reimplementing even a larger part of SDL.
I realize this question is quite old, but my answer could benefit someone. Personally, I use two arrays with SDL_GetKeyState. I store one array holding the current frame's keyboard state, and one array holding that last frame's keyboard state. (With some memcpy commands, it's really easy to update them.) Along with those two arrays, I have a map that converts strings like "A" to the SDL scancode values, but that is optional.
Then, when you need to check if something is released or pressed, you can combine the two arrays to check. (I made this a function.) For example, if you know that the key is pressed this frame, but wasn't pressed last frame, it was clearly just pressed this frame. if (currentFrame["A"] == true && lastFrame["A"] == false) {/*just pressed*/}
You would then do the opposite for the released. I find that method super easy to implement and use.
Is this possible?
I have a file in which a movie clip is launched when the user roles over another element. To make the user experience more pleasant this happens after a 3 second delay using setInterval. Is there a way of stopping and resetting this time if the user rolls off the element before the 3 seconds is up?
var xTimer = setInterval(wait, 3000);
function wait(){
show('all');
play('all');
clearInterval(xTimer);
}
Above is the code I have used to set the delay, and below is the code I had assumed would interrupt and reset the timer.
invisBtn.onRollOut = function(){
rollover_mc.gotoAndStop(1);
stop();
clearInterval(xTimer());
trace('off');
}
Any help on this would be massively appreciated.
First, the setInterval & clearInterval functions use a Number variable to work.
setInterval() returns a Number variable, and clearInterval() takes that Number in parameter to remove the previous started interval. Here you seem to keep the interval ID inside a function variable instead of a Number one.
Thus, clearInterval(xTimer()); should in reality be clearInterval(xTimer); (without the parenthesis after xTimer).
And secondly, so you can use it in the invisBtn.onRollOut function, just be sure that the xTimer variable is scoped correctly (not inside a function where the invisBtn.onRollOut isn't also), and not on different keyframes of the timeline (timeline keyframes in Flash tends to forget the code you've written on it as soon as the reading head passes onto a new keyframe of the layer which has the code on it).
Feel free to ask more details if you need !