AMD clEnqueueMapBuffer and Pinned memory - asynchronous

I currently use an AMD GPU.
/*device memory*/
pattern_obj = clCreateBuffer(context, CL_MEM_READ_ONLY, MAX_PATTERN_SIZE * MAX_PATTERN_NUM * sizeof(cl_char), NULL, &ret);
text_objA = clCreateBuffer(context, CL_MEM_READ_ONLY, fileLen * sizeof(char) / 2, NULL, &ret);
text_objB = clCreateBuffer(context, CL_MEM_READ_ONLY, fileLen * sizeof(char) / 2, NULL, &ret);
failure_obj = clCreateBuffer(context, CL_MEM_READ_ONLY, MAX_PATTERN_SIZE * MAX_PATTERN_NUM * sizeof(cl_int), NULL, &ret);
ret_objA = clCreateBuffer(context, CL_MEM_WRITE_ONLY, MAX_PATTERN_NUM * sizeof(cl_int), NULL, &ret);
ret_objB = clCreateBuffer(context, CL_MEM_WRITE_ONLY, MAX_PATTERN_NUM * sizeof(cl_int), NULL, &ret);
/*pinned memory*/
mPattern_obj = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, MAX_PATTERN_SIZE * MAX_PATTERN_NUM * sizeof(cl_char), NULL, &ret);
mText_obj = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, fileLen * sizeof(char), NULL, &ret);
mFailure_obj = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, MAX_PATTERN_SIZE * MAX_PATTERN_NUM * sizeof(cl_int), NULL, &ret);
mRet_obj = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, MAX_PATTERN_NUM * sizeof(cl_int) * 2, NULL, &ret);
/*mapped pointer for pinned memory*/
pattern = (cl_char *)clEnqueueMapBuffer(command_queue[0], mPattern_obj, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, MAX_PATTERN_SIZE * MAX_PATTERN_NUM * sizeof(cl_char), 0, NULL, NULL, &ret);
strings = (char *)clEnqueueMapBuffer(command_queue[0], mText_obj, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, fileLen * sizeof(char), 0, NULL, NULL, &ret);
failure = (cl_int *)clEnqueueMapBuffer(command_queue[0], mFailure_obj, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, MAX_PATTERN_SIZE * MAX_PATTERN_NUM * sizeof(cl_int), 0, NULL, NULL, &ret);
matched = (cl_int *)clEnqueueMapBuffer(command_queue[0], mRet_obj, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, MAX_PATTERN_NUM * sizeof(cl_int) * 2, 0, NULL, NULL, &ret);
/*Initialize the mapped pointer*/
ret = clEnqueueWriteBuffer(command_queue[0], pattern_obj, CL_FALSE, 0, MAX_PATTERN_SIZE * MAX_PATTERN_NUM * sizeof(cl_char), (void *)&pattern[0], 0, NULL, NULL);
ret = clEnqueueWriteBuffer(command_queue[0], text_objA, CL_FALSE, 0, halfSize, (void *)&strings[0], 0, NULL, NULL);
ret = clEnqueueWriteBuffer(command_queue[0], failure_obj, CL_FALSE, 0, MAX_PATTERN_SIZE * MAX_PATTERN_NUM * sizeof(cl_int), (void *)&failure[0], 0, NULL, NULL);
ret = clEnqueueNDRangeKernel(command_queue[0], kernel[0], 1, NULL, &global_item_size, &local_item_size, 0, NULL, &kmp_event);
clWaitForEvents(1, &kmp_event);
ret = clEnqueueWriteBuffer(command_queue[1], pattern_obj, CL_FALSE, 0, MAX_PATTERN_SIZE * MAX_PATTERN_NUM * sizeof(cl_char), (void *)&pattern[0], 0, NULL, NULL);
ret = clEnqueueWriteBuffer(command_queue[1], text_objB, CL_FALSE, 0, halfSize, (void *)&strings[halfOffset], 0, NULL, NULL);
ret = clEnqueueWriteBuffer(command_queue[1], failure_obj, CL_FALSE, 0, MAX_PATTERN_SIZE * MAX_PATTERN_NUM * sizeof(cl_int), (void *)&failure[0], 0, NULL, NULL);
ret = clEnqueueNDRangeKernel(command_queue[1], kernel[1], 1, NULL, &global_item_size, &local_item_size, 0, NULL, &kmp_event);
clWaitForEvents(1, &kmp_event);
ret = clEnqueueReadBuffer(command_queue[0], ret_objA, CL_FALSE, 0, MAX_PATTERN_NUM * sizeof(cl_int), (void *)&matched[0], 0, NULL, NULL);
ret = clEnqueueReadBuffer(command_queue[1], ret_objB, CL_FALSE, 0, MAX_PATTERN_NUM * sizeof(cl_int), (void *)&matched[MAX_PATTERN_NUM], 0, NULL, NULL);
This is my code for pinned memory.
I use MapBuffer and pinned memory for overlapping data transfer and execution.
I know my code is for Nvidia GPU and I think there is mismatch between Nvidia and AMD.
There is no example code for AMD GPU about overlapping transfers and computation.
So, I have no idea about what I have to do.
What should I change to make my code work in AMD GPU?
I divided text_obj in A & B because I want to transfer the text by splitting it into front-side and back-side.
eg)text: "ababcccc" text_objA=>abab and text_objB=>cccc

