Threaded Blargg + phosphor improvements:

- Handle case of only 1 or zero (!) reported cores
 - Fix memory leak by using smart pointers
This commit is contained in:
Stephen Anthony 2017-08-14 11:57:19 -02:30
parent 6d1a306b52
commit a29d1da57b
2 changed files with 33 additions and 28 deletions

View File

@ -36,8 +36,21 @@ void AtariNTSC::initialize(const Setup& setup, const uInt8* palette)
init(myImpl, setup);
initializePalette(palette);
myNumThreads = std::min(4u, std::thread::hardware_concurrency());
myThreads = new std::thread[myNumThreads];
uInt32 systemThreads = std::thread::hardware_concurrency();
if(systemThreads <= 1)
{
myWorkerThreads = 0;
myTotalThreads = 1;
}
else
{
systemThreads = std::min(4u, systemThreads);
myWorkerThreads = systemThreads - 1;
myTotalThreads = systemThreads;
myThreads = make_unique<std::thread[]>(myWorkerThreads);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -69,36 +82,30 @@ void AtariNTSC::initializePalette(const uInt8* palette)
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AtariNTSC::render(const uInt8* atari_in, const uInt32 in_width,
const uInt32 in_height, void* rgb_out, const uInt32 out_pitch)
{
// Spawn the threads...
for(uInt8 i = 0; i < myNumThreads; i++)
myThreads[i] = std::thread([=] {
renderThread(atari_in, in_width, in_height, myNumThreads, i, rgb_out, out_pitch);
});
// ...and make them join again
for(uInt8 i = 0; i < myNumThreads; i++)
myThreads[i].join();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AtariNTSC::render(const uInt8* atari_in, const uInt32 in_width, const uInt32 in_height,
void* rgb_out, const uInt32 out_pitch, uInt32* rgb_in)
{
// Spawn the threads...
for(uInt8 i = 0; i < myNumThreads; i++)
for(uInt32 i = 0; i < myWorkerThreads; ++i)
{
myThreads[i] = std::thread([=] {
renderWithPhosphorThread(atari_in, in_width, in_height, myNumThreads, i,
rgb_in, rgb_out, out_pitch);
});
rgb_in == nullptr ?
renderThread(atari_in, in_width, in_height, myTotalThreads, i+1, rgb_out, out_pitch) :
renderWithPhosphorThread(atari_in, in_width, in_height, myTotalThreads, i+1, rgb_in, rgb_out, out_pitch);
});
}
// Make the main thread busy too
rgb_in == nullptr ?
renderThread(atari_in, in_width, in_height, myTotalThreads, 0, rgb_out, out_pitch) :
renderWithPhosphorThread(atari_in, in_width, in_height, myTotalThreads, 0, rgb_in, rgb_out, out_pitch);
// ...and make them join again
for(uInt8 i = 0; i < myNumThreads; i++)
for(uInt32 i = 0; i < myWorkerThreads; ++i)
myThreads[i].join();
// Copy phosphor values into out buffer
memcpy(rgb_out, rgb_in, in_height * out_pitch);
if(rgb_in != nullptr)
memcpy(rgb_out, rgb_in, in_height * out_pitch);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -90,9 +90,7 @@ class AtariNTSC
// In_row_width is the number of pixels to get to the next input row.
// Out_pitch is the number of *bytes* to get to the next output row.
void render(const uInt8* atari_in, const uInt32 in_width, const uInt32 in_height,
void* rgb_out, const uInt32 out_pitch);
void render(const uInt8* atari_in, const uInt32 in_width, const uInt32 in_height,
void* rgb_out, const uInt32 out_pitch, uInt32* rgb_in);
void* rgb_out, const uInt32 out_pitch, uInt32* rgb_in = nullptr);
// Number of input pixels that will fit within given output width.
// Might be rounded down slightly; use outWidth() on result to find
@ -165,9 +163,9 @@ class AtariNTSC
uInt8 myPhosphorPalette[256][256];
// Rendering threads
std::thread* myThreads;
// Number of rendering threads
uInt8 myNumThreads;
unique_ptr<std::thread[]> myThreads;
// Number of rendering and total threads
uInt32 myWorkerThreads, myTotalThreads;
struct init_t
{