Москвич-408 — элегантность, ставшая классикой

Тема в разделе "Vulkan", создана пользователем ml64, 25 июл 2026.

  1. Application

    Application Moderator Команда форума

    Публикаций:
    1
    Регистрация:
    8 дек 2007
    Сообщения:
    1.008
    Если называть ЯВУ все что не является ассемблером(например си): на ЯВУ есть свой кайф при программировании.
    Например если твой код не зависит от внешних библиотек/фреймворков это тоже кайф.
     
  2. ml64

    ml64 Member

    Публикаций:
    0
    Регистрация:
    29 окт 2017
    Сообщения:
    89
    А вот тут Intel был ни при чём. Это был типичный ассемблерный ночной баг.
    Нашёл, исправил.

    Мне одному не дают спать Вулкан и ассемблер по ночам?

    RR_07.jpeg
     

    Вложения:

    Последнее редактирование: 12 авг 2026 в 18:16
    Mikl___ и Application нравится это.
  3. GRAFik

    GRAFik Active Member

    Публикаций:
    0
    Регистрация:
    14 мар 2020
    Сообщения:
    541
    Нет я тоже по всем ночам не сплю - всё жду когда вы мне, под мой музейный экспонат процессора, код на MASM64 - для OpenGL напишите. :)
     
  4. ml64

    ml64 Member

    Публикаций:
    0
    Регистрация:
    29 окт 2017
    Сообщения:
    89
    Раз обещал - нехорошо заставлять ждать.
    Вообще я хотел сначала закончить парсер obj -> VBO, а потом перенести его в OpenGL-рамку, но если Вас терзает бессонница, то придётся отвлечься
     
  5. Application

    Application Moderator Команда форума

    Публикаций:
    1
    Регистрация:
    8 дек 2007
    Сообщения:
    1.008
    GRAFik, у вас есть хотябы 1 проект, который вы сами написали и выложили на васме, пусть даже при помощи ллм?
     
  6. Application

    Application Moderator Команда форума

    Публикаций:
    1
    Регистрация:
    8 дек 2007
    Сообщения:
    1.008
    Я бы не отвлекался на этого сетевого хомяка :) Он же вам деньги не платит?
    Какое имеет моральное право критиковать и отвлекать от творчества/лезть не в свое дело?
     
  7. GRAFik

    GRAFik Active Member

    Публикаций:
    0
    Регистрация:
    14 мар 2020
    Сообщения:
    541
    Application, что за менторская манера общения? Модераторская власть что-ли отпечаток накладывает? И на брудершафт мы с вами, вроде, не пили. Так, что повежливее нужно быть с своими зарегистрированными пользователями/форумчанами - их у вас и так, как кот наплакал...
     
  8. ml64

    ml64 Member

    Публикаций:
    0
    Регистрация:
    29 окт 2017
    Сообщения:
    89
    Здесь наши интересы совпадают: мой движок OpenGL основан на технологиях прошлого века (OpenGL 1.0).
    Работать с реальными 3D-моделями он просто не способен. Поэтому мне нужно прикрутить к нему парсер VAO/VBO/EBO.
    Если при этом он кому-то будет полезен, то я только буду рад.
    Vulkan - штука нестабильная и требует наличия библиотеки. OpenGL под Windows запускается из коробки.
    У самурая нет цели, есть только путь. Но я иду в сторону своего IFC-ридера, а возможно, и редактора.
    Мы живём в интересное время.
    Сейчас я один могу делать столько же, сколько 30 лет назад делал весь Autodesk или Graphisoft (в плане разработки, не маркетинга).
    Поэтому мне не жалко написать один модуль, чтобы человеку стало весело.
    Я не гонюсь за авторским правом, потому что всё это придумано не мной и давно написано, я учусь сам и показываю другим людям.
     
    GRAFik и Mikl___ нравится это.
  9. Application

    Application Moderator Команда форума

    Публикаций:
    1
    Регистрация:
    8 дек 2007
    Сообщения:
    1.008
    Имхо, это как дуршлаг водой наполнять. В пустую потраченное время/энергия.
     
  10. ml64

    ml64 Member

    Публикаций:
    0
    Регистрация:
    29 окт 2017
    Сообщения:
    89
    Альтернативное времяпрепровождение - это прикольные видосики в телефоне.
    В лучшем случае просто тупые, в худшем - пропагандистские.
    Я выбрал другой путь. Так узнаю много нового (технологически нового) и держу мозг в тонусе.
    И я не знаю, где пригодятся мои знания в будущем.
    Уже сейчас я держу в руках связку WinAPI-Vulkan-GLSL, причём на чистом ассемблере, без третьих библиотек.
    Считаю матрицы преобразований с помощью AVX и FMA.
    В реальной жизни это мне никогда не пригодится. Почти наверное. Никто даже не знает, что я это умею.
    А что если я по приколу напишу свой мини-Revit, который будет соответствовать ГОСТам?
    Тупо чтобы потроллить Нанософт и Аскон?

    Задача по линии VK и OpenGL сейчас единая - мне нужен парсер obj -> VBO, причём не просто какой-нибудь, а хороший, годный - построенный на векторных инструкциях.
    Когда будет парсер, будет и визуализация
     
    Последнее редактирование: 13 авг 2026 в 03:14
    Mikl___ нравится это.
  11. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    4.279
    ml64,
    мне кажется, что на картинке девочка-подросток с большой грудью или у «Москвича» размер «Чайки»? :yes3:
    размеры«Чайка»«Москвич 408»
    длина5600 мм4090 мм
    ширина2000 мм1550 мм
    высота1620 мм1480 мм
    колёсная база3250 мм2400 мм
     

    Вложения:

    Последнее редактирование: 13 авг 2026 в 09:22
    ml64 нравится это.
  12. ml64

    ml64 Member

    Публикаций:
    0
    Регистрация:
    29 окт 2017
    Сообщения:
    89
    Исправил
    RR_07a.jpeg
     
    Mikl___ и Application нравится это.
  13. GRAFik

    GRAFik Active Member

    Публикаций:
    0
    Регистрация:
    14 мар 2020
    Сообщения:
    541
    А мне дед старые фотографии показывал, когда были в моде "инвалидки", как в старой комедии "самогонщики". Вот такую бы подкрасить, подсветить и с такой девушкой сфотографировать. :)
     
  14. ml64

    ml64 Member

    Публикаций:
    0
    Регистрация:
    29 окт 2017
    Сообщения:
    89
    Самогонщики сами бегали. Причём на лыжах, сквозь берёзу. Мотоколяска была в "Операции "Ы"
     
  15. GRAFik

    GRAFik Active Member

    Публикаций:
    0
    Регистрация:
    14 мар 2020
    Сообщения:
    541
    Точно, именно мотоколяска. У вас нет такой в вашей кодовой базе ? Тогда сразу оформляем спецзаказ, с полной предоплатой. Девушки только могут подвести. Они на такой позор могут не подписаться - ни за какие деньги. :)
     
  16. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    4.279
    GRAFik,
    «Операция Ы» — мотоколяска СМЗ С-3А
    «Кавказская пленница» — немецкий Adler Triumpf Junior 1937 года
     
  17. Application

    Application Moderator Команда форума

    Публикаций:
    1
    Регистрация:
    8 дек 2007
    Сообщения:
    1.008
    Может такое проще на python делать? В асм передавать сконвертированные файлы.
     
  18. ml64

    ml64 Member

    Публикаций:
    0
    Регистрация:
    29 окт 2017
    Сообщения:
    89
    Однозначно - да. На ЯВУ - проще.
    Но cmd = parts(i) - это действия, которые повторяются каждый байт (при каждом проходе):
    1) вычисление адреса parts - это два лишних обращения к памяти:
    lea rax,parts
    add parts,i
    2) весь перебор if cmd == 'v' и др. - это побайтовый опрос.
    Это долго.
    Для "Москвича" это не критично. Но мои объекты - это здания из огромного количества полигонов.
    Здесь нужны векторные возможности процессора, например, VPCMPISTRI
    Эта инструкция поможет определить, есть ли в строке нужные токены, а дальше можно уже по байтам разбирать, как с ними работать.

    Над чем я сейчас работаю:
    Сколько памяти выделить для буфера вершин?
    Можно взять с запасом, но это только для "Москвича" годится.
    Значит, надо считать. Как считать?
    Ищем строки, которые начинаются с "v". Но это могут быть и "v" с пробелом, и "v" с Tab, и "vn", и "vt".
    Как мы ищем? С помощью CMPSB? Нет, конечно.
    CMPSD? Но она сравнивает последовательность байт с последовательностью байт
    Берём VPCMPISTRI. Она сравнивает независимые 16 байт образца с последовательными 16 байтами памяти и ставит флаги, если находит первый совпавший байт.
    Очень удобно искать конец строки, если токен уже отработан или не нужен.

    Это база, а дальше - на любителя.
    Можно первым проходом заменить весь Tab на пробелы, можно удалить ведущие пробелы в начале строк,
    можно этого не делать, а просто посчитать количество токенов каждого типа и под них выделить нужное количество буферной памяти,
    можно идти в лоб и писать сразу в буфер VBO,
    но тогда получится монолитный объект, и я не смогу, например, открывать капот и двери "Москвича"

    Так что ЯВУ - это хорошо, но это не наш метод.
    Если бы я хотел просто и быстро крутить модель, я открыл бы её в SketchUp
    А мне интересен сам механизм.
     
    Последнее редактирование: 13 авг 2026 в 19:08
  19. R81...

    R81... Active Member

    Публикаций:
    0
    Регистрация:
    1 фев 2020
    Сообщения:
    194
    Думал я думал - что это? Даже VPCMPISTRI посмотрел в сети - ничего не понял.
    Код (ASM):
    1. Mov eDi, Начальный Адрес
    2. Mov eCx, Сколько
    3. ClD / StD ; - направление
    4. Mov Al, 'v' ; что
    5. RepNE ScasB
    6. MovZx  eBx, Byte ptr [eDi]
    7. BT  [BitTab], eBx  ; по битмап допустимых после 'v' байт
    8. ??
     
  20. ml64

    ml64 Member

    Публикаций:
    0
    Регистрация:
    29 окт 2017
    Сообщения:
    89
    SCASB обращается к памяти каждый раз. Точнее, сейчас уже Intel это как-то кэширует (именно "как-то", т.к. это делает их тайный микрокод).

    Рассмотрим конкретный пример. Пример возьмём попроще - из широко известного в узких кругах пакета tinyobj_loader - см. вложение.
    Мне нужно узнать, сколько выделять памяти под буфер, т.е. сколько в исходном .obj-файле вершин, нормалей, полигонов, объектов, групп и прочих элементов.
    Моя задача - не найти символ "v" в строке, а подсчитать количество токенов "v", "vn", "vt", "o", "g" и т.д. в двух файлах: "геометрия.obj" и "материалы.mat".
    Причём даже встроенный в 3ds Max конвертер сохраняет данные, мягко говоря, не совсем удобно.
    Он может добавить Tab в начало строки, а может не добавить, он может задать вершины, а только потом объявить токен "o" ("объект"), так, что непонятно, к какому объекту эти вершины потом отнести.

    Мой алгоритм:
    Я беру первый значащий символ в строке, сравниваю его с пробелом, табом, LF, CR, EoF, # (комментарий в формате obj) - для каждого случая свой обработчик.
    Всё. Я определил, что символ значащий, дальше его обрабатываю.
    Если "o", то увеличиваю счётчик объектов, если "v", то увеличиваю счётчик вершин и т.д.

    А теперь представьте, что я для этого использую SCASB.
    1) Мне надо для каждого токена запускать свой цикл сканирования (а если файл 20 мегабайт? Это не редкость для современной графики)
    2) а если v - это не токен, а часть имени объекта, например, o vase - объект "ваза"?

    Сейчас я просто ищу начало строки, беру в ней первый значащий символ и сравниваю байт (или слово) по адресу rcx с ASCII-кодом первого символа токена:
    Код (ASM):
    1. countObjEntities proc
    2. LOCAL pCurrentPosition:QWORD,hHeap:QWORD
    3. LOCAL nObjectIndex:DWORD,nMaterialIndex:DWORD
    4.  
    5. PROLOG 100h
    6.  
    7. ;Set the Local Pointer
    8. mov rcx,gpObjDataStart
    9. mov pCurrentPosition,rcx
    10.  
    11. ;Initialize Counters
    12. mov gnTotalObjects,0
    13. mov gnTotalGroups,0
    14. mov gnTotalSubGroups,0
    15. mov gnTotalVertices,0
    16. mov gnTotalNormals,0
    17. mov gnTotalFaces,0
    18. mov gnTotalMtlLibs,0
    19. mov gnTotalIndices,0
    20.  
    21. ;Initialize Indices
    22. mov nObjectIndex,0
    23.  
    24. lbl_NextLine:
    25.  
    26. mov rcx,pCurrentPosition
    27. cmp rcx,gpObjDataEnd
    28. jge lbl_EndOfFile
    29.  
    30. ;Check for consistency
    31. mov al,byte ptr[rcx]
    32. cmp al,0 ;EOF
    33. je  lbl_EndOfFile
    34. cmp al,9 ;Tab
    35. je  lbl_SkipByte
    36. cmp al,0Ah ;CR
    37. je  lbl_SkipByte
    38. cmp al,0Dh ;LF
    39. je  lbl_SkipByte
    40. cmp al,20h ;Space
    41. je  lbl_SkipByte
    42. cmp al,23h ;# OBJ Format Comment
    43. je  lbl_SkipByte
    44.  
    45. ;Token detection. Arranged by Probability
    46. ;mov rcx,pCurrentPosition
    47. cmp byte ptr[rcx],76h ;"v"
    48. je lbl_TokenStartsWithV
    49. cmp byte ptr[rcx],66h ;"f"
    50. je lbl_TokenFace
    51. cmp dword ptr[rcx],6D657375h ;"usem" in reverse order - part of "usemtl"
    52. je lbl_TokenUseMtl
    53. cmp byte ptr[rcx],6Fh ;"o"
    54. je lbl_TokenObject
    55. cmp byte ptr[rcx],67h ;"g"
    56. je lbl_TokenGroup
    57. cmp dword ptr[rcx],6C6C746Dh; "mtll" in reverse order - part of "mtllib"
    58. je lbl_TokenMtlLib
    59. jmp lbl_SkipByte
    60.  
    61. ;Count object name: o name
    62. lbl_TokenObject:
    63. add pCurrentPosition,2 ;skip "o "
    64. inc gnTotalObjects
    65. jmp lbl_SkipByte
    66.  
    67. ;Count object name: g name
    68. lbl_TokenGroup:
    69. add pCurrentPosition,2 ;skip "g "
    70. inc gnTotalGroups
    71. jmp lbl_SkipByte
    72.  
    73. ;Count material: "usemtl"
    74. lbl_TokenUseMtl:
    75. add pCurrentPosition,7 ;skip "usemtl "
    76. inc gnTotalSubGroups
    77. jmp lbl_SkipByte
    78.  
    79. ;Branch V
    80. lbl_TokenStartsWithV:
    81. inc pCurrentPosition
    82. cmp byte ptr[rcx],6Eh ;"n"
    83. je lbl_TokenNormal
    84. cmp byte ptr[rcx],74h ;"t"
    85. je lbl_TokenTextureCoordinate
    86. ;jmp lbl_TokenVertex ;By default
    87.  
    88. ;Count vertex: v x y z
    89. lbl_TokenVertex:
    90. inc pCurrentPosition ;skip "v "
    91. inc gnTotalVertices
    92. jmp lbl_SkipByte
    93.  
    94. ;Count normal: vn x y z
    95. lbl_TokenNormal:
    96. add pCurrentPosition,2 ;skip "vn "
    97. inc gnTotalNormals
    98. jmp lbl_SkipByte
    99.  
    100. ;Count texture: vt u v w
    101. lbl_TokenTextureCoordinate:
    102. add pCurrentPosition,2 ;skip "vt "
    103. inc gnTotalTextureCoords
    104. jmp lbl_SkipByte
    105.  
    106. ;Count face: f v/vt/vn v/vt/vn v/vt/vn
    107. lbl_TokenFace:
    108. inc pCurrentPosition ;skip "f "
    109. inc gnTotalFaces
    110. jmp lbl_SkipByte
    111.  
    112. ;Count material: "mtllib"
    113. lbl_TokenMtlLib:
    114. add pCurrentPosition,7 ;skip "mtllib "
    115. inc gnTotalMtlLibs
    116. jmp lbl_SkipByte
    117.  
    118. lbl_SkipByte:
    119. mov rcx,pCurrentPosition
    120. cmp rcx,gpObjDataEnd
    121. jge lbl_EndOfFile
    122. mov al,byte ptr[rcx]
    123. cmp al,0 ;EOF
    124. je lbl_EndOfFile
    125. cmp al,0Ah ;LF
    126. je lbl_SkipLF
    127. cmp al,0Dh ;CR
    128. je lbl_SkipCR
    129. inc pCurrentPosition
    130. jmp lbl_SkipByte
    131.  
    132. lbl_SkipCR:
    133. inc pCurrentPosition
    134. mov rcx,pCurrentPosition
    135. cmp byte ptr[rcx],0Ah ;LF
    136. je lbl_SkipLF
    137. jmp lbl_NextLine
    138.  
    139. lbl_SkipLF:
    140. inc pCurrentPosition
    141. jmp lbl_NextLine
    142.  
    143. lbl_EndOfFile:
    144. cmp gnTotalObjects,0
    145. jne @f
    146. LOG_TEXT szErrNoObjects
    147. @@:
    148. cmp gnTotalGroups,0
    149. jne @f
    150. LOG_TEXT szErrNoGroups
    151. @@:
    152. cmp gnTotalSubGroups,0
    153. jne @f
    154. LOG_TEXT szErrNoSubGroups
    155. @@:
    156. cmp gnTotalMtlLibs,0
    157. jne @f
    158. LOG_TEXT szErrNoMtlLibs
    159. @@:
    160. cmp gnTotalVertices,0
    161. jne @f
    162. LOG_TEXT szErrNoVertices
    163. @@:
    164. cmp gnTotalNormals,0
    165. jne @f
    166. LOG_TEXT szErrNoNormals
    167. @@:
    168. cmp gnTotalTextureCoords,0
    169. jne @f
    170. LOG_TEXT szErrNoTextureCoords
    171. @@:
    172. cmp gnTotalFaces,0
    173. jne @f
    174. LOG_TEXT szErrNoFaces
    175. @@:
    176.  
    177. ;Success
    178. mov rax,1
    179. jmp lbl_End
    180.  
    181. lbl_WinError:
    182. call SpellWinError
    183. xor rax,rax
    184. ;jmp lbl_End
    185.  
    186. lbl_End:
    187. EPILOG
    188. countObjEntities endp

    Но это неудобно тем, что я для чтения каждого байта обращаюсь к памяти, гоняю этот несчастный байт по всем шинам и контроллерам.
    SSE предлагает хорошее решение - VPCMPISTRI:
    Я создаю в памяти шаблон поиска - 4, 8 или 16 байт для интересующих меня символов, т.е.
    для поиска начала строки и пропуска пустышек это 10h, 13h, 20h, 9,
    для обработки токенов это ASCII-коды o, g, v, m (первые буквы токенов).
    А дальше - дело техники: xmm0 = шаблон поиска, xmm1 или адрес в памяти - сканируемый участок, imm = маска (ANSI или Unicode и другие настройки).
    Как только VPCMPISTRI встречает в заданном диапазоне любой символ из шаблона, она возвращает в RCX смещение этого символа и устанавливает CF.
    Кстати, если она встречает в заданном диапазоне 0, то устанавливает ZF, что очень важно, т.к. можно проскочить EoF.

    Вот над этим я и работаю:
    массово сканирую в поисках 10h, 13h, 20h, 9, а дальше точечно обрабатываю значимые данные.

    Надеюсь, понятно разложил.
     

    Вложения:

    • cornell_box.zip
      Размер файла:
      797 байт
      Просмотров:
      24
    Последнее редактирование: 14 авг 2026 в 01:34
    R81... и Mikl___ нравится это.