Yes, NVIDIA and AMD do pinned memory differently. NVIDIA has the strange requirement of two buffers (one device, one host) and it magically detects that the host pointer for the copy operations is "special" and that makes the copy faster. Note that in newer drivers you might just get similar performance when you map/unmap a device buffer. That's how AMD does it too (no need for two buffers). Read AMD's developer guidance; they have a whole section on memory transfers. Bottom line: Use the documentation for guidance but try everything and profile you devices to find what really works.

Related

Why doesn't arduino nano together with DS3231 make LED strip work as a clock? (I use FastLED library)

For some reason, my program doesn't make the LED clock work properly. I know that the problem is either in the breadboard or the program itself, since with the other program and different circuit everything works well. Everything is fine with the power supply and the connections between the peices of the LED strip are done correctly...
The program doesn’t light up the LEDs hence making it work as a clock; even though a separate program can light up the LEDs themselves, and the other program makes the clock print into the serial monitor the time
THINGS I HAVE ALREADY DONE:
I have already tried using serial prints,
Switching up the LEDs separately using another code (everything worked fine),
Setting up the DS3231 separately and using serial prints to make sure it is working (everything worked fine),
Making sure that the code does not take too much memory,
I have additionally tried different processors to run the code (there are no mistakes in the code itself and avrdude is not displayed)
Can you, please, help me?
These are the connections on the breadboard:
Connections on the breadboard
This is the clock itself:
connection of the parts of the LED strip
You can see the code here:
#include <DS3231.h>
DS3231 rtc(SDA, SCL);
#include <FastLED.h>
#include <Wire.h>
#include <DS1307RTC.h>
#define NUM_LEDS 172 // 6*7*4 +2+2 Number of LED controlled
#define COLOR_ORDER GRB // Define color order for your strip
#define DATA_PIN 12 // Data pin for led comunication D9
CRGB leds[NUM_LEDS]; // Define LEDs strip
const byte digits[10][42] PROGMEM =
{{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, // Digit 0
{0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1}, // Digit 1
{1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1}, // Digit 2
{0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1}, // Digit 3
{0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1}, // Digit 4
{0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0}, // Digit 5
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0}, // Digit 6
{0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1}, // Digit 7
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, // Digit 8
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0}}; // Digit 9
int last_digit = 0;
int ledColor = CRGB::White; // Color used (in hex)
void setup(){
//Make the clock work and set its initial parameters
Serial.begin(9600);
rtc.begin();
//rtc.setTime(19, 48, 50); // Set the time to 12:00:00 (24hr format)
//rtc.setDate(3, 6, 2017); // Set the date to the current date
Wire.begin();
FastLED.addLeds<WS2812B, DATA_PIN, RGB>(leds, NUM_LEDS);
LEDS.setBrightness(200); // Set initial brightness
}
int GetTime(){
tmElements_t Now;
RTC.read(Now);
//time_t Now = RTC.Now();// Getting the current Time and storing it into a DateTime object
int hour=Now.Hour;
//Serial.println(hour); //ia going to show the hour set to the clock by the other
//Serial.println("--");
int minute=Now.Minute;
//Serial.println(minute); //ia going to show the hour set to the clock by the other
//Serial.println("--");
return (hour*100+minute);
};
// Convert time to array needed for display
void TimeToArray(){
int Now = GetTime(); // Get time
//Serial.print("Time is: ");
//Serial.println(Now);
//delay(1000);
int cursor = 271; // last led number
//dots of the clock
leds[83]=ledColor;
leds[84]=ledColor;
leds[85]=ledColor;
leds[86]=ledColor;
for(int i=1;i<=4;i++){
int digit = Now % 10; // get the last digit of the time starting from the last digit of the minutes
if (i==1){
// Serial.print("the last digit of the minures is : ");Serial.print(digit);Serial.print(" ");
cursor = 129;
for(int k=0; k<=41;k++){
// Serial.print(digits[digit][k]);
if (digits[digit][k]== 1){leds[cursor]=ledColor;}
else if (digits[digit][k]==0){leds[cursor]=0x000000;};
cursor ++;
};
// Serial.println();
}
else if (i==2){
// Serial.print("The first digit of the minutes is : ");Serial.print(digit);Serial.print(" ");
cursor =87;
for(int k=0; k<=41;k++){
// Serial.print(digits[digit][k]);
if (digits[digit][k]== 1){leds[cursor]=ledColor;}
else if (digits[digit][k]==0){leds[cursor]=0x000000;};
cursor ++;
};
// Serial.println();
}
else if (i==3){
// Serial.print("The last digit of the hours is : ");Serial.print(digit);Serial.print(" ");
cursor =41;
for(int k=0; k<=41;k++){
// Serial.print(digits[digit][k]);
if (digits[digit][k]== 1){leds[cursor]=ledColor;}
else if (digits[digit][k]==0){leds[cursor]=0x000000;};
cursor ++;
};
// Serial.println();
}
else if (i==4){
// Serial.print("The first digit of the hours is : ");Serial.print(digit);Serial.print(" ");
cursor =0;
if(digit !=0){
for(int k=0; k<=41;k++){
// Serial.print(digits[digit][k]);
if (digits[digit][k]== 1){leds[cursor]=ledColor;}
else if (digits[digit][k]==0){leds[cursor]=0x000000;};
cursor ++;
};
}
}
Now /= 10;
};
};
void loop() // Main loop
{
GetTime(); // get the time
TimeToArray(); // Get leds array with required configuration
FastLED.show(); // Display leds array
delay(1000);
}
Thank you very much in advance!!
You defined the LED digit patterns in PROGMEM, but did no call pgm_read_byte_near() to access them. As a result, you were loading digit patterns from SRAM, which is zeroed at boot time.
I had to move things around a bit to make a bit more sense of what exactly was going on.
See comment below:
#include <DS3231.h>
#include <FastLED.h>
#include <Wire.h>
#include <DS1307RTC.h>
#define NUM_LEDS 172 // 6*7*4 +2+2 Number of LED controlled
#define COLOR_ORDER GRB // Define color order for your strip
#define DATA_PIN 12 // Data pin for led comunication D9
DS3231 rtc(SDA, SCL);
CRGB leds[NUM_LEDS]; // Define LEDs strip
const byte digits[10][42] PROGMEM =
{ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // Digit 0
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1}, // Digit 1
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // Digit 2
{0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // Digit 3
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1}, // Digit 4
{0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, // Digit 5
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, // Digit 6
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // Digit 7
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // Digit 8
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}
}; // Digit 9
constexpr int ledColor = CRGB::White; // Color used (in hex)
static void ShowTime() {
//dots of the clock
leds[83] = ledColor;
leds[84] = ledColor;
leds[85] = ledColor;
leds[86] = ledColor;
tmElements_t Now;
RTC.read(Now);
for (int i = 1; i <= 4; ++i) {
int digit = 0;
int cursor = 0;
switch (i)
{
case 1:
cursor = 0;
digit = Now.Hour / 10;
break;
case 2:
cursor = 41;
digit = Now.Hour % 10;
break;
case 3:
cursor = 87;
digit = Now.Minute / 10;
break;
case 4:
cursor = 129;
digit = Now.Minute % 10;
break;
}
// added pgm_read_byte_near() to access PROGMEM data
for (int k = 0; k < 42; ++k, ++cursor)
leds[cursor] = pgm_read_byte_near(&digits[digit][k]) ? ledColor : 0;
}
FastLED.show(); // Display leds array
}
void setup() {
//Make the clock work and set its initial parameters
Serial.begin(9600);
rtc.begin();
//rtc.setTime(19, 48, 50); // Set the time to 12:00:00 (24hr format)
//rtc.setDate(3, 6, 2017); // Set the date to the current date
Wire.begin();
FastLED.addLeds<WS2812B, DATA_PIN, RGB>(leds, NUM_LEDS);
LEDS.setBrightness(200); // Set initial brightness
}
void loop() // Main loop
{
ShowTime();
delay(1000);
}

