[Noob] Memory and MemoryTypeBits

I’ve started looking in to buffers and memory.
And I got few questions:

  1. How relevant is the querying vulkan for VkMemoryRequirements, when the .size of the structure will return the same size i declare in for the buffer?

  2. MemoryTypeIndex , takes the index of the memory type array when we query the phisical device’s memory properties. Almost all tutorials I’ve seen have a function to fetch that info. But when i was looking arouind the physical device memory properties via prints to the console. I noticed that one can clearly identify which MemoryTypeIndex(and thus it’s heapIndex) is describing the VRAM, CPU RAM, and the VRAM visible to the CPU.
    Thus I wondered if the above mentioned function is necessary, if we can clearly identify and store these indices. Until I got to the memoryTypeBits of the memory requirements structure. It makes sense that maybe some buffers will only be device local ,while others only be host visible etc. Since I was already printing the size,alignment and typebits to the console I decided to change the settings of the vulkan buffer to see if the typeBits changed.
    I tried changing the size from 1 to way above the available VRAM or CPU RAM, but those still stayed the same. I changed the buffer usage, OR-ed few usages but that didn’t change, I made it conccurent on the sharing mode and gave some other queue family index, still the same bits were in the memory requirements struct. So…is there a case where these memoryTypeBits will be anything but device local, host visible , host coherent and host cached? If they always are the same thus what’s the point of the memory requirements struct if we already know the size when we are creating the buffer, and if the bitmask is always these main typebits why create a function to always query the device for it’s memory types and not just record them under variables like for example cpu_memory, gpu_memory, and just pass that index to the VkMemoryAllocateInfo?

  1. How would you know it is the same without querying first?
  2. Some memory types can be unsupported by a given memory type, so you always need to query.

Do not trial-and-error Vulkan. It is a low level API, not a script kiddie Javascript or something. You have an API contract given solely by the specification (not by trying if something happens to work on your particular PC that one time). Honor it always, or there be dragons.

1 Like

Never assume that what you’re currently seeing is what your Vulkan implementation is required to provide. Always follow the specification, not what the implementation says.

VkMemoryRequirements::size may be larger than the VkBuffer's size. If you ask for 1000 bytes, the implementation may tell you that the actual size shall be 1024, rounding up to the nearest KB. This is relevant as it can force you into moving adjacent buffers and textures around to compensate for any size changes the implementation forces.

The standard is very clear: the memory region bound to a buffer is sized based on what VkMemoryRequirements::size returns. Not the size you asked for.

… so what? That tells you basically nothing of value.

If an implementation requires that you use allocations from memoryType 3 for a particular buffer or image, then for said buffer/image, you must use that memoryType. It doesn’t matter if you can identify if it is “VRAM” or whatever; you must use memory allocated via memoryType 3 for that resource.

For example, if you want to render to a particular image (and therefore require the COLOR_ATTACHMENT usage), the implementation can force you to use memoryType X, even if it is indistinguishable from memoryType Y in terms of its bits. That’s perfectly valid, and your code must respect the implementation’s ability to impose this requirement upon you.


Also, please do not put [Noob] in your titles. It’s not useful information for anyone responding to the thread or reading it later.

@Alfonse_Reinheart
I’m adding [Noob] simply as a notification that the question might be silly or stupid, so people not interested in answering those won’t interact. But if it’s ok to not add that to the title then won’t do it from now on.

About the size of MemoryRequirements, well the specs say that the memory requirements could ask for more memory than what I declare for the buffer , and that was basically the question. Since I changed the buffer size and the memory requirements were 1:1. I changed it’s type and it was 1:1, I chaged the sharing type and it was 1:1. So I wondered in what case it won’t be 1:1. I kind of figured it would be hardware/implementation dependent as you said, just wanted to make sure that my small test (create 1 buffer and check the mem requirements struct) isn’t the norm.

Identifing the memory type index…well from what I understand the memory type in the memory requirement uses a bitmask right? thus all of the on bits are memory types that can be used for that buffer. So if all buffers can be used with these types(since changing the size, usage and sharing mode didn’t change them) then why can’t we explicitly tell which memory goes where? What is a specific case where a buffer can only allocate device local memory?..And yeah I understand it’s implementation dependent, the spec says we should always get the requirements, me looking at one buffer only is wrong since it’s an really isolated case not a working example. But still I was wondering in what case the bits will be different to justify querying the GPU ,every time we make a buffer, about these indices when we can analyze them upfront.
Anyway I think I have a better understanding now.

@krOoze I actually use Python in this case, not because I can’t use C, but because I find python faster in terms of prototyping, rather than dealing with full on C. And I’m not a pro programmer so python is easier for me to learn about Vulkan, at least on a basic level. I guess once I start getting in to multithreading I should start using C.
As for trial and error…well actually I like trial and error learning. For example recently I learned more about the topic on queue creation,types and how to use them, when I was banging my head why is renderdoc capturing my render perfectly but I was not seeing anything on screen. So I don’t see anything wrong if I’m learning by intentionally braking it.
As for the PC at home thing, well I don’t have access to many GPUs except mine so…that’s all I got for now. And I’m trying to learn Vulkan not make a commercial product at the moment.

All of that is defined by the implementation. Your implementation allows any use of buffers from any memory types. Vulkan does not require implementations to do that, nor does your current implementation guarantee that this will be true tomorrow.

So it is not something your code should rely on.

That only works with systems that are safe, where “errors” are readily identified and rejected by the system in obvious, detectable ways.

Vulkan isn’t that kind of system. Safety is something you must provide, not something the system imposes upon you. You can write entirely incorrect code, and it will appear to work on some particular implementation. Or even all implementations… today. Tomorrow, it may not.

Never assume that some Vulkan code is correct because it appears to “work”.

Also, C is not that kind of system. So be careful of that.

So you’re saying that every time I run my code, it’s considered a new “implementation” that could work this time but next time could not? Or your saying that perhaps changes like OS updates or driver updates, can change how vulkan is doing things , thus memoryRequirements is a way to make sure it will always work despite these changes?

Also it’s out of the topic, but are you suggesting that wrong use of Vulkan can inflict damage to the hardware? Or you are suggesting an application crash or system crash etc…

Basically, yes. The requirements specified by the implementation are only valid for the duration of the use of that implementation. What might cause a Vulkan implementation to change its requirements is irrelevant; what matters is that they are reliable only while that VkDevice is live.

If you destroy the device and create a new one, all bets are off; you must ask it what its requirements are.

My point was about “trial and error learning”; that only works when “errors” are reliable. Vulkan does not make errors reliable. Code can violate the Vulkan specification’s requirements without visibly showing any errors.

You cannot rely on “my code seems to work” as a substitute for knowing if your code is correct.

Consider Python. If you index an array out of bounds, you get an error. This is because Python is safe. Trial-and-error coding worked because you tried a thing, got an error consistently and clearly, and therefore learned that this thing is not valid Python code.

Consider C. If you index an array out of bounds… maybe the program crashes. Or maybe you just access random memory. Or maybe it crashes if you do it in some places and not in other places.

Or maybe it works fine for years, and then someone passes cleverly designed input that causes the stack to be bashed and allows them to execute arbitrary code on your machine.

C is not safe. Trial-and-error programming told you that your code was fine, but it really wasn’t.

Vulkan is like that. Trial-and-error programming is not an effective way to learn Vulkan. Or C.

are you suggesting that wrong use of Vulkan can inflict damage to the hardware

There was a time programming could actually do that. These days though OS and HW should protect you from that. Though I mean, if you get BSOD you can have some file corruption or something as a result of the necessary hard reset, right?

What we mean is it is a matter of discipline. And since you identified yourself as “noob”, you are the disciple here. Yes, everybody likes to learn by trial-and-error. It is easy! Elementary school children can do it! But it is a greedy algorithm. It is fast, but can give wrong or suboptimal answer. It is not as bad as if you did that while being a surgeon or bridge architect, but it is still a bad way to learn Vulkan. At this level, you are supposed to learn by actually reading the documentation (imagine the horror!) and be the guarant of correctness for people above you in abstraction level.

