mirror of
https://github.com/TomHarte/CLK.git
synced 2024-07-30 23:29:08 +00:00
Started edging towards completing the CPU side of accumulating enough data for composite decoding.
This commit is contained in:
parent
5c8db71c64
commit
23c223e2ed
@ -66,9 +66,9 @@ void CRT::allocate_buffers(unsigned int number, va_list sizes)
|
|||||||
_run_builders = new CRTRunBuilder *[kCRTNumberOfFields];
|
_run_builders = new CRTRunBuilder *[kCRTNumberOfFields];
|
||||||
for(int builder = 0; builder < kCRTNumberOfFields; builder++)
|
for(int builder = 0; builder < kCRTNumberOfFields; builder++)
|
||||||
{
|
{
|
||||||
_run_builders[builder] = new CRTRunBuilder(kCRTOutputVertexSize);
|
_run_builders[builder] = new CRTRunBuilder(kCRTOutputVertexSize, 6);
|
||||||
}
|
}
|
||||||
_composite_src_runs = std::unique_ptr<CRTRunBuilder>(new CRTRunBuilder(kCRTInputVertexSize));
|
_composite_src_runs = std::unique_ptr<CRTRunBuilder>(new CRTRunBuilder(kCRTInputVertexSize, 2));
|
||||||
|
|
||||||
va_list va;
|
va_list va;
|
||||||
va_copy(va, sizes);
|
va_copy(va, sizes);
|
||||||
@ -77,14 +77,14 @@ void CRT::allocate_buffers(unsigned int number, va_list sizes)
|
|||||||
}
|
}
|
||||||
|
|
||||||
CRT::CRT(unsigned int common_output_divisor) :
|
CRT::CRT(unsigned int common_output_divisor) :
|
||||||
_next_scan(0),
|
|
||||||
_run_write_pointer(0),
|
_run_write_pointer(0),
|
||||||
_sync_capacitor_charge_level(0),
|
_sync_capacitor_charge_level(0),
|
||||||
_is_receiving_sync(false),
|
_is_receiving_sync(false),
|
||||||
_output_mutex(new std::mutex),
|
_output_mutex(new std::mutex),
|
||||||
_visible_area(Rect(0, 0, 1, 1)),
|
_visible_area(Rect(0, 0, 1, 1)),
|
||||||
_sync_period(0),
|
_sync_period(0),
|
||||||
_common_output_divisor(common_output_divisor)
|
_common_output_divisor(common_output_divisor),
|
||||||
|
_composite_src_output_y(0)
|
||||||
{
|
{
|
||||||
construct_openGL();
|
construct_openGL();
|
||||||
}
|
}
|
||||||
@ -131,6 +131,21 @@ Flywheel::SyncEvent CRT::get_next_horizontal_sync_event(bool hsync_is_requested,
|
|||||||
return _horizontal_flywheel->get_next_event_in_period(hsync_is_requested, cycles_to_run_for, cycles_advanced);
|
return _horizontal_flywheel->get_next_event_in_period(hsync_is_requested, cycles_to_run_for, cycles_advanced);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define output_position_x(v) (*(uint16_t *)&next_run[kCRTOutputVertexSize*v + kCRTOutputVertexOffsetOfPosition + 0])
|
||||||
|
#define output_position_y(v) (*(uint16_t *)&next_run[kCRTOutputVertexSize*v + kCRTOutputVertexOffsetOfPosition + 2])
|
||||||
|
#define output_tex_x(v) (*(uint16_t *)&next_run[kCRTOutputVertexSize*v + kCRTOutputVertexOffsetOfTexCoord + 0])
|
||||||
|
#define output_tex_y(v) (*(uint16_t *)&next_run[kCRTOutputVertexSize*v + kCRTOutputVertexOffsetOfTexCoord + 2])
|
||||||
|
#define output_lateral(v) next_run[kCRTOutputVertexSize*v + kCRTOutputVertexOffsetOfLateral]
|
||||||
|
#define output_timestamp(v) (*(uint32_t *)&next_run[kCRTOutputVertexSize*v + kCRTOutputVertexOffsetOfTimestamp])
|
||||||
|
|
||||||
|
#define input_input_position_x(v) (*(uint16_t *)&next_run[kCRTInputVertexSize*v + kCRTInputVertexOffsetOfInputPosition + 0])
|
||||||
|
#define input_input_position_y(v) (*(uint16_t *)&next_run[kCRTInputVertexSize*v + kCRTInputVertexOffsetOfInputPosition + 2])
|
||||||
|
#define input_output_position_x(v) (*(uint16_t *)&next_run[kCRTInputVertexSize*v + kCRTInputVertexOffsetOfOutputPosition + 0])
|
||||||
|
#define input_output_position_y(v) (*(uint16_t *)&next_run[kCRTInputVertexSize*v + kCRTInputVertexOffsetOfOutputPosition + 2])
|
||||||
|
#define input_phase(v) next_run[kCRTOutputVertexSize*v + kCRTInputVertexOffsetOfPhaseAndAmplitude + 0]
|
||||||
|
#define input_amplitude(v) next_run[kCRTOutputVertexSize*v + kCRTInputVertexOffsetOfPhaseAndAmplitude + 1]
|
||||||
|
#define input_phase_time(v) (*(uint16_t *)&next_run[kCRTOutputVertexSize*v + kCRTInputVertexOffsetOfPhaseTime])
|
||||||
|
|
||||||
void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divider, bool hsync_requested, bool vsync_requested, const bool vsync_charging, const Type type, uint16_t tex_x, uint16_t tex_y)
|
void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divider, bool hsync_requested, bool vsync_requested, const bool vsync_charging, const Type type, uint16_t tex_x, uint16_t tex_y)
|
||||||
{
|
{
|
||||||
number_of_cycles *= _time_multiplier;
|
number_of_cycles *= _time_multiplier;
|
||||||
@ -150,33 +165,44 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi
|
|||||||
hsync_requested = false;
|
hsync_requested = false;
|
||||||
vsync_requested = false;
|
vsync_requested = false;
|
||||||
|
|
||||||
uint8_t *next_run = ((is_output_run && next_run_length) && !_horizontal_flywheel->is_in_retrace() && !_vertical_flywheel->is_in_retrace()) ? _run_builders[_run_write_pointer]->get_next_run() : nullptr;
|
bool is_output_segment = ((is_output_run && next_run_length) && !_horizontal_flywheel->is_in_retrace() && !_vertical_flywheel->is_in_retrace());
|
||||||
|
uint8_t *next_run = nullptr;
|
||||||
#define position_x(v) (*(uint16_t *)&next_run[kCRTOutputVertexSize*v + kCRTOutputVertexOffsetOfPosition + 0])
|
if(is_output_segment)
|
||||||
#define position_y(v) (*(uint16_t *)&next_run[kCRTOutputVertexSize*v + kCRTOutputVertexOffsetOfPosition + 2])
|
{
|
||||||
#define tex_x(v) (*(uint16_t *)&next_run[kCRTOutputVertexSize*v + kCRTOutputVertexOffsetOfTexCoord + 0])
|
_output_mutex->lock();
|
||||||
#define tex_y(v) (*(uint16_t *)&next_run[kCRTOutputVertexSize*v + kCRTOutputVertexOffsetOfTexCoord + 2])
|
next_run = (_output_device == CRT::Monitor) ? _run_builders[_run_write_pointer]->get_next_run() : _composite_src_runs->get_next_run();
|
||||||
#define lateral(v) next_run[kCRTOutputVertexSize*v + kCRTOutputVertexOffsetOfLateral]
|
}
|
||||||
#define timestamp(v) (*(uint32_t *)&next_run[kCRTOutputVertexSize*v + kCRTOutputVertexOffsetOfTimestamp])
|
|
||||||
|
|
||||||
// Vertex output is arranged as:
|
// Vertex output is arranged as:
|
||||||
//
|
//
|
||||||
// [0/4] 3
|
// [0/4] 3
|
||||||
//
|
//
|
||||||
// 1 [2/5]
|
// 1 [2/5]
|
||||||
|
|
||||||
if(next_run)
|
if(next_run)
|
||||||
|
{
|
||||||
|
if(_output_device == CRT::Monitor)
|
||||||
{
|
{
|
||||||
// set the type, initial raster position and type of this run
|
// set the type, initial raster position and type of this run
|
||||||
position_x(0) = position_x(1) = position_x(4) = (uint16_t)_horizontal_flywheel->get_current_output_position();
|
output_position_x(0) = output_position_x(1) = output_position_x(4) = (uint16_t)_horizontal_flywheel->get_current_output_position();
|
||||||
position_y(0) = position_y(1) = position_y(4) = (uint16_t)(_vertical_flywheel->get_current_output_position() / _vertical_flywheel_output_divider);
|
output_position_y(0) = output_position_y(1) = output_position_y(4) = (uint16_t)(_vertical_flywheel->get_current_output_position() / _vertical_flywheel_output_divider);
|
||||||
timestamp(0) = timestamp(1) = timestamp(4) = _run_builders[_run_write_pointer]->duration;
|
output_timestamp(0) = output_timestamp(1) = output_timestamp(4) = _run_builders[_run_write_pointer]->duration;
|
||||||
tex_x(0) = tex_x(1) = tex_x(4) = tex_x;
|
output_tex_x(0) = output_tex_x(1) = output_tex_x(4) = tex_x;
|
||||||
|
|
||||||
// these things are constants across the line so just throw them out now
|
// these things are constants across the line so just throw them out now
|
||||||
tex_y(0) = tex_y(4) = tex_y(1) = tex_y(2) = tex_y(3) = tex_y(5) = tex_y;
|
output_tex_y(0) = output_tex_y(4) = output_tex_y(1) = output_tex_y(2) = output_tex_y(3) = output_tex_y(5) = tex_y;
|
||||||
lateral(0) = lateral(4) = lateral(5) = 0;
|
output_lateral(0) = output_lateral(4) = output_lateral(5) = 0;
|
||||||
lateral(1) = lateral(2) = lateral(3) = 1;
|
output_lateral(1) = output_lateral(2) = output_lateral(3) = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
input_input_position_x(0) = tex_x;
|
||||||
|
input_input_position_y(0) = input_input_position_y(1) = tex_y;
|
||||||
|
input_output_position_x(0) = (uint16_t)_horizontal_flywheel->get_current_output_position();
|
||||||
|
input_output_position_y(0) = input_output_position_y(1) = _composite_src_output_y;
|
||||||
|
input_phase(0) = input_phase(1) = _colour_burst_phase;
|
||||||
|
input_amplitude(0) = input_amplitude(1) = _colour_burst_amplitude;
|
||||||
|
input_phase_time(0) = input_phase_time(1) = _colour_burst_time;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// decrement the number of cycles left to run for and increment the
|
// decrement the number of cycles left to run for and increment the
|
||||||
@ -196,18 +222,39 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi
|
|||||||
|
|
||||||
if(next_run)
|
if(next_run)
|
||||||
{
|
{
|
||||||
// store the final raster position
|
|
||||||
position_x(2) = position_x(3) = position_x(5) = (uint16_t)_horizontal_flywheel->get_current_output_position();
|
|
||||||
position_y(2) = position_y(3) = position_y(5) = (uint16_t)(_vertical_flywheel->get_current_output_position() / _vertical_flywheel_output_divider);
|
|
||||||
timestamp(2) = timestamp(3) = timestamp(5) = _run_builders[_run_write_pointer]->duration;
|
|
||||||
|
|
||||||
// if this is a data run then advance the buffer pointer
|
// if this is a data run then advance the buffer pointer
|
||||||
if(type == Type::Data && source_divider) tex_x += next_run_length / (_time_multiplier * source_divider);
|
if(type == Type::Data && source_divider) tex_x += next_run_length / (_time_multiplier * source_divider);
|
||||||
|
|
||||||
// if this is a data or level run then store the end point
|
if(_output_device == CRT::Monitor)
|
||||||
tex_x(2) = tex_x(3) = tex_x(5) = tex_x;
|
{
|
||||||
|
// store the final raster position
|
||||||
|
output_position_x(2) = output_position_x(3) = output_position_x(5) = (uint16_t)_horizontal_flywheel->get_current_output_position();
|
||||||
|
output_position_y(2) = output_position_y(3) = output_position_y(5) = (uint16_t)(_vertical_flywheel->get_current_output_position() / _vertical_flywheel_output_divider);
|
||||||
|
output_timestamp(2) = output_timestamp(3) = output_timestamp(5) = _run_builders[_run_write_pointer]->duration;
|
||||||
|
output_tex_x(2) = output_tex_x(3) = output_tex_x(5) = tex_x;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
input_input_position_x(1) = tex_x;
|
||||||
|
input_output_position_x(1) = (uint16_t)_horizontal_flywheel->get_current_output_position();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(is_output_segment)
|
||||||
|
{
|
||||||
|
_output_mutex->unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this is horizontal retrace then advance the output line counter and bookend an output run
|
||||||
|
if(_output_device == CRT::Television)
|
||||||
|
{
|
||||||
|
if(next_run_length == time_until_horizontal_sync_event && next_horizontal_sync_event == Flywheel::SyncEvent::EndRetrace)
|
||||||
|
{
|
||||||
|
_composite_src_output_y = (_composite_src_output_y + 1) % CRTIntermediateBufferHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this is vertical retrace then adcance a field
|
||||||
if(next_run_length == time_until_vertical_sync_event && next_vertical_sync_event == Flywheel::SyncEvent::EndRetrace)
|
if(next_run_length == time_until_vertical_sync_event && next_vertical_sync_event == Flywheel::SyncEvent::EndRetrace)
|
||||||
{
|
{
|
||||||
// TODO: how to communicate did_detect_vsync? Bring the delegate back?
|
// TODO: how to communicate did_detect_vsync? Bring the delegate back?
|
||||||
@ -219,13 +266,25 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef output_position_x
|
||||||
|
#undef output_position_y
|
||||||
|
#undef output_tex_x
|
||||||
|
#undef output_tex_y
|
||||||
|
#undef output_lateral
|
||||||
|
#undef output_timestamp
|
||||||
|
|
||||||
|
#undef input_input_position_x
|
||||||
|
#undef input_input_position_y
|
||||||
|
#undef input_output_position_x
|
||||||
|
#undef input_output_position_y
|
||||||
|
#undef input_phase
|
||||||
|
#undef input_amplitude
|
||||||
|
#undef input_phase_age
|
||||||
|
|
||||||
#pragma mark - stream feeding methods
|
#pragma mark - stream feeding methods
|
||||||
|
|
||||||
void CRT::output_scan()
|
void CRT::output_scan(Scan *scan)
|
||||||
{
|
{
|
||||||
// _next_scan ^= 1;
|
|
||||||
Scan *scan = &_scans[_next_scan];
|
|
||||||
|
|
||||||
bool this_is_sync = (scan->type == Type::Sync);
|
bool this_is_sync = (scan->type == Type::Sync);
|
||||||
bool is_trailing_edge = (_is_receiving_sync && !this_is_sync);
|
bool is_trailing_edge = (_is_receiving_sync && !this_is_sync);
|
||||||
bool hsync_requested = is_trailing_edge && (_sync_period < (_horizontal_flywheel->get_scan_period() >> 2));
|
bool hsync_requested = is_trailing_edge && (_sync_period < (_horizontal_flywheel->get_scan_period() >> 2));
|
||||||
@ -241,57 +300,55 @@ void CRT::output_scan()
|
|||||||
*/
|
*/
|
||||||
void CRT::output_sync(unsigned int number_of_cycles)
|
void CRT::output_sync(unsigned int number_of_cycles)
|
||||||
{
|
{
|
||||||
_output_mutex->lock();
|
Scan scan{
|
||||||
_scans[_next_scan].type = Type::Sync;
|
.type = Type::Sync,
|
||||||
_scans[_next_scan].number_of_cycles = number_of_cycles;
|
.number_of_cycles = number_of_cycles
|
||||||
output_scan();
|
};
|
||||||
_output_mutex->unlock();
|
output_scan(&scan);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRT::output_blank(unsigned int number_of_cycles)
|
void CRT::output_blank(unsigned int number_of_cycles)
|
||||||
{
|
{
|
||||||
_output_mutex->lock();
|
Scan scan {
|
||||||
_scans[_next_scan].type = Type::Blank;
|
.type = Type::Blank,
|
||||||
_scans[_next_scan].number_of_cycles = number_of_cycles;
|
.number_of_cycles = number_of_cycles
|
||||||
output_scan();
|
};
|
||||||
_output_mutex->unlock();
|
output_scan(&scan);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRT::output_level(unsigned int number_of_cycles)
|
void CRT::output_level(unsigned int number_of_cycles)
|
||||||
{
|
{
|
||||||
_output_mutex->lock();
|
Scan scan {
|
||||||
_scans[_next_scan].type = Type::Level;
|
.type = Type::Level,
|
||||||
_scans[_next_scan].number_of_cycles = number_of_cycles;
|
.number_of_cycles = number_of_cycles,
|
||||||
_scans[_next_scan].tex_x = _buffer_builder->_write_x_position;
|
.tex_x = _buffer_builder->_write_x_position,
|
||||||
_scans[_next_scan].tex_y = _buffer_builder->_write_y_position;
|
.tex_y = _buffer_builder->_write_y_position
|
||||||
output_scan();
|
};
|
||||||
_output_mutex->unlock();
|
output_scan(&scan);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRT::output_colour_burst(unsigned int number_of_cycles, uint8_t phase, uint8_t magnitude)
|
void CRT::output_colour_burst(unsigned int number_of_cycles, uint8_t phase, uint8_t magnitude)
|
||||||
{
|
{
|
||||||
_output_mutex->lock();
|
Scan scan {
|
||||||
_scans[_next_scan].type = Type::ColourBurst;
|
.type = Type::ColourBurst,
|
||||||
_scans[_next_scan].number_of_cycles = number_of_cycles;
|
.number_of_cycles = number_of_cycles,
|
||||||
_scans[_next_scan].phase = phase;
|
.phase = phase,
|
||||||
_scans[_next_scan].magnitude = magnitude;
|
.magnitude = magnitude
|
||||||
output_scan();
|
};
|
||||||
_output_mutex->unlock();
|
output_scan(&scan);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRT::output_data(unsigned int number_of_cycles, unsigned int source_divider)
|
void CRT::output_data(unsigned int number_of_cycles, unsigned int source_divider)
|
||||||
{
|
{
|
||||||
_output_mutex->lock();
|
|
||||||
|
|
||||||
_buffer_builder->reduce_previous_allocation_to(number_of_cycles / source_divider);
|
_buffer_builder->reduce_previous_allocation_to(number_of_cycles / source_divider);
|
||||||
_scans[_next_scan].type = Type::Data;
|
Scan scan {
|
||||||
_scans[_next_scan].number_of_cycles = number_of_cycles;
|
.type = Type::Data,
|
||||||
_scans[_next_scan].tex_x = _buffer_builder->_write_x_position;
|
.number_of_cycles = number_of_cycles,
|
||||||
_scans[_next_scan].tex_y = _buffer_builder->_write_y_position;
|
.tex_x = _buffer_builder->_write_x_position,
|
||||||
_scans[_next_scan].source_divider = source_divider;
|
.tex_y = _buffer_builder->_write_y_position,
|
||||||
output_scan();
|
.source_divider = source_divider
|
||||||
|
};
|
||||||
_output_mutex->unlock();
|
output_scan(&scan);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Buffer supply
|
#pragma mark - Buffer supply
|
||||||
|
@ -292,12 +292,11 @@ class CRT {
|
|||||||
uint8_t phase, magnitude;
|
uint8_t phase, magnitude;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
} _scans[2];
|
};
|
||||||
int _next_scan;
|
void output_scan(Scan *scan);
|
||||||
void output_scan();
|
|
||||||
|
|
||||||
struct CRTRunBuilder {
|
struct CRTRunBuilder {
|
||||||
CRTRunBuilder(size_t vertex_size) : _vertex_size(vertex_size) { reset(); }
|
CRTRunBuilder(size_t vertex_size, int vertices_per_run) : _vertex_size(vertex_size), _vertices_per_run(vertices_per_run) { reset(); }
|
||||||
|
|
||||||
// Resets the run builder.
|
// Resets the run builder.
|
||||||
void reset();
|
void reset();
|
||||||
@ -319,6 +318,7 @@ class CRT {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
size_t _vertex_size;
|
size_t _vertex_size;
|
||||||
|
int _vertices_per_run;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CRTInputBufferBuilder {
|
struct CRTInputBufferBuilder {
|
||||||
@ -355,7 +355,9 @@ class CRT {
|
|||||||
|
|
||||||
// transient buffers indicating composite data not yet decoded
|
// transient buffers indicating composite data not yet decoded
|
||||||
std::unique_ptr<CRTRunBuilder> _composite_src_runs;
|
std::unique_ptr<CRTRunBuilder> _composite_src_runs;
|
||||||
int _composite_src_output_y;
|
uint16_t _composite_src_output_y;
|
||||||
|
uint8_t _colour_burst_phase, _colour_burst_amplitude;
|
||||||
|
uint16_t _colour_burst_time;
|
||||||
|
|
||||||
// OpenGL state, kept behind an opaque pointer to avoid inclusion of the GL headers here.
|
// OpenGL state, kept behind an opaque pointer to avoid inclusion of the GL headers here.
|
||||||
struct OpenGLState;
|
struct OpenGLState;
|
||||||
|
@ -88,16 +88,14 @@ void CRT::CRTRunBuilder::reset()
|
|||||||
|
|
||||||
uint8_t *CRT::CRTRunBuilder::get_next_run()
|
uint8_t *CRT::CRTRunBuilder::get_next_run()
|
||||||
{
|
{
|
||||||
const size_t vertices_per_run = 6;
|
|
||||||
|
|
||||||
// get a run from the allocated list, allocating more if we're about to overrun
|
// get a run from the allocated list, allocating more if we're about to overrun
|
||||||
if((number_of_vertices + vertices_per_run) * _vertex_size >= _runs.size())
|
if((number_of_vertices + (size_t)_vertices_per_run) * _vertex_size >= _runs.size())
|
||||||
{
|
{
|
||||||
_runs.resize(_runs.size() + _vertex_size * vertices_per_run * 100);
|
_runs.resize(_runs.size() + _vertex_size * (size_t)_vertices_per_run * 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *next_run = &_runs[number_of_vertices * _vertex_size];
|
uint8_t *next_run = &_runs[number_of_vertices * _vertex_size];
|
||||||
number_of_vertices += vertices_per_run;
|
number_of_vertices += (size_t)_vertices_per_run;
|
||||||
|
|
||||||
return next_run;
|
return next_run;
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ const size_t kCRTOutputVertexSize = 16;
|
|||||||
const size_t kCRTInputVertexOffsetOfInputPosition = 0;
|
const size_t kCRTInputVertexOffsetOfInputPosition = 0;
|
||||||
const size_t kCRTInputVertexOffsetOfOutputPosition = 4;
|
const size_t kCRTInputVertexOffsetOfOutputPosition = 4;
|
||||||
const size_t kCRTInputVertexOffsetOfPhaseAndAmplitude = 8;
|
const size_t kCRTInputVertexOffsetOfPhaseAndAmplitude = 8;
|
||||||
const size_t kCRTInputVertexOffsetOfPhaseAge = 12;
|
const size_t kCRTInputVertexOffsetOfPhaseTime = 12;
|
||||||
|
|
||||||
const size_t kCRTInputVertexSize = 16;
|
const size_t kCRTInputVertexSize = 16;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user