read-only storage buffer in OpenGL ES and Spir-V - readonly

In OpenGL ES Shading Language, the shader storage buffer object (SSBO) can be decorated with qualifier readonly or writeonly.
Section 4.9 (Memory Access Qualifiers) of OpenGL ES Shading Language version 3.1 specification:
Shader storage blocks, variables declared within shader storage blocks and variables declared as image types (the basic opaque types with “image” in their keyword), can be further qualified with one or more of the following memory qualifiers: ...(A table is listed)
So I can have something in opengl es shader like this:
layout(std430, binding = 0) readonly buffer mybuffer {
a_struct_type myarray[]; //a_struct_type was defined before
};
But how to specify the readonly in spir-v?
In spir-v specification, 3.18 section, Access Qualifier, it says:
Used by OpTypeImage and OpTypePipe.
Does this mean that, in spir-v, the SSBO cannot be specified as readonly? I do not think SSBO falls into type OpTypeImage or OpTypePipe.
---------------------------------------------
Resource Type | Storage Class | Type
---------------------------------------------
Storage Buffer| Uniform |
|----------------| OpTypeStruct
| Storage Buffer |
----------------------------------------------

The appropriate decorations are unintuitively NonWritable and NonReadable.

Related

Ada - Deallocation from a Heterogenous List

