Предел размера OpenGL displayList

Я расскажу об этой проблеме с правилами в «неполном и неполном» проекте стандарта ISO CPP n4659 . Акцент добавлен мной.

11.3.4 определяет объявления массива. Первый абзац содержит

Если присутствует константное выражение [в квадратных скобках] (8.20), оно должно быть преобразованным константным выражением типа std :: size_t [. ..].

blockquote>

std::size_t из и определено как

[...] определяемый реализацией целочисленный тип без знака, который является достаточно большим, чтобы содержать размер в байтах любой объект.

blockquote>

Поскольку он импортируется через заголовки стандартной библиотеки C, стандарт C имеет отношение к свойствам из size_t. Проект ISO C N2176 предписывает в 7.20.3 «минимальные максимумы», если хотите, целочисленных типов. Для size_t этот максимум составляет 65535. Другими словами, 16-битный size_t полностью соответствует.

«Преобразованное константное выражение» определено в 8.20 / 4:

Преобразованное константное выражение типа T является выражением, неявно преобразованным в тип T, где преобразованное выражение является константным выражением, и неявная последовательность преобразования содержит только [любое из 10 различных преобразований, одно из которых касается целых чисел (пар. 4.7):]

- целочисленные преобразования (7.8) , кроме сужения преобразования (11.6.4)

blockquote>

Интегральное преобразование (в отличие от повышения , которое изменяет тип на эквивалентные или более крупные типы) определяется следующим образом (7.8 / 3):

Prvalue целочисленного типа может быть преобразовано в prvalue другого целочисленного типа.

blockquote>

7.8 / 5 затем исключает интегральные продвижения из интегральных преобразований. Это означает, что преобразования обычно сужают изменения типа.

Сужающие преобразования (которые, как вы помните, исключены из списка разрешенных преобразований в преобразованных константных выражениях , используемых для размеров массивов), определены в контексте списка -инициализация, 11.6.4, пар. 7

Сужающее преобразование - это неявное преобразование
[...]
7.3 1 sup> - из целочисленного типа [. ..] к целочисленному типу, который не может представлять все значения исходного типа, за исключением случаев, когда источником является константное выражение, значение которого после интегральных повышений будет соответствовать целевому типу.

blockquote>

Это фактически говорит о том, что эффективный размер массива должен быть постоянным значением при отображении, что является вполне разумным требованием для избежания неожиданностей.


А теперь давайте сделаем это вместе. Рабочая гипотеза состоит в том, что std::size_t представляет собой 16-битный целочисленный тип без знака со значением в диапазоне 0,65535. Целочисленный литерал 65537 не представлен в 16-битной системе unsigned int и поэтому имеет тип long. Поэтому он будет подвергаться целочисленному преобразованию. Это будет сужающее преобразование , потому что значение не представляется в 16-битном size_t 2 sup>, так что условие исключения в 11.6.4 / 7.3, "значение подходит в любом случае ", не применяется.

Итак, что это значит?

11.6.4 / 3.11 - это универсальное правило для сбоя при создании значения инициализатора из элемента в списке инициализатора. Поскольку правила списков инициализаторов используются для размеров массивов, мы можем предположить, что универсальное условие сбоя преобразования применяется к константе размера массива:

(3.11) - В противном случае программа плохо сформирован.

blockquote>

Для создания диагностики требуется соответствующий компилятор, что он и делает. Дело закрыто.


1 sup> Да, они подразделяют абзацы.

2 sup> Преобразование целочисленного значения 65537 (в любом типе, который может содержать число & mdash; здесь, вероятно, `long) в 16-битовое целое число без знака является определенной операцией. 7,8 / 2 подробностей:

Если тип назначения не имеет знака, полученное значение будет являться целочисленным наименьшим числом без знака, совпадающим с целым числом источника (по модулю 2 n sup) > где n - количество битов, используемых для представления типа без знака). [Примечание: в представлении дополнения до двух это преобразование является концептуальным, и в битовой комбинации нет изменений (если нет усечения). - конец примечания]

blockquote>

Двоичное представление 65537 равно 1_0000_0000_0000_0001, то есть установлен только младший значащий бит из младших 16 битов. Преобразование в 16-битное значение без знака (которое указывает косвенное свидетельство size_t) вычисляет [значение выражения] по модулю 2 ^ 16, т. Е. Просто принимает младшие 16 бит. Это приводит к значению 1, указанному в диагностике компилятора.

5
задан DJClayworth 12 February 2009 в 20:47
поделиться

1 ответ

Согласно этой странице документации, при попытке составить список, который является слишком большим, Вы, как предполагается, получаете a GL_OUT_OF_MEMORY сообщение об ошибке.
удостоверьтесь, что Вы звоните glGetError() прежде и после того, как Вы создаете список и обрабатываете все результаты до GL_NO_ERROR возвращается.

Кажется, нет способа оценить количество команд, которые может содержать список. Это, вероятно, потому что каждая команда берет различный размер в зависимости от своих аргументов и устройства определенное используемое кодирование. Списки сохранены в видеопамяти карты поэтому при использовании относительно неархаичной карты, это не должно обычно действительно быть проблемой ни для каких довольно размерных списков. Если Вы действительно находите, что это - действительно проблема, можно, вероятно, использовать массивы Вершины или даже VBOs

4
ответ дан 15 December 2019 в 01:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: