-
Notifications
You must be signed in to change notification settings - Fork 78
/
FrameRecorder.h
180 lines (157 loc) · 7.23 KB
/
FrameRecorder.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
////////////////////////////////////////////////////////////////////////////////
// Copyright 2017 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
////////////////////////////////////////////////////////////////////////////////
#pragma once
/*!
* \file FrameRecorder.h
* \brief Masked occlusion culling recorder class (set MOC_RECORDER_ENABLE to 1 to enable)
*
* Masked occlusion culling recorder class (To enable, set MOC_RECORDER_ENABLE to 1 in MaskedOcclusionCulling.h)
*
* Enables gathering and storing all triangle rendering and all testing calls and their results to a file, for
* later playback and performance testing.
* Usage info:
* - Calling MaskedOcclusionCulling::RecorderStart with a file name will open the file and start recording all subsequent
* triangle rendering and any testing calls including the test results, and MaskedOcclusionCulling::RecorderStop will
* stop recording and close the file.
* - ClearBuffer-s are not recorded so if recording multiple frames, Start/RecorderStop is needed for each frame. For
* correctness testing, the recording should be started around or after ClearBuffer, before any other "Render" calls.
* - BinTriangles and RenderTrilist calls are NOT recorded; If using a custom multithreaded rendering, one should
* record input triangles by manually calling MaskedOcclusionCulling::RecordRenderTriangles - see
* CullingThreadpool::RenderTriangles for an example.
* This is done intentionally in order to get raw input triangles so we can performance test and optimize various
* thread pool approaches.
*/
#include "MaskedOcclusionCulling.h"
#ifndef MOC_RECORDER_USE_STDIO_FILE
/*!
* Whether to use FILE or std::ofstream/istream for file access (to avoid compatibility issues in some environments)
*/
#define MOC_RECORDER_USE_STDIO_FILE 1
#endif
#if MOC_RECORDER_ENABLE
#if MOC_RECORDER_USE_STDIO_FILE
#include <stdio.h>
#else
#include <fstream>
#endif
#include <mutex>
class FrameRecorder
{
#if MOC_RECORDER_USE_STDIO_FILE
FILE * mOutFile;
#else
std::ofstream mOutStream;
#endif
protected:
friend class MaskedOcclusionCulling;
#if MOC_RECORDER_USE_STDIO_FILE
FrameRecorder( FILE *& outFile, const MaskedOcclusionCulling & moc );
#else
FrameRecorder( std::ofstream && outStream, const MaskedOcclusionCulling & moc );
#endif
public:
~FrameRecorder( );
protected:
void Write( const void * buffer, size_t size );
void WriteTriangleRecording( MaskedOcclusionCulling::CullingResult cullingResult, const float *inVtx, const unsigned int *inTris, int nTris, const float *modelToClipMatrix, MaskedOcclusionCulling::ClipPlanes clipPlaneMask, MaskedOcclusionCulling::BackfaceWinding bfWinding, const MaskedOcclusionCulling::VertexLayout & vtxLayout );
public:
void RecordClearBuffer( );
void RecordRenderTriangles( MaskedOcclusionCulling::CullingResult cullingResult, const float *inVtx, const unsigned int *inTris, int nTris, const float *modelToClipMatrix, MaskedOcclusionCulling::ClipPlanes clipPlaneMask, MaskedOcclusionCulling::BackfaceWinding bfWinding, const MaskedOcclusionCulling::VertexLayout &vtxLayout );
void RecordTestRect( MaskedOcclusionCulling::CullingResult cullingResult, float xmin, float ymin, float xmax, float ymax, float wmin );
void RecordTestTriangles( MaskedOcclusionCulling::CullingResult cullingResult, const float *inVtx, const unsigned int *inTris, int nTris, const float *modelToClipMatrix, MaskedOcclusionCulling::ClipPlanes clipPlaneMask, MaskedOcclusionCulling::BackfaceWinding bfWinding, const MaskedOcclusionCulling::VertexLayout &vtxLayout );
};
#if MOC_RECORDER_ENABLE_PLAYBACK
#include <vector>
#if 0 // For future use - in case all vector uses below need conversion to custom allocator
template <class T>
struct MOCVectorAllocator
{
const MaskedOcclusionCulling::pfnAlignedAlloc m_alloc;
const MaskedOcclusionCulling::pfnAlignedFree m_free;
typedef T value_type;
MOCVectorAllocator( ) = delete;
MOCVectorAllocator( MaskedOcclusionCulling::pfnAlignedAlloc alloc, MaskedOcclusionCulling::pfnAlignedFree free ) noexcept : m_alloc( alloc ), m_free( free ) { }
template <class U> constexpr MOCVectorAllocator( const MOCVectorAllocator<U>& c ) noexcept : m_alloc( c.m_alloc ), m_free( c.m_free ) {}
T* allocate( std::size_t n )
{
if( n > std::size_t( -1 ) / sizeof( T ) ) throw std::bad_alloc( );
if( auto p = static_cast<T*>( m_alloc( 64, n * sizeof( T ) ) ) ) return p;
throw std::bad_alloc( );
}
void deallocate( T* p, std::size_t ) noexcept
{
m_free( p );
}
};
template <class T, class U>
inline bool operator==( const MOCVectorAllocator<T>&, const MOCVectorAllocator<U>& ) { return true; }
template <class T, class U>
inline bool operator!=( const MOCVectorAllocator<T>&, const MOCVectorAllocator<U>& ) { return false; }
#endif
struct FrameRecording
{
struct TrianglesEntry
{
MaskedOcclusionCulling::CullingResult mCullingResult;
std::vector<float> mVertices;
std::vector<unsigned int> mTriangles;
float mModelToClipMatrix[16];
MaskedOcclusionCulling::BackfaceWinding mbfWinding;
MaskedOcclusionCulling::VertexLayout mVertexLayout;
MaskedOcclusionCulling::ClipPlanes mClipPlaneMask;
bool mHasModelToClipMatrix;
bool mHasScissorRect;
};
struct RectEntry
{
MaskedOcclusionCulling::CullingResult mCullingResult;
float mXMin;
float mYMin;
float mXMax;
float mYMax;
float mWMin;
};
// list of type&index pairs for playback ( type 0 is RenderTriangles, type 1 is TestRect, type 2 is TestTriangles, type 3 is ClearBuffer )
std::vector< std::pair< char, int > > mPlaybackOrder;
std::vector< TrianglesEntry > mTriangleEntries;
std::vector< RectEntry > mRectEntries;
float mNearClipPlane;
unsigned int mResolutionWidth;
unsigned int mResolutionHeight;
FrameRecording( ) = default;
FrameRecording( const FrameRecording & other ) = default;
FrameRecording( FrameRecording && other )
{
mPlaybackOrder = std::move( other.mPlaybackOrder );
mTriangleEntries = std::move( other.mTriangleEntries );
mRectEntries = std::move( other.mRectEntries );
mNearClipPlane = other.mNearClipPlane;
mResolutionWidth = other.mResolutionWidth;
mResolutionHeight = other.mResolutionHeight;
}
void Reset( )
{
mPlaybackOrder.clear();
mTriangleEntries.clear();
mRectEntries.clear();
mNearClipPlane = 0.0f;
mResolutionWidth = 0;
mResolutionHeight = 0;
}
static bool Load( const char * inputFilePath, FrameRecording & outRecording );
};
#endif // #if MOC_RECORDER_ENABLE_PLAYBACK
#endif // #if MOC_RECORDER_ENABLE