I'm creating a heterogenous circular linked list through inheritance. As a dynamically allocated data type, I need some form of deallocation, so I initially thought of Ada.Unchecked_Deallocation. Unfortunately, with the way that my access type works because the root Element is tagged and because I want to be able to use the same pointer type to access any object of the hierarchy, the following code snippet will not compile.
type Element is tagged private;
type ElementPtr is access all Element'Class;
-- fully define Element
procedure Free is new Ada.Unchecked_Deallocation(Element, ElementPtr);
Does anyone have any suggestions for alternate forms of deallocation that I can use to free the memory used by an object of any inherited Element type pointed to by an ElementPtr? Thanks!
Element and Element'Class are different types,
and you try to instantiate Unchecked_Deallocation with mismatching types.
Try instantiating with Element'Class instead:
procedure Free is new Ada.Unchecked_Deallocation(Element'Class, ElementPtr);

In C++, is there a difference in memory usage between "enum class" versus "enum"?

I understand the benefits of using the strongly typed "enum class" over "enum", but a classmate and I are wondering if one or the other takes up more memory.
enum classs are still just integral values with no additional overhead. However an enum class's underlying type defaults to int while regular enum the type is unspecified and the implementation is free to select a minimal integral type. So in theory if you don't specify the underlying type an enum class may be bigger than a plain enum.
C++ specification 7.2.5 - Enumeration Deceleration
enum class
The underlying type can be explicitly specified using enum-base; if not explicitly specified, the underlying type of a scoped enumeration type is int.
enum
If no initializer is specified for the first enumerator, the initializing value has an unspecified integral
type.

Designs of an entity component system

I wonder how to implement the fastest version of an entity component system (ECS from now on) in C++.
First off, regarding terminology:
a Scene is a container for Entities (and Systems in some implementations)
a Component is a simple data storage (like position, collision box, image to render etc)
a System performs logic on Components fitting the System's requirements (this could be physics, player input, simple rendering etc.)
an Entity contains several Components to make up the final behavior
I listed all the designs we came up with below.
1. The "naive" way
The Scene contains all Entities unordered.
As the Systems update, every System has to loop through all Entities and check whether each Entity contains all required Components and then perform the update upon those Entities.
Obviously, this way is not too performant when having a lot of Systems and/or a lot of Entities.
2. Using "bitmask enums" and mapping
Each Component contains a type identifier in the form of a bitmask (e.g. 1u << 5 / binary [0...]100000).
Each Entity can then compose all Component's type identifiers (assuming all typeIDs are unique inside the Entity), so it looks something like
1u << 5 | 1u << 3 | 1u << 1
binary [0...]101010
The Scene contains some kind of map
where Systems can easily look up fitting Entities:
MovementSystem::update() {
for (auto& kv : parent_scene_) { // kv is pair<TypeID_t, vector<Entity *>>
if (kv.first & (POSITION | VELOCITY))
update_entities(kv.second); // update the whole set of fitting entities
}
}
Pros:
Faster than the naive way
Cons:
Systems have to look up appropriate Entities every single time they are updated.
A bitmask (enum) is limited to a number of bits (32 for uint32_t, at least 64 for unsigned long long) and in some cases you might need more Components than the bitmask allows.
3. Using no Systems
This method is described by Danvil in an answer below.
Pros:
Gets rid of the bitmask thing completely.
Likely to be faster than design #2.
Cons:
Relies on dynamic_cast for looking up a component whereas design #2 can directly look up a component and then safely static_cast it.
4. Using spare sets
This method has been described in by skypjack in an answer below. He explained his approach in great detail, so I'd suggest you read his answer.
Another approach that I found pretty promising and I've used in a project of mine (see EnTT on GitHub) is based on sparse sets.
I used them within the component pools, to keep track of which entity has a component associated and what's its slot.
Major benefits are:
You get for free a small array of all the entities that have the specific component (see here for further details) and this gives you a great boost in terms of performance when you iterate over them.
It keeps at a minimum the number of components actually assigned. Moreover, components are all kept compact in memory.
Cache misses are reduced at a minimum, for you pay only for what you use. In other terms, you get only those components that are actually assigned to an entity and all of them are near to each other in memory, no holes at all.
You get it at the price of an extra array with max length equal to the number of entities for each component pool (note that usually those arrays are smaller in a real world software).
Benchmarks shown that performance are far better than the ones of a well known entity component system based on bitmask descriptors (see the link above for further details). I've also verified that memory pressure is more or less the same, for you get rid of the array of bitmask descriptors but you introduce a set of mini arrays within the component pools.
Iterations over sets of entities when looking for multiple components can be highly improved too with a trick: find the shortest set and iterate over its entities (a really fast operation), then verify if the n-th entity has the other components and eventually return it.
Benchmarks proved that it's still faster than the bitmask based design on dense sets (where each entity has all the components). In case of sets not so dense (that is a reasonable assumption for a real world software), performance are definitely better than bitmask based solutions.
Finally, differently from solution #4, no dynamic cast is required in this case.
The whole thing gives you something I'd call an entity component registry. Systems can be defined as lambdas that capture the registry or functors to which you can pass the registry. There is no need to register systems with the registry itself.
I hope you got the idea behind this implementation.
If you need more details, feel free to ask.
I would say what you call a "System" is actually a component. An example for rendering: there is a component Pose (for 3D location rotation) and a component Mesh (holds vertex buffers). Now instead of having a function which checks if it can render that particular entity, add a component Renderer. This component connects to the Pose and Mesh components. The "System" rendering now only has to communicate with the component Renderer. And each entity is either renderable or it is now, there is not need for checking components each time and all work for rendering is collected as a component.
Code example:
struct Pose : public Component { float x,y; };
struct Mesh : public Component { std::vector<Vertex> vertices; };
struct Renderer : public Component {
Entity* entity;
void render() {
if(!mesh|| entity->componentsChanged) {
mesh = entity->getComponent<Mesh>();
if(!mesh) throw error;
}
if(!entity->pose) throw error;
glTranslate(entity->pose->x, entity->pose->y);
...
}
private:
Mesh* mesh;
};
struct Entity {
std::vector<Component*> components;
bool componentsChanged;
template<typename C> C* getComponent() const {
for(Component* c : components) {
C* cc = dynamic_cast<C>(c);
if(cc) return cc;
}
return NULL;
}
// "fast links" to important components
Pose* pose;
Renderer* renderer;
PhysicsStuff* physics;
};
struct Rendering
{
private:
void render(const std::vector<Entity*>& entities) {
for(Entity* e : entities) {
if(!e->renderer) continue;
e->renderer->render();
}
}
};

COM custom interface, member function pointer arguments get corrupted

I've been using COM few years, but never having to write an interface, so that gets me little confused.
I have an interface, let it be called IFoo, defined as
import "unknwn.idl";
[
object,
uuid( // guidgen generated one // ),
] interface IFoo : IClassFactory
{
HRESULT Bar(const BYTE * pb, ULONG cb );
};
which I have compiled using MIDL-generated files and registered into the Windows registry. I also have made a local COM server, essentially which implements IFoo. In this I followed "Microsoft SDKs\Windows\v7.0\Samples\com\fundamentals\dcom\simple\" sample code replacing IStream by my own IFoo.
I can create an instance of IFoo in my client code and all that, but the member function 'Bar' just doesn't work. I cannot figure out why, see, when I call
IFoo->Bar( 0x42A110, 352 ); // address just an example
the arguments are seen by the server side as
Bar( 0x560E20, 352 );
Address-values are not important, but what is this translation here?? Help appreciated :) Currently, I just pass a pointer to beginning of a std::vector's data which might just be inaccessible across process boundaries, but that doesn't explain the translation.
Arguments passed across COM boundaries are usually marshalled. This is done because the COM boundary may be a machine boundary (in the case of DCOM) or a process boundary (in the case of out of process COM components). The COM infrastructure does this marshalling on your behalf and what's done will depend on the data types involved. Read up on Appartments, Marshalling and Proxies and Stubs (or take a look at COM IDL & Interface Design) if you're interested in the details.
Given that marshalling will be required for your arguments you next need to understand how IDL declares the arguments to your function. The IDL you've written doesn't pass enough information to the MIDL compiler for the proxy and stub to be generated correctly. That BYTE *pb could be a single byte or an array and the value could be passed in to the function or returned from it... Now, I know that it's an array because I can see you have a length specified after it, but MIDL doesn't know that. Likewise I'm guessing it's data being passed into the function as cb isn't a pointer and so you can't be telling the caller how much data you've returned but only how large the array being passed in is... To inform MIDL that it needs to marshal a number of bytes rather than just one you need to tell it that pb is an array. You do this like this:
HRESULT Bar(
[in, size_is(cb)] BYTE *pb,
[in] ULONG cb);
What we're doing here is telling MIDL that the data in both pb and cb needs to be marshalled IN to the function and that pb represents an array of BYTE which is cb bytes long.

What is a Windows Handle?

What is a "Handle" when discussing resources in Windows? How do they work?
It's an abstract reference value to a resource, often memory or an open file, or a pipe.
Properly, in Windows, (and generally in computing) a handle is an abstraction which hides a real memory address from the API user, allowing the system to reorganize physical memory transparently to the program. Resolving a handle into a pointer locks the memory, and releasing the handle invalidates the pointer. In this case think of it as an index into a table of pointers... you use the index for the system API calls, and the system can change the pointer in the table at will.
Alternatively a real pointer may be given as the handle when the API writer intends that the user of the API be insulated from the specifics of what the address returned points to; in this case it must be considered that what the handle points to may change at any time (from API version to version or even from call to call of the API that returns the handle) - the handle should therefore be treated as simply an opaque value meaningful only to the API.
I should add that in any modern operating system, even the so-called "real pointers" are still opaque handles into the virtual memory space of the process, which enables the O/S to manage and rearrange memory without invalidating the pointers within the process.
A HANDLE is a context-specific unique identifier. By context-specific, I mean that a handle obtained from one context cannot necessarily be used in any other aribtrary context that also works on HANDLEs.
For example, GetModuleHandle returns a unique identifier to a currently loaded module. The returned handle can be used in other functions that accept module handles. It cannot be given to functions that require other types of handles. For example, you couldn't give a handle returned from GetModuleHandle to HeapDestroy and expect it to do something sensible.
The HANDLE itself is just an integral type. Usually, but not necessarily, it is a pointer to some underlying type or memory location. For example, the HANDLE returned by GetModuleHandle is actually a pointer to the base virtual memory address of the module. But there is no rule stating that handles must be pointers. A handle could also just be a simple integer (which could possibly be used by some Win32 API as an index into an array).
HANDLEs are intentionally opaque representations that provide encapsulation and abstraction from internal Win32 resources. This way, the Win32 APIs could potentially change the underlying type behind a HANDLE, without it impacting user code in any way (at least that's the idea).
Consider these three different internal implementations of a Win32 API that I just made up, and assume that Widget is a struct.
Widget * GetWidget (std::string name)
{
Widget *w;
w = findWidget(name);
return w;
}
void * GetWidget (std::string name)
{
Widget *w;
w = findWidget(name);
return reinterpret_cast<void *>(w);
}
typedef void * HANDLE;
HANDLE GetWidget (std::string name)
{
Widget *w;
w = findWidget(name);
return reinterpret_cast<HANDLE>(w);
}
The first example exposes the internal details about the API: it allows the user code to know that GetWidget returns a pointer to a struct Widget. This has a couple of consequences:
the user code must have access to the header file that defines the Widget struct
the user code could potentially modify internal parts of the returned Widget struct
Both of these consequences may be undesirable.
The second example hides this internal detail from the user code, by returning just void *. The user code doesn't need access to the header that defines the Widget struct.
The third example is exactly the same as the second, but we just call the void * a HANDLE instead. Perhaps this discourages user code from trying to figure out exactly what the void * points to.
Why go through this trouble? Consider this fourth example of a newer version of this same API:
typedef void * HANDLE;
HANDLE GetWidget (std::string name)
{
NewImprovedWidget *w;
w = findImprovedWidget(name);
return reinterpret_cast<HANDLE>(w);
}
Notice that the function's interface is identical to the third example above. This means that user code can continue to use this new version of the API, without any changes, even though the "behind the scenes" implementation has changed to use the NewImprovedWidget struct instead.
The handles in these example are really just a new, presumably friendlier, name for void *, which is exactly what a HANDLE is in the Win32 API (look it up at MSDN). It provides an opaque wall between the user code and the Win32 library's internal representations that increases portability, between versions of Windows, of code that uses the Win32 API.
A HANDLE in Win32 programming is a token that represents a resource that is managed by the Windows kernel. A handle can be to a window, a file, etc.
Handles are simply a way of identifying a particulate resource that you want to work with using the Win32 APIs.
So for instance, if you want to create a Window, and show it on the screen you could do the following:
// Create the window
HWND hwnd = CreateWindow(...);
if (!hwnd)
return; // hwnd not created
// Show the window.
ShowWindow(hwnd, SW_SHOW);
In the above example HWND means "a handle to a window".
If you are used to an object oriented language you can think of a HANDLE as an instance of a class with no methods who's state is only modifiable by other functions. In this case the ShowWindow function modifies the state of the Window HANDLE.
See Handles and Data Types for more information.
A handle is a unique identifier for an object managed by Windows. It's like a pointer, but not a pointer in the sence that it's not an address that could be dereferenced by user code to gain access to some data. Instead a handle is to be passed to a set of functions that can perform actions on the object the handle identifies.
So at the most basic level a HANDLE of any sort is a pointer to a pointer or
#define HANDLE void **
Now as to why you would want to use it
Lets take a setup:
class Object{
int Value;
}
class LargeObj{
char * val;
LargeObj()
{
val = malloc(2048 * 1000);
}
}
void foo(Object bar){
LargeObj lo = new LargeObj();
bar.Value++;
}
void main()
{
Object obj = new Object();
obj.val = 1;
foo(obj);
printf("%d", obj.val);
}
So because obj was passed by value (make a copy and give that to the function) to foo, the printf will print the original value of 1.
Now if we update foo to:
void foo(Object * bar)
{
LargeObj lo = new LargeObj();
bar->val++;
}
There is a chance that the printf will print the updated value of 2. But there is also the possibility that foo will cause some form of memory corruption or exception.
The reason is this while you are now using a pointer to pass obj to the function you are also allocating 2 Megs of memory, this could cause the OS to move the memory around updating the location of obj. Since you have passed the pointer by value, if obj gets moved then the OS updates the pointer but not the copy in the function and potentially causing problems.
A final update to foo of:
void foo(Object **bar){
LargeObj lo = LargeObj();
Object * b = &bar;
b->val++;
}
This will always print the updated value.
See, when the compiler allocates memory for pointers it marks them as immovable, so any re-shuffling of memory caused by the large object being allocated the value passed to the function will point to the correct address to find out the final location in memory to update.
Any particular types of HANDLEs (hWnd, FILE, etc) are domain specific and point to a certain type of structure to protect against memory corruption.
A handle is like a primary key value of a record in a database.
edit 1: well, why the downvote, a primary key uniquely identifies a database record, and a handle in the Windows system uniquely identifies a window, an opened file, etc, That's what I'm saying.
Think of the window in Windows as being a struct that describes it. This struct is an internal part of Windows and you don't need to know the details of it. Instead, Windows provides a typedef for pointer to struct for that struct. That's the "handle" by which you can get hold on the window.,

Resources