How to establish connection with kafka server in Rust

I'm trying to establish connection with kafka server without third party libraries in Rust.
This is the description of kafka server TCP protocol
This is my code:
fn connect() -> Result<(), std::io::Error> {
let stream = TcpStream::connect("localhost:9092").expect("Could not connect");
let mut input_stream = stream.try_clone().unwrap();
input_stream.set_read_timeout(Some(Duration::new(5, 0)));
input_stream.set_write_timeout(Some(Duration::new(5, 0)));
/// HERE IS MY PROBLEM. I DON'T KNOW HOW TO ENCODE KAFKA MESSAGE
let mut data = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
/// api key 0, 0, 0, 0, 0, 0
/// request_api_version 0, 0, 0, 0, 0, 0
/// correlation_id 0, 0, 0, 0, 0, 0,
let mut buffer: Vec<u8> = Vec::with_capacity(1400);
buffer.extend_from_slice(&[0; 100]);
input_stream.write(&mut data)?;
match input_stream.read(&mut buffer) {
Ok(b) => {
println!("read ok - {:?}", String::from_utf8_lossy(&buffer));
}
Err(e) => println!("Error {}", e),
}
Ok(())
}
fn main() {
connect();
}
How to encode this kafka message to byte array ?
Variable data should be an array of bytes
Naive code for creating kafka message of next interface
request_api_key => INT16
request_api_version => INT16
correlation_id => INT32
const int16 = (prevBuffer: Buffer, value: number) => {
const newBuffer = Buffer.alloc(2)
newBuffer.writeInt16BE(value)
return Buffer.concat([prevBuffer, newBuffer]);
}
const int32 = (prevBuffer: Buffer, value: number) => {
const newBuffer = Buffer.alloc(4)
newBuffer.writeInt32BE(value)
return Buffer.concat([prevBuffer, newBuffer]);
}
const payload = int31(int16(int16(Buffer.alloc(0), 3), 0),1);
The code is shamelessly taken from kafkajs

