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); init(myImpl, setup);
initializePalette(palette); initializePalette(palette);
myNumThreads = std::min(4u, std::thread::hardware_concurrency()); uInt32 systemThreads = std::thread::hardware_concurrency();
myThreads = new std::thread[myNumThreads]; 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,35 +82,29 @@ 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 AtariNTSC::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)
{ {
// Spawn the threads... // Spawn the threads...
for(uInt8 i = 0; i < myNumThreads; i++) for(uInt32 i = 0; i < myWorkerThreads; ++i)
{
myThreads[i] = std::thread([=] { myThreads[i] = std::thread([=] {
renderWithPhosphorThread(atari_in, in_width, in_height, myNumThreads, i, rgb_in == nullptr ?
rgb_in, rgb_out, out_pitch); 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 // ...and make them join again
for(uInt8 i = 0; i < myNumThreads; i++) for(uInt32 i = 0; i < myWorkerThreads; ++i)
myThreads[i].join(); myThreads[i].join();
// Copy phosphor values into out buffer // Copy phosphor values into out buffer
if(rgb_in != nullptr)
memcpy(rgb_out, rgb_in, in_height * out_pitch); 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. // 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. // 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 render(const uInt8* atari_in, const uInt32 in_width, const uInt32 in_height,
void* rgb_out, const uInt32 out_pitch); void* rgb_out, const uInt32 out_pitch, uInt32* rgb_in = nullptr);
void render(const uInt8* atari_in, const uInt32 in_width, const uInt32 in_height,
void* rgb_out, const uInt32 out_pitch, uInt32* rgb_in);
// Number of input pixels that will fit within given output width. // Number of input pixels that will fit within given output width.
// Might be rounded down slightly; use outWidth() on result to find // Might be rounded down slightly; use outWidth() on result to find
@ -165,9 +163,9 @@ class AtariNTSC
uInt8 myPhosphorPalette[256][256]; uInt8 myPhosphorPalette[256][256];
// Rendering threads // Rendering threads
std::thread* myThreads; unique_ptr<std::thread[]> myThreads;
// Number of rendering threads // Number of rendering and total threads
uInt8 myNumThreads; uInt32 myWorkerThreads, myTotalThreads;
struct init_t struct init_t
{ {