How to index arrays of descriptors in glsl? - glsl

I have array of buffer descriptors, and each of them holds an array of different structs. What I need to do is pick each individually and tell what is inside. I, however, have barely any idea how glsl syntax works, and couldn't find anything online. Currently what I do is
struct myData
{
/.../
};
layout(set = 0, binding = 0)buffer a
{
uint count;
myData data[];
};
//or this
layout(set = 0, binding = 0)buffer a
{
uint count;
myData data[];
} A[2];
//And what I want is
layout(set = 0, binding = 0, index = 0)buffer a
{
uint countMyData;
myData data[];
};
layout(set = 0, binding = 0, index = 1)buffer b
{
uint countIndices;
uint indices[];
};

I have array of buffer descriptors, and each of them holds an array of different structs.
You have contradicted yourself. If you have an array of something, then each element is the same kind of something. Each element of an array of ints may have a different value, but each array element is an int.
That's what "array" means.
This is an either/or situation. Either the elements of a descriptor array use the same descriptor definition, or you create two different descriptor definitions, with two different binding locations, that represent two distinct descriptors.
Now, unsized descriptors that are arrayed can have different sizes for different array elements. But they're all going to use the same descriptor definition.

Related

Best way to represent a array of std::optional in protobuf

I need to map my "native" C++ struct that has an array(std::array, but I presume for std::vector solution is same) to protobuf.
So let' say I have
struct MyStruct{
// Color is some class I already know how to map to PB
std::array<std::optional<Color>, 4> opt_colors;
}
I am not sure what is the best way.
My current best guess is:
message ColorPb{
// some fields here
}
message OptColorPb{
int32 idx = 1; // idx in array
ColorPb color = 2; // value
}
message MyStructPb{
// in case of vector I would also have a size, but for array it is known
repeated OptColorPb opt_colors = 1;
}

Suggestions for returning memory from a class

I have a class which is supposed to keep pixel data (floats for the position, floats for the color). I'm trying to use a C++ style in data members (the data is kept in std::array<float, N> instead of plain C arrays). The class has other getters, setters and functions meant to be "helpers" to populate these fields.
Now I need to create an OpenGL vertex data buffer where I should write out
4 floats for xyzw
4 floats for rgba
2 floats for UV coords
in this order. I'm wondering how should I do this.. I tried doing
class MyVertexData {
std::array<float, 4> pos;
std::array<float, 4> rgba;
std::array<float, 2> uv;
public:
void writeData(float *ptrToMemory) {
if(ptrToMemory == nullptr)
throw std::runtime_exception("Null pointer");
std::array<float, 10> output;
output= {
pos[0], pos[1], pos[2], pos[3],
rgba[0], rgba[1], rgba[2], rgba[3],
uv[0], uv[1]
};
memcpy(memory, out.data(), 10 * sizeof(float));
}
};
// Caller code
std::vector<float[10]> buffer(4);
vertex0.writeElements(buffer[0]);
vertex1.writeElements(buffer[1]);
vertex2.writeElements(buffer[2]);
vertex3.writeElements(buffer[3]);
but this approach has two problems:
I need to trust the caller to have allocated memory to store 10 floats
No C++11+ signature, I just get a float pointer
I can't just return a std::unique_ptr since I need a contiguous memory area (buffer) where the elements are to be stored, but I also need a distinction between the different elements (that would also make the code more readable).
It would be nice to return a smart pointer or something similar whose memory I can easily "concatenate" to other elements so I can safely pass this stuff to OpenGL.
CppCoreGuidelines introduces span which is a view of contiguous element, so you may use something like:
void writeData(gsl::span<float, 10> ptrToMemory)
to express the intend.

How to create new Type in MPI

I am new to MPI and I want to create a new datatype for Residence struct. I just want to see if I can create the new type right way.
struct Residence
{
double x;
double y;
};
My new MPI Type
MPI_Datatype createRecType()
{
// Set-up the arguments for the type constructor
MPI_Datatype new_type;
int count = 2;
int blocklens[] = { 1,1 };
MPI_Aint indices[2];
//indices[0]=0;
MPI_Type_extent( MPI_DOUBLE, &indices[0] );
MPI_Type_extent( MPI_DOUBLE, &indices[1] );
MPI_Datatype old_types[] = {MPI_DOUBLE,MPI_DOUBLE};
MPI_Type_struct(count,blocklens,indices,old_types,&new_type);
MPI_Type_commit(&new_type);
}
You've almost got it right except that indices is supposed to give the offset of each structure field in bytes from the beginning of the structure. The correct way to construct such a type would be to use the offsetof operator, defined in stddef.h:
#include <stddef.h> // or <cstddef> for C++
struct Residence
{
double x;
double y;
};
MPI_Datatype createRecType()
{
// Set-up the arguments for the type constructor
MPI_Datatype new_type;
int count = 2;
int blocklens[] = { 1,1 };
MPI_Aint indices[2];
indices[0] = (MPI_Aint)offsetof(struct Residence, x);
indices[1] = (MPI_Aint)offsetof(struct Residence, y);
MPI_Datatype old_types[] = {MPI_DOUBLE,MPI_DOUBLE};
MPI_Type_struct(count,blocklens,indices,old_types,&new_type);
MPI_Type_commit(&new_type);
return new_type;
}
While this would suffice for that particular structure, in general one has to adjust the structured type length in order to account for any trailing padding that the compiler might insert at the end of the structure. This is only necessary if one wants to send multiple items of that structured type, i.e. an array of structure elements. The old way to do that was to add a third member to the structure of type MPI_UB (UB comes from Upper Bound) and set the offset of that member to be equal to sizeof(struct Residence) (padding is accounted in the structure size as returned by sizeof). The modern way is to use MPI_Type_create_resized, which creates a new MPI type with the same type signature as the original one but with a different extent:
MPI_Type_struct(count,blocklens,indices,old_types,&new_type);
// Create a resized type
MPI_Type resized_new_type;
MPI_Type_create_resized(new_type,
// lower bound == min(indices) == indices[0]
indices[0],
(MPI_Aint)sizeof(struct Residence),
&resized_new_type);
MPI_Type_commit(&resized_new_type);
// Free new_type as it is no longer needed
MPI_Type_free(&new_type);
return resized_new_type;
Only the relevant code lines are shown. The code above assumes that indices[0] gives the offset of the first structure element. One could instead use MPI_Type_get_extent to get the true lower bound and that would work for structure types with negative offsets. It is not necessary to commit new_type as it is only used to construct the resized type. It is also not necessary to keep it around and that's why it is freed after resized_new_type has been created.

