Q: OpenGL imageAtomicCompSwap mutex, endless loop - opengl

This shader will run into endless loop because of imageAtomicCompSwap mutex. The code is learn form OpenGL Programming Guide(Eighth Edition)
void takeLock(ivec2 vPos)
{
uint iLockAvaiable;
do
{
iLockAvaiable = imageAtomicCompSwap(uLockImage, vPos, uint(0), uint(1));
}while(iLockAvaiable != uint(0));
}
void releaseLock(ivec2 vPos)
{
//imageStore(uLockImage, vPos, uint(0));
uint uiValue = imageAtomicExchange(uLockImage, vPos, uint(0));
}
void main()
{
takeLock(ivec2(f2TexCoord));
float BaseDepth = imageLoad(uDepthTest, ivec2(f2TexCoord)).x;
if(BaseDepth == 0.0 || refScreenCoord.z < BaseDepth)
imageStore(uDepthTest, ivec2(f2TexCoord), vec4(refScreenCoord.z));
releaseLock(ivec2(f2TexCoord));
}

Related

C# Else confusion

so i keep gettin an error on (else) and im not to sure what i did wrong, i cant seem to find the problem, please help, im pretty new to coding so heres the entire code i have so far
{
public float speed;
private Rigidbody2D myRigidbody;
private Vector3 change;
private Animator animator;
// Start is called before the first frame update
void Start()
{
animator = GetComponent<Animator>();
myRigidbody = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
change = Vector3.zero;
change.x = Input.GetAxisRaw("Horizontal") * Time.deltaTime * speed;
change.y = Input.GetAxisRaw("Vertical") * Time.deltaTime * speed;
if (change != Vector3.zero)
transform.Translate(new Vector3(change.x, change.y));
MoveCharacter();
UpdateAnimationAndMove();
}
void UpdateAnimationAndMove()
{
{
animator.SetFloat("moveX", change.x);
animator.SetFloat("moveY", change.y);
animator.SetBool("moving", true);
} else {
animator.SetBool("moving", false);
}
}
void MoveCharacter()
{
myRigidbody.MovePosition(transform.position + change.normalized * speed * Time.deltaTime);
}
}
You can't use else, without a corresponding if before it.
if(condition)
{
// IF condition is true, this gets executed
}
else
{
// ELSE this gets executed
}

Why am I getting a race condition?