Cube map/ frame buffer problems

So... I am trying to filter an environment map for a BRDF shader, as explained here: https://learnopengl.com/PBR/IBL/Specular-IBL. However, I can't get my filtered result to be properly stored (when loaded, I get a black texture full of artifacts.)
I figure it must have something to do with the frame buffer, since glCheckFramebufferStatus() keeps returning 0 on the LOD/sides loop, but I have spent a couple hours trying to understand why... and I can't see the problem. glGetError() returns 0, I made sure to generate the frame buffer/ render/ buffer before the loop starts, and at that point everything seemed complete. The rest of the program runs fine, and there were no errors compiling the shader I am using.
I am quite new to openGL, is there something obvious I am missing? I am assuming the problem must be in this section... but does it look like it should work? Could it be something I did wrong elsewhere?
This is the code:
if (cubeMapGenerated == false){
//Frame Buffer:
glGenFramebuffers(1, &frameBuffer);
glGenRenderbuffers(1, &renderBuffer);
glGenTextures(1, &genCubeMap);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glBindTexture(GL_TEXTURE_CUBE_MAP, genCubeMap);
for (unsigned int i = 0; i < 6; ++i)
{glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA16F, 128, 128, 0, GL_RGB, GL_FLOAT, nullptr);}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); //params
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glGenerateMipmap(GL_TEXTURE_CUBE_MAP); //generate mipmaps
glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width_, height_);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderBuffer);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "Framebuffer is not complete at gen. Staus: " << glCheckFramebufferStatus(GL_FRAMEBUFFER) << std::endl;
GLuint projection_location, view_location, model_location, normal_matrix_location,
specular_map_location, roughness_location;
cubeMapGen_program_->bind(); //bind irradiance sahder
projection_location = cubeMapGen_program_->uniformLocation("projection");
view_location = cubeMapGen_program_->uniformLocation("view");
model_location = cubeMapGen_program_->uniformLocation("model");
normal_matrix_location = cubeMapGen_program_->uniformLocation("normal_matrix");
specular_map_location = cubeMapGen_program_->uniformLocation("specular_map");
roughness_location =brdf_program_->uniformLocation("roughness");
glUniformMatrix4fv(projection_location, 1, GL_FALSE, e_captureProjection.data());
glUniformMatrix4fv(model_location, 1, GL_FALSE, model.data());
glUniformMatrix3fv(normal_matrix_location, 1, GL_FALSE, normal.data());
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, specular_map_);
glUniform1i(specular_map_location, 0);
for (unsigned int mip = 0; mip < maxMipLevels; ++mip){//render each mip
// resize framebuffer according to mip-level size.
unsigned int mipWidth = 128 * std::pow(0.5, mip);
unsigned int mipHeight = 128 * std::pow(0.5, mip);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, mipWidth, mipHeight);
std::cout << "width: " << mipWidth << " height: " << mipHeight << std::endl;
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderBuffer);
glViewport(0, 0, mipWidth, mipHeight);
float mproughness = (float) mip / (float)(maxMipLevels - 1);
glUniform1f (roughness_location, mproughness);
for (unsigned int i = 0; i < 6; ++i)//render each side
{
glUniformMatrix4fv(view_location, 1, GL_FALSE, e_captureViews[i].data());
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, genCubeMap, mip);
if(i == 0 && glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete! Map: " << mip << std::endl;}
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glVertex3f(2, -2, -2); glVertex3f(2, -2, 2); glVertex3f(2, 2, 2); //Right
glVertex3f(2, -2, -2); glVertex3f(2, 2, 2); glVertex3f(2, 2, -2);
glVertex3f(-2, -2, -2); glVertex3f(-2, 2, 2); glVertex3f(-2, -2, 2); //Left
glVertex3f(-2, -2, -2); glVertex3f(-2, 2, -2); glVertex3f(-2, 2, 2);
glVertex3f(-2, -2, 2); glVertex3f(-2, 2, 2); glVertex3f(2, 2, 2); //Front
glVertex3f(-2, -2, 2); glVertex3f(2, 2, 2); glVertex3f(2, -2, 2);
glVertex3f(-2, -2, -2); glVertex3f(2, 2, -2); glVertex3f(-2, 2, -2); //Back
glVertex3f(-2, -2, -2); glVertex3f(2, -2, -2); glVertex3f(2, 2, -2);
glVertex3f(-2, 2, -2); glVertex3f(2, 2, -2); glVertex3f(2, 2, 2); //Top
glVertex3f(-2, 2, -2); glVertex3f(2, 2, 2); glVertex3f(-2, 2, 2);
glVertex3f(-2, -2, -2); glVertex3f(2, -2, 2); glVertex3f(2, -2, -2); //Bottom
glVertex3f(-2, -2, -2); glVertex3f(-2, -2, 2); glVertex3f(2, -2, 2);
}
//std::cout << glGetError() << ", " << glCheckFramebufferStatus(GL_FRAMEBUFFER) << std::endl;
}
std::cout<<"New pre filtered map generated"<<std::endl;
cubeMapGenerated = true;
}//cubemapgen
glEnd();
I recommend to read about Vertex Specification and to use the state of the art way of Vertex Array Objects for drawing.
But, if you draw the objects in to deprecated Fixed Function Pipeline style, then geometric objects are drawn by enclosing a series of vertex coordinates between glBegin/glEnd pairs.
You have to finish the drawing sequence by glEnd, before you can change or manipulate the framebuffer.
Move the glEnd instruction in the inner loop and your code should work
for (unsigned int mip = 0; mip < maxMipLevels; ++mip)
{
.....
for (unsigned int i = 0; i < 6; ++i)//render each side
{
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, genCubeMap, mip);
glBegin(GL_TRIANGLES);
glVertex3f(2, -2, -2); glVertex3f(2, -2, 2); glVertex3f(2, 2, 2);
.....
glVertex3f(-2, -2, -2); glVertex3f(-2, -2, 2); glVertex3f(2, -2, 2);
glEnd(); // <---- "end" the draw sequence
}
}
See OpenGL 3.0 API Specification; 2.6.3 GL Commands within Begin/End; page 24
or OpenGL 4.6 API Compatibility Profile Specification; 10.7.5 Commands Allowed Between Begin and End; page 433:
The only GL commands that are allowed within any Begin/End pairs are the commands for specifying vertex coordinates, vertex colors, normal coordinates, texture coordinates, generic vertex attributes, and fog coordinates ...

