Giter Site home page Giter Site logo

Comments (13)

mithrendal avatar mithrendal commented on May 27, 2024 1

These two locations are maybe still toxic 😷

int64_t
sleepUntil(uint64_t kernelTargetTime, uint64_t kernelEarlyWakeup)
{
...
    // Sleep
    //printf("Sleeping for %d\n", kernelTargetTime - now);
 #ifdef __EMSCRIPTEN__
    //std::this_thread::sleep_until (kernelTargetTime - kernelEarlyWakeup);
    //emscripten_sleep(kernelTargetTime - kernelEarlyWakeup);
 #else
    mach_wait_until(kernelTargetTime - kernelEarlyWakeup);
 #endif
C64::C64()
{
...
    // Initialize mach timer info
#ifdef __EMSCRIPTEN__
#else
    mach_timebase_info(&timebase);
#endif

I decided to do nothing instead of something wrong ...

Also the current emulation of the mach_time function located in mainsdl.cpp is also a suspect candidat for revision...

/* emulation of macos mach_absolute_time() function. */
long mach_absolute_time()
{
    auto xnow = std::chrono::system_clock::now();
    auto now_ns = std::chrono::time_point_cast<std::chrono::nanoseconds>(xnow);
    auto epoch = now_ns.time_since_epoch();
    auto now_ns_long = std::chrono::duration_cast<std::chrono::nanoseconds>(epoch).count();
    return now_ns_long;
}

from virtualc64web.

mithrendal avatar mithrendal commented on May 27, 2024

which one ? All of them seem to work ...

/* emulation of macos mach_absolute_time() function. */
//#define EMSDK_NOW  1
#define STD_LIB_NOW  1
//#define FAKE_NOW  1

long faked_now=0;
long mach_absolute_time()
{
#ifdef FAKE_NOW
    return faked_now++;
#elif EMSDK_NOW
    return (long)emscripten_get_now();
#elif STD_LIB_NOW
    auto xnow = std::chrono::system_clock::now();
    auto now_ns = std::chrono::time_point_cast<std::chrono::nanoseconds>(xnow);
    auto epoch = now_ns.time_since_epoch();
    auto now_ns_long = std::chrono::duration_cast<std::chrono::nanoseconds>(epoch).count();

    printf("stdlib_now: %lld, emsdk_now: %ld, fake_now: %ld\n", now_ns_long, (long)emscripten_get_now(), faked_now++);

    return now_ns_long;
#endif
}

output here:
grafik

I am wondering what numbers the real not emulated method generates ... 🤔

Can't spot any decrease in emulation accuracy though .... when using any of them ... are the numbers not so important ???

from virtualc64web.

dirkwhoffmann avatar dirkwhoffmann commented on May 27, 2024

which one ? All of them seem to work ...

Afaik std::chrono is a wrapper around some native API (which may be different among different machines). I've read somewhere that we shouldn't use it.

Although I have no real reason, I would go for emscripten_get_now().

Can't spot any decrease in emulation accuracy though .... when using any of them ... are the numbers not so important ???

Hmm, the code relies on all values being measured in nanos.

In C64::synchronizeTiming(), it calculates the new target time as follows:

nanoTargetTime += vic.getFrameDelay();

VIC returns the frame delay in nanos. If nanoTargetTimehas a different unit, there is no chance that the code works (theoretically) 🤔.

BTW, did you implement mach_wait_until()? Otherwise, the emulator would simulate the delay in a counting loop which is likely to screw up our planet's energy resources in no time 😬.

int64_t
sleepUntil(uint64_t kernelTargetTime, uint64_t kernelEarlyWakeup)
{
    uint64_t now = mach_absolute_time();
    int64_t jitter;
    
    if (now > kernelTargetTime)
        return 0;
    
    // Sleep
    // printf("Sleeping for %d\n", kernelTargetTime - now);
    mach_wait_until(kernelTargetTime - kernelEarlyWakeup);
    
    // Count some sheep to increase precision
    unsigned sheep = 0;
    do {
        jitter = mach_absolute_time() - kernelTargetTime;
        sheep++;
    } while (jitter < 0);
    
    return jitter;
}

from virtualc64web.

mithrendal avatar mithrendal commented on May 27, 2024

no I didn't 🙄

#ifdef __EMSCRIPTEN__
    //std::this_thread::sleep_until (kernelTargetTime - kernelEarlyWakeup);
    //emscripten_sleep(kernelTargetTime - kernelEarlyWakeup);
 #else
    mach_wait_until(kernelTargetTime - kernelEarlyWakeup);
 #endif

therefore maybe does it no matter which variant of mach_absolute_time emulation I use 🤔

from virtualc64web.

dirkwhoffmann avatar dirkwhoffmann commented on May 27, 2024

no I didn't 🙄

😃

therefore maybe does it no matter which variant of mach_absolute_time emulation I use 🤔

No. If kernelTargetTime is a very small value, the delay loop would execute forever. How did you manage to write code that works correctly no matter what units are used? Usually, it's the other way round. 🤔

from virtualc64web.

mithrendal avatar mithrendal commented on May 27, 2024

VIC returns the frame delay in nanos. If nanoTargetTimehas a different unit, there is no chance that the code works (theoretically) 🤔.

emscripten_get_now(); return type double unit is millis 😳

from the values in the log output above none of the variant delivers nanos ... Yes I mean I could do millis*1000 but ...

then it is counting innumerable amount of sheeps ....😩 (well ... literally spoken)

from virtualc64web.

mithrendal avatar mithrendal commented on May 27, 2024

How did you manage to write code that works correctly no matter what units are used? Usually, it's the other way round. 🤔

Oh I did not yet mention the flag

#define SELF_HEALING_ON true

😂

from virtualc64web.

mithrendal avatar mithrendal commented on May 27, 2024
int64_t
sleepUntil(uint64_t kernelTargetTime, uint64_t kernelEarlyWakeup)
{
    uint64_t now = mach_absolute_time();
    int64_t jitter;
    printf("KernalTargetTime %llu, now %llu\n", kernelTargetTime , now);
    
    if (now > kernelTargetTime)
        return 0;

...

grafik

no sheep counting ...

Why is KernalTargetTime = zero ??? I bet that was me .... when I rushed like Rambo through the code to make it compile ...

from virtualc64web.

dirkwhoffmann avatar dirkwhoffmann commented on May 27, 2024

Yes I mean I could do millis*1000 but ... then it is counting innumerable amount of sheeps ....😩

Yes, but you can also divide vic.getFrameDelay()by 1000 which means less sheep 😎.

#define SELF_HEALING_ON true

🤤 yes yes yes, I need that, too.

from virtualc64web.

dirkwhoffmann avatar dirkwhoffmann commented on May 27, 2024

no sheep counting ...

Hmm, so I guess kernelTargetTime is wrong and VirtualC64web simply runs at 100% CPU. No?

from virtualc64web.

mithrendal avatar mithrendal commented on May 27, 2024

?

I look for the kernaltargettime ....



void
C64::synchronizeTiming()
{
    const uint64_t earlyWakeup = 1500000; /* 1.5 milliseconds */
    
    // Get current time in nano seconds
    uint64_t nanoAbsTime = 0; //abs_to_nanos(mach_absolute_time());
    
    // Check how long we're supposed to sleep
    int64_t timediff = (int64_t)nanoTargetTime - (int64_t)nanoAbsTime;
    if (timediff > 200000000 || timediff < -200000000 /* 0.2 sec */) {
        
        // The emulator seems to be out of sync, so we better reset the
        // synchronization timer
        
        debug(2, "Emulator lost synchronization (%lld). Restarting timer.\n", timediff);
        restartTimer();
    }
    
    // Convert nanoTargetTime into kernel unit
    int64_t kernelTargetTime = nanos_to_abs(nanoTargetTime);
    
    // Sleep and update target timer
    // debug(2, "%p Sleeping for %lld\n", this, kernelTargetTime - mach_absolute_time());
    int64_t jitter = sleepUntil(kernelTargetTime, earlyWakeup);
    nanoTargetTime += vic.getFrameDelay();

well yes ... thats why ...

uint64_t nanoAbsTime = 0; //abs_to_nanos(mach_absolute_time());

soo ugly ... corrected it to

#ifdef __EMSCRIPTEN__
    uint64_t nanoAbsTime = 0; 
#else
    uint64_t nanoAbsTime = abs_to_nanos(mach_absolute_time());
#endif

Why did I set it to zero ? Hmm 🤔 I guess I had no abs_to_nanos() method and therefore I simply removed it to get A successful compile and my hands on Blue Max🤤 ?

from virtualc64web.

mithrendal avatar mithrendal commented on May 27, 2024

But why did we bother about the nanosecond thing this morning? This code is not needed and never called 😯.

Is this related then with issue #16 ? I ask myself, what is the consequence of setting uint64_t nanoAbsTime = 0; in the code above ? What happens when I set it to nanoAbsTime = abs_to_nanos(mach_absolute_time()); as it was originally ....

I think I get your idea ... you think we don't have to care about the sleep stuff because we do not have to delay because the SDL is doing the delay and synchronisation for us ... yes ?

Maybe I did not understand it ... I will try this out ... hang on

Ahh I see synchronizeTiming(); is called at the end of a frame. You have to do this in the macVersion because the doExecuteOneFrame() is done in a separate thread... independent of the 60 Hz MetalRendering thread.
here

 while (likely(success)) {
       pthread_testcancel();
       success = c64->executeOneFrame();
   }

and because in vc64web the executeOneFrame() is called by the Renderingthread itself, there is no need to synchonize anymore ...

and all the mach_absolute_time() in relation with the synchronize are not needed..

There is only one place in code left where mach_absolute_time() is still needed... in the handling SID over buffer overflow/underrun

from virtualc64web.

mithrendal avatar mithrendal commented on May 27, 2024

B6C0573C-D684-4189-BFE5-E7E1806A8020

Pushed it real good

from virtualc64web.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.