I'm trying to combine multiple CGAL meshes into one single geometry.
I have the following sequential code that works perfectly fine:
while (m_toCombine.size() > 1) {
auto mesh1 = m_toCombine.front();
m_toCombine.pop_front();
auto mesh2 = m_toCombine.front();
m_toCombine.pop_front();
bool result = CGAL::Polygon_mesh_processing::corefine_and_compute_union(mesh1, mesh2, mesh2);
m_toCombine.push_back(mesh2);
}
Where m_toCombine is a std::list<Triangle_mesh_exact>.
Triangle_mesh_exact is a type of CGAL mesh (triangulated polyhedron geometry). But I don't think it's really relevant to the problem.
Unfortunately, this process is way too slow for my intended application, so I decided to use the "divide to conquer" concept and combine meshes in a parallel fashion:
class Combiner
{
public:
Combiner(const std::list<Triangle_mesh_exact>& toCombine) :
m_toCombine(toCombine) {};
~Combiner() {};
Triangle_mesh_exact combineMeshes();
void combineMeshes2();
private:
std::mutex m_listMutex, m_threadListMutex;
std::mutex m_eventLock;
std::list<MiniThread> m_threads;
std::list<Triangle_mesh_exact> m_toCombine;
std::condition_variable m_eventSignal;
std::atomic<bool> m_done = false;
//void poll(int threadListIndex);
};
Triangle_mesh_exact Combiner::combineMeshes()
{
std::unique_lock<std::mutex> uniqueLock(m_eventLock, std::defer_lock);
int runningCount = 0, finishedCount = 0;
int toCombineCount = m_toCombine.size();
bool stillRunning = false;
bool stillCombining = true;
while (stillCombining || stillRunning) {
uniqueLock.lock();
//std::lock_guard<std::mutex> lock(m_listMutex);
m_listMutex.lock();
Triangle_mesh_exact mesh1 = std::move(m_toCombine.front());
m_toCombine.pop_front();
toCombineCount--;
Triangle_mesh_exact mesh2 = std::move(m_toCombine.front());
m_toCombine.pop_front();
toCombineCount--;
m_listMutex.unlock();
runningCount++;
auto thread = new std::thread([&, this, mesh1, mesh2]() mutable {
//m_listMutex.lock();
CGAL::Polygon_mesh_processing::corefine_and_compute_union(mesh1, mesh2, mesh2);
std::lock_guard<std::mutex> lock(m_listMutex);
m_toCombine.push_back(mesh2);
toCombineCount++;
finishedCount++;
m_eventSignal.notify_one();
//m_listMutex.unlock();
});
thread->detach();
while (toCombineCount < 2 && runningCount != finishedCount) {
m_eventSignal.wait(uniqueLock);
}
stillRunning = runningCount != finishedCount;
stillCombining = toCombineCount >= 2;
uniqueLock.unlock();
}
return m_toCombine.front();
}
Unfortunately, despite being extra careful, I'm getting crashes of memory access violation or errors related to either mesh1 or mesh2 destructors.
Am I missing something?
Instead complicating things check capability of standard library:
std::reduce - cppreference.com
Triangle_mesh_exact combine(Triangle_mesh_exact& a, Triangle_mesh_exact& b)
{
auto success = CGAL::Polygon_mesh_processing::corefine_and_compute_union(a, b, b);
if (!success) throw my_combine_exception{};
return b;
}
Triangle_mesh_exact combineAll()
{
if (m_toCombine.size() == 1) return m_toCombine.front();
if (m_toCombine.empty()) throw std::invalid_argument("");
return std::reduce(std::execution::par,
m_toCombine.begin() + 1, m_toCombine.end(),
m_toCombine.front(), combine);
}

Waiting-time of thread switches systematicly between 0 and 30000 microseconds for the same task

