Reassign shader buffer value - opengl

In this question about growing buffers, someone answers with the following code.
// Bind the old buffer to `GL_COPY_READ_BUFFER`
glBindBuffer (GL_COPY_READ_BUFFER, old_buffer);
// Allocate data for a new buffer
glGenBuffers (1, &new_buffer);
glBindBuffer (GL_COPY_WRITE_BUFFER, new_buffer);
glBufferData (GL_COPY_WRITE_BUFFER, ...);
// Copy `old_buffer_size`-bytes of data from `GL_COPY_READ_BUFFER`
// to `GL_COPY_WRITE_BUFFER` beginning at 0.
glCopyBufferSubData (GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, old_buffer_size);
This is my understanding of the above, in order to copy A to B:
Bind A
Generate B
Bind B
Write null contents to B at larger size
Copy A to B
My problem is that A is the original vertex buffer for the shader, but so is B, (since changing the size is the goal). In my code (C# opentk) the shader tells me the ID of the buffer that coincides with a named shader variable using GL.GetActiveAttrib, I can't find how to make it use a different buffer than the one it gives.
So I either have to reassign the shader to use B afterwards, or do a double copy:
Bind A
Generate B
Bind B
Write null contents to B at larger size
Copy A to B
Reassign shader to use B
Write null contents to A at larger size (size of B)
Copy B to A
Is it possible make it use a specific buffer or to avoid double copying?

Once you have set the size of the buffer with glBufferData this size becomes inmutable. That's why a copy to another bigger buffer B is needed.
The good news is that you can re-bind the buffer with a different target. This is what you can do in your buffer-manager (it seems you wrongly call it "shader". A shader is a program in the GPU). No need a second copy.
GL_COPY_READ_BUFFER and GL_COPY_WRITE_BUFFER targets are useful if you want to keep previous bindings. This is not your case, so the copy is simpler:
//The buffer must be bound before copying it
glBindBuffer(GL_ARRAY_BUFFER, oldBuf); //or GL_ELEMENT_ARRAY_BUFFER or whatever it was
//New buffer
glGenBuffers (1, &newBuf);
//GL_COPY_WRITE_BUFFER is needed because GL_ARRAY_BUFFER is in use by oldBuf
glBindBuffer (GL_COPY_WRITE_BUFFER, newBuf);
glBufferData (GL_COPY_WRITE_BUFFER, newSize, ...);
glCopyBufferSubData (GL_ARRAY_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, old_buffer_size);
Now the copy is done, buffer oldBuf can be safetely deleted.
Two things left to do:
a) Tell the buffer-manager to use 'newBuf' insted of 'oldBuf'
b) Before using this new buffer, re-bind it to the target you need
glBindBuffer(GL_ARRAY_BUFFER, newBuf);
Well, there's one more thing to do. When the VAO was bound and the association "attribute - buffer to read from" was established by glVertexAttribPointer it used the oldBuf buffer. But now you want another buffer. So you must bind that VAO again, bind the new buffer and use glVertexAttribPointer.
A better solution may be to have a big buffer, and use only part of it. Let's say you have a VBO for one million vertices. 1M x 3 floats x 4 bytes = 12M bytes. That isn't a size any not-too-old GPU can't handle.
If your data changes in size, but not beyond that 1M vertices, then the easiest way is to use glBufferSubData and upload new data, even it is just added data. No new buffer, no copy, no VAO state change.

Related

sending IOKit command with dynamic length