QPaint onto QGLFramebufferObject texture?

I am trying to learn how to use QPainter with a QGLFramebufferObject. When I try to display the texture in a QGLWidget, it is not visible. (complete code below)
The end goal is to use QPainter to draw text onto textures and then alpha blend the texture overtop of the 2D line geometry.
texture.pro
QT += core gui widgets opengl
TARGET = test
TEMPLATE = app
SOURCES = main.cpp
HEADERS = main.h
main.h
#include <QGLWidget>
#include <QGLFunctions>
class glview : public QGLWidget, protected QGLFunctions
{
Q_OBJECT
public:
explicit glview(QWidget *parent = 0);
~glview();
QSize sizeHint() const;
protected:
void initializeGL();
void resizeGL(int w, int h);
void paintGL();
private:
quint32 vbo_id[2], texture_id;
};
main.cpp
#include <QApplication>
#include <QGLFramebufferObject>
#include <QPainter>
#include "main.h"
struct vrtx {
GLint x;
GLint y;
GLubyte r;
GLubyte g;
GLubyte b;
}__attribute__((packed)) line_geo[] = {
// x, y, r, g, b
{1, 1, 255, 0, 0},
{1, 2, 0, 255, 0},
{1, 2, 0, 255, 0},
{2, 2, 255, 0, 0},
{2, 2, 255, 0, 0},
{2, 1, 0, 255, 0},
{2, 1, 0, 255, 0},
{1, 1, 255, 0, 0},
};
struct txtr_vrtx {
GLint x;
GLint y;
GLint tx;
GLint ty;
}__attribute__((packed)) txtr_geo[] = {
// x, y, tx,ty
{3, 1, 0, 0},
{3, 2, 0, 1},
{4, 2, 1, 1},
{4, 1, 1, 0},
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
glview widget;
widget.show();
return app.exec();
}
glview::glview(QWidget *parent) : QGLWidget(parent)
{
}
glview::~glview()
{
}
QSize glview::sizeHint() const
{
return QSize(500, 300);
}
void glview::initializeGL()
{
initializeGLFunctions();
qglClearColor(Qt::white);
glGenBuffers(2, vbo_id);
glBindBuffer(GL_ARRAY_BUFFER, vbo_id[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(line_geo), line_geo, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vbo_id[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(txtr_geo), txtr_geo, GL_STATIC_DRAW);
QGLFramebufferObject fbo(100, 100, QGLFramebufferObject::CombinedDepthStencil/*GL_TEXTURE_2D*/);
fbo.bind();
texture_id = fbo.texture();
QPainter painter(&fbo);
painter.fillRect(0, 0, 100, 100, Qt::blue);
painter.end();
fbo.release();
}
void glview::resizeGL(int w, int h)
{
glViewport(0, 0, w, h);
}
void glview::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glOrtho(0, 5, 0, 3, -1, 1);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, vbo_id[0]);
glVertexPointer(2, GL_INT, sizeof(struct vrtx), 0);
glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(struct vrtx), ((char*)NULL + 8));
glDrawArrays(GL_LINES, 0, sizeof(line_geo) / sizeof(struct vrtx));
//glColor4ub(0, 0, 255, 255);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
glDisableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, vbo_id[1]);
glBindTexture(GL_TEXTURE_2D, texture_id);
glVertexPointer(2, GL_INT, sizeof(struct txtr_vrtx), 0);
glTexCoordPointer(2, GL_INT, sizeof(struct txtr_vrtx), ((char*)NULL + 8));
glDrawArrays(GL_QUADS, 0, 4);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisable(GL_TEXTURE_2D);
//glDisable(GL_BLEND);
glFlush();
}
The QGLFramebufferObject instance is destroyed when leaving initializeGL(). This results in deleting the texture too. You need to keep the QGLFramebufferObject alive until the texture is no longer needed.
Here is the corrected code. Also with alpha bending.
main.h
#include <QGLWidget>
#include <QGLFunctions>
#include <QGLFramebufferObject>
#include <QFont>
class glview : public QGLWidget, protected QGLFunctions
{
Q_OBJECT
public:
explicit glview(QWidget *parent = 0);
~glview();
QSize sizeHint() const;
protected:
void initializeGL();
void resizeGL(int w, int h);
void paintGL();
private:
QGLFramebufferObject *fbo;
QFont font;
quint32 vbo_id[2], texture_id;
};
main.cpp
#include <QApplication>
#include <QPainter>
#include "main.h"
struct vrtx {
GLint x;
GLint y;
GLubyte r;
GLubyte g;
GLubyte b;
}__attribute__((packed)) line_geo[] = {
// x, y, r, g, b
{1, 1, 255, 0, 0},
{1, 2, 0, 255, 0},
{1, 2, 0, 255, 0},
{2, 2, 255, 0, 0},
{2, 2, 255, 0, 0},
{2, 1, 0, 255, 0},
{2, 1, 0, 255, 0},
{1, 1, 255, 0, 0},
};
struct txtr_vrtx {
GLint x;
GLint y;
GLint tx;
GLint ty;
}__attribute__((packed)) txtr_geo[] = {
// x, y, tx,ty
{3, 1, 0, 0},
{3, 2, 0, 1},
{4, 2, 1, 1},
{4, 1, 1, 0},
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
glview widget;
widget.show();
return app.exec();
}
glview::glview(QWidget *parent) : QGLWidget(parent)
{
font.setFamily("Helvetica");
}
glview::~glview()
{
delete fbo;
}
QSize glview::sizeHint() const
{
return QSize(500, 300);
}
void glview::initializeGL()
{
initializeGLFunctions();
qglClearColor(Qt::white);
glGenBuffers(2, vbo_id);
glBindBuffer(GL_ARRAY_BUFFER, vbo_id[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(line_geo), line_geo, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vbo_id[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(txtr_geo), txtr_geo, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0); // must unbind for QPainter
fbo = new QGLFramebufferObject(100, 100, GL_TEXTURE_2D);
fbo->bind();
texture_id = fbo->texture();
QPainter painter(fbo);
painter.setPen(Qt::blue);
font.setPointSize(20);
painter.setFont(font);
painter.drawText(0, 60, "FBO");
painter.end();
fbo->release();
}
void glview::resizeGL(int w, int h)
{
glViewport(0, 0, w, h);
}
void glview::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glOrtho(0, 5, 0, 3, -1, 1);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, vbo_id[0]);
glVertexPointer(2, GL_INT, sizeof(struct vrtx), 0);
glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(struct vrtx), ((char*)NULL + 8));
glDrawArrays(GL_LINES, 0, sizeof(line_geo) / sizeof(struct vrtx));
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glDisableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, vbo_id[1]);
glBindTexture(GL_TEXTURE_2D, texture_id);
glVertexPointer(2, GL_INT, sizeof(struct txtr_vrtx), 0);
glTexCoordPointer(2, GL_INT, sizeof(struct txtr_vrtx), ((char*)NULL + 8));
glDrawArrays(GL_QUADS, 0, 4);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glFlush();
}