I'm writing a little Console-Game-Engine and for better performance I wanted 2 threads (or more but 2 for this task) using two buffers. One thread is drawing the next frame in the first buffer while the other thread is reading the current frame from the second buffer. Then the buffers get swapped.
Of cause I can only swap them if both threads finished their task and the drawing/writing thread happened to be the one waiting. But the time it is waiting systematicly switches more or less between two values, here a few of the messurements I made (in microseconds):
0, 36968, 0, 36260, 0, 35762, 0, 38069, 0, 36584, 0, 36503
It's pretty obvious that this is not a coincidence but I wasn't able to figure out what the problem was as this is the first time I'm using threads.
Here the code, ask for more if you need it, I think it's too much to post it all:
header-file (Manager currently only adds a pointer to my WinAppBase-class):
class SwapChain : Manager
{
WORD *pScreenBuffer1, *pScreenBuffer2, *pWritePtr, *pReadPtr, *pTemp;
bool isRunning, writingFinished, readingFinished, initialized;
std::mutex lockWriting, lockReading;
std::condition_variable cvWriting, cvReading;
DWORD charsWritten;
COORD startPosition;
int screenBufferWidth;
// THREADS (USES NORMAL THREAD AS SECOND THREAD)
void ReadingThread();
// THIS FUNCTION IS ONLY FOR INTERN USE
void SwapBuffers();
public:
// USE THESE TO CONTROL WHEN THE BUFFERS GET SWAPPED
void BeginDraw();
void EndDraw();
// PUT PIXEL | INLINED FOR BETTER PERFORMANCE
inline void PutPixel(short xPos, short yPos, WORD color)
{
this->pWritePtr[(xPos * 2) + yPos * screenBufferWidth] = color;
this->pWritePtr[(xPos * 2) + yPos * screenBufferWidth + 1] = color;
}
// GENERAL CONTROL OVER SWAP CHAIN
void Initialize();
void Run();
void Stop();
// CONSTRUCTORS
SwapChain(WinAppBase * pAppBase);
virtual ~SwapChain();
};
Cpp-file
SwapChain::SwapChain(WinAppBase * pAppBase)
:
Manager(pAppBase)
{
this->isRunning = false;
this->initialized = false;
this->pReadPtr = NULL;
this->pScreenBuffer1 = NULL;
this->pScreenBuffer2 = NULL;
this->pWritePtr = NULL;
this->pTemp = NULL;
this->charsWritten = 0;
this->startPosition = { 0, 0 };
this->readingFinished = 0;
this->writingFinished = 0;
this->screenBufferWidth = this->pAppBase->screenBufferInfo.dwSize.X;
}
SwapChain::~SwapChain()
{
this->Stop();
if (_CrtIsValidHeapPointer(pReadPtr))
delete[] pReadPtr;
if (_CrtIsValidHeapPointer(pScreenBuffer1))
delete[] pScreenBuffer1;
if (_CrtIsValidHeapPointer(pScreenBuffer2))
delete[] pScreenBuffer2;
if (_CrtIsValidHeapPointer(pWritePtr))
delete[] pWritePtr;
}
void SwapChain::ReadingThread()
{
while (this->isRunning)
{
this->readingFinished = 0;
WriteConsoleOutputAttribute(
this->pAppBase->consoleCursor,
this->pReadPtr,
this->pAppBase->screenBufferSize,
this->startPosition,
&this->charsWritten
);
memset(this->pReadPtr, 0, this->pAppBase->screenBufferSize);
this->readingFinished = true;
this->cvWriting.notify_all();
if (!this->writingFinished)
{
std::unique_lock<std::mutex> lock(this->lockReading);
this->cvReading.wait(lock);
}
}
}
void SwapChain::SwapBuffers()
{
this->pTemp = this->pReadPtr;
this->pReadPtr = this->pWritePtr;
this->pWritePtr = this->pTemp;
this->pTemp = NULL;
}
void SwapChain::BeginDraw()
{
this->writingFinished = false;
}
void SwapChain::EndDraw()
{
TimePoint tpx1, tpx2;
tpx1 = Clock::now();
if (!this->readingFinished)
{
std::unique_lock<std::mutex> lock2(this->lockWriting);
this->cvWriting.wait(lock2);
}
tpx2 = Clock::now();
POST_DEBUG_MESSAGE(std::chrono::duration_cast<std::chrono::microseconds>(tpx2 - tpx1).count(), "EndDraw wating time");
SwapBuffers();
this->writingFinished = true;
this->cvReading.notify_all();
}
void SwapChain::Initialize()
{
if (this->initialized)
{
POST_DEBUG_MESSAGE(Result::CUSTOM, "multiple initialization");
return;
}
this->pScreenBuffer1 = (WORD *)malloc(sizeof(WORD) * this->pAppBase->screenBufferSize);
this->pScreenBuffer2 = (WORD *)malloc(sizeof(WORD) * this->pAppBase->screenBufferSize);
for (int i = 0; i < this->pAppBase->screenBufferSize; i++)
{
this->pScreenBuffer1[i] = 0x0000;
}
for (int i = 0; i < this->pAppBase->screenBufferSize; i++)
{
this->pScreenBuffer2[i] = 0x0000;
}
this->pWritePtr = pScreenBuffer1;
this->pReadPtr = pScreenBuffer2;
this->initialized = true;
}
void SwapChain::Run()
{
this->isRunning = true;
std::thread t1(&SwapChain::ReadingThread, this);
t1.detach();
}
void SwapChain::Stop()
{
this->isRunning = false;
}
This is where I run the SwapChain-class from:
void Application::Run()
{
this->engine.graphicsmanager.swapChain.Initialize();
Sprite<16, 16> sprite(&this->engine);
sprite.LoadSprite("engine/resources/TestData.xml", "root.test.sprites.baum");
this->engine.graphicsmanager.swapChain.Run();
int a, b, c;
for (int i = 0; i < 60; i++)
{
this->engine.graphicsmanager.swapChain.BeginDraw();
for (c = 0; c < 20; c++)
{
for (a = 0; a < 19; a++)
{
for (b = 0; b < 10; b++)
{
sprite.Print(a * 16, b * 16);
}
}
}
this->engine.graphicsmanager.swapChain.EndDraw();
}
this->engine.graphicsmanager.swapChain.Stop();
_getch();
}
The for-loops above simply draw the sprite 20 times from the top-left corner to the bottom-right corner of the console - the buffers don't get swapped during that, and that again for a total of 60 times (so the buffers get swapped 60 times).
sprite.Print uses the PutPixel function of SwapChain.
Here the WinAppBase (which consits more or less of global-like variables)
class WinAppBase
{
public:
// SCREENBUFFER
CONSOLE_SCREEN_BUFFER_INFO screenBufferInfo;
long screenBufferSize;
// CONSOLE
DWORD consoleMode;
HWND consoleWindow;
HANDLE consoleCursor;
HANDLE consoleInputHandle;
HANDLE consoleHandle;
CONSOLE_CURSOR_INFO consoleCursorInfo;
RECT consoleRect;
COORD consoleSize;
// FONT
CONSOLE_FONT_INFOEX fontInfo;
// MEMORY
char * pUserAccessDataPath;
public:
void reload();
WinAppBase();
virtual ~WinAppBase();
};
There are no errors, simply this alternating waitng time.
Maybe you'd like to start by looking if I did the synchronisation of the threads correctly? I'm not exactly sure how to use a mutex or condition-variables so it might comes from that.
Apart from that it is working fine, the sprites are shown as they should.
The clock you are using may have limited resolution. Here is a random example of a clock provided by Microsoft with 15 ms (15000 microsecond) resolution: Why are .NET timers limited to 15 ms resolution?
If one thread is often waiting for the other, it is entirely possible (assuming the above clock resolution) that it sometimes waits two clockticks and sometimes none. Maybe your clock only has 30 ms resolution. We really can't tell from the code. Do you get more precise measurements elsewhere with this clock?
There are also other systems in play such as the OS scheduler or whatever controls your std::threads. That one is (hopefully) much more granular, but how all these interactions play out doesn't have to be obvious or intuitive.