Dynamic Memory Allocation: What is the alternative for a two dimensional array when the rightmost dimension is variable?

I am trying to develop a class to backup & restore console screen buffers. Here's my code in progress.
class CBuff
{
private:
CONST WCHAR max_unit;
HANDLE hnd;
CHAR_INFO *stor_buff;
COORD s_buff_sz;
COORD d_buff_cod;
SMALL_RECT read_region;
public:
CBuff():max_unit(10)
{}
~CBuff(){}
void Initiate(HANDLE hndl, SHORT buff_x, SHORT buff_y, SHORT buff_width, SHORT buff_height)
{
hnd=hndl;
stor_buff=new CHAR_INFO[buff_width*buff_height]();
s_buff_sz.X=buff_width;
s_buff_sz.Y=buff_height;
d_buff_cod.X=0;
d_buff_cod.Y=0;
read_region.Left=0;
read_region.Top=0;
read_region.Right=buff_width-1;
read_region.Bottom=buff_height-1;
}
int Backup()
{
if(!ReadConsoleOutput(hnd,stor_buff,s_buff_sz,d_buff_cod,&read_region)) return -1;
return 0;
}
int Restore()
{
if(!WriteConsoleOutput(hnd,stor_buff,s_buff_sz,d_buff_cod,&read_region)) return -1;
return 0;
}
int Backup_mp()
{/*incomplete*/}
int Restore_mp()
{/*incomplete*/}
};
It works with Backup() & Restore() fine. And then I tried to make another version of Backup, Backup_mp(handle, backup_num), that will create multiple backups from different console buffer instances. I planned on converting last four variables in private space into array, so that a index value (backup_num) can be used for different backup point. An allocation like this
stor_buff=new CHAR_INFO[index][buff_width*buff_height]();
is not working.
What option do I have?
Also, can I use CONST WCHAR max_unit as the parameter for an array like s_buff_sz[max_unit] ?
You're using C++, so make use of it: Use std::vector.
//Declaration of your buffers:
std::vector< std::vector<CHAR_INFO> > store_buffers;
//Append a new buffer entry:
store_buffers.push_back( std::vector<CHAR_INFO>( buff_width * buff_height ) );
// Pass buffer with index index to WinAPI functions:
..., store_buffers[index].data(), s_buff_sz, ...
If using C++11, you can use std::array for the fixed sized dimension (instead of std::vector, which is variable), but that's not critical.
To allocate a two-dimensional array in heap (using new), you need to allocate the pointers first, and then the arrays. Example:
stor_buff = new CHAR_INFO* [buff_height]; // Allocate rows (pointers
for(int index = 0; index < buff_height; ++index)
stor_buff[index] = new CHAR_INFO[buff_width];
And use them directly, as if store_buff is 2D array. For deallocation, you need to delete the arrays (i.e. individual rows) first, and then the row-pointer.
for(int index = 0; index < buff_height; ++index)
delete []stor_buff[index]; // NOTICE the syntax
delete []stor_buff;
Or, you may have a single-dimensional array, use it as 2D. For this you need to do (row,col) calculation to get the desired element.
You may also use vector (or vector of vector), to get the same. But I suggest you to play with native pointers, unless you get accustomed with pointers!

Access Violation with static arrays?

I need to parallelise an application using win32 threads. One of the portions of the code involves modifying an static array using threads.
I pass the array as a parameter like this:
struct threadParameter {
float **array;
int row;
}
An example code would be like this:
// Main
float data[100][100]
for (int i = 0; i < 100; i ++) {
tp = (*threadParameter) new threadParameter;
tp->array = (float **) data;
tp->row = i;
AfxBeginThread... // Begin thread code
}
// Thread Code
UINT myThread(LPVOID param) {
threadParameter *pp = (threadParameter *) param;
for (int j = 0; j < 100; j ++) {
pp->array[pp->row][j] = NEWVALUE;
}
}
However, when executing the project, I get an "Access Violation Error" when I try to acceess the array via the **array pointer. This problem does not occur if the array data is
dynamic. Is there any way to sort this problem out (I am not allowed to change the array data from static to dynamic)?
Static arrays are NOT pointers to pointers -- the entire array is a single huge chunk of data, and addressable with a single pointer, namely, the pointer to the base of the array. Hence
tp->array = (float **) data;
is incorrect, because you're dereferencing a number inside the array. (The fact that you needed to cast also should've raised a red flag, since arrays are implicitly converted to the appropriate pointer types.)
That's why the common phrase "arrays are just pointers" is incorrect; it's half-true for single-dimensional arrays, but completely false with multidimensional arrays. If you need to use two indices, convert a single index into a row-column index by multiplying the row by the row size, then adding the column and indexing into the array with a pointer.