If the documentation is not unambiguously clear, then making stuff up or starting to throw garbage at the GPU to see what works is the wrong instinct. The right instinct is to petition to correct the documentation, so everybody (particularly the driver makers who can do the most harm) are painfully clear about the API contract.

Anyway, may I inquire for what purpose you are learning Vulkan? It is for the people drawn to the bit-jokeying at low level. It is a tool to make the scaffolding and the foundations (the slow way). Or of course for bit of fooling around and expanding one’s brain for no reason at all. But if rapid prototyping is what you want, you might have been misdirected and things like Unity or shader toys are what you need.

1 Like

@Alfonse_Reinheart
I think now I’m more knowledgeable why the memory requirements query exist as a necessary part of memory allocation. I think that bit of information I was looking for, that basically I might be getting the same result now but on another hardware it might be something else, or on the same hardware but with different drivers for example it will also give different result, so vulkan makes sure that the memory allocation is always correct by using that query. If I can sum it up like that. I’ll mark your previous reply as the answer.

As for the C and Python example, yeah I guess you are right, but still isn’t getting junk data from accidently going out of bounds and debugging it, also a form of trial and error. And that’s a replicable result, although as you said we don’t get an explicit error report like in python.

@krOoze
I kind of don’t like the title of disciple…it sounds kind of cultish, but I get your point I’m the novice asking for clarification, and I don’t want to be disrespectful . But I’m not learning only with trial and error, I’m looking at tutorials and reading the specs(yes I’m following the recommendation of everyone out there, although I do have my own opinion on that), reading some books. I’m watching video tutorials(although those were more available in the past 1-2 years), I did the vulkan-tutorial, I’ve read some amd articles, some samsung ones, recently I started looking at the all famous “sascha williems examples” and whenever I encounter something I don’t understand I go in and start poking with trial end error. Basically I don’t want to learn how to do this or that by blindly following a spec or an example of a good solution. I want to understand why I should be doing xyz, like what’s the concept and what happens if you don’t do it xyz.

As for the documentation since I’m a beginner and not working as pro graphics programmer, I don’t feel I’m in any place to petition for anything. I suppose the documentation is geared for graphics programmers not hobbyists like myself who are actually working in another field.
Which brings me to why I’m learning Vulkan, I can go long about why, but let’s say it’s like a hobby. Eventually I have few apps as ideas, but I bet that if I shared those ideas here, everyone will say “use OpenGL instead”.

What if its not “junk data”? What if you’re writing a value off the end of an array and you read it back and it happens to not have been overwritten by anything… that time?

Trial-and-error only works in systems that detect errors consistently. If it is used in systems that do not, it will create false positives (ie: a belief that your code is fine when it isn’t).

The Vulkan specification is not that complex of a document. And learning how to learn from a source text instead of trial-and-error is a good skill to cultivate. Especially if low-level programming is a thing you want to do.

Blindly following example code is also a bad idea. But “blindly following a spec” is exactly what you should be doing. The specification defines what Vulkan is.

UBINAE

1 Like

Well you are correct, it’s not junk data. It was writing to the memory with the exact data I gave it. The difference is that to me it was wrong, since I assumed wrongly what I can do(maybe mislead by the python’s wrapper since it allowed me to pass a float). But yeah the specification says uint32_t. And I didn’t saw that VkBuffers are untyped(or I assume that’s what unformatted means). So in the end Yes, specification is clear and the issue was with me not reading fully and understanding clearly. I’m not critiquing the specification or Vulkan. It’s my fault.

Yes I agree, but again, I’m doing trial and error only on parts that I don’t understand from the spec or haven’t herd or read a good explanation.
And again…to you trial and error is valid only if errors are reported, to me getting false positives is the error being reported. I’m just trying things out in a as fragmented tests as possible(like I couldn’t tested the fill buffer until I had a command buffer, for example) not building an vulkan renderer from start to finish and only then wondering where it’s failing.
Anyway thank you for your time and suggestions, will keep them in mind. And will try to read the full spec from now on, not just the isolated pages from the online searches.