Is it possible to store Arduino data for sketch in plain text onboard Arduino?

I created this arduino sketch and it works fine, what happens is you hold a button down and a pattern of lights plays. You can see my patterns at the bottom. Each button has its own pattern to play when its held.
So this works fine, but I have a question. I'm uneasy about this because I feel that its better practice to keep my patterns outside the program. I want to know, can I store the patterns in a text file that also gets loaded onto the arduino? Is there anyway to put the patterns in a text file, and just read them all onboard the arduino?
const int buttonPin[5] = {8,9,10,11,12};
const int LEDPin[5] = {2,3,4,5,6};
int timer =0;
int millisBegin=0;
boolean reset=true;
boolean run[5] = {false,false,false,false,false};
boolean buttonOn = false;
void setup(){
Serial.begin(57600);
pinMode(buttonPin[0], INPUT);
pinMode(buttonPin[1], INPUT);
pinMode(buttonPin[2], INPUT);
pinMode(buttonPin[3], INPUT);
pinMode(buttonPin[4], INPUT);
pinMode(LEDPin[0], OUTPUT);
pinMode(LEDPin[1], OUTPUT);
pinMode(LEDPin[2], OUTPUT);
pinMode(LEDPin[3], OUTPUT);
pinMode(LEDPin[4], OUTPUT);
}
void loop()
{
for (int x=0; x<6; x++)
{
if (digitalRead(buttonPin[x]) == HIGH)
{
run[x] = true;
}
}
if (run[0] == true)
{
buttonOn = pattern1();
if (buttonOn == false)
{
run[0] = false;
}
}
if (run[1] == true)
{
buttonOn = pattern2();
if (buttonOn == false)
{
run[1] = false;
}
}
if (run[2] == true)
{
buttonOn = pattern3();
if (buttonOn == false)
{
run[2] = false;
}
}
if (run[3] == true)
{
buttonOn = pattern4();
if (buttonOn == false)
{
run[3] = false;
}
}
if (run[4] == true)
{
buttonOn = pattern5();
if (buttonOn == false)
{
run[4] = false;
}
}
}
boolean light(int button, int pattern[][6])
{
while (digitalRead(buttonPin[button])==LOW)
{
reset = true;
for (int x=0; x<5; x++){
digitalWrite(LEDPin[x],LOW);
}
buttonOn = false;
return buttonOn;
}
while (digitalRead(buttonPin[button])==HIGH)
{
if (reset == true)
{
millisBegin = millis();
reset = false;
Serial.println("reset!");
}
timer = millis() - millisBegin;
for (int x=0; x<10; x++) //Pattern amount
{
for (int y=0; y<5; y++) //Lights
{
//if else runs pattern with correct time code
if (timer>pattern[x][5]&&timer<pattern[x+1][5])
{
if (pattern[x][y]==1)
{
digitalWrite(LEDPin[y], HIGH);
}
else
{
digitalWrite(LEDPin[y], LOW);
}
}
}
}
Serial.println(timer);
if (timer > pattern[10][5]){
reset = true;
Serial.println("Over timer!");
}
}
}
boolean pattern1()
{
int pattern[11][6] = {
{0, 0, 0, 0, 0, 100}, //0
{1, 1, 0, 1, 1, 1200}, //1
{0, 0, 1, 0, 0, 2200}, //2
{1, 1, 0, 1, 1, 3200}, //3
{0, 0, 0, 0, 0, 4200}, //4
{1, 1, 1, 1, 1, 5000}, //5
{0, 0, 1, 0, 0, 6000}, //6
{1, 0, 0, 0, 0, 7000}, //7
{0, 1, 0, 1, 1, 8000}, //8arduin
{0, 0, 1, 0, 1, 9000}, //9
{0, 0, 0, 0, 0, 10000}}; //
buttonOn = light(0,pattern);
return buttonOn;
}
boolean pattern2()
{
int pattern[11][6] = {
{1, 0, 1, 0, 0, 100}, //0
{0, 1, 1, 0, 1, 180}, //1
{1, 0, 0, 0, 0, 230}, //2
{0, 1, 0, 1, 1, 340}, //3
{1, 0, 0, 1, 0, 450}, //4
{0, 0, 1, 1, 1, 500}, //5
{0, 0, 1, 0, 0, 550}, //6
{1, 0, 0, 0, 0, 600}, //7
{0, 1, 0, 1, 1, 680}, //8
{0, 0, 1, 0, 1, 800}, //9
{0, 0, 0, 0, 0, 900}}; //
buttonOn = light(1,pattern);
return buttonOn;
}
boolean pattern3()
{
int pattern[11][6] = {
{1, 1, 1, 1, 1, 100}, //0
{0, 0, 0, 0, 0, 180}, //1
{1, 1, 1, 1, 1, 230}, //2
{0, 0, 0, 0, 0, 340}, //3
{1, 1, 1, 1, 1, 450}, //4
{0, 0, 0, 0, 0, 500}, //5
{1, 1, 1, 1, 1, 550}, //6
{0, 0, 0, 0, 0, 600}, //7
{1, 1, 1, 1, 1, 680}, //8
{0, 0, 0, 0, 0, 800}, //9
{0, 0, 0, 0, 0, 810}}; //
buttonOn = light(2,pattern);
return buttonOn;
}
boolean pattern4()
{
int pattern[11][6] = {
{0, 0, 0, 0, 0, 100}, //0
{0, 0, 0, 0, 1, 500}, //1
{0, 0, 0, 1, 1, 800}, //2
{0, 0, 1, 1, 1, 900}, //3
{1, 1, 1, 1, 1, 1000}, //4
{1, 1, 1, 1, 1, 1100}, //5
{1, 1, 1, 1, 0, 1200}, //6
{1, 1, 1, 0, 0, 1300}, //7
{1, 1, 0, 0, 0, 1400}, //8
{1, 0, 0, 0, 0, 1500}, //9
{0, 0, 0, 0, 0, 1600}}; //
buttonOn = light(3,pattern);
return buttonOn;
}
boolean pattern5()
{
int pattern[11][6] = {
{0, 1, 0, 1, 0, 100}, //0
{1, 0, 1, 0, 1, 500}, //1
{0, 1, 0, 1, 0, 800}, //2
{1, 0, 1, 0, 1, 900}, //3
{0, 1, 0, 1, 0, 1000}, //4
{1, 0, 1, 0, 1, 1100}, //5
{0, 1, 0, 1, 0, 1200}, //6
{1, 0, 1, 0, 1, 1300}, //7
{0, 1, 0, 1, 0, 1400}, //8
{1, 0, 1, 0, 1, 1500}, //9
{0, 1, 0, 1, 0, 1600}}; //
buttonOn = light(4,pattern);
return buttonOn;
}
The Arduino boards do not have external storage devices where files can be stored. Of course there are shields with a SD card slot which you can add to your device. This would be overkill however.
But the Arduino has a builtin EEPROM which you can read/write using the EEPROM library.
My suggestion would be:
Extend your program to read and write to USB via Serial. You can then invent some simple text-based commands which allow you to send new patterns to the Arduino.
When the Arduino receives new patterns, it stores them in the EEPROM.
In normal operation mode the Arduino reads the patterns from EEPROM and displays them.
This way you can use your Arduino "standalone" and program it ad-hoc using any computer.

Resources