Unreal engine c++ write delegate OnScreenshotCaptured

I am new to C++. I've wrote code in C# and PHP.Since I am using Unreal engine I am trying to learn C++. For my project I need to make a screenshot in-game and show it immediately so I want to get it as a texture.
I made a blueprint node which calls this function i've made:
void UMyBlueprintFunctionLibrary::TakeScreenshot()
{
FScreenshotRequest::RequestScreenshot(true);
if (GEngine)
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Red, "Tried to take screenshot");
}
When I hover my mouse above RequestScreenshot I see the following pop-up:
"Screenshot can be read from memory by subscribing to the viewsport OnScreenshopCaptured delegate"
So that is what I try to do but I have no idea how I looked up this:
https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/Engine/UGameViewportClient/OnScreenshotCaptured/
Can someone tell me how to implement this and how you see/know how to implement it?
I have an alternative, no delegate, but FRenderTarget::ReadPixel() to some buffer you allocated, by implementing your own UGameViewportClient (inherit it), and overriding Draw() function.
I'll show the essential codes, but not complete.
void UMyGameViewportClient::Draw(FViewport* Viewport, FCanvas* SceneCanvas)
{
Super::Draw(Viewport, SceneCanvas);
if (any_condition_you_need) {
CaptureFrame();
}
}
void UMyGameViewportClient::CaptureFrame()
{
if (!Viewport) {
return;
}
if (ViewportSize.X == 0 || ViewportSize.Y == 0) {
return;
}
ColorBuffer.Empty(); // Declare this in header as TArray<FColor>
if (!Viewport->ReadPixels(ColorBuffer, FReadSurfaceDataFlags(),
FIntRect(0, 0, ViewportSize.X, ViewportSize.Y)))
{
return;
}
SaveThumbnailImage();
}
void UMyGameViewportClient::SaveThumbnailImage()
{
IImageWrapperModule& wrappermodule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
auto wrapper_ptr = wrappermodule.CreateImageWrapper(EImageFormat::PNG);
for (int i = 0; i < ColorBuffer.Num(); i++)
{
auto ptr = &ColorBuffer[i];
auto r = ptr->R;
auto b = ptr->B;
ptr->R = b;
ptr->B = r;
ptr->A = 255;
} // not necessary, if you like bgra, just change the following function argument to ERGBFormat::BGRA
wrapper_ptr->SetRaw(&ColorBuffer[0], ColorBuffer.Num() * 4,
ViewportSize.X, ViewportSize.Y, ERGBFormat::RGBA, 8);
FFileHelper::SaveArrayToFile(wrapper_ptr->GetCompressed(), *ThumbnailFile);
}

