예제 #1
0
void end(trace_event* evt) {
	if (!do_trace_events) {
		// No one to process the event is here
		return;
	}

	if (!initialized) {
		return;
	}

	Assertion(evt->pid == get_pid(), "Complete events must be generated from the same process!");
	Assertion(evt->tid == get_tid(), "Complete events must be generated from the same thread!");

	evt->duration = timer_get_nanoseconds() - evt->timestamp;
	evt->end_event_id = ++current_id;

	// Process CPU events
	submit_event(evt);

	// Create GPU events
	if (do_gpu_queries && evt->category->usesGPUCounter()) {
		Assertion(get_tid() == main_thread_id, "This function must be called from the main thread!");

		gpu_trace_event gpu_event;
		gpu_event.base_evt.category = evt->category;
		gpu_event.base_evt.tid = 1;
		gpu_event.base_evt.pid = GPU_PID;
		gpu_event.base_evt.type = EventType::End;

		gpu_event.gpu_begin_query = get_gpu_timestamp_query();

		// This does not need to be synchronized since GPU queries are only allowed on the main thread.
		gpu_events.push(gpu_event);
	}
}
예제 #2
0
void init() {
	do_trace_events = false;
	do_async_events = false;
	do_counter_events = false;

	if (Cmdline_json_profiling) {
		traceEventWriter.reset(new ThreadedTraceEventWriter());
		do_trace_events = true;
		do_async_events = true;
		do_counter_events = true;
	}
	if (Cmdline_profile_write_file) {
		mainFrameTimer.reset(new ThreadedMainFrameTimer());
		do_async_events = true;
	}
	if (Cmdline_frame_profile) {
		frameProfiler.reset(new FrameProfiler());
		do_trace_events = true;
	}

	do_gpu_queries = gr_is_capable(CAPABILITY_TIMESTAMP_QUERY);

	if (do_gpu_queries) {
		gpu_start_query = get_gpu_timestamp_query();
	}
	cpu_start_time = timer_get_nanoseconds();

	main_thread_id = get_tid();

	initialized = true;
}
예제 #3
0
/**
 * Used to end profiling of a section of code. Note that the parameter given MUST match that of the preceding call
 * to profile_begin
 * @param name A globally unique string that will be displayed in the HUD readout
 */
void profile_end(const char* name)
{
    if (Cmdline_json_profiling)
    {
        std::lock_guard<std::mutex> guard(json_mutex);

        tracing_data data;

        data.name = name;

        data.pid = get_pid();
        data.tid = get_tid();

        data.enter = false;
        data.time = timer_get_nanoseconds();

        if (do_gpu_queries) {
            data.gpu_query = get_query_object();
            gr_query_value(data.gpu_query, QueryType::Timestamp);
        } else {
            data.gpu_query = -1;
        }

        current_frame_data.push_back(data);
    }

    if (Cmdline_frame_profile) {
        int num_parents = 0;
        int child_of = -1;

        for ( int i = 0; i < (int)samples.size(); i++ ) {
            if ( samples[i].open_profiles ) {
                if ( samples[i].num_children == 1 ) {
                    child_of = i;
                }
            }
        }

        for ( int i = 0; i < (int)samples.size(); i++ ) {
            if ( !strcmp(samples[i].name.c_str(), name) && samples[i].parent == child_of ) {
                int inner = 0;
                int parent = -1;
                std::uint64_t end_time = timer_get_microseconds();
                samples[i].open_profiles--;

                // count all parents and find the immediate parent
                while ( inner < (int)samples.size() ) {
                    if ( samples[inner].open_profiles > 0 ) {
                        // found a parent (any open profiles are parents)
                        num_parents++;

                        if (parent < 0) {
                            // replace invalid parent (index)
                            parent = inner;
                        }
                        else if (samples[inner].start_time >= samples[parent].start_time) {
                            // replace with more immediate parent
                            parent = inner;
                        }
                    }
                    inner++;
                }

                // remember the current number of parents of the sample
                samples[i].num_parents = num_parents;

                if ( parent >= 0 ) {
                    // record this time in children_sample_time (add it in)
                    samples[parent].children_sample_time += end_time - samples[i].start_time;
                }

                // save sample time in accumulator
                samples[i].accumulator += end_time - samples[i].start_time;

                break;
            }
        }

        for (int i = 0; i < (int)samples.size(); i++) {
            if (samples[i].open_profiles) {
                samples[i].num_children--;
                samples[i].num_children = MAX(samples[i].num_children, 0);
            }
        }
    }
}
예제 #4
0
/**
 * Used to start profiling a section of code. A section started by profile_begin needs to be closed off by calling
 * profile_end with the same argument.
 * @param name A globally unique string that will be displayed in the HUD readout
 */
void profile_begin(const char* name)
{
    if (Cmdline_json_profiling)
    {
        std::lock_guard<std::mutex> guard(json_mutex);

        tracing_data data;

        data.name = name;

        data.pid = get_pid();
        data.tid = get_tid();

        data.enter = true;
        data.time = timer_get_nanoseconds();

        if (do_gpu_queries) {
            data.gpu_query = get_query_object();
            gr_query_value(data.gpu_query, QueryType::Timestamp);
        } else {
            data.gpu_query = -1;
        }

        current_frame_data.push_back(data);
    }

    if (Cmdline_frame_profile)
    {
        int parent = -1;
        for (int i = 0; i < (int)samples.size(); i++) {
            if ( !samples[i].open_profiles ) {
                continue;
            }

            samples[i].num_children++;

            if (samples[i].num_children == 1) {
                // this is our direct parent for this new sample
                parent = i;
            }
        }

        for(int i = 0; i < (int)samples.size(); i++) {
            if( !strcmp(samples[i].name.c_str(), name) && samples[i].parent == parent ) {
                // found the profile sample
                samples[i].open_profiles++;
                samples[i].profile_instances++;
                samples[i].start_time = timer_get_microseconds();
                Assert(samples[i].open_profiles == 1); // max 1 open at once
                return;
            }
        }

        // create a new profile sample
        profile_sample new_sample;

        new_sample.name = SCP_string(name);
        new_sample.open_profiles = 1;
        new_sample.profile_instances = 1;
        new_sample.accumulator = 0;
        new_sample.start_time = timer_get_microseconds();
        new_sample.children_sample_time = 0;
        new_sample.num_children = 0;
        new_sample.parent = parent;

        samples.push_back(new_sample);
    }
}