I'm using IOKit framework to communicate with my driver using IOConnectCallMethod from the user-space client and IOExternalMethodDispatch on the driver side.
So far I was able to send fixed length commands, and now I wish to send a varied size array of chars (i.e. fullpath).
However, it seems that the driver and the client sides command lengths are coupled, which means that checkStructureInputSize from IOExternalMethodDispatch in driver must be equal to inputStructCnt from
IOConnectCallMethod in client side.
Here are the struct contents on both sides :
DRIVER :
struct IOExternalMethodDispatch
{
IOExternalMethodAction function;
uint32_t checkScalarInputCount;
uint32_t checkStructureInputSize;
uint32_t checkScalarOutputCount;
uint32_t checkStructureOutputSize;
};
CLIENT:
kern_return_t IOConnectCallMethod(
mach_port_t connection, // In
uint32_t selector, // In
const uint64_t *input, // In
uint32_t inputCnt, // In
const void *inputStruct, // In
size_t inputStructCnt, // In
uint64_t *output, // Out
uint32_t *outputCnt, // In/Out
void *outputStruct, // Out
size_t *outputStructCnt) // In/Out
Here's my failed attempt to use a varied size command :
std::vector<char> rawData; //vector of chars
// filling the vector with filePath ...
kr = IOConnectCallMethod(_connection, kCommandIndex , 0, 0, rawData.data(), rawData.size(), 0, 0, 0, 0);
And from the driver command handler side, I'm calling IOUserClient::ExternalMethod with IOExternalMethodArguments *arguments and IOExternalMethodDispatch *dispatch but this requires the exact length of data I'm passing from the client which is dynamic.
this doesn't work unless I set the dispatch function with the exact length of data it should expect.
Any idea how to resolve this or perhaps there's a different API I should use in this case ?
As you have already discovered, the answer for accepting variable-length "struct" inputs and outputs is to specify the special kIOUCVariableStructureSize value for input or output struct size in the IOExternalMethodDispatch.
This will allow the method dispatch to succeed and call out to your method implementation. A nasty pitfall however is that structure inputs and outputs are not necessarily provided via the structureInput and structureOutput pointer fields in the IOExternalMethodArguments structure. In the struct definition (IOKit/IOUserClient.h), notice:
struct IOExternalMethodArguments
{
…
const void * structureInput;
uint32_t structureInputSize;
IOMemoryDescriptor * structureInputDescriptor;
…
void * structureOutput;
uint32_t structureOutputSize;
IOMemoryDescriptor * structureOutputDescriptor;
…
};
Depending on the actual size, the memory region might be referenced by structureInput or structureInputDescriptor (and structureOutput or structureOutputDescriptor) - the crossover point has typically been 8192 bytes, or 2 memory pages. Anything smaller will come in as a pointer, anything larger will be referenced by a memory descriptor. Don't count on a specific crossover point though, that's an implementation detail and could in principle change.
How you handle this situation depends on what you need to do with the input or output data. Usually though, you'll want to read it directly in your kext - so if it comes in as a memory descriptor, you need to map it into the kernel task's address space first. Something like this:
static IOReturn my_external_method_impl(OSObject* target, void* reference, IOExternalMethodArguments* arguments)
{
IOMemoryMap* map = nullptr;
const void* input;
size_t input_size;
if (arguments->structureInputDescriptor != nullptr)
{
map = arguments->structureInputDescriptor->createMappingInTask(kernel_task, 0, kIOMapAnywhere | kIOMapReadOnly);
if (map == nullptr)
{
// insert error handling here
return …;
}
input = reinterpret_cast<const void*>(map->getAddress());
input_size = map->getLength();
}
else
{
input = arguments->structureInput;
input_size = arguments->structureInputSize;
}
// …
// do stuff with input here
// …
OSSafeReleaseNULL(map); // make sure we unmap on all function return paths!
return …;
}
The output descriptor can be treated similarly, except without the kIOMapReadOnly option of course!
CAUTION: SUBTLE SECURITY RISK:
Interpreting user data in the kernel is generally a security-sensitive task. Until recently, the structure input mechanism was particularly vulnerable - because the input struct is memory-mapped from user space to kernel space, another userspace thread can still modify that memory while the kernel is reading it. You need to craft your kernel code very carefully to avoid introducing a vulnerability to malicious user clients. For example, bounds-checking a userspace-supplied value in mapped memory and then re-reading it under the assumption that it's still within the valid range is wrong.
The most straightforward way to avoid this is to make a copy of the memory once and then only use the copied version of the data. To take this approach, you don't even need to memory-map the descriptor: you can use the readBytes() member function. For large amounts of data, you might not want to do this for efficiency though.
Recently (during the 10.12.x cycle) Apple changed the structureInputDescriptor so it's created with the kIOMemoryMapCopyOnWrite option. (Which as far as I can tell was created specifically for this purpose.) The upshot of this is that if userspace modifies the memory range, it doesn't modify the kernel mapping but transparently creates copies of the pages it writes to. Relying on this assumes your user's system is fully patched up though. Even on a fully patched system, the structureOutputDescriptor suffers from the same issue, so treat it as write-only from the kernel's point of view. Never read back any data you wrote there. (Copy-on-write mapping makes no sense for the output struct.)
After going through the relevant manual again, I've found the relevant paragraph :
The checkScalarInputCount, checkStructureInputSize, checkScalarOutputCount, and checkStructureOutputSize fields allow for sanity-checking of the argument list before passing it along to the target object. The scalar counts should be set to the number of scalar (64-bit) values the target's method expects to read or write. The structure sizes should be set to the size of any structures the target's method expects to read or write. For either of the struct size fields, if the size of the struct can't be determined at compile time, specify kIOUCVariableStructureSize instead of the actual size.
So all I had to do in order to avoid the size verification, is to set the field checkStructureInputSize to value kIOUCVariableStructureSize in IoExternalMethodDispatch and the command passed to the driver properly.