openAL looping cycle error

im trying to play a looping sound in openGL/SDL with openAL but when im calling it its just looping infinitely and its stuck at the start ive got no idea how to fix this so i came here hoping some1 knows heres my code of how im calling openAL
SDL_Thread * AudioBG;
bool Init(void)
{
m_Music->LoadFile("Sonido/BGSP.wav",true);
}
int MusicThread(void *arg)//Creating the Thread
{
arg+=0;
for(;;)
{
m_Music->PlaySound();
}
return 0;
}
void Draw()//this is my cycle of the game
{
gui->Draw(x,y,z);
AudioBG = SDL_CreateThread(Music,NULL);
}
this is my class Sound.cpp
Sound::Sound()
{
Device = alcOpenDevice((ALCchar*)"DirectSound3D");
Context = alcCreateContext(Device,NULL);
alcMakeContextCurrent(Context);
alGetError();
}
Sound::~Sound()
{
Context = alcGetCurrentContext();
Device = alcGetContextsDevice(Context);
alcMakeContextCurrent(NULL);
alcDestroyContext(Context);
alcCloseDevice(Device);
}
void Sound::LoadFile(char archivo[40],bool looping)
{
ALboolean loop;
loop = looping;
alutLoadWAVFile(archivo,&alFormatBuffer,
(void **)&alBuffer,
(ALsizei *)&alBufferLen,
&alFreqBuffer,&loop);
alGenSources(1,&this->alSource);
alGenBuffers(1,&alSampleSet);
alBufferData(alSampleSet,alFormatBuffer,alBuffer,alBufferLen,alFreqBuffer);
alSourcei(this->alSource,AL_BUFFER,alSampleSet);
alutUnloadWAV(alFormatBuffer,alBuffer,alBufferLen,alFreqBuffer);
alSourcef(this->alSource,AL_PITCH,1.0f);
alSourcef(this->alSource,AL_GAIN,1.0f);
if(looping)
alSourcei(this->alSource,AL_LOOPING,AL_TRUE);
else
alSourcei(this->alSource,AL_LOOPING,AL_FALSE);
}
void Sound::Direction(float x,float y,float z,float vx,float vy,float vz)
{
alSource3f(this->alSource,AL_POSITION,x,y,z);
alSource3f(this->alSource,AL_VELOCITY,vx,vy,vz);
}
void Sound::RelativeSound()
{
alSourcei(this->alSource,AL_SOURCE_RELATIVE,AL_TRUE);
}
void Sound::PlaySound()
{
alSourcePlay(this->alSource);
}
im really lost... if i call the function LoadFile and initialize the song out of the game loop and without a thread it plays well but inside the loop and with or without the thread im getting the error i tried to describe :S