OpenGL MRT glDrawBuffers() argument numbers and behavior

I have a total of 5 render targets. I use the same shader to write to the first 4, then in a seperate pass write to the last one.
Before calling rendering to the first 4 targets I call:
GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3};
glDrawBuffers(4, drawBuffers);
However, when I call it for second pass and only want to write to the last one, the 5th target, why does the following give strange results?
GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT4 };
glDrawBuffers(1, drawBuffers);
Why do I have to instead use:
GLenum drawBuffers[] = { GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_COLOR_ATTACHMENT4 };
glDrawBuffers(5, drawBuffers);
Is this simply how glDrawBuffers() works, or is being caused by something else?
EDIT: fixed code with regards Jarrods comment
Yes, this is simply how glDrawBuffers works. But there's a reason for that.
Fragment shaders write color outputs that map to certain "color numbers". These have no relation to GL_COLOR_ATTACHMENT''i'' numbers. The entire point of glDrawBuffers is to map those fragment color numbers to actual buffers in the framebuffer.
http://www.opengl.org/sdk/docs/man/xhtml/glDrawBuffers.xml
The 2nd parameter must be of the type const GLenum* i.e. a pointer "to an array of symbolic constants specifying the buffers into which fragment colors or data values will be written".
So just passing GL_COLOR_ATTACHMENT4 as the 2nd param is the wrong type. You need to pass a pointer to an array of GLEnum.
I find that there's something wrong in glDrawBuffers().
for exmple
tmp = {attement_color0, attachement_color2}
glDrawBuffers(tmp).
in shader:
gl_fragdata[0]=...
gl_fragdata[2]=...
or u can use layout location to define the attments output.
But sometimes, at least in my PC, it does not work. I mean the attachment_color2 does NOT have the exact output.

memcpy size value

I will copy the data I received with recv() and the maximum size is MAX_PACKET for in/out buffers.
Is it safe to copy it with the fixed size MAX_PACKET? Is it necessary for me to set the right size of the buffer when I use memcpy ?
recv(sock,recvbuf,MAX_PACKET,0);
memcpy(inbuffer,recvbuf,MAX_PACKET);
you need to declare inbuffer at least as many bytes as the size of MAX_PACKET
char * inbuffer = new char[MAX_PACKET];
and place before each recv()
memset(inbuffer,0,MAX_BUFFER);
to zero out the buffer so you don't mistakenly see the tail end of a previous packet in the scenario you received two packets where the 2nd is shorter than the 1st.
if your incoming packet has no unique termination byte ie '\r'
you need to add
int recvbytes ;
recvbytes =new recv(...)
since recv returns the number of bytes received on the wire
Safe yes but wasteful. Also don't forget to not use the data returned in inbuffer beyond the actual received data from recvbuf.
Not unless inBuffer is at least as large as MAX_PACKET.
In addition to what Oezbek said, recv won't 0 terminate either unless it actually receives a 0.
It is necessary for you to set the right size of the buffer when you use memcpy because recv will put in recvbuf only as much data as is currently available and up to your specified size of MAX_PACKET. Not even if on the other end you're doing send(sock,sendbuf,MAX_PACKET,0); (and MAX_PACKET has the same value in both places).
The only scenario in which your code would make sense would be if you're using UDP (SOCK_DGRAM) and all your datagrams are of size MAX_PACKET.
an alternative approach
std::string inbuffer; // member variable to the class
.......
int ret = recv(sock,recvbuff,MAX_PACKET);
if(ret != 0)
{
inbuffer.insert(inbuffer.end(),recvbuff, recvbuff + ret);
...... // use the data.
}
this avoids using memcpy. Directly anyways, the STD lib should do the smart thing and call memcpy/ memmove for you :)

Calling a C function with the address to an empty std::vector

If I have a std::vector buffer that has room for 100 characters and I call a C function that will write a NULL terminated string like writestring(&buffer[0], buffer.size()) from what I've read that's ok if there is already data in buffer. But if the vector is empty the behavior is undefined. How do I get around that, can I write something to the buffer like "qwerty" and then call writestring() so that I know the behavior is always defined? What kind of storage do you guys use when calling C functions? I just read about .data but I don't know how common or portable that is.
Thanks
C++
std::vector<char> v;
v.resize(100);
writestring(&v[0], v.size());
C
void writestring(char*p, size_t len) {
strncpy(p, "Doofi", len);
}
if the vector is empty the behavior is undefined. How do I get around that?
By passing a non-empty buffer. Use the .resize() method to quickly fill the vector, or construct it to be the right size initially: std::vector<int> v(100);.
What kind of storage do you guys use when calling C functions?
std::vector is a fine choice for this application. To C, it looks just like an array or a malloc'd region. But, realize that C's pointer is only valid as long as the vector is neither reallocated or destroyed.
Resize the vector first:
buffer.resize(100);
writestring(buffer.data(), buffer.size()); // buffer.data() == &buffer[0]
Alternatively, construct the buffer with the desired size all in one go:
std::vector<char> buffer(100);
I think you should test that the buffer is not empty. If it is empty, don't call writestring.

How to make a copy of a pointer

I'm trying to copy a pointers data to another pointer, so that if I change one, the value in the other doesn't change.
I need this because I am coding a loop where I have two struct pointers, value, and lastValue. In each iteration of the loop I assign value's content to lastValue, and I fill value with new content. The problem is that because both are struct pointers, when I change value, lastValue changes too, and that's not the behavior I want. The code would be something like this (the structs are IplImages from OpenCV):
IplImage *value;
Iplimage *lastValue;
while(1)
{
lastValue=value;
value=cvQueryFrame( capture );//This fills the struct with new information
}
This would work if they where normal structs, but because they are pointers, both end up with the same value. Is there a way to get a copy of a pointer, with the same value, but different address?
value=cvQueryFrame( capture );
when I change value, lastValue changes too
No, it doesn't. The pointer value gets overwritten, as you desire. It is impossible for this line of code to affect lastValue.
but because they are pointers, both end up with the same value
No, it doesn't matter that they are pointers. Pointers are still objects in and of themselves.
However, cvQueryFrame returns a pointer to a buffer which you shall not modify or free as this is done for you:
Note that the image captured by the device is allocated/released by the capture function. There is no need to release it explicitly.
Though the documentation is a little unclear, it seems likely to me that the buffer is only valid until the next call to cvQueryFrame (which will then re-use the allocated memory). So even though lastValue can't and doesn't change, it happens to end up pointing to the new frame anyway.
To get around this, you can explicitly copy the object that lastValue points to:
lastValue = cvCloneImage(value);
Now you probably take on responsibility for freeing it (but again it's not entirely clear from my cursory glance at the documentation):
cvReleaseImage(&lastValue);
The function cvQueryFrame grabs a frame from camera or video file, decompresses and returns it. It returns the pointer to internal OpenCV buffer having the last grabbed frame. That should be the reason why you get the same value. If you want 2 frames, you should create a copy of the image.
IplImage * previousFrame, *currentFrame ;
CvCapture* video = cvCaptureFromAVI("video.avi");
currentFrame = cvQueryFrame( video );
// COPY IMAGE
previousFrame = cvCloneImage( currentFrame );
while(currentFrame = cvQueryFrame( video ))
{
//...
cvCopy( currentFrame , previousFrame);
}
//...
It looks like you're doing the right thing.
last_value = value; //copy pointer
but it isn't really what you want because it isn't the pointer you want to copy, it's the data inside. that's why the old pointer is updated along with the new pointer. I think what you need is a copy of the structure itself.
If the pointer points to some class you write, add a copy constructor method to it, then copy the value of the pointer like so:
last_value = new MyClass(*value); //construct object, copy from what value points to
//change value