diff --git a/DagorEngine.rev.txt b/DagorEngine.rev.txt index dbdc4852d..c17482993 100644 --- a/DagorEngine.rev.txt +++ b/DagorEngine.rev.txt @@ -1 +1 @@ -e1b257771f10be67b195ae0de780d15028763dc3 +d82f2aef2d76258d84c43cd2bcd4b0444570b104 diff --git a/_docs/_static/custom.css b/_docs/_static/custom.css index 4a14691b0..d026a072d 100644 --- a/_docs/_static/custom.css +++ b/_docs/_static/custom.css @@ -53,4 +53,23 @@ p { margin-bottom: 14px; } +/* Customization for icon-style numbering of menu items or objects in a picture +for use in text */ + +.sd-badge { + /* display: inline-block; */ + padding: .25em .55em; + font-size: .8em; + font-weight: 700; + line-height: 1; + text-align: center; + white-space: nowrap; + vertical-align: middle; + border-radius: .5rem; +} + +.sd-outline-dark { + border-width: 0.15em !important; +} + diff --git a/_docs/source/dagor-tools/resource-building/_images/res_build_01.png b/_docs/source/dagor-tools/resource-building/_images/res_build_01.png deleted file mode 100644 index 15b1125ed..000000000 Binary files a/_docs/source/dagor-tools/resource-building/_images/res_build_01.png and /dev/null differ diff --git a/_docs/source/dagor-tools/resource-building/_images/resource_building_01.jpg b/_docs/source/dagor-tools/resource-building/_images/resource_building_01.jpg new file mode 100644 index 000000000..f32e92d57 Binary files /dev/null and b/_docs/source/dagor-tools/resource-building/_images/resource_building_01.jpg differ diff --git a/_docs/source/dagor-tools/resource-building/index.rst b/_docs/source/dagor-tools/resource-building/index.rst index 64440cea1..961965ce5 100644 --- a/_docs/source/dagor-tools/resource-building/index.rst +++ b/_docs/source/dagor-tools/resource-building/index.rst @@ -1,15 +1,12 @@ + Resource Building ========================================= -Resource building refers to the process of packaging all game resources: models, -textures, levels, configurations, and game logic into binary files. - -Contents: - .. toctree:: :maxdepth: 2 - :glob: + :caption: Contents: resource_building.md vromfs.md + diff --git a/_docs/source/dagor-tools/resource-building/resource_building.md b/_docs/source/dagor-tools/resource-building/resource_building.md index 502c6925a..17764dbea 100644 --- a/_docs/source/dagor-tools/resource-building/resource_building.md +++ b/_docs/source/dagor-tools/resource-building/resource_building.md @@ -14,34 +14,39 @@ fetched, decompressed, and the required information is extracted from them. This article provides an overview of how to build assets, levels, and settings. -# Parameters in .folder.blk Affecting the Building Process +## Parameters in .folder.blk Affecting the Building Process -Resource building is governed by the rules defined in `.folder.blk` files. For -more details about `.folder.blk`, read -[here](../../assets/all-about-blk/folder_blk.md). For instance, the following -block specifies compression parameters for `.tiff` textures. +Resource building is governed by the rules defined in `.folder.blk` files. +```{seealso} +For more information, see +[.folder.blk](../../assets/all-about-blk/folder_blk.md). ``` + +For example, the following block specifies compression parameters for `.tiff` +textures. + +```text virtual_res_blk{ - find:t="^(.*)\.tiff$" // search for any .tiff files - className:t="tex" // assign the "texture" class - contents{ // processing details - convert:b=yes;fmt:t="DXT1|DXT5" // convert; use DXT1 or DXT5 format (if alpha is present) + find:t="^(.*)\.tiff$" // search for any .tiff files + className:t="tex" // assign the "texture" class + contents{ // processing details + convert:b=yes;fmt:t="DXT1|DXT5" // convert; use DXT1 or DXT5 format (if alpha is present) mipFilter:t="filterKaiser";mipFilterAlpha:r=40;mipFilterStretch:r=2 // mipmap compression using - // the Kaiser filter (sharpens); with two parameters - addrU:t="wrap";addrV:t="wrap" // define texture tiling behavior, wrap = repeat for repeating textures. - hqMip:i=0;mqMip:i=1;lqMip:i=2 // define the displayed mip level based on graphics quality; - // hq (high quality) uses the original texture, - // mq uses mip level 1 (50% compression), lq uses mip level 2 (75% compression). + // the Kaiser filter (sharpens); with two parameters + addrU:t="wrap";addrV:t="wrap" // define texture tiling behavior, wrap = repeat for repeating textures. + hqMip:i=0;mqMip:i=1;lqMip:i=2 // define the displayed mip level based on graphics quality; + // hq (high quality) uses the original texture, + // mq uses mip level 1 (50% compression), lq uses mip level 2 (75% compression). } } ``` -There are numerous such processing blocks. Below, we’ll examine the key ones. +There are numerous such processing blocks. Below, we'll examine the key ones. ## Global Export Parameters -``` +```text export{ package:t="*" // Specify the package to which the asset will be built // (a package is the highest level of asset grouping) @@ -64,21 +69,21 @@ export{ } ``` -These are just a few examples. Let’s delve into the primary parameters. +These are just a few examples. Let's delve into the primary parameters. -# About Packs and Packages +## About Packs and Packages The hierarchy of resources can be illustrated as follows: -![Hierarchy of Resources](_images/res_build_01.png) +Hierarchy of Resources In essence, a project can contain several packages, and each package can include multiple packs. -## What Is a "Package"? +### What Is a "Package"? A *package* typically serves as a container for resources that we want to -distribute to or remove from the player's environment. For instance, we might +distribute to or remove from the player's environment. For example, we might bundle a specific location and its assets into a package for a particular event. Players download it, enjoy the event for a week, and once the event concludes, the package is removed from their resources. @@ -88,9 +93,12 @@ players to download 20 GB of resources upfront, they can start with a minimal setup and quickly get into the game. Later, they can purchase additional content and download the necessary data from the relevant package. -See more details about packages [here](packages.md). +```{seealso} +For more information, see +[Packages](./packages.md). +``` -## What Is a "Pack"? +### What Is a "Pack"? A *pack* is a component of a package where the assets are actually built. The logic for dividing assets into packs is straightforward: @@ -109,7 +117,7 @@ If a pack becomes too large, we break it down into smaller groups. For example, vehicles could be further divided into packs such as `buses`, `trucks`, and `cars`. -# Local Build +## Local Build When you create a new asset, it needs to be tested locally in the game. The local client, like the player's client, only understands built resources, so @@ -123,12 +131,12 @@ There are three types of builds: and efficient. 3. **Partial Package Build**: Builds an entire package (a set of packs). Although this is a longer process, it can be more convenient in some cases, - such as in *daNetGame-based* games, where packaging the resources this way + such as in *daNetGame*-based games, where packaging the resources this way might be preferable to building individual packs. -# Local Full daBuild +## Local Full daBuild -[*daBuild*](../daeditor/daeditor/daeditor.md) is a program executed via the +The [*daBuild*](../daeditor/daeditor/daeditor.md) is a program executed via the `dabuild.cmd` batch file. ```{important} @@ -137,7 +145,7 @@ you only need to build a single resource for quick testing, use `dabuild_test.bat` instead. ``` -## Building and Errors +### Building and Errors In theory, all assets should be error-free. However, asset management initially relied heavily on manual checks, leading to human error and allowing issues to @@ -154,14 +162,14 @@ file command to allow *daBuild* to continue building all resources while logging the errors. ```{note} -This flag should not be used to ignore errors. The build process for specific -assets will still be interrupted, but it will move on to the next asset in the -pack rather than stopping at the first error. Once you've collected error data, -fix the assets and run the build without this flag to ensure that *daBuild* -completes successfully without issues. +The `-keep_building_after_error` flag should not be used to ignore errors. The +build process for specific assets will still be interrupted, but it will move on +to the next asset in the pack rather than stopping at the first error. Once +you've collected error data, fix the assets and run the build without this flag +to ensure that *daBuild* completes successfully without issues. ``` -## Local Pack Build +### Local Pack Build ```{important} Building packs with *daBuild* will compile all packs matching a specified @@ -183,7 +191,7 @@ be named `main_vehicles`. To build a specific pack, open `dabuild_test.bat` in any text editor, and you will see a line like this: -``` +```text ..\..\tools\dagor3_cdk\bin64\dabuild-dev.exe -target:PC ..\application.blk -packs_re:usa_gm -Q ``` @@ -191,72 +199,72 @@ Replace `usa_gm` with the name of the pack you need to build. The pack is determined by the nearest `.folder.blk` file to the asset, containing lines like: -``` +```text export{ ddsxTexPack:t="gm_lvl_assets.dxp.bin" gameResPack:t="gm_lvl_assets.grp" } ``` -`gm_lvl_assets` is an example of the pack name into which the resources will be -built. It may vary – refer to your specific setup. +The `gm_lvl_assets` is an example of the pack name into which the resources will +be built. It may vary – refer to your specific setup. ```{important} Notice that there are two types of packs: -1. `ddsxTexPack` - Exports textures. -2. `gameResPack` - Exports models. -It's possible for textures to be exported to one pack and models to another. For -example: +- `ddsxTexPack`: Exports textures. +- `gameResPack`: Exports models. -``` -export{ - ddsxTexPack:t="gm_lvl_assets.dxp.bin" - gameResPack:t="locations.grp" -} -``` +It's possible for textures to be exported to one pack and models to another. +For example: + + ``` + export{ + ddsxTexPack:t="gm_lvl_assets.dxp.bin" + gameResPack:t="locations.grp" + } + ``` You need to build the packs corresponding to the resources you've modified. If you've changed textures, build the texture pack. If you've changed models, build the model pack. If both were changed, build both packs. ``` -# Local Package Build +## Local Package Build Unlike packs, packages are more comprehensive and refer to self-contained -volumes of resources that can be enabled or disabled with a "toggle." +volumes of resources that can be enabled or disabled with a "toggle". For example, in *War Thunder*: -- `pkg_main` (or simply `*`) - The default package where all assets are - exported. -- `pkg_dev` - Contains assets that should be built but not distributed to +- `pkg_main` (or simply `*`): The default package where all assets are exported. +- `pkg_dev`: Contains assets that should be built but not distributed to players. -- `tomoe` - A package for modifying certain symbols in countries where their +- `tomoe`: A package for modifying certain symbols in countries where their original form is prohibited. - Event packages are also occasionally used. -In *daNetGame-based* games, each location is its own package, which can be +In *daNetGame*-based games, each location is its own package, which can be distributed to players independently. In a `.folder.blk` file, the package entry looks like this: -``` +```text export{ package:t="tomoe" } ``` In *War Thunder*, local package builds are not common, as there are few -packages, and packs are usually built instead. However, in *daNetGame-based* +packages, and packs are usually built instead. However, in *daNetGame*-based games, this is an extremely useful feature. There are two options for such builds. -## Option 1 - Building a Specific Package +### Option 1: Building a Specific Package In the `daBuild` batch file, write: -``` +```text ..\..\tools\dagor3_cdk\bin64\dabuild-dev.exe -target:PC ..\application.blk -package:package_name -Q ``` @@ -276,15 +284,16 @@ updated. To avoid this, you should either: -- Sequentially build both packages using one batch file: - +- sequentially build both packages using one batch file: `-package:package_name -package:package_name_hq` -- Or create two separate batch files: one for the main resource package (non-HQ +or + +- create two separate batch files: one for the main resource package (non-HQ textures) and another specifically for HQ textures. ``` -## Option 2 - Building a Specific Package and Its Dependencies +### Option 2: Building a Specific Package and Its Dependencies In *daNetGame-based* games, packages often have cross-references. When something changes in a "common" package, you need to ensure that everything works @@ -294,24 +303,30 @@ its dependent packages, which is much faster. To do this, write the following in the `daBuild` batch file: -``` +```text ..\..\tools\dagor3_cdk\bin64\dabuild-dev.exe -target:PC ..\application.blk -package_and_deps:package_name -Q ``` -`package_and_deps` refers to the package and its dependencies. +The `package_and_deps` refers to the package and its dependencies. -# Toggling Packages in settings.blk +## Toggling Packages in settings.blk Occasionally, you may need to enable or disable packages to test specific -scenarios (for instance, disabling a package to verify that the game runs -without it). This is configured in the `settings.blk` file. For all projects, -after modifying the package list, you must rebuild the [`.vromfs.bin`](vromfs.md) -files. +scenarios (for example, disabling a package to verify that the game runs without +it). This is configured in the `settings.blk` file. + +```{seealso} +For more information, see +[settings.blk](../../assets/all-about-blk/config_and_settings_blk). +``` + +For all projects, after modifying the package list, you must rebuild the +[`.vromfs.bin`](vromfs.md) files. In *War Thunder*, packages are enabled or disabled in the file located at -`engine_root\skyquake\develop\gameBase\_pc\settings.blk`: +`//develop/gameBase/_pc/settings.blk`: -``` +```text addons{ folder:t = "content.hq/hq_tex" folder:t = "content.hq/pkg_cockpits" @@ -354,24 +369,31 @@ disabling packages within the game; it does not handle the creation of packages. The requirement for a package to be built by *daBuild* is defined in the `application.blk` file within the `packages{}` block. -# Local Build of a Specific Asset +```{seealso} +For more information, see +[application.blk](../../assets/all-about-blk/application_blk.md). +``` + +## Local Build of a Specific Asset The `daBuild` command with the `-build:[:]` parameter allows you to build a single asset into the specified file. This command does not update packages, meaning the updated asset will not be added to any package. -# Local Resource Build in Asset Viewer +## Local Resource Build in Asset Viewer -Resources can also be built using the *Asset Viewer*, which often speeds up the -process since `daBuild` via batch files can sometimes lag unpredictably. +Resources can also be built using the [*Asset +Viewer*](../asset-viewer/asset-viewer/asset_viewer.md), which often speeds up +the process since `daBuild` via batch files can sometimes lag unpredictably. -For instructions on how to build using *Asset Viewer*, refer to the -documentation -[here](../asset-viewer/asset-viewer/asset_viewer.md#building-assets). +```{seealso} +For more information on how to build using *Asset Viewer*, see +[Asset Viewer: Building Assets](../asset-viewer/asset-viewer/asset_viewer.md#building-assets). +``` -# Local Vromfs Build +## Local Vromfs Build -VROMFS stands for "Virtual Read-Only Memory File System". Essentially, +*VROMFS* stands for "Virtual Read-Only Memory File System". Essentially, [vromfs](vromfs.md) files are the "virtual configuration disk" for our game. They contain all the game's operational settings that aren't hard-coded. @@ -386,11 +408,11 @@ following line in the `debug{}` block: `offlineBinaries:b=yes`. Alternatively, you can use `disableNetwork:b=yes` if network features are irrelevant to you. For added security, you might want to include both. -## Methods to Build Vromfs +### Methods to Build Vromfs 1. **Using `create_vrsroms.bat`** - - Located in the `engine_engine_root\\develop\gameBase` directory. - This method is useful because it immediately indicates if there’s an issue + - Located in the `//develop/gameBase` directory. + This method is useful because it immediately indicates if there's an issue with the settings by throwing an error. Additionally, it provides a local log (`log_vrom`) in the same directory, which helps you identify and resolve any problems. @@ -398,50 +420,50 @@ For added security, you might want to include both. 2. **Using `aces_dev.exe`** - Technically, this tool does not build vromfs. However, if you have `vromfsPriority:b=no` set in the `debug{}` block of your `config.blk`, all - configuration files will be read directly from `develop\gameBase` instead + configuration files will be read directly from `develop/gameBase` instead of from vromfs. This approach offers several advantages: there's no need to wait for vromfs building after each change, and errors are logged in a more readable format. Additionally, this method allows you to add the powerful `trackEnvChanges:b=yes` line to your `config.blk`, enabling you to tweak - settings directly in-game. Although this doesn’t work for all settings, - it’s particularly helpful for adjusting weather or visual elements, as you + settings directly in-game. Although this doesn't work for all settings, + it's particularly helpful for adjusting weather or visual elements, as you can see the changes in real-time without restarting the client. Choose the method based on your experience. The in-game approach might be less convenient, but sometimes it's essential to ensure everything behaves exactly as it would in production. -# Local Build of Resources and Vromfs in the open daEditor and Client +## Local Build of Resources and Vromfs in the open daEditor and Client You can build resources and [vromfs](vromfs.md) while the -[*daEditor*](../daeditor/index.rst) is open (though resource building might -cause the *daEditor* to crash). +[*daEditor*](../daeditor/daeditor/daeditor.md) is open (though resource building +might cause the *daEditor* to crash). However, resources and vromfs cannot be built while the client is open. -If you find that resources aren’t building after you’ve closed the client – or -they seem to build, but the changes aren’t reflected in-game – open the Task +If you find that resources aren't building after you've closed the client – or +they seem to build, but the changes aren't reflected in-game – open the Task Manager and terminate any lingering `aces_dev.exe` processes. -# Local Level Export +## Local Level Export -If you’re developing in-game vehicles that are loaded via missions, you can skip +If you're developing in-game vehicles that are loaded via missions, you can skip this section. -However, if you’re creating objects for maps, you’ll need to place them on the +However, if you're creating objects for maps, you'll need to place them on the map and export the level to test them in-game. This process is done via the -*daEditor*. +[*daEditor*](../daeditor/daeditor/daeditor.md). Level export is necessary when: -- You’re working with prefabs. Prefabs are only included in the game during +- You're working with prefabs. Prefabs are only included in the game during level re-export. -- You’ve added a new asset that wasn’t previously on the level or removed +- You've added a new asset that wasn't previously on the level or removed something from the location. - Something has changed in object generation, and their placement needs to be updated. -If you’re only modifying render instances or textures, there’s no need to +If you're only modifying render instances or textures, there's no need to re-export the level – doing so would just waste time. Once you have placed all your objects, save the level and follow these steps: diff --git a/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_01.jpg b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_01.jpg new file mode 100644 index 000000000..7d9179333 Binary files /dev/null and b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_01.jpg differ diff --git a/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_02.jpg b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_02.jpg new file mode 100644 index 000000000..9e7f7c7bb Binary files /dev/null and b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_02.jpg differ diff --git a/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_03.jpg b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_03.jpg new file mode 100644 index 000000000..5e7e9e535 Binary files /dev/null and b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_03.jpg differ diff --git a/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_04.jpg b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_04.jpg new file mode 100644 index 000000000..57ca83a64 Binary files /dev/null and b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_04.jpg differ diff --git a/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_05.jpg b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_05.jpg new file mode 100644 index 000000000..1ad30329e Binary files /dev/null and b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_05.jpg differ diff --git a/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_06.jpg b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_06.jpg new file mode 100644 index 000000000..f45c59b50 Binary files /dev/null and b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_06.jpg differ diff --git a/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_07.jpg b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_07.jpg new file mode 100644 index 000000000..fd1b2b557 Binary files /dev/null and b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_07.jpg differ diff --git a/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_08.jpg b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_08.jpg new file mode 100644 index 000000000..e743e647f Binary files /dev/null and b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_08.jpg differ diff --git a/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_09.jpg b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_09.jpg new file mode 100644 index 000000000..960a81186 Binary files /dev/null and b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_09.jpg differ diff --git a/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_10.jpg b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_10.jpg new file mode 100644 index 000000000..a3a82f943 Binary files /dev/null and b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_10.jpg differ diff --git a/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_11.jpg b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_11.jpg new file mode 100644 index 000000000..83536d7a3 Binary files /dev/null and b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_11.jpg differ diff --git a/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_12.jpg b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_12.jpg new file mode 100644 index 000000000..b4b98c177 Binary files /dev/null and b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_12.jpg differ diff --git a/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_13.jpg b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_13.jpg new file mode 100644 index 000000000..596ddce61 Binary files /dev/null and b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_13.jpg differ diff --git a/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_14.jpg b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_14.jpg new file mode 100644 index 000000000..b3b66c23f Binary files /dev/null and b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_14.jpg differ diff --git a/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_15.jpg b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_15.jpg new file mode 100644 index 000000000..8d2efcc81 Binary files /dev/null and b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_15.jpg differ diff --git a/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_16.jpg b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_16.jpg new file mode 100644 index 000000000..3a28728c0 Binary files /dev/null and b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_16.jpg differ diff --git a/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_17.jpg b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_17.jpg new file mode 100644 index 000000000..6475adc3c Binary files /dev/null and b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_17.jpg differ diff --git a/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_18.jpg b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_18.jpg new file mode 100644 index 000000000..17e114f67 Binary files /dev/null and b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_18.jpg differ diff --git a/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_19.jpg b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_19.jpg new file mode 100644 index 000000000..a46682750 Binary files /dev/null and b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_19.jpg differ diff --git a/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_20.jpg b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_20.jpg new file mode 100644 index 000000000..49edf6c1f Binary files /dev/null and b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_20.jpg differ diff --git a/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_21.jpg b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_21.jpg new file mode 100644 index 000000000..3b054ae2d Binary files /dev/null and b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_21.jpg differ diff --git a/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_22.jpg b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_22.jpg new file mode 100644 index 000000000..a0192cc67 Binary files /dev/null and b/_docs/source/tutorials/dng-non-human-char/_images/dng_non_human_char_22.jpg differ diff --git a/_docs/source/tutorials/dng-non-human-char/dng_non_human_char.md b/_docs/source/tutorials/dng-non-human-char/dng_non_human_char.md new file mode 100644 index 000000000..f823ab057 --- /dev/null +++ b/_docs/source/tutorials/dng-non-human-char/dng_non_human_char.md @@ -0,0 +1,910 @@ +# Non-Human Character: Step-by-Step Guide + +## General Guidelines for Creating Creatures of All Types + +The *Dagor Engine* supports creating any bone-animated object (character). +However, this guide focuses on simple examples that do not involve IK (Inverse +Kinematics), upper or lower body animations, complex animation blending, or +additive animations. After reading this guide, you will be able to create +characters with any number of limbs. Additionally, we will set up animation +states for smooth transitions between character animations. + +## Example Scenes in 3ds Max + +You can download scenes with models properly prepared for export: +{download}`3dsMax2024Files.zip ` + +## Examples in Dagor Engine + +These examples are designed for use in *daNetGame*-based projects. The files +include ready-to-use game assets: a fish and a crow. Compatibility with *War +Thunder* has not been tested due to shader-related issues. + +Download the archive: +{download}`creatures.zip ` + +Extract the files into the `dev` directory of your project (a testing directory +not included in the game build). For example, +`//develop/assets/dev/gameRes/`. After extraction, +the path should look like this: +`//develop/assets/dev/gameRes/creatures`. + +If everything is set up correctly, loading the [*Asset +Viewer*](../../dagor-tools/asset-viewer/asset-viewer/asset_viewer.md) and +selecting the crow asset {bdg-dark-line}`1` will result in error-free loading. +Click {bdg-dark-line}`2` to review error logs. The highlighted section indicates +successful loading. + + + +```{note} +Scenes are compatible with *3ds Max 2024* or later. +``` + +## Skeleton Bone Structure: Features and Scene Configuration + +Let's analyze the crow scene. Open the file {bdg-dark-line}`0` +`crow_detailed_tpose.max`. + + + +Make sure to specify in the file name that it is the character's T-pose. The +model must include a root bone {bdg-dark-line}`3`. The naming is flexible, but +if you plan to use existing `.blk` files as templates, it is better to name it +`root`. This bone is used to move the entire scene. Additionally, a `Body` bone +{bdg-dark-line}`4` must be defined. + +```{seealso} +For more information, see +[.blk File Format](../../dagor-tools/blk/blk.md). +``` + +For complex models with separate upper and lower animations, different +animations may play simultaneously based on specific events. In such cases, bone +names must clearly indicate their purpose for programmers. In this example, the +same animation always applies to all bones, so `Body` directly follows `root`. +This will become crucial when defining properties for generating animation +dependencies. + +```{note} +For more complex characters, the structure may involve actions like running +while rotating the torso and looking at the camera. Such setups require advanced +configurations, which are beyond the scope of this guide. Here, we focus on a +simpler and more straightforward task. +``` + +The *3ds Max* scene must include the following mandatory features: + +- **LODs** (Level of Detail) {bdg-dark-line}`2` must be named consistently, + e.g., `LOD00` {bdg-dark-line}`1`. Inconsistent names across LODs will cause + errors during the [*Asset + Viewer*](../../dagor-tools/asset-viewer/asset-viewer/asset_viewer.md) resource + loading. While *3ds Max* discourages identical names for objects, *Dagor + Engine* requires this convention. To distinguish objects, place them in layers + named according to their LOD levels, as shown in the example above. + +- For the **Skin modifier**, always disable **Dual Quaternion** + {bdg-dark-line}`6` and set the number of points per bone {bdg-dark-line}`5` to + match the configuration specified in the project's `application.blk`. Refer to + the **Skin Parameters in Dagor** section for more details: [Working with the + Skin Modifier](#working-with-the-skin-modifier). + + ```{seealso} + For more information, see + [application.blk](../../assets/all-about-blk/application_blk.md). + ``` + +- Store skinned objects as **Editable Mesh** {bdg-dark-line}`7` to ensure point + weights accurately reflect in *Dagor* after export. These steps help replicate + the Skin modifier's behavior in *Dagor* precisely. + +- Use **Selection Sets** {bdg-dark-line}`8` for easier object selection during + export. For instance, to export `LOD00`, create a group named `lod00` + containing all the scene bones and all objects from the `LOD00` layer. + +Each bone in the scene must include **Custom Properties** so that the *Dagor* +identifies them as bones. Below is the minimum required configuration for the +crow skeleton: + +```text +animated_node:b=yes // Specifies the object is animated +collidable:b=no // Disables all collisions +massType:t="none" // No mass, but the object is physical +renderable:b=no // Excluded from rendering +cast_shadows:b=no // Excluded from shadow generation +``` + +## Adding Basic Physics + +To initialize the scene properly in *Dagor*, assign physical properties to at +least one bone using **Custom Properties** {bdg-dark-line}`2`. + + + +Without physics, the engine cannot generate a valid skeleton. Below is an +example configuration for the `head` bone {bdg-dark-line}`1`: + +```text +animated_node:b=yes // Specifies the object is animated +collidable:b=no // Enables collision handling, though further settings are required +massType:t="box" // Specifies the mass calculation type +collision:t=capsule // Specifies the collision type; consult your mentor for alternatives +physObj:b=yes // Enables physics for the object +density:r=2000 // Density for mass calculation +renderable:b=no // Excluded from rendering +cast_shadows:b=no // Excluded from shadow generation +``` + +```{seealso} +For more information, see +[Rigging, Skinning, and Exporting New Character](../dng-rig-skin-export-new-char.md/dng_rig_skin_export_new_char.md). + +Download example files to review the custom properties of bones like `Bip*`. +These properties dictate how the physical skeleton is generated. +``` + +## Working with the Skin Modifier + +The most critical aspect of working with the **Skin** modifier is controlling +the number of bones per vertex. By convention, this value is set to 4 bones per +vertex. This parameter is defined in the project's general configuration file, +`application.blk`. Other required settings have already been covered earlier. + +Example configuration in `application.blk`: + +```text +dynModel{ + descListOutPath:t="dynModelDesc" + separateModelMatToDescBin:b=yes + + ignoreMappingInPrepareBillboardMesh:b=yes + enableMeshNodeCollapse:b=no + maxBonesCount:i=318 // This is ineffective! Shader limitations cap bone count at 200. + // Exceeding 200 will result in errors during daBuild. + setBonePerVertex:i=4 // Number of bones per vertex +} +``` + +## Creating LODs: Special Considerations for Dynamic Models + +The primary rule for creating LODs is ensuring consistent naming for all LOD +levels. Using the crow as an example: + + + +As shown, LODs share the same base name but are placed in separate layers. Each +LOD may contain multiple skinned objects. This approach is useful, especially +when the total triangle count for a single object exceeds the limit of 65,000 +triangles. If your model exceeds this limit, divide it into multiple pieces. + +For each model with a **Skin** modifier, the following **Custom Properties** +must be added: + +```text +animated_node:b=yes // Specifies the object is animated +collidable:b=no // Disables all collisions +massType:t="none" // Indicates no physical mass for this object +``` + +Ensure all skinned objects {bdg-dark-line}`1` have the specified properties +{bdg-dark-line}`2`: + + + +For efficient management of **Custom Properties**, use an editor or viewer tool. + +```{seealso} +For more information, see +[*Dagor 2 Fast Editor User Properties*](../../dagor-tools/addons/3ds-max/dagor2-3ds-max-tools/fast_editor_user_properties.md). +``` + +## Materials for Dynamic Models + +Let's examine the materials assigned to the skinned models in the scene. In this +case, the materials used are `crow_base` and `Dagor Dagorrat Material 2` +{bdg-dark-line}`0`. To view all available **dynamic materials**, open the +dropdown menu and navigate to the relevant section {bdg-dark-line}`1`. + +While each material type requires dedicated documentation, we will focus on the +simplest and most versatile option for +[PBR](https://en.wikipedia.org/wiki/Physically_based_rendering) lighting: +**dynamic_simple** {bdg-dark-line}`2`. This material supports standard textures +such as **albedo** (with optional transparency), **normal**, **smoothness**, and +**metalness** maps. In this case, the textures are: +- `crow_body_a_tex_d.tif` (albedo) +- `crow_body_a_tex_n.tif` (normal map) + +If the archive was unpacked correctly, these textures can be found at the +following path: +`//enlisted/develop/assets/dev/gameRes/creatures/characters/crow`. + +Assign the textures to the appropriate slots {bdg-dark-line}`3`. To enable +transparency, add the **atest** property {bdg-dark-line}`4` and set its value +{bdg-dark-line}`5` to `127`. This controls the alpha test threshold, where +mid-level brightness determines transparency. Also, enable two-sided rendering +{bdg-dark-line}`6`, as crow feathers must be rendered on both sides. + +:::{grid} 2 + + +::: + +Verify that this material is applied to all skinned objects before proceeding +with export. + +## Exporting the Dynamic Model + +If the **selection sets** {bdg-dark-line}`1` were prepared correctly earlier, +exporting is straightforward. In the crow scene, select the set named `lod00` +{bdg-dark-line}`2`. This action highlights the `LOD00` layer and all associated +bones. + + + + + +Next, navigate to **Utilities**, and choose **Dagor Scene Export**. If this +option is unavailable, add it using the **Sets** button. Within the **Dagor +Export** settings, ensure the following options are enabled: +- **Export hidden objects** +- **Export selected objects only** + +These options are essential for every export. Finally, click **Export DAG**. + +### Important Naming Conventions + +The *Dagor* legacy constraints require specific naming conventions. The files +extracted from the `creatures.zip` archive must follow this format to maintain +compatibility with `.blk` scripts and project building pipelines. + +For dynamic models: +- Append the postfix `_dynmodel`. +- Specify the LOD using the `.lodXX` postfix, where `XX` is the LOD level. + +For example, the crow model's most detailed LOD(00) should be named as crow_detailed_a_dynmodel.lod00.dag. + +- **Green text**: Customizable according to your naming needs. +- **Red text**: Fixed and mandatory to ensure correct processing during build + and to define the LOD number. + +```{note} +Post-export, you may encounter errors like: + + +These errors occur because bones lack assigned **Dagor** materials. Assigning +materials does not resolve this issue; it can be safely ignored. +``` + +Repeat the export process for the other two LODs, naming them: +- `crow_detailed_a_dynmodel.lod01.dag` +- `crow_detailed_a_dynmodel.lod02.dag` + +Once the export is complete, verify the model in the [*Asset +Viewer*](../../dagor-tools/asset-viewer/asset-viewer/asset_viewer.md) by +selecting `crow_lo_a_dynmodel` {bdg-dark-line}`1`: + + + +If everything was done correctly, the model should load without errors. + +## Exporting Animation + +In essence, animation is simply a record of the bone movements associated with a +model. + +```{important} +- **Bone Count, Naming, and Hierarchy:** These must match exactly between the + dynamic model and the animation file. +- Any mismatch can result in odd animation hierarchies or failure to display the + animation altogether. +``` + +Open the file `crow_detailed_idle_b.max`, which contains the animation for idle +movements. Select all bones in the scene; there should be **195 selected +objects**, including all Helpers. + +In the **Dagor Export** panel, ensure the following: +1. Enable the **Export selected objects only** button {bdg-dark-line}`1`. +2. Explicitly set the animation key range for export {bdg-dark-line}`2`, from + **frame 0 to 150**. + + + +```{note} +The animation range displayed on the timeline **is irrelevant** for export. You +must manually specify the key range in the export settings. +``` + +Enabling the checkboxes {bdg-dark-line}`4` significantly increases animation +precision, which is essential in this case to prevent visual errors such as +"sliding" feet. + +```{note} +Exporting the animation with high precision increases the file size by hundreds +of times. Use this option only when it is really necessary. +``` + +Without these checkboxes, animations are compressed hierarchically, accumulating +minor errors over time. This can cause noticeable visual discrepancies. Enabling +high precision minimizes these errors, ensuring smoother playback. + +Leave the **scaling checkbox** unchecked if there is no scaling animation in the +scene (as in this crow example). + +Click the **Export Animation** button {bdg-dark-line}`3`. + +Naming and location conventions for animation files are similar to those for +dynamic models: +- Store animations in: + `//develop/assets/dev/gameRes/creatures/animation/crow` +- Use the `.a2d` extension. +- Naming guidelines: + - Use the same base name as the dynamic model but omit LOD-related or + dynamic-model-specific postfixes. + - Avoid key script processor keywords in the filename (e.g., dynamic-related + terms). + +In this example, save the animation as: `crow_detailed_idle_b.a2d`. + +Next to this file, there should also be a configuration file named: +`crow_detailed_idle_b.a2d.blk`. + +This file contains individual properties and settings for the animation. + +**Example:** + +```text +name:t="crow_detailed_idle_b.a2d" // Name of the animation linked to this script +opt:b=no // Conservative optimization disabled. +posEps:r=0.001 // Position compression accuracy during project build. + // Higher values (e.g., 0.1 > 0.01) reduce file size but decrease accuracy. +rotEps:r=0.001 // Rotation compression accuracy. Higher values reduce accuracy. +sclEps:r=0.1 // Scaling compression accuracy (if applicable). +``` + +This is an example of a `.blk` script used for post-export processing. Carefully +adjust compression values to balance file size and animation precision. + +After exporting, open the animation in the [*Asset +Viewer*](../../dagor-tools/asset-viewer/asset-viewer/asset_viewer.md). If you +select the exported animation (`crow_detailed_idle_b`), you might initially see +nothing: + + + +**Steps to Display the Animation:** +1. Assign the dynamic model {bdg-dark-line}`1` associated with the animation. +2. Re-select the animation {bdg-dark-line}`2`. + +At this point, the crow {bdg-dark-line}`3` should appear in the scene in the +first frame of the animation instead of the default T-pose. + +**Playing the Animation:** +- To play the animation, click the play button {bdg-dark-line}`4`. +- By default, animations play very quickly. Use the speed slider + {bdg-dark-line}`5` to reduce playback speed (e.g., set it to `0.5x` for + smoother observation). + + + +At this stage, all necessary data has been exported from *3ds Max*: +- Animation +- Bone structure +- Hierarchy +- Model and its LODs + +The final step is updating the `.blk` scripts to define the roles of each +component (e.g., bones, animations, models) for integration into *Dagor Engine*. + +## Principles of Working with Dynamic Models in Dagor and Resource Integration + +The `*.blk` files found alongside models in `creatures.zip` are scripts that +automate the preparation, conversion, and generation of resources for the game. +These scripts, written in an internal language for *Dagor*, define specific +processes for managing game entities and objects. + +```{note} +**Reloading After Changes:** +- Some `.blk` files (e.g., `.folder.blk`) only update after reloading the + [*Asset Viewer*](../../dagor-tools/asset-viewer/asset-viewer/asset_viewer.md) + or the [*daEditor*](../../dagor-tools/daeditor/daeditor/daeditor.md). +- In contrast, files related to animations can be edited dynamically, and + changes take effect immediately. +``` + +The `.folder.blk` file processes all contents of the directory it resides in, +along with its subdirectories. This is particularly useful when working with a +large number of resources. + +**Example: Processing Animations** + +`//develop/assets/dev/gameRes/creatures/animation/.folder.blk` + +```text +export{ + gameResPack:t="anims.grp" // Export processed animation resources into the specified game resource package + exported:b=yes // Perform the export +} + +virtual_res_blk{ // Create virtual resource + find:t="^(.*)\.a2d$" // Locate all *.a2d files in the directory tree + className:t="a2d" // Assign the "a2d" class, marking them as animation objects + contents{ + opt:b=yes // Enable conservative optimization + posEps:r=0.01 // Compression accuracy for position + rotEps:r=0.2 // Compression accuracy for rotation + sclEps:r=0.1 // Compression accuracy for scaling + } +} +``` + +This script: +1. Exports animations into the `anims.grp` game resource package. +2. Finds all `*.a2d` files, assigns them the "a2d" class, and processes them as + animations. +3. Applies compression with default thresholds to balance file size and + animation quality. + +**Example: Processing Dynamic Models** + +`//develop/assets/dev/gameRes/creatures/.folder.blk` + +This script is slightly more complex but follows the same structure. + +```text +scan_assets:b=yes // Search for objects +scan_folders:b=yes // Search for directories + +export{ + ddsxTexPack:t="creatures.dxp.bin" // Process textures and store them in this game resource + gameResPack:t="creatures.grp" // Store processed models and virtual objects here +} + +virtual_res_blk{ // Create virtual resource + find:t="^((.*)_dynmodel)\.lod00\.dag$" // Locate dynamic model files + stopProcessing:b=false // Continue processing this object in other blocks + className:t="skeleton" // Generate skeleton from dynamic models + name:t="$2_skeleton" // Assign a skeleton name + contents{ + addSkinNodes:b=yes // Attach skin nodes to the skeleton + reduceNodes:b=yes // Remove bones without Skin vertices + } +} + +virtual_res_blk{ // Create virtual resource + find:t="^((.*)_dynmodel)\.lod00\.dag$" // Scan again for dynamic models + stopProcessing:b=false + className:t="DynModel" // Assign "DynModel" class to dynamic models + name:t="$2_dynmodel" // Assign a name to dynamic model objects + contents{ + lod{ + range:r=3000; fname:t="$1.lod00.dag"; // Set LOD00 rendering distance to 3000 meters + } + ref_skeleton:t="$2_skeleton" // Assign the corresponding skeleton + } +} +``` + +**Key Steps:** + +1. **Search Directories:** + - Use `scan_assets:b=yes` and `scan_folders:b=yes` to locate objects and + directories. + +2. **Export Textures and Models:** + - Textures are saved in `creatures.dxp.bin`. + - Models and virtual objects are saved in `creatures.grp`. + +3. **Generate Skeletons:** + - Find models named as `*_dynmodel.lod00.dag`. + - Create skeletons for these models, removing unused bones and linking skins. + +4. **Assign Properties to Models:** + - Assign a rendering distance of `3000` meters for LOD00. + - Link dynamic models to the generated skeletons. + +After running the scripts, the resulting files (`creatures.grp` and +`creatures.dxp.bin`) are ready for integration into the game. These resources: +- Contain properly configured skeletons, bones, and skin objects. +- Are optimized for gameplay with attributes such as rendering distance and + compression settings. + +These configurations ensure all objects are processed as game entities with +specific classes and properties. + +## Real Resources vs. Virtual Resources and Objects in Dagor + +**Key Concepts:** + +Understanding the distinction between **real resources** (files on disk), +**virtual resources** (engine-created entities), and **virtual resources +converted into game entities** is critical when working with *Dagor*. + +The *Dagor Engine* processes exported files (e.g., `*.a2d`, `*.dag`) into +optimized formats (`*.dxp.bin`, `*.grp`) ready for game use. While physical +files on disk represent raw data, virtual objects in the engine are entities +assigned game properties. These virtual objects are subsequently written into +binary game resources. + +**Real vs. Virtual Resources:** + +1. **Exported Files:** Files from tools like *3ds Max* include animations + (`*.a2d`) and dynamic models (`*.dag` with LOD levels). These raw files are + intermediate resources. + +2. **Engine Optimization:** The *Dagor Engine* transforms exported data, + applying compression and processing to meet game engine requirements (e.g., + reducing file size, optimizing for performance). + +3. **Game Resource Files:** Final outputs like `*.dxp.bin` and `*.grp` are the + only formats recognized by the game executable. Scripts (`*.blk`) process the + exported data into game entities. + +**Example: Crow Dynamic Model Breakdown** + +From a single dynamic model file, the following game entities can be generated +using `*.blk` scripts: +- Skeleton (`crow_skeleton`) +- Model Shell +- Physics Model +- Collision Data + +Notably, physics {bdg-dark-line}`1` and collision {bdg-dark-line}`2` data may +remain empty if unnecessary for the object, as in the case of the crow model. +For example: + +- **Skeleton:** Visible because it was explicitly processed in the script. + + + + +- **Physics & Collisions:** Empty because the script did not define these + components. + + + +## Configuring `*_char.animchar.blk` + +This script assembles the virtual resources (e.g., skeleton, model, physics) +into a character with complex structures that the game code can manage +efficiently. + +**Example:** `//develop/assets/dev/gameRes/creatures/characters/crow/crow_detailed_a_char.animchar.blk` + +```text +//no_anim_dist:r=100 // Distance beyond which animations stop (commented out) +//no_render_dist:r=200 // Distance beyond which the model stops rendering (commented out) +//useCharDep:b=no // Not used here; consult specific documentation if needed +rootNode:t="root" // Starting bone of the skeleton +dynModel:t="crow_detailed_a_dynmodel" // Dynamic model name for the character +skeleton:t="crow_detailed_a_skeleton" // Skeleton name for the character +animTree:t="crow_detailed_a_animbnl" // Animation description tree for blending and rules +physObj:t="crow_detailed_a_phobj" // Physical model for the character + +//ref_states{ // Optional reference states (commented out) +// state:t="stand_ground" +//} +``` + +**Key Points:** + +1. Operates exclusively on **virtual objects** (e.g., skeletons, models). +2. Does not search for or sort physical files; all objects must already exist as + virtual entities. +3. Assembles the higher-level character structure by linking components (dynamic + model, skeleton, physics). + +## Configuring `*_dynmodel.dynmodel.blk` + +This script applies specific properties to an individual model. Unlike +`.folder.blk`, which processes groups of files, `*_dynmodel.dynmodel.blk` +targets a single resource. + +**Example:** `//develop/assets/dev/gameRes/creatures/characters/crow/crow_detailed_a_dynmodel.dynmodel.blk` + +```text +ref_skeleton:t="crow_detailed_a_skeleton" // Assign the corresponding skeleton + +lod{range:r=2;} // LOD00 switches to LOD01 at 2 meters +lod{range:r=7;} // LOD01 switches to LOD02 at 7 meters +lod{range:r=15;} // LOD02 turns off rendering at 15 meters +``` + +**Key Points:** + +1. The **naming convention** ensures precise targeting of a specific dynamic + model (`crow_detailed_a_dynmodel`). +2. **LOD Configuration:** + - `range:r=2`: Transitions from the highest detail (LOD00) to a lower detail + (LOD01). + - `range:r=15`: Stops rendering entirely beyond this distance. +3. Links the skeleton to the dynamic model (`ref_skeleton`), ensuring it uses + the correct hierarchy. + +```{important} +**Real vs. Virtual:** +- Real resources are raw files (e.g., `*.a2d`, `*.dag`), while virtual + resources are entities created and optimized by the engine. +- Game resource files (`*.dxp.bin`, `*.grp`) are the final, optimized outputs. + +**Script Layers:** +- `.folder.blk`: Processes groups of resources. +- `*_char.animchar.blk`: Assembles characters from components like skeletons, + models, and physics. +- `*_dynmodel.dynmodel.blk`: Configures individual models with properties such + as LOD ranges. +``` + +## Configuring `*_animbnl.animtree.blk` + +The `*_animbnl.animtree.blk` file defines the rules for animation states, +blending, and other related configurations, such as additive animations for a +character. This script is one of the most complex due to its detailed control +over animation blending and state transitions. + +```{seealso} +For more information, see +[daAnimations](../../assets/animation/daanimations.md). +``` + +**Key Points:** +1. **Sequential Execution Matters:** Blocks and commands must be executed in the + order they are defined. For instance, a blending controller must be declared + before it is used. + +2. **Nodes as Units:** A **node** can represent an object, model, or bone. Nodes + are identified by names, which are used for configuration. + +3. **Critical Documentation:** It is highly recommended to read related + documentation thoroughly to understand controllers, states, and blending + techniques. + +**Example:** `//develop/assets/dev/gameRes/creatures/characters/crow/crow_detailed_a_animbnl.animtree.blk` + +**Script Breakdown:** + +```text +export:b=yes // Process the script +root:t="fifo3" // Root node for animation blending +defaultForeignAnim:b=yes // Enables blending foreign animations +``` + +```text +nodeMask{ // Defines masks for specific nodes (bones in this case). + name:t="body" // Bone name from 3ds Max + node:t="Bip01" // Root bone name as recognized by Dagor +} +``` + +- **Purpose:** Aligns the bone naming conventions between *3ds Max* and *Dagor* +to ensure compatibility. For example, `Bip01` is historically used for root +bones in *3ds Max*. + +```text +stateDesc{ // Specifies all possible animation states for the character. + // In this example states represent conditions like "flying" + // and "turning right while flying". + defMorphTime:r=0.15 // Transition time between states (morphing) + defNodeName:t="*" // Applies to all bones (nodes) + + chan{ // Mixing channel for the "body" and nodes + name:t="body" + fifo3:t="fifo3" // Controller type + nodeMask:t="" // Applies to all nodes + cond_target:i=1 + } + + chan{ // Mixing channel for the "root" and nodes + name:t="root" + fifo3:t="fifo3_root" + nodeMask:t="" + cond_target:i=0 + } + + state{ // Example animation state + name:t="crow_a_fly_turn_right" // State name + body{ name:t="crow_a_fly_turn_right"; } // Links the state to an animation for the "body" + } +} +``` + +- **States:** Represent high-level conditions that can mix multiple animations + or transitions. +- **Channels:** Control how specific nodes or groups of bones are blended in + animation. + +Each animation state is linked to an `AnimBlendNodeLeaf{}` block that specifies +the actual animation file (`*.a2d`) and its properties. + +```text +AnimBlendNodeLeaf{ + a2d:t="crow_detailed_fly_turn_right" // Animation file + + continuous{ + name:t="crow_a_fly_turn_right" // Internal name linked to the state + key_start:t="fly_turn_right_start" // Start keyframe from 3ds Max + key_end:t="fly_turn_right_end" // End keyframe from 3ds Max + time:r=2.0 // Playback duration + own_timer:b=yes // Unique timer for this animation + eoa_irq:b=yes // End-of-animation interrupt marker + } +} +``` + +- **Purpose:** Prepares the raw animation file for use in the defined states. +- **Keys:** Define specific animation segments exported from 3ds Max. + +Blend controllers manage the mixing of different animation states. + +```text +AnimBlendCtrl{ + fifo3{ + name:t="fifo3" // Name of the controller + varname:t="fifo3_var" // Variable name for internal use + } + + fifo3{ + name:t="fifo3_root" + varname:t="root_ctrl" + } +} +``` + +**Key Execution Steps:** + +1. **Define Controllers:** Controllers like `fifo3` and `fifo3_root` are + declared first. + +2. **Specify States:** States such as `crow_a_fly_turn_right` link animations to + logical conditions. + +3. **Create Animation Nodes:** For each state, an `AnimBlendNodeLeaf{}` is + created to prepare the corresponding animation file. + +4. **Test the Configuration:** Use the *Dagor Engine* visualization tools (e.g., + the [*Asset + Viewer*](../../dagor-tools/asset-viewer/asset-viewer/asset_viewer.md)) to + verify the setup. + +```{important} +- **Purpose:** The `*_animbnl.animtree.blk` file establishes a framework for + managing animation states and blending. +- **Components:** + 1. **Node Masks:** Define skeleton relationships. + 2. **State Descriptions:** Link logical states to animations. + 3. **Animation Nodes:** Prepare animations for state transitions. + 4. **Controllers:** Manage blending logic. +``` + +When viewed {bdg-dark-line}`1` in the [*Asset +Viewer*](../../dagor-tools/asset-viewer/asset-viewer/asset_viewer.md), the +following elements should appear based on this configuration: + +1. **Skeleton Nodes:** The root node (`Bip01`) and associated hierarchy + {bdg-dark-line}`2`. +2. **Blend Nodes:** All defined `AnimBlendNodeLeaf` elements {bdg-dark-line}`3`, + corresponding to animation states. +3. **Controllers:** All specified controllers (`fifo3`, `fifo3_root`). +4. **States:** List of all defined animation states, such as + `crow_a_fly_turn_right`. + + + +## Testing the Character in Asset Viewer + +**Step 1: Checking Files in Asset Viewer** + +1. Open the [*Asset + Viewer*](../../dagor-tools/asset-viewer/asset-viewer/asset_viewer.md) and + load all the files related to your character {bdg-dark-line}`1`. + + **Goal:** Ensure no errors appear in the console {bdg-dark-line}`2`. A + successful result looks like this: + + + +2. **Common Checkpoints:** + - Inspect every file linked to the character (e.g., animations, blend + controllers, state descriptions). + - Console errors indicate an issue with one or more configurations. + +**Step 2: Local Resource Building** + +1. **Initiate `daBuild`:** + To include the created character in `.grp` and `.dxp.bin` files: + - Navigate to the folder {bdg-dark-line}`1` containing the character + resources (e.g., `crow`). + - Right-click the folder and select the **Export All (PC)** option + {bdg-dark-line}`2`. + + + +2. **Monitor Build Progress:** + - The building process starts and may take a significant amount of time + depending on your computer's performance. + - Build progress is displayed in the console. A successful build ends with an + output similar to this {bdg-dark-line}`1`: + + + +3. **Integration:** + Once built, the character is ready for inclusion in the game. + +## Common Errors + +### Error: Bracket Mismatches + +Missing or extra brackets can cause critical errors during script parsing. + +**Example:** + +```text +BLK error 'D:/dagor2/enlisted/develop/assets/dev/gameRes/creatures/characters/crow/crow_detailed_a_animbnl.animtree.blk',228: unexpected EOF: +``` + +- **Cause:** Unmatched brackets result in an "unexpected end of file" (EOF) + error. +- **Solution:** Carefully check the script for bracket pairs, especially in + deeply nested blocks. + + + +### Error: Incorrect Data Types + +**Example:** + +```text +BLK invalid time (type real) value in line 209 of 'D:/dagor2/enlisted/develop/assets/dev/gameRes/creatures/characters/crow/crow_detailed_a_animbnl.animtree.blk': 'sdfsd' +DataBlockParser: invalid value 'sdfsd' at line 209 of file '.../crow_detailed_a_animbnl.animtree.blk' +``` + +- **Cause:** A non-numeric value (e.g., string) is assigned to a numeric + property like `time`. +- **Solution:** Review and correct the value. Ensure all numeric parameters + are defined as valid numbers (e.g., `time:r=2.0`). + + + +### Debugging Tips + +1. **Error Line Numbers:** While error messages indicate a line number, they may + not always be accurate. Errors often occur earlier in the script but only + show later. + +2. **Manual Validation:** + - Verify the syntax for critical properties such as `state`, `chan`, and + `AnimBlendNodeLeaf`. + - Cross-check with examples or templates to ensure consistency. + +3. **Progressive Testing:** + - Test the script incrementally by adding elements in small chunks. + - This approach isolates errors more effectively. + +### Summary + +**Key Steps for Testing:** + +1. Verify all character files in the [*Asset + Viewer*](../../dagor-tools/asset-viewer/asset-viewer/asset_viewer.md). +2. Perform a local build using the the *daBuild* and monitor for successful + output. +3. Address any errors detected during the process. + +**Common Pitfalls:** + +- Missing or extra brackets (`{`, `}`). +- Incorrect value types (e.g., string instead of number). +- Errors at incorrect line numbers due to delayed detection. + +By following these steps and debugging techniques, you can ensure your character +is fully functional and ready for game integration. + +```{tip} +If you encounter any errors or have questions regarding this document, please +reach out to the author directly at {octicon}`mail;1.4em;sd-text-info` +. +``` + + diff --git a/_docs/source/tutorials/dng-non-human-char/index.rst b/_docs/source/tutorials/dng-non-human-char/index.rst new file mode 100644 index 000000000..044a406ed --- /dev/null +++ b/_docs/source/tutorials/dng-non-human-char/index.rst @@ -0,0 +1,11 @@ + +Non-Human Character: Step-by-Step Guide +========================================= + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + dng_non_human_char.md + + diff --git a/_docs/source/tutorials/index.rst b/_docs/source/tutorials/index.rst index 548b4d193..79143c335 100644 --- a/_docs/source/tutorials/index.rst +++ b/_docs/source/tutorials/index.rst @@ -9,5 +9,7 @@ Guides and step-by-step instructions to help you master the Dagor Engine. :caption: Contents: create-mission-wt/index.rst + dng-non-human-char/index.rst + wt-designing-vehicle-deformations/index.rst diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_01.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_01.jpg new file mode 100644 index 000000000..95f35ba48 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_01.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_02.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_02.jpg new file mode 100644 index 000000000..05e26e4f6 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_02.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_03.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_03.jpg new file mode 100644 index 000000000..c4e8fef60 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_03.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_04.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_04.jpg new file mode 100644 index 000000000..fecfb889a Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_04.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_05.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_05.jpg new file mode 100644 index 000000000..b720ebb10 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_05.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_06.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_06.jpg new file mode 100644 index 000000000..d60ec0e00 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_06.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_07.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_07.jpg new file mode 100644 index 000000000..7983921be Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_07.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_08.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_08.jpg new file mode 100644 index 000000000..904a44abe Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_08.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_09.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_09.jpg new file mode 100644 index 000000000..ea188cb25 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_09.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_10.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_10.jpg new file mode 100644 index 000000000..344a53999 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_10.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_11.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_11.jpg new file mode 100644 index 000000000..70df7e138 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_11.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_12.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_12.jpg new file mode 100644 index 000000000..e82b852d0 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_12.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_13.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_13.jpg new file mode 100644 index 000000000..cbaee9513 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_13.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_14.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_14.jpg new file mode 100644 index 000000000..57d807098 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_14.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_15.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_15.jpg new file mode 100644 index 000000000..fb32a65b4 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_15.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_16.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_16.jpg new file mode 100644 index 000000000..692be6940 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_16.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_17.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_17.jpg new file mode 100644 index 000000000..9b0abc5ee Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_17.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_18.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_18.jpg new file mode 100644 index 000000000..ece15bb8b Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_18.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_19.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_19.jpg new file mode 100644 index 000000000..f27ed4f5a Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_19.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_20.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_20.jpg new file mode 100644 index 000000000..a67c9cefb Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_20.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_21.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_21.jpg new file mode 100644 index 000000000..86094cd78 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_21.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_22.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_22.jpg new file mode 100644 index 000000000..8d47dd22d Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_22.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_23.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_23.jpg new file mode 100644 index 000000000..c8f28c612 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_23.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_24.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_24.jpg new file mode 100644 index 000000000..f0f610432 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_24.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_25.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_25.jpg new file mode 100644 index 000000000..be8499fb9 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_25.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_26.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_26.jpg new file mode 100644 index 000000000..a3a660b20 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_26.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_27.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_27.jpg new file mode 100644 index 000000000..69baad27c Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_27.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_28.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_28.jpg new file mode 100644 index 000000000..360848526 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_28.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_29.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_29.jpg new file mode 100644 index 000000000..b6bb69eb0 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_29.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_30.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_30.jpg new file mode 100644 index 000000000..c91e5a7ad Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_30.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_31.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_31.jpg new file mode 100644 index 000000000..29b39939d Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_31.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_32.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_32.jpg new file mode 100644 index 000000000..38c87ebaa Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_32.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_33.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_33.jpg new file mode 100644 index 000000000..bce6bd011 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_33.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_34.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_34.jpg new file mode 100644 index 000000000..59d6a954f Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_34.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_35.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_35.jpg new file mode 100644 index 000000000..436169d3d Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_35.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_36.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_36.jpg new file mode 100644 index 000000000..e34c56d2a Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_36.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_37.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_37.jpg new file mode 100644 index 000000000..48fab659a Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_37.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_38.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_38.jpg new file mode 100644 index 000000000..73d790abc Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_38.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_39.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_39.jpg new file mode 100644 index 000000000..17f220fb1 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_39.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_40.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_40.jpg new file mode 100644 index 000000000..b0362050c Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_40.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_41.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_41.jpg new file mode 100644 index 000000000..cd00731d7 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_41.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_42.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_42.jpg new file mode 100644 index 000000000..b172048eb Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_42.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_43.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_43.jpg new file mode 100644 index 000000000..fd3e2c87a Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_43.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_44.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_44.jpg new file mode 100644 index 000000000..27f20954c Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_44.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_45.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_45.jpg new file mode 100644 index 000000000..b64e2261c Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_45.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_46.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_46.jpg new file mode 100644 index 000000000..5b9088b16 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_46.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_47.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_47.jpg new file mode 100644 index 000000000..cb0f80348 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_47.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_48.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_48.jpg new file mode 100644 index 000000000..2d3cd8402 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_48.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_49.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_49.jpg new file mode 100644 index 000000000..064cf664b Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_49.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_50.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_50.jpg new file mode 100644 index 000000000..a0892bcd1 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_50.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_51.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_51.jpg new file mode 100644 index 000000000..2eef6df33 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_51.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_52.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_52.jpg new file mode 100644 index 000000000..0d0868f85 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_52.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_53.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_53.jpg new file mode 100644 index 000000000..80f364167 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_53.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_54.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_54.jpg new file mode 100644 index 000000000..da16c530a Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_54.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_55.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_55.jpg new file mode 100644 index 000000000..1b74b5ff4 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_55.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_56.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_56.jpg new file mode 100644 index 000000000..391491a91 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_56.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_57.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_57.jpg new file mode 100644 index 000000000..8683938e8 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_57.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_58.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_58.jpg new file mode 100644 index 000000000..b7b065cd8 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_58.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_59.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_59.jpg new file mode 100644 index 000000000..68f524129 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_59.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_60.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_60.jpg new file mode 100644 index 000000000..6f2fa94ff Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_60.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_61.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_61.jpg new file mode 100644 index 000000000..ff69e10db Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_61.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_62.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_62.jpg new file mode 100644 index 000000000..677f86602 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_62.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_63.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_63.jpg new file mode 100644 index 000000000..bf43303e8 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_63.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_64.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_64.jpg new file mode 100644 index 000000000..30cdcb097 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_64.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_65.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_65.jpg new file mode 100644 index 000000000..9f35fda4d Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_65.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_66.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_66.jpg new file mode 100644 index 000000000..7996d591d Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_66.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_67.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_67.jpg new file mode 100644 index 000000000..83fc045e9 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_67.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_68.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_68.jpg new file mode 100644 index 000000000..ae2360d9e Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_68.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_69.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_69.jpg new file mode 100644 index 000000000..690dc11b3 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_69.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_70.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_70.jpg new file mode 100644 index 000000000..030289e60 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_70.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_71.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_71.jpg new file mode 100644 index 000000000..2a25585da Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_71.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_72.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_72.jpg new file mode 100644 index 000000000..bd6ae51d6 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_72.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_73.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_73.jpg new file mode 100644 index 000000000..c4c998fdf Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_73.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_74.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_74.jpg new file mode 100644 index 000000000..f6deee41a Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_74.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_75.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_75.jpg new file mode 100644 index 000000000..4f891c96c Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_75.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_76.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_76.jpg new file mode 100644 index 000000000..16a251ce0 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_76.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_77.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_77.jpg new file mode 100644 index 000000000..43422e09d Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_77.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_78.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_78.jpg new file mode 100644 index 000000000..8d64e835a Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_78.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_79.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_79.jpg new file mode 100644 index 000000000..8972da30e Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_79.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_80.jpg b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_80.jpg new file mode 100644 index 000000000..89e88dcb6 Binary files /dev/null and b/_docs/source/tutorials/wt-designing-vehicle-deformations/_images/wt_designing_vehicle_deformations_80.jpg differ diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/index.rst b/_docs/source/tutorials/wt-designing-vehicle-deformations/index.rst new file mode 100644 index 000000000..4559b4522 --- /dev/null +++ b/_docs/source/tutorials/wt-designing-vehicle-deformations/index.rst @@ -0,0 +1,11 @@ + +Designing Vehicle Deformations +========================================= + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + wt_designing_vehicle_deformations.md + + diff --git a/_docs/source/tutorials/wt-designing-vehicle-deformations/wt_designing_vehicle_deformations.md b/_docs/source/tutorials/wt-designing-vehicle-deformations/wt_designing_vehicle_deformations.md new file mode 100644 index 000000000..f7017fc27 --- /dev/null +++ b/_docs/source/tutorials/wt-designing-vehicle-deformations/wt_designing_vehicle_deformations.md @@ -0,0 +1,1049 @@ +# Designing Vehicle Deformations + +## Overview + +This article provides a step-by-step guide for creating vehicle deformations. It +uses three vehicle models as examples, detailing how to implement destruction on +them. The focus is on working with existing vehicles. You'll need advanced +knowledge of *3ds Max* and a thorough understanding of how *Dagor Engine* +handles destruction. + +### Prerequisites + +**Plugins and Tools:** + +- *Dagor import/export plugin*. +- [*Dagor 2 Transfer Vertex Position to Vertex Color + Tool*](../../dagor-tools/addons/3ds-max/dagor2-3ds-max-tools/transfer_vertex_position_to_vertex_color_tool.md). +- [*Dagor 2 Damages Setup + Tool*](../../dagor-tools/addons/3ds-max/dagor2-3ds-max-tools/damages_setup_tool.md) + for setting up rigid-body destruction. +- [*Dagor 2 Fast Editor User + Properties*](../../dagor-tools/addons/3ds-max/dagor2-3ds-max-tools/fast_editor_user_properties.md) + for streamlined property editing. +- [*Dagor 2 Fix Normal Orientation + Tool*](../../dagor-tools/addons/3ds-max/dagor2-3ds-max-tools/fix_normal_orientation_tool.md) + to preemptively correct normal issues in dynamic objects. +- [*RayFire plugin*](https://rayfirestudios.com/) for glass and wood + destruction. + +### Platform Specifics + +The examples and guidelines are based on *War Thunder*. Projects based on +*daNetGame* framework will follow the same principles, with minor differences in +shaders. + +### Version Requirements + +- Minimum *3ds Max 2021* is required. +- All example files were created using *3ds Max 2024*. + +## General Concepts of Vehicle Deformations and Destruction + +### Key Constraints + +The primary limitation in a single Dagor `.dag` model file is that only **one +deformable object** can exist. If multiple deformable objects are present, the +engine will prioritize the largest object by bounding box, as indicated in logs: + +```text +43.52 [E] multiple nodes with dynamic_deformed shader in instance, choosing the biggest one +``` + +Rigid-body (non-deformable) objects are limited to **a few hundred per model**. +These rigid objects should be identified and separated during the design phase +to achieve the desired destruction effect. Objects that visually detach during +real-world vehicle destruction or significantly differ in material (e.g., +wheels, wooden fences, glass, plastic panels) must be isolated into separate +components by material type. + +## Preparing the Model for Destruction + +### Importing the Model + +Import the `.dag` model: +{download}`m123_truck.lod00.zip +` + +For material insights, preview the model with textures in the [*Asset +Viewer*](../../dagor-tools/asset-viewer/asset-viewer/asset_viewer.md): +`//develop/assets/entities/vehicles/cars_modern/m123_truck.lod00.dag` + +The model with textures preview in Asset Viewer + +### Setting Up Layers + +Organize your scene into layers for a structured workflow: + +1. **DeformStart**: Contains objects to be deformed. +2. **DeformEnd**: Contains objects after deformation. + + ```{important} + Pay close attention to the naming of objects in **DeformStart** and + **DeformEnd** layers. The quantity and naming must be identical. This + consistency will prevent indexing errors in the order of vertices in the + final model during the subsequent merging of all deformable objects. + ``` + +3. **RigidObj**: Houses rigid, detachable components. +4. **EXPORT**: Final output layer. + +#### Object Identification + +- **Green (1)**: Deformable metal requiring tessellation (placed in + **DeformStart**). +- **Brown (3)**: Metal with sufficient detail, no tessellation needed (also in + **DeformStart**). +- **Blue (2)**: Metal requiring separation for realistic deformation (e.g., + doors). +- **Purple (4)**: Rigid objects, such as detachable components (placed in + **RigidObj**). + +Color identification of the model parts in 3ds Max + +## Deforming Large Rigid Components + +Pre-deform large rigid objects to improve realism post-separation. Minor parts +can remain mostly intact. For example, large tires should appear damaged and +should resemble this degree of deformation: + +Deformed vehicle tyres in 3ds Max + +## Configuring Rigid Components + +1. **Set Active Layer**: Work in the **RigidObj** layer. + + Rigid object layer icon in 3ds Mas + +2. **Launch Script**: Use [*Dagor 2 Damages Setup + Tool*](../../dagor-tools/addons/3ds-max/dagor2-3ds-max-tools/damages_setup_tool.md). +3. **Reset Pivots**: Reset pivots to object centers. + + Pivots reset to objects center in 3ds Max + +### Script Adjustments + +- Change `materialName:t="wood_solid"` to `materialName:t="metal"` for proper + sound and effects. +- Change `density:r=150` to `density:r=250` for metal properties. + + Dagor 2 Damage Setup properties window + +### Applying Changes + +- **(1)** Select all objects in **RigidObj** layer. +- **(2)** Apply the script to generate accurate collision hierarchies and + user-defined properties. + + Selecting objects in Rigid object layer and applying the script to generate collision hierarchies in 3ds Max + + Generated objects collisions in 3ds Max + +### Adjusting Collision Boxes for Objects + +As observed, a collision box **(1)** is generated for each object, but it does +not always precisely conform to the shape of the objects **(2)**. Therefore, it +is necessary to manually adjust the collision boxes in the scene to achieve +accurate coverage. + +For instance, when working with wheels, align the box size to the wheel's +diameter and duplicate the box collisions by rotating them. This will create an +approximate cylinder shape. Unfortunately, *Dagor Engine* does not support +native cylinder or sphere collisions, so all shapes must be approximated using +boxes. The final scene will look as follows: + +Generated collision boxes and objects in 3ds Max + +```{note} +All scaling, positioning, and rotation adjustments must be performed in **Local +Space**. + +Local Space in enabled on the panel in 3ds Max + +Failure to do so will result in distortions and inaccuracies after export to +*Dagor Engine*. Correcting these issues later is extremely difficult and +time-consuming. +``` + +Notice that components such as wheels **(1)**, headlight lenses **(1)**, and +mudguards **(1)** are defined using multiple collision boxes. For complex +shapes, take an existing collision box and modify it to match the object's +contours as closely as possible. If one box is insufficient, add as many as +necessary. Simpler shapes, such as side mirrors **(2)**, can typically be +described with a single box. + +To streamline the review of object properties, it is recommended to use the +[*Dagor 2 Fast Editor User +Properties*](../../dagor-tools/addons/3ds-max/dagor2-3ds-max-tools/fast_editor_user_properties.md) +script. After installation, the script is activated with `Alt`+`Ctrl`. For all +selected objects **(1)**, it will display the contents of their **custom user +properties** **(3)** in a dedicated window **(2)**, eliminating the need to +individually access these properties via context menus. To hide the script +window, press `Alt`+`Shift`. + +With this step, the configuration of solid objects is complete. Hide this layer, +as it will no longer be needed before export. + +## Configuring the Deformable Parts of the Vehicle + +Begin by configuring objects within the **DeformStart** and **DeformEnd** +layers. For realistic vehicle deformation, the model must have sufficient +detail. This often necessitates tessellating the model to enhance deformation +quality. For example, attempting to deform fuel tanks **(1)**, the vehicle base +**(2)**, wheel arches and fenders **(4)**, mudguards **(3)**, and the cab +**(5)** will result in issues if there are insufficient triangles to allow +proper deformation. Even separate components, like the door **(6)**, require +tessellation. + +View of model deformable parts in 3ds Max before tesselation in 3ds Max + +After tessellation, the model should not exceed 65,000 triangles in total. A +properly tessellated vehicle should look approximately like this: + +View of model deformable parts in 3ds Max after tesselation in 3ds Max + +Unfortunately, there are no strict tessellation rules. A good recommendation is +to create cuts every 20-30 cm, striking a balance between visual quality and the +triangle count. Aim to keep the triangle count as low as possible without +sacrificing deformation quality. The optimal balance comes with experience after +deforming 3-4 models. + +Next, copy all objects from the **DeformStart** layer into the **DeformEnd** +layer. **Pay close attention to naming conventions**. Ensuring consistent naming +is crucial for preserving vertex indexation when combining pieces later. +Matching the vertex indexing between the initial (undeformed) and final (fully +deformed) models is essential. Hide the **DeformStart** layer, as it contains +the undeformed model version needed only at the end of the workflow to bake +vertex position data into vertex colors. Verify that all names and object +sequences are identical: + +Copying all objects from the DeformStart layer into the DeformEnd layer in 3ds Max + +At this stage, you are ready to begin deformation. **Save the scene before +starting each deformation step**. Results may not always match your +expectations, and rolling back is often easier. Consider setting undo steps to +at least 300-400 for safety. However, saving regularly is more reliable, as +*3ds Max* may crash unexpectedly during deeper undo actions. + +### Deformation Process + +Deforming the vehicle involves using **Soft Selection** on vertices to create a +realistic crumpled effect. Start with broader adjustments and refine as you go. +For example: + +- **Doors**: Open or partially open the doors before deformation. Doors nearly + always open or partially detach during vehicle collisions. +- **Fragile parts**: Separate brittle components rather than deform them. + +Initially, apply an **FFD (Free Form Deformation)** modifier to all objects for +rough adjustments: + +Appling an FFD (Free Form Deformation) modifier to all objects for rough adjustments in 3ds Max + +Then carefully deform individual vehicle elements: + +Deforming individual vehicle elements in 3ds Max + +### Combining Layers + +After deformation, merge all parts in the **DeformStart** layer and then do the +same for the **DeformEnd** layer. When merging, ensure that objects are attached +in numerical order (e.g., attach to object `*000` in sequence). This step is +critical to maintain consistent vertex indexing. The result will be two distinct +models – deformed and undeformed. For convenience, move the pivot point of each +model to the center of the scene and perform a **Reset Transform**. This step +helps prevent potential issues with normals during export. Tools such as the +[*Dagor 2 Fix Normal Orientation +Tool*](../../dagor-tools/addons/3ds-max/dagor2-3ds-max-tools/fix_normal_orientation_tool.md) +or *3ds Max*'s built-in tools can assist with this. The scene should now appear +as follows: + +Moving the pivot point of each model to the center of the scene and performing a Reset Transform + +### Transferring Vertex Positions to Vertex Colors + +Run the [*Dagor 2 Transfer Vertex Position to Vertex Color +Tool*](../../dagor-tools/addons/3ds-max/dagor2-3ds-max-tools/transfer_vertex_position_to_vertex_color_tool.md) +script. Select the undeformed model, set the deformed model as the source in the +**Pick Source Object** field, and click **Transfer Vertex Position to VColor!** +This will map the deformed model's vertex position changes into the vertex color +channel of the undeformed model. Check the vertex color channel to confirm it +contains data. The undeformed model should now look similar to this: + +Maping the deformed model's vertex position changes into the vertex color channel of the undeformed model + +The intensity of the vertex colors indicates the degree of deformation – +stronger deformations produce more vibrant colors, while minimal deformations +appear closer to gray. This step verifies the successful transfer of position +data into vertex colors. The deformed model is no longer needed and can be +hidden along with the **DeformEnd** layer. + +### Assigning Custom User Properties + +Assign the following **custom user properties** to the undeformed model to +ensure correct behavior in *Dagor Engine*: + +```text +animated_node:b=yes +physObj:b=yes +collidable:b=no +density:r=15500 +massType:t="none" +``` + +The `density:r=15500` parameter is set based on the vehicle type. For a heavy +vehicle, use a value of ~`15,500`; for passenger cars, values between `5,000` and +`7,000` are typical. + +Setting the Dagor 2 Fast Properties tool parameters + +### Final Scene Setup + +Complete the general scene configuration to ensure the vehicle interacts +properly in *Dagor Engine*. The vehicle body must behave correctly as a physical +object and respond as intended within the engine. + +## Auxiliary Collision Objects + +To ensure proper interactions between the destructible vehicle model and tanks +or other vehicles, auxiliary collision boxes need to be added to the scene. +These objects are designed similarly to standard collision boxes but must be +attached +The Attaching icon +to the main deformable body of the vehicle. + +Collision boxes of the model parts in 3ds Max + +- **Stepped Base (2)**: Enables wheeled vehicles with smaller wheel diameters to + visually climb onto a deformed section of the vehicle. +- **Bumper (2) and External Platforms**: Ensure the detached wheels are pushed + correctly away from the main body. +- **Box (3)**: Simulates falling glass fragments dispersing outward. +- **Cabin (large deformation)**: Prevents tanks from driving further by creating + a larger physical obstacle. +- **Box Set (4)**: Facilitates correct interaction with the vehicle's rear bulk. +- **Rear Platform Box (5)**: Acts as a support platform for smaller debris at + the back of the vehicle. +- **Diagonal Boxes (bottom)**: Prevent the vehicle from landing flat like a + slab, instead allowing a natural tilted fall. + +Tailored auxiliary collision boxes of the model parts in 3ds Max + +Each vehicle requires tailored auxiliary collision boxes. + +## Assigning Dynamic Materials + +Since we start with a static model, its materials need to be converted into +dynamic ones to enable deformation. Dynamic vehicle pieces require specific +shaders, distinct from static ones. Assign **Dagorrat Material 1** to the +deformable body of the vehicle. Use the following settings: + +Assigning Dagorrat Material 1 in Material Editor + +- **(1) Material Name**: Use descriptive naming for clarity. +- **(2) Material Class**: Set to `dynamic_deformed` to specify the shader type. +- **(3) Slot 0**: Albedo texture. +- **(4) Slot 2**: Normal texture packed with metalness (B channel) and + smoothness (A channel). +- **(5) Slot 7**: Damaged metal albedo texture with a fracture/mask in the alpha + channel. +- **(6) Slot 8**: Damaged metal normal map, packed identically to Slot 2. + +
+ +Next, assign **Dagorrat Material 2** for solid objects using these settings: + +Assigning Dagorrat Material 2 in Material Editor + +- **(1) Material Class**: `dynamic_simple`. +- **(2) Slot 0**: Vehicle's albedo texture. +- **(3) Slot 3**: Packed normal/metalness/smoothness texture. + +
+ +Assign **Dagorrat Material 2** to all non-collision objects within the +**RigidObj** layer. + +```{seealso} +For more information on complex models with hierarchical materials, see +[Proxy materials](../../assets/materials/proxymats.md). +``` + +## Exporting the Vehicle + +To export the completed vehicle: + +1. Select all objects in the **DeformStart** and **RigidObj** layers. +2. Move them to the **EXPORT** layer and make it active. +3. Export with the following Dagor exporter settings: + + Group of Dagor Exporter Settings labels + +4. Save the output file as (with overwriting): +`//develop/assets/entities/vehicles/cars_modern/m123_truck_destr.lod00.dag` + +Ready-to-export scene: +{download}`m123_truck_destr_deform.zip +` + +## Testing the Model + +1. Open the model in [*Asset + Viewer*](../../dagor-tools/asset-viewer/asset-viewer/asset_viewer.md) to test + its destruction mechanics. + + Model in Asset Viewer + + - Select the vehicle model **(0)**. + - Set the physics engine **(1)**. + - Start the simulation **(2)**. + + Steps for starting the simulation process in Asset Viewer + + If errors occur (commonly shader-related), check the console logs + The Console icon + + ```{tip} + If the issues remain unresolved, please contact the author of this document + at {octicon}`mail;1.4em;sd-text-info` . + ``` + +2. Export resources to Dagor binary formats using the **Export All (PC)** option + in the context menu: + + The Export All (PC) option in Asset Viewer menu + + To suppress warnings from older files during export, add the following block + to `application.blk`: + + ```text + logerr_to_con{ + AssetViewer{ + exclude_re:t="(warning: node from)|(Shader 'simple_aces' not found in bin dump)|(Shader 'simple' not found in bin dump)|(Shader 'land_mesh_combined' not found in bin dump)|(has mesh with 0 faces)|(degenerate tri)|(degenerate mesh node)" + } + } + ``` + + This will allow to ignore warnings that outdated shaders are not found. + Ensure there are no errors in the console after building: + + The Asset Viewer console output + +3. Modify the destruction configuration for the vehicle in `rendinst_dmg.blk` + placed at `//develop/gameBase/config/` directory: + + ```text + m123_truck{ + physRes:t="m123_truck_destr_phobj"; + hp:r=40; + impulseThreshold:r=3; + dmPreset:t="metal_light_explosive_props"; + fx:t="ad_car_wreck"; + fxScale:r=1; + material:t="metal"; + } + ``` + Below is an explanation of key parameters for configuring destruction + properties: + + - `m123_truck`: The name of the primary object that will be destructible. + - `m123_truck_destr_phobj`: The name of the virtual object generated from + `m123_truck_destr.lod00.dag`. This represents the destructible version of + the object and is the result of the processes outlined so far. + - `hp:r=40`: Specifies the HP threshold at which the destruction occurs. When + the object's HP falls below this value, it will break apart. + - `impulseThreshold:r=3`: Defines the impulse force required to trigger + destruction. For instance, a collision or impact with a force greater than + this value will cause the object to break. + - `dmPreset:t="metal_light_explosive_props"`: The destruction model preset to + be used. This determines the destruction behavior, including debris + generation and dynamics. + - `fx:t="ad_car_wreck"`: Specifies the particle effect to be used during the + destruction event. For example, this could represent the explosion visuals + triggered when the object is destroyed. Other particle effects can be + reviewed in this file and substituted as needed. + - `fxScale:r=1`: Adjusts the scale of the explosion effect. This parameter + may need fine-tuning to match the size of the vehicle or object being + destroyed. + - `material:t="metal"`: This critical parameter overrides the material + settings defined within the `.dag` file. For instance, if the **custom user + properties** within the `.dag` file specify `materialName:t="wood"`, but + this file specifies `materialName:t="metal"`, the material used for the + destroyed parts will be **metal**. **Always remember** that this parameter + takes precedence over internal `.dag` settings. + + Adjust the parameters as needed, e.g., particle effects, explosion scaling, + or material overrides. + + ```{important} + By carefully adjusting these parameters, you can define how the vehicle + behaves during destruction events, including material properties, effects, + and thresholds for breaking apart. + ``` + +4. Rebuild vfsroms using `create_vfsroms.bat`. + + ```{seealso} + For more information, see + [Resource Building](../../dagor-tools/resource-building/resource_building.md). + ``` + + ```{tip} + If you encounter any errors or have questions regarding this document, please + reach out to the author directly at + {octicon}`mail;1.4em;sd-text-info` . + ``` + +**Placing and Testing the Vehicle in a Level:** + +1. Open the level in the + [*daEditor*](../../dagor-tools/daeditor/daeditor/daeditor.md): + `//develop/levels/avg_proto/apex_test_scene/apex_test_scene.level.blk`. + + The level opened in daEditor + +2. Export the level to a binary format using the top menu. Save the level after + successful export. + + The Export to Game (PC format) option in daEditor menu + +3. Download test mission: {download}`test_01_car.zip + ` + +4. Place it in: + `//develop/gameBase/gameData/missions`. + +5. Open the **Mission Editor**, select the test mission, and start the game + The Play icon. + + The Mission Editor panel + +```{note} +During testing, it is likely that the console will display numerous errors +related to resource mismatches or insufficiently built resources. However, these +errors are not critical for the purpose of testing. + +The daEditor console output during testing + +In case of **assert errors**, initially try ignoring them by pressing the +**Ignore** button. +``` + +If everything is set up correctly, you should see a tank in the environment, +which can be used to collide with the test truck. + +```{tip} +If the issues remain unresolved, please contact the author of this document at +{octicon}`mail;1.4em;sd-text-info` . +``` + +## Fine-Tuning Deformation Parameters for a Vehicle Body + +To achieve realistic vehicle deformation, specific parameters can be configured +in the vehicle body material in *3ds Max*. These settings influence shaders and +allow precise control over deformation behavior. Below is a detailed list of +parameters and their purpose: + +### Shader Parameters + +- `diffuse_tex_scale=1`: Controls the scale of the damage texture's albedo. + Adjust based on the vehicle's size. +- `normals_tex_scale=1`: Similar to `diffuse_tex_scale`, this affects the + normal/metalness/smoothness texture scale. +- `diffuse_power=1`: Determines the intensity of the albedo damage texture. + Default: `1.0`. +- `normals_power=1`: Controls the intensity of the normal/metalness/smoothness + damage texture. Default: `1.0`. +- `max_height=1.2`: A multiplier for maximum deformation height. Default baked + value is `1.0`. Increase (e.g., `1.9`) for larger deformations. +- `springback=0.05`: Defines how much the metal bends back after deformation. + Higher values mean greater restoration. +- `expand_atten=0.5`: Sets the range of deformation expansion, simulating + material characteristics. +- `expand_atten_pow=0.5`: Adjusts the pressure curve during deformation, + affecting how the material bends under force. +- `noise_scale=1.0`: Adds procedural deformation noise. Larger models require + smaller values for realism. +- `noise_power=1.3`: Amplifies the procedural noise intensity for dynamic + deformations. +- `crumple_rnd=0.5`: Randomizes the crumpling intensity, visible only during + dynamic interaction. +- `crumple_force=0.1`: Determines the crumpling force during dynamic + interactions. +- `crumple_dist=0.5`: Specifies the crumpling effect distance during collisions. + +### Testing Parameters In-Game + +To test these parameters effectively: +1. Launch the game and simulate interaction (e.g., a tank driving over a truck). +2. Pause the game using `P`, then open the in-game editor with `F2`. +3. Navigate to the **dynamic_deform** menu: + + The Dynamic Deform menu in game + + - Identify the coordinates **(1)** of the test vehicle body **(2)**. + + Identifying the coordinates and the test vehicle body in daEditor + + - Input the coordinates into the deformation testing block to align the test + box with the vehicle. + + Inputting the coordinates into the deformation testing block to align the test box with the vehicle + +4. Adjust the test deformation box: + - Enable checkboxes to visualize the deformation. + + Enabling the Debug and Debug Draw checkboxes in DynamicDeform menu + + - Use sliders to manipulate the deformation box and observe effects dynamically. + + Using sliders to manipulate the deformation box + + ```{tip} + Always clear deformations after each test using the + The Clear All button + button to reset the vehicle for further iterations. + ``` + +```{important} +For the deformation box to function correctly, ensure it intersects with the +**bounding box** of the deformable object (indicated by a red highlight). +Misalignment may prevent parameter application. +``` + +Ensuring the deformation box intersects with the bounding box of the deformable object + +### Refining Parameters in 3ds Max + +After determining the optimal settings: +1. Adjust parameters like `max_height` (e.g., `1.5`) and `noise_power` (`1.0`) + in the material properties of the vehicle in *3ds Max*. + + Adjusting the Max Height and Noise Power parameters in Material Editor + +2. Re-export the model following the steps outlined earlier. +3. Test the updated model in the game and iterate as needed. + +### Iterative Adjustments and Enhancements + +Testing often reveals areas for refinement, such as missing components like +broken windshield glass. These elements can be added and fine-tuned in +subsequent iterations. + +#### Shading and Coloring Adjustments + +Vehicles may include random color tinting for variety. This is configured using +procedural settings within the +[rendinst_simple](../../assets/shaders/dng-shaders/rendinst_simple.md) shader. + +```{seealso} +For more information, see +[Procedural Rendinst Painting](../../assets/about-assets/procedural-rendinst-painting/procedural_rendinst_painting.md). +``` + +The parameters for `use_painting` and `painting_line` can be specified in the +same location as the **shader dynamic_deformed** parameters, as follows: + +Specifying the Use Painting and Painting Line parameters + +This ensures proper integration and behavior of the painting line within the +shader configuration. + +```{important} +Ensure that static shader settings match their dynamic counterparts to avoid +inconsistencies. +``` + +#### Simulating Broken Glass + +To add shattered glass: +1. Extract original glass models from the `.dag` file. +2. Use [*RayFire*](https://rayfirestudios.com/) for fracturing: + - Set fracture parameters to produce radial breakage patterns. + - Remove overly small fragments to optimize simulation performance. + + Using the RayFire plugin for 3ds Max for fracturing + + ```{tip} + Keep the number of glass fragments below 100 to prevent excessive physics + calculations. + ``` + + Glass fragments in 3ds Max + +3. For each fragment: + - Separate front-facing triangles. + - Adjust pivots to the center for accurate collision generation. + + Separating front-facing triangles and adjusting pivots to the center for accurate collision generation in 3ds Max + +4. Apply a slight **Noise modifier** for realism, then assign a dynamic shader + for glass fragments: + + Applying the NoiseModifier in 3ds Max + +5. Change the `rendinst_pbr_glass` shader to `dynamic_pbr_glass`: + + Changing the Rendinst Pbr Glass shader to Dynamic Pbr Glass shader in 3ds Max + +6. Assigned it to all available glass fragments, generate collisions with + [*Dagor 2 Damages Setup + Tool*](../../dagor-tools/addons/3ds-max/dagor2-3ds-max-tools/damages_setup_tool.md): + + The Dagor 2 Damages Setup Tool option in Gaijin Tools menu in 3ds Max + + Generating collisions with Dagor 2 Damages Setup Tool + + As you can see, all bboxes have their own thickness. + +#### Exporting the Final Model + +After finalizing deformation and additional enhancements: +1. Save the model as `m123_truck_destr.lod00.dag`. + + Saving the model + +2. Rebuild and test resources in the game using the steps outlined in earlier + sections. + +### Final Testing + +The completed scene should include deformation behavior and additional features +like broken glass. For adjustments, iterate on the *3ds Max* scene and test +within the game environment until the desired results are achieved. + +Download the final *3ds Max* scene: +{download}`m123_truck_destr_deform_final.max ` + +## Example: Vehicle Destruction with a Large Tank + +To begin, import the model from the archive: +{download}`zis_6_bz.zip ` + +The primary challenge here is deforming the tank separately. During crushing, +the tank will not only compress vertically but also bulge horizontally. The +truck's cab should also be separated into a distinct object. Before deformation, +the scene should look approximately as follows: + +Separating the tank and the cabin from truck body in 3ds Max + +When assessing the vehicle's construction, note that elements like the fenders +are distinct from the cab, just like the doors, the tank, and the tank's guard +rails. The key is to consider the varying rigidity of these parts. Consequently, +deform these as separate objects. The vehicle's internal components should also +be split into segments based on the material's rigidity. The image below +illustrates a color-coded example of this segmentation: + +Color-coded example of the segmentation in 3ds Max + +Next, as before, apply **FDD modifiers** to deform each object individually. +After initial rough deformation, the scene will look something like this: + +Applying FDD modifiers to deform each object individually in 3ds Max + +Deforming the tank is the most complex task, given its size. Here's an example +of a partially deformed tank: + +The first example of a partially deformed tank on a real truck + +The second example of a partially deformed tank on a real truck + +The third example of a partially deformed tank on a real truck + +Following this initial deformation, fine-tune the shapes manually using **Soft +Selection**. The resulting deformed vehicle should preserve realistic creases +and folds. The tank necks are minimally deformed, while sharp edges exhibit +folds consistent with the model's level of detail. The tank expands horizontally +under pressure from above, creating natural-looking radial folds around the +necks. The detailed appearance of the tank after refinement is shown below: + +Top view of the detailed appearance of the tank after refinement in 3ds Max + +Front view of the detailed appearance of the tank after refinement in 3ds Max + +Side view of the detailed appearance of the tank after refinement in 3ds Max + +### Physics Adjustments Post-Testing + +- **(1) Wheels:** Slightly tilted to naturally detach from the vehicle body and + roll away. +- **(2) Ejection Boxes:** Added to prevent wheels from clipping through the tank + guard rails. These boxes push the wheels outward, creating more natural + movement. +- **(3) Rear Wheel:** Designed to detach along with part of its assembly. + Additional collision boxes are added to replicate a round wheel's behavior, + improving realism. +- **(4) Flat Tire:** Includes a collision box to tilt the vehicle's frame when + it falls. A single collision box is deliberately used here to amplify the + impact. + +Side view of model collision boxes in 3ds Max + +Back view of model collision boxes in 3ds Max + +### Note on Quality vs. Time Constraints + +Balancing time and quality is crucial. While the tank could feature more +advanced details like ruptures or cracks, such improvements require significant +time investment. The chosen approach aims for an optimal balance of detail and +efficiency. + +The scene with the modifier stack and detailed setup: +{download}`zis_6_bz_deform_modificators.zip ` + +The final scene, fully prepared for export with refined collision settings and +other adjustments: +{download}`zis_6_bz_deform.max ` + +## Example: Vehicle Destruction with Extensive Plastic Components + +This example demonstrates the destruction of a vehicle model that incorporates +significant plastic components, such as bumpers and panels. Plastic behaves +differently than metal, often bending, springing back, or detaching entirely +under stress. Here's a step-by-step guide to prepare and simulate such +destruction. + +Download the model: +{download}`arctic_tayga_patrul_551.zip ` + +### Initial Checks + +1. **Ensure proper scale**: + - Verify that the model has no negative scaling and that all scaling values + are `1.0`. + + ```{warning} + Ensuring the correct scale is critical for the pipeline. **If this step is + skipped, everything may need to be redone from scratch later, so address it + upfront**. + ``` + +2. **Inspect model structure**: + - This particular model is relatively new, so it doesn't have scaling issues. + However, older models may require adjustments. + +### Separation of Components + +- Begin by separating **glass** and other **rigid objects** (e.g., detachable + plastic parts like panels, bumpers). +- Objects such as the protective transparent visor often have intricate shapes. + After generating collisions, manually adjust their position and size for + accurate representation. + + The goal is to achieve a realistic breakup of rigid parts that can detach + during collisions. Example result: + + Example of a realistic breakup of rigid parts that can detach during collisions + +### Export and Initial Testing + +1. Assign appropriate materials to the separated components. +2. Export the current setup into the game without adding deformation to the main + body. +3. Evaluate the in-game appearance: + - Rigid parts should separate cleanly during interactions. + - Large gaps (e.g., from detached panels) should be filled or masked + appropriately. + +Example result after initial export: + +Example result after initial export in Asset Viewer + +Intermediate stage of the scene with finished rigid objects and materials: +{download}`arctic_tayga_patrul_551_deform_Rigid_Body_done.max ` + +### Refining the Model + +#### Adding Internal Structure + +Plastic panels often cover empty spaces. To mask these gaps: +1. Duplicate the **deformable panels** and adjust their placement. +2. Use these duplicates to create an **approximate internal frame**: + - Assign a dark texture from the existing material library to simulate depth. + - Ensure the base structure is visually coherent when panels detach. + + Making an approximate internal frame + +- **Black Base (3):** Separate the base along with the driver and passenger + seats as distinct entities. +- **Dashboard and Plastic Covering (2):** Extract these into an individual + entity for separate handling. +- **Side Panels (1):** These are essentially the vehicle's fenders and should + also be separated into distinct entities. They will detach from the main body + during deformation, revealing the black base underneath. + +As per standard practice, further separate parts that will deform independently +due to differences in metal or material rigidity. This ensures a realistic +deformation process tailored to the specific properties of each component. + +```{warning} +1. Do **not** modify smoothing groups or normals during this stage. Adjustments + to these attributes will change vertex indexing, leading to errors during + deformation. +2. Keep the model as an **Editable Mesh** throughout. Avoid converting between + `Edit Poly` and `Edit Mesh` to preserve vertex consistency. +``` + +### Final Scene for Export + +Once the internal structure and rigid body setup are complete: +1. Fine-tune materials and shaders for plastic and metal parts. +2. Test the model in the game environment to verify the detachment and + deformation behaviors. +3. Export the model as a finalized `.max` file: + {download}`arctic_tayga_patrul_551_deform.max ` + +## Example: Vehicle Destruction with Canvas and Fabric Components + +In this section, we'll explore the process of preparing a vehicle with fabric +and canvas elements for dynamic deformation and destruction. The focus will be +on separating, refining, and deforming components such as wooden supports, metal +parts, and fabric material. + +Download the base model: +{download}`renault_ahn.zip ` + +### Initial Checks + +1. **Inspect Transform Settings**: + - Check for negative scaling or non-uniform scaling values (e.g., not equal + to `1.0`). + - Incorrect transforms can cause inverted normals and other issues after + exporting to a dynamic model. + + **Example of incorrect scaling:** + + Example of incorrect scaling in 3ds Max + +2. **Correcting Transforms**: + - Attach the vehicle body to a temporary box object. + - Detach the box and reposition the **Pivot** to the original position, + typically `[0, 0, 0]`. + + ```{important} + Ensure the scaling values are normalized before proceeding. Fixing these + issues after deformation and settings adjustments can be exceedingly + difficult. + ``` + + **Example of correct transformation:** + + Example of correct transformation in 3ds Max + +### Preparing the Canvas and Wooden Supports + +#### Wooden Components + +1. **Separate Wooden Elements**: + - Identify seatbacks, planks, and other wooden components. + - Split them into smaller fragments using *RayFire*: use fracture settings + that mimic natural wood breakage. + + Identifying seatbacks, planks, and other wooden model components + + Splitting them into smaller fragments using RayFireplug in in 3ds Max + +2. **Fracturing Details**: + - Divide each plank into **2-3 pieces** (to meet the 100-object limit per + `.dag` file). + - Apply a **Noise modifier** to simulate splintered edges. + + Dividing each plank into 2-3 pieces to meet the 100-object limit per .dag file in 3ds Max + +#### Metal Components + +**Attach Non-Deforming Metal Parts**: + +- Metal elements like seat mounts and corner brackets should remain rigid + (highlighted in red in the image below). +- Merge these with the main body and assign them a metal material for proper + deformation behavior. + + Metal model elements that should remain rigid are highlighted in red in 3ds Max + +### Organizing the Deformable Objects + +Divide the vehicle into logical deformation groups: + +1. **Side Panels (1)**: These should behave like hinged doors, bending and + opening during a collision. + +2. **Rear Mudguards (5)**: These have different densities and require separate + deformation behavior. + +3. **Fuel Tank (2)**: Sturdier than the body frame; must deform separately. + +4. **Wheel Discs (3)**: Should have independent deformation logic due to their + circular shape. + +5. **Front Fenders**: Their rounded design requires unique deformation + parameters compared to the angular cabin structure. + +Dividing the vehicle into logical deformation groups in 3ds Max + +Intermediate preparation stage of the model: +{download}`renault_ahn_a_deform_ready_to_deform.max ` + +### Initial Deformation with FFD + +**Apply Rough Deformations**: +- Use an **FFD modifier** to simulate large-scale bending and crushing. +- Test deformations at this stage to ensure logical breakage patterns. + +Result after rough deformation: + +The right side view of result after rough deformation + +The left side view of result after rough deformation + +The scene after rough deformation: +{download}`renault_ahn_a_deform_FFD_done.max ` + +### Detailed Deformation + +**Finalize Deformation Details**: +- Add finer details using **Noise modifiers** and **manual adjustments** to + simulate realistic crushing and bending. +- Ensure no overlapping geometry or unnatural stretching. + +Final detailed deformation result: + +The side view of final detailed deformation result + +The front view of final detailed deformation result + +The scene after detailed deformation: +{download}`renault_ahn_a_deform_all_deformation_done.max ` + +### Assigning Materials for the Canvas + +To accurately simulate the canvas (tent), create a unique material with specific +deformation properties: + +**Separate the Canvas Material**: +- Use a dark texture for initial testing. +- Modify deformation parameters for the canvas: + - Disable blending of deformation textures. + - Increase recovery behavior to simulate fabric's spring-back properties. + +Example of material setup for canvas: + +Example of material setup for canvas + +### Final Testing and Export + +1. **In-Game Testing**: + - Verify deformation and recovery behaviors in the game. + - Adjust shader parameters based on observed results. + +2. **Export the Final Model**: + - After testing, export the complete setup for integration into the game. + +Final scene: +{download}`renault_ahn_a_deform.max ` + +By following these steps, you'll achieve a destructible vehicle model with +realistic behavior for both rigid and flexible components, including proper +handling of wooden and fabric elements. + + diff --git a/prog/1stPartyLibs/daScript/examples/test/compilation_fail_tests/const_ref.das b/prog/1stPartyLibs/daScript/examples/test/compilation_fail_tests/const_ref.das index 138f370ad..d3d7f7ec8 100644 --- a/prog/1stPartyLibs/daScript/examples/test/compilation_fail_tests/const_ref.das +++ b/prog/1stPartyLibs/daScript/examples/test/compilation_fail_tests/const_ref.das @@ -1,6 +1,6 @@ require UnitTest -// expect 30102 // once we disable relaxed_pointer_const, we can't pass const to non-const +expect 30102 // passThrough expect 30106 expect 30303:1 // operator_not_found expect 30304:2 // function_not_found diff --git a/prog/1stPartyLibs/daScript/examples/test/compilation_fail_tests/smart_ptr.das b/prog/1stPartyLibs/daScript/examples/test/compilation_fail_tests/smart_ptr.das index f30a45d71..68d41e910 100644 --- a/prog/1stPartyLibs/daScript/examples/test/compilation_fail_tests/smart_ptr.das +++ b/prog/1stPartyLibs/daScript/examples/test/compilation_fail_tests/smart_ptr.das @@ -6,8 +6,8 @@ def pass_by_value_is_unsafe ( p:smart_ptr ) // this will fai pass def move_smart_ptr_is_unsafe_when_not_ref - var a : smart_ptr - a <- new TestObjectSmart + var inscope a : smart_ptr + a <- new TestObjectSmart // 31300: moving values which contain smart pointers is unsafe [export] def test diff --git a/prog/1stPartyLibs/daScript/examples/test/unit_tests/_apply_macro.das b/prog/1stPartyLibs/daScript/examples/test/unit_tests/_apply_macro.das index a1dfb13f4..3b685cf8b 100644 --- a/prog/1stPartyLibs/daScript/examples/test/unit_tests/_apply_macro.das +++ b/prog/1stPartyLibs/daScript/examples/test/unit_tests/_apply_macro.das @@ -4,12 +4,12 @@ require ast require daslib/ast_boost def private prepend_cond(var fn:FunctionPtr; cond:string) - var iblk <- fn.body - var blk <- new [[ExprBlock() at=fn.at]] - var ifm <- new [[ExprCall() at=fn.at, name:=cond]] - var ife <- new [[ExprIfThenElse() at=fn.at, cond<-ifm, if_true<-iblk]] + var inscope iblk <- fn.body + var inscope blk <- new [[ExprBlock() at=fn.at]] + var inscope ifm <- new [[ExprCall() at=fn.at, name:=cond]] + var inscope ife <- new [[ExprIfThenElse() at=fn.at, cond<-ifm, if_true<-iblk]] emplace(blk.list,ife) - fn.body <- blk + fn.body |> move() <| blk [function_macro(name="add_cond")] class AppendCondAnnotation : AstFunctionAnnotation diff --git a/prog/1stPartyLibs/daScript/examples/test/unit_tests/_array_reader.das b/prog/1stPartyLibs/daScript/examples/test/unit_tests/_array_reader.das index 7386c9a35..8f4621fb2 100644 --- a/prog/1stPartyLibs/daScript/examples/test/unit_tests/_array_reader.das +++ b/prog/1stPartyLibs/daScript/examples/test/unit_tests/_array_reader.das @@ -17,10 +17,11 @@ class ArrayReader : AstReaderMacro return true def override visit ( prog:ProgramPtr; mod:Module?; expr:smart_ptr ) : ExpressionPtr let seqStr = string(expr.sequence) - var arrT <- new [[TypeDecl() baseType=Type tInt]] + var inscope arrT <- new [[TypeDecl() baseType=Type tInt]] push(arrT.dim,length(seqStr)) - var mkArr <- new [[ExprMakeArray() at = expr.at, makeType <- arrT]] + var inscope mkArr <- new [[ExprMakeArray() at = expr.at, makeType <- arrT]] for x in seqStr - var mkC <- new [[ExprConstInt() at=expr.at, value=x]] - emplace(mkArr.values,mkC) - return mkArr + if true + var inscope mkC <- new [[ExprConstInt() at=expr.at, value=x]] + emplace(mkArr.values,mkC) + return <-mkArr diff --git a/prog/1stPartyLibs/daScript/examples/test/unit_tests/_enum_total.das b/prog/1stPartyLibs/daScript/examples/test/unit_tests/_enum_total.das index 1863c4ce5..e5f66652e 100644 --- a/prog/1stPartyLibs/daScript/examples/test/unit_tests/_enum_total.das +++ b/prog/1stPartyLibs/daScript/examples/test/unit_tests/_enum_total.das @@ -14,5 +14,5 @@ class EnumTotalAnnotation : AstEnumerationAnnotation if itot < 0 errors := "can't add `total` field" return false - enu.list[itot].value <- new [[ExprConstInt() at=enu.at, value=length(enu.list)-1]] + enu.list[itot].value |> move_new() <| new [[ExprConstInt() at=enu.at, value=length(enu.list)-1]] return true diff --git a/prog/1stPartyLibs/daScript/examples/test/unit_tests/_hint_macros.das b/prog/1stPartyLibs/daScript/examples/test/unit_tests/_hint_macros.das index ff6e14174..ca5af17f2 100644 --- a/prog/1stPartyLibs/daScript/examples/test/unit_tests/_hint_macros.das +++ b/prog/1stPartyLibs/daScript/examples/test/unit_tests/_hint_macros.das @@ -28,6 +28,6 @@ class GetHintFnMacro : AstFunctionAnnotation let hint = hash("{arg2.value}") emplace_new(new_call.arguments, new [[ExprConstUInt64() at=arg2.at, value=hint]]) return new_call - return [[ExpressionPtr]] + return <-[[ExpressionPtr]] diff --git a/prog/1stPartyLibs/daScript/examples/test/unit_tests/_typeinfo_macro_example.das b/prog/1stPartyLibs/daScript/examples/test/unit_tests/_typeinfo_macro_example.das index 43d2ea4fb..05243e631 100644 --- a/prog/1stPartyLibs/daScript/examples/test/unit_tests/_typeinfo_macro_example.das +++ b/prog/1stPartyLibs/daScript/examples/test/unit_tests/_typeinfo_macro_example.das @@ -9,7 +9,7 @@ require daslib/ast_boost class TypeInfoGetAliasName : AstTypeInfoMacro def override getAstChange ( expr:smart_ptr; var errors:das_string ) : ExpressionPtr if expr.typeexpr != null - return new [[ExprConstString() at=expr.at, value:=expr.typeexpr.alias]] + return <- new [[ExprConstString() at=expr.at, value:=expr.typeexpr.alias]] errors := "type is missing or not inferred" - return [[ExpressionPtr]] + return <- [[ExpressionPtr]] diff --git a/prog/1stPartyLibs/daScript/examples/test/unit_tests/make_handle.das b/prog/1stPartyLibs/daScript/examples/test/unit_tests/make_handle.das index 975d092b9..64e22f1fe 100644 --- a/prog/1stPartyLibs/daScript/examples/test/unit_tests/make_handle.das +++ b/prog/1stPartyLibs/daScript/examples/test/unit_tests/make_handle.das @@ -31,9 +31,10 @@ def test unsafe delete ascend_t // ascend with smart-ptr - var ascend_smart_t <- new [[TestObjectSmart() fooData=1]] - assert(ascend_smart_t.fooData==1) - unsafe - delete ascend_smart_t + // TODO: fix this (aot is broken) + // var inscope ascend_smart_t <- new [[TestObjectSmart() fooData=1]] + // assert(ascend_smart_t.fooData==1) + // unsafe + // delete ascend_smart_t return true diff --git a/prog/1stPartyLibs/daScript/examples/test/unit_tests/mksmart_zero.das b/prog/1stPartyLibs/daScript/examples/test/unit_tests/mksmart_zero.das index 2b97f3d49..0e8ab29cd 100644 --- a/prog/1stPartyLibs/daScript/examples/test/unit_tests/mksmart_zero.das +++ b/prog/1stPartyLibs/daScript/examples/test/unit_tests/mksmart_zero.das @@ -5,10 +5,10 @@ typedef [export] def mks () - return [[TestObjectSmartPtr]] + return <- [[TestObjectSmartPtr]] [export] def test - let p <- mks() + var inscope p <- mks() verify(get_ptr(p)==null) return true diff --git a/prog/1stPartyLibs/daScript/examples/test/unit_tests/smart_ptr.das b/prog/1stPartyLibs/daScript/examples/test/unit_tests/smart_ptr.das index 522344291..5d92b9ed9 100644 --- a/prog/1stPartyLibs/daScript/examples/test/unit_tests/smart_ptr.das +++ b/prog/1stPartyLibs/daScript/examples/test/unit_tests/smart_ptr.das @@ -1,9 +1,10 @@ require UnitTest def inside_scope_test - var sptr <- new TestObjectSmart - verify(getTotalTestObjectSmart()==1) - return get_ptr(sptr) + unsafe + var sptr <- new TestObjectSmart + verify(getTotalTestObjectSmart()==1) + return get_ptr(sptr) def scope_test verify(getTotalTestObjectSmart()==0) @@ -16,8 +17,8 @@ def scope_test def inside_move_test verify(getTotalTestObjectSmart()==0) - var t1 <- new TestObjectSmart - var t2 <- t1 // unsafe operation + var inscope t1 <- new TestObjectSmart + var inscope t2 <- t1 // unsafe operation assert(smart_ptr_use_count(t1)==0u) assert(smart_ptr_use_count(t2)==1u) verify(getTotalTestObjectSmart()==1) @@ -25,15 +26,14 @@ def inside_move_test def move_test verify(getTotalTestObjectSmart()==0) - var t <- inside_move_test() - verify(getTotalTestObjectSmart()==1) - unsafe - delete t + if true + var inscope t <- inside_move_test() + verify(getTotalTestObjectSmart()==1) verify(getTotalTestObjectSmart()==0) def ref_count_test verify(getTotalTestObjectSmart()==0) - var sptr <- new TestObjectSmart // ref_count = 1 + var inscope sptr <- new TestObjectSmart // ref_count = 1 verify(getTotalTestObjectSmart()==1) assert(smart_ptr_use_count(sptr)==1u) var ptr = get_ptr(sptr) @@ -41,13 +41,13 @@ def ref_count_test pptr = get_ptr(sptr) assert(sptr==ptr) assert(get_const_ptr(sptr)==ptr) - var qptr : smart_ptr + var inscope qptr : smart_ptr qptr := get_ptr(sptr) // ref_count = 2 assert(smart_ptr_use_count(sptr)==2u) assert(qptr==ptr) assert(get_const_ptr(qptr)==ptr) assert(qptr==sptr) - var fptr := qptr // ref_count = 3 + var inscope fptr := qptr // ref_count = 3 assert(smart_ptr_use_count(sptr)==3u) assert(fptr!=null) assert(get_const_ptr(fptr)==sptr) @@ -72,7 +72,7 @@ def ref_count_test def access_test verify(getTotalTestObjectSmart()==0) - var ptr <- new TestObjectSmart + var inscope ptr <- new TestObjectSmart assert(ptr.fooData == 1234) // . var t = ptr ?. fooData ?? 1 // ?? rvalue assert(t==1234) @@ -94,7 +94,7 @@ def access_test def fn_test verify(getTotalTestObjectSmart()==0) - var ptr <- makeTestObjectSmart() + var inscope ptr <- makeTestObjectSmart() assert(countTestObjectSmart(ptr)==1u) verify(getTotalTestObjectSmart()==1) unsafe diff --git a/prog/1stPartyLibs/daScript/include/daScript/ast/ast.h b/prog/1stPartyLibs/daScript/include/daScript/ast/ast.h index 9c564d9c3..35fb22fe8 100644 --- a/prog/1stPartyLibs/daScript/include/daScript/ast/ast.h +++ b/prog/1stPartyLibs/daScript/include/daScript/ast/ast.h @@ -1419,7 +1419,7 @@ namespace das // rtti bool rtti = false; // create extended RTTI // language - bool relaxed_pointer_const = true; // allow const correctness to be relaxed on pointers + bool relaxed_pointer_const = false; // allow const correctness to be relaxed on pointers bool version_2_syntax = false; // use syntax version 2 bool gen2_make_syntax = false; // only new make syntax is allowed (no [[...]] or [{...}]) bool relaxed_assign = true; // allow = to <- substitution, in certain expressions @@ -1440,7 +1440,7 @@ namespace das bool default_module_public = true; // by default module is 'public', not 'private' bool no_deprecated = false; bool no_aliasing = false; // if true, aliasing will be reported as error, otherwise will turn off optimization - bool strict_smart_pointers = false; // collection of tests for smart pointers, like van inscope for any local, etc + bool strict_smart_pointers = true; // collection of tests for smart pointers, like van inscope for any local, etc bool no_init = false; // if true, then no [init] is allowed in any shape or form bool strict_unsafe_delete = false; // if true, delete of type which contains 'unsafe' delete is unsafe // TODO: enable when need be bool no_members_functions_in_struct = false; // structures can't have member functions diff --git a/prog/1stPartyLibs/daScript/include/daScript/simulate/aot_builtin_matrix.h b/prog/1stPartyLibs/daScript/include/daScript/simulate/aot_builtin_matrix.h index 3a4ad5539..211016a9b 100644 --- a/prog/1stPartyLibs/daScript/include/daScript/simulate/aot_builtin_matrix.h +++ b/prog/1stPartyLibs/daScript/include/daScript/simulate/aot_builtin_matrix.h @@ -64,7 +64,7 @@ namespace das { float4 quat_from_unit_vec_ang(float3 v, float ang); float4 quat_from_euler_vec(float3 v); float4 quat_from_euler(float x, float y, float z); - float3 euler_from_quat(float4 v); + float3 euler_from_quat_vec(float4 v); float4 quat_from_float3x3(const float3x3 & a); float4 quat_from_float3x4(const float3x4 & a); float4 quat_from_float4x4(const float4x4 & a); diff --git a/prog/1stPartyLibs/daScript/include/daScript/simulate/runtime_string.h b/prog/1stPartyLibs/daScript/include/daScript/simulate/runtime_string.h index 6c6101b65..a17d8e17a 100644 --- a/prog/1stPartyLibs/daScript/include/daScript/simulate/runtime_string.h +++ b/prog/1stPartyLibs/daScript/include/daScript/simulate/runtime_string.h @@ -15,5 +15,6 @@ namespace das const string & fixme, CompilationError erc = CompilationError::unspecified ); string reportError ( const char * st, uint32_t stlen, const char * fileName, int row, int col, int lrow, int lcol, int tabSize, const string & message, const string & extra, const string & fixme, CompilationError erc = CompilationError::unspecified ); + int32_t levenshtein_distance ( const char * s1, const char * s2 ); } diff --git a/prog/1stPartyLibs/daScript/include/daScript/simulate/simulate.h b/prog/1stPartyLibs/daScript/include/daScript/simulate/simulate.h index f8fc06a57..e76c93f65 100644 --- a/prog/1stPartyLibs/daScript/include/daScript/simulate/simulate.h +++ b/prog/1stPartyLibs/daScript/include/daScript/simulate/simulate.h @@ -1,5 +1,6 @@ #pragma once +#include "daScript/misc/platform.h" #include "daScript/misc/vectypes.h" #include "daScript/misc/type_name.h" #include "daScript/misc/arraytype.h" @@ -212,7 +213,7 @@ namespace das } public: LineInfo exceptionAt; - std::string exceptionWhat; + das::string exceptionWhat; }; #endif diff --git a/prog/1stPartyLibs/daScript/src/ast/ast_infer_type.cpp b/prog/1stPartyLibs/daScript/src/ast/ast_infer_type.cpp index 88e65a7cb..1e331885e 100644 --- a/prog/1stPartyLibs/daScript/src/ast/ast_infer_type.cpp +++ b/prog/1stPartyLibs/daScript/src/ast/ast_infer_type.cpp @@ -764,82 +764,80 @@ namespace das { return findMatchingFunctions(name, arguments, false, false); } - MatchingFunctions findCandidates ( const string & name, const vector & ) const { - string moduleName, funcName; - splitTypeName(name, moduleName, funcName); - MatchingFunctions result; - getSearchModule(moduleName); - auto hFuncName = hash64z(funcName.c_str()); - program->library.foreach([&](Module * mod) -> bool { - auto itFnList = mod->functionsByName.find(hFuncName); - if ( itFnList != mod->functionsByName.end() ) { - auto & goodFunctions = itFnList->second; - result.reserve(result.size()+goodFunctions.size()); - for ( auto & it : goodFunctions ) { - result.push_back(it.get()); - } - } - return true; - },moduleName); - return result; + // MISSING CANDIDATES + + bool isOperator (const string & s) const { + for ( auto ch : s ) { + if ( ch>='0' && ch<='9' ) return false; + else if ( ch>='a' && ch<='z' ) return false; + else if ( ch>='A' && ch<='Z' ) return false; + else if ( ch=='_' ) return false; + } + return true; } - MatchingFunctions findCandidates ( const string & name, const vector & ) const { - string moduleName, funcName; - splitTypeName(name, moduleName, funcName); - MatchingFunctions result; - getSearchModule(moduleName); - auto hFuncName = hash64z(funcName.c_str()); - program->library.foreach([&](Module * mod) -> bool { - auto itFnList = mod->functionsByName.find(hFuncName); - if ( itFnList != mod->functionsByName.end() ) { - auto & goodFunctions = itFnList->second; - result.reserve(result.size()+goodFunctions.size()); - for ( auto & it : goodFunctions ) { - result.push_back(it.get()); - } - } + bool isCloseEnoughName ( const string & s, const string & t, bool identical ) const { + if ( s==t ) return true; + if ( identical ) return false; + auto ls = s.size(); + auto lt = t.size(); + if ( ls-lt>3 || lt-ls>3 ) return false; // too much difference in length, no way its typo + if ( isOperator(s) || isOperator(t) ) return false; + string upper_s, upper_t; + upper_s.reserve(s.size()); + for ( auto ch : s ) upper_s.push_back((char)toupper(ch)); + upper_t.reserve(t.size()); + for ( auto ch : t ) upper_t.push_back((char)toupper(ch)); + if ( upper_s==upper_t ) return true; + /* + Length ≤ 5: Distance ≤ 1 is likely a typo. + Length 6–10: Distance ≤ 2 is likely a typo. + Length > 10: Distance ≤ 3 might still be a typo. + */ + int longer = int(ls>lt ? ls : lt); + int maxDist = 1; + if ( longer>10 ) maxDist = 3; + else if ( longer>5 ) maxDist = 2; + auto dist = levenshtein_distance(upper_s.c_str(),upper_t.c_str()); + if ( dist <= maxDist ) { return true; - },moduleName); - return result; + } else { + return false; + } } - MatchingFunctions findGenericCandidates ( const string & name, const vector & ) const { - // TODO: better error reporting + MatchingFunctions findMissingCandidates ( const string & name, bool identicalName ) const { string moduleName, funcName; splitTypeName(name, moduleName, funcName); MatchingFunctions result; getSearchModule(moduleName); - auto hFuncName = hash64z(funcName.c_str()); program->library.foreach([&](Module * mod) -> bool { - auto itFnList = mod->genericsByName.find(hFuncName); - if ( itFnList != mod->genericsByName.end() ) { - auto & goodFunctions = itFnList->second; - result.reserve(result.size()+goodFunctions.size()); - for ( auto & it : goodFunctions ) { - result.push_back(it.get()); + mod->functions.foreach([&](const FunctionPtr & fn) -> bool { + if ( isCloseEnoughName(fn->name,funcName,identicalName) ) { + isCloseEnoughName(fn->name,funcName,identicalName); + result.push_back(fn.get()); } - } + return true; + }); return true; },moduleName); return result; } - MatchingFunctions findGenericCandidates ( const string & name, const vector & ) const { + + MatchingFunctions findMissingGenericCandidates ( const string & name, bool identicalName ) const { + // TODO: better error reporting string moduleName, funcName; splitTypeName(name, moduleName, funcName); MatchingFunctions result; getSearchModule(moduleName); - auto hFuncName = hash64z(funcName.c_str()); program->library.foreach([&](Module * mod) -> bool { - auto itFnList = mod->genericsByName.find(hFuncName); - if ( itFnList != mod->genericsByName.end() ) { - auto & goodFunctions = itFnList->second; - result.reserve(result.size()+goodFunctions.size()); - for ( auto & it : goodFunctions ) { - result.push_back(it.get()); + mod->generics.foreach([&](const FunctionPtr & fn) -> bool { + if ( isCloseEnoughName(fn->name,funcName,identicalName) ) { + result.push_back(fn.get()); } - } + return true; + }); return true; },moduleName); return result; @@ -1274,6 +1272,99 @@ namespace das { return result; } + void reportDualFunctionNotFound( const string & name, const string & extra, + const LineInfo & at, const MatchingFunctions & candidateFunctions, + const vector & types, const vector & types2, bool inferAuto, bool inferBlocks, bool reportDetails, + CompilationError cerror, int nExtra, const string & moreError ) { + if ( verbose ) { + TextWriter ss; + ss << name << "("; + bool first = true; + for ( auto &it : types ) { + if ( !first ) { + ss << ", "; + } + first = false; + ss << it->describe(); + } + ss << ") or ("; + first = true; + for ( auto &it : types2 ) { + if ( !first ) { + ss << ", "; + } + first = false; + ss << it->describe(); + } + ss << ")\n"; + if ( func ) { + ss << "while compiling: " << func->describe() << "\n"; + } + if ( !moreError.empty() ) { + ss << moreError; + } + if ( candidateFunctions.size()==0 ) { + ss << "there are no good matching candidates out of " << nExtra << " total functions with the same name\n"; + } else if ( candidateFunctions.size() > 1 ) { + ss << "candidates:\n"; + } else if ( candidateFunctions.size()==1 ) { + ss << (nExtra ? "\nmost likely candidate:\n" : "\ncandidate function:\n"); + } + string moduleName, funcName; + splitTypeName(name, moduleName, funcName); + auto inWhichModule = getSearchModule(moduleName); + for ( auto & missFn : candidateFunctions ) { + auto visM = getFunctionVisModule(missFn); + bool isVisible = isVisibleFunc(inWhichModule,visM); + if ( !reportInvisibleFunctions && !isVisible ) continue; + bool isPrivate = missFn->privateFunction && !canCallPrivate(missFn,inWhichModule,program->thisModule.get()); + if ( !reportPrivateFunctions && isPrivate ) continue; + ss << "\t"; + if ( missFn->module && !missFn->module->name.empty() && !(missFn->module->name=="$") ) + ss << missFn->module->name << "::"; + ss << describeFunction(missFn); + if ( missFn->builtIn ) { + ss << " // builtin"; + } else { + ss << " at " << missFn->at.describe(); + } + ss << "\n"; + if ( missFn->name != name ) { + ss << "\t\tname is similar, typo?\n"; + } + if ( reportDetails ) { + if ( missFn->arguments.size() == types2.size() ) { + ss << describeMismatchingFunction(missFn, types2, inferAuto, inferBlocks); + } else { + ss << describeMismatchingFunction(missFn, types, inferAuto, inferBlocks); + } + } + if ( !isVisible ) { + ss << "\t\tmodule " << visM->name << " is not visible directly from "; + if ( inWhichModule->name.empty()) { + ss << "the current module\n"; + } else { + ss << inWhichModule->name << "\n"; + } + } + if ( isPrivate ) { + ss << "\t\tfunction is private"; + if ( missFn->module && !missFn->module->name.empty() ) { + ss << " to module " << missFn->module->name; + } + ss << "\n"; + } + } + if ( nExtra>0 && candidateFunctions.size()!=0 ) { + ss << "also " << nExtra << " more candidates\n"; + } + error(extra, ss.str(), "", at, cerror); + } else { + error(extra, "", "", at, cerror); + } + } + + void reportFunctionNotFound( const string & name, const string & extra, const LineInfo & at, const MatchingFunctions & candidateFunctions, const vector & types, bool inferAuto, bool inferBlocks, bool reportDetails, @@ -1322,6 +1413,9 @@ namespace das { ss << " at " << missFn->at.describe(); } ss << "\n"; + if ( missFn->name != name ) { + ss << "\t\tname is similar, typo?\n"; + } if ( reportDetails ) { ss << describeMismatchingFunction(missFn, types, inferAuto, inferBlocks); } @@ -2009,7 +2103,13 @@ namespace das { } else { varT->ref = false; TypeDecl::applyAutoContracts(varT, var->type); + if ( !relaxedPointerConst ) { // var a = Foo? const -> var a : Foo const? = Foo? const + if ( varT->isPointer() && !varT->constant && var->init->type->constant ) { + varT->firstType->constant = true; + } + } var->type = varT; + var->type->sanitize(); reportAstChanged(); } } else if ( !canCopyOrMoveType(var->type,var->init->type,TemporaryMatters::no,var->init.get(), @@ -5403,8 +5503,22 @@ namespace das { expr->type->constant |= tupleT->constant; } } else if ( !expr->type ) { - error("field '" + expr->name + "' not found in " + describeType(expr->value->type), "", "", - expr->at, CompilationError::cant_get_field); + if ( verbose && valT ) { + MatchingFunctions mf; + collectMissingOperators(".`"+expr->name,mf,false); + collectMissingOperators(".",mf,true); + if ( !mf.empty() ) { + reportDualFunctionNotFound(".`"+expr->name, "field '" + expr->name + "' not found in " + describeType(valT), + expr->at, mf, {valT}, {valT, make_smart(Type::tString)}, true, false, true, + CompilationError::cant_get_field, 0, ""); + } else { + error("field '" + expr->name + "' not found in " + describeType(valT), "", "", + expr->at, CompilationError::cant_get_field); + } + } else { + error("field '" + expr->name + "' not found in " + describeType(valT), "", "", + expr->at, CompilationError::cant_get_field); + } return Visitor::visit(expr); } else { expr->type->constant |= valT->constant; @@ -5412,7 +5526,14 @@ namespace das { propagateTempType(expr->value->type, expr->type); // a#.foo = foo# return Visitor::visit(expr); } - // ExprSafeField + void collectMissingOperators ( const string & opN, MatchingFunctions & mf, bool identicalName ) { + auto opName = "_::" + opN; + auto can1 = findMissingCandidates(opName,identicalName); + auto can2 = findMissingGenericCandidates(opName,identicalName); + mf.reserve(mf.size()+can1.size()+can2.size()); + mf.insert(mf.end(), can1.begin(), can1.end()); + mf.insert(mf.end(), can2.begin(), can2.end()); + } virtual ExpressionPtr visit ( ExprSafeField * expr ) override { if ( !expr->value->type || expr->value->type->isAliasOrExpr() ) return Visitor::visit(expr); // failed to infer if ( !expr->no_promotion ) { @@ -5421,8 +5542,22 @@ namespace das { } auto valT = expr->value->type; if ( !valT->isPointer() || !valT->firstType ) { - error("can only safe dereference a pointer to a tupe, a structure or a handle " + describeType(valT), "", "", - expr->at, CompilationError::cant_get_field); + if ( verbose && !expr->no_promotion ) { + MatchingFunctions mf; + collectMissingOperators("?.`"+expr->name,mf,false); + collectMissingOperators("?.",mf,true); + if ( !mf.empty() ) { + reportDualFunctionNotFound("?.`"+expr->name, "can only safe dereference a pointer to a tuple, a structure or a handle " + describeType(valT), + expr->at, mf, {expr->value->type}, {expr->value->type, make_smart(Type::tString)}, true, false, true, + CompilationError::cant_get_field, 0, ""); + } else { + error("can only safe dereference a pointer to a tuple, a structure or a handle " + describeType(valT), "", "", + expr->at, CompilationError::cant_get_field); + } + } else { + error("can only safe dereference a pointer to a tuple, a structure or a handle " + describeType(valT), "", "", + expr->at, CompilationError::cant_get_field); + } return Visitor::visit(expr); } expr->value = Expression::autoDereference(expr->value); @@ -5980,6 +6115,9 @@ namespace das { return Visitor::visit(expr); } // ExprMove + bool isVoidOrNothing ( const TypeDeclPtr & ptr ) const { + return !ptr || ptr->isVoid(); + } bool canCopyOrMoveType ( const TypeDeclPtr & leftType, const TypeDeclPtr & rightType, TemporaryMatters tmatter, Expression * leftExpr, const string & errorText, CompilationError errorCode, const LineInfo & at ) const { if ( leftType->baseType==Type::tPointer ) { @@ -5993,9 +6131,9 @@ namespace das { } } if ( !relaxedPointerConst ) { - if ( !leftType->constant && rightType->constant && !(leftType->firstType && leftType->firstType->constant) ) { // Foo const? = Foo? const ok. + if ( !leftType->constant && rightType->constant && !(leftType->firstType && leftType->firstType->constant) && !isVoidOrNothing(leftType->firstType) ) { error(errorText + "; "+ describeType(leftType) + " = " + describeType(rightType), - "can't copy constant to non-constant pointer. needs to be " + (leftType->firstType ? describeType(leftType->firstType) : "void") + " const?", "", at, errorCode); + "can't copy constant to non-constant pointer. needs to be " + describeType(leftType->firstType) + " const?", "", at, errorCode); return false; } } @@ -7145,6 +7283,11 @@ namespace das { } else { varT->ref = false; TypeDecl::applyAutoContracts(varT, var->type); + if ( !relaxedPointerConst ) { // var a = Foo? const -> var a : Foo const? = Foo? const + if ( varT->isPointer() && !varT->constant && var->init->type->constant ) { + varT->firstType->constant = true; + } + } var->type = varT; var->type->sanitize(); reportAstChanged(); @@ -7415,8 +7558,8 @@ namespace das { void reportMissing ( ExprNamedCall * expr, const vector& nonNamedArguments, const string & msg, bool reportDetails, CompilationError cerror = CompilationError::function_not_found) { if ( verbose ) { - auto can1 = findCandidates(expr->name, expr->arguments); - auto can2 = findGenericCandidates(expr->name, expr->arguments); + auto can1 = findMissingCandidates(expr->name, false); + auto can2 = findMissingGenericCandidates(expr->name, false); can1.reserve(can1.size()+can2.size()); can1.insert(can1.end(), can2.begin(), can2.end()); auto nExtra = prepareCandidates(can1, nonNamedArguments, expr->arguments, true, true); @@ -7479,8 +7622,8 @@ namespace das { const string & msg, bool reportDetails, CompilationError cerror = CompilationError::function_not_found) { if ( verbose ) { - auto can1 = findCandidates(expr->name, types); - auto can2 = findGenericCandidates(expr->name, types); + auto can1 = findMissingCandidates(expr->name, false); + auto can2 = findMissingGenericCandidates(expr->name, false); can1.reserve(can1.size()+can2.size()); can1.insert(can1.end(), can2.begin(), can2.end()); auto nExtra = prepareCandidates(can1, types, true, true); @@ -8625,22 +8768,46 @@ namespace das { } } else { TextWriter extra; - if ( verbose ) { - vector args; - args.push_back(expr->makeType); - args.push_back(decl->value->type); - auto opName = "_::.`" + decl->name + "`clone"; - auto funs = findMatchingFunctions(opName, args); - auto gens = findMatchingGenerics(opName, args); - if ( funs.size()==1 || gens.size()==1 ) { - if ( strictProperties ) { + vector args; + args.push_back(expr->makeType); + args.push_back(decl->value->type); + auto compareName = ".`" + decl->name + "`clone"; + auto opName = "_::" + compareName; + auto funs = findMatchingFunctions(opName, args); + auto gens = findMatchingGenerics(opName, args); + bool brokenStrictProperty = false; + if ( funs.size()==1 || gens.size()==1 ) { + if ( strictProperties ) { + brokenStrictProperty = true; + if ( verbose ) { extra << "since there is operator ." << decl->name << " := (" << expr->makeType->structType->name << "," << decl->value->type->describe() << ") , try " << decl->name << " := " << *(decl->value); - } else { - convertCloneSemanticsToExpression(expr,index,decl); - return nullptr; + } + } else { + convertCloneSemanticsToExpression(expr,index,decl); + return nullptr; + } + } + if ( !brokenStrictProperty && verbose ) { + auto can1 = findMissingCandidates(opName, false); + auto can2 = findMissingGenericCandidates(opName, false); + can1.reserve(can1.size()+can2.size()); + can1.insert(can1.end(), can2.begin(), can2.end()); + for ( auto & fn : can1 ) { + if ( fn->isClassMethod && fn->arguments.size()==2 ) { + if ( fn->name != compareName ) { + // .`name`clone + auto realName = fn->name.substr(2,fn->name.size()-8); + extra << "property name " << realName << " is similar, typo?\n"; + if ( !fn->arguments[1]->type->isSameType(*args[1],RefMatters::yes,ConstMatters::yes,TemporaryMatters::yes) ) { + extra << "\t" << describeType(fn->arguments[1]->type) << " can't be initialized with " << decl->value->type->describe() << "\n"; + } + + } else if ( !fn->arguments[1]->type->isSameType(*args[1],RefMatters::yes,ConstMatters::yes,TemporaryMatters::yes) ) { + extra << "property " << decl->name << " : " << describeType(fn->arguments[1]->type) << " can't be initialized with " << decl->value->type->describe() << "\n"; + } } } } diff --git a/prog/1stPartyLibs/daScript/src/ast/ast_typedecl.cpp b/prog/1stPartyLibs/daScript/src/ast/ast_typedecl.cpp index 872c18584..495af388c 100644 --- a/prog/1stPartyLibs/daScript/src/ast/ast_typedecl.cpp +++ b/prog/1stPartyLibs/daScript/src/ast/ast_typedecl.cpp @@ -917,6 +917,7 @@ namespace das } else if ( baseType == Type::tPointer ) { if ( smartPtr || smartPtrNative ) return true; // TODO: fix this if ( !firstType ) return true; // void pointer can always be cloned + if ( firstType->isVoid() ) return true; // void pointer can always be cloned if ( firstType->constant ) return true; // can clone to const pointer, i.e. Foo const? return false; } else if (baseType == Type::tBlock) { diff --git a/prog/1stPartyLibs/daScript/src/builtin/module_builtin_ast_serialize.cpp b/prog/1stPartyLibs/daScript/src/builtin/module_builtin_ast_serialize.cpp index f26fdba4c..4bdf43337 100644 --- a/prog/1stPartyLibs/daScript/src/builtin/module_builtin_ast_serialize.cpp +++ b/prog/1stPartyLibs/daScript/src/builtin/module_builtin_ast_serialize.cpp @@ -2092,6 +2092,7 @@ namespace das { << value.no_deprecated << value.no_aliasing << value.strict_smart_pointers + << value.relaxed_pointer_const << value.no_init << value.strict_unsafe_delete << value.no_optimizations @@ -2195,7 +2196,7 @@ namespace das { } uint32_t AstSerializer::getVersion () { - static constexpr uint32_t currentVersion = 53; + static constexpr uint32_t currentVersion = 54; return currentVersion; } diff --git a/prog/1stPartyLibs/daScript/src/builtin/module_builtin_math.cpp b/prog/1stPartyLibs/daScript/src/builtin/module_builtin_math.cpp index 8595576bc..645522fbc 100644 --- a/prog/1stPartyLibs/daScript/src/builtin/module_builtin_math.cpp +++ b/prog/1stPartyLibs/daScript/src/builtin/module_builtin_math.cpp @@ -517,11 +517,11 @@ namespace das { } float4 quat_from_euler_vec(float3 v) { - return v_quat_from_euler_yzx(v_make_vec3f(v.z, v.x, v.y)); + return v_quat_from_euler(v_ldu(&v.x)); } float4 quat_from_euler(float x, float y, float z) { - return v_quat_from_euler_yzx(v_make_vec3f(z, x, y)); + return v_quat_from_euler(v_make_vec4f(x, y, z, 0.f)); } float3 euler_from_quat_vec(float4 v) { diff --git a/prog/1stPartyLibs/daScript/src/builtin/module_builtin_rtti.cpp b/prog/1stPartyLibs/daScript/src/builtin/module_builtin_rtti.cpp index 0661fb7f0..b0af2854b 100644 --- a/prog/1stPartyLibs/daScript/src/builtin/module_builtin_rtti.cpp +++ b/prog/1stPartyLibs/daScript/src/builtin/module_builtin_rtti.cpp @@ -717,6 +717,7 @@ namespace das { // rtti addField("rtti"); // language + addField("relaxed_pointer_const"); addField("version_2_syntax"); addField("gen2_make_syntax"); addField("relaxed_assign"); diff --git a/prog/1stPartyLibs/daScript/src/builtin/network.das b/prog/1stPartyLibs/daScript/src/builtin/network.das index 109a70f6b..1c2acaccb 100644 --- a/prog/1stPartyLibs/daScript/src/builtin/network.das +++ b/prog/1stPartyLibs/daScript/src/builtin/network.das @@ -17,12 +17,12 @@ class Server def init ( port : int ) : bool return server_init(_server,port) def restore ( var shared_orphan : smart_ptr& ) - _server <- shared_orphan + _server |> move() <| shared_orphan let classInfo = class_info(self) unsafe server_restore(_server,addr(self),classInfo) def save ( var shared_orphan : smart_ptr& ) - shared_orphan <- _server + shared_orphan |> move() <| _server def has_session : bool return _server != null def is_open : bool diff --git a/prog/1stPartyLibs/daScript/src/parser/ds2_parser.cpp b/prog/1stPartyLibs/daScript/src/parser/ds2_parser.cpp index 692a6422c..4ca12dcb1 100644 --- a/prog/1stPartyLibs/daScript/src/parser/ds2_parser.cpp +++ b/prog/1stPartyLibs/daScript/src/parser/ds2_parser.cpp @@ -936,7 +936,7 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 2 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 11116 +#define YYLAST 11243 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 210 @@ -945,7 +945,7 @@ union yyalloc /* YYNRULES -- Number of rules. */ #define YYNRULES 784 /* YYNSTATES -- Number of states. */ -#define YYNSTATES 1438 +#define YYNSTATES 1439 /* YYMAXUTOK -- Last valid token kind. */ #define YYMAXUTOK 437 @@ -1230,7 +1230,7 @@ yysymbol_name (yysymbol_kind_t yysymbol) } #endif -#define YYPACT_NINF (-1259) +#define YYPACT_NINF (-1263) #define yypact_value_is_default(Yyn) \ ((Yyn) == YYPACT_NINF) @@ -1244,150 +1244,150 @@ yysymbol_name (yysymbol_kind_t yysymbol) STATE-NUM. */ static const yytype_int16 yypact[] = { - -1259, 21, -1259, -1259, 30, -52, -12, 337, -1259, -67, - 337, 337, 337, -1259, 28, 219, -1259, -1259, -70, 34, - -1259, -1259, 407, -1259, 96, -1259, -1259, -1259, -1259, -1259, - -1259, -1259, -1259, -1259, -1259, 51, -1259, 105, 129, 150, - -1259, -1259, -12, 5, -1259, -1259, -1259, 169, 172, -1259, - -1259, 96, 236, 284, 295, 330, 327, -1259, -1259, -1259, - 219, 219, 219, 294, -1259, 498, 217, -1259, -1259, -1259, - -1259, -1259, 477, 499, 506, -1259, 508, 23, 30, 381, - -52, 352, 379, -1259, 384, 389, -1259, -1259, -1259, 520, - -1259, -1259, -1259, -1259, 436, 442, -1259, -1259, -49, 30, - 219, 219, 219, 219, -1259, -1259, -1259, -1259, -1259, -1259, - -1259, 460, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, - -1259, -1259, -1259, 518, 114, -1259, -1259, -1259, -1259, 547, - -1259, -1259, 448, -1259, -1259, -1259, 449, 493, 494, -1259, - -1259, 507, -1259, -106, -1259, 427, 534, 498, 1737, -1259, - 505, 569, 479, -1259, -1259, -1259, 531, -1259, -1259, -1259, - -1259, -1259, -1259, -1259, 55, -1259, 1583, -1259, -1259, -1259, - -1259, -1259, 9647, -1259, -1259, -1259, -1259, -1259, -1259, -1259, - -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, - -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, 654, 655, - -1259, 487, 528, 402, 535, -1259, 542, -1259, 30, 500, - 544, -1259, -1259, -1259, 114, -1259, 522, 524, 525, 509, - 526, 530, -1259, -1259, -1259, 511, -1259, -1259, -1259, -1259, - -1259, 538, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, - -1259, -1259, -1259, 539, -1259, -1259, -1259, 540, 543, -1259, - -1259, -1259, -1259, 545, 546, 514, 28, -1259, -1259, -1259, - -1259, -1259, -1259, 127, 552, 551, -1259, -1259, 558, 559, - -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, - -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, - 560, 523, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, - -1259, -1259, -1259, -1259, 707, -1259, -1259, -1259, -1259, -1259, - -1259, -1259, -1259, -1259, -1259, -1259, -1259, 573, 533, -1259, - -1259, -109, 557, -1259, -1259, -1259, -1259, -1259, -1259, -1259, - -1259, -1259, -1259, -1259, -1259, 561, 570, -1259, 30, -1259, - 369, -1259, -1259, -1259, -1259, -1259, 6365, -1259, -1259, 577, - -1259, 278, 303, 304, -1259, -1259, 6365, 62, -1259, -1259, - -1259, 32, -1259, -1259, -1259, 0, 3453, -1259, 541, 1298, - -1259, 563, 1437, 343, -1259, -1259, -1259, -1259, 583, 614, - -1259, 550, -1259, 57, -1259, -93, 1583, -1259, 1875, 585, - 28, -1259, -1259, -1259, -1259, 586, 1583, -1259, 99, 1583, - 1583, 1583, 564, 566, -1259, -1259, 53, 28, 567, 14, - -1259, 81, 562, 571, 578, 565, 580, 572, 134, 581, - -1259, 199, 584, 590, 6365, 6365, 574, 579, 587, 588, - 591, 599, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, - -1259, 3649, 6365, 6365, 6365, 6365, 6365, 3065, 6365, -1259, - 554, -1259, -1259, -1259, 602, -1259, -1259, -1259, -1259, 568, - -1259, -1259, -1259, -1259, -1259, -1259, 56, 915, -1259, 604, - -1259, -1259, -1259, -1259, -1259, -1259, 1583, 1583, 589, 623, - 1583, 487, 1583, 487, 1583, 487, 6708, 624, 6702, -1259, - 6365, -1259, -1259, -1259, -1259, 606, -1259, -1259, 9159, 3843, - -1259, -1259, 649, -1259, -53, -1259, -1259, 417, -1259, 552, - 644, 635, 417, -1259, 646, -1259, -1259, 6365, -1259, -1259, - 309, -74, -1259, 552, -1259, 615, -1259, -1259, 616, 4037, - -1259, 528, 4231, 617, 657, -1259, 651, 669, 4425, -25, - 4619, 788, -1259, 656, 658, 621, 817, -1259, -1259, -1259, - -1259, -1259, 659, -1259, 660, 661, 662, 663, 665, -1259, - 763, -1259, 666, 9531, 667, -1259, 664, -1259, 18, -1259, - 108, -1259, -1259, -1259, 6365, 332, 419, 653, 367, -1259, - -1259, -1259, 636, -1259, -1259, 250, -1259, 668, 670, 671, - -1259, 6365, 1583, 6365, 6365, -1259, -1259, 6365, -1259, 6365, - -1259, 6365, -1259, -1259, 6365, -1259, 1583, 46, 46, 6365, - 6365, 6365, 6365, 6365, 6365, 513, 309, 9678, -1259, 674, - 46, 46, -55, 46, 46, 309, 827, 676, 10335, 676, - 194, 2673, 843, -1259, 640, 568, -1259, 10825, 10857, 6365, - 6365, -1259, -1259, 6365, 6365, 6365, 6365, 687, 6365, 19, - 6365, 6365, 6365, 6365, 6365, 6365, 6365, 6365, 6365, 4813, - 6365, 6365, 6365, 6365, 6365, 6365, 6365, 6365, 6365, 6365, - 10913, 6365, -1259, 5007, 439, 467, -1259, -1259, -19, 469, - 557, 470, 557, 472, 557, -1259, 326, -1259, 339, -1259, - 1583, 652, 676, -1259, -1259, -1259, 9190, -1259, 679, 1583, - -1259, -1259, 1583, -1259, -1259, 6738, 673, 814, -1259, 145, - -1259, 6365, 309, 6365, 10335, 851, 6365, 10335, 6365, 688, - -1259, 685, 713, 10335, -1259, 6365, 10335, 699, -1259, -1259, - 6365, 675, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -64, - -1259, 6365, 6365, 6365, 6365, 6365, 6365, 6365, 6365, 6365, - 6365, 6365, 6365, 6365, 6365, 6365, 6365, 6365, 6365, 6365, - 585, -1259, -1259, 862, 479, -1259, 6365, 9777, -1259, -1259, - -1259, 1583, 1583, 1583, 1583, 3259, 709, 6365, 1583, -1259, - -1259, -1259, 1583, 676, 341, 674, 6830, 1583, 1583, 6929, - 1583, 6960, 1583, 676, 1583, 1583, 676, 1583, 686, 7059, - 7151, 7184, 7276, 7375, 7406, -1259, 6365, -84, 16, 6365, - 6365, 702, 22, 309, 6365, 677, 678, 680, 681, 305, - -1259, -1259, 90, 682, -18, 2869, -1259, 111, 698, 683, - 690, 487, 2080, -1259, 843, 692, 694, -1259, -1259, 703, - 696, -1259, -1259, 1042, 1042, 672, 672, 175, 175, 700, - 8, 701, -1259, 9280, -59, -59, 604, 1042, 1042, 823, - 10538, 10570, 10424, 10945, 9866, 10652, 457, 10684, 672, 672, - 1236, 1236, 8, 8, 8, 126, 6365, 704, 705, 237, - 6365, 878, 706, 9311, -1259, 147, -1259, -1259, 728, -1259, - -1259, 710, -1259, 711, -1259, 717, -1259, 6708, -1259, 624, - 344, 552, -1259, -1259, -1259, -1259, 552, 552, -1259, 6365, - 729, -1259, 731, -1259, 1583, -1259, 6365, 7505, 36, 10335, - 528, 10335, 7597, 6365, -1259, -1259, 10335, -1259, 7630, 6365, - 708, 861, 745, -1259, 374, -1259, 10335, 10335, 10335, 10335, - 10335, 10335, 10335, 10335, 10335, 10335, 10335, 10335, 10335, 10335, - 10335, 10335, 10335, 10335, 10335, -1259, 743, 537, 848, 744, - 9898, -1259, -1259, -1259, -1259, 552, 732, 733, 475, 291, - 165, 714, 715, 351, 7722, 480, 1583, 1583, 1583, 736, - 719, 712, 1583, 720, -1259, 737, 742, -1259, 746, -1259, - 747, 723, 748, 749, 725, 757, 843, -1259, -1259, -1259, - -1259, -1259, 739, 9980, 6365, 10335, -1259, -1259, 6365, 40, - 10335, -1259, -1259, 6365, 6365, 1583, 487, 119, -1259, 753, - 6365, 6365, 6365, 256, 6559, -1259, 371, -1259, -69, 557, - -1259, 487, -1259, 6365, -1259, 6365, 5201, 6365, -1259, 764, - 750, -1259, -1259, 6365, 761, -1259, 9401, 6365, 5395, 762, - -1259, 9432, -1259, 5589, -1259, 6365, -1259, -1259, -1259, -1259, - -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, - -1259, 765, 1583, 7821, -1259, 926, -17, 10335, 528, 6365, - -1259, 528, 10335, 2285, 528, 7852, 6365, 809, -1259, 191, - 810, 1583, 99, -1259, -1259, -1259, 440, -1259, -1, -1259, - -1259, -1259, -1259, -1259, 767, -1259, -1259, -1259, 769, 813, - -1259, -1259, 790, 797, 798, -1259, -1259, 6365, 799, -1259, - -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, 76, - 5783, -1259, 421, 424, 6365, 7951, 8043, 800, 557, -1259, - 8076, 10335, 10335, 781, 2869, 783, 189, 828, 829, 784, - 831, 833, -1259, 196, 12, 557, 1583, 8168, 1583, 8267, - -1259, 197, 8298, -1259, 6365, 10456, 6365, -1259, 8397, -1259, - 210, 6365, -1259, -1259, -1259, 213, -1259, -1259, -1259, 6365, - 552, -1259, 834, 6365, -1259, 242, -1259, -1259, 519, 985, - 8489, -1259, 836, 313, 956, 201, 6365, 967, -1, -1259, - -1259, 537, 812, 815, -1259, -1259, 6365, 816, -1259, -1259, - -1259, -1259, 818, 821, 674, 819, 6365, 6365, 6365, 824, - 933, 842, 845, 5977, -1259, -1259, 255, 6365, 6365, 425, - -1259, -1259, -1259, 832, 222, -1259, 276, 6365, 6365, 6365, - -1259, -1259, 853, -1259, -1259, -69, -1259, 6171, -1259, -1259, - 528, 835, -1259, 483, -1259, -1259, -1259, 1583, 8522, 8614, - -1259, -1259, 8713, -1259, 822, -1259, 10335, 528, 528, -1259, - -1259, 846, -1259, 2479, 847, -1259, -1259, 1583, 99, 860, - -1259, 6365, 10012, -1259, -1259, 967, 309, 933, 933, 8744, - 852, 854, 856, 857, 6365, -1259, -1259, 6365, 672, 672, - 672, 6365, -1259, -1259, 933, 291, -1259, 8843, -1259, 864, - 10094, 6365, 320, -1259, 6365, 6365, 863, 8935, 10335, 10335, - 865, -1259, 6365, 10424, -1259, -1259, -1259, 488, -1259, -1259, - -1259, -1259, -1259, -1259, 6365, -1259, -1259, -1259, -1259, -1259, - 10335, -1259, 99, 6365, -1259, 10128, -1259, 1737, -1259, -1259, - -35, -35, -1259, 6365, 933, 933, 291, 866, 867, 676, - -35, 698, 869, -1259, 951, 870, 874, 10094, -1259, 320, - 10335, 10335, -1259, 257, -1259, 10456, -1259, -1259, -1259, 8968, - 6365, 10210, -1259, 880, 1737, 291, 698, 888, -1259, 873, - 875, 9060, -35, -35, 876, -1259, -1259, 877, 879, -1259, - 6365, -1259, -1259, 882, -1259, 6365, 6365, -1259, 528, 10299, - -1259, -1259, 528, 263, 883, -1259, -1259, -1259, -1259, 881, - 884, -1259, -1259, -1259, 10335, -1259, 10335, 10335, 519, -1259, - -1259, -1259, 291, -1259, -1259, -1259, 269, -1259 + -1263, 22, -1263, -1263, 72, 77, 0, 436, -1263, -97, + 436, 436, 436, -1263, 196, 67, -1263, -1263, -4, 79, + 92, -1263, 356, -1263, 278, -1263, -1263, -1263, -1263, -1263, + -1263, -1263, -1263, -1263, -1263, -7, -1263, 76, 166, 257, + -1263, -1263, 0, 17, -1263, -1263, -1263, 296, 298, -1263, + -1263, 278, 323, 350, 393, 404, 405, -1263, -1263, -1263, + 67, 67, 67, 349, -1263, 465, 124, -1263, -1263, -1263, + -1263, -1263, -1263, 467, 474, 483, -1263, 484, 21, 72, + 412, 77, 376, 410, -1263, 422, 461, -1263, -1263, -1263, + 485, -1263, -1263, -1263, -1263, 466, 456, -1263, -1263, -59, + 72, 67, 67, 67, 67, -1263, -1263, -1263, -1263, -1263, + -1263, -1263, 476, -1263, -1263, -1263, -1263, -1263, -1263, -1263, + -1263, -1263, -1263, -1263, 492, 123, -1263, -1263, -1263, -1263, + 593, -1263, -1263, 480, -1263, -1263, -1263, 500, 501, 502, + -1263, -1263, 510, -1263, 49, -1263, 241, 537, 465, 1738, + -1263, 497, 569, 471, -1263, -1263, -1263, 498, -1263, -1263, + -1263, -1263, -1263, -1263, -1263, 71, -1263, 1584, -1263, -1263, + -1263, -1263, -1263, 9648, -1263, -1263, -1263, -1263, -1263, -1263, + -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, + -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, 645, + 646, -1263, 478, 514, 397, 515, -1263, 525, -1263, 72, + 482, 526, -1263, -1263, -1263, 123, -1263, 506, 508, 511, + 493, 512, 517, -1263, -1263, -1263, 499, -1263, -1263, -1263, + -1263, -1263, 518, -1263, -1263, -1263, -1263, -1263, -1263, -1263, + -1263, -1263, -1263, -1263, 520, -1263, -1263, -1263, 521, 522, + -1263, -1263, -1263, -1263, 523, 524, 505, 196, -1263, -1263, + -1263, -1263, -1263, -1263, 9, 529, 550, -1263, -1263, 552, + 553, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, + -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, + -1263, 554, 495, -1263, -1263, -1263, -1263, -1263, -1263, -1263, + -1263, -1263, -1263, -1263, -1263, 695, -1263, -1263, -1263, -1263, + -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, 558, 519, + -1263, -1263, -73, 540, -1263, -1263, -1263, -1263, -1263, -1263, + -1263, -1263, -1263, -1263, -1263, -1263, 541, 555, -1263, 72, + -1263, 344, -1263, -1263, -1263, -1263, -1263, 6366, -1263, -1263, + 562, -1263, 261, 273, 279, -1263, -1263, 6366, 63, -1263, + -1263, -1263, -2, -1263, -1263, -1263, -6, 3454, -1263, 527, + 1299, -1263, 548, 1438, 212, -1263, -1263, -1263, -1263, 566, + 597, -1263, 533, -1263, 50, -1263, -69, 1584, -1263, 1876, + 570, 196, -1263, -1263, -1263, -1263, 577, 1584, -1263, 35, + 1584, 1584, 1584, 546, 556, -1263, -1263, 54, 196, 557, + 15, -1263, 65, 535, 560, 565, 547, 568, 551, 126, + 572, -1263, 144, 578, 579, 6366, 6366, 561, 563, 567, + 571, 573, 575, -1263, -1263, -1263, -1263, -1263, -1263, -1263, + -1263, -1263, 3650, 6366, 6366, 6366, 6366, 6366, 3066, 6366, + -1263, 559, -1263, -1263, -1263, 580, -1263, -1263, -1263, -1263, + 583, -1263, -1263, -1263, -1263, -1263, -1263, -49, 916, -1263, + 582, -1263, -1263, -1263, -1263, -1263, -1263, 1584, 1584, 564, + 609, 1584, 478, 1584, 478, 1584, 478, 6709, 626, 6703, + -1263, 6366, -1263, -1263, -1263, -1263, 585, -1263, -1263, 9160, + 3844, -1263, -1263, 631, -1263, -54, -1263, -1263, 372, -1263, + 529, 623, 615, 372, -1263, 634, -1263, -1263, 6366, -1263, + -1263, 18, -89, -1263, 529, -1263, 592, -1263, -1263, 601, + 4038, -1263, 514, 4232, 602, 648, -1263, 636, 656, 4426, + -99, 4620, 775, -1263, 644, 650, 612, 808, -1263, -1263, + -1263, -1263, -1263, 651, -1263, 652, 653, 654, 657, 658, + -1263, 761, -1263, 659, 9532, 649, -1263, 660, -1263, 8, + -1263, -28, -1263, -1263, -1263, 6366, 140, 269, 647, 341, + -1263, -1263, -1263, 627, -1263, -1263, 184, -1263, 662, 663, + 664, -1263, 6366, 1584, 6366, 6366, -1263, -1263, 6366, -1263, + 6366, -1263, 6366, -1263, -1263, 6366, -1263, 1584, 618, 618, + 6366, 6366, 6366, 6366, 6366, 6366, 488, 18, 9679, -1263, + 661, 618, 618, -88, 618, 618, 18, 821, 665, 10336, + 665, 180, 2674, 831, -1263, 628, 583, -1263, 10831, 10919, + 6366, 6366, -1263, -1263, 6366, 6366, 6366, 6366, 678, 6366, + -67, 6366, 6366, 6366, 6366, 6366, 6366, 6366, 6366, 6366, + 4814, 6366, 6366, 6366, 6366, 6366, 6366, 6366, 6366, 6366, + 6366, 11040, 6366, -1263, 5008, 329, 370, -1263, -1263, -9, + 408, 540, 413, 540, 414, 540, -1263, 328, -1263, 330, + -1263, 1584, 635, 665, -1263, -1263, -1263, 9191, -1263, 671, + 1584, -1263, -1263, 1584, -1263, -1263, 6739, 666, 807, -1263, + -50, -1263, 6366, 18, 6366, 10336, 837, 6366, 10336, 6366, + 674, -1263, 675, 699, 10336, -1263, 6366, 10336, 685, -1263, + -1263, 6366, 667, -1263, -1263, -1263, -1263, -1263, -1263, -1263, + -79, -1263, 6366, 6366, 6366, 6366, 6366, 6366, 6366, 6366, + 6366, 6366, 6366, 6366, 6366, 6366, 6366, 6366, 6366, 6366, + 6366, 570, -1263, -1263, 849, 471, -1263, 6366, 9778, -1263, + -1263, -1263, 1584, 1584, 1584, 1584, 3260, 696, 6366, 1584, + -1263, -1263, -1263, 1584, 665, 331, 661, 6831, 1584, 1584, + 6930, 1584, 6961, 1584, 665, 1584, 1584, 665, 1584, 680, + 7060, 7152, 7185, 7277, 7376, 7407, -1263, 6366, 318, 10, + 6366, 6366, 688, 23, 18, 6366, 669, 668, 672, 676, + 300, -1263, -1263, 11, 677, 16, 2870, -1263, 110, 689, + 679, 681, 478, 2081, -1263, 831, 683, 682, -1263, -1263, + 684, 686, -1263, -1263, 673, 673, 164, 164, 10767, 10767, + 687, 285, 691, -1263, 9281, -62, -62, 582, 673, 673, + 824, 10539, 10571, 10425, 10952, 9867, 10653, 458, 10685, 164, + 164, 1043, 1043, 285, 285, 285, 13, 6366, 692, 693, + 162, 6366, 869, 697, 9312, -1263, 127, -1263, -1263, 716, + -1263, -1263, 694, -1263, 702, -1263, 703, -1263, 6709, -1263, + 626, 332, 529, -1263, -1263, -1263, -1263, 529, 529, -1263, + 6366, 717, -1263, 728, -1263, 1584, -1263, 6366, 7506, 30, + 10336, 514, 10336, 7598, 6366, -1263, -1263, 10336, -1263, 7631, + 6366, 700, 851, 738, -1263, 354, -1263, 10336, 10336, 10336, + 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, + 10336, 10336, 10336, 10336, 10336, 10336, -1263, 733, 494, 839, + 735, 9899, -1263, -1263, -1263, -1263, 529, 722, 724, 415, + 299, 185, 705, 706, 348, 7723, 416, 1584, 1584, 1584, + 729, 708, 711, 1584, 712, -1263, 731, 734, -1263, 736, + -1263, 737, 713, 740, 741, 715, 743, 831, -1263, -1263, + -1263, -1263, -1263, 719, 9981, 6366, 10336, -1263, -1263, 6366, + 53, 10336, -1263, -1263, 6366, 6366, 1584, 478, 120, -1263, + 726, 6366, 6366, 6366, 201, 6560, -1263, 339, -1263, -68, + 540, -1263, 478, -1263, 6366, -1263, 6366, 5202, 6366, -1263, + 745, 730, -1263, -1263, 6366, 739, -1263, 9402, 6366, 5396, + 751, -1263, 9433, -1263, 5590, -1263, 6366, -1263, -1263, -1263, + -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, + -1263, -1263, 755, 1584, 7822, -1263, 890, -33, 10336, 514, + 6366, -1263, 514, 10336, 2286, 514, 7853, 6366, 772, -1263, + 192, 774, 1584, 35, -1263, -1263, -1263, 334, -1263, 3, + -1263, -1263, -1263, -1263, -1263, 744, -1263, -1263, -1263, 762, + 783, -1263, -1263, 782, 784, 785, -1263, -1263, 6366, 786, + -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, + 60, 5784, -1263, 381, 391, 6366, 7952, 8044, 787, 540, + -1263, 8077, 10336, 10336, 768, 2870, 770, 121, 814, 815, + 779, 823, 825, -1263, 194, 34, 540, 1584, 8169, 1584, + 8268, -1263, 200, 8299, -1263, 6366, 10457, 6366, -1263, 8398, + -1263, 221, 6366, -1263, -1263, -1263, 226, -1263, -1263, -1263, + 6366, 529, -1263, 826, 6366, -1263, 242, -1263, -1263, 433, + 974, 8490, -1263, 827, -85, 947, 158, 6366, 958, 3, + -1263, -1263, 494, 789, 791, -1263, -1263, 6366, 806, -1263, + -1263, -1263, -1263, 792, 793, 661, 795, 6366, 6366, 6366, + 796, 928, 798, 799, 5978, -1263, -1263, 243, 6366, 6366, + 392, -1263, -1263, -1263, 819, 141, -1263, 207, 6366, 6366, + 6366, -1263, -1263, 854, -1263, -1263, -68, -1263, 6172, -1263, + -1263, 514, 832, -1263, 421, -1263, -1263, -1263, 1584, 8523, + 8615, -1263, -1263, 8714, -1263, 813, -1263, 10336, 514, 514, + -1263, -1263, 816, -1263, 2480, 848, -1263, -1263, 1584, 35, + 860, -1263, 6366, 10013, -1263, -1263, 958, 18, 928, 928, + 8745, 818, 820, 843, 846, 6366, -1263, -1263, 6366, 164, + 164, 164, 6366, -1263, -1263, 928, 299, -1263, 8844, -1263, + 852, 10095, 6366, 306, -1263, 6366, 6366, 822, 8936, 10336, + 10336, 836, -1263, 6366, 10425, -1263, -1263, -1263, 440, -1263, + -1263, -1263, -1263, -1263, -1263, 6366, -1263, -1263, -1263, -1263, + -1263, 10336, -1263, 35, 6366, -1263, 10129, -1263, 1738, -1263, + -1263, 82, 82, -1263, 6366, 928, 928, 299, 847, 856, + 665, 82, 689, 857, -1263, 976, 859, 833, 10095, -1263, + 306, 10336, 10336, -1263, 178, -1263, 10457, -1263, -1263, -1263, + 8969, 6366, 10211, -1263, 880, 1738, 299, 689, 882, -1263, + 861, 862, 9061, 82, 82, 864, -1263, -1263, 865, 866, + -1263, 6366, -1263, -1263, 870, -1263, 6366, 6366, -1263, 514, + 10300, -1263, -1263, 514, 244, 853, -1263, -1263, -1263, -1263, + 867, 873, -1263, -1263, -1263, 10336, -1263, 10336, 10336, 433, + -1263, -1263, -1263, 299, -1263, -1263, -1263, 256, -1263 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. @@ -1397,212 +1397,212 @@ static const yytype_int16 yydefact[] = { 2, 114, 1, 269, 0, 0, 0, 543, 270, 0, 543, 543, 543, 16, 0, 0, 15, 3, 0, 0, - 9, 8, 0, 7, 531, 6, 11, 5, 4, 13, + 0, 8, 0, 7, 531, 6, 11, 5, 4, 13, 12, 14, 86, 87, 85, 94, 96, 38, 51, 48, 49, 40, 0, 46, 39, 545, 544, 0, 0, 22, 21, 531, 0, 0, 0, 0, 243, 36, 101, 102, 0, 0, 0, 103, 105, 112, 0, 100, 17, 10, - 564, 563, 207, 549, 565, 532, 533, 0, 0, 0, - 0, 41, 0, 47, 0, 0, 44, 546, 548, 18, - 709, 701, 705, 245, 0, 0, 111, 106, 0, 0, - 0, 0, 0, 0, 115, 209, 208, 211, 206, 551, - 550, 0, 567, 566, 570, 535, 534, 536, 92, 93, - 90, 91, 89, 0, 0, 88, 97, 52, 50, 46, - 43, 42, 0, 19, 20, 23, 0, 0, 0, 244, - 34, 37, 110, 0, 107, 108, 109, 113, 0, 552, - 553, 560, 469, 24, 25, 29, 0, 81, 82, 79, - 80, 78, 77, 83, 0, 45, 0, 710, 702, 706, - 35, 104, 0, 181, 182, 183, 184, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, - 198, 199, 200, 201, 202, 203, 204, 205, 0, 0, - 121, 116, 0, 0, 0, 561, 0, 571, 0, 470, - 0, 26, 27, 28, 0, 95, 0, 0, 0, 0, - 0, 0, 578, 598, 579, 614, 580, 584, 585, 586, - 587, 604, 591, 592, 593, 594, 595, 596, 597, 599, - 600, 601, 602, 671, 583, 590, 603, 678, 685, 581, - 588, 582, 589, 0, 0, 0, 0, 613, 635, 638, - 636, 637, 698, 633, 547, 619, 497, 503, 175, 176, - 173, 124, 125, 127, 126, 128, 129, 130, 131, 157, - 158, 155, 156, 148, 159, 160, 149, 146, 147, 174, - 168, 0, 172, 161, 162, 163, 164, 135, 136, 137, - 132, 133, 134, 145, 0, 151, 152, 150, 143, 144, - 139, 138, 140, 141, 142, 123, 122, 167, 0, 153, - 154, 469, 119, 234, 212, 605, 608, 611, 612, 606, - 609, 607, 610, 554, 555, 558, 568, 98, 0, 523, - 516, 537, 84, 639, 662, 665, 0, 668, 658, 0, - 622, 672, 679, 686, 692, 695, 0, 0, 648, 653, - 647, 0, 661, 657, 650, 0, 0, 652, 634, 0, - 620, 780, 703, 707, 177, 178, 171, 166, 179, 169, - 165, 0, 117, 268, 491, 0, 0, 210, 0, 540, - 0, 562, 482, 572, 99, 0, 0, 517, 0, 0, - 0, 0, 0, 0, 375, 376, 0, 0, 0, 0, - 369, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 604, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 458, 314, 316, 315, 317, 318, 319, 320, - 30, 0, 0, 0, 0, 0, 0, 0, 0, 299, - 300, 373, 372, 451, 370, 444, 443, 442, 441, 114, - 447, 371, 446, 445, 416, 377, 417, 0, 378, 0, - 374, 713, 717, 714, 715, 716, 0, 0, 0, 0, - 0, 116, 0, 116, 0, 116, 0, 0, 0, 644, - 237, 655, 656, 649, 651, 0, 654, 630, 0, 0, - 700, 699, 781, 711, 243, 626, 625, 0, 498, 493, - 0, 0, 0, 504, 0, 180, 170, 0, 266, 267, - 0, 469, 118, 120, 236, 0, 61, 62, 0, 260, - 258, 0, 0, 0, 0, 259, 0, 0, 0, 0, - 0, 213, 216, 0, 0, 0, 0, 229, 224, 221, - 220, 222, 0, 235, 0, 68, 69, 66, 67, 230, - 272, 219, 0, 65, 538, 541, 780, 559, 483, 524, - 0, 514, 515, 513, 0, 0, 0, 0, 627, 736, - 739, 248, 252, 251, 257, 0, 288, 0, 0, 0, - 765, 0, 0, 0, 0, 279, 282, 0, 285, 0, - 769, 0, 745, 751, 0, 742, 0, 405, 406, 0, - 0, 0, 0, 0, 0, 0, 0, 749, 772, 780, - 382, 381, 418, 380, 379, 0, 0, 780, 294, 780, - 301, 0, 309, 234, 300, 114, 215, 0, 0, 0, - 0, 407, 408, 0, 0, 0, 0, 0, 0, 0, + 9, 564, 563, 207, 549, 565, 532, 533, 0, 0, + 0, 0, 41, 0, 47, 0, 0, 44, 546, 548, + 18, 709, 701, 705, 245, 0, 0, 111, 106, 0, + 0, 0, 0, 0, 0, 115, 209, 208, 211, 206, + 551, 550, 0, 567, 566, 570, 535, 534, 536, 92, + 93, 90, 91, 89, 0, 0, 88, 97, 52, 50, + 46, 43, 42, 0, 19, 20, 23, 0, 0, 0, + 244, 34, 37, 110, 0, 107, 108, 109, 113, 0, + 552, 553, 560, 469, 24, 25, 29, 0, 81, 82, + 79, 80, 78, 77, 83, 0, 45, 0, 710, 702, + 706, 35, 104, 0, 181, 182, 183, 184, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, + 197, 198, 199, 200, 201, 202, 203, 204, 205, 0, + 0, 121, 116, 0, 0, 0, 561, 0, 571, 0, + 470, 0, 26, 27, 28, 0, 95, 0, 0, 0, + 0, 0, 0, 578, 598, 579, 614, 580, 584, 585, + 586, 587, 604, 591, 592, 593, 594, 595, 596, 597, + 599, 600, 601, 602, 671, 583, 590, 603, 678, 685, + 581, 588, 582, 589, 0, 0, 0, 0, 613, 635, + 638, 636, 637, 698, 633, 547, 619, 497, 503, 175, + 176, 173, 124, 125, 127, 126, 128, 129, 130, 131, + 157, 158, 155, 156, 148, 159, 160, 149, 146, 147, + 174, 168, 0, 172, 161, 162, 163, 164, 135, 136, + 137, 132, 133, 134, 145, 0, 151, 152, 150, 143, + 144, 139, 138, 140, 141, 142, 123, 122, 167, 0, + 153, 154, 469, 119, 234, 212, 605, 608, 611, 612, + 606, 609, 607, 610, 554, 555, 558, 568, 98, 0, + 523, 516, 537, 84, 639, 662, 665, 0, 668, 658, + 0, 622, 672, 679, 686, 692, 695, 0, 0, 648, + 653, 647, 0, 661, 657, 650, 0, 0, 652, 634, + 0, 620, 780, 703, 707, 177, 178, 171, 166, 179, + 169, 165, 0, 117, 268, 491, 0, 0, 210, 0, + 540, 0, 562, 482, 572, 99, 0, 0, 517, 0, + 0, 0, 0, 0, 0, 375, 376, 0, 0, 0, + 0, 369, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 604, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 458, 314, 316, 315, 317, 318, 319, + 320, 30, 0, 0, 0, 0, 0, 0, 0, 0, + 299, 300, 373, 372, 451, 370, 444, 443, 442, 441, + 114, 447, 371, 446, 445, 416, 377, 417, 0, 378, + 0, 374, 713, 717, 714, 715, 716, 0, 0, 0, + 0, 0, 116, 0, 116, 0, 116, 0, 0, 0, + 644, 237, 655, 656, 649, 651, 0, 654, 630, 0, + 0, 700, 699, 781, 711, 243, 626, 625, 0, 498, + 493, 0, 0, 0, 504, 0, 180, 170, 0, 266, + 267, 0, 469, 118, 120, 236, 0, 61, 62, 0, + 260, 258, 0, 0, 0, 0, 259, 0, 0, 0, + 0, 0, 213, 216, 0, 0, 0, 0, 229, 224, + 221, 220, 222, 0, 235, 0, 68, 69, 66, 67, + 230, 272, 219, 0, 65, 538, 541, 780, 559, 483, + 524, 0, 514, 515, 513, 0, 0, 0, 0, 627, + 736, 739, 248, 252, 251, 257, 0, 288, 0, 0, + 0, 765, 0, 0, 0, 0, 279, 282, 0, 285, + 0, 769, 0, 745, 751, 0, 742, 0, 405, 406, + 0, 0, 0, 0, 0, 0, 0, 0, 749, 772, + 780, 382, 381, 418, 380, 379, 0, 0, 780, 294, + 780, 301, 0, 309, 234, 300, 114, 215, 0, 0, + 0, 0, 407, 408, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 359, 0, 642, 0, 0, 0, 615, 617, 0, 0, - 119, 0, 119, 0, 119, 495, 0, 501, 0, 616, - 0, 0, 780, 646, 629, 632, 0, 621, 0, 0, - 499, 704, 0, 505, 708, 0, 0, 573, 489, 508, - 492, 0, 0, 0, 261, 0, 0, 246, 0, 0, - 233, 0, 0, 55, 73, 0, 263, 0, 231, 232, - 0, 0, 223, 218, 225, 226, 227, 228, 271, 0, - 217, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 359, 0, 642, 0, 0, 0, 615, 617, 0, + 0, 119, 0, 119, 0, 119, 495, 0, 501, 0, + 616, 0, 0, 780, 646, 629, 632, 0, 621, 0, + 0, 499, 704, 0, 505, 708, 0, 0, 573, 489, + 508, 492, 0, 0, 0, 261, 0, 0, 246, 0, + 0, 233, 0, 0, 55, 73, 0, 263, 0, 231, + 232, 0, 0, 223, 218, 225, 226, 227, 228, 271, + 0, 217, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 781, 556, 569, 0, 469, 528, 0, 0, 640, 663, - 666, 0, 0, 0, 0, 734, 0, 0, 0, 755, - 758, 761, 0, 780, 0, 780, 0, 0, 0, 0, - 0, 0, 0, 780, 0, 0, 780, 0, 0, 0, - 0, 0, 0, 0, 0, 33, 0, 31, 0, 0, - 781, 0, 0, 0, 781, 0, 0, 0, 0, 347, - 344, 346, 0, 0, 243, 0, 362, 0, 727, 0, - 0, 116, 0, 301, 309, 0, 0, 430, 429, 0, - 0, 431, 435, 383, 384, 396, 397, 394, 395, 0, - 424, 0, 414, 0, 448, 449, 450, 385, 386, 401, - 402, 403, 404, 0, 0, 399, 400, 398, 392, 393, - 388, 387, 389, 390, 391, 0, 0, 0, 353, 0, - 0, 0, 0, 0, 367, 0, 669, 659, 0, 623, - 673, 0, 680, 0, 687, 0, 693, 0, 696, 0, - 0, 241, 643, 238, 631, 712, 494, 500, 490, 0, - 0, 507, 0, 506, 0, 509, 0, 0, 0, 262, - 0, 247, 0, 0, 53, 54, 264, 234, 0, 0, - 0, 518, 0, 278, 516, 277, 331, 332, 334, 333, - 335, 325, 326, 327, 336, 337, 323, 324, 338, 339, - 328, 329, 330, 322, 539, 542, 0, 476, 479, 0, - 0, 530, 641, 664, 667, 628, 0, 0, 0, 735, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 419, 0, 0, 420, 0, 452, - 0, 0, 0, 0, 0, 0, 309, 453, 454, 455, - 456, 457, 0, 0, 0, 748, 773, 774, 0, 0, - 295, 754, 409, 0, 0, 0, 116, 0, 363, 0, - 0, 0, 0, 0, 0, 366, 0, 364, 0, 119, - 313, 116, 426, 0, 432, 0, 0, 0, 412, 0, - 0, 436, 440, 0, 0, 415, 0, 0, 0, 0, - 354, 0, 360, 0, 410, 0, 368, 670, 660, 618, - 624, 674, 676, 681, 683, 688, 690, 694, 496, 697, - 502, 0, 0, 0, 575, 576, 510, 512, 0, 0, - 265, 0, 76, 0, 0, 0, 0, 0, 273, 0, - 0, 0, 0, 557, 477, 478, 479, 480, 471, 484, - 529, 737, 740, 249, 0, 254, 255, 253, 0, 0, - 291, 289, 0, 0, 0, 766, 764, 239, 0, 775, - 280, 283, 286, 770, 768, 746, 752, 750, 743, 0, - 0, 32, 0, 0, 0, 0, 0, 0, 119, 365, - 0, 719, 718, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 307, 0, 0, 119, 0, 0, 0, 0, - 342, 0, 0, 437, 0, 425, 0, 413, 0, 355, - 0, 0, 411, 361, 357, 0, 677, 684, 691, 237, - 242, 574, 0, 0, 74, 0, 75, 214, 58, 63, - 0, 520, 0, 516, 521, 0, 0, 474, 471, 472, - 473, 476, 0, 0, 250, 256, 0, 0, 290, 756, - 759, 762, 0, 0, 780, 0, 0, 0, 0, 0, - 734, 0, 0, 0, 423, 459, 0, 0, 0, 0, - 345, 468, 348, 0, 0, 340, 0, 0, 0, 0, - 304, 305, 0, 303, 302, 0, 310, 0, 296, 311, - 0, 0, 467, 0, 465, 343, 462, 0, 0, 0, - 461, 356, 0, 358, 0, 577, 511, 0, 0, 56, - 57, 0, 70, 0, 0, 519, 274, 0, 0, 0, - 525, 0, 0, 475, 485, 474, 0, 734, 734, 0, - 0, 0, 0, 0, 237, 776, 240, 239, 281, 284, - 287, 0, 735, 747, 734, 0, 421, 0, 460, 778, - 778, 0, 0, 351, 0, 0, 0, 0, 721, 720, - 0, 308, 0, 297, 312, 427, 433, 0, 466, 464, - 463, 645, 72, 59, 0, 64, 68, 69, 66, 67, - 65, 71, 0, 0, 522, 0, 527, 0, 487, 481, - 733, 733, 292, 0, 734, 734, 0, 0, 0, 780, - 733, 726, 0, 422, 0, 0, 0, 778, 349, 0, - 723, 722, 341, 0, 306, 298, 428, 434, 438, 0, - 0, 0, 526, 0, 0, 0, 730, 780, 732, 0, - 0, 0, 733, 733, 0, 767, 777, 0, 0, 744, - 0, 784, 782, 0, 352, 0, 0, 439, 0, 0, - 276, 486, 0, 0, 781, 731, 738, 741, 293, 0, - 0, 763, 771, 753, 779, 783, 725, 724, 58, 275, - 488, 728, 0, 757, 760, 60, 0, 729 + 0, 781, 556, 569, 0, 469, 528, 0, 0, 640, + 663, 666, 0, 0, 0, 0, 734, 0, 0, 0, + 755, 758, 761, 0, 780, 0, 780, 0, 0, 0, + 0, 0, 0, 0, 780, 0, 0, 780, 0, 0, + 0, 0, 0, 0, 0, 0, 33, 0, 31, 0, + 0, 781, 0, 0, 0, 781, 0, 0, 0, 0, + 347, 344, 346, 0, 0, 243, 0, 362, 0, 727, + 0, 0, 116, 0, 301, 309, 0, 0, 430, 429, + 0, 0, 431, 435, 383, 384, 396, 397, 394, 395, + 0, 424, 0, 414, 0, 448, 449, 450, 385, 386, + 401, 402, 403, 404, 0, 0, 399, 400, 398, 392, + 393, 388, 387, 389, 390, 391, 0, 0, 0, 353, + 0, 0, 0, 0, 0, 367, 0, 669, 659, 0, + 623, 673, 0, 680, 0, 687, 0, 693, 0, 696, + 0, 0, 241, 643, 238, 631, 712, 494, 500, 490, + 0, 0, 507, 0, 506, 0, 509, 0, 0, 0, + 262, 0, 247, 0, 0, 53, 54, 264, 234, 0, + 0, 0, 518, 0, 278, 516, 277, 331, 332, 334, + 333, 335, 325, 326, 327, 336, 337, 323, 324, 338, + 339, 328, 329, 330, 322, 539, 542, 0, 476, 479, + 0, 0, 530, 641, 664, 667, 628, 0, 0, 0, + 735, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 419, 0, 0, 420, 0, + 452, 0, 0, 0, 0, 0, 0, 309, 453, 454, + 455, 456, 457, 0, 0, 0, 748, 773, 774, 0, + 0, 295, 754, 409, 0, 0, 0, 116, 0, 363, + 0, 0, 0, 0, 0, 0, 366, 0, 364, 0, + 119, 313, 116, 426, 0, 432, 0, 0, 0, 412, + 0, 0, 436, 440, 0, 0, 415, 0, 0, 0, + 0, 354, 0, 360, 0, 410, 0, 368, 670, 660, + 618, 624, 674, 676, 681, 683, 688, 690, 694, 496, + 697, 502, 0, 0, 0, 575, 576, 510, 512, 0, + 0, 265, 0, 76, 0, 0, 0, 0, 0, 273, + 0, 0, 0, 0, 557, 477, 478, 479, 480, 471, + 484, 529, 737, 740, 249, 0, 254, 255, 253, 0, + 0, 291, 289, 0, 0, 0, 766, 764, 239, 0, + 775, 280, 283, 286, 770, 768, 746, 752, 750, 743, + 0, 0, 32, 0, 0, 0, 0, 0, 0, 119, + 365, 0, 719, 718, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 307, 0, 0, 119, 0, 0, 0, + 0, 342, 0, 0, 437, 0, 425, 0, 413, 0, + 355, 0, 0, 411, 361, 357, 0, 677, 684, 691, + 237, 242, 574, 0, 0, 74, 0, 75, 214, 58, + 63, 0, 520, 0, 516, 521, 0, 0, 474, 471, + 472, 473, 476, 0, 0, 250, 256, 0, 0, 290, + 756, 759, 762, 0, 0, 780, 0, 0, 0, 0, + 0, 734, 0, 0, 0, 423, 459, 0, 0, 0, + 0, 345, 468, 348, 0, 0, 340, 0, 0, 0, + 0, 304, 305, 0, 303, 302, 0, 310, 0, 296, + 311, 0, 0, 467, 0, 465, 343, 462, 0, 0, + 0, 461, 356, 0, 358, 0, 577, 511, 0, 0, + 56, 57, 0, 70, 0, 0, 519, 274, 0, 0, + 0, 525, 0, 0, 475, 485, 474, 0, 734, 734, + 0, 0, 0, 0, 0, 237, 776, 240, 239, 281, + 284, 287, 0, 735, 747, 734, 0, 421, 0, 460, + 778, 778, 0, 0, 351, 0, 0, 0, 0, 721, + 720, 0, 308, 0, 297, 312, 427, 433, 0, 466, + 464, 463, 645, 72, 59, 0, 64, 68, 69, 66, + 67, 65, 71, 0, 0, 522, 0, 527, 0, 487, + 481, 733, 733, 292, 0, 734, 734, 0, 0, 0, + 780, 733, 726, 0, 422, 0, 0, 0, 778, 349, + 0, 723, 722, 341, 0, 306, 298, 428, 434, 438, + 0, 0, 0, 526, 0, 0, 0, 730, 780, 732, + 0, 0, 0, 733, 733, 0, 767, 777, 0, 0, + 744, 0, 784, 782, 0, 352, 0, 0, 439, 0, + 0, 276, 486, 0, 0, 781, 731, 738, 741, 293, + 0, 0, 763, 771, 753, 779, 783, 725, 724, 58, + 275, 488, 728, 0, 757, 760, 60, 0, 729 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -1259, -1259, -1259, -1259, -1259, -1259, 452, 993, -1259, -1259, - -1259, 1079, -1259, -1259, -1259, 1047, -1259, 955, -1259, -1259, - 1011, -1259, -1259, -1259, -334, -1259, -1259, -181, -1259, -1259, - -1259, -1259, -1259, -1259, 893, -1259, -1259, -66, 997, -1259, - -1259, -1259, 349, -1259, -422, -472, -662, -1259, -1259, -1259, - -1253, -1259, -1259, -514, -1259, -1259, -628, -1135, -189, -1259, - -14, -1259, -1259, -1259, -1259, -1259, -162, -161, -159, -157, - -1259, -1259, 1108, -1259, -1259, -1259, -1259, -1259, -1259, -1259, - -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -336, -1259, - 689, -126, -1259, -794, -1259, -1259, -1259, -1259, -1259, -1259, - -1258, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, - 536, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -144, -78, - -163, -77, 27, -1259, -1259, -1259, -1259, -1259, 605, -1259, - -471, -1259, -1259, -481, -1259, -1259, -706, -158, -560, -918, - -1259, -1259, -1259, -1259, 1074, -1259, -1259, -1259, 372, -1259, - 691, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, - -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -593, - -164, -1259, 721, -1259, -1259, -1259, -1259, -1259, -1259, -339, - -1259, -1259, -365, -1259, -1259, -1259, -1259, -1259, -1259, -1259, - -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, - -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, - -1259, -142, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, - -1259, -1259, -1259, -1259, 730, -624, -225, -740, -1259, -1259, - -955, -1003, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, - -1259, -796, -1259, -1259, -1259, -1259, -1259, -1259, -1259, -1259, - -1259, -1259, -1259, -1259, -1259, -1259, -389, -1259, -1235, -523, - -1259 + -1263, -1263, -1263, -1263, -1263, -1263, 460, 1002, -1263, -1263, + -1263, 1080, -1263, -1263, -1263, 1040, -1263, 953, -1263, -1263, + 1003, -1263, -1263, -1263, -344, -1263, -1263, -188, -1263, -1263, + -1263, -1263, -1263, -1263, 872, -1263, -1263, -64, 988, -1263, + -1263, -1263, 335, -1263, -426, -472, -662, -1263, -1263, -1263, + -1198, -1263, -1263, -514, -1263, -1263, -627, -1135, -209, -1263, + -14, -1263, -1263, -1263, -1263, -1263, -184, -183, -182, -181, + -1263, -1263, 1094, -1263, -1263, -1263, -1263, -1263, -1263, -1263, + -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -336, -1263, + 630, -138, -1263, -782, -1263, -1263, -1263, -1263, -1263, -1263, + -1262, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, + 536, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -144, -90, + -176, -87, 20, -1263, -1263, -1263, -1263, -1263, 590, -1263, + -481, -1263, -1263, -475, -1263, -1263, -706, -174, -560, -918, + -1263, -1263, -1263, -1263, 1069, -1263, -1263, -1263, 360, -1263, + 655, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, + -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -593, + -164, -1263, 718, -1263, -1263, -1263, -1263, -1263, -1263, -339, + -1263, -1263, -365, -1263, -1263, -1263, -1263, -1263, -1263, -1263, + -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, + -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, + -1263, -142, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, + -1263, -1263, -1263, -1263, 720, -624, -234, -748, -1263, -1263, + -1049, -980, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, + -1263, -809, -1263, -1263, -1263, -1263, -1263, -1263, -1263, -1263, + -1263, -1263, -1263, -1263, -1263, -1263, -404, -1263, -1256, -523, + -1263 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - 0, 1, 16, 135, 51, 17, 156, 162, 615, 451, - 141, 452, 95, 19, 20, 43, 44, 86, 21, 39, - 40, 543, 544, 1271, 1272, 545, 1274, 546, 547, 548, - 549, 550, 551, 552, 163, 164, 35, 36, 37, 209, - 63, 64, 65, 66, 22, 322, 387, 201, 23, 107, - 202, 108, 148, 324, 453, 553, 388, 691, 1213, 900, - 454, 554, 582, 774, 1204, 455, 555, 556, 557, 558, - 559, 520, 560, 739, 1089, 933, 561, 456, 787, 1216, - 788, 1217, 790, 1218, 457, 778, 1208, 458, 627, 1249, - 459, 1152, 1153, 831, 460, 636, 461, 562, 462, 463, - 821, 464, 1015, 1312, 1016, 1369, 465, 881, 1173, 466, - 628, 1156, 1376, 1158, 1377, 1257, 1407, 468, 383, 1201, - 1284, 1096, 1098, 959, 568, 764, 1347, 1384, 384, 385, - 507, 686, 372, 512, 688, 373, 1022, 708, 574, 398, - 934, 340, 935, 341, 76, 117, 25, 152, 565, 566, - 47, 48, 132, 26, 111, 150, 204, 27, 389, 956, - 391, 206, 207, 74, 114, 393, 28, 151, 336, 709, - 469, 333, 259, 260, 678, 371, 261, 479, 1060, 508, - 577, 368, 262, 263, 399, 962, 690, 477, 1058, 400, - 963, 401, 964, 476, 1057, 480, 1061, 481, 1176, 482, - 1063, 483, 1177, 484, 1065, 485, 1178, 486, 1067, 487, - 1069, 509, 29, 137, 266, 510, 30, 138, 267, 514, - 31, 136, 265, 698, 470, 1386, 1362, 829, 1387, 1388, - 1389, 972, 471, 772, 1202, 773, 1203, 797, 1222, 794, - 1220, 618, 472, 795, 1221, 473, 976, 1291, 977, 1292, - 978, 1293, 782, 1212, 792, 1219, 1214, 474, 1365, 503, - 475 + 0, 1, 16, 136, 51, 17, 157, 163, 616, 452, + 142, 453, 96, 19, 20, 43, 44, 87, 21, 39, + 40, 544, 545, 1272, 1273, 546, 1275, 547, 548, 549, + 550, 551, 552, 553, 164, 165, 35, 36, 37, 210, + 63, 64, 65, 66, 22, 323, 388, 202, 23, 108, + 203, 109, 149, 325, 454, 554, 389, 692, 1214, 901, + 455, 555, 583, 775, 1205, 456, 556, 557, 558, 559, + 560, 521, 561, 740, 1090, 934, 562, 457, 788, 1217, + 789, 1218, 791, 1219, 458, 779, 1209, 459, 628, 1250, + 460, 1153, 1154, 832, 461, 637, 462, 563, 463, 464, + 822, 465, 1016, 1313, 1017, 1370, 466, 882, 1174, 467, + 629, 1157, 1377, 1159, 1378, 1258, 1408, 469, 384, 1202, + 1285, 1097, 1099, 960, 569, 765, 1348, 1385, 385, 386, + 508, 687, 373, 513, 689, 374, 1023, 709, 575, 399, + 935, 341, 936, 342, 77, 118, 25, 153, 566, 567, + 47, 48, 133, 26, 112, 151, 205, 27, 390, 957, + 392, 207, 208, 75, 115, 394, 28, 152, 337, 710, + 470, 334, 260, 261, 679, 372, 262, 480, 1061, 509, + 578, 369, 263, 264, 400, 963, 691, 478, 1059, 401, + 964, 402, 965, 477, 1058, 481, 1062, 482, 1177, 483, + 1064, 484, 1178, 485, 1066, 486, 1179, 487, 1068, 488, + 1070, 510, 29, 138, 267, 511, 30, 139, 268, 515, + 31, 137, 266, 699, 471, 1387, 1363, 830, 1388, 1389, + 1390, 973, 472, 773, 1203, 774, 1204, 798, 1223, 795, + 1221, 619, 473, 796, 1222, 474, 977, 1292, 978, 1293, + 979, 1294, 783, 1213, 793, 1220, 1215, 475, 1366, 504, + 476 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If @@ -1610,1336 +1610,1389 @@ static const yytype_int16 yydefgoto[] = number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_int16 yytable[] = { - 57, 67, 258, 916, 501, 832, 687, 828, 210, 680, - 766, 682, 126, 684, 1006, 685, 1092, 715, 891, 587, - 893, 2, 895, 808, 264, 724, -114, 82, 3, 637, - 638, 570, 812, 493, 513, 971, 1004, 632, 118, 119, - 1031, 381, 1008, 761, 1264, 1199, 67, 67, 67, 32, - 33, 4, 619, 5, 1368, 6, 1079, 1147, 402, 403, - 1134, 7, 83, 1148, 518, 491, 647, 637, 638, 649, - 650, 8, 78, 649, 650, 1366, 381, 9, 409, 521, - 211, 212, 1019, 930, 411, 94, 67, 67, 67, 67, - 100, 101, 102, 1149, 1383, 49, 811, 382, 931, 208, - 171, 10, 68, 38, 815, 1200, 816, 519, 911, 911, - 1150, 1404, 629, 522, 1021, 1151, 588, 589, 823, 918, - 94, 418, 419, 11, 12, 641, 642, 1017, 699, 157, - 158, 1412, 1403, 647, 208, 648, 649, 650, 651, 652, - 50, 932, 337, 670, 671, 323, 763, 670, 671, 1247, - 41, 828, 257, 888, 692, 421, 422, 142, 75, 1357, - 358, 913, 913, 641, 642, 369, 55, 889, 700, 903, - 1385, 647, 851, 703, 649, 650, 651, 652, 120, 42, - 599, 852, 323, 121, 494, 122, 123, 359, 360, 762, - 56, 55, 34, 13, 912, 84, 637, 638, 828, 590, - 912, 1023, 1129, 495, 785, 258, 69, 85, 258, 496, - 670, 671, 14, 834, 912, 56, 492, 1303, 912, 591, - 1009, 15, 258, 441, 15, 571, 633, 784, 124, 1104, - 77, 572, 258, 214, 571, 258, 258, 258, 581, 771, - 572, 798, 357, 823, 523, 911, 323, 489, 670, 671, - 361, 1021, 1017, 58, 362, 783, 447, 575, 576, 578, - 980, 215, 983, 449, 634, 793, 592, 490, 796, 159, - 991, 911, 394, 994, 160, 1278, 161, 123, 573, 1044, - 765, 1223, 59, 78, 1350, 1351, 593, 573, 1045, 1024, - 639, 640, 641, 642, 643, 827, 1018, 644, 913, 1083, - 647, 1360, 648, 649, 650, 651, 652, 363, 653, 654, - 79, 364, 258, 258, 365, 911, 258, 1025, 258, 600, - 258, 1238, 258, 912, 913, 1055, 914, 571, 80, 915, - 366, 87, 55, 572, 674, 675, 367, 885, 679, 601, - 681, 817, 683, 1055, 88, 828, 818, 897, 911, 899, - 60, 1392, 1393, 1056, 1314, 257, 56, 55, 257, 1029, - 663, 664, 665, 666, 667, 668, 669, 1154, 913, 1192, - 1183, 1105, 257, 1280, 1245, 1055, 567, 670, 671, 819, - 573, 56, 257, 911, 603, 257, 257, 257, 1055, 1405, - 1049, 1055, 257, 585, 45, 103, 1390, 1193, 90, 1050, - 46, 913, 1246, 1255, 604, 1398, 1080, 966, 967, 96, - 97, 98, 70, 71, 61, 72, 1261, 979, 1070, 1263, - 1055, 104, 985, 986, 62, 988, 1068, 990, 258, 992, - 993, 1309, 995, 1055, 1026, 776, 913, 1419, 1420, 970, - 1239, 1026, 258, 73, 823, 982, 91, 1026, 1267, 144, - 145, 146, 147, 1017, 1026, 777, 706, 92, 55, -675, - 1143, 1308, 257, 257, -675, 94, 257, 817, 257, 1431, - 257, 707, 257, 838, 842, 1437, 1233, 325, 637, 638, - 1316, 326, 56, -675, -682, -689, -350, 1197, 856, -682, - -689, -350, 93, 1250, 1277, 327, 328, 397, 505, 99, - 329, 330, 331, 332, 506, 511, 882, 1097, -682, -689, - -350, 505, 896, 505, 369, 505, 505, 506, 768, 506, - 1236, 506, 506, 505, 1145, 898, 258, 981, 1315, 506, - 1071, 1268, 1196, 1146, 105, 258, 127, 1108, 258, 505, - 106, 129, 1269, 1270, 1138, 506, 130, 395, 901, 369, - 396, 131, 1090, 397, 85, 1091, 109, 906, 397, 1155, - 907, 1072, 110, 112, 1184, 115, 100, 1186, 102, 113, - 1188, 116, 639, 640, 641, 642, 643, 133, 257, 644, - 645, 646, 647, 134, 648, 649, 650, 651, 652, 505, - 653, 654, 257, 1227, 1094, 506, 1228, 1311, 139, 1055, - 1095, 369, 1055, 1055, 83, 769, 140, 258, 258, 258, - 258, 1112, 1113, 1114, 258, 1224, 820, 1118, 258, 167, - 958, 369, 149, 258, 258, 886, 258, 166, 258, 965, - 258, 258, 968, 258, 1109, 1281, 975, 100, 101, 102, - 1248, 662, 663, 664, 665, 666, 667, 668, 669, 369, - 1137, 369, 369, 887, 369, 890, 892, 369, 894, 670, - 671, 1103, 369, 168, 169, 369, 1111, 1406, 1132, 1326, - 369, 170, 1133, 100, 1378, 205, 257, 153, 154, 805, - 806, 1361, 153, 154, 155, 257, 203, 208, 257, 319, - 320, 1296, 321, 637, 638, 211, 212, 213, 323, 1042, - 1161, 52, 53, 54, 335, 334, 339, 343, 338, 344, - 345, 347, 1170, 370, 346, 348, 349, 1175, 1343, 356, - 374, 375, 376, 350, 351, 352, 1195, 377, 353, 378, - 354, 355, 1361, 258, 369, 379, 1324, 380, 386, 478, - 392, 502, 390, 1185, 499, 515, 516, 564, 569, 579, - 258, 580, 586, 1332, 1333, 517, 595, 257, 257, 257, - 257, 1413, 630, 596, 257, 598, 602, 594, 257, 605, - 597, 15, 1076, 257, 257, 606, 257, 599, 257, 609, - 257, 257, 1380, 257, 610, 677, 511, 639, 640, 641, - 642, 1251, 611, 612, 1226, 676, 613, 647, 1229, 648, - 649, 650, 651, 652, 614, 653, 654, 631, 1436, 673, - 693, 697, 258, 258, 258, 701, 702, 704, 258, 719, - 711, 712, 718, 720, 721, 727, 730, 731, 728, 738, - 729, 732, 733, 734, 735, 736, 1397, 737, 740, 770, - 813, 775, 760, 692, 637, 638, 759, 830, 833, 849, - 905, 258, 810, 779, 814, 780, 781, 910, 902, 665, - 666, 667, 668, 669, 1415, 920, 924, 923, 925, 927, - 957, 973, 996, 1007, 670, 671, 1026, 1032, 909, 1052, - 929, 1011, 467, 257, 1012, 1013, 1014, 1020, 1034, 1027, - 1059, 1074, 488, 1075, 1428, 1028, 1062, 1064, 1430, 1033, - 257, 1035, 498, 1066, 1087, 1036, 1037, 1088, 258, 1047, - 1048, 1053, 1342, 1086, 1093, 1097, 1099, 1117, 1101, 1102, - 1106, 1107, 1115, 1120, 563, 1116, 1119, 258, 1121, 1124, - 1180, 1127, 1122, 1123, 1125, 1126, 637, 638, 639, 640, - 641, 642, 643, 1128, 1130, 644, 645, 646, 647, 1163, - 648, 649, 650, 651, 652, 1164, 653, 654, 692, 1139, - 607, 608, 257, 257, 257, 1359, 1166, 1171, 257, 1182, - 1179, 1191, 1194, 1205, 1206, 1207, 1209, 617, 620, 621, - 622, 623, 624, 1210, 1211, 1215, 1232, 1235, 1237, 1242, - 1240, 1241, 258, 1243, 258, 1244, 1265, 1273, 1276, 1279, - 1283, 257, 1290, 1302, 1400, 660, 661, 662, 663, 664, - 665, 666, 667, 668, 669, 1320, 1253, 1287, 1313, 1341, - 1288, 1325, 1344, 1294, 1297, 670, 671, 1295, 1331, 1301, - 639, 640, 641, 642, 643, 696, 1364, 644, 645, 646, - 647, 1401, 648, 649, 650, 651, 652, 1304, 653, 654, - 1305, 1334, 1411, 705, 655, 656, 657, 1353, 257, 1354, - 658, 1355, 1356, 637, 638, 714, 1414, 807, 717, 1372, - 125, 1374, 1395, 1396, 723, 1399, 726, 257, 1402, 1416, - 18, 1417, 1421, 1422, 165, 1423, 1425, 1433, 1432, 81, - 1434, 128, 1335, 258, 1435, 659, 143, 660, 661, 662, - 663, 664, 665, 666, 667, 668, 669, 342, 1358, 24, - 767, 1336, 1337, 258, 1338, 1327, 1339, 670, 671, 1321, - 1285, 672, 1348, 1198, 1286, 89, 710, 583, 1349, 617, - 786, 1394, 955, 789, 0, 791, 584, 0, 0, 0, - 0, 0, 257, 0, 257, 799, 800, 801, 802, 803, - 804, 0, 0, 0, 0, 635, 0, 0, 0, 641, - 642, 0, 0, 0, 0, 0, 0, 647, 0, 648, - 649, 650, 651, 652, 0, 843, 844, 0, 0, 845, - 846, 847, 848, 0, 850, 0, 853, 854, 855, 857, - 858, 859, 860, 861, 862, 864, 865, 866, 867, 868, - 869, 870, 871, 872, 873, 874, 0, 883, 0, 0, + 57, 67, 1007, 259, 917, 502, 686, 833, 829, 211, + 681, 767, 683, 688, 685, 127, -114, 1093, 716, 892, + 588, 894, 2, 896, 809, 265, 725, 494, 972, 3, + 1005, 492, 571, 813, 633, 514, 119, 120, 620, 83, + 650, 651, 359, 1009, 762, 1265, 67, 67, 67, 1200, + 1080, 1369, 4, 1032, 5, 1367, 6, 519, 1148, 403, + 404, 382, 7, 648, 1149, 49, 650, 651, 931, 360, + 361, 324, 8, 1135, 84, 1020, 912, 382, 9, 410, + 101, 102, 103, 932, 95, 412, 852, 67, 67, 67, + 67, 32, 33, 912, 1150, 853, 1278, 812, 572, 398, + 520, 58, 10, 522, 573, 816, 600, 817, 1405, 1201, + 50, 1151, 1404, 630, 671, 672, 1152, 589, 590, 209, + 919, 634, 419, 420, 11, 12, 933, 700, 913, 914, + 59, 915, 362, 383, 916, 209, 363, 523, 158, 159, + 671, 672, 912, 764, 766, 338, 914, 143, 1022, 370, + 1384, 574, 829, 258, 95, 693, 422, 423, 450, 635, + 1358, 572, 41, 889, 824, 707, 1045, 573, 68, 701, + 904, 1248, 78, 1018, 704, 1046, 121, 890, 495, 763, + 708, 122, 493, 123, 124, 638, 639, 1413, 913, 364, + 786, 42, 55, 365, 13, 914, 366, 496, 60, 829, + 591, 913, 1024, 497, 324, 55, 259, 85, 913, 259, + 835, 15, 367, 14, 574, 1130, 56, 1019, 368, 86, + 592, 1010, 1105, 259, 442, 15, 125, 79, 785, 56, + 324, 913, 38, 259, 34, 824, 259, 259, 259, 582, + 772, 1304, 799, 358, 1018, 524, 912, 912, 490, 215, + 593, 69, 1022, 1239, 79, 172, 784, 448, 576, 577, + 579, 981, 61, 984, 70, 1224, 794, 912, 491, 797, + 594, 992, 62, 1315, 995, 395, 1279, 216, 160, 640, + 641, 642, 643, 161, 572, 162, 124, 1386, 1025, 648, + 573, 649, 650, 651, 652, 653, 828, 654, 655, 914, + 914, 1084, 104, 1391, 912, 1056, 638, 639, 1351, 1352, + 1406, 601, 1399, 259, 259, 1050, 1026, 259, 55, 259, + 914, 259, 370, 259, 1051, 1361, 769, 818, 105, 604, + 1281, 602, 819, 1057, 55, 675, 676, 574, 886, 680, + 76, 682, 56, 684, 1420, 1421, 829, 80, 898, 605, + 900, 666, 667, 668, 669, 670, 258, 914, 56, 258, + 1030, 71, 72, 1056, 73, 820, 671, 672, 1155, 777, + 1193, 1184, 1246, 258, 512, 1393, 1394, 568, 1056, 1027, + 101, 1198, 103, 258, 506, 1027, 258, 258, 258, 778, + 507, 1106, 74, 258, 586, 97, 98, 99, 1194, 1056, + 1247, 1098, 642, 643, 1056, 1144, 1256, 1081, 967, 968, + 648, 1317, 649, 650, 651, 652, 653, 1069, 980, 1310, + 1056, 1056, 1027, 986, 987, 1071, 989, 1262, 991, 259, + 993, 994, 1264, 996, 1027, 81, 145, 146, 147, 148, + 971, 1240, -675, 259, 55, 1269, 983, -675, 1268, 1309, + 1432, 370, 824, 818, -682, 770, 1270, 1271, 88, -682, + -689, 1018, 1438, 258, 258, -689, -675, 258, 56, 258, + 89, 258, 326, 258, 839, 843, 327, 1234, -682, 638, + 639, -350, 212, 213, -689, 91, -350, 671, 672, 857, + 328, 329, 1146, 45, 1251, 330, 331, 332, 333, 46, + 506, 1147, 506, 506, 506, -350, 507, 883, 507, 507, + 507, 370, 92, 506, 897, 887, 899, 982, 1072, 507, + 506, 1237, 396, 370, 106, 397, 507, 259, 398, 1316, + 107, 110, 1091, 1197, 1109, 1092, 259, 111, 398, 259, + 113, 116, 134, 95, 506, 1139, 114, 117, 135, 902, + 507, 1095, 370, 1228, 100, 93, 888, 1096, 907, 1056, + 1156, 908, 1073, 1229, 1312, 1185, 94, 128, 1187, 1056, + 1056, 1189, 130, 640, 641, 642, 643, 644, 86, 258, + 645, 646, 647, 648, 131, 649, 650, 651, 652, 653, + 370, 654, 655, 258, 891, 370, 370, 370, 370, 893, + 895, 1104, 1112, 370, 101, 102, 103, 1327, 259, 259, + 259, 259, 1113, 1114, 1115, 259, 1225, 821, 1119, 259, + 141, 959, 370, 132, 259, 259, 1379, 259, 140, 259, + 966, 259, 259, 969, 259, 1110, 1282, 976, 150, 638, + 639, 1249, 663, 664, 665, 666, 667, 668, 669, 670, + 84, 1138, 154, 155, 806, 807, 154, 155, 156, 167, + 671, 672, 212, 213, 214, 52, 53, 54, 1407, 1133, + 168, 169, 170, 1134, 171, 206, 101, 258, 204, 209, + 320, 321, 1362, 322, 324, 335, 258, 336, 340, 258, + 339, 344, 1297, 345, 638, 639, 346, 348, 347, 378, + 1043, 1162, 349, 351, 350, 352, 353, 354, 355, 356, + 357, 370, 371, 1171, 375, 376, 377, 379, 1176, 1344, + 380, 387, 391, 381, 479, 393, 503, 1196, 516, 517, + 500, 580, 565, 1362, 259, 642, 643, 1325, 518, 570, + 595, 581, 587, 648, 1186, 596, 650, 651, 652, 653, + 597, 259, 598, 599, 1333, 1334, 600, 603, 258, 258, + 258, 258, 1414, 606, 607, 258, 610, 631, 611, 258, + 677, 678, 612, 1077, 258, 258, 613, 258, 614, 258, + 615, 258, 258, 1381, 258, 632, 15, 674, 512, 694, + 642, 643, 1252, 698, 702, 1227, 703, 712, 648, 1230, + 649, 650, 651, 652, 653, 705, 713, 719, 721, 1437, + 720, 722, 728, 259, 259, 259, 729, 731, 732, 259, + 671, 672, 730, 733, 734, 735, 736, 739, 760, 737, + 738, 741, 776, 771, 814, 831, 834, 1398, 761, 811, + 850, 903, 906, 815, 693, 638, 639, 780, 781, 782, + 911, 921, 259, 924, 926, 928, 925, 958, 974, 1008, + 666, 667, 668, 669, 670, 1416, 997, 1027, 1033, 1035, + 1053, 910, 930, 1012, 1013, 671, 672, 1014, 1060, 1075, + 1063, 1015, 1021, 468, 258, 1028, 1029, 1034, 1065, 1067, + 1076, 1036, 1037, 489, 1088, 1429, 1038, 1048, 1049, 1431, + 1089, 258, 1054, 499, 1094, 1087, 1098, 1100, 1102, 259, + 1103, 1107, 1108, 1343, 1117, 1116, 1118, 1121, 1120, 1125, + 1122, 1128, 1123, 1124, 1131, 564, 1126, 1127, 259, 1129, + 1164, 1181, 1140, 1183, 1192, 1165, 1195, 638, 639, 640, + 641, 642, 643, 644, 1167, 1208, 645, 646, 647, 648, + 1206, 649, 650, 651, 652, 653, 1172, 654, 655, 693, + 1180, 608, 609, 258, 258, 258, 1360, 1207, 1210, 258, + 1211, 1212, 1216, 1233, 1236, 1238, 1241, 1242, 618, 621, + 622, 623, 624, 625, 1243, 1244, 1274, 1245, 1266, 1277, + 1280, 1284, 1291, 259, 1288, 259, 1289, 1295, 1303, 1296, + 1298, 1302, 258, 1305, 1306, 1314, 661, 662, 663, 664, + 665, 666, 667, 668, 669, 670, 1321, 1254, 1326, 1332, + 1342, 1335, 1345, 1354, 1365, 1355, 671, 672, 1373, 1401, + 1402, 640, 641, 642, 643, 644, 697, 1403, 645, 646, + 647, 648, 1375, 649, 650, 651, 652, 653, 1356, 654, + 655, 1357, 1412, 1396, 706, 656, 657, 658, 1433, 258, + 1415, 659, 1397, 1400, 638, 639, 715, 1417, 1418, 718, + 1422, 1423, 1424, 1434, 1426, 724, 808, 727, 258, 1435, + 126, 18, 82, 166, 129, 1436, 1336, 343, 144, 1359, + 1337, 1338, 1339, 1340, 259, 24, 660, 636, 661, 662, + 663, 664, 665, 666, 667, 668, 669, 670, 1322, 1286, + 1349, 768, 711, 1350, 259, 1287, 1328, 1199, 671, 672, + 90, 956, 673, 1395, 0, 584, 0, 585, 0, 0, + 618, 787, 0, 0, 790, 0, 792, 0, 0, 0, + 0, 0, 0, 258, 0, 258, 800, 801, 802, 803, + 804, 805, 0, 0, 0, 0, 0, 0, 0, 0, + 642, 643, 0, 0, 0, 0, 0, 0, 648, 0, + 649, 650, 651, 652, 653, 0, 844, 845, 0, 0, + 846, 847, 848, 849, 0, 851, 0, 854, 855, 856, + 858, 859, 860, 861, 862, 863, 865, 866, 867, 868, + 869, 870, 871, 872, 873, 874, 875, 0, 884, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 665, - 666, 667, 668, 669, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 257, 670, 671, 0, 917, 0, 919, - 0, 0, 921, 0, 922, 0, 0, 637, 638, 0, - 0, 926, 0, 257, 0, 0, 928, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 936, 937, 938, + 0, 0, 668, 669, 670, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 258, 671, 672, 0, 918, 0, + 920, 0, 0, 922, 0, 923, 0, 0, 0, 0, + 0, 0, 927, 0, 258, 0, 0, 929, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, - 949, 950, 951, 952, 953, 954, 0, 0, 820, 0, - 0, 0, 960, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 974, 0, 0, 0, 216, 0, 0, - 0, 0, 0, 217, 0, 0, 0, 0, 0, 218, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, - 0, 0, 1003, 0, 0, 1005, 617, 220, 0, 0, - 1010, 0, 0, 641, 642, 820, 0, 0, 0, 0, - 0, 647, 221, 648, 649, 650, 651, 652, 563, 222, + 949, 950, 951, 952, 953, 954, 955, 0, 0, 821, + 0, 0, 0, 961, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 975, 0, 0, 0, 217, 0, + 0, 0, 0, 0, 218, 0, 0, 0, 0, 0, + 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 220, 0, 0, 1004, 0, 0, 1006, 618, 221, 0, + 0, 1011, 0, 0, 0, 0, 821, 0, 0, 0, + 0, 0, 0, 222, 0, 0, 0, 0, 0, 564, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, - 253, 254, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1046, 0, 0, 0, 1051, 0, 0, 0, - 0, 0, 0, 0, 0, 667, 668, 669, 0, 0, - 0, 0, 0, 0, 0, 0, 55, 0, 670, 671, - 0, 0, 0, 0, 0, 1073, 0, 0, 0, 255, - 0, 0, 1077, 0, 0, 0, 216, 0, 0, 1082, - 56, 0, 217, 0, 0, 1085, 0, 0, 218, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 219, 0, - 0, 0, 0, 0, 0, 0, 220, 0, 0, 0, + 253, 254, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1047, 0, 0, 0, 1052, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, + 0, 0, 0, 0, 0, 0, 1074, 0, 0, 0, + 256, 0, 0, 1078, 0, 0, 0, 217, 0, 0, + 1083, 56, 0, 218, 0, 0, 1086, 0, 0, 219, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, + 0, 0, 0, 0, 0, 0, 0, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 221, 0, 0, 0, 256, 0, 500, 222, 223, + 0, 0, 222, 0, 0, 0, 257, 0, 501, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 0, 0, 0, 0, 0, 0, 0, 0, 1135, - 1136, 0, 0, 0, 0, 0, 1140, 1141, 1142, 0, - 1010, 0, 0, 0, 0, 0, 0, 0, 0, 1157, - 0, 1159, 0, 1162, 0, 55, 0, 0, 0, 1165, - 0, 0, 0, 1168, 0, 0, 0, 0, 255, 0, - 0, 1010, 0, 0, 0, 0, 0, 0, 0, 504, - 0, 0, 216, 0, 0, 0, 0, 0, 217, 505, - 0, 0, 0, 0, 218, 506, 0, 0, 0, 563, - 0, 0, 1190, 0, 219, 0, 0, 0, 0, 0, - 0, 0, 220, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 256, 0, 0, 221, 0, 0, - 0, 0, 0, 617, 222, 223, 224, 225, 226, 227, + 254, 255, 0, 0, 0, 0, 0, 0, 0, 0, + 1136, 1137, 0, 0, 0, 0, 0, 1141, 1142, 1143, + 0, 1011, 0, 0, 0, 0, 0, 0, 0, 0, + 1158, 0, 1160, 0, 1163, 0, 55, 0, 0, 0, + 1166, 0, 0, 0, 1169, 0, 0, 0, 0, 256, + 0, 0, 1011, 0, 0, 0, 0, 0, 0, 0, + 505, 0, 0, 217, 0, 0, 0, 0, 0, 218, + 506, 0, 0, 0, 0, 219, 507, 0, 0, 0, + 564, 0, 0, 1191, 0, 220, 0, 0, 0, 0, + 0, 0, 0, 221, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 257, 0, 0, 222, 0, + 0, 0, 0, 0, 618, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 0, 0, 0, + 248, 249, 250, 251, 252, 253, 254, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1258, 0, 1259, 0, 0, 0, 0, 1262, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1266, - 0, 55, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1282, 0, 255, 0, 0, 0, 0, 0, - 0, 0, 1289, 0, 0, 56, 0, 0, 0, 0, - 0, 0, 1298, 1299, 1300, 0, 0, 0, 0, 1307, - 0, 0, 0, 617, 1310, 0, 0, 0, 0, 0, - 0, 0, 172, 1317, 1318, 1319, 0, 0, 0, 0, - 0, 0, 0, 1323, 0, 0, 0, 0, 0, 0, - 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 173, 1340, - 174, 0, 175, 176, 177, 178, 179, 1345, 180, 181, - 182, 183, 184, 185, 186, 187, 188, 189, 190, 0, - 191, 192, 193, 617, 0, 194, 195, 196, 197, 0, - 0, 0, 0, 0, 0, 0, 0, 1367, 0, 0, - 1370, 1371, 0, 0, 198, 199, 0, 0, 1375, 0, + 0, 1259, 0, 1260, 0, 0, 0, 0, 1263, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1379, 0, 0, 0, 0, 0, 524, 0, 0, 1381, - 402, 403, 3, 0, 525, 526, 527, 0, 528, 1391, - 404, 405, 406, 407, 408, 0, 0, 0, 0, 200, - 409, 529, 410, 530, 531, 0, 411, 0, 0, 0, - 0, 0, 0, 532, 412, 0, 1409, 533, 0, 534, - 413, 0, 0, 414, 0, 8, 415, 535, 0, 536, - 416, 0, 0, 537, 538, 0, 1424, 0, 0, 0, - 539, 1426, 1427, 418, 419, 0, 222, 223, 224, 0, - 226, 227, 228, 229, 230, 420, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 0, 244, 245, - 246, 0, 0, 249, 250, 251, 252, 421, 422, 423, - 540, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 424, 425, 0, 0, 0, 0, 0, 0, + 1267, 0, 55, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1283, 0, 256, 0, 0, 0, 0, + 0, 0, 0, 1290, 0, 0, 56, 0, 0, 0, + 0, 0, 0, 1299, 1300, 1301, 0, 0, 0, 0, + 1308, 0, 0, 0, 618, 1311, 0, 0, 0, 0, + 0, 0, 0, 173, 1318, 1319, 1320, 0, 0, 0, + 0, 0, 0, 0, 1324, 0, 0, 0, 0, 0, + 0, 257, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, + 1341, 175, 0, 176, 177, 178, 179, 180, 1346, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 0, 192, 193, 194, 618, 0, 195, 196, 197, 198, + 0, 0, 0, 0, 0, 0, 0, 0, 1368, 0, + 0, 1371, 1372, 0, 0, 199, 200, 0, 0, 1376, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, - 0, 426, 427, 428, 429, 430, 0, 431, 0, 432, - 433, 434, 435, 436, 437, 438, 439, 56, 440, 0, - 0, 0, 0, 0, 0, 441, 541, 542, 0, 0, + 0, 1380, 0, 0, 0, 0, 0, 525, 0, 0, + 1382, 403, 404, 3, 0, 526, 527, 528, 0, 529, + 1392, 405, 406, 407, 408, 409, 0, 0, 0, 0, + 201, 410, 530, 411, 531, 532, 0, 412, 0, 0, + 0, 0, 0, 0, 533, 413, 0, 1410, 534, 0, + 535, 414, 0, 0, 415, 0, 8, 416, 536, 0, + 537, 417, 0, 0, 538, 539, 0, 1425, 0, 0, + 0, 540, 1427, 1428, 419, 420, 0, 223, 224, 225, + 0, 227, 228, 229, 230, 231, 421, 233, 234, 235, + 236, 237, 238, 239, 240, 241, 242, 243, 0, 245, + 246, 247, 0, 0, 250, 251, 252, 253, 422, 423, + 424, 541, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 425, 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 442, 443, 444, 0, 14, 0, 0, 445, - 446, 0, 0, 0, 0, 0, 0, 0, 447, 0, - 448, 524, 449, 450, 0, 402, 403, 3, 0, 525, - 526, 527, 0, 528, 0, 404, 405, 406, 407, 408, - 0, 0, 0, 0, 0, 409, 529, 410, 530, 531, - 0, 411, 0, 0, 0, 0, 0, 0, 532, 412, - 0, 0, 533, 0, 534, 413, 0, 0, 414, 0, - 8, 415, 535, 0, 536, 416, 0, 0, 537, 538, - 0, 0, 0, 0, 0, 539, 0, 0, 418, 419, - 0, 222, 223, 224, 0, 226, 227, 228, 229, 230, - 420, 232, 233, 234, 235, 236, 237, 238, 239, 240, - 241, 242, 0, 244, 245, 246, 0, 0, 249, 250, - 251, 252, 421, 422, 423, 540, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 424, 425, 0, + 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, + 0, 0, 427, 428, 429, 430, 431, 0, 432, 0, + 433, 434, 435, 436, 437, 438, 439, 440, 56, 441, + 0, 0, 0, 0, 0, 0, 442, 542, 543, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, - 0, 0, 0, 0, 0, 0, 426, 427, 428, 429, - 430, 0, 431, 0, 432, 433, 434, 435, 436, 437, - 438, 439, 56, 440, 0, 0, 0, 0, 0, 0, - 441, 1030, 542, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 442, 443, 444, - 0, 14, 0, 0, 445, 446, 0, 0, 0, 0, - 0, 0, 0, 447, 0, 448, 524, 449, 450, 0, - 402, 403, 3, 0, 525, 526, 527, 0, 528, 0, - 404, 405, 406, 407, 408, 0, 0, 0, 0, 0, - 409, 529, 410, 530, 531, 0, 411, 0, 0, 0, - 0, 0, 0, 532, 412, 0, 0, 533, 0, 534, - 413, 0, 0, 414, 0, 8, 415, 535, 0, 536, - 416, 0, 0, 537, 538, 0, 0, 0, 0, 0, - 539, 0, 0, 418, 419, 0, 222, 223, 224, 0, - 226, 227, 228, 229, 230, 420, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 0, 244, 245, - 246, 0, 0, 249, 250, 251, 252, 421, 422, 423, - 540, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 424, 425, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 443, 444, 445, 0, 14, 0, 0, + 446, 447, 0, 0, 0, 0, 0, 0, 0, 448, + 0, 449, 525, 450, 451, 0, 403, 404, 3, 0, + 526, 527, 528, 0, 529, 0, 405, 406, 407, 408, + 409, 0, 0, 0, 0, 0, 410, 530, 411, 531, + 532, 0, 412, 0, 0, 0, 0, 0, 0, 533, + 413, 0, 0, 534, 0, 535, 414, 0, 0, 415, + 0, 8, 416, 536, 0, 537, 417, 0, 0, 538, + 539, 0, 0, 0, 0, 0, 540, 0, 0, 419, + 420, 0, 223, 224, 225, 0, 227, 228, 229, 230, + 231, 421, 233, 234, 235, 236, 237, 238, 239, 240, + 241, 242, 243, 0, 245, 246, 247, 0, 0, 250, + 251, 252, 253, 422, 423, 424, 541, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 425, 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, - 0, 426, 427, 428, 429, 430, 0, 431, 0, 432, - 433, 434, 435, 436, 437, 438, 439, 56, 440, 0, - 0, 0, 0, 0, 0, 441, 1187, 542, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, + 0, 0, 0, 0, 0, 0, 0, 427, 428, 429, + 430, 431, 0, 432, 0, 433, 434, 435, 436, 437, + 438, 439, 440, 56, 441, 0, 0, 0, 0, 0, + 0, 442, 1031, 543, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 443, 444, + 445, 0, 14, 0, 0, 446, 447, 0, 0, 0, + 0, 0, 0, 0, 448, 0, 449, 525, 450, 451, + 0, 403, 404, 3, 0, 526, 527, 528, 0, 529, + 0, 405, 406, 407, 408, 409, 0, 0, 0, 0, + 0, 410, 530, 411, 531, 532, 0, 412, 0, 0, + 0, 0, 0, 0, 533, 413, 0, 0, 534, 0, + 535, 414, 0, 0, 415, 0, 8, 416, 536, 0, + 537, 417, 0, 0, 538, 539, 0, 0, 0, 0, + 0, 540, 0, 0, 419, 420, 0, 223, 224, 225, + 0, 227, 228, 229, 230, 231, 421, 233, 234, 235, + 236, 237, 238, 239, 240, 241, 242, 243, 0, 245, + 246, 247, 0, 0, 250, 251, 252, 253, 422, 423, + 424, 541, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 425, 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 442, 443, 444, 0, 14, 0, 0, 445, - 446, 0, 0, 0, 402, 403, 0, 0, 447, 0, - 448, 0, 449, 450, 404, 405, 406, 407, 408, 0, - 0, 0, 0, 0, 409, 529, 410, 530, 0, 0, - 411, 0, 0, 0, 0, 0, 0, 0, 412, 0, - 0, 0, 0, 0, 413, 0, 0, 414, 0, 0, - 415, 535, 0, 0, 416, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 417, 0, 0, 418, 419, 0, - 222, 223, 224, 0, 226, 227, 228, 229, 230, 420, - 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, - 242, 0, 244, 245, 246, 0, 0, 249, 250, 251, - 252, 421, 422, 423, 540, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 424, 425, 0, 0, + 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, + 0, 0, 427, 428, 429, 430, 431, 0, 432, 0, + 433, 434, 435, 436, 437, 438, 439, 440, 56, 441, + 0, 0, 0, 0, 0, 0, 442, 1188, 543, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, - 0, 0, 0, 0, 0, 426, 427, 428, 429, 430, - 0, 431, 0, 432, 433, 434, 435, 436, 437, 438, - 439, 56, 440, 0, 0, 0, 0, 0, 0, 441, + 0, 0, 0, 443, 444, 445, 0, 14, 0, 0, + 446, 447, 0, 0, 0, 403, 404, 0, 0, 448, + 0, 449, 0, 450, 451, 405, 406, 407, 408, 409, + 0, 0, 0, 0, 0, 410, 530, 411, 531, 0, + 0, 412, 0, 0, 0, 0, 0, 0, 0, 413, + 0, 0, 0, 0, 0, 414, 0, 0, 415, 0, + 0, 416, 536, 0, 0, 417, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 418, 0, 0, 419, 420, + 0, 223, 224, 225, 0, 227, 228, 229, 230, 231, + 421, 233, 234, 235, 236, 237, 238, 239, 240, 241, + 242, 243, 0, 245, 246, 247, 0, 0, 250, 251, + 252, 253, 422, 423, 424, 541, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 425, 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 442, 443, 444, 0, - 14, 0, 0, 445, 446, 0, 0, 0, 402, 403, - 0, 0, 447, 0, 448, 0, 449, 450, 404, 405, - 406, 407, 408, 0, 0, 0, 0, 0, 409, 0, - 410, 0, 0, 0, 411, 0, 0, 0, 0, 0, - 0, 0, 412, 0, 0, 0, 0, 0, 413, 0, - 0, 414, 0, 0, 415, 0, 0, 0, 416, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 417, 0, - 0, 418, 419, 822, 222, 223, 224, 0, 226, 227, - 228, 229, 230, 420, 232, 233, 234, 235, 236, 237, - 238, 239, 240, 241, 242, 0, 244, 245, 246, 0, - 0, 249, 250, 251, 252, 421, 422, 423, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, + 0, 0, 0, 0, 0, 0, 427, 428, 429, 430, + 431, 0, 432, 0, 433, 434, 435, 436, 437, 438, + 439, 440, 56, 441, 0, 0, 0, 0, 0, 0, + 442, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 443, 444, 445, + 0, 14, 0, 0, 446, 447, 0, 0, 0, 403, + 404, 0, 0, 448, 0, 449, 0, 450, 451, 405, + 406, 407, 408, 409, 0, 0, 0, 0, 0, 410, + 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, + 0, 0, 0, 413, 0, 0, 0, 0, 0, 414, + 0, 0, 415, 0, 0, 416, 0, 0, 0, 417, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 418, + 0, 0, 419, 420, 823, 223, 224, 225, 0, 227, + 228, 229, 230, 231, 421, 233, 234, 235, 236, 237, + 238, 239, 240, 241, 242, 243, 0, 245, 246, 247, + 0, 0, 250, 251, 252, 253, 422, 423, 424, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 424, 425, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 425, 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 55, 0, 0, 0, 0, 0, 0, 0, 426, - 427, 428, 429, 430, 0, 431, 823, 432, 433, 434, - 435, 436, 437, 438, 439, 824, 440, 0, 0, 0, - 0, 0, 0, 441, 0, 0, 0, 0, 0, 0, + 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, + 427, 428, 429, 430, 431, 0, 432, 824, 433, 434, + 435, 436, 437, 438, 439, 440, 825, 441, 0, 0, + 0, 0, 0, 0, 442, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 442, 443, 444, 0, 14, 0, 0, 445, 446, 0, - 0, 0, 0, 0, 402, 403, 825, 0, 448, 826, - 449, 450, 625, 0, 404, 405, 406, 407, 408, 0, - 0, 0, 0, 0, 409, 0, 410, 0, 0, 0, - 411, 0, 0, 0, 0, 0, 0, 0, 412, 0, - 0, 0, 0, 0, 413, 0, 0, 414, 626, 0, - 415, 0, 0, 0, 416, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 417, 0, 0, 418, 419, 0, - 222, 223, 224, 0, 226, 227, 228, 229, 230, 420, - 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, - 242, 0, 244, 245, 246, 0, 0, 249, 250, 251, - 252, 421, 422, 423, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 424, 425, 0, 0, + 0, 443, 444, 445, 0, 14, 0, 0, 446, 447, + 0, 0, 0, 0, 0, 403, 404, 826, 0, 449, + 827, 450, 451, 626, 0, 405, 406, 407, 408, 409, + 0, 0, 0, 0, 0, 410, 0, 411, 0, 0, + 0, 412, 0, 0, 0, 0, 0, 0, 0, 413, + 0, 0, 0, 0, 0, 414, 0, 0, 415, 627, + 0, 416, 0, 0, 0, 417, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 418, 0, 0, 419, 420, + 0, 223, 224, 225, 0, 227, 228, 229, 230, 231, + 421, 233, 234, 235, 236, 237, 238, 239, 240, 241, + 242, 243, 0, 245, 246, 247, 0, 0, 250, 251, + 252, 253, 422, 423, 424, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 425, 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, - 0, 0, 0, 0, 0, 426, 427, 428, 429, 430, - 0, 431, 823, 432, 433, 434, 435, 436, 437, 438, - 439, 824, 440, 0, 0, 0, 0, 0, 0, 441, + 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, + 0, 0, 0, 0, 0, 0, 427, 428, 429, 430, + 431, 0, 432, 824, 433, 434, 435, 436, 437, 438, + 439, 440, 825, 441, 0, 0, 0, 0, 0, 0, + 442, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 443, 444, 445, + 0, 14, 0, 0, 446, 447, 0, 0, 0, 0, + 0, 403, 404, 448, 0, 449, 0, 450, 451, 626, + 0, 405, 406, 407, 408, 409, 0, 0, 0, 0, + 0, 410, 0, 411, 0, 0, 0, 412, 0, 0, + 0, 0, 0, 0, 0, 413, 0, 0, 0, 0, + 0, 414, 0, 0, 415, 627, 0, 416, 0, 0, + 0, 417, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 418, 0, 0, 419, 420, 0, 223, 224, 225, + 0, 227, 228, 229, 230, 231, 421, 233, 234, 235, + 236, 237, 238, 239, 240, 241, 242, 243, 0, 245, + 246, 247, 0, 0, 250, 251, 252, 253, 422, 423, + 424, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 425, 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 442, 443, 444, 0, - 14, 0, 0, 445, 446, 0, 0, 0, 0, 0, - 402, 403, 447, 0, 448, 0, 449, 450, 625, 0, - 404, 405, 406, 407, 408, 0, 0, 0, 0, 0, - 409, 0, 410, 0, 0, 0, 411, 0, 0, 0, - 0, 0, 0, 0, 412, 0, 0, 0, 0, 0, - 413, 0, 0, 414, 626, 0, 415, 0, 0, 0, - 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 417, 0, 0, 418, 419, 0, 222, 223, 224, 0, - 226, 227, 228, 229, 230, 420, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 0, 244, 245, - 246, 0, 0, 249, 250, 251, 252, 421, 422, 423, + 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, + 0, 0, 427, 428, 429, 430, 431, 0, 432, 0, + 433, 434, 435, 436, 437, 438, 439, 440, 56, 441, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 424, 425, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 443, 444, 445, 0, 14, 0, 0, + 446, 447, 0, 0, 0, 403, 404, 0, 0, 448, + 0, 449, 0, 450, 451, 405, 406, 407, 408, 409, + 0, 0, 0, 0, 0, 410, 0, 411, 0, 0, + 0, 412, 0, 0, 0, 0, 0, 0, 0, 413, + 0, 0, 0, 0, 0, 414, 0, 0, 415, 0, + 0, 416, 0, 0, 0, 417, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 418, 0, 0, 419, 420, + 970, 223, 224, 225, 0, 227, 228, 229, 230, 231, + 421, 233, 234, 235, 236, 237, 238, 239, 240, 241, + 242, 243, 0, 245, 246, 247, 0, 0, 250, 251, + 252, 253, 422, 423, 424, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 425, 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, - 0, 426, 427, 428, 429, 430, 0, 431, 0, 432, - 433, 434, 435, 436, 437, 438, 439, 56, 440, 0, - 0, 0, 0, 0, 0, 441, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, + 0, 0, 0, 0, 0, 0, 427, 428, 429, 430, + 431, 0, 432, 824, 433, 434, 435, 436, 437, 438, + 439, 440, 825, 441, 0, 0, 0, 0, 0, 0, + 442, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 443, 444, 445, + 0, 14, 0, 0, 446, 447, 0, 0, 0, 403, + 404, 0, 0, 448, 0, 449, 0, 450, 451, 405, + 406, 407, 408, 409, 0, 0, 0, 0, 0, 410, + 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, + 0, 0, 0, 413, 0, 0, 0, 0, 0, 414, + 0, 0, 415, 0, 0, 416, 0, 0, 0, 417, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 418, + 0, 0, 419, 420, 0, 223, 224, 225, 0, 227, + 228, 229, 230, 231, 421, 233, 234, 235, 236, 237, + 238, 239, 240, 241, 242, 243, 0, 245, 246, 247, + 0, 0, 250, 251, 252, 253, 422, 423, 424, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 442, 443, 444, 0, 14, 0, 0, 445, - 446, 0, 0, 0, 402, 403, 0, 0, 447, 0, - 448, 0, 449, 450, 404, 405, 406, 407, 408, 0, - 0, 0, 0, 0, 409, 0, 410, 0, 0, 0, - 411, 0, 0, 0, 0, 0, 0, 0, 412, 0, - 0, 0, 0, 0, 413, 0, 0, 414, 0, 0, - 415, 0, 0, 0, 416, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 417, 0, 0, 418, 419, 969, - 222, 223, 224, 0, 226, 227, 228, 229, 230, 420, - 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, - 242, 0, 244, 245, 246, 0, 0, 249, 250, 251, - 252, 421, 422, 423, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 424, 425, 0, 0, + 0, 425, 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, - 0, 0, 0, 0, 0, 426, 427, 428, 429, 430, - 0, 431, 823, 432, 433, 434, 435, 436, 437, 438, - 439, 824, 440, 0, 0, 0, 0, 0, 0, 441, + 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, + 427, 428, 429, 430, 431, 0, 432, 0, 433, 434, + 435, 436, 437, 438, 439, 440, 56, 441, 0, 0, + 0, 0, 0, 0, 442, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 442, 443, 444, 0, - 14, 0, 0, 445, 446, 0, 0, 0, 402, 403, - 0, 0, 447, 0, 448, 0, 449, 450, 404, 405, - 406, 407, 408, 0, 0, 0, 0, 0, 409, 0, - 410, 0, 0, 0, 411, 0, 0, 0, 0, 0, - 0, 0, 412, 0, 0, 0, 0, 0, 413, 0, - 0, 414, 0, 0, 415, 0, 0, 0, 416, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 417, 0, - 0, 418, 419, 0, 222, 223, 224, 0, 226, 227, - 228, 229, 230, 420, 232, 233, 234, 235, 236, 237, - 238, 239, 240, 241, 242, 0, 244, 245, 246, 0, - 0, 249, 250, 251, 252, 421, 422, 423, 0, 0, + 0, 443, 444, 445, 0, 14, 0, 0, 446, 447, + 0, 0, 0, 0, 0, 403, 404, 448, 498, 449, + 0, 450, 451, 617, 0, 405, 406, 407, 408, 409, + 0, 0, 0, 0, 0, 410, 0, 411, 0, 0, + 0, 412, 0, 0, 0, 0, 0, 0, 0, 413, + 0, 0, 0, 0, 0, 414, 0, 0, 415, 0, + 0, 416, 0, 0, 0, 417, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 418, 0, 0, 419, 420, + 0, 223, 224, 225, 0, 227, 228, 229, 230, 231, + 421, 233, 234, 235, 236, 237, 238, 239, 240, 241, + 242, 243, 0, 245, 246, 247, 0, 0, 250, 251, + 252, 253, 422, 423, 424, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 425, 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 424, 425, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, + 0, 0, 0, 0, 0, 0, 427, 428, 429, 430, + 431, 0, 432, 0, 433, 434, 435, 436, 437, 438, + 439, 440, 56, 441, 0, 0, 0, 0, 0, 0, + 442, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 443, 444, 445, + 0, 14, 0, 0, 446, 447, 0, 0, 0, 403, + 404, 0, 0, 448, 0, 449, 0, 450, 451, 405, + 406, 407, 408, 409, 0, 0, 0, 0, 0, 410, + 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, + 0, 0, 0, 413, 0, 0, 0, 0, 0, 414, + 0, 0, 415, 0, 0, 416, 0, 0, 0, 417, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 418, + 0, 0, 419, 420, 0, 223, 224, 225, 0, 227, + 228, 229, 230, 231, 421, 233, 234, 235, 236, 237, + 238, 239, 240, 241, 242, 243, 0, 245, 246, 247, + 0, 0, 250, 251, 252, 253, 422, 423, 424, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 55, 0, 0, 0, 0, 0, 0, 0, 426, - 427, 428, 429, 430, 0, 431, 0, 432, 433, 434, - 435, 436, 437, 438, 439, 56, 440, 0, 0, 0, - 0, 0, 0, 441, 0, 0, 0, 0, 0, 0, + 0, 425, 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 442, 443, 444, 0, 14, 0, 0, 445, 446, 0, - 0, 0, 0, 0, 402, 403, 447, 497, 448, 0, - 449, 450, 616, 0, 404, 405, 406, 407, 408, 0, - 0, 0, 0, 0, 409, 0, 410, 0, 0, 0, - 411, 0, 0, 0, 0, 0, 0, 0, 412, 0, - 0, 0, 0, 0, 413, 0, 0, 414, 0, 0, - 415, 0, 0, 0, 416, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 417, 0, 0, 418, 419, 0, - 222, 223, 224, 0, 226, 227, 228, 229, 230, 420, - 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, - 242, 0, 244, 245, 246, 0, 0, 249, 250, 251, - 252, 421, 422, 423, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 424, 425, 0, 0, + 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, + 427, 428, 429, 430, 431, 0, 432, 0, 433, 434, + 435, 436, 437, 438, 439, 440, 56, 441, 0, 0, + 0, 0, 0, 0, 442, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, - 0, 0, 0, 0, 0, 426, 427, 428, 429, 430, - 0, 431, 0, 432, 433, 434, 435, 436, 437, 438, - 439, 56, 440, 0, 0, 0, 0, 0, 0, 441, + 0, 443, 444, 445, 0, 14, 0, 0, 446, 447, + 0, 0, 0, 403, 404, 0, 0, 448, 696, 449, + 0, 450, 451, 405, 406, 407, 408, 409, 0, 0, + 0, 0, 0, 410, 0, 411, 0, 0, 0, 412, + 0, 0, 0, 0, 0, 0, 0, 413, 0, 0, + 0, 0, 0, 414, 0, 0, 415, 0, 0, 416, + 0, 0, 0, 417, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 418, 0, 0, 419, 420, 0, 223, + 224, 225, 0, 227, 228, 229, 230, 231, 421, 233, + 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, + 0, 245, 246, 247, 0, 0, 250, 251, 252, 253, + 422, 423, 424, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 425, 426, 0, 0, 0, + 0, 0, 0, 0, 714, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, + 0, 0, 0, 0, 427, 428, 429, 430, 431, 0, + 432, 0, 433, 434, 435, 436, 437, 438, 439, 440, + 56, 441, 0, 0, 0, 0, 0, 0, 442, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 442, 443, 444, 0, - 14, 0, 0, 445, 446, 0, 0, 0, 402, 403, - 0, 0, 447, 0, 448, 0, 449, 450, 404, 405, - 406, 407, 408, 0, 0, 0, 0, 0, 409, 0, - 410, 0, 0, 0, 411, 0, 0, 0, 0, 0, - 0, 0, 412, 0, 0, 0, 0, 0, 413, 0, - 0, 414, 0, 0, 415, 0, 0, 0, 416, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 417, 0, - 0, 418, 419, 0, 222, 223, 224, 0, 226, 227, - 228, 229, 230, 420, 232, 233, 234, 235, 236, 237, - 238, 239, 240, 241, 242, 0, 244, 245, 246, 0, - 0, 249, 250, 251, 252, 421, 422, 423, 0, 0, + 0, 0, 0, 0, 0, 443, 444, 445, 0, 14, + 0, 0, 446, 447, 0, 0, 0, 403, 404, 0, + 0, 448, 0, 449, 0, 450, 451, 405, 406, 407, + 408, 409, 0, 0, 0, 0, 0, 410, 0, 411, + 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, + 0, 413, 0, 0, 0, 0, 0, 414, 0, 0, + 415, 0, 0, 416, 0, 0, 0, 417, 0, 0, + 0, 0, 0, 717, 0, 0, 0, 418, 0, 0, + 419, 420, 0, 223, 224, 225, 0, 227, 228, 229, + 230, 231, 421, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 0, 245, 246, 247, 0, 0, + 250, 251, 252, 253, 422, 423, 424, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 425, + 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 424, 425, 0, 0, 0, 0, 0, 0, 0, 0, + 55, 0, 0, 0, 0, 0, 0, 0, 427, 428, + 429, 430, 431, 0, 432, 0, 433, 434, 435, 436, + 437, 438, 439, 440, 56, 441, 0, 0, 0, 0, + 0, 0, 442, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, + 444, 445, 0, 14, 0, 0, 446, 447, 0, 0, + 0, 403, 404, 0, 0, 448, 0, 449, 0, 450, + 451, 405, 406, 407, 408, 409, 0, 0, 0, 0, + 0, 410, 0, 411, 0, 0, 0, 412, 0, 0, + 0, 0, 0, 0, 0, 413, 0, 0, 0, 0, + 0, 414, 0, 0, 415, 0, 0, 416, 0, 0, + 0, 417, 0, 0, 723, 0, 0, 0, 0, 0, + 0, 418, 0, 0, 419, 420, 0, 223, 224, 225, + 0, 227, 228, 229, 230, 231, 421, 233, 234, 235, + 236, 237, 238, 239, 240, 241, 242, 243, 0, 245, + 246, 247, 0, 0, 250, 251, 252, 253, 422, 423, + 424, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 425, 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 55, 0, 0, 0, 0, 0, 0, 0, 426, - 427, 428, 429, 430, 0, 431, 0, 432, 433, 434, - 435, 436, 437, 438, 439, 56, 440, 0, 0, 0, - 0, 0, 0, 441, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, + 0, 0, 427, 428, 429, 430, 431, 0, 432, 0, + 433, 434, 435, 436, 437, 438, 439, 440, 56, 441, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 442, 443, 444, 0, 14, 0, 0, 445, 446, 0, - 0, 0, 402, 403, 0, 0, 447, 695, 448, 0, - 449, 450, 404, 405, 406, 407, 408, 0, 0, 0, - 0, 0, 409, 0, 410, 0, 0, 0, 411, 0, - 0, 0, 0, 0, 0, 0, 412, 0, 0, 0, - 0, 0, 413, 0, 0, 414, 0, 0, 415, 0, - 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 417, 0, 0, 418, 419, 0, 222, 223, - 224, 0, 226, 227, 228, 229, 230, 420, 232, 233, - 234, 235, 236, 237, 238, 239, 240, 241, 242, 0, - 244, 245, 246, 0, 0, 249, 250, 251, 252, 421, - 422, 423, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 424, 425, 0, 0, 0, 0, - 0, 0, 0, 713, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, - 0, 0, 0, 426, 427, 428, 429, 430, 0, 431, - 0, 432, 433, 434, 435, 436, 437, 438, 439, 56, - 440, 0, 0, 0, 0, 0, 0, 441, 0, 0, + 0, 0, 0, 443, 444, 445, 0, 14, 0, 0, + 446, 447, 0, 0, 0, 403, 404, 0, 0, 448, + 0, 449, 0, 450, 451, 405, 406, 407, 408, 409, + 0, 0, 0, 0, 0, 410, 0, 411, 0, 0, + 0, 412, 0, 0, 0, 0, 0, 0, 0, 413, + 0, 0, 0, 0, 0, 414, 0, 0, 415, 0, + 0, 416, 0, 0, 0, 417, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 418, 0, 0, 419, 420, + 0, 223, 224, 225, 0, 227, 228, 229, 230, 231, + 421, 233, 234, 235, 236, 237, 238, 239, 240, 241, + 242, 243, 0, 245, 246, 247, 0, 0, 250, 251, + 252, 253, 422, 423, 424, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 425, 426, 0, + 0, 0, 0, 0, 0, 0, 726, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, + 0, 0, 0, 0, 0, 0, 427, 428, 429, 430, + 431, 0, 432, 0, 433, 434, 435, 436, 437, 438, + 439, 440, 56, 441, 0, 0, 0, 0, 0, 0, + 442, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 443, 444, 445, + 0, 14, 0, 0, 446, 447, 0, 0, 0, 403, + 404, 0, 0, 448, 0, 449, 0, 450, 451, 405, + 406, 407, 408, 409, 0, 0, 864, 0, 0, 410, + 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, + 0, 0, 0, 413, 0, 0, 0, 0, 0, 414, + 0, 0, 415, 0, 0, 416, 0, 0, 0, 417, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 418, + 0, 0, 419, 420, 0, 223, 224, 225, 0, 227, + 228, 229, 230, 231, 421, 233, 234, 235, 236, 237, + 238, 239, 240, 241, 242, 243, 0, 245, 246, 247, + 0, 0, 250, 251, 252, 253, 422, 423, 424, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 442, 443, 444, 0, 14, 0, - 0, 445, 446, 0, 0, 0, 402, 403, 0, 0, - 447, 0, 448, 0, 449, 450, 404, 405, 406, 407, - 408, 0, 0, 0, 0, 0, 409, 0, 410, 0, - 0, 0, 411, 0, 0, 0, 0, 0, 0, 0, - 412, 0, 0, 0, 0, 0, 413, 0, 0, 414, - 0, 0, 415, 0, 0, 0, 416, 0, 0, 0, - 0, 0, 716, 0, 0, 0, 417, 0, 0, 418, - 419, 0, 222, 223, 224, 0, 226, 227, 228, 229, - 230, 420, 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 0, 244, 245, 246, 0, 0, 249, - 250, 251, 252, 421, 422, 423, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 424, 425, + 0, 425, 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, - 0, 0, 0, 0, 0, 0, 0, 426, 427, 428, - 429, 430, 0, 431, 0, 432, 433, 434, 435, 436, - 437, 438, 439, 56, 440, 0, 0, 0, 0, 0, - 0, 441, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 442, 443, - 444, 0, 14, 0, 0, 445, 446, 0, 0, 0, - 402, 403, 0, 0, 447, 0, 448, 0, 449, 450, - 404, 405, 406, 407, 408, 0, 0, 0, 0, 0, - 409, 0, 410, 0, 0, 0, 411, 0, 0, 0, - 0, 0, 0, 0, 412, 0, 0, 0, 0, 0, - 413, 0, 0, 414, 0, 0, 415, 0, 0, 0, - 416, 0, 0, 722, 0, 0, 0, 0, 0, 0, - 417, 0, 0, 418, 419, 0, 222, 223, 224, 0, - 226, 227, 228, 229, 230, 420, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 0, 244, 245, - 246, 0, 0, 249, 250, 251, 252, 421, 422, 423, + 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, + 427, 428, 429, 430, 431, 0, 432, 0, 433, 434, + 435, 436, 437, 438, 439, 440, 56, 441, 0, 0, + 0, 0, 0, 0, 442, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 424, 425, 0, 0, 0, 0, 0, 0, + 0, 443, 444, 445, 0, 14, 0, 0, 446, 447, + 0, 0, 0, 403, 404, 0, 0, 448, 0, 449, + 0, 450, 451, 405, 406, 407, 408, 409, 0, 0, + 0, 0, 0, 410, 0, 411, 0, 0, 0, 412, + 0, 0, 0, 0, 0, 0, 0, 413, 0, 0, + 0, 0, 0, 414, 0, 0, 415, 0, 0, 416, + 0, 0, 0, 417, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 418, 0, 0, 419, 420, 0, 223, + 224, 225, 0, 227, 228, 229, 230, 231, 421, 233, + 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, + 0, 245, 246, 247, 0, 0, 250, 251, 252, 253, + 422, 423, 424, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 425, 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, - 0, 426, 427, 428, 429, 430, 0, 431, 0, 432, - 433, 434, 435, 436, 437, 438, 439, 56, 440, 0, - 0, 0, 0, 0, 0, 441, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, + 0, 0, 0, 0, 427, 428, 429, 430, 431, 0, + 432, 0, 433, 434, 435, 436, 437, 438, 439, 440, + 56, 441, 0, 0, 0, 0, 0, 0, 442, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 442, 443, 444, 0, 14, 0, 0, 445, - 446, 0, 0, 0, 402, 403, 0, 0, 447, 0, - 448, 0, 449, 450, 404, 405, 406, 407, 408, 0, - 0, 0, 0, 0, 409, 0, 410, 0, 0, 0, - 411, 0, 0, 0, 0, 0, 0, 0, 412, 0, - 0, 0, 0, 0, 413, 0, 0, 414, 0, 0, - 415, 0, 0, 0, 416, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 417, 0, 0, 418, 419, 0, - 222, 223, 224, 0, 226, 227, 228, 229, 230, 420, - 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, - 242, 0, 244, 245, 246, 0, 0, 249, 250, 251, - 252, 421, 422, 423, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 424, 425, 0, 0, - 0, 0, 0, 0, 0, 725, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, - 0, 0, 0, 0, 0, 426, 427, 428, 429, 430, - 0, 431, 0, 432, 433, 434, 435, 436, 437, 438, - 439, 56, 440, 0, 0, 0, 0, 0, 0, 441, + 0, 0, 0, 0, 0, 443, 444, 445, 0, 14, + 0, 0, 446, 447, 0, 0, 0, 403, 404, 0, + 0, 448, 0, 449, 885, 450, 451, 405, 406, 407, + 408, 409, 0, 0, 0, 0, 0, 410, 0, 411, + 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, + 0, 413, 0, 0, 0, 0, 0, 414, 0, 0, + 415, 0, 0, 416, 0, 0, 0, 417, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 418, 0, 0, + 419, 420, 0, 223, 224, 225, 0, 227, 228, 229, + 230, 231, 421, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 0, 245, 246, 247, 0, 0, + 250, 251, 252, 253, 422, 423, 424, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 425, + 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 442, 443, 444, 0, - 14, 0, 0, 445, 446, 0, 0, 0, 402, 403, - 0, 0, 447, 0, 448, 0, 449, 450, 404, 405, - 406, 407, 408, 0, 0, 863, 0, 0, 409, 0, - 410, 0, 0, 0, 411, 0, 0, 0, 0, 0, - 0, 0, 412, 0, 0, 0, 0, 0, 413, 0, - 0, 414, 0, 0, 415, 0, 0, 0, 416, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 417, 0, - 0, 418, 419, 0, 222, 223, 224, 0, 226, 227, - 228, 229, 230, 420, 232, 233, 234, 235, 236, 237, - 238, 239, 240, 241, 242, 0, 244, 245, 246, 0, - 0, 249, 250, 251, 252, 421, 422, 423, 0, 0, + 55, 0, 0, 0, 0, 0, 0, 0, 427, 428, + 429, 430, 431, 0, 432, 0, 433, 434, 435, 436, + 437, 438, 439, 440, 56, 441, 0, 0, 0, 0, + 0, 0, 442, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, + 444, 445, 0, 14, 0, 0, 446, 447, 0, 0, + 0, 403, 404, 0, 0, 448, 0, 449, 1161, 450, + 451, 405, 406, 407, 408, 409, 0, 0, 0, 0, + 0, 410, 0, 411, 0, 0, 0, 412, 0, 0, + 0, 0, 0, 0, 0, 413, 0, 0, 0, 0, + 0, 414, 0, 0, 415, 0, 0, 416, 0, 0, + 0, 417, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 418, 0, 0, 419, 420, 0, 223, 224, 225, + 0, 227, 228, 229, 230, 231, 421, 233, 234, 235, + 236, 237, 238, 239, 240, 241, 242, 243, 0, 245, + 246, 247, 0, 0, 250, 251, 252, 253, 422, 423, + 424, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 425, 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 424, 425, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, + 0, 0, 427, 428, 429, 430, 431, 0, 432, 0, + 433, 434, 435, 436, 437, 438, 439, 440, 56, 441, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 55, 0, 0, 0, 0, 0, 0, 0, 426, - 427, 428, 429, 430, 0, 431, 0, 432, 433, 434, - 435, 436, 437, 438, 439, 56, 440, 0, 0, 0, - 0, 0, 0, 441, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 443, 444, 445, 0, 14, 0, 0, + 446, 447, 0, 0, 0, 403, 404, 0, 0, 448, + 0, 449, 1170, 450, 451, 405, 406, 407, 408, 409, + 0, 0, 0, 0, 0, 410, 0, 411, 0, 0, + 0, 412, 0, 0, 0, 0, 0, 0, 0, 413, + 0, 0, 0, 0, 0, 414, 0, 0, 415, 0, + 0, 416, 0, 0, 0, 417, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 418, 0, 0, 419, 420, + 0, 223, 224, 225, 0, 227, 228, 229, 230, 231, + 421, 233, 234, 235, 236, 237, 238, 239, 240, 241, + 242, 243, 0, 245, 246, 247, 0, 0, 250, 251, + 252, 253, 422, 423, 424, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 425, 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 442, 443, 444, 0, 14, 0, 0, 445, 446, 0, - 0, 0, 402, 403, 0, 0, 447, 0, 448, 0, - 449, 450, 404, 405, 406, 407, 408, 0, 0, 0, - 0, 0, 409, 0, 410, 0, 0, 0, 411, 0, - 0, 0, 0, 0, 0, 0, 412, 0, 0, 0, - 0, 0, 413, 0, 0, 414, 0, 0, 415, 0, - 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 417, 0, 0, 418, 419, 0, 222, 223, - 224, 0, 226, 227, 228, 229, 230, 420, 232, 233, - 234, 235, 236, 237, 238, 239, 240, 241, 242, 0, - 244, 245, 246, 0, 0, 249, 250, 251, 252, 421, - 422, 423, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 424, 425, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, + 0, 0, 0, 0, 0, 0, 427, 428, 429, 430, + 431, 0, 432, 0, 433, 434, 435, 436, 437, 438, + 439, 440, 56, 441, 0, 0, 0, 0, 0, 0, + 442, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 443, 444, 445, + 0, 14, 0, 0, 446, 447, 0, 0, 0, 403, + 404, 0, 0, 448, 0, 449, 1175, 450, 451, 405, + 406, 407, 408, 409, 0, 0, 0, 0, 0, 410, + 0, 411, 0, 0, 0, 412, 0, 0, 0, 0, + 0, 0, 0, 413, 0, 0, 0, 0, 0, 414, + 0, 0, 415, 0, 0, 416, 0, 0, 0, 417, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 418, + 0, 0, 419, 420, 0, 223, 224, 225, 0, 227, + 228, 229, 230, 231, 421, 233, 234, 235, 236, 237, + 238, 239, 240, 241, 242, 243, 0, 245, 246, 247, + 0, 0, 250, 251, 252, 253, 422, 423, 424, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, - 0, 0, 0, 426, 427, 428, 429, 430, 0, 431, - 0, 432, 433, 434, 435, 436, 437, 438, 439, 56, - 440, 0, 0, 0, 0, 0, 0, 441, 0, 0, + 0, 425, 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 442, 443, 444, 0, 14, 0, - 0, 445, 446, 0, 0, 0, 402, 403, 0, 0, - 447, 0, 448, 884, 449, 450, 404, 405, 406, 407, - 408, 0, 0, 0, 0, 0, 409, 0, 410, 0, - 0, 0, 411, 0, 0, 0, 0, 0, 0, 0, - 412, 0, 0, 0, 0, 0, 413, 0, 0, 414, - 0, 0, 415, 0, 0, 0, 416, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 417, 0, 0, 418, - 419, 0, 222, 223, 224, 0, 226, 227, 228, 229, - 230, 420, 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 0, 244, 245, 246, 0, 0, 249, - 250, 251, 252, 421, 422, 423, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 424, 425, + 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, + 427, 428, 429, 430, 431, 0, 432, 0, 433, 434, + 435, 436, 437, 438, 439, 440, 56, 441, 0, 0, + 0, 0, 0, 0, 442, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, - 0, 0, 0, 0, 0, 0, 0, 426, 427, 428, - 429, 430, 0, 431, 0, 432, 433, 434, 435, 436, - 437, 438, 439, 56, 440, 0, 0, 0, 0, 0, - 0, 441, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 442, 443, - 444, 0, 14, 0, 0, 445, 446, 0, 0, 0, - 402, 403, 0, 0, 447, 0, 448, 1160, 449, 450, - 404, 405, 406, 407, 408, 0, 0, 0, 0, 0, - 409, 0, 410, 0, 0, 0, 411, 0, 0, 0, - 0, 0, 0, 0, 412, 0, 0, 0, 0, 0, - 413, 0, 0, 414, 0, 0, 415, 0, 0, 0, - 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 417, 0, 0, 418, 419, 0, 222, 223, 224, 0, - 226, 227, 228, 229, 230, 420, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 0, 244, 245, - 246, 0, 0, 249, 250, 251, 252, 421, 422, 423, + 0, 443, 444, 445, 0, 14, 0, 0, 446, 447, + 0, 0, 0, 403, 404, 0, 0, 448, 0, 449, + 1226, 450, 451, 405, 406, 407, 408, 409, 0, 0, + 0, 0, 0, 410, 0, 411, 0, 0, 0, 412, + 0, 0, 0, 0, 0, 0, 0, 413, 0, 0, + 0, 0, 0, 414, 0, 0, 415, 0, 0, 416, + 0, 0, 0, 417, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 418, 0, 0, 419, 420, 0, 223, + 224, 225, 0, 227, 228, 229, 230, 231, 421, 233, + 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, + 0, 245, 246, 247, 0, 0, 250, 251, 252, 253, + 422, 423, 424, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 425, 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 424, 425, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, + 0, 0, 0, 0, 427, 428, 429, 430, 431, 0, + 432, 0, 433, 434, 435, 436, 437, 438, 439, 440, + 56, 441, 0, 0, 0, 0, 0, 0, 442, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, - 0, 426, 427, 428, 429, 430, 0, 431, 0, 432, - 433, 434, 435, 436, 437, 438, 439, 56, 440, 0, - 0, 0, 0, 0, 0, 441, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 443, 444, 445, 0, 14, + 0, 0, 446, 447, 0, 0, 0, 403, 404, 0, + 0, 448, 0, 449, 1307, 450, 451, 405, 406, 407, + 408, 409, 0, 0, 0, 0, 0, 410, 0, 411, + 0, 0, 0, 412, 0, 0, 0, 0, 0, 0, + 0, 413, 0, 0, 0, 0, 0, 414, 0, 0, + 415, 0, 0, 416, 0, 0, 0, 417, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 418, 0, 0, + 419, 420, 0, 223, 224, 225, 0, 227, 228, 229, + 230, 231, 421, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 0, 245, 246, 247, 0, 0, + 250, 251, 252, 253, 422, 423, 424, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 425, + 426, 0, 0, 0, 0, 0, 0, 0, 1323, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 442, 443, 444, 0, 14, 0, 0, 445, - 446, 0, 0, 0, 402, 403, 0, 0, 447, 0, - 448, 1169, 449, 450, 404, 405, 406, 407, 408, 0, - 0, 0, 0, 0, 409, 0, 410, 0, 0, 0, - 411, 0, 0, 0, 0, 0, 0, 0, 412, 0, - 0, 0, 0, 0, 413, 0, 0, 414, 0, 0, - 415, 0, 0, 0, 416, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 417, 0, 0, 418, 419, 0, - 222, 223, 224, 0, 226, 227, 228, 229, 230, 420, - 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, - 242, 0, 244, 245, 246, 0, 0, 249, 250, 251, - 252, 421, 422, 423, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 424, 425, 0, 0, + 55, 0, 0, 0, 0, 0, 0, 0, 427, 428, + 429, 430, 431, 0, 432, 0, 433, 434, 435, 436, + 437, 438, 439, 440, 56, 441, 0, 0, 0, 0, + 0, 0, 442, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, + 444, 445, 0, 14, 0, 0, 446, 447, 0, 0, + 0, 403, 404, 0, 0, 448, 0, 449, 0, 450, + 451, 405, 406, 407, 408, 409, 0, 0, 0, 0, + 0, 410, 0, 411, 0, 0, 0, 412, 0, 0, + 0, 0, 0, 0, 0, 413, 0, 0, 0, 0, + 0, 414, 0, 0, 415, 0, 0, 416, 0, 0, + 0, 417, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 418, 0, 0, 419, 420, 0, 223, 224, 225, + 0, 227, 228, 229, 230, 231, 421, 233, 234, 235, + 236, 237, 238, 239, 240, 241, 242, 243, 0, 245, + 246, 247, 0, 0, 250, 251, 252, 253, 422, 423, + 424, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 425, 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, - 0, 0, 0, 0, 0, 426, 427, 428, 429, 430, - 0, 431, 0, 432, 433, 434, 435, 436, 437, 438, - 439, 56, 440, 0, 0, 0, 0, 0, 0, 441, + 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, + 0, 0, 427, 428, 429, 430, 431, 0, 432, 0, + 433, 434, 435, 436, 437, 438, 439, 440, 56, 441, + 0, 0, 0, 0, 0, 0, 442, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 442, 443, 444, 0, - 14, 0, 0, 445, 446, 0, 0, 0, 402, 403, - 0, 0, 447, 0, 448, 1174, 449, 450, 404, 405, - 406, 407, 408, 0, 0, 0, 0, 0, 409, 0, - 410, 0, 0, 0, 411, 0, 0, 0, 0, 0, - 0, 0, 412, 0, 0, 0, 0, 0, 413, 0, - 0, 414, 0, 0, 415, 0, 0, 0, 416, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 417, 0, - 0, 418, 419, 0, 222, 223, 224, 0, 226, 227, - 228, 229, 230, 420, 232, 233, 234, 235, 236, 237, - 238, 239, 240, 241, 242, 0, 244, 245, 246, 0, - 0, 249, 250, 251, 252, 421, 422, 423, 0, 0, + 0, 0, 0, 443, 444, 445, 0, 14, 0, 0, + 446, 447, 0, 0, 0, 403, 404, 0, 0, 448, + 0, 449, 0, 450, 451, 405, 406, 407, 408, 409, + 0, 0, 0, 0, 0, 410, 0, 411, 0, 0, + 0, 412, 0, 0, 0, 0, 0, 0, 0, 413, + 0, 0, 0, 0, 0, 414, 0, 0, 415, 0, + 0, 416, 0, 0, 0, 417, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 418, 0, 0, 419, 420, + 0, 223, 224, 225, 0, 227, 228, 229, 230, 231, + 421, 233, 234, 235, 236, 237, 238, 239, 240, 241, + 242, 243, 0, 245, 246, 247, 0, 0, 250, 251, + 252, 253, 422, 423, 424, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 425, 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 424, 425, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, + 0, 0, 0, 0, 0, 0, 427, 428, 429, 430, + 431, 0, 432, 0, 433, 434, 435, 436, 437, 438, + 439, 440, 56, 441, 638, 639, 0, 0, 217, 0, + 442, 0, 0, 0, 218, 0, 0, 0, 0, 0, + 219, 0, 0, 0, 0, 0, 0, 443, 444, 445, + 220, 14, 0, 0, 446, 447, 0, 0, 221, 0, + 638, 639, 0, 1145, 0, 449, 0, 450, 451, 0, + 0, 0, 0, 222, 0, 0, 0, 0, 0, 0, + 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, + 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, + 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 0, 0, 0, 0, 0, 640, 641, + 642, 643, 644, 0, 0, 645, 646, 647, 648, 0, + 649, 650, 651, 652, 653, 0, 654, 655, 0, 0, + 0, 0, 656, 657, 658, 0, 0, 55, 659, 0, + 0, 0, 638, 639, 640, 641, 642, 643, 644, 0, + 256, 645, 646, 647, 648, 0, 649, 650, 651, 652, + 653, 505, 654, 655, 0, 0, 0, 0, 656, 657, + 658, 0, 0, 660, 659, 661, 662, 663, 664, 665, + 666, 667, 668, 669, 670, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 671, 672, 0, 0, 690, + 0, 0, 0, 0, 0, 0, 257, 0, 0, 660, + 0, 661, 662, 663, 664, 665, 666, 667, 668, 669, + 670, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 671, 672, 0, 0, 909, 640, 641, 642, 643, + 644, 638, 639, 645, 646, 647, 648, 0, 649, 650, + 651, 652, 653, 0, 654, 655, 0, 0, 0, 0, + 656, 657, 658, 0, 0, 0, 659, 0, 0, 0, + 0, 0, 638, 639, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 55, 0, 0, 0, 0, 0, 0, 0, 426, - 427, 428, 429, 430, 0, 431, 0, 432, 433, 434, - 435, 436, 437, 438, 439, 56, 440, 0, 0, 0, - 0, 0, 0, 441, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 442, 443, 444, 0, 14, 0, 0, 445, 446, 0, - 0, 0, 402, 403, 0, 0, 447, 0, 448, 1225, - 449, 450, 404, 405, 406, 407, 408, 0, 0, 0, - 0, 0, 409, 0, 410, 0, 0, 0, 411, 0, - 0, 0, 0, 0, 0, 0, 412, 0, 0, 0, - 0, 0, 413, 0, 0, 414, 0, 0, 415, 0, - 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 417, 0, 0, 418, 419, 0, 222, 223, - 224, 0, 226, 227, 228, 229, 230, 420, 232, 233, - 234, 235, 236, 237, 238, 239, 240, 241, 242, 0, - 244, 245, 246, 0, 0, 249, 250, 251, 252, 421, - 422, 423, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 424, 425, 0, 0, 0, 0, + 0, 660, 0, 661, 662, 663, 664, 665, 666, 667, + 668, 669, 670, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 671, 672, 0, 0, 985, 0, 0, + 0, 0, 0, 0, 0, 640, 641, 642, 643, 644, + 0, 0, 645, 646, 647, 648, 0, 649, 650, 651, + 652, 653, 0, 654, 655, 0, 0, 0, 0, 656, + 657, 658, 0, 0, 0, 659, 640, 641, 642, 643, + 644, 638, 639, 645, 646, 647, 648, 0, 649, 650, + 651, 652, 653, 0, 654, 655, 0, 0, 0, 0, + 656, 657, 658, 0, 0, 0, 659, 0, 0, 0, + 660, 0, 661, 662, 663, 664, 665, 666, 667, 668, + 669, 670, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 671, 672, 0, 0, 988, 0, 0, 0, + 0, 660, 0, 661, 662, 663, 664, 665, 666, 667, + 668, 669, 670, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 671, 672, 0, 0, 990, 0, 0, + 0, 0, 0, 638, 639, 640, 641, 642, 643, 644, + 0, 0, 645, 646, 647, 648, 0, 649, 650, 651, + 652, 653, 0, 654, 655, 0, 0, 0, 0, 656, + 657, 658, 0, 0, 0, 659, 638, 639, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, - 0, 0, 0, 426, 427, 428, 429, 430, 0, 431, - 0, 432, 433, 434, 435, 436, 437, 438, 439, 56, - 440, 0, 0, 0, 0, 0, 0, 441, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 442, 443, 444, 0, 14, 0, - 0, 445, 446, 0, 0, 0, 402, 403, 0, 0, - 447, 0, 448, 1306, 449, 450, 404, 405, 406, 407, - 408, 0, 0, 0, 0, 0, 409, 0, 410, 0, - 0, 0, 411, 0, 0, 0, 0, 0, 0, 0, - 412, 0, 0, 0, 0, 0, 413, 0, 0, 414, - 0, 0, 415, 0, 0, 0, 416, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 417, 0, 0, 418, - 419, 0, 222, 223, 224, 0, 226, 227, 228, 229, - 230, 420, 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 0, 244, 245, 246, 0, 0, 249, - 250, 251, 252, 421, 422, 423, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 424, 425, - 0, 0, 0, 0, 0, 0, 0, 1322, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, - 0, 0, 0, 0, 0, 0, 0, 426, 427, 428, - 429, 430, 0, 431, 0, 432, 433, 434, 435, 436, - 437, 438, 439, 56, 440, 0, 0, 0, 0, 0, - 0, 441, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 442, 443, - 444, 0, 14, 0, 0, 445, 446, 0, 0, 0, - 402, 403, 0, 0, 447, 0, 448, 0, 449, 450, - 404, 405, 406, 407, 408, 0, 0, 0, 0, 0, - 409, 0, 410, 0, 0, 0, 411, 0, 0, 0, - 0, 0, 0, 0, 412, 0, 0, 0, 0, 0, - 413, 0, 0, 414, 0, 0, 415, 0, 0, 0, - 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 417, 0, 0, 418, 419, 0, 222, 223, 224, 0, - 226, 227, 228, 229, 230, 420, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 0, 244, 245, - 246, 0, 0, 249, 250, 251, 252, 421, 422, 423, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 424, 425, 0, 0, 0, 0, 0, 0, + 660, 0, 661, 662, 663, 664, 665, 666, 667, 668, + 669, 670, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 671, 672, 0, 0, 998, 640, 641, 642, + 643, 644, 0, 0, 645, 646, 647, 648, 0, 649, + 650, 651, 652, 653, 0, 654, 655, 0, 0, 0, + 0, 656, 657, 658, 0, 0, 0, 659, 638, 639, + 640, 641, 642, 643, 644, 0, 0, 645, 646, 647, + 648, 0, 649, 650, 651, 652, 653, 0, 654, 655, + 0, 0, 0, 0, 656, 657, 658, 0, 0, 0, + 659, 0, 660, 0, 661, 662, 663, 664, 665, 666, + 667, 668, 669, 670, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 671, 672, 0, 0, 999, 0, + 0, 0, 0, 0, 0, 660, 0, 661, 662, 663, + 664, 665, 666, 667, 668, 669, 670, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 671, 672, 0, + 0, 1000, 640, 641, 642, 643, 644, 638, 639, 645, + 646, 647, 648, 0, 649, 650, 651, 652, 653, 0, + 654, 655, 0, 0, 0, 0, 656, 657, 658, 0, + 0, 0, 659, 0, 0, 0, 0, 0, 638, 639, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, - 0, 426, 427, 428, 429, 430, 0, 431, 0, 432, - 433, 434, 435, 436, 437, 438, 439, 56, 440, 0, - 0, 0, 0, 0, 0, 441, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 442, 443, 444, 0, 14, 0, 0, 445, - 446, 0, 0, 0, 402, 403, 0, 0, 447, 0, - 448, 0, 449, 450, 404, 405, 406, 407, 408, 0, - 0, 0, 0, 0, 409, 0, 410, 0, 0, 0, - 411, 0, 0, 0, 0, 0, 0, 0, 412, 0, - 0, 0, 0, 0, 413, 0, 0, 414, 0, 0, - 415, 0, 0, 0, 416, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 417, 0, 0, 418, 419, 0, - 222, 223, 224, 0, 226, 227, 228, 229, 230, 420, - 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, - 242, 0, 244, 245, 246, 0, 0, 249, 250, 251, - 252, 421, 422, 423, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 424, 425, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 660, 0, 661, + 662, 663, 664, 665, 666, 667, 668, 669, 670, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 671, + 672, 0, 0, 1001, 0, 0, 0, 0, 0, 0, + 0, 640, 641, 642, 643, 644, 0, 0, 645, 646, + 647, 648, 0, 649, 650, 651, 652, 653, 0, 654, + 655, 0, 0, 0, 0, 656, 657, 658, 0, 0, + 0, 659, 640, 641, 642, 643, 644, 638, 639, 645, + 646, 647, 648, 0, 649, 650, 651, 652, 653, 0, + 654, 655, 0, 0, 0, 0, 656, 657, 658, 0, + 0, 0, 659, 0, 0, 0, 660, 0, 661, 662, + 663, 664, 665, 666, 667, 668, 669, 670, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 671, 672, + 0, 0, 1002, 0, 0, 0, 0, 660, 0, 661, + 662, 663, 664, 665, 666, 667, 668, 669, 670, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 671, + 672, 0, 0, 1003, 0, 0, 0, 0, 0, 638, + 639, 640, 641, 642, 643, 644, 0, 0, 645, 646, + 647, 648, 0, 649, 650, 651, 652, 653, 0, 654, + 655, 0, 0, 0, 0, 656, 657, 658, 0, 0, + 0, 659, 638, 639, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, - 0, 0, 0, 0, 0, 426, 427, 428, 429, 430, - 0, 431, 0, 432, 433, 434, 435, 436, 437, 438, - 439, 56, 440, 637, 638, 0, 0, 216, 0, 441, - 0, 0, 0, 217, 0, 0, 0, 0, 0, 218, - 0, 0, 0, 0, 0, 0, 442, 443, 444, 219, - 14, 0, 0, 445, 446, 0, 0, 220, 0, 637, - 638, 0, 1144, 0, 448, 0, 449, 450, 0, 0, - 0, 0, 221, 0, 0, 0, 0, 0, 0, 222, - 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, - 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, - 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, - 253, 254, 0, 0, 0, 0, 0, 639, 640, 641, - 642, 643, 0, 0, 644, 645, 646, 647, 0, 648, - 649, 650, 651, 652, 0, 653, 654, 0, 0, 0, - 0, 655, 656, 657, 0, 0, 55, 658, 0, 0, - 0, 637, 638, 639, 640, 641, 642, 643, 0, 255, - 644, 645, 646, 647, 0, 648, 649, 650, 651, 652, - 504, 653, 654, 0, 0, 0, 0, 655, 656, 657, - 0, 0, 659, 658, 660, 661, 662, 663, 664, 665, - 666, 667, 668, 669, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 670, 671, 0, 0, 689, 0, - 0, 0, 0, 0, 0, 256, 0, 0, 659, 0, - 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 670, 671, 0, 0, 908, 639, 640, 641, 642, 643, - 637, 638, 644, 645, 646, 647, 0, 648, 649, 650, - 651, 652, 0, 653, 654, 0, 0, 0, 0, 655, - 656, 657, 0, 0, 0, 658, 0, 0, 0, 0, - 0, 637, 638, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 660, 0, 661, 662, + 663, 664, 665, 666, 667, 668, 669, 670, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 671, 672, + 0, 0, 1079, 640, 641, 642, 643, 644, 0, 0, + 645, 646, 647, 648, 0, 649, 650, 651, 652, 653, + 0, 654, 655, 0, 0, 0, 0, 656, 657, 658, + 0, 0, 0, 659, 638, 639, 640, 641, 642, 643, + 644, 0, 0, 645, 646, 647, 648, 0, 649, 650, + 651, 652, 653, 0, 654, 655, 0, 0, 0, 0, + 656, 657, 658, 0, 0, 0, 659, 0, 660, 0, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 671, 672, 0, 0, 1082, 0, 0, 0, 0, 0, + 0, 660, 0, 661, 662, 663, 664, 665, 666, 667, + 668, 669, 670, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 671, 672, 0, 0, 1085, 640, 641, + 642, 643, 644, 638, 639, 645, 646, 647, 648, 0, + 649, 650, 651, 652, 653, 0, 654, 655, 0, 0, + 0, 0, 656, 657, 658, 0, 0, 0, 659, 0, + 0, 0, 0, 0, 638, 639, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 659, 0, 660, 661, 662, 663, 664, 665, 666, 667, - 668, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 670, 671, 0, 0, 984, 0, 0, 0, - 0, 0, 0, 0, 639, 640, 641, 642, 643, 0, - 0, 644, 645, 646, 647, 0, 648, 649, 650, 651, - 652, 0, 653, 654, 0, 0, 0, 0, 655, 656, - 657, 0, 0, 0, 658, 639, 640, 641, 642, 643, - 637, 638, 644, 645, 646, 647, 0, 648, 649, 650, - 651, 652, 0, 653, 654, 0, 0, 0, 0, 655, - 656, 657, 0, 0, 0, 658, 0, 0, 0, 659, - 0, 660, 661, 662, 663, 664, 665, 666, 667, 668, - 669, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 670, 671, 0, 0, 987, 0, 0, 0, 0, - 659, 0, 660, 661, 662, 663, 664, 665, 666, 667, - 668, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 670, 671, 0, 0, 989, 0, 0, 0, - 0, 0, 637, 638, 639, 640, 641, 642, 643, 0, - 0, 644, 645, 646, 647, 0, 648, 649, 650, 651, - 652, 0, 653, 654, 0, 0, 0, 0, 655, 656, - 657, 0, 0, 0, 658, 637, 638, 0, 0, 0, + 0, 0, 0, 660, 0, 661, 662, 663, 664, 665, + 666, 667, 668, 669, 670, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 671, 672, 0, 0, 1111, + 0, 0, 0, 0, 0, 0, 0, 640, 641, 642, + 643, 644, 0, 0, 645, 646, 647, 648, 0, 649, + 650, 651, 652, 653, 0, 654, 655, 0, 0, 0, + 0, 656, 657, 658, 0, 0, 0, 659, 640, 641, + 642, 643, 644, 638, 639, 645, 646, 647, 648, 0, + 649, 650, 651, 652, 653, 0, 654, 655, 0, 0, + 0, 0, 656, 657, 658, 0, 0, 0, 659, 0, + 0, 0, 660, 0, 661, 662, 663, 664, 665, 666, + 667, 668, 669, 670, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 671, 672, 0, 0, 1182, 0, + 0, 0, 0, 660, 0, 661, 662, 663, 664, 665, + 666, 667, 668, 669, 670, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 671, 672, 0, 0, 1190, + 0, 0, 0, 0, 0, 638, 639, 640, 641, 642, + 643, 644, 0, 0, 645, 646, 647, 648, 0, 649, + 650, 651, 652, 653, 0, 654, 655, 0, 0, 0, + 0, 656, 657, 658, 0, 0, 0, 659, 638, 639, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 659, - 0, 660, 661, 662, 663, 664, 665, 666, 667, 668, - 669, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 670, 671, 0, 0, 997, 639, 640, 641, 642, - 643, 0, 0, 644, 645, 646, 647, 0, 648, 649, - 650, 651, 652, 0, 653, 654, 0, 0, 0, 0, - 655, 656, 657, 0, 0, 0, 658, 637, 638, 639, - 640, 641, 642, 643, 0, 0, 644, 645, 646, 647, - 0, 648, 649, 650, 651, 652, 0, 653, 654, 0, - 0, 0, 0, 655, 656, 657, 0, 0, 0, 658, - 0, 659, 0, 660, 661, 662, 663, 664, 665, 666, - 667, 668, 669, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 670, 671, 0, 0, 998, 0, 0, - 0, 0, 0, 0, 659, 0, 660, 661, 662, 663, - 664, 665, 666, 667, 668, 669, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 670, 671, 0, 0, - 999, 639, 640, 641, 642, 643, 637, 638, 644, 645, - 646, 647, 0, 648, 649, 650, 651, 652, 0, 653, - 654, 0, 0, 0, 0, 655, 656, 657, 0, 0, - 0, 658, 0, 0, 0, 0, 0, 637, 638, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 660, 0, 661, 662, 663, 664, 665, 666, + 667, 668, 669, 670, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 671, 672, 0, 0, 1231, 640, + 641, 642, 643, 644, 0, 0, 645, 646, 647, 648, + 0, 649, 650, 651, 652, 653, 0, 654, 655, 0, + 0, 0, 0, 656, 657, 658, 0, 0, 0, 659, + 638, 639, 640, 641, 642, 643, 644, 0, 0, 645, + 646, 647, 648, 0, 649, 650, 651, 652, 653, 0, + 654, 655, 0, 0, 0, 0, 656, 657, 658, 0, + 0, 0, 659, 0, 660, 0, 661, 662, 663, 664, + 665, 666, 667, 668, 669, 670, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 671, 672, 0, 0, + 1232, 0, 0, 0, 0, 0, 0, 660, 0, 661, + 662, 663, 664, 665, 666, 667, 668, 669, 670, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 671, + 672, 0, 0, 1235, 640, 641, 642, 643, 644, 638, + 639, 645, 646, 647, 648, 0, 649, 650, 651, 652, + 653, 0, 654, 655, 0, 0, 0, 0, 656, 657, + 658, 0, 0, 0, 659, 0, 0, 0, 0, 0, + 638, 639, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 659, 0, 660, 661, - 662, 663, 664, 665, 666, 667, 668, 669, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 670, 671, - 0, 0, 1000, 0, 0, 0, 0, 0, 0, 0, - 639, 640, 641, 642, 643, 0, 0, 644, 645, 646, - 647, 0, 648, 649, 650, 651, 652, 0, 653, 654, - 0, 0, 0, 0, 655, 656, 657, 0, 0, 0, - 658, 639, 640, 641, 642, 643, 637, 638, 644, 645, - 646, 647, 0, 648, 649, 650, 651, 652, 0, 653, - 654, 0, 0, 0, 0, 655, 656, 657, 0, 0, - 0, 658, 0, 0, 0, 659, 0, 660, 661, 662, - 663, 664, 665, 666, 667, 668, 669, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 670, 671, 0, - 0, 1001, 0, 0, 0, 0, 659, 0, 660, 661, - 662, 663, 664, 665, 666, 667, 668, 669, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 670, 671, - 0, 0, 1002, 0, 0, 0, 0, 0, 637, 638, - 639, 640, 641, 642, 643, 0, 0, 644, 645, 646, - 647, 0, 648, 649, 650, 651, 652, 0, 653, 654, - 0, 0, 0, 0, 655, 656, 657, 0, 0, 0, - 658, 637, 638, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 660, + 0, 661, 662, 663, 664, 665, 666, 667, 668, 669, + 670, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 671, 672, 0, 0, 1253, 0, 0, 0, 0, + 0, 0, 0, 640, 641, 642, 643, 644, 0, 0, + 645, 646, 647, 648, 0, 649, 650, 651, 652, 653, + 0, 654, 655, 0, 0, 0, 0, 656, 657, 658, + 0, 0, 0, 659, 640, 641, 642, 643, 644, 638, + 639, 645, 646, 647, 648, 0, 649, 650, 651, 652, + 653, 0, 654, 655, 0, 0, 0, 0, 656, 657, + 658, 0, 0, 0, 659, 0, 0, 0, 660, 0, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 671, 672, 0, 0, 1255, 0, 0, 0, 0, 660, + 0, 661, 662, 663, 664, 665, 666, 667, 668, 669, + 670, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 671, 672, 0, 0, 1257, 0, 0, 0, 0, + 0, 638, 639, 640, 641, 642, 643, 644, 0, 0, + 645, 646, 647, 648, 0, 649, 650, 651, 652, 653, + 0, 654, 655, 0, 0, 0, 0, 656, 657, 658, + 0, 0, 0, 659, 638, 639, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 659, 0, 660, 661, 662, - 663, 664, 665, 666, 667, 668, 669, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 670, 671, 0, - 0, 1078, 639, 640, 641, 642, 643, 0, 0, 644, - 645, 646, 647, 0, 648, 649, 650, 651, 652, 0, - 653, 654, 0, 0, 0, 0, 655, 656, 657, 0, - 0, 0, 658, 637, 638, 639, 640, 641, 642, 643, - 0, 0, 644, 645, 646, 647, 0, 648, 649, 650, - 651, 652, 0, 653, 654, 0, 0, 0, 0, 655, - 656, 657, 0, 0, 0, 658, 0, 659, 0, 660, - 661, 662, 663, 664, 665, 666, 667, 668, 669, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 670, - 671, 0, 0, 1081, 0, 0, 0, 0, 0, 0, - 659, 0, 660, 661, 662, 663, 664, 665, 666, 667, - 668, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 670, 671, 0, 0, 1084, 639, 640, 641, - 642, 643, 637, 638, 644, 645, 646, 647, 0, 648, - 649, 650, 651, 652, 0, 653, 654, 0, 0, 0, - 0, 655, 656, 657, 0, 0, 0, 658, 0, 0, - 0, 0, 0, 637, 638, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 660, 0, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 659, 0, 660, 661, 662, 663, 664, 665, - 666, 667, 668, 669, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 670, 671, 0, 0, 1110, 0, - 0, 0, 0, 0, 0, 0, 639, 640, 641, 642, - 643, 0, 0, 644, 645, 646, 647, 0, 648, 649, - 650, 651, 652, 0, 653, 654, 0, 0, 0, 0, - 655, 656, 657, 0, 0, 0, 658, 639, 640, 641, - 642, 643, 637, 638, 644, 645, 646, 647, 0, 648, - 649, 650, 651, 652, 0, 653, 654, 0, 0, 0, - 0, 655, 656, 657, 0, 0, 0, 658, 0, 0, - 0, 659, 0, 660, 661, 662, 663, 664, 665, 666, - 667, 668, 669, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 670, 671, 0, 0, 1181, 0, 0, - 0, 0, 659, 0, 660, 661, 662, 663, 664, 665, - 666, 667, 668, 669, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 670, 671, 0, 0, 1189, 0, - 0, 0, 0, 0, 637, 638, 639, 640, 641, 642, - 643, 0, 0, 644, 645, 646, 647, 0, 648, 649, - 650, 651, 652, 0, 653, 654, 0, 0, 0, 0, - 655, 656, 657, 0, 0, 0, 658, 637, 638, 0, + 671, 672, 0, 0, 1261, 640, 641, 642, 643, 644, + 0, 0, 645, 646, 647, 648, 0, 649, 650, 651, + 652, 653, 0, 654, 655, 0, 0, 0, 0, 656, + 657, 658, 0, 0, 0, 659, 638, 639, 640, 641, + 642, 643, 644, 0, 0, 645, 646, 647, 648, 0, + 649, 650, 651, 652, 653, 0, 654, 655, 0, 0, + 0, 0, 656, 657, 658, 0, 0, 0, 659, 0, + 660, 0, 661, 662, 663, 664, 665, 666, 667, 668, + 669, 670, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 671, 672, 0, 0, 1276, 0, 0, 0, + 0, 0, 0, 660, 0, 661, 662, 663, 664, 665, + 666, 667, 668, 669, 670, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 671, 672, 0, 0, 1329, + 640, 641, 642, 643, 644, 638, 639, 645, 646, 647, + 648, 0, 649, 650, 651, 652, 653, 0, 654, 655, + 0, 0, 0, 0, 656, 657, 658, 0, 0, 0, + 659, 0, 0, 0, 0, 0, 638, 639, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 660, 0, 661, 662, 663, + 664, 665, 666, 667, 668, 669, 670, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 671, 672, 0, + 0, 1330, 0, 0, 0, 0, 0, 0, 0, 640, + 641, 642, 643, 644, 0, 0, 645, 646, 647, 648, + 0, 649, 650, 651, 652, 653, 0, 654, 655, 0, + 0, 0, 0, 656, 657, 658, 0, 0, 0, 659, + 640, 641, 642, 643, 644, 638, 639, 645, 646, 647, + 648, 0, 649, 650, 651, 652, 653, 0, 654, 655, + 0, 0, 0, 0, 656, 657, 658, 0, 0, 0, + 659, 0, 0, 0, 660, 0, 661, 662, 663, 664, + 665, 666, 667, 668, 669, 670, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 671, 672, 0, 0, + 1331, 0, 0, 0, 0, 660, 0, 661, 662, 663, + 664, 665, 666, 667, 668, 669, 670, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 671, 672, 0, + 0, 1353, 0, 0, 0, 0, 0, 638, 639, 640, + 641, 642, 643, 644, 0, 0, 645, 646, 647, 648, + 0, 649, 650, 651, 652, 653, 0, 654, 655, 0, + 0, 0, 0, 656, 657, 658, 0, 0, 0, 659, + 638, 639, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 659, 0, 660, 661, 662, 663, 664, 665, 666, - 667, 668, 669, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 670, 671, 0, 0, 1230, 639, 640, - 641, 642, 643, 0, 0, 644, 645, 646, 647, 0, - 648, 649, 650, 651, 652, 0, 653, 654, 0, 0, - 0, 0, 655, 656, 657, 0, 0, 0, 658, 637, - 638, 639, 640, 641, 642, 643, 0, 0, 644, 645, - 646, 647, 0, 648, 649, 650, 651, 652, 0, 653, - 654, 0, 0, 0, 0, 655, 656, 657, 0, 0, - 0, 658, 0, 659, 0, 660, 661, 662, 663, 664, - 665, 666, 667, 668, 669, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 670, 671, 0, 0, 1231, - 0, 0, 0, 0, 0, 0, 659, 0, 660, 661, - 662, 663, 664, 665, 666, 667, 668, 669, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 670, 671, - 0, 0, 1234, 639, 640, 641, 642, 643, 637, 638, - 644, 645, 646, 647, 0, 648, 649, 650, 651, 652, - 0, 653, 654, 0, 0, 0, 0, 655, 656, 657, - 0, 0, 0, 658, 0, 0, 0, 0, 0, 637, - 638, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 659, 0, - 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, + 0, 0, 0, 0, 660, 0, 661, 662, 663, 664, + 665, 666, 667, 668, 669, 670, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 671, 672, 0, 0, + 1364, 640, 641, 642, 643, 644, 0, 0, 645, 646, + 647, 648, 0, 649, 650, 651, 652, 653, 0, 654, + 655, 0, 0, 0, 0, 656, 657, 658, 0, 0, + 0, 659, 638, 639, 640, 641, 642, 643, 644, 0, + 0, 645, 646, 647, 648, 0, 649, 650, 651, 652, + 653, 0, 654, 655, 0, 0, 0, 0, 656, 657, + 658, 0, 0, 0, 659, 0, 660, 0, 661, 662, + 663, 664, 665, 666, 667, 668, 669, 670, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 671, 672, + 0, 0, 1374, 0, 0, 0, 0, 0, 0, 660, + 0, 661, 662, 663, 664, 665, 666, 667, 668, 669, + 670, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 671, 672, 0, 0, 1409, 640, 641, 642, 643, + 644, 638, 639, 645, 646, 647, 648, 0, 649, 650, + 651, 652, 653, 0, 654, 655, 0, 0, 0, 0, + 656, 657, 658, 0, 0, 0, 659, 0, 0, 0, + 0, 0, 638, 639, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 670, 671, 0, 0, 1252, 0, 0, 0, 0, 0, - 0, 0, 639, 640, 641, 642, 643, 0, 0, 644, - 645, 646, 647, 0, 648, 649, 650, 651, 652, 0, - 653, 654, 0, 0, 0, 0, 655, 656, 657, 0, - 0, 0, 658, 639, 640, 641, 642, 643, 637, 638, - 644, 645, 646, 647, 0, 648, 649, 650, 651, 652, - 0, 653, 654, 0, 0, 0, 0, 655, 656, 657, - 0, 0, 0, 658, 0, 0, 0, 659, 0, 660, - 661, 662, 663, 664, 665, 666, 667, 668, 669, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 670, - 671, 0, 0, 1254, 0, 0, 0, 0, 659, 0, - 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 670, 671, 0, 0, 1256, 0, 0, 0, 0, 0, - 637, 638, 639, 640, 641, 642, 643, 0, 0, 644, - 645, 646, 647, 0, 648, 649, 650, 651, 652, 0, - 653, 654, 0, 0, 0, 0, 655, 656, 657, 0, - 0, 0, 658, 637, 638, 0, 0, 0, 0, 0, + 0, 660, 0, 661, 662, 663, 664, 665, 666, 667, + 668, 669, 670, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 671, 672, 0, 0, 1419, 0, 0, + 0, 0, 0, 0, 0, 640, 641, 642, 643, 644, + 0, 0, 645, 646, 647, 648, 0, 649, 650, 651, + 652, 653, 0, 654, 655, 0, 0, 0, 0, 656, + 657, 658, 638, 639, 0, 659, 640, 641, 642, 643, + 644, 0, 0, 645, 646, 647, 648, 0, 649, 650, + 651, 652, 653, 0, 654, 655, 0, 0, 0, 0, + 656, 657, 658, 638, 639, 0, 659, 0, 0, 0, + 660, 0, 661, 662, 663, 664, 665, 666, 667, 668, + 669, 670, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 671, 672, 695, 0, 0, 0, 0, 0, + 0, 660, 0, 661, 662, 663, 664, 665, 666, 667, + 668, 669, 670, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 671, 672, 905, 640, 641, 642, 643, + 644, 0, 0, 645, 646, 647, 648, 0, 649, 650, + 651, 652, 653, 0, 654, 655, 0, 0, 0, 0, + 656, 657, 658, 638, 639, 0, 659, 640, 641, 642, + 643, 644, 0, 0, 645, 646, 647, 648, 0, 649, + 650, 651, 652, 653, 0, 654, 655, 0, 0, 0, + 0, 656, 657, 658, 638, 639, 0, 659, 0, 0, + 0, 660, 0, 661, 662, 663, 664, 665, 666, 667, + 668, 669, 670, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 671, 672, 1039, 0, 0, 0, 0, + 0, 0, 660, 0, 661, 662, 663, 664, 665, 666, + 667, 668, 669, 670, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 671, 672, 1055, 640, 641, 642, + 643, 644, 0, 0, 645, 646, 647, 648, 0, 649, + 650, 651, 652, 653, 0, 654, 655, 0, 0, 0, + 0, 656, 657, 658, 0, 0, 0, 659, 640, 641, + 642, 643, 644, 638, 639, 645, 646, 647, 648, 0, + 649, 650, 651, 652, 653, 0, 654, 655, 0, 0, + 0, 0, 656, 657, 658, 0, 0, 0, 659, 0, + 0, 0, 660, 0, 661, 662, 663, 664, 665, 666, + 667, 668, 669, 670, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 671, 672, 1168, 0, 0, 0, + 0, 0, 0, 660, 0, 661, 662, 663, 664, 665, + 666, 667, 668, 669, 670, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 671, 672, 1173, 0, 742, + 743, 744, 745, 746, 747, 748, 749, 640, 641, 642, + 643, 644, 750, 751, 645, 646, 647, 648, 752, 649, + 650, 651, 652, 653, 753, 654, 655, 754, 755, 269, + 270, 656, 657, 658, 756, 757, 758, 659, 0, 0, + 0, 0, 0, 0, 0, 0, 271, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 638, 639, 0, 0, -321, 0, 0, 0, 0, 0, + 0, 759, 660, 0, 661, 662, 663, 664, 665, 666, + 667, 668, 669, 670, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 671, 672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 659, 0, 660, - 661, 662, 663, 664, 665, 666, 667, 668, 669, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 670, - 671, 0, 0, 1260, 639, 640, 641, 642, 643, 0, - 0, 644, 645, 646, 647, 0, 648, 649, 650, 651, - 652, 0, 653, 654, 0, 0, 0, 0, 655, 656, - 657, 0, 0, 0, 658, 637, 638, 639, 640, 641, - 642, 643, 0, 0, 644, 645, 646, 647, 0, 648, - 649, 650, 651, 652, 0, 653, 654, 0, 0, 0, - 0, 655, 656, 657, 0, 0, 0, 658, 0, 659, - 0, 660, 661, 662, 663, 664, 665, 666, 667, 668, - 669, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 670, 671, 0, 0, 1275, 0, 0, 0, 0, - 0, 0, 659, 0, 660, 661, 662, 663, 664, 665, - 666, 667, 668, 669, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 670, 671, 0, 0, 1328, 639, - 640, 641, 642, 643, 637, 638, 644, 645, 646, 647, - 0, 648, 649, 650, 651, 652, 0, 653, 654, 0, - 0, 0, 0, 655, 656, 657, 0, 0, 0, 658, - 0, 0, 0, 0, 0, 637, 638, 0, 0, 0, + 0, 0, 0, 0, 0, 272, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, + 287, 288, 289, 0, 0, 290, 291, 292, 0, 0, + 293, 294, 295, 296, 297, 0, 0, 298, 299, 300, + 301, 302, 303, 304, 640, 641, 642, 643, 644, 638, + 639, 645, 646, 647, 648, 0, 649, 650, 651, 652, + 653, 0, 654, 655, 0, 0, 810, 0, 656, 657, + 658, 0, 0, 0, 659, 0, 0, 0, 305, 0, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 0, 0, 316, 317, 0, 0, 0, 0, 0, 0, + 318, 319, 0, 0, 0, 0, 0, 0, 0, 660, + 0, 661, 662, 663, 664, 665, 666, 667, 668, 669, + 670, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 671, 672, 0, 0, 0, 0, 0, 638, 639, + 0, 0, 0, 640, 641, 642, 643, 644, 0, 0, + 645, 646, 647, 648, 0, 649, 650, 651, 652, 653, + 0, 654, 655, 0, 0, 0, 0, 656, 657, 658, + 638, 639, 0, 659, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 659, 0, 660, 661, 662, 663, - 664, 665, 666, 667, 668, 669, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 670, 671, 0, 0, - 1329, 0, 0, 0, 0, 0, 0, 0, 639, 640, - 641, 642, 643, 0, 0, 644, 645, 646, 647, 0, - 648, 649, 650, 651, 652, 0, 653, 654, 0, 0, - 0, 0, 655, 656, 657, 0, 0, 0, 658, 639, - 640, 641, 642, 643, 637, 638, 644, 645, 646, 647, - 0, 648, 649, 650, 651, 652, 0, 653, 654, 0, - 0, 0, 0, 655, 656, 657, 0, 0, 0, 658, - 0, 0, 0, 659, 0, 660, 661, 662, 663, 664, - 665, 666, 667, 668, 669, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 670, 671, 0, 0, 1330, - 0, 0, 0, 0, 659, 0, 660, 661, 662, 663, - 664, 665, 666, 667, 668, 669, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 670, 671, 0, 0, - 1352, 0, 0, 0, 0, 0, 637, 638, 639, 640, - 641, 642, 643, 0, 0, 644, 645, 646, 647, 0, - 648, 649, 650, 651, 652, 0, 653, 654, 0, 0, - 0, 0, 655, 656, 657, 0, 0, 0, 658, 637, - 638, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 962, 0, 0, 0, 0, 0, 0, 0, 660, 0, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 671, 672, 640, 641, 642, 643, 644, 0, 0, 645, + 646, 647, 648, 0, 649, 650, 651, 652, 653, 0, + 654, 655, 638, 639, 0, 0, 656, 657, 658, 0, + 0, 0, 659, 0, 640, 641, 642, 643, 644, 0, + 0, 645, 646, 647, 648, 0, 649, 650, 651, 652, + 653, 0, 654, 655, 638, 639, 0, 0, 656, 657, + 658, 0, 0, 0, 659, 0, 0, 660, 1044, 661, + 662, 663, 664, 665, 666, 667, 668, 669, 670, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 671, + 672, 1101, 0, 0, 0, 0, 0, 0, 0, 660, + 0, 661, 662, 663, 664, 665, 666, 667, 668, 669, + 670, 0, 0, 0, 0, 0, 640, 641, 642, 643, + 644, 671, 672, 645, 646, 647, 648, 0, 649, 650, + 651, 652, 653, 0, 654, 655, 638, 639, 0, 0, + 656, 657, 658, 0, 0, 0, 659, 0, 640, 641, + 642, 643, 644, 0, 0, 645, 646, 647, 648, 0, + 649, 650, 651, 652, 653, 0, 654, 655, 0, 1132, + 638, 639, 656, 657, 658, 0, 0, 0, 659, 0, + 0, 660, 0, 661, 662, 663, 664, 665, 666, 667, + 668, 669, 670, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 671, 672, 1347, 0, 0, 0, 0, + 0, 0, 0, 660, 0, 661, 662, 663, 664, 665, + 666, 667, 668, 669, 670, 0, 0, 0, 0, 0, + 640, 641, 642, 643, 644, 671, 672, 645, 646, 647, + 648, 0, 649, 650, 651, 652, 653, 0, 654, 655, + 0, 0, 638, 639, 656, 657, 658, 0, 0, 0, + 659, 0, 0, 0, 640, 641, 642, 643, 644, 0, + 0, 645, 646, 647, 648, 0, 649, 650, 651, 652, + 653, 0, 654, 655, 0, 0, 0, 1365, 656, 657, + 658, 0, 0, 0, 659, 660, 0, 661, 662, 663, + 664, 665, 666, 667, 668, 669, 670, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 671, 672, 0, + 0, 1383, 0, 0, 0, 0, 0, 0, 0, 660, + 0, 661, 662, 663, 664, 665, 666, 667, 668, 669, + 670, 638, 639, 0, 0, 0, 640, 641, 642, 643, + 644, 671, 672, 645, 646, 647, 648, 0, 649, 650, + 651, 652, 653, 0, 654, 655, 0, 0, 0, 0, + 656, 657, 658, 0, 0, 0, 659, 638, 639, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 659, 0, 660, 661, 662, 663, 664, - 665, 666, 667, 668, 669, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 670, 671, 0, 0, 1363, - 639, 640, 641, 642, 643, 0, 0, 644, 645, 646, - 647, 0, 648, 649, 650, 651, 652, 0, 653, 654, - 0, 0, 0, 0, 655, 656, 657, 0, 0, 0, - 658, 637, 638, 639, 640, 641, 642, 643, 0, 0, - 644, 645, 646, 647, 0, 648, 649, 650, 651, 652, - 0, 653, 654, 0, 0, 0, 0, 655, 656, 657, - 0, 0, 0, 658, 0, 659, 0, 660, 661, 662, - 663, 664, 665, 666, 667, 668, 669, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 670, 671, 0, - 0, 1373, 0, 0, 0, 0, 0, 0, 659, 0, - 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 670, 671, 0, 0, 1408, 639, 640, 641, 642, 643, - 637, 638, 644, 645, 646, 647, 0, 648, 649, 650, - 651, 652, 0, 653, 654, 0, 0, 0, 0, 655, - 656, 657, 0, 0, 0, 658, 0, 0, 0, 0, - 0, 637, 638, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1411, 0, 0, 0, 0, 0, 0, + 0, 660, 0, 661, 662, 663, 664, 665, 666, 667, + 668, 669, 670, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 671, 672, 640, 641, 642, 643, 644, + 0, 0, 645, 646, 647, 648, 0, 649, 650, 651, + 652, 653, 0, 654, 655, 0, 0, 0, 0, 656, + 657, 658, 0, 0, 0, 659, 638, 639, 0, 0, + 0, 640, 641, 642, 643, 644, 0, 0, 645, 646, + 647, 648, 0, 649, 650, 651, 652, 653, 0, 654, + 655, 0, 1430, 0, 0, 656, 657, 658, 638, 639, + 660, 659, 661, 662, 663, 664, 665, 666, 667, 668, + 669, 670, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 671, 672, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 660, 0, 661, 662, + 663, 664, 665, 666, 667, 668, 669, 670, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 671, 672, + 640, 641, 642, 643, 644, 0, 0, 645, 646, 647, + 648, 0, 649, 650, 651, 652, 653, 0, 654, 655, + 638, 639, 0, 0, 656, 657, 658, 0, 0, 0, + -690, 0, 640, 641, 642, 643, 644, 0, 0, 645, + 646, 647, 648, 0, 649, 650, 651, 652, 653, 0, + 654, 655, 638, 639, 0, 0, 656, 657, 658, 0, + 0, 0, 0, 0, 0, 660, 0, 661, 662, 663, + 664, 665, 666, 667, 668, 669, 670, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 671, 672, 0, + 0, 0, 0, 0, 0, 0, 0, 660, 0, 661, + 662, 663, 664, 665, 666, 667, 668, 669, 670, 0, + 0, 0, 0, 0, 640, 641, 642, 643, 644, 671, + 672, 645, 646, 647, 648, 0, 649, 650, 651, 652, + 653, 0, 654, 655, 638, 639, 0, 0, 656, 0, + 658, 0, 0, 0, 0, 0, 640, 641, 642, 643, + 644, 0, 0, 645, 646, 647, 648, 0, 649, 650, + 651, 652, 653, 0, 654, 655, 638, 639, 0, 0, + 656, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 661, 662, 663, 664, 665, 666, 667, 668, 669, + 670, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 671, 672, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 661, 662, 663, 664, 665, 666, 667, + 668, 669, 670, 0, 0, 0, 0, 0, 640, 641, + 642, 643, 644, 671, 672, 645, 646, 647, 648, 0, + 649, 650, 651, 652, 653, 0, 654, 655, 638, 639, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 640, 641, 642, 643, 644, 0, 0, 645, 646, 647, + 648, 0, 649, 650, 651, 652, 653, 0, 654, 655, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 659, 0, 660, 661, 662, 663, 664, 665, 666, 667, - 668, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 670, 671, 0, 0, 1418, 0, 0, 0, - 0, 0, 0, 0, 639, 640, 641, 642, 643, 0, - 0, 644, 645, 646, 647, 0, 648, 649, 650, 651, - 652, 0, 653, 654, 0, 0, 0, 0, 655, 656, - 657, 637, 638, 0, 658, 639, 640, 641, 642, 643, - 0, 0, 644, 645, 646, 647, 0, 648, 649, 650, - 651, 652, 0, 653, 654, 0, 0, 0, 0, 655, - 656, 657, 637, 638, 0, 658, 0, 0, 0, 659, - 0, 660, 661, 662, 663, 664, 665, 666, 667, 668, - 669, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 670, 671, 694, 0, 0, 0, 0, 0, 0, - 659, 0, 660, 661, 662, 663, 664, 665, 666, 667, - 668, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 670, 671, 904, 639, 640, 641, 642, 643, - 0, 0, 644, 645, 646, 647, 0, 648, 649, 650, - 651, 652, 0, 653, 654, 0, 0, 0, 0, 655, - 656, 657, 637, 638, 0, 658, 639, 640, 641, 642, - 643, 0, 0, 644, 645, 646, 647, 0, 648, 649, - 650, 651, 652, 0, 653, 654, 0, 0, 0, 0, - 655, 656, 657, 637, 638, 0, 658, 0, 0, 0, - 659, 0, 660, 661, 662, 663, 664, 665, 666, 667, - 668, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 670, 671, 1038, 0, 0, 0, 0, 0, - 0, 659, 0, 660, 661, 662, 663, 664, 665, 666, - 667, 668, 669, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 670, 671, 1054, 639, 640, 641, 642, - 643, 0, 0, 644, 645, 646, 647, 0, 648, 649, - 650, 651, 652, 0, 653, 654, 0, 0, 0, 0, - 655, 656, 657, 0, 0, 0, 658, 639, 640, 641, - 642, 643, 637, 638, 644, 645, 646, 647, 0, 648, - 649, 650, 651, 652, 0, 653, 654, 0, 0, 0, - 0, 655, 656, 657, 0, 0, 0, 658, 0, 0, - 0, 659, 0, 660, 661, 662, 663, 664, 665, 666, - 667, 668, 669, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 670, 671, 1167, 0, 0, 0, 0, - 0, 0, 659, 0, 660, 661, 662, 663, 664, 665, - 666, 667, 668, 669, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 670, 671, 1172, 0, 741, 742, - 743, 744, 745, 746, 747, 748, 639, 640, 641, 642, - 643, 749, 750, 644, 645, 646, 647, 751, 648, 649, - 650, 651, 652, 752, 653, 654, 753, 754, 268, 269, - 655, 656, 657, 755, 756, 757, 658, 0, 0, 0, - 0, 0, 0, 0, 0, 270, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 637, - 638, 0, 0, -321, 0, 0, 0, 0, 0, 0, - 758, 659, 0, 660, 661, 662, 663, 664, 665, 666, - 667, 668, 669, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 670, 671, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 662, 663, 664, 665, + 666, 667, 668, 669, 670, 0, 0, 0, 0, 0, + 836, 0, 0, 0, 0, 671, 672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 0, 0, 289, 290, 291, 0, 0, 292, - 293, 294, 295, 296, 0, 0, 297, 298, 299, 300, - 301, 302, 303, 639, 640, 641, 642, 643, 637, 638, - 644, 645, 646, 647, 0, 648, 649, 650, 651, 652, - 0, 653, 654, 0, 0, 809, 0, 655, 656, 657, - 0, 0, 0, 658, 0, 0, 0, 304, 0, 305, - 306, 307, 308, 309, 310, 311, 312, 313, 314, 0, - 0, 315, 316, 0, 0, 0, 0, 0, 0, 317, - 318, 0, 0, 0, 0, 0, 0, 0, 659, 0, - 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, + 664, 665, 666, 667, 668, 669, 670, 0, 0, 0, + 0, 0, 640, 641, 642, 643, 644, 671, 672, 645, + 0, 0, 648, 0, 649, 650, 651, 652, 653, 0, + 654, 655, 223, 224, 225, 0, 227, 228, 229, 230, + 231, 421, 233, 234, 235, 236, 237, 238, 239, 240, + 241, 242, 243, 0, 245, 246, 247, 0, 0, 250, + 251, 252, 253, 0, 0, 0, 0, 0, 840, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 670, 671, 0, 0, 0, 0, 0, 637, 638, 0, - 0, 0, 639, 640, 641, 642, 643, 0, 0, 644, - 645, 646, 647, 0, 648, 649, 650, 651, 652, 0, - 653, 654, 0, 0, 0, 0, 655, 656, 657, 637, - 638, 0, 658, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 664, 665, 666, 667, 668, 669, 670, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 671, + 672, 1040, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 837, 0, 0, 0, 0, 0, + 223, 224, 225, 838, 227, 228, 229, 230, 231, 421, + 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, + 243, 0, 245, 246, 247, 0, 0, 250, 251, 252, + 253, 0, 0, 223, 224, 225, 0, 227, 228, 229, + 230, 231, 421, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 0, 245, 246, 247, 0, 0, + 250, 251, 252, 253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 961, - 0, 0, 0, 0, 0, 0, 0, 659, 0, 660, - 661, 662, 663, 664, 665, 666, 667, 668, 669, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 670, - 671, 639, 640, 641, 642, 643, 0, 0, 644, 645, - 646, 647, 0, 648, 649, 650, 651, 652, 0, 653, - 654, 637, 638, 0, 0, 655, 656, 657, 0, 0, - 0, 658, 0, 639, 640, 641, 642, 643, 0, 0, - 644, 645, 646, 647, 0, 648, 649, 650, 651, 652, - 0, 653, 654, 637, 638, 0, 0, 655, 656, 657, - 0, 0, 0, 658, 0, 0, 659, 1043, 660, 661, - 662, 663, 664, 665, 666, 667, 668, 669, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 670, 671, - 1100, 0, 0, 0, 0, 0, 0, 0, 659, 0, - 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, - 0, 0, 0, 0, 0, 639, 640, 641, 642, 643, - 670, 671, 644, 645, 646, 647, 0, 648, 649, 650, - 651, 652, 0, 653, 654, 637, 638, 0, 0, 655, - 656, 657, 0, 0, 0, 658, 0, 639, 640, 641, - 642, 643, 0, 0, 644, 645, 646, 647, 0, 648, - 649, 650, 651, 652, 0, 653, 654, 0, 1131, 637, - 638, 655, 656, 657, 0, 0, 0, 658, 0, 0, - 659, 0, 660, 661, 662, 663, 664, 665, 666, 667, - 668, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 670, 671, 1346, 0, 0, 0, 0, 0, - 0, 0, 659, 0, 660, 661, 662, 663, 664, 665, - 666, 667, 668, 669, 0, 0, 0, 0, 0, 639, - 640, 641, 642, 643, 670, 671, 644, 645, 646, 647, - 0, 648, 649, 650, 651, 652, 0, 653, 654, 0, - 0, 637, 638, 655, 656, 657, 0, 0, 0, 658, - 0, 0, 0, 639, 640, 641, 642, 643, 0, 0, - 644, 645, 646, 647, 0, 648, 649, 650, 651, 652, - 0, 653, 654, 0, 0, 0, 1364, 655, 656, 657, - 0, 0, 0, 658, 659, 0, 660, 661, 662, 663, - 664, 665, 666, 667, 668, 669, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 670, 671, 0, 0, - 1382, 0, 0, 0, 0, 0, 0, 0, 659, 0, - 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, - 637, 638, 0, 0, 0, 639, 640, 641, 642, 643, - 670, 671, 644, 645, 646, 647, 0, 648, 649, 650, - 651, 652, 0, 653, 654, 0, 0, 0, 0, 655, - 656, 657, 0, 0, 0, 658, 637, 638, 0, 0, + 0, 0, 841, 0, 0, 0, 0, 0, 0, 0, + 0, 842, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1041, 0, 0, 0, 0, + 0, 223, 224, 225, 1042, 227, 228, 229, 230, 231, + 421, 233, 234, 235, 236, 237, 238, 239, 240, 241, + 242, 243, 0, 245, 246, 247, 0, 0, 250, 251, + 252, 253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1410, 0, 0, 0, 0, 0, 0, 0, - 659, 0, 660, 661, 662, 663, 664, 665, 666, 667, - 668, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 670, 671, 639, 640, 641, 642, 643, 0, - 0, 644, 645, 646, 647, 0, 648, 649, 650, 651, - 652, 0, 653, 654, 0, 0, 0, 0, 655, 656, - 657, 0, 0, 0, 658, 637, 638, 0, 0, 0, - 639, 640, 641, 642, 643, 0, 0, 644, 645, 646, - 647, 0, 648, 649, 650, 651, 652, 0, 653, 654, - 0, 1429, 0, 0, 655, 656, 657, 637, 638, 659, - 658, 660, 661, 662, 663, 664, 665, 666, 667, 668, - 669, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 670, 671, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 659, 0, 660, 661, 662, - 663, 664, 665, 666, 667, 668, 669, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 670, 671, 639, - 640, 641, 642, 643, 0, 0, 644, 645, 646, 647, - 0, 648, 649, 650, 651, 652, 0, 653, 654, 637, - 638, 0, 0, 655, 656, 657, 0, 0, 0, -690, - 0, 639, 640, 641, 642, 643, 0, 0, 644, 645, - 646, 647, 0, 648, 649, 650, 651, 652, 0, 653, - 654, 637, 638, 0, 0, 655, 656, 657, 0, 0, - 0, 0, 0, 0, 659, 0, 660, 661, 662, 663, - 664, 665, 666, 667, 668, 669, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 670, 671, 0, 0, - 0, 0, 0, 0, 0, 0, 659, 0, 660, 661, - 662, 663, 664, 665, 666, 667, 668, 669, 0, 0, - 0, 0, 0, 639, 640, 641, 642, 643, 670, 671, - 644, 645, 646, 647, 0, 648, 649, 650, 651, 652, - 0, 653, 654, 637, 638, 0, 0, 655, 0, 657, - 0, 0, 0, 0, 0, 639, 640, 641, 642, 643, - 0, 0, 644, 645, 646, 647, 0, 648, 649, 650, - 651, 652, 0, 653, 654, 637, 638, 0, 0, 655, + 0, 0, 0, 0, 0, 0, 0, 0, 876, 877, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 670, 671, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 660, 661, 662, 663, 664, 665, 666, 667, - 668, 669, 0, 0, 0, 0, 0, 639, 640, 641, - 642, 643, 670, 671, 644, 645, 646, 647, 0, 648, - 649, 650, 651, 652, 0, 653, 654, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 639, - 640, 641, 642, 643, 0, 0, 644, 645, 646, 647, - 0, 648, 649, 650, 651, 652, 0, 653, 654, 0, + 0, 0, 0, 878, 0, 0, 0, 0, 0, 0, + 0, 0, 879, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 661, 662, 663, 664, 665, - 666, 667, 668, 669, 835, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 670, 671, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 663, - 664, 665, 666, 667, 668, 669, 839, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 670, 671, 0, 0, - 0, 0, 0, 0, 0, 0, 222, 223, 224, 0, - 226, 227, 228, 229, 230, 420, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 0, 244, 245, - 246, 0, 0, 249, 250, 251, 252, 0, 222, 223, - 224, 0, 226, 227, 228, 229, 230, 420, 232, 233, - 234, 235, 236, 237, 238, 239, 240, 241, 242, 0, - 244, 245, 246, 0, 0, 249, 250, 251, 252, 0, - 0, 0, 0, 0, 1039, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 836, 0, - 0, 0, 0, 0, 222, 223, 224, 837, 226, 227, - 228, 229, 230, 420, 232, 233, 234, 235, 236, 237, - 238, 239, 240, 241, 242, 0, 244, 245, 246, 0, - 840, 249, 250, 251, 252, 0, 222, 223, 224, 841, - 226, 227, 228, 229, 230, 420, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 0, 244, 245, - 246, 875, 876, 249, 250, 251, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 877, 0, 0, 0, - 0, 0, 0, 0, 0, 878, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1040, 0, - 0, 0, 0, 0, 0, 0, 0, 1041, 0, 0, - 0, 0, 0, 0, 0, 879, 880 + 0, 0, 880, 881 }; static const yytype_int16 yycheck[] = { - 14, 15, 166, 709, 369, 633, 487, 631, 152, 481, - 570, 483, 78, 485, 810, 486, 934, 531, 680, 5, - 682, 0, 684, 616, 166, 539, 8, 22, 7, 21, - 22, 396, 625, 33, 373, 775, 20, 459, 15, 16, - 834, 150, 20, 566, 1179, 46, 60, 61, 62, 19, - 20, 30, 441, 32, 1312, 34, 20, 126, 5, 6, - 20, 40, 57, 132, 7, 33, 125, 21, 22, 128, - 129, 50, 178, 128, 129, 1310, 150, 56, 25, 172, - 164, 165, 822, 147, 31, 138, 100, 101, 102, 103, - 139, 140, 141, 162, 1347, 162, 619, 206, 162, 208, - 206, 80, 172, 155, 627, 106, 629, 50, 126, 126, - 179, 1369, 448, 206, 132, 184, 102, 103, 153, 712, - 138, 68, 69, 102, 103, 117, 118, 162, 181, 15, - 16, 1384, 1367, 125, 208, 127, 128, 129, 130, 131, - 207, 205, 208, 202, 203, 170, 568, 202, 203, 137, - 162, 775, 166, 172, 490, 102, 103, 206, 62, 1294, - 33, 179, 179, 117, 118, 182, 138, 186, 507, 692, - 205, 125, 153, 512, 128, 129, 130, 131, 155, 191, - 205, 162, 170, 160, 184, 162, 163, 60, 61, 171, - 162, 138, 162, 172, 178, 190, 21, 22, 822, 185, - 178, 825, 996, 203, 593, 369, 172, 202, 372, 209, - 202, 203, 191, 635, 178, 162, 184, 1220, 178, 205, - 813, 203, 386, 170, 203, 126, 170, 592, 205, 969, - 179, 132, 396, 178, 126, 399, 400, 401, 185, 578, - 132, 606, 256, 153, 386, 126, 170, 185, 202, 203, - 123, 132, 162, 34, 127, 591, 203, 399, 400, 401, - 783, 206, 785, 207, 208, 601, 185, 205, 604, 155, - 793, 126, 338, 796, 160, 1193, 162, 163, 179, 153, - 172, 205, 63, 178, 1287, 1288, 205, 179, 162, 178, - 115, 116, 117, 118, 119, 631, 206, 122, 179, 927, - 125, 1304, 127, 128, 129, 130, 131, 180, 133, 134, - 181, 184, 476, 477, 187, 126, 480, 206, 482, 185, - 484, 132, 486, 178, 179, 178, 181, 126, 178, 184, - 203, 162, 138, 132, 476, 477, 209, 673, 480, 205, - 482, 147, 484, 178, 172, 969, 152, 686, 126, 688, - 131, 1354, 1355, 206, 132, 369, 162, 138, 372, 831, - 185, 186, 187, 188, 189, 190, 191, 1029, 179, 178, - 1076, 206, 386, 172, 178, 178, 390, 202, 203, 185, - 179, 162, 396, 126, 185, 399, 400, 401, 178, 132, - 153, 178, 406, 407, 57, 178, 1351, 206, 162, 162, - 63, 179, 206, 206, 205, 1360, 920, 772, 773, 60, - 61, 62, 5, 6, 195, 8, 206, 782, 899, 206, - 178, 204, 787, 788, 205, 790, 897, 792, 592, 794, - 795, 1227, 797, 178, 178, 185, 179, 1392, 1393, 775, - 1146, 178, 606, 36, 153, 784, 162, 178, 206, 100, - 101, 102, 103, 162, 178, 205, 147, 162, 138, 181, - 204, 206, 476, 477, 186, 138, 480, 147, 482, 206, - 484, 162, 486, 637, 638, 206, 1138, 75, 21, 22, - 204, 79, 162, 205, 181, 181, 181, 47, 652, 186, - 186, 186, 162, 1155, 181, 93, 94, 184, 172, 205, - 98, 99, 100, 101, 178, 162, 670, 67, 205, 205, - 205, 172, 186, 172, 182, 172, 172, 178, 186, 178, - 1144, 178, 178, 172, 153, 186, 690, 186, 1234, 178, - 186, 12, 1092, 162, 57, 699, 155, 186, 702, 172, - 63, 162, 23, 24, 1016, 178, 162, 178, 690, 182, - 181, 162, 178, 184, 202, 181, 57, 699, 184, 1031, - 702, 900, 63, 57, 1078, 57, 139, 1081, 141, 63, - 1084, 63, 115, 116, 117, 118, 119, 57, 592, 122, - 123, 124, 125, 63, 127, 128, 129, 130, 131, 172, - 133, 134, 606, 172, 57, 178, 172, 172, 162, 178, - 63, 182, 178, 178, 57, 186, 164, 771, 772, 773, - 774, 976, 977, 978, 778, 1129, 630, 982, 782, 170, - 764, 182, 162, 787, 788, 186, 790, 179, 792, 771, - 794, 795, 774, 797, 973, 1195, 778, 139, 140, 141, - 1154, 184, 185, 186, 187, 188, 189, 190, 191, 182, - 1015, 182, 182, 186, 182, 186, 186, 182, 186, 202, - 203, 186, 182, 170, 170, 182, 186, 1373, 1004, 186, - 182, 164, 1008, 139, 186, 106, 690, 164, 165, 166, - 167, 1305, 164, 165, 166, 699, 181, 208, 702, 35, - 35, 1214, 205, 21, 22, 164, 165, 166, 170, 863, - 1036, 10, 11, 12, 162, 170, 162, 185, 208, 185, - 185, 185, 1048, 162, 205, 185, 205, 1053, 1278, 205, - 162, 162, 162, 185, 185, 185, 1091, 204, 185, 22, - 185, 185, 1356, 897, 182, 162, 1250, 204, 181, 162, - 170, 178, 181, 1079, 203, 162, 132, 162, 162, 185, - 914, 185, 185, 1267, 1268, 205, 185, 771, 772, 773, - 774, 1385, 208, 185, 778, 185, 185, 205, 782, 185, - 205, 203, 914, 787, 788, 185, 790, 205, 792, 205, - 794, 795, 1342, 797, 205, 162, 162, 115, 116, 117, - 118, 1156, 205, 205, 1130, 206, 205, 125, 1134, 127, - 128, 129, 130, 131, 205, 133, 134, 205, 1432, 205, - 204, 162, 976, 977, 978, 171, 181, 171, 982, 162, - 205, 205, 205, 172, 155, 37, 205, 10, 172, 66, - 172, 172, 172, 172, 172, 172, 1359, 172, 172, 186, - 13, 205, 178, 1179, 21, 22, 179, 4, 208, 162, - 171, 1015, 178, 185, 178, 185, 185, 43, 206, 187, - 188, 189, 190, 191, 1387, 14, 181, 179, 155, 170, - 8, 162, 186, 171, 202, 203, 178, 185, 205, 1, - 205, 204, 346, 897, 206, 205, 205, 205, 185, 206, - 162, 162, 356, 162, 1408, 205, 186, 186, 1412, 205, - 914, 205, 366, 186, 43, 205, 205, 162, 1072, 205, - 205, 205, 1277, 205, 171, 67, 172, 205, 186, 186, - 206, 206, 186, 186, 388, 206, 206, 1091, 186, 206, - 1072, 206, 186, 186, 186, 186, 21, 22, 115, 116, - 117, 118, 119, 186, 205, 122, 123, 124, 125, 185, - 127, 128, 129, 130, 131, 205, 133, 134, 1294, 206, - 424, 425, 976, 977, 978, 1301, 205, 205, 982, 43, - 205, 162, 162, 206, 205, 162, 186, 441, 442, 443, - 444, 445, 446, 186, 186, 186, 186, 206, 205, 205, - 162, 162, 1156, 162, 1158, 162, 162, 12, 162, 43, - 33, 1015, 186, 70, 53, 182, 183, 184, 185, 186, - 187, 188, 189, 190, 191, 162, 1158, 205, 186, 172, - 205, 186, 162, 205, 205, 202, 203, 206, 206, 205, - 115, 116, 117, 118, 119, 499, 172, 122, 123, 124, - 125, 171, 127, 128, 129, 130, 131, 205, 133, 134, - 205, 205, 172, 517, 139, 140, 141, 205, 1072, 205, - 145, 205, 205, 21, 22, 529, 178, 615, 532, 206, - 77, 206, 206, 206, 538, 206, 540, 1091, 204, 206, - 1, 206, 206, 206, 129, 206, 204, 206, 205, 42, - 206, 80, 1273, 1257, 1428, 180, 99, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, 214, 1297, 1, - 574, 1273, 1273, 1277, 1273, 1257, 1273, 202, 203, 1245, - 1198, 206, 1285, 1096, 1201, 51, 521, 406, 1286, 593, - 594, 1356, 760, 597, -1, 599, 406, -1, -1, -1, - -1, -1, 1156, -1, 1158, 609, 610, 611, 612, 613, - 614, -1, -1, -1, -1, 466, -1, -1, -1, 117, - 118, -1, -1, -1, -1, -1, -1, 125, -1, 127, - 128, 129, 130, 131, -1, 639, 640, -1, -1, 643, - 644, 645, 646, -1, 648, -1, 650, 651, 652, 653, + 14, 15, 811, 167, 710, 370, 487, 634, 632, 153, + 482, 571, 484, 488, 486, 79, 8, 935, 532, 681, + 5, 683, 0, 685, 617, 167, 540, 33, 776, 7, + 20, 33, 397, 626, 460, 374, 15, 16, 442, 22, + 128, 129, 33, 20, 567, 1180, 60, 61, 62, 46, + 20, 1313, 30, 835, 32, 1311, 34, 7, 126, 5, + 6, 150, 40, 125, 132, 162, 128, 129, 147, 60, + 61, 170, 50, 20, 57, 823, 126, 150, 56, 25, + 139, 140, 141, 162, 138, 31, 153, 101, 102, 103, + 104, 19, 20, 126, 162, 162, 181, 620, 126, 184, + 50, 34, 80, 172, 132, 628, 205, 630, 1370, 106, + 207, 179, 1368, 449, 202, 203, 184, 102, 103, 208, + 713, 170, 68, 69, 102, 103, 205, 181, 178, 179, + 63, 181, 123, 206, 184, 208, 127, 206, 15, 16, + 202, 203, 126, 569, 172, 209, 179, 206, 132, 182, + 1348, 179, 776, 167, 138, 491, 102, 103, 207, 208, + 1295, 126, 162, 172, 153, 147, 153, 132, 172, 508, + 693, 137, 179, 162, 513, 162, 155, 186, 184, 171, + 162, 160, 184, 162, 163, 21, 22, 1385, 178, 180, + 594, 191, 138, 184, 172, 179, 187, 203, 131, 823, + 185, 178, 826, 209, 170, 138, 370, 190, 178, 373, + 636, 203, 203, 191, 179, 997, 162, 206, 209, 202, + 205, 814, 970, 387, 170, 203, 205, 178, 593, 162, + 170, 178, 155, 397, 162, 153, 400, 401, 402, 185, + 579, 1221, 607, 257, 162, 387, 126, 126, 185, 178, + 185, 172, 132, 132, 178, 206, 592, 203, 400, 401, + 402, 784, 195, 786, 172, 205, 602, 126, 205, 605, + 205, 794, 205, 132, 797, 339, 1194, 206, 155, 115, + 116, 117, 118, 160, 126, 162, 163, 205, 178, 125, + 132, 127, 128, 129, 130, 131, 632, 133, 134, 179, + 179, 928, 178, 1352, 126, 178, 21, 22, 1288, 1289, + 132, 185, 1361, 477, 478, 153, 206, 481, 138, 483, + 179, 485, 182, 487, 162, 1305, 186, 147, 204, 185, + 172, 205, 152, 206, 138, 477, 478, 179, 674, 481, + 62, 483, 162, 485, 1393, 1394, 970, 181, 687, 205, + 689, 187, 188, 189, 190, 191, 370, 179, 162, 373, + 832, 5, 6, 178, 8, 185, 202, 203, 1030, 185, + 178, 1077, 178, 387, 162, 1355, 1356, 391, 178, 178, + 139, 47, 141, 397, 172, 178, 400, 401, 402, 205, + 178, 206, 36, 407, 408, 60, 61, 62, 206, 178, + 206, 67, 117, 118, 178, 204, 206, 921, 773, 774, + 125, 204, 127, 128, 129, 130, 131, 898, 783, 1228, + 178, 178, 178, 788, 789, 900, 791, 206, 793, 593, + 795, 796, 206, 798, 178, 178, 101, 102, 103, 104, + 776, 1147, 181, 607, 138, 12, 785, 186, 206, 206, + 206, 182, 153, 147, 181, 186, 23, 24, 162, 186, + 181, 162, 206, 477, 478, 186, 205, 481, 162, 483, + 172, 485, 75, 487, 638, 639, 79, 1139, 205, 21, + 22, 181, 164, 165, 205, 162, 186, 202, 203, 653, + 93, 94, 153, 57, 1156, 98, 99, 100, 101, 63, + 172, 162, 172, 172, 172, 205, 178, 671, 178, 178, + 178, 182, 162, 172, 186, 186, 186, 186, 186, 178, + 172, 1145, 178, 182, 57, 181, 178, 691, 184, 1235, + 63, 57, 178, 1093, 186, 181, 700, 63, 184, 703, + 57, 57, 57, 138, 172, 1017, 63, 63, 63, 691, + 178, 57, 182, 172, 205, 162, 186, 63, 700, 178, + 1032, 703, 901, 172, 172, 1079, 162, 155, 1082, 178, + 178, 1085, 162, 115, 116, 117, 118, 119, 202, 593, + 122, 123, 124, 125, 162, 127, 128, 129, 130, 131, + 182, 133, 134, 607, 186, 182, 182, 182, 182, 186, + 186, 186, 186, 182, 139, 140, 141, 186, 772, 773, + 774, 775, 977, 978, 979, 779, 1130, 631, 983, 783, + 164, 765, 182, 162, 788, 789, 186, 791, 162, 793, + 772, 795, 796, 775, 798, 974, 1196, 779, 162, 21, + 22, 1155, 184, 185, 186, 187, 188, 189, 190, 191, + 57, 1016, 164, 165, 166, 167, 164, 165, 166, 179, + 202, 203, 164, 165, 166, 10, 11, 12, 1374, 1005, + 170, 170, 170, 1009, 164, 106, 139, 691, 181, 208, + 35, 35, 1306, 205, 170, 170, 700, 162, 162, 703, + 208, 185, 1215, 185, 21, 22, 185, 185, 205, 204, + 864, 1037, 185, 185, 205, 185, 185, 185, 185, 185, + 205, 182, 162, 1049, 162, 162, 162, 22, 1054, 1279, + 162, 181, 181, 204, 162, 170, 178, 1092, 162, 132, + 203, 185, 162, 1357, 898, 117, 118, 1251, 205, 162, + 205, 185, 185, 125, 1080, 185, 128, 129, 130, 131, + 185, 915, 205, 185, 1268, 1269, 205, 185, 772, 773, + 774, 775, 1386, 185, 185, 779, 205, 208, 205, 783, + 206, 162, 205, 915, 788, 789, 205, 791, 205, 793, + 205, 795, 796, 1343, 798, 205, 203, 205, 162, 204, + 117, 118, 1157, 162, 171, 1131, 181, 205, 125, 1135, + 127, 128, 129, 130, 131, 171, 205, 205, 172, 1433, + 162, 155, 37, 977, 978, 979, 172, 205, 10, 983, + 202, 203, 172, 172, 172, 172, 172, 66, 179, 172, + 172, 172, 205, 186, 13, 4, 208, 1360, 178, 178, + 162, 206, 171, 178, 1180, 21, 22, 185, 185, 185, + 43, 14, 1016, 179, 155, 170, 181, 8, 162, 171, + 187, 188, 189, 190, 191, 1388, 186, 178, 185, 185, + 1, 205, 205, 204, 206, 202, 203, 205, 162, 162, + 186, 205, 205, 347, 898, 206, 205, 205, 186, 186, + 162, 205, 205, 357, 43, 1409, 205, 205, 205, 1413, + 162, 915, 205, 367, 171, 205, 67, 172, 186, 1073, + 186, 206, 206, 1278, 206, 186, 205, 186, 206, 206, + 186, 206, 186, 186, 205, 389, 186, 186, 1092, 186, + 185, 1073, 206, 43, 162, 205, 162, 21, 22, 115, + 116, 117, 118, 119, 205, 162, 122, 123, 124, 125, + 206, 127, 128, 129, 130, 131, 205, 133, 134, 1295, + 205, 425, 426, 977, 978, 979, 1302, 205, 186, 983, + 186, 186, 186, 186, 206, 205, 162, 162, 442, 443, + 444, 445, 446, 447, 205, 162, 12, 162, 162, 162, + 43, 33, 186, 1157, 205, 1159, 205, 205, 70, 206, + 205, 205, 1016, 205, 205, 186, 182, 183, 184, 185, + 186, 187, 188, 189, 190, 191, 162, 1159, 186, 206, + 172, 205, 162, 205, 172, 205, 202, 203, 206, 53, + 171, 115, 116, 117, 118, 119, 500, 204, 122, 123, + 124, 125, 206, 127, 128, 129, 130, 131, 205, 133, + 134, 205, 172, 206, 518, 139, 140, 141, 205, 1073, + 178, 145, 206, 206, 21, 22, 530, 206, 206, 533, + 206, 206, 206, 206, 204, 539, 616, 541, 1092, 206, + 78, 1, 42, 130, 81, 1429, 1274, 215, 100, 1298, + 1274, 1274, 1274, 1274, 1258, 1, 180, 467, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, 1246, 1199, + 1286, 575, 522, 1287, 1278, 1202, 1258, 1097, 202, 203, + 51, 761, 206, 1357, -1, 407, -1, 407, -1, -1, + 594, 595, -1, -1, 598, -1, 600, -1, -1, -1, + -1, -1, -1, 1157, -1, 1159, 610, 611, 612, 613, + 614, 615, -1, -1, -1, -1, -1, -1, -1, -1, + 117, 118, -1, -1, -1, -1, -1, -1, 125, -1, + 127, 128, 129, 130, 131, -1, 640, 641, -1, -1, + 644, 645, 646, 647, -1, 649, -1, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, - 664, 665, 666, 667, 668, 669, -1, 671, -1, -1, + 664, 665, 666, 667, 668, 669, 670, -1, 672, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 187, - 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 1257, 202, 203, -1, 711, -1, 713, - -1, -1, 716, -1, 718, -1, -1, 21, 22, -1, - -1, 725, -1, 1277, -1, -1, 730, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 741, 742, 743, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 189, 190, 191, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 1258, 202, 203, -1, 712, -1, + 714, -1, -1, 717, -1, 719, -1, -1, -1, -1, + -1, -1, 726, -1, 1278, -1, -1, 731, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, - 754, 755, 756, 757, 758, 759, -1, -1, 1312, -1, - -1, -1, 766, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 777, -1, -1, -1, 19, -1, -1, - -1, -1, -1, 25, -1, -1, -1, -1, -1, 31, + 754, 755, 756, 757, 758, 759, 760, -1, -1, 1313, + -1, -1, -1, 767, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 778, -1, -1, -1, 19, -1, + -1, -1, -1, -1, 25, -1, -1, -1, -1, -1, + 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 41, -1, -1, 807, -1, -1, 810, 811, 49, -1, + -1, 815, -1, -1, -1, -1, 1370, -1, -1, -1, + -1, -1, -1, 64, -1, -1, -1, -1, -1, 833, + 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, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 877, -1, -1, -1, 881, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 138, -1, -1, + -1, -1, -1, -1, -1, -1, 910, -1, -1, -1, + 151, -1, -1, 917, -1, -1, -1, 19, -1, -1, + 924, 162, -1, 25, -1, -1, 930, -1, -1, 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, 41, - -1, -1, 806, -1, -1, 809, 810, 49, -1, -1, - 814, -1, -1, 117, 118, 1369, -1, -1, -1, -1, - -1, 125, 64, 127, 128, 129, 130, 131, 832, 71, + -1, -1, -1, -1, -1, -1, -1, 49, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 64, -1, -1, -1, 207, -1, 209, 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, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 876, -1, -1, -1, 880, -1, -1, -1, - -1, -1, -1, -1, -1, 189, 190, 191, -1, -1, - -1, -1, -1, -1, -1, -1, 138, -1, 202, 203, - -1, -1, -1, -1, -1, 909, -1, -1, -1, 151, - -1, -1, 916, -1, -1, -1, 19, -1, -1, 923, - 162, -1, 25, -1, -1, 929, -1, -1, 31, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 41, -1, - -1, -1, -1, -1, -1, -1, 49, -1, -1, -1, + 1014, 1015, -1, -1, -1, -1, -1, 1021, 1022, 1023, + -1, 1025, -1, -1, -1, -1, -1, -1, -1, -1, + 1034, -1, 1036, -1, 1038, -1, 138, -1, -1, -1, + 1044, -1, -1, -1, 1048, -1, -1, -1, -1, 151, + -1, -1, 1056, -1, -1, -1, -1, -1, -1, -1, + 162, -1, -1, 19, -1, -1, -1, -1, -1, 25, + 172, -1, -1, -1, -1, 31, 178, -1, -1, -1, + 1084, -1, -1, 1087, -1, 41, -1, -1, -1, -1, + -1, -1, -1, 49, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 207, -1, -1, 64, -1, + -1, -1, -1, -1, 1118, 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, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 64, -1, -1, -1, 207, -1, 209, 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, -1, -1, -1, -1, -1, -1, -1, -1, 1013, - 1014, -1, -1, -1, -1, -1, 1020, 1021, 1022, -1, - 1024, -1, -1, -1, -1, -1, -1, -1, -1, 1033, - -1, 1035, -1, 1037, -1, 138, -1, -1, -1, 1043, - -1, -1, -1, 1047, -1, -1, -1, -1, 151, -1, - -1, 1055, -1, -1, -1, -1, -1, -1, -1, 162, - -1, -1, 19, -1, -1, -1, -1, -1, 25, 172, - -1, -1, -1, -1, 31, 178, -1, -1, -1, 1083, - -1, -1, 1086, -1, 41, -1, -1, -1, -1, -1, - -1, -1, 49, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 207, -1, -1, 64, -1, -1, - -1, -1, -1, 1117, 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, -1, -1, -1, + -1, 1165, -1, 1167, -1, -1, -1, -1, 1172, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 1164, -1, 1166, -1, -1, -1, -1, 1171, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 1183, - -1, 138, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 1196, -1, 151, -1, -1, -1, -1, -1, - -1, -1, 1206, -1, -1, 162, -1, -1, -1, -1, - -1, -1, 1216, 1217, 1218, -1, -1, -1, -1, 1223, - -1, -1, -1, 1227, 1228, -1, -1, -1, -1, -1, - -1, -1, 35, 1237, 1238, 1239, -1, -1, -1, -1, - -1, -1, -1, 1247, -1, -1, -1, -1, -1, -1, - 207, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 71, 1273, - 73, -1, 75, 76, 77, 78, 79, 1281, 81, 82, - 83, 84, 85, 86, 87, 88, 89, 90, 91, -1, - 93, 94, 95, 1297, -1, 98, 99, 100, 101, -1, - -1, -1, -1, -1, -1, -1, -1, 1311, -1, -1, - 1314, 1315, -1, -1, 117, 118, -1, -1, 1322, -1, + 1184, -1, 138, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 1197, -1, 151, -1, -1, -1, -1, + -1, -1, -1, 1207, -1, -1, 162, -1, -1, -1, + -1, -1, -1, 1217, 1218, 1219, -1, -1, -1, -1, + 1224, -1, -1, -1, 1228, 1229, -1, -1, -1, -1, + -1, -1, -1, 35, 1238, 1239, 1240, -1, -1, -1, + -1, -1, -1, -1, 1248, -1, -1, -1, -1, -1, + -1, 207, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 71, + 1274, 73, -1, 75, 76, 77, 78, 79, 1282, 81, + 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + -1, 93, 94, 95, 1298, -1, 98, 99, 100, 101, + -1, -1, -1, -1, -1, -1, -1, -1, 1312, -1, + -1, 1315, 1316, -1, -1, 117, 118, -1, -1, 1323, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 1334, -1, -1, -1, -1, -1, 1, -1, -1, 1343, - 5, 6, 7, -1, 9, 10, 11, -1, 13, 1353, - 15, 16, 17, 18, 19, -1, -1, -1, -1, 162, - 25, 26, 27, 28, 29, -1, 31, -1, -1, -1, - -1, -1, -1, 38, 39, -1, 1380, 42, -1, 44, - 45, -1, -1, 48, -1, 50, 51, 52, -1, 54, - 55, -1, -1, 58, 59, -1, 1400, -1, -1, -1, - 65, 1405, 1406, 68, 69, -1, 71, 72, 73, -1, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, -1, 93, 94, - 95, -1, -1, 98, 99, 100, 101, 102, 103, 104, - 105, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 117, 118, -1, -1, -1, -1, -1, -1, + -1, 1335, -1, -1, -1, -1, -1, 1, -1, -1, + 1344, 5, 6, 7, -1, 9, 10, 11, -1, 13, + 1354, 15, 16, 17, 18, 19, -1, -1, -1, -1, + 162, 25, 26, 27, 28, 29, -1, 31, -1, -1, + -1, -1, -1, -1, 38, 39, -1, 1381, 42, -1, + 44, 45, -1, -1, 48, -1, 50, 51, 52, -1, + 54, 55, -1, -1, 58, 59, -1, 1401, -1, -1, + -1, 65, 1406, 1407, 68, 69, -1, 71, 72, 73, + -1, 75, 76, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, -1, 93, + 94, 95, -1, -1, 98, 99, 100, 101, 102, 103, + 104, 105, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 117, 118, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 138, -1, -1, -1, -1, -1, + -1, -1, 146, 147, 148, 149, 150, -1, 152, -1, + 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, + -1, -1, -1, -1, -1, -1, 170, 171, 172, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 187, 188, 189, -1, 191, -1, -1, + 194, 195, -1, -1, -1, -1, -1, -1, -1, 203, + -1, 205, 1, 207, 208, -1, 5, 6, 7, -1, + 9, 10, 11, -1, 13, -1, 15, 16, 17, 18, + 19, -1, -1, -1, -1, -1, 25, 26, 27, 28, + 29, -1, 31, -1, -1, -1, -1, -1, -1, 38, + 39, -1, -1, 42, -1, 44, 45, -1, -1, 48, + -1, 50, 51, 52, -1, 54, 55, -1, -1, 58, + 59, -1, -1, -1, -1, -1, 65, -1, -1, 68, + 69, -1, 71, 72, 73, -1, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, -1, 93, 94, 95, -1, -1, 98, + 99, 100, 101, 102, 103, 104, 105, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 117, 118, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 138, + -1, -1, -1, -1, -1, -1, -1, 146, 147, 148, + 149, 150, -1, 152, -1, 154, 155, 156, 157, 158, + 159, 160, 161, 162, 163, -1, -1, -1, -1, -1, + -1, 170, 171, 172, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 187, 188, + 189, -1, 191, -1, -1, 194, 195, -1, -1, -1, + -1, -1, -1, -1, 203, -1, 205, 1, 207, 208, + -1, 5, 6, 7, -1, 9, 10, 11, -1, 13, + -1, 15, 16, 17, 18, 19, -1, -1, -1, -1, + -1, 25, 26, 27, 28, 29, -1, 31, -1, -1, + -1, -1, -1, -1, 38, 39, -1, -1, 42, -1, + 44, 45, -1, -1, 48, -1, 50, 51, 52, -1, + 54, 55, -1, -1, 58, 59, -1, -1, -1, -1, + -1, 65, -1, -1, 68, 69, -1, 71, 72, 73, + -1, 75, 76, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, -1, 93, + 94, 95, -1, -1, 98, 99, 100, 101, 102, 103, + 104, 105, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 138, -1, -1, -1, -1, -1, -1, - -1, 146, 147, 148, 149, 150, -1, 152, -1, 154, - 155, 156, 157, 158, 159, 160, 161, 162, 163, -1, - -1, -1, -1, -1, -1, 170, 171, 172, -1, -1, + -1, -1, -1, -1, 138, -1, -1, -1, -1, -1, + -1, -1, 146, 147, 148, 149, 150, -1, 152, -1, + 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, + -1, -1, -1, -1, -1, -1, 170, 171, 172, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 187, 188, 189, -1, 191, -1, -1, 194, - 195, -1, -1, -1, -1, -1, -1, -1, 203, -1, - 205, 1, 207, 208, -1, 5, 6, 7, -1, 9, - 10, 11, -1, 13, -1, 15, 16, 17, 18, 19, - -1, -1, -1, -1, -1, 25, 26, 27, 28, 29, - -1, 31, -1, -1, -1, -1, -1, -1, 38, 39, - -1, -1, 42, -1, 44, 45, -1, -1, 48, -1, - 50, 51, 52, -1, 54, 55, -1, -1, 58, 59, + -1, -1, -1, 187, 188, 189, -1, 191, -1, -1, + 194, 195, -1, -1, -1, 5, 6, -1, -1, 203, + -1, 205, -1, 207, 208, 15, 16, 17, 18, 19, + -1, -1, -1, -1, -1, 25, 26, 27, 28, -1, + -1, 31, -1, -1, -1, -1, -1, -1, -1, 39, + -1, -1, -1, -1, -1, 45, -1, -1, 48, -1, + -1, 51, 52, -1, -1, 55, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, -1, -1, 68, 69, -1, 71, 72, 73, -1, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, @@ -2951,721 +3004,669 @@ static const yytype_int16 yycheck[] = -1, -1, -1, -1, -1, -1, 146, 147, 148, 149, 150, -1, 152, -1, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, -1, -1, -1, -1, -1, -1, - 170, 171, 172, -1, -1, -1, -1, -1, -1, -1, + 170, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 187, 188, 189, - -1, 191, -1, -1, 194, 195, -1, -1, -1, -1, - -1, -1, -1, 203, -1, 205, 1, 207, 208, -1, - 5, 6, 7, -1, 9, 10, 11, -1, 13, -1, - 15, 16, 17, 18, 19, -1, -1, -1, -1, -1, - 25, 26, 27, 28, 29, -1, 31, -1, -1, -1, - -1, -1, -1, 38, 39, -1, -1, 42, -1, 44, - 45, -1, -1, 48, -1, 50, 51, 52, -1, 54, - 55, -1, -1, 58, 59, -1, -1, -1, -1, -1, - 65, -1, -1, 68, 69, -1, 71, 72, 73, -1, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, -1, 93, 94, - 95, -1, -1, 98, 99, 100, 101, 102, 103, 104, - 105, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 117, 118, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 138, -1, -1, -1, -1, -1, -1, - -1, 146, 147, 148, 149, 150, -1, 152, -1, 154, - 155, 156, 157, 158, 159, 160, 161, 162, 163, -1, - -1, -1, -1, -1, -1, 170, 171, 172, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 187, 188, 189, -1, 191, -1, -1, 194, - 195, -1, -1, -1, 5, 6, -1, -1, 203, -1, - 205, -1, 207, 208, 15, 16, 17, 18, 19, -1, - -1, -1, -1, -1, 25, 26, 27, 28, -1, -1, - 31, -1, -1, -1, -1, -1, -1, -1, 39, -1, - -1, -1, -1, -1, 45, -1, -1, 48, -1, -1, - 51, 52, -1, -1, 55, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 65, -1, -1, 68, 69, -1, - 71, 72, 73, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - 91, -1, 93, 94, 95, -1, -1, 98, 99, 100, - 101, 102, 103, 104, 105, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 117, 118, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 138, -1, -1, - -1, -1, -1, -1, -1, 146, 147, 148, 149, 150, - -1, 152, -1, 154, 155, 156, 157, 158, 159, 160, - 161, 162, 163, -1, -1, -1, -1, -1, -1, 170, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 187, 188, 189, -1, - 191, -1, -1, 194, 195, -1, -1, -1, 5, 6, - -1, -1, 203, -1, 205, -1, 207, 208, 15, 16, - 17, 18, 19, -1, -1, -1, -1, -1, 25, -1, - 27, -1, -1, -1, 31, -1, -1, -1, -1, -1, - -1, -1, 39, -1, -1, -1, -1, -1, 45, -1, - -1, 48, -1, -1, 51, -1, -1, -1, 55, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 65, -1, - -1, 68, 69, 70, 71, 72, 73, -1, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, -1, 93, 94, 95, -1, - -1, 98, 99, 100, 101, 102, 103, 104, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 138, -1, -1, -1, -1, -1, -1, -1, 146, - 147, 148, 149, 150, -1, 152, 153, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, -1, -1, -1, - -1, -1, -1, 170, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 187, 188, 189, -1, 191, -1, -1, 194, 195, -1, - -1, -1, -1, -1, 5, 6, 203, -1, 205, 206, - 207, 208, 13, -1, 15, 16, 17, 18, 19, -1, - -1, -1, -1, -1, 25, -1, 27, -1, -1, -1, - 31, -1, -1, -1, -1, -1, -1, -1, 39, -1, - -1, -1, -1, -1, 45, -1, -1, 48, 49, -1, - 51, -1, -1, -1, 55, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 65, -1, -1, 68, 69, -1, - 71, 72, 73, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - 91, -1, 93, 94, 95, -1, -1, 98, 99, 100, - 101, 102, 103, 104, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 117, 118, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 138, -1, -1, - -1, -1, -1, -1, -1, 146, 147, 148, 149, 150, - -1, 152, 153, 154, 155, 156, 157, 158, 159, 160, - 161, 162, 163, -1, -1, -1, -1, -1, -1, 170, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 187, 188, 189, -1, - 191, -1, -1, 194, 195, -1, -1, -1, -1, -1, - 5, 6, 203, -1, 205, -1, 207, 208, 13, -1, - 15, 16, 17, 18, 19, -1, -1, -1, -1, -1, - 25, -1, 27, -1, -1, -1, 31, -1, -1, -1, - -1, -1, -1, -1, 39, -1, -1, -1, -1, -1, - 45, -1, -1, 48, 49, -1, 51, -1, -1, -1, - 55, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 65, -1, -1, 68, 69, -1, 71, 72, 73, -1, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, -1, 93, 94, - 95, -1, -1, 98, 99, 100, 101, 102, 103, 104, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 117, 118, -1, -1, -1, -1, -1, -1, + -1, 191, -1, -1, 194, 195, -1, -1, -1, 5, + 6, -1, -1, 203, -1, 205, -1, 207, 208, 15, + 16, 17, 18, 19, -1, -1, -1, -1, -1, 25, + -1, 27, -1, -1, -1, 31, -1, -1, -1, -1, + -1, -1, -1, 39, -1, -1, -1, -1, -1, 45, + -1, -1, 48, -1, -1, 51, -1, -1, -1, 55, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, + -1, -1, 68, 69, 70, 71, 72, 73, -1, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, 88, 89, 90, 91, -1, 93, 94, 95, + -1, -1, 98, 99, 100, 101, 102, 103, 104, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 138, -1, -1, -1, -1, -1, -1, - -1, 146, 147, 148, 149, 150, -1, 152, -1, 154, - 155, 156, 157, 158, 159, 160, 161, 162, 163, -1, - -1, -1, -1, -1, -1, 170, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 187, 188, 189, -1, 191, -1, -1, 194, - 195, -1, -1, -1, 5, 6, -1, -1, 203, -1, - 205, -1, 207, 208, 15, 16, 17, 18, 19, -1, - -1, -1, -1, -1, 25, -1, 27, -1, -1, -1, - 31, -1, -1, -1, -1, -1, -1, -1, 39, -1, - -1, -1, -1, -1, 45, -1, -1, 48, -1, -1, - 51, -1, -1, -1, 55, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 65, -1, -1, 68, 69, 70, - 71, 72, 73, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - 91, -1, 93, 94, 95, -1, -1, 98, 99, 100, - 101, 102, 103, 104, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 117, 118, -1, -1, + -1, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 138, -1, -1, - -1, -1, -1, -1, -1, 146, 147, 148, 149, 150, - -1, 152, 153, 154, 155, 156, 157, 158, 159, 160, - 161, 162, 163, -1, -1, -1, -1, -1, -1, 170, + -1, -1, 138, -1, -1, -1, -1, -1, -1, -1, + 146, 147, 148, 149, 150, -1, 152, 153, 154, 155, + 156, 157, 158, 159, 160, 161, 162, 163, -1, -1, + -1, -1, -1, -1, 170, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 187, 188, 189, -1, - 191, -1, -1, 194, 195, -1, -1, -1, 5, 6, - -1, -1, 203, -1, 205, -1, 207, 208, 15, 16, - 17, 18, 19, -1, -1, -1, -1, -1, 25, -1, - 27, -1, -1, -1, 31, -1, -1, -1, -1, -1, - -1, -1, 39, -1, -1, -1, -1, -1, 45, -1, - -1, 48, -1, -1, 51, -1, -1, -1, 55, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 65, -1, - -1, 68, 69, -1, 71, 72, 73, -1, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, -1, 93, 94, 95, -1, - -1, 98, 99, 100, 101, 102, 103, 104, -1, -1, + -1, 187, 188, 189, -1, 191, -1, -1, 194, 195, + -1, -1, -1, -1, -1, 5, 6, 203, -1, 205, + 206, 207, 208, 13, -1, 15, 16, 17, 18, 19, + -1, -1, -1, -1, -1, 25, -1, 27, -1, -1, + -1, 31, -1, -1, -1, -1, -1, -1, -1, 39, + -1, -1, -1, -1, -1, 45, -1, -1, 48, 49, + -1, 51, -1, -1, -1, 55, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 65, -1, -1, 68, 69, + -1, 71, 72, 73, -1, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, -1, 93, 94, 95, -1, -1, 98, 99, + 100, 101, 102, 103, 104, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 138, -1, + -1, -1, -1, -1, -1, -1, 146, 147, 148, 149, + 150, -1, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, -1, -1, -1, -1, -1, -1, + 170, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 187, 188, 189, + -1, 191, -1, -1, 194, 195, -1, -1, -1, -1, + -1, 5, 6, 203, -1, 205, -1, 207, 208, 13, + -1, 15, 16, 17, 18, 19, -1, -1, -1, -1, + -1, 25, -1, 27, -1, -1, -1, 31, -1, -1, + -1, -1, -1, -1, -1, 39, -1, -1, -1, -1, + -1, 45, -1, -1, 48, 49, -1, 51, -1, -1, + -1, 55, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 65, -1, -1, 68, 69, -1, 71, 72, 73, + -1, 75, 76, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, -1, 93, + 94, 95, -1, -1, 98, 99, 100, 101, 102, 103, + 104, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 138, -1, -1, -1, -1, -1, -1, -1, 146, - 147, 148, 149, 150, -1, 152, -1, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, -1, -1, -1, - -1, -1, -1, 170, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 138, -1, -1, -1, -1, -1, + -1, -1, 146, 147, 148, 149, 150, -1, 152, -1, + 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, + -1, -1, -1, -1, -1, -1, 170, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 187, 188, 189, -1, 191, -1, -1, 194, 195, -1, - -1, -1, -1, -1, 5, 6, 203, 204, 205, -1, - 207, 208, 13, -1, 15, 16, 17, 18, 19, -1, - -1, -1, -1, -1, 25, -1, 27, -1, -1, -1, - 31, -1, -1, -1, -1, -1, -1, -1, 39, -1, - -1, -1, -1, -1, 45, -1, -1, 48, -1, -1, - 51, -1, -1, -1, 55, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 65, -1, -1, 68, 69, -1, - 71, 72, 73, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - 91, -1, 93, 94, 95, -1, -1, 98, 99, 100, - 101, 102, 103, 104, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 117, 118, -1, -1, + -1, -1, -1, 187, 188, 189, -1, 191, -1, -1, + 194, 195, -1, -1, -1, 5, 6, -1, -1, 203, + -1, 205, -1, 207, 208, 15, 16, 17, 18, 19, + -1, -1, -1, -1, -1, 25, -1, 27, -1, -1, + -1, 31, -1, -1, -1, -1, -1, -1, -1, 39, + -1, -1, -1, -1, -1, 45, -1, -1, 48, -1, + -1, 51, -1, -1, -1, 55, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 65, -1, -1, 68, 69, + 70, 71, 72, 73, -1, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, -1, 93, 94, 95, -1, -1, 98, 99, + 100, 101, 102, 103, 104, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 138, -1, -1, - -1, -1, -1, -1, -1, 146, 147, 148, 149, 150, - -1, 152, -1, 154, 155, 156, 157, 158, 159, 160, - 161, 162, 163, -1, -1, -1, -1, -1, -1, 170, + -1, -1, -1, -1, -1, -1, -1, -1, 138, -1, + -1, -1, -1, -1, -1, -1, 146, 147, 148, 149, + 150, -1, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, -1, -1, -1, -1, -1, -1, + 170, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 187, 188, 189, + -1, 191, -1, -1, 194, 195, -1, -1, -1, 5, + 6, -1, -1, 203, -1, 205, -1, 207, 208, 15, + 16, 17, 18, 19, -1, -1, -1, -1, -1, 25, + -1, 27, -1, -1, -1, 31, -1, -1, -1, -1, + -1, -1, -1, 39, -1, -1, -1, -1, -1, 45, + -1, -1, 48, -1, -1, 51, -1, -1, -1, 55, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, + -1, -1, 68, 69, -1, 71, 72, 73, -1, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, 88, 89, 90, 91, -1, 93, 94, 95, + -1, -1, 98, 99, 100, 101, 102, 103, 104, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 187, 188, 189, -1, - 191, -1, -1, 194, 195, -1, -1, -1, 5, 6, - -1, -1, 203, -1, 205, -1, 207, 208, 15, 16, - 17, 18, 19, -1, -1, -1, -1, -1, 25, -1, - 27, -1, -1, -1, 31, -1, -1, -1, -1, -1, - -1, -1, 39, -1, -1, -1, -1, -1, 45, -1, - -1, 48, -1, -1, 51, -1, -1, -1, 55, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 65, -1, - -1, 68, 69, -1, 71, 72, 73, -1, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, -1, 93, 94, 95, -1, - -1, 98, 99, 100, 101, 102, 103, 104, -1, -1, + -1, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 138, -1, -1, -1, -1, -1, -1, -1, + 146, 147, 148, 149, 150, -1, 152, -1, 154, 155, + 156, 157, 158, 159, 160, 161, 162, 163, -1, -1, + -1, -1, -1, -1, 170, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 138, -1, -1, -1, -1, -1, -1, -1, 146, - 147, 148, 149, 150, -1, 152, -1, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, -1, -1, -1, - -1, -1, -1, 170, -1, -1, -1, -1, -1, -1, + -1, 187, 188, 189, -1, 191, -1, -1, 194, 195, + -1, -1, -1, -1, -1, 5, 6, 203, 204, 205, + -1, 207, 208, 13, -1, 15, 16, 17, 18, 19, + -1, -1, -1, -1, -1, 25, -1, 27, -1, -1, + -1, 31, -1, -1, -1, -1, -1, -1, -1, 39, + -1, -1, -1, -1, -1, 45, -1, -1, 48, -1, + -1, 51, -1, -1, -1, 55, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 65, -1, -1, 68, 69, + -1, 71, 72, 73, -1, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, -1, 93, 94, 95, -1, -1, 98, 99, + 100, 101, 102, 103, 104, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 187, 188, 189, -1, 191, -1, -1, 194, 195, -1, - -1, -1, 5, 6, -1, -1, 203, 204, 205, -1, - 207, 208, 15, 16, 17, 18, 19, -1, -1, -1, - -1, -1, 25, -1, 27, -1, -1, -1, 31, -1, - -1, -1, -1, -1, -1, -1, 39, -1, -1, -1, - -1, -1, 45, -1, -1, 48, -1, -1, 51, -1, - -1, -1, 55, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 65, -1, -1, 68, 69, -1, 71, 72, - 73, -1, 75, 76, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 88, 89, 90, 91, -1, - 93, 94, 95, -1, -1, 98, 99, 100, 101, 102, - 103, 104, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 117, 118, -1, -1, -1, -1, - -1, -1, -1, 126, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 138, -1, -1, -1, -1, - -1, -1, -1, 146, 147, 148, 149, 150, -1, 152, - -1, 154, 155, 156, 157, 158, 159, 160, 161, 162, - 163, -1, -1, -1, -1, -1, -1, 170, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 138, -1, + -1, -1, -1, -1, -1, -1, 146, 147, 148, 149, + 150, -1, 152, -1, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, -1, -1, -1, -1, -1, -1, + 170, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 187, 188, 189, + -1, 191, -1, -1, 194, 195, -1, -1, -1, 5, + 6, -1, -1, 203, -1, 205, -1, 207, 208, 15, + 16, 17, 18, 19, -1, -1, -1, -1, -1, 25, + -1, 27, -1, -1, -1, 31, -1, -1, -1, -1, + -1, -1, -1, 39, -1, -1, -1, -1, -1, 45, + -1, -1, 48, -1, -1, 51, -1, -1, -1, 55, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, + -1, -1, 68, 69, -1, 71, 72, 73, -1, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, 88, 89, 90, 91, -1, 93, 94, 95, + -1, -1, 98, 99, 100, 101, 102, 103, 104, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 187, 188, 189, -1, 191, -1, - -1, 194, 195, -1, -1, -1, 5, 6, -1, -1, - 203, -1, 205, -1, 207, 208, 15, 16, 17, 18, - 19, -1, -1, -1, -1, -1, 25, -1, 27, -1, - -1, -1, 31, -1, -1, -1, -1, -1, -1, -1, - 39, -1, -1, -1, -1, -1, 45, -1, -1, 48, - -1, -1, 51, -1, -1, -1, 55, -1, -1, -1, - -1, -1, 61, -1, -1, -1, 65, -1, -1, 68, - 69, -1, 71, 72, 73, -1, 75, 76, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, -1, 93, 94, 95, -1, -1, 98, - 99, 100, 101, 102, 103, 104, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 117, 118, + -1, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 138, - -1, -1, -1, -1, -1, -1, -1, 146, 147, 148, - 149, 150, -1, 152, -1, 154, 155, 156, 157, 158, - 159, 160, 161, 162, 163, -1, -1, -1, -1, -1, - -1, 170, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 187, 188, - 189, -1, 191, -1, -1, 194, 195, -1, -1, -1, - 5, 6, -1, -1, 203, -1, 205, -1, 207, 208, - 15, 16, 17, 18, 19, -1, -1, -1, -1, -1, - 25, -1, 27, -1, -1, -1, 31, -1, -1, -1, - -1, -1, -1, -1, 39, -1, -1, -1, -1, -1, - 45, -1, -1, 48, -1, -1, 51, -1, -1, -1, - 55, -1, -1, 58, -1, -1, -1, -1, -1, -1, - 65, -1, -1, 68, 69, -1, 71, 72, 73, -1, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, -1, 93, 94, - 95, -1, -1, 98, 99, 100, 101, 102, 103, 104, + -1, -1, 138, -1, -1, -1, -1, -1, -1, -1, + 146, 147, 148, 149, 150, -1, 152, -1, 154, 155, + 156, 157, 158, 159, 160, 161, 162, 163, -1, -1, + -1, -1, -1, -1, 170, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 117, 118, -1, -1, -1, -1, -1, -1, + -1, 187, 188, 189, -1, 191, -1, -1, 194, 195, + -1, -1, -1, 5, 6, -1, -1, 203, 204, 205, + -1, 207, 208, 15, 16, 17, 18, 19, -1, -1, + -1, -1, -1, 25, -1, 27, -1, -1, -1, 31, + -1, -1, -1, -1, -1, -1, -1, 39, -1, -1, + -1, -1, -1, 45, -1, -1, 48, -1, -1, 51, + -1, -1, -1, 55, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 65, -1, -1, 68, 69, -1, 71, + 72, 73, -1, 75, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + -1, 93, 94, 95, -1, -1, 98, 99, 100, 101, + 102, 103, 104, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 117, 118, -1, -1, -1, + -1, -1, -1, -1, 126, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 138, -1, -1, -1, + -1, -1, -1, -1, 146, 147, 148, 149, 150, -1, + 152, -1, 154, 155, 156, 157, 158, 159, 160, 161, + 162, 163, -1, -1, -1, -1, -1, -1, 170, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 138, -1, -1, -1, -1, -1, -1, - -1, 146, 147, 148, 149, 150, -1, 152, -1, 154, - 155, 156, 157, 158, 159, 160, 161, 162, 163, -1, - -1, -1, -1, -1, -1, 170, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 187, 188, 189, -1, 191, + -1, -1, 194, 195, -1, -1, -1, 5, 6, -1, + -1, 203, -1, 205, -1, 207, 208, 15, 16, 17, + 18, 19, -1, -1, -1, -1, -1, 25, -1, 27, + -1, -1, -1, 31, -1, -1, -1, -1, -1, -1, + -1, 39, -1, -1, -1, -1, -1, 45, -1, -1, + 48, -1, -1, 51, -1, -1, -1, 55, -1, -1, + -1, -1, -1, 61, -1, -1, -1, 65, -1, -1, + 68, 69, -1, 71, 72, 73, -1, 75, 76, 77, + 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, -1, 93, 94, 95, -1, -1, + 98, 99, 100, 101, 102, 103, 104, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 117, + 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 187, 188, 189, -1, 191, -1, -1, 194, - 195, -1, -1, -1, 5, 6, -1, -1, 203, -1, - 205, -1, 207, 208, 15, 16, 17, 18, 19, -1, - -1, -1, -1, -1, 25, -1, 27, -1, -1, -1, - 31, -1, -1, -1, -1, -1, -1, -1, 39, -1, - -1, -1, -1, -1, 45, -1, -1, 48, -1, -1, - 51, -1, -1, -1, 55, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 65, -1, -1, 68, 69, -1, - 71, 72, 73, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - 91, -1, 93, 94, 95, -1, -1, 98, 99, 100, - 101, 102, 103, 104, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 117, 118, -1, -1, - -1, -1, -1, -1, -1, 126, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 138, -1, -1, - -1, -1, -1, -1, -1, 146, 147, 148, 149, 150, - -1, 152, -1, 154, 155, 156, 157, 158, 159, 160, - 161, 162, 163, -1, -1, -1, -1, -1, -1, 170, + 138, -1, -1, -1, -1, -1, -1, -1, 146, 147, + 148, 149, 150, -1, 152, -1, 154, 155, 156, 157, + 158, 159, 160, 161, 162, 163, -1, -1, -1, -1, + -1, -1, 170, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 187, + 188, 189, -1, 191, -1, -1, 194, 195, -1, -1, + -1, 5, 6, -1, -1, 203, -1, 205, -1, 207, + 208, 15, 16, 17, 18, 19, -1, -1, -1, -1, + -1, 25, -1, 27, -1, -1, -1, 31, -1, -1, + -1, -1, -1, -1, -1, 39, -1, -1, -1, -1, + -1, 45, -1, -1, 48, -1, -1, 51, -1, -1, + -1, 55, -1, -1, 58, -1, -1, -1, -1, -1, + -1, 65, -1, -1, 68, 69, -1, 71, 72, 73, + -1, 75, 76, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, -1, 93, + 94, 95, -1, -1, 98, 99, 100, 101, 102, 103, + 104, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 187, 188, 189, -1, - 191, -1, -1, 194, 195, -1, -1, -1, 5, 6, - -1, -1, 203, -1, 205, -1, 207, 208, 15, 16, - 17, 18, 19, -1, -1, 22, -1, -1, 25, -1, - 27, -1, -1, -1, 31, -1, -1, -1, -1, -1, - -1, -1, 39, -1, -1, -1, -1, -1, 45, -1, - -1, 48, -1, -1, 51, -1, -1, -1, 55, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 65, -1, - -1, 68, 69, -1, 71, 72, 73, -1, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, -1, 93, 94, 95, -1, - -1, 98, 99, 100, 101, 102, 103, 104, -1, -1, + -1, -1, -1, -1, 138, -1, -1, -1, -1, -1, + -1, -1, 146, 147, 148, 149, 150, -1, 152, -1, + 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, + -1, -1, -1, -1, -1, -1, 170, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 187, 188, 189, -1, 191, -1, -1, + 194, 195, -1, -1, -1, 5, 6, -1, -1, 203, + -1, 205, -1, 207, 208, 15, 16, 17, 18, 19, + -1, -1, -1, -1, -1, 25, -1, 27, -1, -1, + -1, 31, -1, -1, -1, -1, -1, -1, -1, 39, + -1, -1, -1, -1, -1, 45, -1, -1, 48, -1, + -1, 51, -1, -1, -1, 55, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 65, -1, -1, 68, 69, + -1, 71, 72, 73, -1, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, -1, 93, 94, 95, -1, -1, 98, 99, + 100, 101, 102, 103, 104, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 117, 118, -1, + -1, -1, -1, -1, -1, -1, 126, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 138, -1, + -1, -1, -1, -1, -1, -1, 146, 147, 148, 149, + 150, -1, 152, -1, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, -1, -1, -1, -1, -1, -1, + 170, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 187, 188, 189, + -1, 191, -1, -1, 194, 195, -1, -1, -1, 5, + 6, -1, -1, 203, -1, 205, -1, 207, 208, 15, + 16, 17, 18, 19, -1, -1, 22, -1, -1, 25, + -1, 27, -1, -1, -1, 31, -1, -1, -1, -1, + -1, -1, -1, 39, -1, -1, -1, -1, -1, 45, + -1, -1, 48, -1, -1, 51, -1, -1, -1, 55, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, + -1, -1, 68, 69, -1, 71, 72, 73, -1, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, 88, 89, 90, 91, -1, 93, 94, 95, + -1, -1, 98, 99, 100, 101, 102, 103, 104, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 138, -1, -1, -1, -1, -1, -1, -1, 146, - 147, 148, 149, 150, -1, 152, -1, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, -1, -1, -1, - -1, -1, -1, 170, -1, -1, -1, -1, -1, -1, + -1, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 187, 188, 189, -1, 191, -1, -1, 194, 195, -1, - -1, -1, 5, 6, -1, -1, 203, -1, 205, -1, - 207, 208, 15, 16, 17, 18, 19, -1, -1, -1, - -1, -1, 25, -1, 27, -1, -1, -1, 31, -1, - -1, -1, -1, -1, -1, -1, 39, -1, -1, -1, - -1, -1, 45, -1, -1, 48, -1, -1, 51, -1, - -1, -1, 55, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 65, -1, -1, 68, 69, -1, 71, 72, - 73, -1, 75, 76, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 88, 89, 90, 91, -1, - 93, 94, 95, -1, -1, 98, 99, 100, 101, 102, - 103, 104, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 117, 118, -1, -1, -1, -1, + -1, -1, 138, -1, -1, -1, -1, -1, -1, -1, + 146, 147, 148, 149, 150, -1, 152, -1, 154, 155, + 156, 157, 158, 159, 160, 161, 162, 163, -1, -1, + -1, -1, -1, -1, 170, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 138, -1, -1, -1, -1, - -1, -1, -1, 146, 147, 148, 149, 150, -1, 152, - -1, 154, 155, 156, 157, 158, 159, 160, 161, 162, - 163, -1, -1, -1, -1, -1, -1, 170, -1, -1, + -1, 187, 188, 189, -1, 191, -1, -1, 194, 195, + -1, -1, -1, 5, 6, -1, -1, 203, -1, 205, + -1, 207, 208, 15, 16, 17, 18, 19, -1, -1, + -1, -1, -1, 25, -1, 27, -1, -1, -1, 31, + -1, -1, -1, -1, -1, -1, -1, 39, -1, -1, + -1, -1, -1, 45, -1, -1, 48, -1, -1, 51, + -1, -1, -1, 55, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 65, -1, -1, 68, 69, -1, 71, + 72, 73, -1, 75, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + -1, 93, 94, 95, -1, -1, 98, 99, 100, 101, + 102, 103, 104, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 187, 188, 189, -1, 191, -1, - -1, 194, 195, -1, -1, -1, 5, 6, -1, -1, - 203, -1, 205, 206, 207, 208, 15, 16, 17, 18, - 19, -1, -1, -1, -1, -1, 25, -1, 27, -1, - -1, -1, 31, -1, -1, -1, -1, -1, -1, -1, - 39, -1, -1, -1, -1, -1, 45, -1, -1, 48, - -1, -1, 51, -1, -1, -1, 55, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 65, -1, -1, 68, - 69, -1, 71, 72, 73, -1, 75, 76, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, -1, 93, 94, 95, -1, -1, 98, - 99, 100, 101, 102, 103, 104, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 117, 118, + -1, -1, -1, -1, -1, -1, 138, -1, -1, -1, + -1, -1, -1, -1, 146, 147, 148, 149, 150, -1, + 152, -1, 154, 155, 156, 157, 158, 159, 160, 161, + 162, 163, -1, -1, -1, -1, -1, -1, 170, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 138, - -1, -1, -1, -1, -1, -1, -1, 146, 147, 148, - 149, 150, -1, 152, -1, 154, 155, 156, 157, 158, - 159, 160, 161, 162, 163, -1, -1, -1, -1, -1, - -1, 170, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 187, 188, - 189, -1, 191, -1, -1, 194, 195, -1, -1, -1, - 5, 6, -1, -1, 203, -1, 205, 206, 207, 208, - 15, 16, 17, 18, 19, -1, -1, -1, -1, -1, - 25, -1, 27, -1, -1, -1, 31, -1, -1, -1, - -1, -1, -1, -1, 39, -1, -1, -1, -1, -1, - 45, -1, -1, 48, -1, -1, 51, -1, -1, -1, - 55, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 65, -1, -1, 68, 69, -1, 71, 72, 73, -1, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, -1, 93, 94, - 95, -1, -1, 98, 99, 100, 101, 102, 103, 104, + -1, -1, -1, -1, -1, 187, 188, 189, -1, 191, + -1, -1, 194, 195, -1, -1, -1, 5, 6, -1, + -1, 203, -1, 205, 206, 207, 208, 15, 16, 17, + 18, 19, -1, -1, -1, -1, -1, 25, -1, 27, + -1, -1, -1, 31, -1, -1, -1, -1, -1, -1, + -1, 39, -1, -1, -1, -1, -1, 45, -1, -1, + 48, -1, -1, 51, -1, -1, -1, 55, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 65, -1, -1, + 68, 69, -1, 71, 72, 73, -1, 75, 76, 77, + 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, -1, 93, 94, 95, -1, -1, + 98, 99, 100, 101, 102, 103, 104, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 117, + 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 117, 118, -1, -1, -1, -1, -1, -1, + 138, -1, -1, -1, -1, -1, -1, -1, 146, 147, + 148, 149, 150, -1, 152, -1, 154, 155, 156, 157, + 158, 159, 160, 161, 162, 163, -1, -1, -1, -1, + -1, -1, 170, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 187, + 188, 189, -1, 191, -1, -1, 194, 195, -1, -1, + -1, 5, 6, -1, -1, 203, -1, 205, 206, 207, + 208, 15, 16, 17, 18, 19, -1, -1, -1, -1, + -1, 25, -1, 27, -1, -1, -1, 31, -1, -1, + -1, -1, -1, -1, -1, 39, -1, -1, -1, -1, + -1, 45, -1, -1, 48, -1, -1, 51, -1, -1, + -1, 55, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 65, -1, -1, 68, 69, -1, 71, 72, 73, + -1, 75, 76, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, -1, 93, + 94, 95, -1, -1, 98, 99, 100, 101, 102, 103, + 104, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 138, -1, -1, -1, -1, -1, -1, - -1, 146, 147, 148, 149, 150, -1, 152, -1, 154, - 155, 156, 157, 158, 159, 160, 161, 162, 163, -1, - -1, -1, -1, -1, -1, 170, -1, -1, -1, -1, + -1, -1, -1, -1, 138, -1, -1, -1, -1, -1, + -1, -1, 146, 147, 148, 149, 150, -1, 152, -1, + 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, + -1, -1, -1, -1, -1, -1, 170, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 187, 188, 189, -1, 191, -1, -1, 194, - 195, -1, -1, -1, 5, 6, -1, -1, 203, -1, - 205, 206, 207, 208, 15, 16, 17, 18, 19, -1, - -1, -1, -1, -1, 25, -1, 27, -1, -1, -1, - 31, -1, -1, -1, -1, -1, -1, -1, 39, -1, - -1, -1, -1, -1, 45, -1, -1, 48, -1, -1, - 51, -1, -1, -1, 55, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 65, -1, -1, 68, 69, -1, - 71, 72, 73, -1, 75, 76, 77, 78, 79, 80, - 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - 91, -1, 93, 94, 95, -1, -1, 98, 99, 100, - 101, 102, 103, 104, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 117, 118, -1, -1, + -1, -1, -1, 187, 188, 189, -1, 191, -1, -1, + 194, 195, -1, -1, -1, 5, 6, -1, -1, 203, + -1, 205, 206, 207, 208, 15, 16, 17, 18, 19, + -1, -1, -1, -1, -1, 25, -1, 27, -1, -1, + -1, 31, -1, -1, -1, -1, -1, -1, -1, 39, + -1, -1, -1, -1, -1, 45, -1, -1, 48, -1, + -1, 51, -1, -1, -1, 55, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 65, -1, -1, 68, 69, + -1, 71, 72, 73, -1, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, -1, 93, 94, 95, -1, -1, 98, 99, + 100, 101, 102, 103, 104, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 138, -1, -1, - -1, -1, -1, -1, -1, 146, 147, 148, 149, 150, - -1, 152, -1, 154, 155, 156, 157, 158, 159, 160, - 161, 162, 163, -1, -1, -1, -1, -1, -1, 170, + -1, -1, -1, -1, -1, -1, -1, -1, 138, -1, + -1, -1, -1, -1, -1, -1, 146, 147, 148, 149, + 150, -1, 152, -1, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, -1, -1, -1, -1, -1, -1, + 170, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 187, 188, 189, + -1, 191, -1, -1, 194, 195, -1, -1, -1, 5, + 6, -1, -1, 203, -1, 205, 206, 207, 208, 15, + 16, 17, 18, 19, -1, -1, -1, -1, -1, 25, + -1, 27, -1, -1, -1, 31, -1, -1, -1, -1, + -1, -1, -1, 39, -1, -1, -1, -1, -1, 45, + -1, -1, 48, -1, -1, 51, -1, -1, -1, 55, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, + -1, -1, 68, 69, -1, 71, 72, 73, -1, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, 88, 89, 90, 91, -1, 93, 94, 95, + -1, -1, 98, 99, 100, 101, 102, 103, 104, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 187, 188, 189, -1, - 191, -1, -1, 194, 195, -1, -1, -1, 5, 6, - -1, -1, 203, -1, 205, 206, 207, 208, 15, 16, - 17, 18, 19, -1, -1, -1, -1, -1, 25, -1, - 27, -1, -1, -1, 31, -1, -1, -1, -1, -1, - -1, -1, 39, -1, -1, -1, -1, -1, 45, -1, - -1, 48, -1, -1, 51, -1, -1, -1, 55, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 65, -1, - -1, 68, 69, -1, 71, 72, 73, -1, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, -1, 93, 94, 95, -1, - -1, 98, 99, 100, 101, 102, 103, 104, -1, -1, + -1, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 138, -1, -1, -1, -1, -1, -1, -1, + 146, 147, 148, 149, 150, -1, 152, -1, 154, 155, + 156, 157, 158, 159, 160, 161, 162, 163, -1, -1, + -1, -1, -1, -1, 170, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 138, -1, -1, -1, -1, -1, -1, -1, 146, - 147, 148, 149, 150, -1, 152, -1, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, -1, -1, -1, - -1, -1, -1, 170, -1, -1, -1, -1, -1, -1, + -1, 187, 188, 189, -1, 191, -1, -1, 194, 195, + -1, -1, -1, 5, 6, -1, -1, 203, -1, 205, + 206, 207, 208, 15, 16, 17, 18, 19, -1, -1, + -1, -1, -1, 25, -1, 27, -1, -1, -1, 31, + -1, -1, -1, -1, -1, -1, -1, 39, -1, -1, + -1, -1, -1, 45, -1, -1, 48, -1, -1, 51, + -1, -1, -1, 55, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 65, -1, -1, 68, 69, -1, 71, + 72, 73, -1, 75, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + -1, 93, 94, 95, -1, -1, 98, 99, 100, 101, + 102, 103, 104, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 187, 188, 189, -1, 191, -1, -1, 194, 195, -1, - -1, -1, 5, 6, -1, -1, 203, -1, 205, 206, - 207, 208, 15, 16, 17, 18, 19, -1, -1, -1, - -1, -1, 25, -1, 27, -1, -1, -1, 31, -1, - -1, -1, -1, -1, -1, -1, 39, -1, -1, -1, - -1, -1, 45, -1, -1, 48, -1, -1, 51, -1, - -1, -1, 55, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 65, -1, -1, 68, 69, -1, 71, 72, - 73, -1, 75, 76, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 88, 89, 90, 91, -1, - 93, 94, 95, -1, -1, 98, 99, 100, 101, 102, - 103, 104, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 117, 118, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 138, -1, -1, -1, + -1, -1, -1, -1, 146, 147, 148, 149, 150, -1, + 152, -1, 154, 155, 156, 157, 158, 159, 160, 161, + 162, 163, -1, -1, -1, -1, -1, -1, 170, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 138, -1, -1, -1, -1, - -1, -1, -1, 146, 147, 148, 149, 150, -1, 152, - -1, 154, 155, 156, 157, 158, 159, 160, 161, 162, - 163, -1, -1, -1, -1, -1, -1, 170, -1, -1, + -1, -1, -1, -1, -1, 187, 188, 189, -1, 191, + -1, -1, 194, 195, -1, -1, -1, 5, 6, -1, + -1, 203, -1, 205, 206, 207, 208, 15, 16, 17, + 18, 19, -1, -1, -1, -1, -1, 25, -1, 27, + -1, -1, -1, 31, -1, -1, -1, -1, -1, -1, + -1, 39, -1, -1, -1, -1, -1, 45, -1, -1, + 48, -1, -1, 51, -1, -1, -1, 55, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 65, -1, -1, + 68, 69, -1, 71, 72, 73, -1, 75, 76, 77, + 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, -1, 93, 94, 95, -1, -1, + 98, 99, 100, 101, 102, 103, 104, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 117, + 118, -1, -1, -1, -1, -1, -1, -1, 126, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 187, 188, 189, -1, 191, -1, - -1, 194, 195, -1, -1, -1, 5, 6, -1, -1, - 203, -1, 205, 206, 207, 208, 15, 16, 17, 18, - 19, -1, -1, -1, -1, -1, 25, -1, 27, -1, - -1, -1, 31, -1, -1, -1, -1, -1, -1, -1, - 39, -1, -1, -1, -1, -1, 45, -1, -1, 48, - -1, -1, 51, -1, -1, -1, 55, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 65, -1, -1, 68, - 69, -1, 71, 72, 73, -1, 75, 76, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, -1, 93, 94, 95, -1, -1, 98, - 99, 100, 101, 102, 103, 104, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 117, 118, - -1, -1, -1, -1, -1, -1, -1, 126, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 138, - -1, -1, -1, -1, -1, -1, -1, 146, 147, 148, - 149, 150, -1, 152, -1, 154, 155, 156, 157, 158, - 159, 160, 161, 162, 163, -1, -1, -1, -1, -1, - -1, 170, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 187, 188, - 189, -1, 191, -1, -1, 194, 195, -1, -1, -1, - 5, 6, -1, -1, 203, -1, 205, -1, 207, 208, - 15, 16, 17, 18, 19, -1, -1, -1, -1, -1, - 25, -1, 27, -1, -1, -1, 31, -1, -1, -1, - -1, -1, -1, -1, 39, -1, -1, -1, -1, -1, - 45, -1, -1, 48, -1, -1, 51, -1, -1, -1, - 55, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 65, -1, -1, 68, 69, -1, 71, 72, 73, -1, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, -1, 93, 94, - 95, -1, -1, 98, 99, 100, 101, 102, 103, 104, + 138, -1, -1, -1, -1, -1, -1, -1, 146, 147, + 148, 149, 150, -1, 152, -1, 154, 155, 156, 157, + 158, 159, 160, 161, 162, 163, -1, -1, -1, -1, + -1, -1, 170, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 187, + 188, 189, -1, 191, -1, -1, 194, 195, -1, -1, + -1, 5, 6, -1, -1, 203, -1, 205, -1, 207, + 208, 15, 16, 17, 18, 19, -1, -1, -1, -1, + -1, 25, -1, 27, -1, -1, -1, 31, -1, -1, + -1, -1, -1, -1, -1, 39, -1, -1, -1, -1, + -1, 45, -1, -1, 48, -1, -1, 51, -1, -1, + -1, 55, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 65, -1, -1, 68, 69, -1, 71, 72, 73, + -1, 75, 76, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, -1, 93, + 94, 95, -1, -1, 98, 99, 100, 101, 102, 103, + 104, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 117, 118, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 138, -1, -1, -1, -1, -1, + -1, -1, 146, 147, 148, 149, 150, -1, 152, -1, + 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, + -1, -1, -1, -1, -1, -1, 170, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 138, -1, -1, -1, -1, -1, -1, - -1, 146, 147, 148, 149, 150, -1, 152, -1, 154, - 155, 156, 157, 158, 159, 160, 161, 162, 163, -1, - -1, -1, -1, -1, -1, 170, -1, -1, -1, -1, + -1, -1, -1, 187, 188, 189, -1, 191, -1, -1, + 194, 195, -1, -1, -1, 5, 6, -1, -1, 203, + -1, 205, -1, 207, 208, 15, 16, 17, 18, 19, + -1, -1, -1, -1, -1, 25, -1, 27, -1, -1, + -1, 31, -1, -1, -1, -1, -1, -1, -1, 39, + -1, -1, -1, -1, -1, 45, -1, -1, 48, -1, + -1, 51, -1, -1, -1, 55, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 65, -1, -1, 68, 69, + -1, 71, 72, 73, -1, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, -1, 93, 94, 95, -1, -1, 98, 99, + 100, 101, 102, 103, 104, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 117, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 187, 188, 189, -1, 191, -1, -1, 194, - 195, -1, -1, -1, 5, 6, -1, -1, 203, -1, - 205, -1, 207, 208, 15, 16, 17, 18, 19, -1, - -1, -1, -1, -1, 25, -1, 27, -1, -1, -1, - 31, -1, -1, -1, -1, -1, -1, -1, 39, -1, - -1, -1, -1, -1, 45, -1, -1, 48, -1, -1, - 51, -1, -1, -1, 55, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 65, -1, -1, 68, 69, -1, - 71, 72, 73, -1, 75, 76, 77, 78, 79, 80, + -1, -1, -1, -1, -1, -1, -1, -1, 138, -1, + -1, -1, -1, -1, -1, -1, 146, 147, 148, 149, + 150, -1, 152, -1, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 21, 22, -1, -1, 19, -1, + 170, -1, -1, -1, 25, -1, -1, -1, -1, -1, + 31, -1, -1, -1, -1, -1, -1, 187, 188, 189, + 41, 191, -1, -1, 194, 195, -1, -1, 49, -1, + 21, 22, -1, 203, -1, 205, -1, 207, 208, -1, + -1, -1, -1, 64, -1, -1, -1, -1, -1, -1, + 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - 91, -1, 93, 94, 95, -1, -1, 98, 99, 100, - 101, 102, 103, 104, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 117, 118, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 138, -1, -1, - -1, -1, -1, -1, -1, 146, 147, 148, 149, 150, - -1, 152, -1, 154, 155, 156, 157, 158, 159, 160, - 161, 162, 163, 21, 22, -1, -1, 19, -1, 170, - -1, -1, -1, 25, -1, -1, -1, -1, -1, 31, - -1, -1, -1, -1, -1, -1, 187, 188, 189, 41, - 191, -1, -1, 194, 195, -1, -1, 49, -1, 21, - 22, -1, 203, -1, 205, -1, 207, 208, -1, -1, - -1, -1, 64, -1, -1, -1, -1, -1, -1, 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, -1, -1, -1, -1, -1, 115, 116, 117, - 118, 119, -1, -1, 122, 123, 124, 125, -1, 127, - 128, 129, 130, 131, -1, 133, 134, -1, -1, -1, - -1, 139, 140, 141, -1, -1, 138, 145, -1, -1, - -1, 21, 22, 115, 116, 117, 118, 119, -1, 151, - 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, - 162, 133, 134, -1, -1, -1, -1, 139, 140, 141, - -1, -1, 180, 145, 182, 183, 184, 185, 186, 187, - 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 202, 203, -1, -1, 206, -1, - -1, -1, -1, -1, -1, 207, -1, -1, 180, -1, - 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 202, 203, -1, -1, 206, 115, 116, 117, 118, 119, - 21, 22, 122, 123, 124, 125, -1, 127, 128, 129, - 130, 131, -1, 133, 134, -1, -1, -1, -1, 139, - 140, 141, -1, -1, -1, 145, -1, -1, -1, -1, - -1, 21, 22, -1, -1, -1, -1, -1, -1, -1, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, + 101, 102, 103, -1, -1, -1, -1, -1, 115, 116, + 117, 118, 119, -1, -1, 122, 123, 124, 125, -1, + 127, 128, 129, 130, 131, -1, 133, 134, -1, -1, + -1, -1, 139, 140, 141, -1, -1, 138, 145, -1, + -1, -1, 21, 22, 115, 116, 117, 118, 119, -1, + 151, 122, 123, 124, 125, -1, 127, 128, 129, 130, + 131, 162, 133, 134, -1, -1, -1, -1, 139, 140, + 141, -1, -1, 180, 145, 182, 183, 184, 185, 186, + 187, 188, 189, 190, 191, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 202, 203, -1, -1, 206, + -1, -1, -1, -1, -1, -1, 207, -1, -1, 180, + -1, 182, 183, 184, 185, 186, 187, 188, 189, 190, + 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 202, 203, -1, -1, 206, 115, 116, 117, 118, + 119, 21, 22, 122, 123, 124, 125, -1, 127, 128, + 129, 130, 131, -1, 133, 134, -1, -1, -1, -1, + 139, 140, 141, -1, -1, -1, 145, -1, -1, -1, + -1, -1, 21, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 180, -1, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 202, 203, -1, -1, 206, -1, -1, -1, - -1, -1, -1, -1, 115, 116, 117, 118, 119, -1, - -1, 122, 123, 124, 125, -1, 127, 128, 129, 130, - 131, -1, 133, 134, -1, -1, -1, -1, 139, 140, - 141, -1, -1, -1, 145, 115, 116, 117, 118, 119, - 21, 22, 122, 123, 124, 125, -1, 127, 128, 129, + -1, 180, -1, 182, 183, 184, 185, 186, 187, 188, + 189, 190, 191, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 202, 203, -1, -1, 206, -1, -1, + -1, -1, -1, -1, -1, 115, 116, 117, 118, 119, + -1, -1, 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, 133, 134, -1, -1, -1, -1, 139, - 140, 141, -1, -1, -1, 145, -1, -1, -1, 180, - -1, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 202, 203, -1, -1, 206, -1, -1, -1, -1, + 140, 141, -1, -1, -1, 145, 115, 116, 117, 118, + 119, 21, 22, 122, 123, 124, 125, -1, 127, 128, + 129, 130, 131, -1, 133, 134, -1, -1, -1, -1, + 139, 140, 141, -1, -1, -1, 145, -1, -1, -1, 180, -1, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 202, 203, -1, -1, 206, -1, -1, -1, - -1, -1, 21, 22, 115, 116, 117, 118, 119, -1, - -1, 122, 123, 124, 125, -1, 127, 128, 129, 130, - 131, -1, 133, 134, -1, -1, -1, -1, 139, 140, - 141, -1, -1, -1, 145, 21, 22, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 180, - -1, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 202, 203, -1, -1, 206, 115, 116, 117, 118, - 119, -1, -1, 122, 123, 124, 125, -1, 127, 128, - 129, 130, 131, -1, 133, 134, -1, -1, -1, -1, - 139, 140, 141, -1, -1, -1, 145, 21, 22, 115, - 116, 117, 118, 119, -1, -1, 122, 123, 124, 125, - -1, 127, 128, 129, 130, 131, -1, 133, 134, -1, - -1, -1, -1, 139, 140, 141, -1, -1, -1, 145, -1, 180, -1, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 202, 203, -1, -1, 206, -1, -1, - -1, -1, -1, -1, 180, -1, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 202, 203, -1, -1, - 206, 115, 116, 117, 118, 119, 21, 22, 122, 123, - 124, 125, -1, 127, 128, 129, 130, 131, -1, 133, - 134, -1, -1, -1, -1, 139, 140, 141, -1, -1, - -1, 145, -1, -1, -1, -1, -1, 21, 22, -1, + -1, -1, -1, 21, 22, 115, 116, 117, 118, 119, + -1, -1, 122, 123, 124, 125, -1, 127, 128, 129, + 130, 131, -1, 133, 134, -1, -1, -1, -1, 139, + 140, 141, -1, -1, -1, 145, 21, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 180, -1, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 202, 203, - -1, -1, 206, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 180, -1, 182, 183, 184, 185, 186, 187, 188, 189, + 190, 191, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 202, 203, -1, -1, 206, 115, 116, 117, + 118, 119, -1, -1, 122, 123, 124, 125, -1, 127, + 128, 129, 130, 131, -1, 133, 134, -1, -1, -1, + -1, 139, 140, 141, -1, -1, -1, 145, 21, 22, 115, 116, 117, 118, 119, -1, -1, 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, 133, 134, -1, -1, -1, -1, 139, 140, 141, -1, -1, -1, - 145, 115, 116, 117, 118, 119, 21, 22, 122, 123, - 124, 125, -1, 127, 128, 129, 130, 131, -1, 133, - 134, -1, -1, -1, -1, 139, 140, 141, -1, -1, - -1, 145, -1, -1, -1, 180, -1, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 202, 203, -1, - -1, 206, -1, -1, -1, -1, 180, -1, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 202, 203, - -1, -1, 206, -1, -1, -1, -1, -1, 21, 22, - 115, 116, 117, 118, 119, -1, -1, 122, 123, 124, - 125, -1, 127, 128, 129, 130, 131, -1, 133, 134, - -1, -1, -1, -1, 139, 140, 141, -1, -1, -1, - 145, 21, 22, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 145, -1, 180, -1, 182, 183, 184, 185, 186, 187, + 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 202, 203, -1, -1, 206, -1, -1, -1, -1, -1, -1, 180, -1, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 202, 203, -1, - -1, 206, 115, 116, 117, 118, 119, -1, -1, 122, + -1, 206, 115, 116, 117, 118, 119, 21, 22, 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, 133, 134, -1, -1, -1, -1, 139, 140, 141, -1, - -1, -1, 145, 21, 22, 115, 116, 117, 118, 119, - -1, -1, 122, 123, 124, 125, -1, 127, 128, 129, - 130, 131, -1, 133, 134, -1, -1, -1, -1, 139, - 140, 141, -1, -1, -1, 145, -1, 180, -1, 182, + -1, -1, 145, -1, -1, -1, -1, -1, 21, 22, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 180, -1, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 202, 203, -1, -1, 206, -1, -1, -1, -1, -1, -1, - 180, -1, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 202, 203, -1, -1, 206, 115, 116, 117, - 118, 119, 21, 22, 122, 123, 124, 125, -1, 127, - 128, 129, 130, 131, -1, 133, 134, -1, -1, -1, - -1, 139, 140, 141, -1, -1, -1, 145, -1, -1, - -1, -1, -1, 21, 22, -1, -1, -1, -1, -1, + -1, 115, 116, 117, 118, 119, -1, -1, 122, 123, + 124, 125, -1, 127, 128, 129, 130, 131, -1, 133, + 134, -1, -1, -1, -1, 139, 140, 141, -1, -1, + -1, 145, 115, 116, 117, 118, 119, 21, 22, 122, + 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, + 133, 134, -1, -1, -1, -1, 139, 140, 141, -1, + -1, -1, 145, -1, -1, -1, 180, -1, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 202, 203, + -1, -1, 206, -1, -1, -1, -1, 180, -1, 182, + 183, 184, 185, 186, 187, 188, 189, 190, 191, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 202, + 203, -1, -1, 206, -1, -1, -1, -1, -1, 21, + 22, 115, 116, 117, 118, 119, -1, -1, 122, 123, + 124, 125, -1, 127, 128, 129, 130, 131, -1, 133, + 134, -1, -1, -1, -1, 139, 140, 141, -1, -1, + -1, 145, 21, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 180, -1, 182, 183, 184, 185, 186, 187, - 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 202, 203, -1, -1, 206, -1, - -1, -1, -1, -1, -1, -1, 115, 116, 117, 118, - 119, -1, -1, 122, 123, 124, 125, -1, 127, 128, - 129, 130, 131, -1, 133, 134, -1, -1, -1, -1, - 139, 140, 141, -1, -1, -1, 145, 115, 116, 117, - 118, 119, 21, 22, 122, 123, 124, 125, -1, 127, - 128, 129, 130, 131, -1, 133, 134, -1, -1, -1, - -1, 139, 140, 141, -1, -1, -1, 145, -1, -1, - -1, 180, -1, 182, 183, 184, 185, 186, 187, 188, - 189, 190, 191, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 202, 203, -1, -1, 206, -1, -1, - -1, -1, 180, -1, 182, 183, 184, 185, 186, 187, - 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 202, 203, -1, -1, 206, -1, - -1, -1, -1, -1, 21, 22, 115, 116, 117, 118, + -1, -1, -1, -1, -1, -1, 180, -1, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 202, 203, + -1, -1, 206, 115, 116, 117, 118, 119, -1, -1, + 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, + -1, 133, 134, -1, -1, -1, -1, 139, 140, 141, + -1, -1, -1, 145, 21, 22, 115, 116, 117, 118, 119, -1, -1, 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, 133, 134, -1, -1, -1, -1, - 139, 140, 141, -1, -1, -1, 145, 21, 22, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 139, 140, 141, -1, -1, -1, 145, -1, 180, -1, + 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 202, 203, -1, -1, 206, -1, -1, -1, -1, -1, -1, 180, -1, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 202, 203, -1, -1, 206, 115, 116, - 117, 118, 119, -1, -1, 122, 123, 124, 125, -1, + 117, 118, 119, 21, 22, 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, 133, 134, -1, -1, - -1, -1, 139, 140, 141, -1, -1, -1, 145, 21, - 22, 115, 116, 117, 118, 119, -1, -1, 122, 123, - 124, 125, -1, 127, 128, 129, 130, 131, -1, 133, - 134, -1, -1, -1, -1, 139, 140, 141, -1, -1, - -1, 145, -1, 180, -1, 182, 183, 184, 185, 186, + -1, -1, 139, 140, 141, -1, -1, -1, 145, -1, + -1, -1, -1, -1, 21, 22, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 180, -1, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 202, 203, -1, -1, 206, - -1, -1, -1, -1, -1, -1, 180, -1, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 202, 203, - -1, -1, 206, 115, 116, 117, 118, 119, 21, 22, - 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, - -1, 133, 134, -1, -1, -1, -1, 139, 140, 141, - -1, -1, -1, 145, -1, -1, -1, -1, -1, 21, - 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 115, 116, 117, + 118, 119, -1, -1, 122, 123, 124, 125, -1, 127, + 128, 129, 130, 131, -1, 133, 134, -1, -1, -1, + -1, 139, 140, 141, -1, -1, -1, 145, 115, 116, + 117, 118, 119, 21, 22, 122, 123, 124, 125, -1, + 127, 128, 129, 130, 131, -1, 133, 134, -1, -1, + -1, -1, 139, 140, 141, -1, -1, -1, 145, -1, + -1, -1, 180, -1, 182, 183, 184, 185, 186, 187, + 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 202, 203, -1, -1, 206, -1, + -1, -1, -1, 180, -1, 182, 183, 184, 185, 186, + 187, 188, 189, 190, 191, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 202, 203, -1, -1, 206, + -1, -1, -1, -1, -1, 21, 22, 115, 116, 117, + 118, 119, -1, -1, 122, 123, 124, 125, -1, 127, + 128, 129, 130, 131, -1, 133, 134, -1, -1, -1, + -1, 139, 140, 141, -1, -1, -1, 145, 21, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 180, -1, - 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 202, 203, -1, -1, 206, -1, -1, -1, -1, -1, - -1, -1, 115, 116, 117, 118, 119, -1, -1, 122, - 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, - 133, 134, -1, -1, -1, -1, 139, 140, 141, -1, - -1, -1, 145, 115, 116, 117, 118, 119, 21, 22, - 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, - -1, 133, 134, -1, -1, -1, -1, 139, 140, 141, - -1, -1, -1, 145, -1, -1, -1, 180, -1, 182, - 183, 184, 185, 186, 187, 188, 189, 190, 191, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 202, - 203, -1, -1, 206, -1, -1, -1, -1, 180, -1, - 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 202, 203, -1, -1, 206, -1, -1, -1, -1, -1, + -1, -1, 180, -1, 182, 183, 184, 185, 186, 187, + 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 202, 203, -1, -1, 206, 115, + 116, 117, 118, 119, -1, -1, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, 133, 134, -1, + -1, -1, -1, 139, 140, 141, -1, -1, -1, 145, 21, 22, 115, 116, 117, 118, 119, -1, -1, 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, 133, 134, -1, -1, -1, -1, 139, 140, 141, -1, - -1, -1, 145, 21, 22, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 180, -1, 182, + -1, -1, 145, -1, 180, -1, 182, 183, 184, 185, + 186, 187, 188, 189, 190, 191, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 202, 203, -1, -1, + 206, -1, -1, -1, -1, -1, -1, 180, -1, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 202, - 203, -1, -1, 206, 115, 116, 117, 118, 119, -1, - -1, 122, 123, 124, 125, -1, 127, 128, 129, 130, + 203, -1, -1, 206, 115, 116, 117, 118, 119, 21, + 22, 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, 133, 134, -1, -1, -1, -1, 139, 140, - 141, -1, -1, -1, 145, 21, 22, 115, 116, 117, - 118, 119, -1, -1, 122, 123, 124, 125, -1, 127, - 128, 129, 130, 131, -1, 133, 134, -1, -1, -1, - -1, 139, 140, 141, -1, -1, -1, 145, -1, 180, + 141, -1, -1, -1, 145, -1, -1, -1, -1, -1, + 21, 22, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 180, -1, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 202, 203, -1, -1, 206, -1, -1, -1, -1, - -1, -1, 180, -1, 182, 183, 184, 185, 186, 187, - 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 202, 203, -1, -1, 206, 115, - 116, 117, 118, 119, 21, 22, 122, 123, 124, 125, - -1, 127, 128, 129, 130, 131, -1, 133, 134, -1, - -1, -1, -1, 139, 140, 141, -1, -1, -1, 145, - -1, -1, -1, -1, -1, 21, 22, -1, -1, -1, + -1, -1, -1, 115, 116, 117, 118, 119, -1, -1, + 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, + -1, 133, 134, -1, -1, -1, -1, 139, 140, 141, + -1, -1, -1, 145, 115, 116, 117, 118, 119, 21, + 22, 122, 123, 124, 125, -1, 127, 128, 129, 130, + 131, -1, 133, 134, -1, -1, -1, -1, 139, 140, + 141, -1, -1, -1, 145, -1, -1, -1, 180, -1, + 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 202, 203, -1, -1, 206, -1, -1, -1, -1, 180, + -1, 182, 183, 184, 185, 186, 187, 188, 189, 190, + 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 202, 203, -1, -1, 206, -1, -1, -1, -1, + -1, 21, 22, 115, 116, 117, 118, 119, -1, -1, + 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, + -1, 133, 134, -1, -1, -1, -1, 139, 140, 141, + -1, -1, -1, 145, 21, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 180, -1, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 202, 203, -1, -1, - 206, -1, -1, -1, -1, -1, -1, -1, 115, 116, + -1, -1, -1, -1, -1, -1, -1, -1, 180, -1, + 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 202, 203, -1, -1, 206, 115, 116, 117, 118, 119, + -1, -1, 122, 123, 124, 125, -1, 127, 128, 129, + 130, 131, -1, 133, 134, -1, -1, -1, -1, 139, + 140, 141, -1, -1, -1, 145, 21, 22, 115, 116, 117, 118, 119, -1, -1, 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, 133, 134, -1, -1, - -1, -1, 139, 140, 141, -1, -1, -1, 145, 115, - 116, 117, 118, 119, 21, 22, 122, 123, 124, 125, - -1, 127, 128, 129, 130, 131, -1, 133, 134, -1, - -1, -1, -1, 139, 140, 141, -1, -1, -1, 145, + -1, -1, 139, 140, 141, -1, -1, -1, 145, -1, + 180, -1, 182, 183, 184, 185, 186, 187, 188, 189, + 190, 191, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 202, 203, -1, -1, 206, -1, -1, -1, -1, -1, -1, 180, -1, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 202, 203, -1, -1, 206, - -1, -1, -1, -1, 180, -1, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 202, 203, -1, -1, - 206, -1, -1, -1, -1, -1, 21, 22, 115, 116, - 117, 118, 119, -1, -1, 122, 123, 124, 125, -1, - 127, 128, 129, 130, 131, -1, 133, 134, -1, -1, - -1, -1, 139, 140, 141, -1, -1, -1, 145, 21, - 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 115, 116, 117, 118, 119, 21, 22, 122, 123, 124, + 125, -1, 127, 128, 129, 130, 131, -1, 133, 134, + -1, -1, -1, -1, 139, 140, 141, -1, -1, -1, + 145, -1, -1, -1, -1, -1, 21, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 180, -1, 182, 183, 184, 185, 186, - 187, 188, 189, 190, 191, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 202, 203, -1, -1, 206, - 115, 116, 117, 118, 119, -1, -1, 122, 123, 124, + -1, -1, -1, -1, -1, 180, -1, 182, 183, 184, + 185, 186, 187, 188, 189, 190, 191, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 202, 203, -1, + -1, 206, -1, -1, -1, -1, -1, -1, -1, 115, + 116, 117, 118, 119, -1, -1, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, 133, 134, -1, + -1, -1, -1, 139, 140, 141, -1, -1, -1, 145, + 115, 116, 117, 118, 119, 21, 22, 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, 133, 134, -1, -1, -1, -1, 139, 140, 141, -1, -1, -1, - 145, 21, 22, 115, 116, 117, 118, 119, -1, -1, - 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, - -1, 133, 134, -1, -1, -1, -1, 139, 140, 141, - -1, -1, -1, 145, -1, 180, -1, 182, 183, 184, + 145, -1, -1, -1, 180, -1, 182, 183, 184, 185, + 186, 187, 188, 189, 190, 191, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 202, 203, -1, -1, + 206, -1, -1, -1, -1, 180, -1, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 202, 203, -1, - -1, 206, -1, -1, -1, -1, -1, -1, 180, -1, - 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 202, 203, -1, -1, 206, 115, 116, 117, 118, 119, - 21, 22, 122, 123, 124, 125, -1, 127, 128, 129, - 130, 131, -1, 133, 134, -1, -1, -1, -1, 139, - 140, 141, -1, -1, -1, 145, -1, -1, -1, -1, - -1, 21, 22, -1, -1, -1, -1, -1, -1, -1, + -1, 206, -1, -1, -1, -1, -1, 21, 22, 115, + 116, 117, 118, 119, -1, -1, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, 133, 134, -1, + -1, -1, -1, 139, 140, 141, -1, -1, -1, 145, + 21, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 180, -1, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 202, 203, -1, -1, 206, -1, -1, -1, - -1, -1, -1, -1, 115, 116, 117, 118, 119, -1, + -1, -1, -1, -1, 180, -1, 182, 183, 184, 185, + 186, 187, 188, 189, 190, 191, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 202, 203, -1, -1, + 206, 115, 116, 117, 118, 119, -1, -1, 122, 123, + 124, 125, -1, 127, 128, 129, 130, 131, -1, 133, + 134, -1, -1, -1, -1, 139, 140, 141, -1, -1, + -1, 145, 21, 22, 115, 116, 117, 118, 119, -1, -1, 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, 133, 134, -1, -1, -1, -1, 139, 140, - 141, 21, 22, -1, 145, 115, 116, 117, 118, 119, - -1, -1, 122, 123, 124, 125, -1, 127, 128, 129, - 130, 131, -1, 133, 134, -1, -1, -1, -1, 139, - 140, 141, 21, 22, -1, 145, -1, -1, -1, 180, + 141, -1, -1, -1, 145, -1, 180, -1, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 202, 203, + -1, -1, 206, -1, -1, -1, -1, -1, -1, 180, -1, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 202, 203, 204, -1, -1, -1, -1, -1, -1, - 180, -1, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 202, 203, 204, 115, 116, 117, 118, 119, + -1, 202, 203, -1, -1, 206, 115, 116, 117, 118, + 119, 21, 22, 122, 123, 124, 125, -1, 127, 128, + 129, 130, 131, -1, 133, 134, -1, -1, -1, -1, + 139, 140, 141, -1, -1, -1, 145, -1, -1, -1, + -1, -1, 21, 22, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 180, -1, 182, 183, 184, 185, 186, 187, 188, + 189, 190, 191, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 202, 203, -1, -1, 206, -1, -1, + -1, -1, -1, -1, -1, 115, 116, 117, 118, 119, -1, -1, 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, 133, 134, -1, -1, -1, -1, 139, 140, 141, 21, 22, -1, 145, 115, 116, 117, 118, @@ -3680,164 +3681,189 @@ static const yytype_int16 yycheck[] = -1, -1, -1, 202, 203, 204, 115, 116, 117, 118, 119, -1, -1, 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, 133, 134, -1, -1, -1, -1, - 139, 140, 141, -1, -1, -1, 145, 115, 116, 117, - 118, 119, 21, 22, 122, 123, 124, 125, -1, 127, + 139, 140, 141, 21, 22, -1, 145, 115, 116, 117, + 118, 119, -1, -1, 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, 133, 134, -1, -1, -1, - -1, 139, 140, 141, -1, -1, -1, 145, -1, -1, + -1, 139, 140, 141, 21, 22, -1, 145, -1, -1, -1, 180, -1, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 202, 203, 204, -1, -1, -1, -1, -1, -1, 180, -1, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 202, 203, 204, -1, 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, 21, 22, - 139, 140, 141, 142, 143, 144, 145, -1, -1, -1, - -1, -1, -1, -1, -1, 38, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, - 22, -1, -1, 172, -1, -1, -1, -1, -1, -1, - 179, 180, -1, 182, 183, 184, 185, 186, 187, 188, - 189, 190, 191, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 202, 203, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 107, 108, 109, 110, 111, 112, - 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, - 123, 124, -1, -1, 127, 128, 129, -1, -1, 132, - 133, 134, 135, 136, -1, -1, 139, 140, 141, 142, - 143, 144, 145, 115, 116, 117, 118, 119, 21, 22, - 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, - -1, 133, 134, -1, -1, 137, -1, 139, 140, 141, - -1, -1, -1, 145, -1, -1, -1, 180, -1, 182, - 183, 184, 185, 186, 187, 188, 189, 190, 191, -1, - -1, 194, 195, -1, -1, -1, -1, -1, -1, 202, - 203, -1, -1, -1, -1, -1, -1, -1, 180, -1, - 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + -1, -1, -1, -1, 202, 203, 204, 115, 116, 117, + 118, 119, -1, -1, 122, 123, 124, 125, -1, 127, + 128, 129, 130, 131, -1, 133, 134, -1, -1, -1, + -1, 139, 140, 141, -1, -1, -1, 145, 115, 116, + 117, 118, 119, 21, 22, 122, 123, 124, 125, -1, + 127, 128, 129, 130, 131, -1, 133, 134, -1, -1, + -1, -1, 139, 140, 141, -1, -1, -1, 145, -1, + -1, -1, 180, -1, 182, 183, 184, 185, 186, 187, + 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 202, 203, 204, -1, -1, -1, + -1, -1, -1, 180, -1, 182, 183, 184, 185, 186, + 187, 188, 189, 190, 191, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 202, 203, 204, -1, 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, 21, + 22, 139, 140, 141, 142, 143, 144, 145, -1, -1, + -1, -1, -1, -1, -1, -1, 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 202, 203, -1, -1, -1, -1, -1, 21, 22, -1, - -1, -1, 115, 116, 117, 118, 119, -1, -1, 122, - 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, - 133, 134, -1, -1, -1, -1, 139, 140, 141, 21, - 22, -1, 145, -1, -1, -1, -1, -1, -1, -1, + 21, 22, -1, -1, 172, -1, -1, -1, -1, -1, + -1, 179, 180, -1, 182, 183, 184, 185, 186, 187, + 188, 189, 190, 191, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 202, 203, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 172, - -1, -1, -1, -1, -1, -1, -1, 180, -1, 182, - 183, 184, 185, 186, 187, 188, 189, 190, 191, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 202, - 203, 115, 116, 117, 118, 119, -1, -1, 122, 123, - 124, 125, -1, 127, 128, 129, 130, 131, -1, 133, - 134, 21, 22, -1, -1, 139, 140, 141, -1, -1, - -1, 145, -1, 115, 116, 117, 118, 119, -1, -1, - 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, - -1, 133, 134, 21, 22, -1, -1, 139, 140, 141, - -1, -1, -1, 145, -1, -1, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 202, 203, - 172, -1, -1, -1, -1, -1, -1, -1, 180, -1, + -1, -1, -1, -1, -1, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 123, 124, -1, -1, 127, 128, 129, -1, -1, + 132, 133, 134, 135, 136, -1, -1, 139, 140, 141, + 142, 143, 144, 145, 115, 116, 117, 118, 119, 21, + 22, 122, 123, 124, 125, -1, 127, 128, 129, 130, + 131, -1, 133, 134, -1, -1, 137, -1, 139, 140, + 141, -1, -1, -1, 145, -1, -1, -1, 180, -1, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - -1, -1, -1, -1, -1, 115, 116, 117, 118, 119, - 202, 203, 122, 123, 124, 125, -1, 127, 128, 129, - 130, 131, -1, 133, 134, 21, 22, -1, -1, 139, - 140, 141, -1, -1, -1, 145, -1, 115, 116, 117, - 118, 119, -1, -1, 122, 123, 124, 125, -1, 127, - 128, 129, 130, 131, -1, 133, 134, -1, 168, 21, - 22, 139, 140, 141, -1, -1, -1, 145, -1, -1, - 180, -1, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 202, 203, 172, -1, -1, -1, -1, -1, - -1, -1, 180, -1, 182, 183, 184, 185, 186, 187, - 188, 189, 190, 191, -1, -1, -1, -1, -1, 115, - 116, 117, 118, 119, 202, 203, 122, 123, 124, 125, - -1, 127, 128, 129, 130, 131, -1, 133, 134, -1, - -1, 21, 22, 139, 140, 141, -1, -1, -1, 145, + -1, -1, 194, 195, -1, -1, -1, -1, -1, -1, + 202, 203, -1, -1, -1, -1, -1, -1, -1, 180, + -1, 182, 183, 184, 185, 186, 187, 188, 189, 190, + 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 202, 203, -1, -1, -1, -1, -1, 21, 22, -1, -1, -1, 115, 116, 117, 118, 119, -1, -1, 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, - -1, 133, 134, -1, -1, -1, 172, 139, 140, 141, - -1, -1, -1, 145, 180, -1, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 202, 203, -1, -1, + -1, 133, 134, -1, -1, -1, -1, 139, 140, 141, + 21, 22, -1, 145, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 172, -1, -1, -1, -1, -1, -1, -1, 180, -1, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - 21, 22, -1, -1, -1, 115, 116, 117, 118, 119, - 202, 203, 122, 123, 124, 125, -1, 127, 128, 129, - 130, 131, -1, 133, 134, -1, -1, -1, -1, 139, - 140, 141, -1, -1, -1, 145, 21, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 172, -1, -1, -1, -1, -1, -1, -1, - 180, -1, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 202, 203, 115, 116, 117, 118, 119, -1, + 202, 203, 115, 116, 117, 118, 119, -1, -1, 122, + 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, + 133, 134, 21, 22, -1, -1, 139, 140, 141, -1, + -1, -1, 145, -1, 115, 116, 117, 118, 119, -1, -1, 122, 123, 124, 125, -1, 127, 128, 129, 130, - 131, -1, 133, 134, -1, -1, -1, -1, 139, 140, - 141, -1, -1, -1, 145, 21, 22, -1, -1, -1, - 115, 116, 117, 118, 119, -1, -1, 122, 123, 124, + 131, -1, 133, 134, 21, 22, -1, -1, 139, 140, + 141, -1, -1, -1, 145, -1, -1, 180, 181, 182, + 183, 184, 185, 186, 187, 188, 189, 190, 191, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 202, + 203, 172, -1, -1, -1, -1, -1, -1, -1, 180, + -1, 182, 183, 184, 185, 186, 187, 188, 189, 190, + 191, -1, -1, -1, -1, -1, 115, 116, 117, 118, + 119, 202, 203, 122, 123, 124, 125, -1, 127, 128, + 129, 130, 131, -1, 133, 134, 21, 22, -1, -1, + 139, 140, 141, -1, -1, -1, 145, -1, 115, 116, + 117, 118, 119, -1, -1, 122, 123, 124, 125, -1, + 127, 128, 129, 130, 131, -1, 133, 134, -1, 168, + 21, 22, 139, 140, 141, -1, -1, -1, 145, -1, + -1, 180, -1, 182, 183, 184, 185, 186, 187, 188, + 189, 190, 191, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 202, 203, 172, -1, -1, -1, -1, + -1, -1, -1, 180, -1, 182, 183, 184, 185, 186, + 187, 188, 189, 190, 191, -1, -1, -1, -1, -1, + 115, 116, 117, 118, 119, 202, 203, 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, 133, 134, - -1, 172, -1, -1, 139, 140, 141, 21, 22, 180, - 145, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 202, 203, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 180, -1, 182, 183, 184, + -1, -1, 21, 22, 139, 140, 141, -1, -1, -1, + 145, -1, -1, -1, 115, 116, 117, 118, 119, -1, + -1, 122, 123, 124, 125, -1, 127, 128, 129, 130, + 131, -1, 133, 134, -1, -1, -1, 172, 139, 140, + 141, -1, -1, -1, 145, 180, -1, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 202, 203, 115, - 116, 117, 118, 119, -1, -1, 122, 123, 124, 125, - -1, 127, 128, 129, 130, 131, -1, 133, 134, 21, - 22, -1, -1, 139, 140, 141, -1, -1, -1, 145, + -1, -1, -1, -1, -1, -1, -1, 202, 203, -1, + -1, 172, -1, -1, -1, -1, -1, -1, -1, 180, + -1, 182, 183, 184, 185, 186, 187, 188, 189, 190, + 191, 21, 22, -1, -1, -1, 115, 116, 117, 118, + 119, 202, 203, 122, 123, 124, 125, -1, 127, 128, + 129, 130, 131, -1, 133, 134, -1, -1, -1, -1, + 139, 140, 141, -1, -1, -1, 145, 21, 22, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 172, -1, -1, -1, -1, -1, -1, + -1, 180, -1, 182, 183, 184, 185, 186, 187, 188, + 189, 190, 191, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 202, 203, 115, 116, 117, 118, 119, + -1, -1, 122, 123, 124, 125, -1, 127, 128, 129, + 130, 131, -1, 133, 134, -1, -1, -1, -1, 139, + 140, 141, -1, -1, -1, 145, 21, 22, -1, -1, -1, 115, 116, 117, 118, 119, -1, -1, 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, 133, - 134, 21, 22, -1, -1, 139, 140, 141, -1, -1, - -1, -1, -1, -1, 180, -1, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 202, 203, -1, -1, + 134, -1, 172, -1, -1, 139, 140, 141, 21, 22, + 180, 145, 182, 183, 184, 185, 186, 187, 188, 189, + 190, 191, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 202, 203, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 180, -1, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, -1, -1, - -1, -1, -1, 115, 116, 117, 118, 119, 202, 203, - 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, - -1, 133, 134, 21, 22, -1, -1, 139, -1, 141, - -1, -1, -1, -1, -1, 115, 116, 117, 118, 119, - -1, -1, 122, 123, 124, 125, -1, 127, 128, 129, - 130, 131, -1, 133, 134, 21, 22, -1, -1, 139, + -1, -1, -1, -1, -1, -1, -1, -1, 202, 203, + 115, 116, 117, 118, 119, -1, -1, 122, 123, 124, + 125, -1, 127, 128, 129, 130, 131, -1, 133, 134, + 21, 22, -1, -1, 139, 140, 141, -1, -1, -1, + 145, -1, 115, 116, 117, 118, 119, -1, -1, 122, + 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, + 133, 134, 21, 22, -1, -1, 139, 140, 141, -1, + -1, -1, -1, -1, -1, 180, -1, 182, 183, 184, + 185, 186, 187, 188, 189, 190, 191, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 202, 203, -1, + -1, -1, -1, -1, -1, -1, -1, 180, -1, 182, + 183, 184, 185, 186, 187, 188, 189, 190, 191, -1, + -1, -1, -1, -1, 115, 116, 117, 118, 119, 202, + 203, 122, 123, 124, 125, -1, 127, 128, 129, 130, + 131, -1, 133, 134, 21, 22, -1, -1, 139, -1, + 141, -1, -1, -1, -1, -1, 115, 116, 117, 118, + 119, -1, -1, 122, 123, 124, 125, -1, 127, 128, + 129, 130, 131, -1, 133, 134, 21, 22, -1, -1, + 139, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 182, 183, 184, 185, 186, 187, 188, 189, 190, + 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 202, 203, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 182, 183, 184, 185, 186, 187, 188, + 189, 190, 191, -1, -1, -1, -1, -1, 115, 116, + 117, 118, 119, 202, 203, 122, 123, 124, 125, -1, + 127, 128, 129, 130, 131, -1, 133, 134, 21, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 115, 116, 117, 118, 119, -1, -1, 122, 123, 124, + 125, -1, 127, 128, 129, 130, 131, -1, 133, 134, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 202, 203, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, -1, -1, -1, -1, -1, 115, 116, 117, - 118, 119, 202, 203, 122, 123, 124, 125, -1, 127, - 128, 129, 130, 131, -1, 133, 134, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 115, - 116, 117, 118, 119, -1, -1, 122, 123, 124, 125, - -1, 127, 128, 129, 130, 131, -1, 133, 134, -1, + -1, -1, -1, -1, -1, -1, 183, 184, 185, 186, + 187, 188, 189, 190, 191, -1, -1, -1, -1, -1, + 19, -1, -1, -1, -1, 202, 203, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 183, 184, 185, 186, 187, - 188, 189, 190, 191, 19, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 202, 203, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 185, - 186, 187, 188, 189, 190, 191, 19, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 202, 203, -1, -1, - -1, -1, -1, -1, -1, -1, 71, 72, 73, -1, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, -1, 93, 94, - 95, -1, -1, 98, 99, 100, 101, -1, 71, 72, - 73, -1, 75, 76, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 88, 89, 90, 91, -1, - 93, 94, 95, -1, -1, 98, 99, 100, 101, -1, - -1, -1, -1, -1, 19, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 153, -1, - -1, -1, -1, -1, 71, 72, 73, 162, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, -1, 93, 94, 95, -1, - 153, 98, 99, 100, 101, -1, 71, 72, 73, 162, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, -1, 93, 94, - 95, 128, 129, 98, 99, 100, 101, -1, -1, -1, + 185, 186, 187, 188, 189, 190, 191, -1, -1, -1, + -1, -1, 115, 116, 117, 118, 119, 202, 203, 122, + -1, -1, 125, -1, 127, 128, 129, 130, 131, -1, + 133, 134, 71, 72, 73, -1, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, -1, 93, 94, 95, -1, -1, 98, + 99, 100, 101, -1, -1, -1, -1, -1, 19, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 185, 186, 187, 188, 189, 190, 191, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 202, + 203, 19, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 153, -1, -1, -1, -1, -1, + 71, 72, 73, 162, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, + 91, -1, 93, 94, 95, -1, -1, 98, 99, 100, + 101, -1, -1, 71, 72, 73, -1, 75, 76, 77, + 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, -1, 93, 94, 95, -1, -1, + 98, 99, 100, 101, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 153, -1, -1, -1, -1, -1, -1, -1, + -1, 162, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 153, -1, -1, -1, - -1, -1, -1, -1, -1, 162, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 153, -1, -1, -1, -1, + -1, 71, 72, 73, 162, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, -1, 93, 94, 95, -1, -1, 98, 99, + 100, 101, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 153, -1, - -1, -1, -1, -1, -1, -1, -1, 162, -1, -1, - -1, -1, -1, -1, -1, 202, 203 + -1, -1, -1, -1, -1, -1, -1, -1, 128, 129, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 153, -1, -1, -1, -1, -1, -1, + -1, -1, 162, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 202, 203 }; /* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of @@ -3851,143 +3877,143 @@ static const yytype_int16 yystos[] = 230, 162, 191, 225, 226, 57, 63, 360, 361, 162, 207, 214, 360, 360, 360, 138, 162, 270, 34, 63, 131, 195, 205, 250, 251, 252, 253, 270, 172, 172, - 5, 6, 8, 36, 373, 62, 354, 179, 178, 181, - 178, 225, 22, 57, 190, 202, 227, 162, 172, 354, - 162, 162, 162, 162, 138, 222, 252, 252, 252, 205, - 139, 140, 141, 178, 204, 57, 63, 259, 261, 57, - 63, 364, 57, 63, 374, 57, 63, 355, 15, 16, - 155, 160, 162, 163, 205, 217, 247, 155, 230, 162, - 162, 162, 362, 57, 63, 213, 431, 423, 427, 162, - 164, 220, 206, 248, 252, 252, 252, 252, 262, 162, - 365, 377, 357, 164, 165, 166, 216, 15, 16, 155, - 160, 162, 217, 244, 245, 227, 179, 170, 170, 170, - 164, 206, 35, 71, 73, 75, 76, 77, 78, 79, - 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - 91, 93, 94, 95, 98, 99, 100, 101, 117, 118, - 162, 257, 260, 181, 366, 106, 371, 372, 208, 249, - 328, 164, 165, 166, 178, 206, 19, 25, 31, 41, - 49, 64, 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, 151, 207, 270, 380, 382, - 383, 386, 392, 393, 421, 432, 424, 428, 21, 22, - 38, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, 119, 120, 121, 122, 123, 124, 127, - 128, 129, 132, 133, 134, 135, 136, 139, 140, 141, - 142, 143, 144, 145, 180, 182, 183, 184, 185, 186, - 187, 188, 189, 190, 191, 194, 195, 202, 203, 35, - 35, 205, 255, 170, 263, 75, 79, 93, 94, 98, - 99, 100, 101, 381, 170, 162, 378, 247, 208, 162, - 351, 353, 244, 185, 185, 185, 205, 185, 185, 205, - 185, 185, 185, 185, 185, 185, 205, 270, 33, 60, - 61, 123, 127, 180, 184, 187, 203, 209, 391, 182, - 162, 385, 342, 345, 162, 162, 162, 204, 22, 162, - 204, 150, 206, 328, 338, 339, 181, 256, 266, 368, - 181, 370, 170, 375, 247, 178, 181, 184, 349, 394, - 399, 401, 5, 6, 15, 16, 17, 18, 19, 25, - 27, 31, 39, 45, 48, 51, 55, 65, 68, 69, - 80, 102, 103, 104, 117, 118, 146, 147, 148, 149, - 150, 152, 154, 155, 156, 157, 158, 159, 160, 161, - 163, 170, 187, 188, 189, 194, 195, 203, 205, 207, - 208, 219, 221, 264, 270, 275, 287, 294, 297, 300, - 304, 306, 308, 309, 311, 316, 319, 320, 327, 380, - 434, 442, 452, 455, 467, 470, 403, 397, 162, 387, - 405, 407, 409, 411, 413, 415, 417, 419, 320, 185, - 205, 33, 184, 33, 184, 203, 209, 204, 320, 203, - 209, 392, 178, 469, 162, 172, 178, 340, 389, 421, - 425, 162, 343, 389, 429, 162, 132, 205, 7, 50, - 281, 172, 206, 421, 1, 9, 10, 11, 13, 26, - 28, 29, 38, 42, 44, 52, 54, 58, 59, 65, - 105, 171, 172, 231, 232, 235, 237, 238, 239, 240, - 241, 242, 243, 265, 271, 276, 277, 278, 279, 280, - 282, 286, 307, 320, 162, 358, 359, 270, 334, 162, - 392, 126, 132, 179, 348, 421, 421, 390, 421, 185, - 185, 185, 272, 382, 434, 270, 185, 5, 102, 103, - 185, 205, 185, 205, 205, 185, 185, 205, 185, 205, - 185, 205, 185, 185, 205, 185, 185, 320, 320, 205, - 205, 205, 205, 205, 205, 218, 13, 320, 451, 466, - 320, 320, 320, 320, 320, 13, 49, 298, 320, 298, - 208, 205, 254, 170, 208, 300, 305, 21, 22, 115, - 116, 117, 118, 119, 122, 123, 124, 125, 127, 128, - 129, 130, 131, 133, 134, 139, 140, 141, 145, 180, - 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - 202, 203, 206, 205, 421, 421, 206, 162, 384, 421, - 255, 421, 255, 421, 255, 340, 341, 343, 344, 206, - 396, 267, 298, 204, 204, 204, 320, 162, 433, 181, - 389, 171, 181, 389, 171, 320, 147, 162, 347, 379, - 338, 205, 205, 126, 320, 263, 61, 320, 205, 162, - 172, 155, 58, 320, 263, 126, 320, 37, 172, 172, - 205, 10, 172, 172, 172, 172, 172, 172, 66, 283, - 172, 107, 108, 109, 110, 111, 112, 113, 114, 120, - 121, 126, 132, 135, 136, 142, 143, 144, 179, 179, - 178, 469, 171, 254, 335, 172, 348, 320, 186, 186, - 186, 389, 443, 445, 273, 205, 185, 205, 295, 185, - 185, 185, 462, 298, 392, 466, 320, 288, 290, 320, - 292, 320, 464, 298, 449, 453, 298, 447, 392, 320, - 320, 320, 320, 320, 320, 166, 167, 216, 379, 137, - 178, 469, 379, 13, 178, 469, 469, 147, 152, 185, - 270, 310, 70, 153, 162, 203, 206, 298, 435, 437, - 4, 303, 266, 208, 254, 19, 153, 162, 380, 19, - 153, 162, 380, 320, 320, 320, 320, 320, 320, 162, - 320, 153, 162, 320, 320, 320, 380, 320, 320, 320, - 320, 320, 320, 22, 320, 320, 320, 320, 320, 320, - 320, 320, 320, 320, 320, 128, 129, 153, 162, 202, - 203, 317, 380, 320, 206, 298, 186, 186, 172, 186, - 186, 256, 186, 256, 186, 256, 186, 389, 186, 389, - 269, 421, 206, 469, 204, 171, 421, 421, 206, 205, - 43, 126, 178, 179, 181, 184, 346, 320, 379, 320, - 14, 320, 320, 179, 181, 155, 320, 170, 320, 205, - 147, 162, 205, 285, 350, 352, 320, 320, 320, 320, + 172, 5, 6, 8, 36, 373, 62, 354, 179, 178, + 181, 178, 225, 22, 57, 190, 202, 227, 162, 172, + 354, 162, 162, 162, 162, 138, 222, 252, 252, 252, + 205, 139, 140, 141, 178, 204, 57, 63, 259, 261, + 57, 63, 364, 57, 63, 374, 57, 63, 355, 15, + 16, 155, 160, 162, 163, 205, 217, 247, 155, 230, + 162, 162, 162, 362, 57, 63, 213, 431, 423, 427, + 162, 164, 220, 206, 248, 252, 252, 252, 252, 262, + 162, 365, 377, 357, 164, 165, 166, 216, 15, 16, + 155, 160, 162, 217, 244, 245, 227, 179, 170, 170, + 170, 164, 206, 35, 71, 73, 75, 76, 77, 78, + 79, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 93, 94, 95, 98, 99, 100, 101, 117, + 118, 162, 257, 260, 181, 366, 106, 371, 372, 208, + 249, 328, 164, 165, 166, 178, 206, 19, 25, 31, + 41, 49, 64, 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, 151, 207, 270, 380, + 382, 383, 386, 392, 393, 421, 432, 424, 428, 21, + 22, 38, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, + 127, 128, 129, 132, 133, 134, 135, 136, 139, 140, + 141, 142, 143, 144, 145, 180, 182, 183, 184, 185, + 186, 187, 188, 189, 190, 191, 194, 195, 202, 203, + 35, 35, 205, 255, 170, 263, 75, 79, 93, 94, + 98, 99, 100, 101, 381, 170, 162, 378, 247, 208, + 162, 351, 353, 244, 185, 185, 185, 205, 185, 185, + 205, 185, 185, 185, 185, 185, 185, 205, 270, 33, + 60, 61, 123, 127, 180, 184, 187, 203, 209, 391, + 182, 162, 385, 342, 345, 162, 162, 162, 204, 22, + 162, 204, 150, 206, 328, 338, 339, 181, 256, 266, + 368, 181, 370, 170, 375, 247, 178, 181, 184, 349, + 394, 399, 401, 5, 6, 15, 16, 17, 18, 19, + 25, 27, 31, 39, 45, 48, 51, 55, 65, 68, + 69, 80, 102, 103, 104, 117, 118, 146, 147, 148, + 149, 150, 152, 154, 155, 156, 157, 158, 159, 160, + 161, 163, 170, 187, 188, 189, 194, 195, 203, 205, + 207, 208, 219, 221, 264, 270, 275, 287, 294, 297, + 300, 304, 306, 308, 309, 311, 316, 319, 320, 327, + 380, 434, 442, 452, 455, 467, 470, 403, 397, 162, + 387, 405, 407, 409, 411, 413, 415, 417, 419, 320, + 185, 205, 33, 184, 33, 184, 203, 209, 204, 320, + 203, 209, 392, 178, 469, 162, 172, 178, 340, 389, + 421, 425, 162, 343, 389, 429, 162, 132, 205, 7, + 50, 281, 172, 206, 421, 1, 9, 10, 11, 13, + 26, 28, 29, 38, 42, 44, 52, 54, 58, 59, + 65, 105, 171, 172, 231, 232, 235, 237, 238, 239, + 240, 241, 242, 243, 265, 271, 276, 277, 278, 279, + 280, 282, 286, 307, 320, 162, 358, 359, 270, 334, + 162, 392, 126, 132, 179, 348, 421, 421, 390, 421, + 185, 185, 185, 272, 382, 434, 270, 185, 5, 102, + 103, 185, 205, 185, 205, 205, 185, 185, 205, 185, + 205, 185, 205, 185, 185, 205, 185, 185, 320, 320, + 205, 205, 205, 205, 205, 205, 218, 13, 320, 451, + 466, 320, 320, 320, 320, 320, 13, 49, 298, 320, + 298, 208, 205, 254, 170, 208, 300, 305, 21, 22, + 115, 116, 117, 118, 119, 122, 123, 124, 125, 127, + 128, 129, 130, 131, 133, 134, 139, 140, 141, 145, + 180, 182, 183, 184, 185, 186, 187, 188, 189, 190, + 191, 202, 203, 206, 205, 421, 421, 206, 162, 384, + 421, 255, 421, 255, 421, 255, 340, 341, 343, 344, + 206, 396, 267, 298, 204, 204, 204, 320, 162, 433, + 181, 389, 171, 181, 389, 171, 320, 147, 162, 347, + 379, 338, 205, 205, 126, 320, 263, 61, 320, 205, + 162, 172, 155, 58, 320, 263, 126, 320, 37, 172, + 172, 205, 10, 172, 172, 172, 172, 172, 172, 66, + 283, 172, 107, 108, 109, 110, 111, 112, 113, 114, + 120, 121, 126, 132, 135, 136, 142, 143, 144, 179, + 179, 178, 469, 171, 254, 335, 172, 348, 320, 186, + 186, 186, 389, 443, 445, 273, 205, 185, 205, 295, + 185, 185, 185, 462, 298, 392, 466, 320, 288, 290, + 320, 292, 320, 464, 298, 449, 453, 298, 447, 392, + 320, 320, 320, 320, 320, 320, 166, 167, 216, 379, + 137, 178, 469, 379, 13, 178, 469, 469, 147, 152, + 185, 270, 310, 70, 153, 162, 203, 206, 298, 435, + 437, 4, 303, 266, 208, 254, 19, 153, 162, 380, + 19, 153, 162, 380, 320, 320, 320, 320, 320, 320, + 162, 320, 153, 162, 320, 320, 320, 380, 320, 320, + 320, 320, 320, 320, 22, 320, 320, 320, 320, 320, + 320, 320, 320, 320, 320, 320, 128, 129, 153, 162, + 202, 203, 317, 380, 320, 206, 298, 186, 186, 172, + 186, 186, 256, 186, 256, 186, 256, 186, 389, 186, + 389, 269, 421, 206, 469, 204, 171, 421, 421, 206, + 205, 43, 126, 178, 179, 181, 184, 346, 320, 379, + 320, 14, 320, 320, 179, 181, 155, 320, 170, 320, + 205, 147, 162, 205, 285, 350, 352, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, - 320, 320, 320, 320, 320, 358, 369, 8, 328, 333, - 320, 172, 395, 400, 402, 421, 392, 392, 421, 70, - 298, 437, 441, 162, 320, 421, 456, 458, 460, 392, - 469, 186, 389, 469, 206, 392, 392, 206, 392, 206, - 392, 469, 392, 392, 469, 392, 186, 206, 206, 206, - 206, 206, 206, 320, 20, 320, 451, 171, 20, 379, - 320, 204, 206, 205, 205, 312, 314, 162, 206, 437, - 205, 132, 346, 435, 178, 206, 178, 206, 205, 255, - 171, 303, 185, 205, 185, 205, 205, 205, 204, 19, - 153, 162, 380, 181, 153, 162, 320, 205, 205, 153, - 162, 320, 1, 205, 204, 178, 206, 404, 398, 162, - 388, 406, 186, 410, 186, 414, 186, 418, 340, 420, - 343, 186, 389, 320, 162, 162, 421, 320, 206, 20, - 263, 206, 320, 266, 206, 320, 205, 43, 162, 284, - 178, 181, 349, 171, 57, 63, 331, 67, 332, 172, - 172, 186, 186, 186, 437, 206, 206, 206, 186, 389, - 206, 186, 392, 392, 392, 186, 206, 205, 392, 206, - 186, 186, 186, 186, 206, 186, 186, 206, 186, 303, - 205, 168, 298, 298, 20, 320, 320, 392, 255, 206, - 320, 320, 320, 204, 203, 153, 162, 126, 132, 162, - 179, 184, 301, 302, 256, 255, 321, 320, 323, 320, - 206, 298, 320, 185, 205, 320, 205, 204, 320, 206, - 298, 205, 204, 318, 206, 298, 408, 412, 416, 205, - 421, 206, 43, 346, 263, 298, 263, 171, 263, 206, - 320, 162, 178, 206, 162, 392, 348, 47, 332, 46, - 106, 329, 444, 446, 274, 206, 205, 162, 296, 186, - 186, 186, 463, 268, 466, 186, 289, 291, 293, 465, - 450, 454, 448, 205, 263, 206, 298, 172, 172, 298, - 206, 206, 186, 256, 206, 206, 435, 205, 132, 346, - 162, 162, 205, 162, 162, 178, 206, 137, 263, 299, - 256, 392, 206, 421, 206, 206, 206, 325, 320, 320, - 206, 206, 320, 206, 267, 162, 320, 206, 12, 23, - 24, 233, 234, 12, 236, 206, 162, 181, 349, 43, - 172, 348, 320, 33, 330, 329, 331, 205, 205, 320, - 186, 457, 459, 461, 205, 206, 469, 205, 320, 320, - 320, 205, 70, 441, 205, 205, 206, 320, 206, 451, - 320, 172, 313, 186, 132, 346, 204, 320, 320, 320, - 162, 301, 126, 320, 263, 186, 186, 421, 206, 206, - 206, 206, 263, 263, 205, 237, 276, 277, 278, 279, - 320, 172, 392, 348, 162, 320, 172, 336, 330, 347, - 441, 441, 206, 205, 205, 205, 205, 267, 268, 298, - 441, 435, 436, 206, 172, 468, 468, 320, 310, 315, - 320, 320, 206, 206, 206, 320, 322, 324, 186, 320, - 348, 320, 172, 260, 337, 205, 435, 438, 439, 440, - 440, 320, 441, 441, 436, 206, 206, 469, 440, 206, - 53, 171, 204, 468, 310, 132, 346, 326, 206, 320, - 172, 172, 260, 435, 178, 469, 206, 206, 206, 440, - 440, 206, 206, 206, 320, 204, 320, 320, 263, 172, - 263, 206, 205, 206, 206, 234, 435, 206 + 320, 320, 320, 320, 320, 320, 358, 369, 8, 328, + 333, 320, 172, 395, 400, 402, 421, 392, 392, 421, + 70, 298, 437, 441, 162, 320, 421, 456, 458, 460, + 392, 469, 186, 389, 469, 206, 392, 392, 206, 392, + 206, 392, 469, 392, 392, 469, 392, 186, 206, 206, + 206, 206, 206, 206, 320, 20, 320, 451, 171, 20, + 379, 320, 204, 206, 205, 205, 312, 314, 162, 206, + 437, 205, 132, 346, 435, 178, 206, 178, 206, 205, + 255, 171, 303, 185, 205, 185, 205, 205, 205, 204, + 19, 153, 162, 380, 181, 153, 162, 320, 205, 205, + 153, 162, 320, 1, 205, 204, 178, 206, 404, 398, + 162, 388, 406, 186, 410, 186, 414, 186, 418, 340, + 420, 343, 186, 389, 320, 162, 162, 421, 320, 206, + 20, 263, 206, 320, 266, 206, 320, 205, 43, 162, + 284, 178, 181, 349, 171, 57, 63, 331, 67, 332, + 172, 172, 186, 186, 186, 437, 206, 206, 206, 186, + 389, 206, 186, 392, 392, 392, 186, 206, 205, 392, + 206, 186, 186, 186, 186, 206, 186, 186, 206, 186, + 303, 205, 168, 298, 298, 20, 320, 320, 392, 255, + 206, 320, 320, 320, 204, 203, 153, 162, 126, 132, + 162, 179, 184, 301, 302, 256, 255, 321, 320, 323, + 320, 206, 298, 320, 185, 205, 320, 205, 204, 320, + 206, 298, 205, 204, 318, 206, 298, 408, 412, 416, + 205, 421, 206, 43, 346, 263, 298, 263, 171, 263, + 206, 320, 162, 178, 206, 162, 392, 348, 47, 332, + 46, 106, 329, 444, 446, 274, 206, 205, 162, 296, + 186, 186, 186, 463, 268, 466, 186, 289, 291, 293, + 465, 450, 454, 448, 205, 263, 206, 298, 172, 172, + 298, 206, 206, 186, 256, 206, 206, 435, 205, 132, + 346, 162, 162, 205, 162, 162, 178, 206, 137, 263, + 299, 256, 392, 206, 421, 206, 206, 206, 325, 320, + 320, 206, 206, 320, 206, 267, 162, 320, 206, 12, + 23, 24, 233, 234, 12, 236, 206, 162, 181, 349, + 43, 172, 348, 320, 33, 330, 329, 331, 205, 205, + 320, 186, 457, 459, 461, 205, 206, 469, 205, 320, + 320, 320, 205, 70, 441, 205, 205, 206, 320, 206, + 451, 320, 172, 313, 186, 132, 346, 204, 320, 320, + 320, 162, 301, 126, 320, 263, 186, 186, 421, 206, + 206, 206, 206, 263, 263, 205, 237, 276, 277, 278, + 279, 320, 172, 392, 348, 162, 320, 172, 336, 330, + 347, 441, 441, 206, 205, 205, 205, 205, 267, 268, + 298, 441, 435, 436, 206, 172, 468, 468, 320, 310, + 315, 320, 320, 206, 206, 206, 320, 322, 324, 186, + 320, 348, 320, 172, 260, 337, 205, 435, 438, 439, + 440, 440, 320, 441, 441, 436, 206, 206, 469, 440, + 206, 53, 171, 204, 468, 310, 132, 346, 326, 206, + 320, 172, 172, 260, 435, 178, 469, 206, 206, 206, + 440, 440, 206, 206, 206, 320, 204, 320, 320, 263, + 172, 263, 206, 205, 206, 206, 234, 435, 206 }; /* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */ @@ -4077,7 +4103,7 @@ static const yytype_int16 yyr1[] = /* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */ static const yytype_int8 yyr2[] = { - 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, + 0, 2, 0, 2, 2, 2, 2, 2, 2, 3, 3, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 1, 4, 1, 1, 2, 2, 3, 2, 0, 2, 4, 3, 1, 2, 0, 4, 2, 2, diff --git a/prog/1stPartyLibs/daScript/src/parser/ds2_parser.ypp b/prog/1stPartyLibs/daScript/src/parser/ds2_parser.ypp index 19939ce80..617536489 100644 --- a/prog/1stPartyLibs/daScript/src/parser/ds2_parser.ypp +++ b/prog/1stPartyLibs/daScript/src/parser/ds2_parser.ypp @@ -541,7 +541,7 @@ program | program global_let { yyextra->das_has_type_declarations = true; } | program global_function_declaration { yyextra->das_has_type_declarations = true; } | program expect_declaration - | program require_declaration + | program require_declaration ';' | program options_declaration ';' | program alias_declaration { yyextra->das_has_type_declarations = true; } | program variant_alias_declaration { yyextra->das_has_type_declarations = true; } diff --git a/prog/1stPartyLibs/daScript/src/simulate/runtime_string.cpp b/prog/1stPartyLibs/daScript/src/simulate/runtime_string.cpp index 299c5c205..efba40b98 100644 --- a/prog/1stPartyLibs/daScript/src/simulate/runtime_string.cpp +++ b/prog/1stPartyLibs/daScript/src/simulate/runtime_string.cpp @@ -510,6 +510,25 @@ namespace das } } + int32_t levenshtein_distance ( const char * s1, const char * s2 ) { + int len1 = int(strlen(s1)); + int len2 = int(strlen(s2)); + if ( len1==0 ) return len2; + if ( len2==0 ) return len1; + int * v0 = (int *) alloca(sizeof(int)*(len2+1)); + int * v1 = (int *) alloca(sizeof(int)*(len2+1)); + for ( int i=0; i<=len2; ++i ) v0[i] = i; + for ( int i=0; i 0) braceCounter[0]--; break; + case '}': if (braceCounter[1] > 0) braceCounter[1]--; break; + case ']': if (braceCounter[2] > 0) braceCounter[2]--; break; + default: break; + } + } + + if (braceCounter[0] > 0 || braceCounter[1] > 0 || braceCounter[2] > 0) + return true; + + + if (mLanguageDefinition == &LanguageDefinition::Daslang()) + { + static const char * const startKeywordsIndent[] = { + "if", "elif", "else", "for", "while", "switch", "class", "struct", "enum", "def", "try", "except", "finally", "with", "lambda" + }; + + static const char * const singleKeywordsIndent[] = { + "let", "var" + }; + + bool singleWord = true; + eastl::string w = parse_first_word(line.c_str(), singleWord); + + for (auto &k : startKeywordsIndent) + { + if (w == k) + return true; + } + + if (singleWord) + for (auto &k : singleKeywordsIndent) + if (w == k) + return true; + + // block_call() $ (arg1, arg2) + const char * lambdaPos = strrchr(line.c_str(), '$'); + if (lambdaPos) + { + const char * endOfParameter = find_pair_brace(lambdaPos, '(', ')'); + if (!endOfParameter) + return true; + + const char * p = endOfParameter + 1; + while (*p && isspace(*p)) + p++; + + bool nonSpaceSymbols = *p && !isspace(*p); + + if (!nonSpaceSymbols) + return true; + } + } + + return false; +} diff --git a/prog/3rdPartyLibs/ImGuiColorTextEdit/TextEditor.cpp b/prog/3rdPartyLibs/ImGuiColorTextEdit/TextEditor.cpp index 84597d9ce..cf3f82193 100644 --- a/prog/3rdPartyLibs/ImGuiColorTextEdit/TextEditor.cpp +++ b/prog/3rdPartyLibs/ImGuiColorTextEdit/TextEditor.cpp @@ -23,6 +23,7 @@ TextEditor::TextEditor() TextEditor::~TextEditor() { + ClearHighlights(); } void TextEditor::SetPalette(PaletteId aValue) @@ -159,6 +160,8 @@ void TextEditor::ClearSelections() mState.mCursors[c].mInteractiveEnd = mState.mCursors[c].mInteractiveStart = mState.mCursors[c].GetSelectionEnd(); + + ClearHighlights(); } void TextEditor::SetCursorPosition(int aLine, int aCharIndex) @@ -197,6 +200,10 @@ void TextEditor::Copy() auto& line = mLines[GetActualCursorCoordinates().mLine]; for (auto& g : line) str.push_back(g.mChar); +#ifdef _WIN32 + str.push_back('\r'); +#endif + str.push_back('\n'); ImGui::SetClipboardText(str.c_str()); } } @@ -233,6 +240,46 @@ void TextEditor::Paste() const char* text = ImGui::GetClipboardText(); if (!text || !text[0]) return; + + if (!mLines.empty() && !AnyCursorHasSelection()) + { + auto &line = mLines[GetActualCursorCoordinates().mLine]; + int lineLen = (int)strlen(text); + if (lineLen > 0 && text[lineLen - 1] == '\n') + lineLen--; + if (lineLen > 0 && text[lineLen - 1] == '\r') + lineLen--; + + if (bool sameLine = (lineLen == line.size() && lineLen > 0)) + { + for (int i = 0; i < lineLen; i++) + if (line[i].mChar != text[i]) + { + sameLine = false; + break; + } + + if (sameLine) + { + eastl::string textToInsert = "\n"; + textToInsert += text; + if (textToInsert.back() == '\n') + textToInsert.pop_back(); + + auto coords = GetActualCursorCoordinates(); + auto newCursorPos = coords; + + coords.mColumn = mLines[coords.mLine].size(); + SetCursorPosition(coords, 0); + PasteText(textToInsert.c_str()); + + newCursorPos.mLine++; + SetCursorPosition(newCursorPos, 0, true); + return; + } + } + } + PasteText(ImGui::GetClipboardText()); } @@ -298,6 +345,36 @@ void TextEditor::PasteText(const char * text) AddUndo(u); } +void TextEditor::ClearHighlights() +{ + for (auto &h : highlights) + { + delete h; + h = nullptr; + } +} + +void TextEditor::AddHighlight(int line, int start, int end) +{ + if (start > 32000 || end > 32000) + return; + + if (line >= (int)highlights.size()) + { + for (int i = (int)highlights.size(); i <= line; i++) + highlights.push_back(nullptr); + } + + if (highlights[line] == nullptr) + highlights[line] = new HighlightRanges(); + + if (highlights[line]->size() > 20) + return; + + highlights[line]->push_back({ start, end }); +} + + bool TextEditor::UndoRecord::isSimilarTo(const TextEditor::UndoRecord& other) const { if (mOperations.size() != 1 || other.mOperations.size() != 1) @@ -472,7 +549,11 @@ bool TextEditor::Render(const char* aTitle, bool aParentIsFocused, const ImVec2& mCursorPositionChanged = false; if (colorizeTime != 0.0 && ImGui::GetTime() > colorizeTime) + { ColorizeAll(); + ClearHighlights(); + HighlightSelectedText(); + } ImGui::PushStyleColor(ImGuiCol_ChildBg, ImGui::ColorConvertU32ToFloat4(mPalette[(int)PaletteIndex::Background])); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f)); @@ -1009,6 +1090,26 @@ void TextEditor::MoveEnd(bool aSelect) } } +void TextEditor::FindPreferredIndentChar(int lineNum) +{ + int from = max(lineNum - 10, 0); + int to = min(lineNum + 10, (int)mLines.size()); + int tabs = 0; + int spaces = 0; + for (int i = from; i < to; i++) + { + auto& line = mLines[i]; + if (line.empty()) + continue; + if (line[0].mChar == '\t') + tabs++; + else if (line[0].mChar == ' ') + spaces++; + } + + preferredIndentChar = tabs > spaces ? '\t' : ' '; +} + void TextEditor::EnterCharacter(ImWchar aChar, bool aShift) { EASTL_ASSERT(!mReadOnly); @@ -1060,13 +1161,34 @@ void TextEditor::EnterCharacter(ImWchar aChar, bool aShift) added.mText = ""; added.mText += (char)aChar; if (mAutoIndent) + { + FindPreferredIndentChar(coord.mLine); + char lastIndentChar = preferredIndentChar; + for (int i = 0; i < line.size() && unsigned(line[i].mChar) < 128 && isblank(line[i].mChar); ++i) { if (i >= coord.mColumn) break; newLine.push_back(line[i]); added.mText += line[i].mChar; + if (line[i].mChar == '\t' || line[i].mChar == ' ') + lastIndentChar = line[i].mChar; + } + + eastl::string lineBeforeCursor; + for (int i = 0; i < coord.mColumn && i < (int)line.size(); i++) + lineBeforeCursor += line[i].mChar; + + if (RequireIndentationAfterNewLine(lineBeforeCursor)) + { + if (lastIndentChar == ' ') + for (int i = 0; i < mTabSize; ++i) + newLine.push_back(Glyph(' ', PaletteIndex::Background)); + + if (lastIndentChar == '\t') + newLine.push_back(Glyph('\t', PaletteIndex::Background)); } + } const size_t whitespaceSize = newLine.size(); auto cindex = GetCharacterIndexR(coord); @@ -1195,6 +1317,63 @@ void TextEditor::Delete(bool aWordMode, const EditorState* aEditorState) } } +void TextEditor::HighlightSelectedText() +{ + eastl::string sel = GetSelectedText(0); + bool spacesOnly = true; + + for (auto c : sel) + { + if (c != ' ' && c != '\t') + spacesOnly = false; + + if (c == '\n') + return; + } + + if (spacesOnly) + return; + + int highlightedCount = 0; + int highlightAroundLine = mState.mCursors[0].mInteractiveStart.mLine; + + for (int pass = 0; pass < 2; pass++) + { + for (int k = 0; k < Min((int)mLines.size(), 30000); k++) + { + bool insideRange = abs(k - highlightAroundLine) < 30; + if ((pass == 0) != (insideRange)) + continue; + + auto & line = mLines[k]; + for (int i = 0; i <= (int)line.size() - (int)sel.length(); i++) + { + if (line[i].mChar == sel[0]) + { + bool found = true; + for (int j = 1; j < (int)sel.length(); j++) + { + if (line[i + j].mChar != sel[j]) + { + found = false; + break; + } + } + + if (found) + { + AddHighlight(k, i, i + (int)sel.length()); + i += (int)sel.length() - 1; + highlightedCount++; + if (highlightedCount > 400) + return; + } + } + } + } + } +} + void TextEditor::SetSelection(Coordinates aStart, Coordinates aEnd, int aCursor) { if (aCursor == -1) @@ -1214,6 +1393,9 @@ void TextEditor::SetSelection(Coordinates aStart, Coordinates aEnd, int aCursor) mState.mCursors[aCursor].mInteractiveStart = aStart; SetCursorPosition(aEnd, aCursor, false); + + ClearHighlights(); + HighlightSelectedText(); } void TextEditor::SetSelection(int aStartLine, int aStartChar, int aEndLine, int aEndChar, int aCursor) @@ -2438,6 +2620,23 @@ void TextEditor::Render(bool aParentIsFocused) Coordinates lineStartCoord(lineNo, 0); Coordinates lineEndCoord(lineNo, maxColumnLimited); + // Draw highlights for the current line + if (lineNo < highlights.size() && highlights[lineNo]) + { + HighlightRanges &ranges = *highlights[lineNo]; + for (auto && range : ranges) + { + if (range.first < line.size() && range.second <= line.size()) + { + float x1 = TextDistanceToLineStart(Coordinates(lineNo, range.first)); + float x2 = TextDistanceToLineStart(Coordinates(lineNo, range.second)); + drawList->AddRectFilled(ImVec2{ lineStartScreenPos.x + mTextStart + x1, lineStartScreenPos.y }, + ImVec2{ lineStartScreenPos.x + mTextStart + x2, lineStartScreenPos.y + mCharAdvance.y }, + mPalette[(int)PaletteIndex::HighlightedTextFill]); + } + } + } + // Draw selection for the current line for (int c = 0; c <= mState.mCurrentCursor; c++) { @@ -2693,6 +2892,9 @@ void TextEditor::OnCursorPositionChanged() mState.SortCursorsFromTopToBottom(); MergeCursorsIfPossible(); } + + ClearHighlights(); + HighlightSelectedText(); } void TextEditor::OnLineChanged(bool aBeforeChange, int aLine, int aColumn, int aCharCount, bool aDeleted) // adjusts cursor position when other cursor writes/deletes in the same line @@ -2998,6 +3200,7 @@ const TextEditor::Palette& TextEditor::GetDarkPalette() 0x00000040, // Current line fill 0x80808040, // Current line fill (inactive) 0xa0a0a040, // Current line edge + 0xff406080, // Highlight fill } }; return p; } @@ -3027,6 +3230,7 @@ const TextEditor::Palette& TextEditor::GetMarianaPalette() 0x4e5a6580, // Current line fill 0x4e5a6530, // Current line fill (inactive) 0x4e5a65b0, // Current line edge + 0xff406080, // Highlight fill } }; return p; } @@ -3056,6 +3260,7 @@ const TextEditor::Palette& TextEditor::GetLightPalette() 0x00000040, // Current line fill 0x80808040, // Current line fill (inactive) 0x00000040, // Current line edge + 0xffA0A0A0, // Highlight fill } }; return p; } @@ -3084,6 +3289,7 @@ const TextEditor::Palette& TextEditor::GetRetroBluePalette() 0x00000040, // Current line fill 0x80808040, // Current line fill (inactive) 0xe0e0e040, // Current line edge + 0xff404080, // Highlight fill } }; return p; } diff --git a/prog/3rdPartyLibs/ImGuiColorTextEdit/TextEditor.h b/prog/3rdPartyLibs/ImGuiColorTextEdit/TextEditor.h index ed787557a..23573777f 100644 --- a/prog/3rdPartyLibs/ImGuiColorTextEdit/TextEditor.h +++ b/prog/3rdPartyLibs/ImGuiColorTextEdit/TextEditor.h @@ -167,6 +167,7 @@ class IMGUI_API TextEditor CurrentLineFill, CurrentLineFillInactive, CurrentLineEdge, + HighlightedTextFill, Max }; @@ -297,6 +298,8 @@ class IMGUI_API TextEditor static const LanguageDefinition& Daslang(); }; + bool RequireIndentationAfterNewLine(const eastl::string &line) const; + enum class UndoOperationType { Add, Delete }; struct UndoOperation { @@ -418,6 +421,7 @@ class IMGUI_API TextEditor double colorizeTime = 0.0; + char preferredIndentChar = ' '; int mTabSize = 4; float mLineSpacing = 1.0f; bool mOverwrite = false; @@ -464,12 +468,20 @@ class IMGUI_API TextEditor Palette mPalette; LanguageDefinitionId mLanguageDefinitionId; const LanguageDefinition* mLanguageDefinition = nullptr; + + typedef eastl::vector> HighlightRanges; + eastl::vector highlights; + void ClearHighlights(); + void AddHighlight(int line, int start, int end); + void HighlightSelectedText(); + eastl::string mLineBuffer; eastl::string tabString; inline bool IsHorizontalScrollbarVisible() const { return mCurrentSpaceWidth > mContentWidth; } inline bool IsVerticalScrollbarVisible() const { return mCurrentSpaceHeight > mContentHeight; } inline int TabSizeAtColumn(int aColumn) const { return mTabSize - (aColumn % mTabSize); } + void FindPreferredIndentChar(int lineNum); static const Palette& GetDarkPalette(); static const Palette& GetMarianaPalette(); diff --git a/prog/3rdPartyLibs/ImGuizmo/ImGuizmo.cpp b/prog/3rdPartyLibs/ImGuizmo/ImGuizmo.cpp index 24f72b857..8312a53a5 100644 --- a/prog/3rdPartyLibs/ImGuizmo/ImGuizmo.cpp +++ b/prog/3rdPartyLibs/ImGuizmo/ImGuizmo.cpp @@ -2795,14 +2795,14 @@ namespace IMGUIZMO_NAMESPACE } } - void ViewManipulate(float* view, const float* projection, OPERATION operation, MODE mode, float* matrix, float length, ImVec2 position, ImVec2 size, ImU32 backgroundColor) + bool ViewManipulate(float* view, const float* projection, OPERATION operation, MODE mode, float* matrix, float length, ImVec2 position, ImVec2 size, ImU32 backgroundColor) { // Scale is always local or matrix will be skewed when applying world scale or oriented matrix ComputeContext(view, projection, matrix, (operation & SCALE) ? LOCAL : mode); - ViewManipulate(view, length, position, size, backgroundColor); + return ViewManipulate(view, length, position, size, backgroundColor); } - void ViewManipulate(float* view, float length, ImVec2 position, ImVec2 size, ImU32 backgroundColor) + bool ViewManipulate(float* view, float length, ImVec2 position, ImVec2 size, ImU32 backgroundColor) { static bool isDraging = false; static bool isClicking = false; @@ -3023,5 +3023,6 @@ namespace IMGUIZMO_NAMESPACE // restore view/projection because it was used to compute ray ComputeContext(svgView.m16, svgProjection.m16, gContext.mModelSource.m16, gContext.mMode); + return isDraging; } }; diff --git a/prog/3rdPartyLibs/ImGuizmo/ImGuizmo.h b/prog/3rdPartyLibs/ImGuizmo/ImGuizmo.h index 63af89d05..34e02c174 100644 --- a/prog/3rdPartyLibs/ImGuizmo/ImGuizmo.h +++ b/prog/3rdPartyLibs/ImGuizmo/ImGuizmo.h @@ -215,10 +215,10 @@ namespace IMGUIZMO_NAMESPACE // It seems to be a defensive patent in the US. I don't think it will bring troubles using it as // other software are using the same mechanics. But just in case, you are now warned! // - IMGUI_API void ViewManipulate(float* view, float length, ImVec2 position, ImVec2 size, ImU32 backgroundColor); + IMGUI_API bool ViewManipulate(float* view, float length, ImVec2 position, ImVec2 size, ImU32 backgroundColor); // use this version if you did not call Manipulate before and you are just using ViewManipulate - IMGUI_API void ViewManipulate(float* view, const float* projection, OPERATION operation, MODE mode, float* matrix, float length, ImVec2 position, ImVec2 size, ImU32 backgroundColor); + IMGUI_API bool ViewManipulate(float* view, const float* projection, OPERATION operation, MODE mode, float* matrix, float length, ImVec2 position, ImVec2 size, ImU32 backgroundColor); IMGUI_API void SetID(int id); diff --git a/prog/3rdPartyLibs/imgui/imgui.cpp b/prog/3rdPartyLibs/imgui/imgui.cpp index b1db521ea..0e78b46c7 100644 --- a/prog/3rdPartyLibs/imgui/imgui.cpp +++ b/prog/3rdPartyLibs/imgui/imgui.cpp @@ -7192,8 +7192,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) if (window_title_visible_elsewhere && !window_just_created && strcmp(name, window->Name) != 0) { size_t buf_len = (size_t)window->NameBufLen; + const bool syncDrawListName = window->Name == window->DrawList->_OwnerName; window->Name = ImStrdupcpy(window->Name, &buf_len, name); window->NameBufLen = (int)buf_len; + if (syncDrawListName) + window->DrawList->_OwnerName = window->Name; } // UPDATE CONTENTS SIZE, UPDATE HIDDEN STATUS diff --git a/prog/commonFx/commonFxGame/dafxCompound.cpp b/prog/commonFx/commonFxGame/dafxCompound.cpp index 631805416..208309ea7 100644 --- a/prog/commonFx/commonFxGame/dafxCompound.cpp +++ b/prog/commonFx/commonFxGame/dafxCompound.cpp @@ -675,7 +675,7 @@ struct DafxCompound : BaseParticleEffect dafx::set_instance_pos(g_dafx_ctx, iid, pos); } else if (id == _MAKE4C('PFXV')) - dafx::set_instance_visibility(g_dafx_ctx, iid, value ? *(bool *)value : false); + dafx::set_instance_visibility(g_dafx_ctx, iid, value ? *(uint32_t *)value : 0); else if (id == _MAKE4C('PFXI')) ((eastl::vector *)value)->push_back(iid); else if (id == HUID_TM) diff --git a/prog/commonFx/commonFxGame/dafxModFx.cpp b/prog/commonFx/commonFxGame/dafxModFx.cpp index a387b213b..515f9dc28 100644 --- a/prog/commonFx/commonFxGame/dafxModFx.cpp +++ b/prog/commonFx/commonFxGame/dafxModFx.cpp @@ -163,7 +163,7 @@ struct DafxModFx : BaseParticleEffect dafx::set_instance_pos(g_dafx_ctx, iid, pos); } else if (id == _MAKE4C('PFXV')) - dafx::set_instance_visibility(g_dafx_ctx, iid, value ? *(bool *)value : false); + dafx::set_instance_visibility(g_dafx_ctx, iid, value ? *(uint32_t *)value : 0); else if (id == HUID_TM) setTm((TMatrix *)value); else if (id == HUID_EMITTER_TM) diff --git a/prog/commonFx/commonFxGame/dafxModFxSystem.cpp b/prog/commonFx/commonFxGame/dafxModFxSystem.cpp index b3985c0c9..8e98f5657 100644 --- a/prog/commonFx/commonFxGame/dafxModFxSystem.cpp +++ b/prog/commonFx/commonFxGame/dafxModFxSystem.cpp @@ -343,6 +343,7 @@ bool dafx_modfx_system_load(const char *ptr, int len, BaseParamScriptLoadCB *loa GDATA(dt); GDATA(water_level); GDATA(globtm); + GDATA(globtm_prev); GDATA(view_dir_x); GDATA(view_dir_y); GDATA(view_dir_z); @@ -358,6 +359,7 @@ bool dafx_modfx_system_load(const char *ptr, int len, BaseParamScriptLoadCB *loa GDATA(sky_color); GDATA(zn_zfar); GDATA(znear_offset); + GDATA(proj_hk); GDATA(wind_dir); GDATA(wind_power); GDATA(wind_scroll); @@ -1930,4 +1932,4 @@ bool dafx_modfx_system_load(const char *ptr, int len, BaseParamScriptLoadCB *loa sinfo.onePointRadius = parGlobals.one_point_radius; return true; -} \ No newline at end of file +} diff --git a/prog/commonFx/commonFxGame/dafxSparks.cpp b/prog/commonFx/commonFxGame/dafxSparks.cpp index ba0b105e1..d1912c7b2 100644 --- a/prog/commonFx/commonFxGame/dafxSparks.cpp +++ b/prog/commonFx/commonFxGame/dafxSparks.cpp @@ -365,7 +365,7 @@ struct DafxSparks : BaseParticleEffect ((eastl::vector *)value)->push_back(iid); } else if (id == _MAKE4C('PFXV')) - dafx::set_instance_visibility(g_dafx_ctx, iid, value ? *(bool *)value : false); + dafx::set_instance_visibility(g_dafx_ctx, iid, value ? *(uint32_t *)value : 0); else if (id == _MAKE4C('PFXG')) dafx::warmup_instance(g_dafx_ctx, iid, value ? *(float *)value : 0); else if (id == _MAKE4C('GZTM')) diff --git a/prog/commonFx/commonFxGame/dafx_frame_boundary.dshl b/prog/commonFx/commonFxGame/dafx_frame_boundary.dshl index 04ca49a7f..e25db430b 100644 --- a/prog/commonFx/commonFxGame/dafx_frame_boundary.dshl +++ b/prog/commonFx/commonFxGame/dafx_frame_boundary.dshl @@ -14,23 +14,25 @@ int dafx_fill_boundary_frame_id = 0; int dafx_use_experimental_boundary_calc = 0; interval dafx_use_experimental_boundary_calc: no < 1, yes; +int dafx_fill_boundary_legacy_frame_boundary_result_uav_no = 0; // horribly slow, only used for debugging ->> should be deprecated if there is no problem with the optimized version shader fill_fx_keyframe_boundary_legacy { - (cs){ + (cs) { dafx_fill_boundary_tex@tex2d = dafx_fill_boundary_tex; dafx_fill_boundary_params@f4 = dafx_fill_boundary_params; dafx_fill_boundary_offset@i1 = dafx_fill_boundary_offset; tile_size@f2 = (dafx_fill_boundary_params.z / dafx_fill_boundary_params.x, dafx_fill_boundary_params.w / dafx_fill_boundary_params.y); tile_size_inv@f2 = (dafx_fill_boundary_params.x / dafx_fill_boundary_params.z, dafx_fill_boundary_params.y / dafx_fill_boundary_params.w); + frame_boundary_result@uav : register(dafx_fill_boundary_legacy_frame_boundary_result_uav_no) hlsl { + RWStructuredBuffer frame_boundary_result@uav; + }; } ENABLE_ASSERT(cs) hlsl(cs) { - RWStructuredBuffer frame_boundary_result : register(u0); - float4 transformInverseY(float4 boundary) { boundary.yw = 1 - boundary.wy; @@ -80,14 +82,19 @@ shader fill_fx_keyframe_boundary_legacy compile("target_cs", "main_cs"); } - +int dafx_fill_boundary_opt_start_frame_boundary_tmp_uav_no = 0; shader fill_fx_keyframe_boundary_opt_start { ENABLE_ASSERT(cs) - hlsl(cs) { - RWStructuredBuffer dafx_frame_boundary_tmp : register(u0); + (cs) { + dafx_frame_boundary_tmp@uav : register(dafx_fill_boundary_opt_start_frame_boundary_tmp_uav_no) hlsl { + RWStructuredBuffer dafx_frame_boundary_tmp@uav; + }; + } + + hlsl(cs) { [numthreads( 16, 4, 1 )] void main_cs( uint2 dtId : SV_DispatchThreadID ) { @@ -99,19 +106,22 @@ shader fill_fx_keyframe_boundary_opt_start compile("target_cs", "main_cs"); } +int dafx_fill_boundary_approx_frame_boundary_tmp_uav_no = 0; + shader fill_fx_keyframe_boundary_approx { - (cs){ + (cs) { dafx_fill_boundary_tex@tex2d = dafx_fill_boundary_tex; dafx_fill_boundary_params@f4 = dafx_fill_boundary_params; tile_size@f2 = (dafx_fill_boundary_params.z / dafx_fill_boundary_params.x, dafx_fill_boundary_params.w / dafx_fill_boundary_params.y); + dafx_frame_boundary_tmp@uav : register(dafx_fill_boundary_approx_frame_boundary_tmp_uav_no) hlsl { + RWStructuredBuffer dafx_frame_boundary_tmp@uav; + }; } ENABLE_ASSERT(cs) hlsl(cs) { - RWStructuredBuffer dafx_frame_boundary_tmp : register(u0); - #define BOUNDARY_CACHE_SIZE 8 groupshared uint tmp_boundary_cache[4]; @@ -174,19 +184,22 @@ shader fill_fx_keyframe_boundary_approx compile("target_cs", "main_cs"); } +int dafx_fill_boundary_opt_frame_boundary_tmp_uav_no = 0; + shader fill_fx_keyframe_boundary_opt { - (cs){ + (cs) { dafx_fill_boundary_tex@tex2d = dafx_fill_boundary_tex; dafx_fill_boundary_params@f4 = dafx_fill_boundary_params; tile_size@f2 = (dafx_fill_boundary_params.z / dafx_fill_boundary_params.x, dafx_fill_boundary_params.w / dafx_fill_boundary_params.y); + dafx_frame_boundary_tmp@uav : register(dafx_fill_boundary_opt_frame_boundary_tmp_uav_no) hlsl { + RWStructuredBuffer dafx_frame_boundary_tmp@uav; + }; } ENABLE_ASSERT(cs) hlsl(cs) { - RWStructuredBuffer dafx_frame_boundary_tmp : register(u0); - #define BOUNDARY_CACHE_SIZE 8 ##if dafx_use_experimental_boundary_calc == yes @@ -254,18 +267,23 @@ shader fill_fx_keyframe_boundary_opt compile("target_cs", "main_cs"); } +int dafx_fill_boundary_opt_end_frame_boundary_result_uav_no = 0; + shader fill_fx_keyframe_boundary_opt_end { - (cs){ + (cs) { dafx_fill_boundary_params@f4 = dafx_fill_boundary_params; dafx_fill_boundary_offset@i1 = dafx_fill_boundary_offset; tile_size_inv@f2 = (dafx_fill_boundary_params.x / dafx_fill_boundary_params.z, dafx_fill_boundary_params.y / dafx_fill_boundary_params.w); dafx_frame_boundary_tmp@buf = dafx_frame_boundary_tmp hlsl { StructuredBuffer dafx_frame_boundary_tmp@buf; }; + frame_boundary_result@uav : register(dafx_fill_boundary_opt_end_frame_boundary_result_uav_no) hlsl { + RWStructuredBuffer frame_boundary_result@uav; + }; } + ENABLE_ASSERT(cs) - hlsl(cs) { - RWStructuredBuffer frame_boundary_result : register(u0); + hlsl(cs) { float4 transformInverseY(float4 boundary) { boundary.yw = 1 - boundary.wy; @@ -299,16 +317,20 @@ shader fill_fx_keyframe_boundary_opt_end compile("target_cs", "main_cs"); } +int dafx_clear_boundary_frame_boundary_result_uav_no = 0; shader clear_fx_keyframe_boundary { - (cs){ + (cs) { dafx_fill_boundary_count@i1 = dafx_fill_boundary_count; + frame_boundary_result@uav : register(dafx_clear_boundary_frame_boundary_result_uav_no) hlsl { + RWStructuredBuffer frame_boundary_result@uav; + }; } + ENABLE_ASSERT(cs) - hlsl(cs) { - RWStructuredBuffer frame_boundary_result : register(u0); + hlsl(cs) { [numthreads( 64, 1, 1 )] void main_cs( uint dtId : SV_DispatchThreadID ) { @@ -319,10 +341,11 @@ shader clear_fx_keyframe_boundary compile("target_cs", "main_cs"); } +int dafx_frame_boundary_debug_update_outputTex_uav_no = 0; shader frame_boundary_debug_update { - (cs){ + (cs) { dafx_fill_boundary_tex@smp2d = dafx_fill_boundary_tex; dafx_fill_boundary_params@f4 = dafx_fill_boundary_params; dafx_fill_boundary_offset@i1 = dafx_fill_boundary_offset; @@ -331,12 +354,12 @@ shader frame_boundary_debug_update tile_size_inv@f2 = (dafx_fill_boundary_params.x / dafx_fill_boundary_params.z, dafx_fill_boundary_params.y / dafx_fill_boundary_params.w); frames_inv@f2 = (1.0 / dafx_fill_boundary_params.x, 1.0 / dafx_fill_boundary_params.y, 0, 0); dafx_frame_boundary_buffer@buf = dafx_frame_boundary_buffer hlsl { StructuredBuffer dafx_frame_boundary_buffer@buf; }; + outputTex@uav : register(dafx_frame_boundary_debug_update_outputTex_uav_no) hlsl { RWTexture2D outputTex@uav; }; } - ENABLE_ASSERT(cs) - hlsl(cs) { - RWTexture2D outputTex : register(u0); + ENABLE_ASSERT(cs) + hlsl(cs) { float4 getTextureResult(uint2 dtId) { if (any(dtId >= (uint2)tile_size)) diff --git a/prog/commonFx/commonFxGame/modfx/modfx_bboard_render.hlsl b/prog/commonFx/commonFxGame/modfx/modfx_bboard_render.hlsl index 8dde2e597..79180e995 100644 --- a/prog/commonFx/commonFxGame/modfx/modfx_bboard_render.hlsl +++ b/prog/commonFx/commonFxGame/modfx/modfx_bboard_render.hlsl @@ -970,13 +970,19 @@ struct PsOutput #if DAFXEX_USE_REACTIVE_MASK float reactive : SV_Target1; #endif +#if MODFX_USE_DEPTH_OUTPUT + float depth : SV_Target1; +#endif }; -PsOutput encode_output(float4 color) +PsOutput encode_output(float4 color, float depth) { PsOutput output; output.color = color; #if DAFXEX_USE_REACTIVE_MASK output.reactive = color.a; +#endif +#if MODFX_USE_DEPTH_OUTPUT + output.depth = depth; #endif return output; } @@ -988,7 +994,7 @@ PsOutput encode_output(float4 color) #elif MODFX_SHADER_VOLSHAPE_WBOIT #define fx_null (WboitData)0 #else - #define fx_null encode_output(0) + #define fx_null encode_output(0, 0) #endif bool color_discard_test(float4 src, uint flags) @@ -1019,7 +1025,7 @@ bool color_discard_test(float4 src, uint flags) { #if MODFX_DEBUG_RENDER_ENABLED - PsOutput output = encode_output(0); + PsOutput output = encode_output(0, 0); #if !MODFX_RIBBON_SHAPE // TODO: add ribbon support for debug rendering output.color.xyz = modfx_pack_hdr(calc_debug_color(input.delta.xy)); #endif @@ -1336,7 +1342,7 @@ bool color_discard_test(float4 src, uint flags) float3 col = wboit_accum.xyz / clamp(wboit_accum.w, 0.0000001f, 1000.f); float a = 1.f - wboit_r; - return encode_output(float4(col * a, a) * alpha * a); + return encode_output(float4(col * a, a) * alpha * a, 0); #endif #endif @@ -1446,16 +1452,17 @@ bool color_discard_test(float4 src, uint flags) emissive_part *= alpha; float4 result = float4( emissive_part + lighting_part, alpha ); - + float depth = 0; #if MODFX_SHADER_DISTORTION float depthScene = tex2Dlod(haze_scene_depth_tex, float4(viewport_tc.xy,0, haze_scene_depth_tex_lod)).x; float depthHaze = GET_SCREEN_POS(input.pos).z; + depth = depthHaze; BRANCH if (depthHaze <= depthScene) { discard; - return encode_output(0); + return encode_output(0, 0); } float distortionMod = dafx_get_1f(0, parent_data.mods_offsets[MODFX_RMOD_DISTORTION_STRENGTH]); @@ -1514,7 +1521,7 @@ bool color_discard_test(float4 src, uint flags) result.xyz = modfx_pack_hdr( result.xyz ); clip_alpha( result.w ); result.w = 1.f; - return encode_output(result); + return encode_output(result, depth); #elif MODFX_SHADER_FOM @@ -1581,7 +1588,7 @@ bool color_discard_test(float4 src, uint flags) wboit_res.alpha = result.w * wboit_weight(cur_depth, result.w); return wboit_res; #else - return encode_output(result); + return encode_output(result, depth); #endif #endif diff --git a/prog/commonFx/commonFxGame/modfx_bboard_render.dshl b/prog/commonFx/commonFxGame/modfx_bboard_render.dshl index 03242edc3..15e651b55 100644 --- a/prog/commonFx/commonFxGame/modfx_bboard_render.dshl +++ b/prog/commonFx/commonFxGame/modfx_bboard_render.dshl @@ -37,6 +37,9 @@ float haze_scene_depth_tex_lod; define_macro_if_not_defined DAFX_USE_CLOUD_SHADOWS() endmacro +int dafx_modfx_g_tex_0_const_no = 10; +int dafx_modfx_g_tex_1_const_no = 11; + shader dafx_modfx_bboard_render, dafx_modfx_ribbon_render, dafx_modfx_ribbon_render_side_only, dafx_modfx_bboard_render_atest, dafx_modfx_bboard_distortion, dafx_modfx_ribbon_distortion, dafx_modfx_ribbon_distortion_side_only, dafx_modfx_bboard_thermals, dafx_modfx_bboard_render_fom, dafx_modfx_bboard_rain, dafx_modfx_bboard_rain_distortion, dafx_modfx_volshape_render, dafx_modfx_volshape_thermal, dafx_modfx_volshape_wboit_render, dafx_modfx_bboard_volfog_injection { ENABLE_ASSERT(ps) @@ -187,11 +190,14 @@ shader dafx_modfx_bboard_render, dafx_modfx_ribbon_render, dafx_modfx_ribbon_ren else if ( shader == dafx_modfx_bboard_distortion || shader == dafx_modfx_ribbon_distortion || shader == dafx_modfx_ribbon_distortion_side_only || shader == dafx_modfx_bboard_rain_distortion) { z_write =true; - blend_src=one; - blend_dst=one; + blend_src[0]=one; + blend_dst[0]=one; - blend_asrc=one; - blend_adst=one; + blend_asrc[0]=one; + blend_adst[0]=one; + + blend_src[1] = 1; blend_dst[1] = 1; + blend_op[1] = max; // reverse depth (ps) { @@ -209,7 +215,11 @@ shader dafx_modfx_bboard_render, dafx_modfx_ribbon_render, dafx_modfx_ribbon_ren hlsl { + #undef DAFXEX_USE_REACTIVE_MASK + #define DAFXEX_USE_REACTIVE_MASK 0 // Disable reactive mask for distortions, since they apply after txaa + #define MODFX_SHADER_DISTORTION 1 + #define MODFX_USE_DEPTH_OUTPUT 1 #undef HAS_STATIC_SHADOW #undef MODFX_USE_SHADOW @@ -387,14 +397,14 @@ shader dafx_modfx_bboard_render, dafx_modfx_ribbon_render, dafx_modfx_ribbon_ren #undef FX_VS } - hlsl(ps) + (ps) { - Texture2D g_tex_0 : register(t10); - SamplerState g_tex_0_samplerstate:register(s10); - - Texture2D g_tex_1 : register(t11); - SamplerState g_tex_1_samplerstate:register(s11); + g_tex_0@smp2d : register(dafx_modfx_g_tex_0_const_no); + g_tex_1@smp2d : register(dafx_modfx_g_tex_1_const_no); + } + hlsl(ps) + { #define FX_PS 1 #include "modfx/modfx_bboard_render.hlsl" #undef FX_PS @@ -450,6 +460,11 @@ shader dafx_modfx_bvh DAFXEX_USE_ABOVE_DEPTH_PLACEMENT() + (vs) + { + bvh_meta_id@i1 : register(dafx_modfx_bvh_meta_id_regno); + } + hlsl(vs) { #define MODFX_USE_FRAMEBLEND 1 @@ -466,8 +481,6 @@ shader dafx_modfx_bvh #include "modfx/modfx_bboard_render.hlsl" #undef FX_VS - int bvh_meta_id : register(c32); - #define ADD_SHADOW_INSTANCE 0 float4 dafx_bvh_vs(uint vertexId : SV_VertexID, uint instanceId : SV_InstanceID, uint draw_call_id : TEXCOORD0) : SV_Position diff --git a/prog/daNetGame/camera/stub/camstub.cpp b/prog/daNetGame/camera/stub/camstub.cpp index 4ab10efa5..e6e76bda7 100644 --- a/prog/daNetGame/camera/stub/camstub.cpp +++ b/prog/daNetGame/camera/stub/camstub.cpp @@ -27,6 +27,4 @@ ecs::EntityId enable_spectator_camera(const TMatrix &, int, ecs::EntityId) { ret void reset_all_cameras() {} ecs::EntityId get_cur_cam_entity() { return ecs::INVALID_ENTITY_ID; } ecs::EntityId set_scene_camera_entity(ecs::EntityId) { return ecs::INVALID_ENTITY_ID; } -CameraSetup get_active_camera_setup() { return CameraSetup(); } -void calc_camera_values(const CameraSetup &, TMatrix &viewTm, Driver3dPerspective &, int &, int &) { viewTm = TMatrix::IDENT; } TMatrix4 calc_active_camera_globtm() { return TMatrix4::IDENT; } diff --git a/prog/daNetGame/dasModules/websocket/webSocket.das b/prog/daNetGame/dasModules/websocket/webSocket.das index 51f84625f..e4afa416a 100644 --- a/prog/daNetGame/dasModules/websocket/webSocket.das +++ b/prog/daNetGame/dasModules/websocket/webSocket.das @@ -14,12 +14,12 @@ class WebSocket def init_path(port : int; document_root : string) : bool return websocket_init_path(_websocket, port, document_root) def restore(var shared_orphan : smart_ptr&) - _websocket <- shared_orphan + _websocket |> move() <| shared_orphan let classInfo = class_info(self) unsafe websocket_restore(_websocket, addr(self), classInfo) def save(var shared_orphan : smart_ptr&) - shared_orphan <- _websocket + shared_orphan |> move() <| _websocket def has_session : bool return _websocket != null def is_open : bool diff --git a/prog/daNetGame/game/capsuleApproximationCollisionsES.cpp.gen.es.cpp b/prog/daNetGame/game/capsuleApproximationCollisionsES.cpp.gen.es.cpp index 5cf4cb057..c0948a07e 100644 --- a/prog/daNetGame/game/capsuleApproximationCollisionsES.cpp.gen.es.cpp +++ b/prog/daNetGame/game/capsuleApproximationCollisionsES.cpp.gen.es.cpp @@ -61,7 +61,7 @@ static ecs::EntitySystemDesc capsules_collisions_es_es_desc empty_span(), ecs::EventSetBuilder::build(), 0 -,"render",nullptr,nullptr,"animchar_before_render_es"); +,"render",nullptr,"*"); static constexpr ecs::ComponentDesc get_attached_to_capsules_preprocess_ecs_query_comps[] = { //start of 1 rw components at [0] diff --git a/prog/daNetGame/game/capsuleApproximationCollisionsES.cpp.inl b/prog/daNetGame/game/capsuleApproximationCollisionsES.cpp.inl index 7aab41b98..c7e067e33 100644 --- a/prog/daNetGame/game/capsuleApproximationCollisionsES.cpp.inl +++ b/prog/daNetGame/game/capsuleApproximationCollisionsES.cpp.inl @@ -44,7 +44,7 @@ void capsules_collision_on_appear_es(const ecs::Event &, } ECS_TAG(render) -ECS_AFTER(animchar_before_render_es) +ECS_NO_ORDER void capsules_collisions_es(const UpdateStageInfoBeforeRender &, ecs::EntityId &slot_attach__attachedTo, ecs::IntList &capsule_approximation_collisions_ids, diff --git a/prog/daNetGame/game/riDestr.h b/prog/daNetGame/game/riDestr.h index 0fd16f95f..869736a1f 100644 --- a/prog/daNetGame/game/riDestr.h +++ b/prog/daNetGame/game/riDestr.h @@ -1,6 +1,8 @@ // Copyright (C) Gaijin Games KFT. All rights reserved. #pragma once +class TMatrix; +class TMatrix4; namespace net { class IConnection; diff --git a/prog/daNetGame/game/riDestrES.cpp.inl b/prog/daNetGame/game/riDestrES.cpp.inl index fe1b99f79..56a29075c 100644 --- a/prog/daNetGame/game/riDestrES.cpp.inl +++ b/prog/daNetGame/game/riDestrES.cpp.inl @@ -1,7 +1,5 @@ // Copyright (C) Gaijin Games KFT. All rights reserved. -#include - #include "game/riDestr.h" #include "game/gameEvents.h" #include "main/level.h" @@ -548,7 +546,7 @@ void update(float dt, const TMatrix4 &glob_tm) else flush_dirty_ri_destr_msg(); } - else // FIXME: used camera matrix from previous frame + else { const Frustum frustum(glob_tm); rendinstdestr::update(dt, &frustum); diff --git a/prog/daNetGame/main/app.cpp b/prog/daNetGame/main/app.cpp index a1d3a3f30..7c8923158 100644 --- a/prog/daNetGame/main/app.cpp +++ b/prog/daNetGame/main/app.cpp @@ -197,15 +197,6 @@ void update(float dt, float real_dt, float cur_time) imgui_update(); - TMatrix viewTm; - TMatrix4 projTm; - Driver3dPerspective persp; - int view_w, view_h; - CameraSetup cameraSetup = get_active_camera_setup(); - calc_camera_values(cameraSetup, viewTm, persp, view_w, view_h); - d3d::calcproj(persp, projTm); - TMatrix4 globTm = TMatrix4(viewTm) * projTm; - { if (is_level_loaded()) g_entity_mgr->update(ecs::UpdateStageInfoAct(dt, cur_time)); @@ -220,7 +211,7 @@ void update(float dt, float real_dt, float cur_time) if (dedicated::is_dedicated()) g_entity_mgr->broadcastEventImmediate(ParallelUpdateFrameDelayed(dt, cur_time)); net_send_phys_snapshots(cur_time, dt); // after all phys/anim updates - ridestr::update(dt, globTm); + ridestr::update(dt, calc_active_camera_globtm()); } } g_entity_mgr->broadcastEventImmediate(UpdateStageGameLogic(dt, cur_time)); diff --git a/prog/daNetGame/main/main.cpp b/prog/daNetGame/main/main.cpp index eebf727a4..5d5919c78 100644 --- a/prog/daNetGame/main/main.cpp +++ b/prog/daNetGame/main/main.cpp @@ -402,7 +402,7 @@ static void post_shutdown_handler() DEBUG_CTX("shutdown because of '%s'!", quit_reason); #if _TARGET_PC - if (!dedicated::is_dedicated()) + if (!dedicated::is_dedicated() && dgs_get_settings()->getBool("launchCountTelemetry", true)) { get_settings_override_blk()->setBool("launchCorrectExit", true); save_settings(nullptr, false); @@ -1035,10 +1035,13 @@ int DagorWinMain(int nCmdShow, bool /*debugmode*/) { send_first_run_event(); #if _TARGET_PC - bool lastLaunchFailed = !dgs_get_settings()->getBool("launchCorrectExit", true); - get_settings_override_blk()->setBool("incorrectExitWarning", lastLaunchFailed); - get_settings_override_blk()->setBool("launchCorrectExit", false); - save_settings(nullptr, false); + if (dgs_get_settings()->getBool("launchCountTelemetry", true)) + { + bool lastLaunchFailed = !dgs_get_settings()->getBool("launchCorrectExit", true); + get_settings_override_blk()->setBool("incorrectExitWarning", lastLaunchFailed); + get_settings_override_blk()->setBool("launchCorrectExit", false); + save_settings(nullptr, false); + } #endif } diff --git a/prog/daNetGame/net/telemetry.cpp b/prog/daNetGame/net/telemetry.cpp index 7e4c01e42..a9e3805e7 100644 --- a/prog/daNetGame/net/telemetry.cpp +++ b/prog/daNetGame/net/telemetry.cpp @@ -227,6 +227,8 @@ int on_debug_log(int lev_tag, const char *fmt, const void *arg, int anum, const void send_first_run_event() { + if (!dgs_get_settings()->getBool("launchCountTelemetry", true)) + return; int launchCnt = dgs_get_settings()->getInt("launchCnt", 0); get_settings_override_blk()->setInt("launchCnt", launchCnt + 1); save_settings(nullptr, false); diff --git a/prog/daNetGame/render/drawScene.cpp b/prog/daNetGame/render/drawScene.cpp index 46ad77688..65df26f2c 100644 --- a/prog/daNetGame/render/drawScene.cpp +++ b/prog/daNetGame/render/drawScene.cpp @@ -69,7 +69,6 @@ #include #include #include -#include CONSOLE_INT_VAL("app", sleep_msec_val, 0, 0, 1000); CONSOLE_BOOL_VAL("app", screenshot_hide_debug, true); @@ -117,6 +116,8 @@ static class AdditionalGameJob final : public cpujobs::IJob } void doJob() override { + static bool gpuLatencyWait = dgs_get_settings()->getBlockByName("video")->getBool("pufdGpuLatencyWait", true); + if (gpuLatencyWait) { TIME_PROFILE(gpu_latency_wait); d3d::gpu_latency_wait(); @@ -144,14 +145,12 @@ static class AdditionalGameJob final : public cpujobs::IJob static inline void wait_additional_game_job_done() { - workcycleperf::mark_cpu_only_cycle_pause(); if (!interlocked_acquire_load(additional_game_job.done)) { TIME_PROFILE(wait_additional_game_job_done); threadpool::wait(&additional_game_job); } bind_dascript::enable_thread_safe_das_ctx_region(false); - workcycleperf::mark_cpu_only_cycle_start(); } void render_scene_debug(BaseTexture *target, BaseTexture *depth, const CameraParams &camera) diff --git a/prog/daNetGame/render/heroData.h b/prog/daNetGame/render/heroData.h new file mode 100644 index 000000000..3d4575762 --- /dev/null +++ b/prog/daNetGame/render/heroData.h @@ -0,0 +1,18 @@ +// Copyright (C) Gaijin Games KFT. All rights reserved. +#pragma once + +#include + +struct HeroWtmAndBox +{ + mutable mat44f resWtm = {}; + mutable vec3f resWofs = {}; + mutable bbox3f resLbox = {}; + mutable bool resReady = false; + enum + { + WEAPON = 1, + VEHICLE = 2 + }; + mutable uint8_t resFlags = 0; // WEAPON|VEHICLE +}; \ No newline at end of file diff --git a/prog/daNetGame/render/renderEvent.h b/prog/daNetGame/render/renderEvent.h index 9f9bea4a0..720b3856f 100644 --- a/prog/daNetGame/render/renderEvent.h +++ b/prog/daNetGame/render/renderEvent.h @@ -13,6 +13,7 @@ #include "rendererFeatures.h" #include <3d/dag_texStreamingContext.h> #include +#include #include #include #include @@ -289,21 +290,10 @@ struct UpdateStageInfoRenderDistortion : public ecs::Event, public TransformHold {} }; -struct QueryHeroWtmAndBoxForRender : public ecs::Event +struct QueryHeroWtmAndBoxForRender : public ecs::Event, public HeroWtmAndBox { - // result - mutable mat44f resWtm = {}; - mutable vec3f resWofs = {}; - mutable bbox3f resLbox = {}; - mutable bool resReady = false; // parameters bool onlyWeapons = false; - enum - { - WEAPON = 1, - VEHICLE = 2 - }; - mutable uint8_t resFlags = 0; // WEAPON|VEHICLE ECS_UNICAST_EVENT_DECL(QueryHeroWtmAndBoxForRender) QueryHeroWtmAndBoxForRender(bool weap_only = false) : ECS_EVENT_CONSTRUCTOR(QueryHeroWtmAndBoxForRender), onlyWeapons(weap_only) {} diff --git a/prog/daNetGame/render/temporalSuperResolution.cpp b/prog/daNetGame/render/temporalSuperResolution.cpp index 0b21a2154..aa3b8c5c2 100644 --- a/prog/daNetGame/render/temporalSuperResolution.cpp +++ b/prog/daNetGame/render/temporalSuperResolution.cpp @@ -160,6 +160,8 @@ TemporalSuperResolution::TemporalSuperResolution(const IPoint2 &output_resolutio auto cameraHndl = registry.readBlob("current_camera").handle(); + registry.readBlob("motion_vector_access_token"); + return [this, opaqueFinalTargetHndl, antialiasedHndl, antialiasedHistHndl, confidenceHndl, confidenceHistHndl, cameraHndl] { set_viewvecs_to_shader(cameraHndl.ref().viewTm, cameraHndl.ref().jitterProjTm); tsr_render(TextureIDPair{opaqueFinalTargetHndl.view().getTex2D(), opaqueFinalTargetHndl.view().getTexId()}, diff --git a/prog/daNetGame/render/world/cameraParams.h b/prog/daNetGame/render/world/cameraParams.h index a4160dcdd..99c6950ad 100644 --- a/prog/daNetGame/render/world/cameraParams.h +++ b/prog/daNetGame/render/world/cameraParams.h @@ -28,6 +28,8 @@ struct CameraParams TMatrix4_vec4 jitterProjTm = TMatrix4::IDENT; TMatrix4_vec4 jitterGlobtm = TMatrix4::IDENT; + Point2 jitterOffsetUv; + Frustum noJitterFrustum; Frustum jitterFrustum; float znear = 0.01, zfar = 1000; diff --git a/prog/daNetGame/render/world/depthAOAbove.cpp b/prog/daNetGame/render/world/depthAOAbove.cpp index 1f3d92c8c..2a8369df3 100644 --- a/prog/daNetGame/render/world/depthAOAbove.cpp +++ b/prog/daNetGame/render/world/depthAOAbove.cpp @@ -148,6 +148,12 @@ bool DepthAOAboveContext::prepare(const Point3 &view_pos, float scene_min_z, flo return tpJobsAdded; } +void DepthAOAboveContext::waitCullJobs() +{ + for (auto &j : cullJobs) + threadpool::wait(&j); +} + void DepthAOAboveContext::render(WorldRenderer &wr, const TMatrix &view_itm) { FRAME_LAYER_GUARD(globalFrameBlockId); diff --git a/prog/daNetGame/render/world/depthAOAbove.h b/prog/daNetGame/render/world/depthAOAbove.h index b45acb33c..fe5087fdf 100644 --- a/prog/daNetGame/render/world/depthAOAbove.h +++ b/prog/daNetGame/render/world/depthAOAbove.h @@ -20,8 +20,9 @@ class DepthAOAboveContext bool prepare(const Point3 &view_pos, float scene_min_z, float scene_max_z); // Return true if some tp jobs were added void render(WorldRenderer &wr, const TMatrix &view_itm); - inline void invalidateAO(bool force) { renderer.invalidateAO(force); } - inline void invalidateAO(const BBox3 &box) { renderer.invalidateAO(box); } + void invalidateAO(bool force) { renderer.invalidateAO(force); } + void invalidateAO(const BBox3 &box) { renderer.invalidateAO(box); } + void waitCullJobs(); private: static const int g_max_visibility_jobs = 8; diff --git a/prog/daNetGame/render/world/frameGraphNodes/environmentNode.cpp b/prog/daNetGame/render/world/frameGraphNodes/environmentNode.cpp index b0dd53b51..403315efa 100644 --- a/prog/daNetGame/render/world/frameGraphNodes/environmentNode.cpp +++ b/prog/daNetGame/render/world/frameGraphNodes/environmentNode.cpp @@ -13,6 +13,7 @@ #include #include "frameGraphNodes.h" +#include #include @@ -68,6 +69,8 @@ eastl::fixed_vector makeEnvironmentNodes() result.push_back(dabfg::register_node("render_skies", DABFG_PP_NODE_SRC, [panorama](dabfg::Registry registry) { auto state = registry.requestState(); + use_volfog(registry, dabfg::Stage::PS_OR_CS); + // Optimization: keep the depth in RO state auto pass = registry.requestRenderPass() .color({"opaque_with_envi"}) diff --git a/prog/daNetGame/render/world/frameGraphNodes/frameGraphNodes.h b/prog/daNetGame/render/world/frameGraphNodes/frameGraphNodes.h index c7045efd3..e8bf42662 100644 --- a/prog/daNetGame/render/world/frameGraphNodes/frameGraphNodes.h +++ b/prog/daNetGame/render/world/frameGraphNodes/frameGraphNodes.h @@ -105,7 +105,7 @@ dabfg::NodeHandle makeGiFeedbackNode(); dabfg::NodeHandle makeGiScreenDebugNode(); dabfg::NodeHandle makeGiScreenDebugDepthNode(); -dabfg::NodeHandle makeDeferredLightNode(); +dabfg::NodeHandle makeDeferredLightNode(bool need_reprojection); dabfg::NodeHandle makeResolveGbufferNode(const char *resolve_pshader_name, const char *resolve_cshader_name, const char *classify_cshader_name, diff --git a/prog/daNetGame/render/world/frameGraphNodes/gbufferNodes.cpp b/prog/daNetGame/render/world/frameGraphNodes/gbufferNodes.cpp index 83a7bf748..a12bb0ceb 100644 --- a/prog/daNetGame/render/world/frameGraphNodes/gbufferNodes.cpp +++ b/prog/daNetGame/render/world/frameGraphNodes/gbufferNodes.cpp @@ -174,11 +174,12 @@ static inline float w_to_depth(float w, const Point2 &zNearFar, float def) } #define RESOLVE_GBUFFER_SHADERVARS \ + VAR(reproject_screen_gi, true) \ VAR(thin_gbuf_resolve, true) \ VAR(frame_tex, false) \ VAR(use_rtr, true) -#define VAR(a, o) static int a##VarId = -1; +#define VAR(a, o) static ShaderVariableInfo a##VarId(#a, o); RESOLVE_GBUFFER_SHADERVARS #undef VAR @@ -186,13 +187,17 @@ RESOLVE_GBUFFER_SHADERVARS // CONSOLE_BOOL_VAL("render", deferred_light_on_compute, false); // deferredLightCompute = Ptr(new_compute_shader("deferred_light_compute")) // And instead of render target just set current_specular and current_ambient as @uav shadervars -dabfg::NodeHandle makeDeferredLightNode() +dabfg::NodeHandle makeDeferredLightNode(bool reprojectGI) { - return dabfg::register_node("deferred_light_node", DABFG_PP_NODE_SRC, [](dabfg::Registry registry) { - auto currentSpecularHndl = registry.create("current_specular", dabfg::History::No) - .texture({TEXFMT_R11G11B10F | TEXCF_RTARGET, registry.getResolution<2>("main_view"), 1}); - auto currentAmbientHndl = registry.create("current_ambient", dabfg::History::No) - .texture({TEXFMT_R11G11B10F | TEXCF_RTARGET, registry.getResolution<2>("main_view"), 1}); + return dabfg::register_node("deferred_light_node", DABFG_PP_NODE_SRC, [reprojectGI](dabfg::Registry registry) { + auto giHistory = reprojectGI ? dabfg::History::ClearZeroOnFirstFrame : dabfg::History::No; + const uint32_t gi_fmt = reprojectGI && d3d::check_texformat(TEXFMT_R9G9B9E5 | TEXCF_RTARGET) ? TEXFMT_R9G9B9E5 : TEXFMT_R11G11B10F; + + auto currentSpecularHndl = + registry.create("current_specular", giHistory).texture({gi_fmt | TEXCF_RTARGET, registry.getResolution<2>("main_view"), 1}); + auto currentAmbientHndl = + registry.create("current_ambient", giHistory).texture({gi_fmt | TEXCF_RTARGET, registry.getResolution<2>("main_view"), 1}); + d3d::SamplerInfo smpInfo; smpInfo.address_mode_u = smpInfo.address_mode_v = smpInfo.address_mode_w = d3d::AddressMode::Clamp; registry.create("current_ambient_sampler", dabfg::History::No).blob(d3d::request_sampler(smpInfo)); @@ -203,19 +208,41 @@ dabfg::NodeHandle makeDeferredLightNode() registry.read("gbuf_sampler").blob().bindToShaderVar("normal_gbuf_samplerstate"); registry.read("gbuf_2").texture().atStage(dabfg::Stage::PS).bindToShaderVar("material_gbuf"); registry.read("gbuf_sampler").blob().bindToShaderVar("material_gbuf_samplerstate"); + registry.read("motion_vecs").texture().atStage(dabfg::Stage::PS_OR_CS).bindToShaderVar("motion_gbuf").optional(); + registry.read("gbuf_sampler").blob().bindToShaderVar("motion_gbuf_samplerstate").optional(); auto stateRequest = registry.requestState().setFrameBlock("global_frame"); - auto renderPass = registry.requestRenderPass().color({currentSpecularHndl, currentAmbientHndl}); - if (depth_bounds_enabled()) + auto depthBoundsSet = [&](dabfg::VirtualPassRequest &renderPass) { + if (depth_bounds_enabled()) + { + shaders::OverrideState state; + state.set(shaders::OverrideState::Z_BOUNDS_ENABLED); + eastl::move(stateRequest).enableOverride(state); + eastl::move(renderPass).depthRoAndBindToShaderVars(gbufDepthHndl, {"depth_gbuf"}); + } + else + eastl::move(gbufDepthHndl).atStage(dabfg::Stage::PS).bindToShaderVar("depth_gbuf"); + }; + + if (reprojectGI) { - shaders::OverrideState state; - state.set(shaders::OverrideState::Z_BOUNDS_ENABLED); - eastl::move(stateRequest).enableOverride(state); - eastl::move(renderPass).depthRoAndBindToShaderVars(gbufDepthHndl, {"depth_gbuf"}); + registry.historyFor("depth_for_postfx").texture().atStage(dabfg::Stage::PS).bindToShaderVar("prev_gbuf_depth"); + auto currentAgeHndl = registry.create("current_gi_pixel_age", dabfg::History::ClearZeroOnFirstFrame) + .texture({TEXFMT_R8UI | TEXCF_RTARGET, registry.getResolution<2>("main_view"), 1}); + registry.historyFor("current_gi_pixel_age").texture().atStage(dabfg::Stage::PS).bindToShaderVar("prev_gi_pixel_age"); + registry.historyFor("current_specular").texture().atStage(dabfg::Stage::PS).bindToShaderVar("prev_specular"); + registry.historyFor("current_ambient").texture().atStage(dabfg::Stage::PS).bindToShaderVar("prev_ambient"); + auto renderPass = registry.requestRenderPass().color({currentSpecularHndl, currentAmbientHndl, currentAgeHndl}); + depthBoundsSet(renderPass); } else - eastl::move(gbufDepthHndl).atStage(dabfg::Stage::PS).bindToShaderVar("depth_gbuf"); + { + auto renderPass = registry.requestRenderPass().color({currentSpecularHndl, currentAmbientHndl}); + depthBoundsSet(renderPass); + } + ShaderGlobal::set_int(reproject_screen_giVarId, reprojectGI ? 1 : 0); + registry.read("gi_before_frame_lit_token").blob().optional(); @@ -241,9 +268,6 @@ dabfg::NodeHandle makeResolveGbufferNode(const char *resolve_pshader_name, const char *classify_cshader_name, const ShadingResolver::PermutationsDesc &permutations_desc) { -#define VAR(a, o) a##VarId = get_shader_variable_id(#a, o); - RESOLVE_GBUFFER_SHADERVARS -#undef VAR return dabfg::register_node("resolve_gbuffer_node", DABFG_PP_NODE_SRC, [resolve_pshader_name, resolve_cshader_name, classify_cshader_name, permutations_desc](dabfg::Registry registry) { auto &wr = *static_cast(get_world_renderer()); diff --git a/prog/daNetGame/render/world/frameGraphNodes/postFxNodes.cpp b/prog/daNetGame/render/world/frameGraphNodes/postFxNodes.cpp index 9156abef8..f15cdb504 100644 --- a/prog/daNetGame/render/world/frameGraphNodes/postFxNodes.cpp +++ b/prog/daNetGame/render/world/frameGraphNodes/postFxNodes.cpp @@ -347,6 +347,8 @@ dabfg::NodeHandle makeDistortionFxNode() auto distortionPostfxRequired = registry.readBlob("distortion_postfx_required").handle(); + registry.readTexture("depth_after_transparency").atStage(dabfg::Stage::PS).bindToShaderVar("haze_scene_depth_tex"); + registry.readTexture("haze_offset").atStage(dabfg::Stage::POST_RASTER).bindToShaderVar("haze_offset_tex").optional(); registry.create("haze_default_sampler", dabfg::History::No) .blob(d3d::request_sampler({})) diff --git a/prog/daNetGame/render/world/global_vars.h b/prog/daNetGame/render/world/global_vars.h index 9dfe46c6e..e8bfff98d 100644 --- a/prog/daNetGame/render/world/global_vars.h +++ b/prog/daNetGame/render/world/global_vars.h @@ -100,6 +100,7 @@ VAR(lens_frame_tex) \ VAR(lens_frame_tex_samplerstate) \ VAR(lens_distortion_params) \ + VAR(lens_brighthness) \ VAR(jitteredCamPosToUnjitteredHistoryClip) \ VAR(prev_to_cur_origin_move) \ VAR(prevViewProjTm0) \ diff --git a/prog/daNetGame/render/world/gpuDeformObjectsES.cpp.gen.es.cpp b/prog/daNetGame/render/world/gpuDeformObjectsES.cpp.gen.es.cpp index 57e086bb9..7768d84b9 100644 --- a/prog/daNetGame/render/world/gpuDeformObjectsES.cpp.gen.es.cpp +++ b/prog/daNetGame/render/world/gpuDeformObjectsES.cpp.gen.es.cpp @@ -2,6 +2,36 @@ ECS_DEF_PULL_VAR(gpuDeformObjects); //built with ECS codegen version 1.0 #include +static constexpr ecs::ComponentDesc gpu_deform_objects_manager_draw_debug_geometry_es_comps[] = +{ +//start of 3 ro components at [0] + {ECS_HASH("transform"), ecs::ComponentTypeInfo()}, + {ECS_HASH("deform_bbox__bmin"), ecs::ComponentTypeInfo()}, + {ECS_HASH("deform_bbox__bmax"), ecs::ComponentTypeInfo()} +}; +static void gpu_deform_objects_manager_draw_debug_geometry_es_all(const ecs::UpdateStageInfo &__restrict info, const ecs::QueryView & __restrict components) +{ + auto comp = components.begin(), compE = components.end(); G_ASSERT(comp!=compE); + do + gpu_deform_objects_manager_draw_debug_geometry_es(*info.cast() + , ECS_RO_COMP(gpu_deform_objects_manager_draw_debug_geometry_es_comps, "transform", TMatrix) + , ECS_RO_COMP(gpu_deform_objects_manager_draw_debug_geometry_es_comps, "deform_bbox__bmin", Point3) + , ECS_RO_COMP(gpu_deform_objects_manager_draw_debug_geometry_es_comps, "deform_bbox__bmax", Point3) + ); + while (++comp != compE); +} +static ecs::EntitySystemDesc gpu_deform_objects_manager_draw_debug_geometry_es_es_desc +( + "gpu_deform_objects_manager_draw_debug_geometry_es", + "prog/daNetGame/render/world/gpuDeformObjectsES.cpp.inl", + ecs::EntitySystemOps(gpu_deform_objects_manager_draw_debug_geometry_es_all), + empty_span(), + make_span(gpu_deform_objects_manager_draw_debug_geometry_es_comps+0, 3)/*ro*/, + empty_span(), + empty_span(), + ecs::EventSetBuilder<>::build(), + (1< #include +#include #include #include #include #include #include #include +#include #include "gpuDeformObjects.h" #include "shaders/obstacleStruct.hlsli" #include #include +#include +#include +#include +#include + +CONSOLE_BOOL_VAL("obstacles", show_obstacles, false); enum { @@ -33,6 +41,17 @@ void GpuDeformObjectsManager::fillEmpty() setEmpty(); } +static BBox3 create_inflated_bbox(const BBox3 &box, const TMatrix &tm) +{ + BBox3 inflatedBox = box; + // Add 1 meter to the bbox's height + Point3 pt = box.center() + orthonormalized_inverse(tm).getcol(1); + inflatedBox += pt; + inflatedBox[0] -= Point3(0.25, 0.25, 0.25); + inflatedBox[1] += Point3(0.25, 0.25, 0.25); + return inflatedBox; +} + void GpuDeformObjectsManager::updateDeforms() { TIME_PROFILE(update_deforms); @@ -51,7 +70,7 @@ void GpuDeformObjectsManager::updateDeforms() carray gridCrd; const float dist = float(width) * 0.5f * cellSize; Point2 indirection_lt; - indirection_lt = Point2::xz(origin) - Point2(dist, dist); + indirection_lt = floor(Point2::xz(origin) / cellSize) * cellSize - Point2(dist, dist); // box[1] = indirection_lt + Point2(totalDist, totalDist); ObstaclesData *deformsCBPtr = 0; if (!deformsCB.getBuf()->lock(0, sizeof(ObstaclesData), (void **)&deformsCBPtr, VBLOCK_WRITEONLY | VBLOCK_DISCARD) || !deformsCBPtr) @@ -71,11 +90,7 @@ void GpuDeformObjectsManager::updateDeforms() if (usedObstaclesCount >= MAX_OBSTACLES || lengthSq(tm.getcol(3) - origin) > maxDistPreCheckSq) return; BBox3 box(deform_bbox__bmin, deform_bbox__bmax); - BBox3 inflatedBox = box; - Point3 pt = box.center() + orthonormalized_inverse(tm).getcol(1); - inflatedBox += pt; - inflatedBox[0] -= Point3(0.25, 0.25, 0.25); - inflatedBox[1] += Point3(0.25, 0.25, 0.25); + BBox3 inflatedBox = create_inflated_bbox(box, tm); // intenipnally instead of scale, use fixed grass size. Regardless of a size of objet, grass should collide with soft offset BBox3 oBox = tm * inflatedBox; IPoint2 lt = ipoint2(floor((Point2::xz(oBox[0]) - indirection_lt - Point2(0.5, 0.5)) / cellSize)); @@ -188,3 +203,16 @@ void GpuDeformObjectsManager::initIndicesBuffer(uint32_t max_indices) unsigned sbcf = SBCF_DYNAMIC | SBCF_CPU_ACCESS_WRITE | SBCF_BIND_SHADER_RES | SBCF_MISC_STRUCTURED; indices = dag::create_sbuffer(sizeof(uint32_t), width * width + max_indices, sbcf, 0, "obstacle_indices_buf"); } + +ECS_TAG(render, dev) +ECS_NO_ORDER +static void gpu_deform_objects_manager_draw_debug_geometry_es( + const ecs::UpdateStageInfoRenderDebug &, const TMatrix &transform, const Point3 &deform_bbox__bmin, const Point3 &deform_bbox__bmax) +{ + if (!show_obstacles) + return; + + BBox3 box(deform_bbox__bmin, deform_bbox__bmax); + BBox3 inflatedBox = create_inflated_bbox(box, transform); + draw_debug_box_buffered(inflatedBox, transform, E3DCOLOR_MAKE(0, 0, 255, 255)); +} diff --git a/prog/daNetGame/render/world/private_worldRenderer.h b/prog/daNetGame/render/world/private_worldRenderer.h index a647acb85..78828aab6 100644 --- a/prog/daNetGame/render/world/private_worldRenderer.h +++ b/prog/daNetGame/render/world/private_worldRenderer.h @@ -40,6 +40,8 @@ #include #include #include +#include +#include #include "satelliteRenderer.h" #include "antiAliasingMode.h" @@ -379,6 +381,7 @@ class WorldRenderer final : public IRenderWorld, public IShadowInfoProvider void createVolumetricLightsNode(); void createGiNodes(); void createResolveGbufferNode(); + void createDeferredLightNode(); void createUINodes(); static WaterRenderMode determineWaterRenderMode(bool underWater, bool belowClouds); @@ -621,6 +624,12 @@ class WorldRenderer final : public IRenderWorld, public IShadowInfoProvider TMatrix itm; } depthAOAboveData; + void invalidate() + { + lightProbeData.render = false; + lightProbeData.texPtr = nullptr; + depthAOAboveData.render = false; + } } delayedRenderCtx; bool prepareDelayedRender(const TMatrix &itm); // Return true if some tp jobs were added @@ -934,6 +943,9 @@ class WorldRenderer final : public IRenderWorld, public IShadowInfoProvider void applyStaticUpsampleQuality(); AntiAliasingMode currentAntiAliasingMode = AntiAliasingMode::TSR; + bool hasDepthHistory = false; + dabfg::NodeHandle prepareDepthForPostFxNode; + void makePrepareDepthForPostFxNode(); int msaaQuality = 0; eastl::unique_ptr antiAliasing; #if !_TARGET_PC && !_TARGET_ANDROID && !_TARGET_IOS && !_TARGET_C3 @@ -1156,6 +1168,7 @@ class WorldRenderer final : public IRenderWorld, public IShadowInfoProvider void drawGIDebug(const Frustum &camera_frustum); void invalidateGI(bool force); void setGIQualityFromSettings(); + bool giNeedsReprojection(); void initFsr(const IPoint2 &postfx_resolution, const IPoint2 &display_resolution); void closeFsr(); @@ -1176,8 +1189,9 @@ class WorldRenderer final : public IRenderWorld, public IShadowInfoProvider void resetLatencyMode(); void resetPerformanceMetrics(); - void updateHeroMatrix(const DPoint3 &world_pos); + void updateHeroData(); + HeroWtmAndBox heroData; CameraParams currentFrameCamera; CameraParams prevFrameCamera; TexStreamingContext currentTexCtx = TexStreamingContext(0); @@ -1207,9 +1221,6 @@ class WorldRenderer final : public IRenderWorld, public IShadowInfoProvider eastl::unique_ptr staticSceneCollisionResource; - mat44f oldHeroGunOrVehicleTm; - DPoint3 oldWorldPos; - BBox3 worldBBox; BBox3 additionalBBox; diff --git a/prog/daNetGame/render/world/shadowsManager.cpp b/prog/daNetGame/render/world/shadowsManager.cpp index a25aac08a..aa0b2d209 100644 --- a/prog/daNetGame/render/world/shadowsManager.cpp +++ b/prog/daNetGame/render/world/shadowsManager.cpp @@ -514,14 +514,14 @@ struct StaticShadowCullJob final : public cpujobs::IJob DAG_DECLARE_RELOCATABLE(StaticShadowCullJob); static dag::RelocatableFixedVector static_shadow_jobs[ShadowsManager::MAX_NUM_STATIC_SHADOWS_CASCADES]; -static void free_overflowed_static_shadow_cull_jobs() +void wait_static_shadows_cull_jobs() { for (auto &jobs : static_shadow_jobs) { - for ([[maybe_unused]] auto &j : jobs) - G_ASSERT(interlocked_relaxed_load(j.done)); // Expected to be waited on by `renderStaticShadowsRegion` + for (auto &j : jobs) + threadpool::wait(&j); if (DAGOR_UNLIKELY(jobs.size() > jobs.static_size)) // Overflowed? - jobs.clear(); + jobs.resize(jobs.static_size); } } @@ -841,7 +841,7 @@ void ShadowsManager::renderStaticShadows() staticShadows->render(cb); if (staticShadowsSetShaderVars) staticShadows->setShaderVars(); - free_overflowed_static_shadow_cull_jobs(); + wait_static_shadows_cull_jobs(); // Free overflowed jobs } } diff --git a/prog/daNetGame/render/world/worldRenderer.cpp b/prog/daNetGame/render/world/worldRenderer.cpp index da4e76f9b..0951b489c 100644 --- a/prog/daNetGame/render/world/worldRenderer.cpp +++ b/prog/daNetGame/render/world/worldRenderer.cpp @@ -43,6 +43,7 @@ #include #include #include +#include // dagor_work_cycle_is_need_to_draw #include #include @@ -185,7 +186,6 @@ extern void term_fx(); extern void add_volfog_optional_graphs(); extern void set_nightly_spot_lights(); - #if _TARGET_PC_WIN && DAGOR_DBGLEVEL == 0 extern int optimus_pull_var; int loc_optimus_pull_var = optimus_pull_var; @@ -1396,6 +1396,7 @@ void WorldRenderer::afterDeviceReset(bool full_reset) closeResetable(); initResetable(); resetGI(); + delayedRenderCtx.invalidate(); invalidateCube(); reinitSpecularCubesContainerIfNeeded(); onSceneLoaded(binScene); @@ -1867,6 +1868,8 @@ void WorldRenderer::setResolution() ssaaNode = {}; prepareForPostfxNoAANode = makePrepareForPostfxNoAANode(); } + motion_vector_access::set_motion_vector_type( + needMotionVectors() ? motion_vector_access::MotionVectorType::DynamicUVZ : motion_vector_access::MotionVectorType::StaticUVZ); initStaticUpsample(displayResolution, postFxResolution); // Used on consoles and bareMinimum G_ASSERTF(!isFXAAEnabled() || resolutionScaleMode != RESOLUTION_SCALE_POSTFX, "FXAA must run in render resolution! video/upscaleInPostfx should be off"); @@ -2333,7 +2336,9 @@ static void hang_gpu() if (!gpu_hang_cs) gpu_hang_cs.reset((new_compute_shader("hang_gpu_cs", false))); - d3d::set_rwtex(STAGE_CS, 7, gpu_hang_uav.getBaseTex(), 0, 0, true); + static int gpu_hang_uav_no = ShaderGlobal::get_slot_by_name("gpu_hang_uav_no"); + + d3d::set_rwtex(STAGE_CS, gpu_hang_uav_no, gpu_hang_uav.getBaseTex(), 0, 0, true); gpu_hang_cs->dispatch(10, 10, 1); } @@ -2593,6 +2598,15 @@ void WorldRenderer::setFilmGrainFromSettings() template using BlobHandle = dabfg::VirtualResourceHandle; +void WorldRenderer::makePrepareDepthForPostFxNode() +{ + const bool aaNeedsHistory = antiAliasing && antiAliasing->needDepthHistory(); + const bool giNeedsHistory = giNeedsReprojection(); + const bool needHistory = aaNeedsHistory || giNeedsHistory; + if (hasDepthHistory != needHistory || !prepareDepthForPostFxNode) + prepareDepthForPostFxNode = ::makePrepareDepthForPostFxNode(hasDepthHistory = needHistory); +} + void WorldRenderer::createNodes() { fgNodeHandles.clear(); @@ -2633,7 +2647,7 @@ void WorldRenderer::createNodes() fgNodeHandles.emplace_back(factory()); } - fgNodeHandles.emplace_back(makePrepareDepthForPostFxNode(antiAliasing && antiAliasing->needDepthHistory())); + makePrepareDepthForPostFxNode(); fgNodeHandles.emplace_back(makePrepareDepthAfterTransparent()); if (hasMotionVectors) fgNodeHandles.emplace_back(makePrepareMotionVectorsAfterTransparent(antiAliasing && antiAliasing->needMotionVectorHistory())); @@ -2966,6 +2980,8 @@ void WorldRenderer::createNodes() Point2 jitterOffset(0, 0); if (antiAliasing) jitterOffset = antiAliasing->update(jitterPersp); + + currentFrameCamera.jitterOffsetUv = jitterOffset; // todo: replce that with 'double' version! d3d::setpersp(jitterPersp, ¤tFrameCamera.jitterProjTm); d3d::settm(TM_VIEW, currentFrameCamera.viewTm); @@ -3012,6 +3028,125 @@ void WorldRenderer::createNodes() }; })); + fgNodeHandles.emplace_back(dabfg::register_node("hero_matrix_setup_node", DABFG_PP_NODE_SRC, [this](dabfg::Registry registry) { + registry.executionHas(dabfg::SideEffects::External); + + auto cameraHndl = registry.readBlob("current_camera").handle(); + auto prevCameraHndl = registry.readBlobHistory("current_camera").handle(); + auto heroGunOrVehicleTmHndl = + registry.createBlob("hero_gun_or_vehicle_tm", dabfg::History::ClearZeroOnFirstFrame).handle(); + auto prevHeroGunOrVehicleTmHndl = registry.readBlobHistory("hero_gun_or_vehicle_tm").handle(); + auto heroMatrixParamsHndl = + registry.createBlob>("hero_matrix_params", dabfg::History::No).handle(); + + return [this, cameraHndl, prevCameraHndl, heroGunOrVehicleTmHndl, prevHeroGunOrVehicleTmHndl, heroMatrixParamsHndl] { + const DPoint3 &worldPos = cameraHndl.ref().cameraWorldPos; + const DPoint3 &oldWorldPos = prevCameraHndl.ref().cameraWorldPos; + mat44f oldHeroGunOrVehicleTm; + v_mat44_make_from_43cu(oldHeroGunOrVehicleTm, prevHeroGunOrVehicleTmHndl.ref().array); + + if (heroData.resReady) + { + heroData.resWtm.col3 = + v_add(heroData.resWtm.col3, v_make_vec4f(v_extract_x(heroData.resWofs) - worldPos.x, + v_extract_y(heroData.resWofs) - worldPos.y, v_extract_z(heroData.resWofs) - worldPos.z, 0)); + + const mat44f oldHeroGunOrVehicleNoReprojectedWposTm = oldHeroGunOrVehicleTm; + oldHeroGunOrVehicleTm.col3 = v_add(oldHeroGunOrVehicleTm.col3, + v_make_vec4f(oldWorldPos.x - worldPos.x, oldWorldPos.y - worldPos.y, oldWorldPos.z - worldPos.z, 0)); + + vec3f lbc = v_bbox3_center(heroData.resLbox); + vec3f lbsize = v_sub(heroData.resLbox.bmax, lbc); + ShaderGlobal::set_real(gi_hero_cockpit_distanceVarId, v_extract_x(v_length3_x(lbsize))); + lbsize = v_sel(lbsize, v_add(lbsize, lbsize), (vec4f)V_CI_MASK1000); // increase size in one direction, to catch hands + + mat44f invHeroGun; + v_mat44_inverse43(invHeroGun, heroData.resWtm); + + mat44f boxMatrix, heroMatrix; + boxMatrix.col0 = v_and(v_div(V_C_UNIT_1000, lbsize), (vec4f)V_CI_MASK1110); + boxMatrix.col1 = v_and(v_div(V_C_UNIT_0100, lbsize), (vec4f)V_CI_MASK1110); + boxMatrix.col2 = v_and(v_div(V_C_UNIT_0010, lbsize), (vec4f)V_CI_MASK1110); + boxMatrix.col3 = v_sel(V_C_ONE, v_sub(v_zero(), v_div(lbc, lbsize)), (vec4f)V_CI_MASK1110); + v_mat44_mul43(heroMatrix, boxMatrix, invHeroGun); + + mat44f worldToPrev; + v_mat44_mul43(worldToPrev, oldHeroGunOrVehicleTm, invHeroGun); + + mat43f wtm, wtmPrev; + v_mat44_transpose_to_mat43(wtmPrev, worldToPrev); + v_mat44_transpose_to_mat43(wtm, heroMatrix); + + ShaderGlobal::set_color4(prev_hero_matrixXVarId, Color4((float *)&wtmPrev.row0)); + ShaderGlobal::set_color4(prev_hero_matrixYVarId, Color4((float *)&wtmPrev.row1)); + ShaderGlobal::set_color4(prev_hero_matrixZVarId, Color4((float *)&wtmPrev.row2)); + + ShaderGlobal::set_color4(hero_matrixXVarId, Color4((float *)&wtm.row0)); + ShaderGlobal::set_color4(hero_matrixYVarId, Color4((float *)&wtm.row1)); + ShaderGlobal::set_color4(hero_matrixZVarId, Color4((float *)&wtm.row2)); + ShaderGlobal::set_int(hero_is_cockpitVarId, heroData.resFlags == heroData.WEAPON); + + auto toTMatrix = [](const mat43f &m) { + Point4 rows[3]; + v_stu(&rows[0].x, m.row0); + v_stu(&rows[1].x, m.row1); + v_stu(&rows[2].x, m.row2); + + TMatrix tm; + tm.setcol(0, rows[0].x, rows[1].x, rows[2].x); + tm.setcol(1, rows[0].y, rows[1].y, rows[2].y); + tm.setcol(2, rows[0].z, rows[1].z, rows[2].z); + tm.setcol(3, rows[0].w, rows[1].w, rows[2].w); + return tm; + }; + + heroMatrixParamsHndl.ref() = + motion_vector_access::HeroMatrixParams{toTMatrix(wtm), toTMatrix(wtmPrev), heroData.resFlags == heroData.WEAPON}; + + mat44f worldToPrevNoReprojectedWPos; + mat43f wtmPrevNoReprojectedWpos; + v_mat44_mul43(worldToPrevNoReprojectedWPos, oldHeroGunOrVehicleNoReprojectedWposTm, invHeroGun); + v_mat44_transpose_to_mat43(wtmPrevNoReprojectedWpos, worldToPrevNoReprojectedWPos); + + ShaderGlobal::set_color4(hero_bbox_reprojectionXVarId, Color4((float *)&wtmPrevNoReprojectedWpos.row0)); + ShaderGlobal::set_color4(hero_bbox_reprojectionYVarId, Color4((float *)&wtmPrevNoReprojectedWpos.row1)); + ShaderGlobal::set_color4(hero_bbox_reprojectionZVarId, Color4((float *)&wtmPrevNoReprojectedWpos.row2)); + + v_mat_43cu_from_mat44(heroGunOrVehicleTmHndl.ref().array, heroData.resWtm); + } + else + { + ShaderGlobal::set_real(gi_hero_cockpit_distanceVarId, 0); + ShaderGlobal::set_color4(hero_matrixXVarId, 0, 0, 0, 2); + ShaderGlobal::set_color4(hero_matrixYVarId, 0, 0, 0, 2); + ShaderGlobal::set_color4(hero_matrixZVarId, 0, 0, 0, 2); + heroGunOrVehicleTmHndl.ref() = prevHeroGunOrVehicleTmHndl.ref(); + heroMatrixParamsHndl.ref() = eastl::nullopt; + } + }; + })); + + fgNodeHandles.emplace_back(dabfg::register_node("motion_vector_access_setup_node", DABFG_PP_NODE_SRC, [](dabfg::Registry registry) { + registry.executionHas(dabfg::SideEffects::External); + + auto cameraHndl = registry.readBlob("current_camera").handle(); + auto prevCameraHndl = registry.readBlobHistory("current_camera").handle(); + auto heroMatrixParamsHndl = + registry.readBlob>("hero_matrix_params").handle(); + + registry.createBlob("motion_vector_access_token", dabfg::History::No); // something to use in dependent nodes + + return [cameraHndl, prevCameraHndl, heroMatrixParamsHndl] { + motion_vector_access::CameraParams currentCamera{cameraHndl.ref().viewTm, cameraHndl.ref().viewItm, + cameraHndl.ref().noJitterProjTm, cameraHndl.ref().cameraWorldPos, cameraHndl.ref().znear, cameraHndl.ref().zfar}; + motion_vector_access::CameraParams previousCamera{prevCameraHndl.ref().viewTm, prevCameraHndl.ref().viewItm, + prevCameraHndl.ref().noJitterProjTm, prevCameraHndl.ref().cameraWorldPos, prevCameraHndl.ref().znear, + prevCameraHndl.ref().zfar}; + motion_vector_access::set_params(currentCamera, previousCamera, cameraHndl.ref().jitterOffsetUv, + prevCameraHndl.ref().jitterOffsetUv, heroMatrixParamsHndl.ref()); + }; + })); + dabfg::invalidate_history(); } @@ -3351,8 +3486,6 @@ WorldRenderer::WorldRenderer() : cameraHeight(0.f), waterSSRFrame(0), water_ssr_id(-1), - oldHeroGunOrVehicleTm(ZERO()), - oldWorldPos(0, 0, 0), debugLightProbeSpheres(nullptr) { if (d3d::get_driver_code().is(d3d::dx12)) @@ -3611,6 +3744,9 @@ void WorldRenderer::update(float dt, float, const TMatrix &itm) #if TIME_PROFILER_ENABLED render::imgui_profiler::update_profiler(dagor_frame_no()); #endif + + if (!dagor_work_cycle_is_need_to_draw()) // Note: we still have to update frp for it's side effects + uirender::update_all_gui_scenes_mainthread(dt); } void WorldRenderer::cullFrustumLights(vec3f viewPos, mat44f_cref globtm, mat44f_cref view, mat44f_cref proj, float zn) @@ -3846,7 +3982,8 @@ void WorldRenderer::beforeRender(float scaled_dt, transparentPartitionSphere = PartitionSphere(); } - updateHeroMatrix(view_pos); + updateHeroData(); + if (fomShadowManager) { float minHt, maxHt; @@ -4583,7 +4720,7 @@ void WorldRenderer::draw(float realDt) d3d::setwire(false); resource_slot::resolve_access(); - dabfg::run_nodes(); + [[maybe_unused]] bool fgWasRun = dabfg::run_nodes(); if (allsamples > 1) set_mip_bias(last_mip_scale); @@ -4598,6 +4735,11 @@ void WorldRenderer::draw(float realDt) if (dynamicResolution) dynamicResolution->endFrame(); +#if _TARGET_PC // Assume that only PC can reset + if (!fgWasRun) // Dev lost? + waitAllJobs(); +#endif + // Stuff after this point is GUI and debug visualization, they don't // support the `global_frame` block. ShaderGlobal::setBlock(-1, ShaderGlobal::LAYER_FRAME); @@ -4623,6 +4765,8 @@ void WorldRenderer::setDirToSun() Point3 newSunDir = get_daskies() ? get_daskies()->getPrimarySunDir() : Point3(0.400, -0.610, 0.684); dir_to_sun.realTime = newSunDir; + rendinst::setDirFromSun(-newSunDir); // it can be outdated, so we update it no matter what + auto useCompression = [] { return ::dgs_get_settings()->getBlockByNameEx("graphics")->getBool("globalShadowCompression", true); }; switch (dir_to_sun.sunDirectionUpdateStage) @@ -4644,7 +4788,6 @@ void WorldRenderer::setDirToSun() } break; case DirToSun::RENDINST_GLOBAL_SHADOWS: - rendinst::setDirFromSun(-dir_to_sun.curr); if (!rendinst::rendinstGlobalShadows || (rendinst::render::are_impostors_ready_for_depth_shadows() && rendinst::render::renderRIGenGlobalShadowsToTextures(-dir_to_sun.curr, false, useCompression(), !isTimeDynamic()))) @@ -5954,72 +6097,13 @@ void WorldRenderer::renderLmeshReflection() ShaderGlobal::setBlock(-1, ShaderGlobal::LAYER_FRAME); } -void WorldRenderer::updateHeroMatrix(const DPoint3 &world_pos) +void WorldRenderer::updateHeroData() { - QueryHeroWtmAndBoxForRender hero_data; + QueryHeroWtmAndBoxForRender heroDataQuery{}; if (const ecs::EntityId heroEid = game::get_controlled_hero()) if (g_entity_mgr->getEntityTemplateId(heroEid) != ecs::INVALID_TEMPLATE_INDEX) - g_entity_mgr->sendEventImmediate(heroEid, hero_data); - if (hero_data.resReady) - { - hero_data.resWtm.col3 = - v_add(hero_data.resWtm.col3, v_make_vec4f(v_extract_x(hero_data.resWofs) - world_pos.x, - v_extract_y(hero_data.resWofs) - world_pos.y, v_extract_z(hero_data.resWofs) - world_pos.z, 0)); - - const mat44f oldHeroGunOrVehicleNoReprojectedWposTm = oldHeroGunOrVehicleTm; - oldHeroGunOrVehicleTm.col3 = v_add(oldHeroGunOrVehicleTm.col3, - v_make_vec4f(oldWorldPos.x - world_pos.x, oldWorldPos.y - world_pos.y, oldWorldPos.z - world_pos.z, 0)); - - vec3f lbc = v_bbox3_center(hero_data.resLbox); - vec3f lbsize = v_sub(hero_data.resLbox.bmax, lbc); - ShaderGlobal::set_real(gi_hero_cockpit_distanceVarId, v_extract_x(v_length3_x(lbsize))); - lbsize = v_sel(lbsize, v_add(lbsize, lbsize), (vec4f)V_CI_MASK1000); // increase size in one direction, to catch hands - - mat44f invHeroGun; - v_mat44_inverse43(invHeroGun, hero_data.resWtm); - - mat44f boxMatrix, heroMatrix; - boxMatrix.col0 = v_and(v_div(V_C_UNIT_1000, lbsize), (vec4f)V_CI_MASK1110); - boxMatrix.col1 = v_and(v_div(V_C_UNIT_0100, lbsize), (vec4f)V_CI_MASK1110); - boxMatrix.col2 = v_and(v_div(V_C_UNIT_0010, lbsize), (vec4f)V_CI_MASK1110); - boxMatrix.col3 = v_sel(V_C_ONE, v_sub(v_zero(), v_div(lbc, lbsize)), (vec4f)V_CI_MASK1110); - v_mat44_mul43(heroMatrix, boxMatrix, invHeroGun); - - mat44f worldToPrev; - v_mat44_mul43(worldToPrev, oldHeroGunOrVehicleTm, invHeroGun); - - mat43f wtm, wtmPrev; - v_mat44_transpose_to_mat43(wtmPrev, worldToPrev); - v_mat44_transpose_to_mat43(wtm, heroMatrix); - - ShaderGlobal::set_color4(prev_hero_matrixXVarId, Color4((float *)&wtmPrev.row0)); - ShaderGlobal::set_color4(prev_hero_matrixYVarId, Color4((float *)&wtmPrev.row1)); - ShaderGlobal::set_color4(prev_hero_matrixZVarId, Color4((float *)&wtmPrev.row2)); - - ShaderGlobal::set_color4(hero_matrixXVarId, Color4((float *)&wtm.row0)); - ShaderGlobal::set_color4(hero_matrixYVarId, Color4((float *)&wtm.row1)); - ShaderGlobal::set_color4(hero_matrixZVarId, Color4((float *)&wtm.row2)); - ShaderGlobal::set_int(hero_is_cockpitVarId, hero_data.resFlags == hero_data.WEAPON); - - mat44f worldToPrevNoReprojectedWPos; - mat43f wtmPrevNoReprojectedWpos; - v_mat44_mul43(worldToPrevNoReprojectedWPos, oldHeroGunOrVehicleNoReprojectedWposTm, invHeroGun); - v_mat44_transpose_to_mat43(wtmPrevNoReprojectedWpos, worldToPrevNoReprojectedWPos); - - ShaderGlobal::set_color4(hero_bbox_reprojectionXVarId, Color4((float *)&wtmPrevNoReprojectedWpos.row0)); - ShaderGlobal::set_color4(hero_bbox_reprojectionYVarId, Color4((float *)&wtmPrevNoReprojectedWpos.row1)); - ShaderGlobal::set_color4(hero_bbox_reprojectionZVarId, Color4((float *)&wtmPrevNoReprojectedWpos.row2)); - - oldHeroGunOrVehicleTm = hero_data.resWtm; - oldWorldPos = world_pos; - } - else - { - ShaderGlobal::set_real(gi_hero_cockpit_distanceVarId, 0); - ShaderGlobal::set_color4(hero_matrixXVarId, 0, 0, 0, 2); - ShaderGlobal::set_color4(hero_matrixYVarId, 0, 0, 0, 2); - ShaderGlobal::set_color4(hero_matrixZVarId, 0, 0, 0, 2); - } + g_entity_mgr->sendEventImmediate(heroEid, heroDataQuery); + heroData = heroDataQuery; } void WorldRenderer::renderWaterSSR(bool enabled, diff --git a/prog/daNetGame/render/world/worldRendererGI.cpp b/prog/daNetGame/render/world/worldRendererGI.cpp index 552450c4c..5bdb54a9d 100644 --- a/prog/daNetGame/render/world/worldRendererGI.cpp +++ b/prog/daNetGame/render/world/worldRendererGI.cpp @@ -60,7 +60,6 @@ CONSOLE_INT_VAL("render", gi_quality, GI_COLORED, GI_ONLY_AO, GI_SCREEN_PROBES); CONSOLE_FLOAT_VAL_MINMAX("render", min_sdf_voxel_with_lights_size, 0.35, 0, 4); CONSOLE_FLOAT_VAL_MINMAX("render", max_sdf_voxel_with_lights_size, 2.33, 0, 4); CONSOLE_FLOAT_VAL_MINMAX("render", gi_algorithm_quality, 1, 0, 1); -CONSOLE_FLOAT_VAL_MINMAX("render", gi_temporal_quality_override, -1.0f, -1.0f, 8.0f); CONSOLE_BOOL_VAL("render", gi_update_pos, true); CONSOLE_BOOL_VAL("render", gi_update_scene, true); CONSOLE_BOOL_VAL("render", gi_enabled, true); @@ -137,10 +136,19 @@ void WorldRenderer::setGIQualityFromSettings() giUpdatePosFrameCounter = 0; } +bool WorldRenderer::giNeedsReprojection() +{ + return hasFeature(FeatureRenderFlags::DEFERRED_LIGHT) && daGI2 && gi_quality == GI_SCREEN_PROBES && + daGI2->getNextSettings().screenProbes.tileSize > 8; +} + void WorldRenderer::giBeforeRender() { if (daGI2 && !gi_enabled.get()) + { closeGI(); + makePrepareDepthForPostFxNode(); + } if (!daGI2 && gi_enabled.get()) initGI(); @@ -151,6 +159,8 @@ void WorldRenderer::giBeforeRender() return; TIME_D3D_PROFILE(gi2_before_render) + const bool hadReprojection = giNeedsReprojection(); + int w, h, maxW, maxH; getRenderingResolution(w, h); getMaxPossibleRenderingResolution(maxW, maxH); @@ -206,20 +216,26 @@ void WorldRenderer::giBeforeRender() return lerp(min_value, max_value, lerpS); }; + auto remapUnclamped = [](float min_value, float max_value, float interval_min, float interval_max, float t) -> float { + G_ASSERT(interval_min < interval_max); + float lerpS = (t - interval_min) / (interval_max - interval_min); + return lerp(min_value, max_value, lerpS); + }; + if (gi_algorithm_quality >= 0.75f) giDynamicQuality = remap(0.55f, 1.0f, 0.75f, 1.0f, gi_algorithm_quality); else giDynamicQuality = remap(0.1f, 0.55f, 0.25f, 0.5f, gi_algorithm_quality); s.screenProbes.temporality = giDynamicQuality; - // minimum s.screenProbes.tileSize is 16 at 1080p, 20 at 1440p, 24 at 4k + // minimum s.screenProbes.tileSize is 20 at 1080p, 24 at 1440p, 32 at 4k int w, h; getRenderingResolution(w, h); - float minTileSize = clamp(round(lerp(2.0f, 4.0f, h / 1080.0f - 1.0f)), 2, 6) * 4 + 8; - float tileSizeF = remap(minTileSize, 8, 0, 0.25f, gi_algorithm_quality); + float minTileSize = remapUnclamped(16, 32, 1080, 1080 * 2, h); + float tileSizeF = remap(minTileSize, 8, 0.25, 0.95f, gi_algorithm_quality); s.screenProbes.tileSize = static_cast(round(tileSizeF)) & ~1; - float radianceOctResF = remap(4, 8, 0.5f, 0.75f, gi_algorithm_quality); + float radianceOctResF = remap(4, 8, 0.f, 0.5f, gi_algorithm_quality); s.screenProbes.radianceOctRes = static_cast(round(radianceOctResF)); s.screenProbes.angleFiltering = gi_algorithm_quality > 0.875f; @@ -251,6 +267,9 @@ void WorldRenderer::giBeforeRender() const float halfDist = sdfW * sdfV * 0.5f * 1.2f; // 120% bigger treesAbove->init(halfDist, voxel0); } + makePrepareDepthForPostFxNode(); + if (giNeedsReprojection() != hadReprojection) + createDeferredLightNode(); } void WorldRenderer::renderGiCollision(const TMatrix &view_itm, const Frustum &) @@ -637,6 +656,15 @@ void WorldRenderer::createGiNodes() #endif } +void WorldRenderer::createDeferredLightNode() +{ + if (isForwardRender()) + return; + + deferredLightNode = + hasFeature(FeatureRenderFlags::DEFERRED_LIGHT) ? makeDeferredLightNode(giNeedsReprojection()) : dabfg::NodeHandle{}; +} + void WorldRenderer::createResolveGbufferNode() { if (isForwardRender()) @@ -660,6 +688,6 @@ void WorldRenderer::createResolveGbufferNode() {0 /* LIGHTS_OFF */} /* shaderVarValuesToSkipClassifications */ }; - deferredLightNode = hasFeature(FeatureRenderFlags::DEFERRED_LIGHT) ? makeDeferredLightNode() : dabfg::NodeHandle{}; + createDeferredLightNode(); resolveGbufferNode = makeResolveGbufferNode(resolve_shader, resolve_cshader, classify_cshader, resolve_permutations); } diff --git a/prog/daNetGame/render/world/worldRendererVisibility.cpp b/prog/daNetGame/render/world/worldRendererVisibility.cpp index a2ef5d192..f6939f64c 100644 --- a/prog/daNetGame/render/world/worldRendererVisibility.cpp +++ b/prog/daNetGame/render/world/worldRendererVisibility.cpp @@ -23,6 +23,7 @@ #include #include "render/world/parallelOcclusionRasterizer.h" #include "render/world/worldRendererQueries.h" +#include "depthAOAbove.h" extern ConVarB stop_occlusion; extern ConVarB use_occlusion; @@ -33,6 +34,8 @@ CONSOLE_BOOL_VAL("render", sw_hmap_occlusion, true); CONSOLE_BOOL_VAL("render", sw_animchars_occlusion, true); CONSOLE_BOOL_VAL("render", occlusion_async_readback_gpu, true); +extern void wait_static_shadows_cull_jobs(); + static ShaderVariableInfo cockpit_distanceVarId("cockpit_distance", true); static struct VisibilityReprojectJob final : public cpujobs::IJob @@ -407,7 +410,10 @@ void WorldRenderer::waitAllJobs() waitLights(); waitGroundVisibility(); waitGroundReflectionVisibility(); + wait_static_shadows_cull_jobs(); waitLightProbeVisibility(); + if (depthAOAboveCtx) + depthAOAboveCtx->waitCullJobs(); } void WorldRenderer::toggleProbeReflectionQuality() diff --git a/prog/daNetGame/scripts/das/remote/jsonrpc_handler.das b/prog/daNetGame/scripts/das/remote/jsonrpc_handler.das index 043a0352b..e5595cb56 100644 --- a/prog/daNetGame/scripts/das/remote/jsonrpc_handler.das +++ b/prog/daNetGame/scripts/das/remote/jsonrpc_handler.das @@ -46,7 +46,7 @@ class JsonRpcMatch : Matcher self->clean() if find(str, "\"jsonrpc\"") < 0 - return <- [[MatchResult invalid = null]] + return <- [[MatchResult invalid = true]] let strLen = length(str) var start = 0 @@ -75,7 +75,7 @@ class JsonRpcMatch : Matcher end = strLen if length(requests) == 0 - return <- [[MatchResult invalid = null]] + return <- [[MatchResult invalid = true]] return <- [[MatchResult success = end]] def parseReq(str : string) : bool diff --git a/prog/daNetGame/scripts/das/remote/server.das b/prog/daNetGame/scripts/das/remote/server.das index f2f2db7b1..9a5b49ca6 100644 --- a/prog/daNetGame/scripts/das/remote/server.das +++ b/prog/daNetGame/scripts/das/remote/server.das @@ -7,7 +7,7 @@ require strings typedef Handler = lambda < (message : string) : string > - MatchResult = variant + MatchResult = variant class Matcher def abstract match(str : string) : MatchResult @@ -20,7 +20,7 @@ class StringMatch : Matcher def override match(str : string) : MatchResult if str == matchStr return <- [[MatchResult success = length(str)]] - return <- [[MatchResult invalid = null]] + return <- [[MatchResult invalid = true]] class WebServer : WebSocket diff --git a/prog/daNetGame/shaders/_build/variants.blk b/prog/daNetGame/shaders/_build/variants.blk index ce0b73970..6b70ea18e 100644 --- a/prog/daNetGame/shaders/_build/variants.blk +++ b/prog/daNetGame/shaders/_build/variants.blk @@ -1,2 +1,3 @@ -invalid {gi_quality:i = 0;ssr_alternate_reflections:i=1;} - +// each invalid block denotes an AND relationship between the given variants +invalid {gi_quality:i=0;ssr_alternate_reflections:i=1;} +invalid {motion_vector_type:i=1;} diff --git a/prog/daNetGame/shaders/deferred_light.dshl b/prog/daNetGame/shaders/deferred_light.dshl index f386e68cb..e187bc99c 100644 --- a/prog/daNetGame/shaders/deferred_light.dshl +++ b/prog/daNetGame/shaders/deferred_light.dshl @@ -36,14 +36,22 @@ shader deferredLight } hlsl(ps) { +##if gi_quality == screen_probes struct MRT_OUTPUT { - float3 specular:SV_Target0; + GI_ENCODED_TYPE specular:SV_Target0; + GI_ENCODED_TYPE ambient:SV_Target1; + uint age:SV_Target2; + }; +##else + struct MRT_OUTPUT + { + half3 specular:SV_Target0; ##if gi_quality != off - float3 ambient:SV_Target1; + half3 ambient:SV_Target1; ##endif }; - +##endif MRT_OUTPUT deferred_light_ps(VsOutput input HW_USE_SCREEN_POS) { float4 screenpos = GET_SCREEN_POS(input.pos); @@ -64,12 +72,18 @@ shader deferredLight float3 worldPos = world_view_pos.xyz - pointToEyeOfs; float3 computedSpecular, computedAmbient; - ComputeDeferredLight(gbuffer, worldPos, rawDepth, input.texcoord.xy, screenpos.xy, pointToEye, computedSpecular, computedAmbient); - - ret.specular = computedSpecular; + uint age; + ComputeDeferredLight(gbuffer, worldPos, rawDepth, input.texcoord.xy, screenpos.xy, pointToEye, computedSpecular, computedAmbient, age); + + ##if gi_quality == screen_probes + encode_gi_colors(ret.ambient, ret.specular, computedAmbient, computedSpecular); + ret.age = age; + ##else + ret.specular = computedSpecular; ##if gi_quality != off - ret.ambient = computedAmbient; + ret.ambient = computedAmbient; ##endif + ##endif return ret; } } diff --git a/prog/daNetGame/shaders/deferred_light_common.dshl b/prog/daNetGame/shaders/deferred_light_common.dshl index d0dec9c8d..4fdf05f70 100644 --- a/prog/daNetGame/shaders/deferred_light_common.dshl +++ b/prog/daNetGame/shaders/deferred_light_common.dshl @@ -16,6 +16,7 @@ include "custom_probe_inc.dshl" include "world_sdf.dshl" include "use_gi.dshl" +include "reproject_gi.dshl" int shadow_frame = 0; @@ -70,6 +71,7 @@ macro INIT_AND_USE_DEFERRED_LIGHT_COMMON(code) } else { SAMPLE_IRRADIANCE_SPECULAR_SP(code) + REPROJECT_GI(code) } hlsl(code) { @@ -86,7 +88,7 @@ macro INIT_AND_USE_DEFERRED_LIGHT_COMMON(code) ##endif void ComputeDeferredLight(ProcessedGbuffer gbuffer, float3 worldPos, float rawDepth, float2 viewTexcoord, float2 viewPixcoord, - float3 pointToEye, out float3 outSpecular, out float3 outAmbient) + float3 pointToEye, out float3 outSpecular, out float3 outAmbient, out uint outPixelAge) { ##if gi_quality != screen_probes // this is incorrect even with other GI algorithms. @@ -274,8 +276,18 @@ macro INIT_AND_USE_DEFERRED_LIGHT_COMMON(code) } } */ - outSpecular = pack_hdr(totalReflection); + outSpecular = totalReflection; + outPixelAge = 0; + + ##if gi_quality == screen_probes + half3 roughSpecular = outSpecular; + const half maxAmbientWeight = 1./8; + reproject_gi(getPrevInvExposure(), gbuffer.isHeroCockpit, depth_gbuf_read_samplerstate, lerp(0.25, maxAmbientWeight, gbuffer.linearRoughness), maxAmbientWeight, + -pointToEye, viewTexcoord, rawDepth, linearize_z(rawDepth, zn_zfar.zw), outAmbient, roughSpecular, outPixelAge); + outSpecular = lerp(roughSpecular, outSpecular, saturate(1 - 2*gbuffer.linearRoughness)*0.9); + ##endif outAmbient = pack_hdr(outAmbient); + outSpecular = pack_hdr(outSpecular); } } endmacro \ No newline at end of file diff --git a/prog/daNetGame/shaders/deferred_light_compute.dshl b/prog/daNetGame/shaders/deferred_light_compute.dshl index 552d48c90..0e836b42d 100644 --- a/prog/daNetGame/shaders/deferred_light_compute.dshl +++ b/prog/daNetGame/shaders/deferred_light_compute.dshl @@ -1,5 +1,7 @@ include "deferred_light_common.dshl" +sampler depth_gbuf_samplerstate; + shader deferred_light_compute { if (compatibility_mode == compatibility_mode_on) @@ -23,15 +25,22 @@ shader deferred_light_compute current_time@f1 = (time_phase(0, 0)); world_view_pos@f4 = world_view_pos; depth_bounds@f2 = depth_bounds; + depth_gbuf_read_samplerstate@sampler = depth_gbuf_samplerstate; } hlsl(cs) { #include - RWTexture2D g_specular : register(u0); -##if gi_quality != off - RWTexture2D g_ambient : register(u1); -##endif + ##if gi_quality == screen_probes + RWTexture2D g_specular : register(u0); + RWTexture2D g_ambient : register(u1); + RWTexture2D g_pixel_age : register(u2); + ##else + RWTexture2D g_specular : register(u0); + ##if gi_quality != off + RWTexture2D g_ambient : register(u1); + ##endif + ##endif [numthreads(DEFERRED_LIGHT_COMPUTE_GRP_SIZE_X, DEFERRED_LIGHT_COMPUTE_GRP_SIZE_Y, 1)] void deferred_light_cs( uint3 Groupid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint GI : SV_GroupIndex ) @@ -61,13 +70,19 @@ shader deferred_light_compute float3 pointToEyeOfs = pointToEye; float3 worldPos = world_view_pos.xyz - pointToEyeOfs; - float3 computedSpecular, computedAmbient; - ComputeDeferredLight(gbuffer, worldPos, rawDepth, curViewTc, screenCoordCenter, pointToEye, computedSpecular, computedAmbient); + half3 computedSpecular, computedAmbient; + uint age; + ComputeDeferredLight(gbuffer, worldPos, rawDepth, curViewTc, screenCoordCenter, pointToEye, computedSpecular, computedAmbient, age); - g_specular[DTid.xy] = computedSpecular; + ##if gi_quality == screen_probes + encode_gi_colors(g_ambient[DTid.xy], g_specular[DTid.xy], computedAmbient, computedSpecular); + g_pixel_age[DTid.xy] = age; + ##else + g_specular[DTid.xy] = computedSpecular; ##if gi_quality != off - g_ambient[DTid.xy] = computedAmbient; + g_ambient[DTid.xy] = computedAmbient; ##endif + ##endif } } diff --git a/prog/daNetGame/shaders/deferred_shadow_common.dshl b/prog/daNetGame/shaders/deferred_shadow_common.dshl index 7e8195bc4..b6a7c7317 100644 --- a/prog/daNetGame/shaders/deferred_shadow_common.dshl +++ b/prog/daNetGame/shaders/deferred_shadow_common.dshl @@ -31,6 +31,7 @@ include "use_gi.dshl" include "night_light.dshl" include "rtao_use.dshl" include "rtr_use.dshl" +include "screen_gi_encoding.dshl" float4 stereo_params = (0, 0, 0, 0); @@ -191,15 +192,18 @@ macro COMMON_RESOLVE_EXTENDED(code) if (gi_quality == only_ao) { DAGI_SKY_VIS_SAMPLE(code) + DAGI_NO_SCREEN_ENCODING(code) } else if (gi_quality == colored) { hlsl { #define DAGI_IRRADIANCE_GRID_TYPE DAGI_IRRADIANCE_GRID_TYPE_IRRADIANCE } DAGI_IRRADIANCE_GRID_SAMPLE(code) + DAGI_NO_SCREEN_ENCODING(code) } else { SAMPLE_IRRADIANCE_SP(code) + DAGI_GAMMA2_SCREEN_ENCODING(code) } } @@ -522,8 +526,12 @@ macro USE_DEFERRED_SHADOW_PER_SAMPLE(code) //half3 environmentAmbientUnoccludedLighting = lerp3(localLightProbeAmbient1, localLightProbeAmbient2, GetSkySHDiffuse(enviLightingNormal), ambientWeights) * gbuffer.diffuseColor; float fake_light_strength = 0.25; ##if (gi_quality != off) - half3 enviLight = unpack_hdr(texelFetch(current_ambient, screenpos, 0).rgb); - ##else + half3 enviLight, giSpecular; + decode_gi_colors(texelFetch(current_ambient, screenpos, 0). GI_ENCODED_ATTR, texelFetch(specular_tex, screenpos, 0). GI_ENCODED_ATTR, enviLight, giSpecular); + enviLight = unpack_hdr(enviLight); + giSpecular = unpack_hdr(giSpecular); + ##endif + ##if (gi_quality == off) half3 enviLight = GetSkySHDiffuse(enviLightingNormal); ##endif @@ -545,7 +553,7 @@ macro USE_DEFERRED_SHADOW_PER_SAMPLE(code) environmentAmbientLighting *= AB.z; //environmentAmbientReflection *= lerp(1, enviAO, gbuffer.translucency);//g.amelihin asked for that hack ##if (gi_quality != off) - half3 totalReflection = (unpack_hdr(texelFetch(specular_tex, screenpos, 0).rgb)*(specularAOcclusion*enviSSR) + ssrReflections.rgb)*enviBRDF; + half3 totalReflection = (giSpecular*(specularAOcclusion*enviSSR) + ssrReflections.rgb)*enviBRDF; ##else float3 roughR = getRoughReflectionVec(lightProbeReflectionVec.xyz, gbuffer.normal, ggx_alpha); float roughMip = ComputeReflectionCaptureMipFromRoughness(gbuffer.linearRoughness); diff --git a/prog/daNetGame/shaders/dynamic_painted_by_mask.dshl b/prog/daNetGame/shaders/dynamic_painted_by_mask.dshl index ba1355238..35158f109 100644 --- a/prog/daNetGame/shaders/dynamic_painted_by_mask.dshl +++ b/prog/daNetGame/shaders/dynamic_painted_by_mask.dshl @@ -78,7 +78,7 @@ shader dynamic_painted_by_mask #endif #if HAS_BLOOD_DECAL float4 bloodDecalTC : TEXCOORD6; - nointerpolation float textureIndexTime : TEXCOORD7; + nointerpolation float4 hitNormalTextureIndexTime : TEXCOORD7; #endif #if HAS_TORN_WOUNDS float4 tornWoundParams : TEXCOORD8; diff --git a/prog/daNetGame/shaders/dynamic_simple_inc.dshl b/prog/daNetGame/shaders/dynamic_simple_inc.dshl index 672a45910..ab4478cbb 100644 --- a/prog/daNetGame/shaders/dynamic_simple_inc.dshl +++ b/prog/daNetGame/shaders/dynamic_simple_inc.dshl @@ -209,7 +209,7 @@ macro DYNAMIC_SIMPLE_VS_BASE_PREAMBLE() float3 normal : TEXCOORD2; #if HAS_BLOOD_DECAL float4 bloodDecalTC : TEXCOORD6; - nointerpolation float textureIndexTime : TEXCOORD7; + nointerpolation float4 hitNormalTextureIndexTime : TEXCOORD7; #endif #if HAS_TORN_WOUNDS float4 tornWoundParams : TEXCOORD8; diff --git a/prog/daNetGame/shaders/glass.dshl b/prog/daNetGame/shaders/glass.dshl index b6275b014..810d9f8d1 100644 --- a/prog/daNetGame/shaders/glass.dshl +++ b/prog/daNetGame/shaders/glass.dshl @@ -65,9 +65,10 @@ macro INIT_SIMPLE_GLASS() (ps) { tint_color@f4 = (tint_color); opaque_coeff@f1 = (opaque_coeff); - glass_specular_color@f3 = (pow(glass_specular_color.r, 2.2) * sun_color_0.r, - pow(glass_specular_color.g, 2.2) * sun_color_0.g, - pow(glass_specular_color.b, 2.2) * sun_color_0.b); + glass_specular_color@f3 = ( + pow(glass_specular_color.r, 2.2) * sun_color_0.r / max(max(sun_color_0.r, sun_color_0.g), max(sun_color_0.b, 1.0)), + pow(glass_specular_color.g, 2.2) * sun_color_0.g / max(max(sun_color_0.r, sun_color_0.g), max(sun_color_0.b, 1.0)), + pow(glass_specular_color.b, 2.2) * sun_color_0.b / max(max(sun_color_0.r, sun_color_0.g), max(sun_color_0.b, 1.0))); glass_specular_power@f1 = specular_power; } diff --git a/prog/daNetGame/shaders/heightmap.dshl b/prog/daNetGame/shaders/heightmap.dshl index 46f36e8c3..affa3d914 100644 --- a/prog/daNetGame/shaders/heightmap.dshl +++ b/prog/daNetGame/shaders/heightmap.dshl @@ -630,6 +630,7 @@ shader heightmap struct HsControlPoint { float2 pos : POSITION0; + half heightForPuddle : POSITION1; }; float3 restoreWorldPosNoPatches(float2 posXZ) @@ -671,7 +672,10 @@ shader heightmap uint vertexId = inputPatch[tid].vertexInstanceId_patchTessFactor >> 16; uint instance_id = inputPatch[tid].vertexInstanceId_patchTessFactor & ((1U << 16) - 1); DECODE_VERTEXID_POSXZ - output.pos = decodeWorldPosXZ(posXZ USED_INSTANCE_ID); + float2 pos_xz = decodeWorldPosXZ(posXZ USED_INSTANCE_ID); + pos_xz = clamp(pos_xz, heightmap_region.xy, heightmap_region.zw);; + output.pos = pos_xz; + output.heightForPuddle = get_height_for_puddle(restoreWorldPos(pos_xz)); return output; } } @@ -686,22 +690,31 @@ shader heightmap return result; } + float Bilerp(float v0, float v1, float v2, float v3, float2 i) + { + float bottom = lerp(v0, v3, i.x); + float top = lerp(v1, v2, i.x); + float result = lerp(bottom, top, i.y); + return result; + } + + #define BILERP(input, channel, coords) Bilerp(input[0].channel, input[1].channel, input[2].channel, input[3].channel, coords) + [domain("quad")] VsOutput hmap_tessellation_ds(HsPatchData patchData, const OutputPatch input, float2 coords : SV_DomainLocation) { VsOutput output; - float2 posXZ = Bilerp(input[0].pos, input[1].pos, input[2].pos, input[3].pos, coords.yx); + float2 posXZ = BILERP(input, pos, coords.yx); + float heightForPuddle = BILERP(input, heightForPuddle, coords.yx); //transform and output data float3 worldPos = restoreWorldPos(posXZ); - worldPos.xz = clamp(worldPos.xz, heightmap_region.xy, heightmap_region.zw); output.tcWorldPos = worldPos.xz; float3 worldNormal; float displacementEffect = 0; float deformAmount = 0; worldPos = worldPosNormalCorrection(worldPos, 0, worldNormal, displacementEffect, deformAmount); - float heightForPuddle = get_height_for_puddle(worldPos.xyz); float puddle, worldPosYPuddleOffset, puddleHeight; getPuddleData(worldPos.y, worldPos, heightForPuddle, puddle, worldPosYPuddleOffset, puddleHeight); output.scaledDeformedHeight = worldPos.y+(100-100*displacementEffect); diff --git a/prog/daNetGame/shaders/init_projective_wounds.dshl b/prog/daNetGame/shaders/init_projective_wounds.dshl index 9a3317e80..3884bfeea 100644 --- a/prog/daNetGame/shaders/init_projective_wounds.dshl +++ b/prog/daNetGame/shaders/init_projective_wounds.dshl @@ -12,6 +12,9 @@ float4 blood_wound_meat_color_low_intensity = (0.002, 0, 0, 1); float4 blood_wound_skin_meat_color_high_intensity = (0.007, 0, 0, 1); float4 blood_wound_skin_meat_color_low_intensity = (0.002, 0, 0, 1); +float4 blood_wound_angle_dist_fadeoff_range = (-0.25, 1.25, 0.25, 1.0); +float blood_wound_angle_free_zone = 0.85; + float blood_wound_dark_albedo_compensation_factor = 0.04; float blood_wound_low_porosity_reflectance = 0.3; float blood_wound_dry_edge_scale = 0.5; @@ -68,6 +71,9 @@ local float blood_wound_puddle_edge_thickness_width = blood_wound_puddle_begin_t blood_wound_skin_color_high_intensity@f3 = blood_wound_skin_color_high_intensity.xyz; blood_wound_skin_color_low_intensity@f3 = blood_wound_skin_color_low_intensity.xyz; + blood_wound_angle_fadeoff_range@f2 = blood_wound_angle_dist_fadeoff_range.xy; + blood_wound_dist_fadeoff_range@f2 = blood_wound_angle_dist_fadeoff_range.zw; + blood_wound_angle_free_zone@f1 = blood_wound_angle_free_zone; } endmacro diff --git a/prog/daNetGame/shaders/layered_inc.dshl b/prog/daNetGame/shaders/layered_inc.dshl index 15594020a..429d78ce1 100644 --- a/prog/daNetGame/shaders/layered_inc.dshl +++ b/prog/daNetGame/shaders/layered_inc.dshl @@ -1,3 +1,5 @@ +include "get_mix_weight_inc.dshl" + macro WEIGHT_BLENDING(stage) hlsl(stage) { half3 get_blending_weights(half3 weights, half3 initialHeight) @@ -178,17 +180,6 @@ macro LAYERED_PS(is_normal_pass) #define SAMPLE_TEX(tex, tc) tex2DBindless(tex, tc) #endif static const float modulation_detail2_alpha_inv_weight = 0.85; - half get_mix_weight(float detail1_a, float detail2_a, float mask_weight) - { - half2 weights = half2(detail1_a*(1.0-mask_weight), detail2_a*mask_weight+0.000001); - weights = pow4_vec2(weights); - half weight2 = weights.y*rcp(dot(weights,1.0)); - - //make it more contrast! - half weight2_pow2 = weight2*weight2; - weight2 = (-2.666666666666667*weight2_pow2 + (4*weight2 - 0.333333333333333))*weight2; - return saturate(weight2); - } #if VOXELIZE_ALBEDO_PASS void simple_ps(VsOutput input INPUT_VFACE HW_USE_SCREEN_POS) diff --git a/prog/daNetGame/shaders/mask_layered_inc.dshl b/prog/daNetGame/shaders/mask_layered_inc.dshl index eac77d42d..2515192ae 100644 --- a/prog/daNetGame/shaders/mask_layered_inc.dshl +++ b/prog/daNetGame/shaders/mask_layered_inc.dshl @@ -119,6 +119,10 @@ macro MASK_LAYERED_PS() half3 normalMap = unpack_ag_normal(packedNormalMap); half3 worldNormal = perturb_normal_precise( normalMap, normalize(input.normal.xyz), input.pointToEye.xyz, input.uv12.xy ); +#if USE_TOP_PROJECTION_TEXTURE + apply_top_projection(worldNormal, detailColor1, detailColor2, weight, weight2, baseColor.rgb); +#endif + half4 detailNormal1 = SAMPLE_TEX(get_tile1normal(), detail_uv); half4 detailNormal2 = SAMPLE_TEX(get_tile2normal(), detail_uv); half4 packedDetailNormalMap = detailNormal1*weights.x + detailNormal2*weights.y; diff --git a/prog/daNetGame/shaders/projective_wounds.dshl b/prog/daNetGame/shaders/projective_wounds.dshl index f1e3a2103..3a53faf32 100644 --- a/prog/daNetGame/shaders/projective_wounds.dshl +++ b/prog/daNetGame/shaders/projective_wounds.dshl @@ -97,7 +97,7 @@ macro WOUNDS_AND_BURNING_USE(samplerName) output.burnedEffect = getBurnedEffect(); #endif #if HAS_BLOOD_DECAL - vs_blood_decal_function(input.pos, output.bloodDecalTC, output.textureIndexTime); + vs_blood_decal_function(input.pos, output.bloodDecalTC, output.hitNormalTextureIndexTime); #endif #if HAS_TORN_WOUNDS vs_torn_wounds_function(input.pos, output); @@ -286,10 +286,10 @@ hlsl(vs) { return float2(-coords.x, -coords.y); } - void vs_blood_decal_function(float3 input_pos, inout float4 bloodDecalTC, inout float textureIndexTime) + void vs_blood_decal_function(float3 input_pos, inout float4 bloodDecalTC, inout float4 hitNormalTextureIndexTime) { bloodDecalTC = NaN; - textureIndexTime = 0; + hitNormalTextureIndexTime = float4(0, 0, 0, 0); uint2 dataOffsetCount = get_offset_count_additional_data(HUMAN_COMBINED_PARAMS); if (dataOffsetCount.y == 0) return; @@ -312,7 +312,8 @@ hlsl(vs) { mindist = lenSq; bloodDecalTC.xyz = pos; bloodDecalTC.w = i + 1; - textureIndexTime = start_time; + hitNormalTextureIndexTime.w = start_time; + hitNormalTextureIndexTime.xyz = dir_depth_time.xyz; //we rotate all texture for 180 degreese, to make floating along attachment bloodDecalTC.xy = rotate_on_minus_pi(bloodDecalTC.xy); @@ -392,7 +393,27 @@ hlsl(ps) { } } - void apply_blood_decal(float4 decal_tc, float start_time, uint tex_index, float3 frag_norm, float3 normal, + float calc_mask(float3 frag_pos, float3 normal, float3 hitDir, float2 distance_range, float2 angle_range, float angle_free_zone) + { + float mask = 1.0; + float dotV = dot(normal, hitDir); + float distanceFactor = smoothstep(distance_range.x, distance_range.y, (1 - length(frag_pos.xyz))); + float angleFact = smoothstep(angle_range.x, angle_range.y, dotV); + + if (distanceFactor > angle_free_zone) + mask = distanceFactor; + else + mask = angleFact * distanceFactor; + + return mask; + } + + float to_border_mask(float mask) + { + return saturate(mask / 0.3); + } + + void apply_blood_decal(float4 decal_tc, float start_time, uint tex_index, float3 frag_norm, float3 normal, float3 hitDir, float3 point_to_eye, int micro_detail_layer, inout float3 diffuse_color, inout float3 world_normal, inout float smoothness, inout float reflectance) @@ -404,7 +425,15 @@ hlsl(ps) { { //r - time, g - packed norm, b - intensive, a - packed norm //decal_tc.xyz in one-unit sphere, need to translate it to half-unit sphere, so scale = 0.5 - float4 blood = sample_texture_from_pos(wounds_decal_array, samplerName, tex_index, decal_tc.xyz, frag_norm, 0.5); + float mask = calc_mask(decal_tc.xyz, normal, hitDir, blood_wound_dist_fadeoff_range, blood_wound_angle_fadeoff_range, blood_wound_angle_free_zone); + + BRANCH + if (mask == 0.0) + return; + + mask = to_border_mask(mask); + + float4 blood = sample_texture_from_pos(wounds_decal_array, samplerName, tex_index, decal_tc.xyz, hitDir, 0.5); float current_time = time_wetness_bloody_time.x; float time = current_time - start_time; float bloody_time = time_wetness_bloody_time.y; @@ -428,9 +457,12 @@ hlsl(ps) { float porosity = micro_detail_layer != -1 ? get_porosity_by_microdetail_base(micro_detail_layer) : 1.0; float3 bloodWorldNormal = perturb_normal_precise(unpack_ag_normal(blood), normal, point_to_eye, decal_tc.xy); + float3 diffuseWithBlood = diffuse_color; apply_blood_material(thickness, edgeCloseness, porosity, bloodWorldNormal, - world_normal, diffuse_color, smoothness, reflectance); + world_normal, diffuseWithBlood, smoothness, reflectance); + + diffuse_color = lerp(diffuse_color, diffuseWithBlood, mask); } } } @@ -464,8 +496,8 @@ hlsl(ps) { { float start_time; uint tex_index; - extract_time_index(input.textureIndexTime, start_time, tex_index); - apply_blood_decal(input.bloodDecalTC, start_time, tex_index, input.fragNormal, input.normal, input.pointToEye, + extract_time_index(input.hitNormalTextureIndexTime.w, start_time, tex_index); + apply_blood_decal(input.bloodDecalTC, start_time, tex_index, input.fragNormal, input.normal, input.hitNormalTextureIndexTime.xyz, input.pointToEye, micro_detail_layer, diffuse_color, world_normal, smoothness, reflectance); } #endif diff --git a/prog/daNetGame/shaders/rendinst_layered.dshl b/prog/daNetGame/shaders/rendinst_layered.dshl index 63be8f870..88844f7b0 100644 --- a/prog/daNetGame/shaders/rendinst_layered.dshl +++ b/prog/daNetGame/shaders/rendinst_layered.dshl @@ -6,6 +6,7 @@ include "mask_layered_inc.dshl" include "hmap_blend_inc.dshl" include "hmap_blend_use_inc.dshl" include "plod_inc.dshl" +include "rendinst_top_projection_inc.dshl" shader rendinst_layered { @@ -20,6 +21,8 @@ shader rendinst_layered NO_DYNSTCODE() } + SETUP_TOP_PROJECTION(true) + PLOD_GBUF_GEN_INIT(rendinst_render_pass == rendinst_render_pass_normal) ENABLE_MULTI_DRAW(rendinst_render_pass == rendinst_render_pass_to_shadow || rendinst_render_pass == rendinst_render_pass_depth) diff --git a/prog/daNetGame/shaders/rendinst_simple_inc.dshl b/prog/daNetGame/shaders/rendinst_simple_inc.dshl index 5c72dfd94..5a8ea456c 100644 --- a/prog/daNetGame/shaders/rendinst_simple_inc.dshl +++ b/prog/daNetGame/shaders/rendinst_simple_inc.dshl @@ -44,10 +44,12 @@ macro INIT_COMMON_RENDINST_TESSELLATION() static float max_tessellation_distance = 2.0 no_warnings; static float tessellation_transition_distance = 1.0 no_warnings; static float tessellation_max_edge_length = 0.024 no_warnings; + static int enable_shadow_tessellation = 1 no_warnings; + interval enable_shadow_tessellation: off<1, on; bool pn_triangulation_enabled = (object_tess_factor == object_tess_factor_on && material_pn_triangulation != off && - (rendinst_render_pass == rendinst_render_pass_normal || rendinst_render_pass == rendinst_render_pass_depth)); + (rendinst_render_pass == rendinst_render_pass_normal || rendinst_render_pass == rendinst_render_pass_depth || (rendinst_render_pass == rendinst_render_pass_to_shadow && enable_shadow_tessellation == on))); if (pn_triangulation_enabled) { @@ -65,6 +67,7 @@ macro INIT_COMMON_RENDINST_TESSELLATION() max_tessellation_distance@f1 = max_tessellation_distance; tessellation_transition_distance@f1 = tessellation_transition_distance; tessellation_max_edge_length@f1 = tessellation_max_edge_length; + enable_shadow_tessellation@i1 = enable_shadow_tessellation; } hlsl(ds) { diff --git a/prog/daNetGame/shaders/rendinst_vcolor_inc.dshl b/prog/daNetGame/shaders/rendinst_vcolor_inc.dshl index bb4cdf780..75ddce675 100644 --- a/prog/daNetGame/shaders/rendinst_vcolor_inc.dshl +++ b/prog/daNetGame/shaders/rendinst_vcolor_inc.dshl @@ -22,11 +22,8 @@ endmacro macro COMMON_RENDINST_VCOLOR_PS(is_blending_hmap) - if (rendinst_render_pass != rendinst_render_pass_to_shadow) - { - USE_VCOLOR_LAYERED(ps) - USE_VCOLOR_LAYERED(vs) - } + USE_VCOLOR_LAYERED(ps) + USE_VCOLOR_LAYERED(vs) COMMON_RENDINST_PS_PREP(false) diff --git a/prog/daNetGame/shaders/reproject_gi.dshl b/prog/daNetGame/shaders/reproject_gi.dshl new file mode 100644 index 000000000..2c6581122 --- /dev/null +++ b/prog/daNetGame/shaders/reproject_gi.dshl @@ -0,0 +1,124 @@ +include "motion_vectors_type.dshl" +include "screen_gi_encoding.dshl" +include "hero_matrix_inc.dshl" +int reproject_screen_gi; + +texture prev_ambient; +texture prev_specular; +texture prev_gbuf_depth; +texture prev_gi_pixel_age; +float4x4 jitteredCamPosToUnjitteredHistoryClip; + +macro REPROJECT_GI(code) + DAGI_GAMMA2_SCREEN_ENCODING(code) + local float4 prev_gbuffer_depth_dim = get_dimensions(prev_gbuf_depth, 0); + (code) { + reproject_screen_gi@i1 = reproject_screen_gi; + + prev_ambient@tex = prev_ambient hlsl { Texture2D prev_ambient@tex; }; + prev_specular@tex = prev_specular hlsl { Texture2D prev_specular@tex; }; + /* + // later we need to add support (for better quality) + if (dagi_sp_has_exposure_assume == always_rgbe) + { + prev_ambient@tex = prev_ambient hlsl { Texture2D prev_ambient@tex; }; + prev_specular@tex = prev_specular hlsl { Texture2D prev_specular@tex; }; + } else + { + prev_ambient@tex = prev_ambient hlsl { Texture2D prev_ambient@tex; }; + prev_specular@tex = prev_specular hlsl { Texture2D prev_specular@tex; }; + }*/ + + prev_gi_pixel_age@tex = prev_gi_pixel_age hlsl { Texture2D prev_gi_pixel_age@tex; }; + + jitteredCamPosToUnjitteredHistoryClip@f44 = jitteredCamPosToUnjitteredHistoryClip;// current jittered screencoord -> history unjittered screencoord + prev_gbuf_depth@tex2d = prev_gbuf_depth; + //fixme: prev_zn_zfar + prev_zn_zfar@f4 = (zn_zfar.x, zn_zfar.y, zn_zfar.x/(zn_zfar.x * zn_zfar.y), (zn_zfar.y-zn_zfar.x)/(zn_zfar.x * zn_zfar.y));//fixme + depth_gbuf_dim@f2 = get_dimensions(depth_gbuf, 0); + prev_gbuffer_depth_dim@f4 = (prev_gbuffer_depth_dim.x, prev_gbuffer_depth_dim.y, 1./max(1, prev_gbuffer_depth_dim.x), 1./max(prev_gbuffer_depth_dim.y, 1)); + current_jittered_pos_to_prev_jittered_pos_ofs@f2 = (uv_temporal_jitter.z - uv_temporal_jitter.x, uv_temporal_jitter.w - uv_temporal_jitter.y,0,0); + uv_temporal_jitter@f4 = uv_temporal_jitter; + } + INIT_LOAD_MOTION_BUFFER_BASE(code) + USE_LOAD_MOTION_BUFFER_BASE(code) + INIT_HERO_MATRIX_NO_GBUF(code) + USE_HERO_MATRIX_NO_GBUF(code) + MOTION_VECTORS_TYPE(code) + + hlsl(code) + { + #define MOTION_TO_PREV_JITTERED_UV_OFS (current_jittered_pos_to_prev_jittered_pos_ofs) + bool reproject_gi(half preExposure, bool isHeroCockpitGbuf, SamplerState sampler_st, half new_specular_w, half new_diffuse_w, float3 camPos, float2 cur_view_tc, float rawDepth, float linearDepth, inout half3 ambient, inout half3 specular, out uint age) + { + age = 0; + if (!reproject_screen_gi) + return false; + ##if motion_gbuf != NULL + motion_type surface_motion = loadMotionBuffer(uint2(cur_view_tc*prev_gbuffer_depth_dim.xy)).motion_attr; + surface_motion.xy += MOTION_TO_PREV_JITTERED_UV_OFS; + float3 historyUVZ = float3(cur_view_tc, linearDepth) + surface_motion; + ##else + if (isInHero(isHeroCockpitGbuf, camPos)) + camPos = just_apply_hero_matrix(camPos); + float4 historyClip = mul(float4(camPos, 1), jitteredCamPosToUnjitteredHistoryClip); + historyClip.xyz = historyClip.w > 1e-4 ? historyClip.xyz / historyClip.w : float3(2,2,2); + float3 historyUVZ = float3(historyClip.xy*float2(0.5, -0.5) + 0.5, linearize_z(historyClip.z, prev_zn_zfar.zw)); + ##endif + + half newAge = 0; + bool valid = all(abs(historyUVZ.xy*2 - 1) < 1); + { + float2 historyCrdf = historyUVZ.xy * prev_gbuffer_depth_dim.xy - 0.5; + float2 floorCrd = floor(historyCrdf); + float2 gatherUV = floorCrd*prev_gbuffer_depth_dim.zw + prev_gbuffer_depth_dim.zw; + float2 fractCrd = historyCrdf - floorCrd; + #ifdef MOTION_TO_PREV_JITTERED_UV_OFS + fractCrd = saturate(fractCrd - MOTION_TO_PREV_JITTERED_UV_OFS*prev_gbuffer_depth_dim.xy); + #endif + + float4 prevRawZ = prev_gbuf_depth.GatherRed(sampler_st, gatherUV.xy).wzxy; + float4 prevLinearDepths = linearize_z4(prevRawZ, prev_zn_zfar.zw); + float4 bilW = float4(1-fractCrd, fractCrd); + bilW = bilW.xzxz*bilW.yyww; + + float4 depthDiff = abs(historyUVZ.z - prevLinearDepths); + float threshold = 0.05*historyUVZ.z; + float4 weights = (depthDiff < threshold); + float4 spatialWeights = exp(-depthDiff * (5.0 / threshold)); + weights *= (spatialWeights * bilW); + weights = select(weights > 1e-4, weights, float4(0,0,0,0)); + float sumW = valid ? dot(weights, 1.0) : 0; + if (sumW > 1e-4) + { + weights /= sumW; + half3 prevAmbient, prevSpecular; + #if GI_PACK_ALGO == GI_USE_SW_RGBE + decode_weighted_colors(prev_ambient.GatherRed(sampler_st, gatherUV.xy).wzxy, + prev_specular.GatherRed(sampler_st, gatherUV.xy).wzxy, + prevAmbient, prevSpecular, + weights); + #else + decode_weighted_colors(prev_ambient.GatherRed(sampler_st, gatherUV.xy).wzxy, + prev_ambient.GatherGreen(sampler_st, gatherUV.xy).wzxy, + prev_ambient.GatherBlue(sampler_st, gatherUV.xy).wzxy, + prev_specular.GatherRed(sampler_st, gatherUV.xy).wzxy, + prev_specular.GatherGreen(sampler_st, gatherUV.xy).wzxy, + prev_specular.GatherBlue(sampler_st, gatherUV.xy).wzxy, + prevAmbient, prevSpecular, + weights); + #endif + + float oldAge = dot(prev_gi_pixel_age.GatherRed(sampler_st, gatherUV.xy).wzxy, weights); + float newAgeF = (oldAge + 1); + float historyW = 1./(newAgeF + 1); + ambient = lerp(preExposure*prevAmbient, ambient, max(new_diffuse_w, historyW)); + specular = lerp(preExposure*prevSpecular, specular, max(new_specular_w, historyW)); + age = newAgeF + 0.5f; + return true; + } + } + return false; + } + } +endmacro diff --git a/prog/daNetGame/shaders/shader_global.dshl b/prog/daNetGame/shaders/shader_global.dshl index ddb168193..a645f714d 100644 --- a/prog/daNetGame/shaders/shader_global.dshl +++ b/prog/daNetGame/shaders/shader_global.dshl @@ -687,6 +687,8 @@ hlsl { } hlsl { + #define DETAIL_TEX_MULTIPLIER 4.59479341998814 + #define DETAIL_TEX_MULTIPLIER_RCP (1.0 / DETAIL_TEX_MULTIPLIER) #define DISABLE_RAY_LIGHT_INTERSECTION 1 #define ALLOW_CLOUD_HOLE 1 } diff --git a/prog/daNetGame/shaders/tsr_game.dshl b/prog/daNetGame/shaders/tsr_game.dshl index f9bb5927d..5780c4e0c 100644 --- a/prog/daNetGame/shaders/tsr_game.dshl +++ b/prog/daNetGame/shaders/tsr_game.dshl @@ -1,32 +1,18 @@ -texture resolved_motion_vectors; - -float4x4 tsr_reprojection; +include "motion_vector_access.dshl" macro TSR_GAME(stage) + INIT_FETCH_MOTION_VECTOR(stage, full) + USE_FETCH_MOTION_VECTOR(stage, full) hlsl (stage) { // the first and second value is in screen space, the third is the raw depth difference (non-linear) float3 fetchMotionVector(float raw_depth, float2 uv, out uint is_dynamic) { is_dynamic = isGbufferDynamic(uv); - float linearDepth = linearize_z(raw_depth, zn_zfar.zw); - float3 viewVec = getViewVecOptimized(uv); - float3 cameraToPoint = viewVec * linearDepth; - - ##if motion_gbuf != NULL - float3 uvz = readMotionBuffer(uv).xyz; - float prevLinearZ = linearDepth + uvz.z; - float prevDepth = inv_linearizeZ(prevLinearZ, zn_zfar); - return float3(uvz.xy, prevDepth - raw_depth); - ##else - BRANCH - if (is_dynamic) - apply_hero_matrix(uv, cameraToPoint); - - float4 prevClip = mul(float4(cameraToPoint, 1), jitteredCamPosToUnjitteredHistoryClip); - float3 prevPos = prevClip.xyz / prevClip.w; - return float3(prevPos.xy * float2(0.5, -0.5) + float2(0.5, 0.5), prevPos.z) - float3(uv, raw_depth); - ##endif + float3 uvz = fetch_motion_vector_unjittered(uv, raw_depth); + float prevLinearZ = linearize_z(raw_depth, zn_zfar.zw) + uvz.z; // TODO: switch to rejection by linear Z + float prevDepth = inv_linearizeZ(prevLinearZ, zn_zfar); + return float3(uvz.xy, prevDepth - raw_depth); } } endmacro diff --git a/prog/daNetGame/shaders/water_3d_geometry.dshl b/prog/daNetGame/shaders/water_3d_geometry.dshl index f94dea97c..9d76faa96 100644 --- a/prog/daNetGame/shaders/water_3d_geometry.dshl +++ b/prog/daNetGame/shaders/water_3d_geometry.dshl @@ -121,11 +121,11 @@ macro USE_WATER_PROJECTED_EFFECTS(stage) } endmacro -macro GET_WATER_COLOR() -hlsl(ps) { +macro GET_WATER_COLOR(code) +hlsl(code) { #define INV_MIN_IOR 50 } -hlsl(ps) { +hlsl(code) { #include "pbr/BRDF.hlsl" } endmacro @@ -197,7 +197,6 @@ macro WATER_3D_COMMON_VS() supports water3d_block; DECL_POSTFX_TC_VS_RT() - GET_WATER_COLOR() INIT_WORLD_HEIGHTMAP_VS() USE_HEIGHTMAP_COMMON_VS() HEIGHTMAP_DECODE_EDGE_TESSELATION() @@ -249,6 +248,7 @@ macro WATER_3D_COMMON_VS() endmacro macro WATER_3D_COMMON_PS() + GET_WATER_COLOR(ps) USE_SCREENPOS_TO_TC() USE_SCREENPOS_TO_LOWRES_TC() USE_WATER_RIPPLES() diff --git a/prog/daNetGame/ui/uiRender.cpp b/prog/daNetGame/ui/uiRender.cpp index 8f8a7d3b9..13455cc38 100644 --- a/prog/daNetGame/ui/uiRender.cpp +++ b/prog/daNetGame/ui/uiRender.cpp @@ -167,6 +167,14 @@ void skip_ui_render_job() StdGuiRender::reset_per_frame_dynamic_buffer_pos(); } +void update_all_gui_scenes_mainthread(float dt) +{ + for (darg::IGuiScene *scn : get_all_scenes()) + { + scn->update(dt); + scn->mainThreadBeforeRender(); + } +} void before_render(float dt, const TMatrix &view_itm, const TMatrix &view_tm) { @@ -188,13 +196,7 @@ void before_render(float dt, const TMatrix &view_itm, const TMatrix &view_tm) interlocked_release_store(ui_render_job.runState, ui_render_job.INITIAL); } else - { - for (darg::IGuiScene *scn : scenes) - { - scn->update(dt); - scn->mainThreadBeforeRender(); - } - } + update_all_gui_scenes_mainthread(dt); for (auto &uiscn : scenes) { @@ -224,4 +226,4 @@ void init() } -} // namespace uirender \ No newline at end of file +} // namespace uirender diff --git a/prog/daNetGame/ui/uiRender.h b/prog/daNetGame/ui/uiRender.h index 9ce437260..0d0df36fa 100644 --- a/prog/daNetGame/ui/uiRender.h +++ b/prog/daNetGame/ui/uiRender.h @@ -17,6 +17,7 @@ using all_darg_scenes_t = dag::RelocatableFixedVector ManagedTexView { return normFactorView; }); diff --git a/prog/daNetGameLibs/blood_puddles/private/render/bloodPuddlesES.cpp.inl b/prog/daNetGameLibs/blood_puddles/private/render/bloodPuddlesES.cpp.inl index f56520dee..63f2f001b 100644 --- a/prog/daNetGameLibs/blood_puddles/private/render/bloodPuddlesES.cpp.inl +++ b/prog/daNetGameLibs/blood_puddles/private/render/bloodPuddlesES.cpp.inl @@ -92,9 +92,12 @@ BloodPuddles::BloodPuddles() : { index_buffer::init_box(); + const char *bloodQuality = dgs_get_settings()->getBlockByName("graphics")->getStr("bloodQuality", "high"); + const bool hasPrepass = !strcmp(bloodQuality, "high"); + const DataBlock paramsBlk(BLOOD_PARAMS_DATA_BLOCK_NAME); initResources(paramsBlk); - useAccumulationPrepass(paramsBlk.getBool("mergeBlood", false)); + useAccumulationPrepass(hasPrepass); initNodes(); initTextureParams(paramsBlk); initShadingParams(paramsBlk); diff --git a/prog/daNetGameLibs/blood_puddles/private/shaders/blood_puddles.dshl b/prog/daNetGameLibs/blood_puddles/private/shaders/blood_puddles.dshl index f0c93048c..db5d0c8fa 100644 --- a/prog/daNetGameLibs/blood_puddles/private/shaders/blood_puddles.dshl +++ b/prog/daNetGameLibs/blood_puddles/private/shaders/blood_puddles.dshl @@ -13,8 +13,8 @@ float blood_puddle_smoothness_edge = 0.9 always_referenced; float blood_puddle_landscape_reflectance = 0.21 always_referenced; float blood_puddle_landscape_smoothness_edge = 0.4 always_referenced; float blood_puddle_landscape_albedo_darkening = 0.5 always_referenced; -float4 blood_puddle_high_intensity_color = (0.157, 0.012, 0.000, 1.000); -float4 blood_puddle_low_intensity_color = (0.086, 0.024, 0.020, 0.960); +float4 blood_puddle_high_intensity_color = (0.157, 0.012, 0.000, 1.000) always_referenced; +float4 blood_puddle_low_intensity_color = (0.086, 0.024, 0.020, 0.960) always_referenced; float4 blood_decals_atlas_size = (1, 1, 0, 0); float blood_puddle_start_size = 0.2; texture blood_puddle_tex; @@ -140,8 +140,6 @@ macro BLOOD_PUDDLES_COMMON_PS() (ps) { atlas_size@f2 = (blood_decals_atlas_size); - blood_puddle_high_intensity_color@f4 = (blood_puddle_high_intensity_color); - blood_puddle_low_intensity_color@f4 = (blood_puddle_low_intensity_color); blood_puddle_start_size@f1 = (blood_puddle_start_size); perlin_noise3d@smp3d = perlin_noise3d; blood_puddle_tex@smp2d = blood_puddle_tex; @@ -184,29 +182,40 @@ macro BLOOD_PUDDLES_COMMON_PS() void unpack_blood(VsOutput input, float4 screen, out float3 normal, out float drying_time, out float intensity, out float alpha, - out float flow_value, out float edge_closeness, out uint decal_type__is_landscape) + out float flow_value, out float edge_closeness, out uint decal_type__is_landscape, + out uint decal_type, out bool is_landscape) { uint2 atlasSize = atlas_size; decal_type__is_landscape = input.decal_type_and_landscape__frame__rndIndex.x; - uint decalType = decal_type__is_landscape >> 1; - bool isLandscape = (decal_type__is_landscape & 0x1) == 1; - bool isPuddle = decalType == DecalGroup::BLOOD_DECAL_GROUP_PUDDLE; + decal_type = decal_type__is_landscape >> 1; + is_landscape = (decal_type__is_landscape & 0x1) == 1; + + bool isPuddle = decal_type == DecalGroup::BLOOD_DECAL_GROUP_PUDDLE; uint frameNo = input.decal_type_and_landscape__frame__rndIndex.y; uint rndIndex = input.decal_type_and_landscape__frame__rndIndex.z; float3 worldNormal = normalize(input.normal_fadetime.xyz); float3 flow = normalize(normal * float3(1, 0.01, 1)); float3 vecToEdge = normalize(input.vecToEdge_starttime.xyz); float linearTime = input.vecToEdge_starttime.w; - float sizeTime = easeFunc(saturate(abs(linearTime) * perGroupParams[decalType].invLifetime + blood_puddle_start_size), rndIndex); + float sizeTime = easeFunc(saturate(abs(linearTime) * perGroupParams[decal_type].invLifetime + blood_puddle_start_size), rndIndex); float strength = input.strength; bool mirror = frameNo & 1; frameNo >>= 1; const float3 eyeToPoint = get_decal_eye_to_point(screen); const float3 pointToEye = -eyeToPoint; + const float3 surfaceNormal = normalize(cross(normalize(ddx(pointToEye)), normalize(ddy(pointToEye)))); + + const float cos30 = 0.866; + const bool surfaceNormalNotWithinValidRange = dot(surfaceNormal, worldNormal) < cos30; + const float3 worldPos = world_view_pos + eyeToPoint; float3 decalTC = get_decal_tex_coord_from_world_pos(worldPos, input.patchCenter__inv_size.xyz, worldNormal, input.tang_shrink.xyz); + const bool depthNotWithinValidRange = abs(decalTC.z) >= 0.05; + + if (!is_landscape && (surfaceNormalNotWithinValidRange || depthNotWithinValidRange)) + discard; decalTC.x *= input.tang_shrink.w; decalTC *= input.patchCenter__inv_size.w; @@ -235,7 +244,7 @@ macro BLOOD_PUDDLES_COMMON_PS() clip_alpha(alpha); BRANCH - if (isLandscape && isPuddle) + if (is_landscape && isPuddle) normal = worldNormal; else { @@ -244,15 +253,94 @@ macro BLOOD_PUDDLES_COMMON_PS() } intensity = bloodParams.b; - drying_time = saturate((max(linearTime, 0.0) + perGroupParams[decalType].dryingDelay) * perGroupParams[decalType].invDryingTime); + drying_time = saturate((max(linearTime, 0.0) + perGroupParams[decal_type].dryingDelay) * perGroupParams[decal_type].invDryingTime); - float edgeWidthScale = float(perGroupParams[decalType].bloodNormalDominanceTerm_edgeWidthScale >> 8)/255.0; + float edgeWidthScale = float(perGroupParams[decal_type].bloodNormalDominanceTerm_edgeWidthScale >> 8)/255.0; float edgeClosenessScale = lerp(16.0, 1.0, edgeWidthScale); edge_closeness = 1.0 - saturate((flow_value - timeThreshold - cuttingOffset) * edgeClosenessScale); } } endmacro +macro BLOOD_PUDDLES_RESOLVE_COMMON_PS() + (ps) { + blood_puddle_high_intensity_color@f4 = (blood_puddle_high_intensity_color); + blood_puddle_low_intensity_color@f4 = (blood_puddle_low_intensity_color); + blood_puddle_reflectance@f1 = (blood_puddle_reflectance); + blood_puddle_smoothness@f1 = (blood_puddle_smoothness); + blood_puddle_smoothness_edge@f1 = (blood_puddle_smoothness_edge) + + blood_puddle_landscape_reflectance@f1 = (blood_puddle_landscape_reflectance); + blood_puddle_landscape_smoothness_edge@f1 = (blood_puddle_landscape_smoothness_edge); + blood_puddle_landscape_albedo_darkening@f1 = (blood_puddle_landscape_albedo_darkening); + } + + hlsl(ps) { + GBUFFER_OUTPUT apply_blood_puddle_resolve_ps(uint decal_type, bool is_landscape, + float thickness, float edgeCloseness, float3 normal, float alpha) + { + float reflectance; + float smoothness; + float bloodNormalBlend; + float3 diffuse; + + diffuse = lerp(blood_puddle_low_intensity_color.xyz, + blood_puddle_high_intensity_color.xyz, + 1.0 - thickness); + + BRANCH + if (is_landscape) + { + reflectance = blood_puddle_landscape_reflectance; + smoothness = lerp(blood_puddle_smoothness, blood_puddle_landscape_smoothness_edge, edgeCloseness); + bloodNormalBlend = 1.0 - edgeCloseness; + + diffuse *= lerp(blood_puddle_landscape_albedo_darkening, 1.0, edgeCloseness); + alpha *= 1.0 - pow(edgeCloseness, 4.0); + } + else + { + reflectance = blood_puddle_reflectance; + smoothness = lerp(blood_puddle_smoothness, blood_puddle_smoothness_edge, edgeCloseness); + + float invEdgeCloseness = 1.0 - edgeCloseness; + float3 vecToEdge = (ddx(invEdgeCloseness) * (view_vecLT + view_vecLB) + ddy(invEdgeCloseness) * (view_vecLT + view_vecRT)).xyz; + if (fwidth(invEdgeCloseness) > 0.5 / 255) + normal = lerp(normal, vecToEdge, saturate(edgeCloseness)); + + float bloodNormalDominanceTerm = float(perGroupParams[decal_type].bloodNormalDominanceTerm_edgeWidthScale & 0xFF)/255.0; + bloodNormalBlend = max(edgeCloseness, bloodNormalDominanceTerm); + } + + diffuse = lerp(1.0.xxx, diffuse, alpha); + + float alpha3 = pow3(alpha); + float srcMulDstDominance = lerp(1.0, 0.96, alpha3); + float srcDominance = (1.0/srcMulDstDominance - 1.0); + + UnpackedGbuffer output; + init_gbuffer(output); + init_albedo(output, diffuse * srcMulDstDominance); + init_ao(output, srcDominance); + init_reflectance(output, reflectance); + init_metalness(output, 0.0); + init_smoothness(output, smoothness); + init_normal(output, normal); + ##if special_vision == thermal_vision + init_material(output, SHADING_SELFILLUM); + init_emission(output, MAX_EMISSION); + init_emission_color(output, half4(255, 255, 255, 255.0f)); + output.smoothness = 0; + ##endif + + GBUFFER_OUTPUT gbuf = encode_gbuffer(output, 0, GET_SCREEN_POS(input.pos)); + gbuf.normal_material.w = bloodNormalBlend * alpha3; + gbuf.smoothness_reflectance_metallTranslucency_shadow.w = 0.9 * alpha3; + return gbuf; + } + } +endmacro + shader blood_puddles_accumulation { if (compatibility_mode == compatibility_mode_on) @@ -290,8 +378,10 @@ shader blood_puddles_accumulation float3 normal; float intensity, edgeCloseness, alpha, stub; + uint uiStub; + bool bStub; uint decalType__landscape; - unpack_blood(input, screen, normal, stub, intensity, alpha, stub, edgeCloseness, decalType__landscape); + unpack_blood(input, screen, normal, stub, intensity, alpha, stub, edgeCloseness, decalType__landscape, uiStub, bStub); float packedDecalTypeAndLandscape = ((float)decalType__landscape+0.1)/255.0f; @@ -348,20 +438,11 @@ shader blood_puddles_resolve ENABLE_ASSERT(ps) INIT_PER_GROUP_PARAMS(ps) INIT_VIEW_VEC_STAGE(ps) + BLOOD_PUDDLES_RESOLVE_COMMON_PS() (ps) { - blood_acc_buf0@tex2d = blood_acc_buf0; - blood_acc_normal@tex2d = blood_acc_normal; - - blood_puddle_high_intensity_color@f4 = (blood_puddle_high_intensity_color); - blood_puddle_low_intensity_color@f4 = (blood_puddle_low_intensity_color); - blood_puddle_reflectance@f1 = (blood_puddle_reflectance); - blood_puddle_smoothness@f1 = (blood_puddle_smoothness); - blood_puddle_smoothness_edge@f1 = (blood_puddle_smoothness_edge) - - blood_puddle_landscape_reflectance@f1 = (blood_puddle_landscape_reflectance); - blood_puddle_landscape_smoothness_edge@f1 = (blood_puddle_landscape_smoothness_edge); - blood_puddle_landscape_albedo_darkening@f1 = (blood_puddle_landscape_albedo_darkening); + blood_acc_buf0@smp2d = blood_acc_buf0; + blood_acc_normal@smp2d = blood_acc_normal; } @@ -380,69 +461,15 @@ shader blood_puddles_resolve float intensity = accBuf0.r; float thickness = 1.0 - intensity; - thickness = clamp(thickness - edgeCloseness, 0.0, 0.93); float2 packedNormal = texelFetch(blood_acc_normal, input.pos.xy, 0).rg; float3 normal = unpack_normal_so(packedNormal); - float reflectance; - float smoothness; - float bloodNormalBlend; float alpha = (1.0 - invAlpha); - float3 diffuse = lerp(blood_puddle_low_intensity_color.xyz, - blood_puddle_high_intensity_color.xyz, - 1.0 - thickness); - - BRANCH - if (isLandscape) - { - reflectance = blood_puddle_landscape_reflectance; - smoothness = lerp(blood_puddle_smoothness, blood_puddle_landscape_smoothness_edge, edgeCloseness); - bloodNormalBlend = 1.0 - edgeCloseness; - - diffuse *= lerp(blood_puddle_landscape_albedo_darkening, 1.0, edgeCloseness); - alpha *= 1.0 - pow(edgeCloseness, 4.0); - } - else - { - reflectance = blood_puddle_reflectance; - smoothness = lerp(blood_puddle_smoothness, blood_puddle_smoothness_edge, edgeCloseness); - - float invEdgeCloseness = 1.0 - edgeCloseness; - float3 vecToEdge = (ddx(invEdgeCloseness) * (view_vecLT + view_vecLB) + ddy(invEdgeCloseness) * (view_vecLT + view_vecRT)).xyz; - if (fwidth(invEdgeCloseness) > 0.5 / 255) - normal = lerp(normal, vecToEdge, saturate(edgeCloseness)); - float bloodNormalDominanceTerm = float(perGroupParams[decalType].bloodNormalDominanceTerm_edgeWidthScale & 0xFF)/255.0; - bloodNormalBlend = max(edgeCloseness, bloodNormalDominanceTerm); - } - - diffuse = lerp(1.0.xxx, diffuse, alpha); - float alpha3 = pow3(alpha); - - float srcMulDstDominance = lerp(1.0, 0.96, alpha3); - float srcDominance = (1.0/srcMulDstDominance - 1.0); - - UnpackedGbuffer output; - init_gbuffer(output); - init_albedo(output, diffuse * srcMulDstDominance); - init_ao(output, srcDominance); - init_reflectance(output, reflectance); - init_metalness(output, 0.0); - init_smoothness(output, smoothness); - init_normal(output, normal); - ##if special_vision == thermal_vision - init_material(output, SHADING_SELFILLUM); - init_emission(output, MAX_EMISSION); - init_emission_color(output, half4(255, 255, 255, 255.0f)); - output.smoothness = 0; - ##endif - - GBUFFER_OUTPUT gbuf = encode_gbuffer(output, 0, GET_SCREEN_POS(input.pos)); - gbuf.normal_material.w = bloodNormalBlend * alpha3; - gbuf.smoothness_reflectance_metallTranslucency_shadow.w = 0.9 * alpha3; - return gbuf; + return apply_blood_puddle_resolve_ps(decalType, isLandscape, thickness, edgeCloseness, + normal, alpha); } } @@ -472,6 +499,7 @@ shader blood_puddles WRITE_GBUFFER() INIT_PER_GROUP_PARAMS(ps) BLOOD_PUDDLES_COMMON_PS() + BLOOD_PUDDLES_RESOLVE_COMMON_PS() ENABLE_ASSERT(ps) hlsl(ps) { @@ -484,54 +512,15 @@ shader blood_puddles ##endif float3 normal; - float dryingTime, intensity, alpha, flowValue, edgeCloseness; - int stub; - unpack_blood(input, screen, normal, dryingTime, intensity, alpha, flowValue, edgeCloseness, stub); - - float3 vecToEdge = (ddx(flowValue) * (view_vecLT + view_vecLB) + ddy(flowValue) * (view_vecLT + view_vecRT)).xyz; - if (fwidth(flowValue) > 0.5 / 255) - normal = lerp(normal, (normal + normalize(vecToEdge)) * 0.5, edgeCloseness); - - float thicknessDrying = max(0.5, 1.0 - dryingTime); - float thickness = min(1.0 - intensity - edgeCloseness, 0.93) * thicknessDrying; - - float3 bloodColor = lerp(blood_puddle_high_intensity_color.xyz, blood_puddle_low_intensity_color.xyz, dryingTime); - float3 opacityColor = lerp(bloodColor.rrr, 1.0.xxx, edgeCloseness); - - float3 diffuse = lerp(bloodColor, opacityColor, edgeCloseness * dryingTime) - * (1.0-thickness); - diffuse = lerp(1.0.xxx, diffuse, alpha); - - float smoothness = lerp(1.0, 0.9, edgeCloseness); - float reflectance = lerp(0.19, 0.35, edgeCloseness); - - float alpha3 = pow3(alpha); - float srcMulDstDominance = lerp(1.0, 0.96, alpha3); - float srcDominance = (1.0/srcMulDstDominance - 1.0); - - UnpackedGbuffer output; - init_gbuffer(output); - init_albedo(output, diffuse * srcMulDstDominance); - init_ao(output, srcDominance); - init_reflectance(output, reflectance); - init_metalness(output, 0.0); - init_smoothness(output, smoothness); - init_normal(output, normal); - ##if special_vision == thermal_vision - init_material(output, SHADING_SELFILLUM); - init_emission(output, MAX_EMISSION); - init_emission_color(output, half4(255, 255, 255, 255.0f)); - output.smoothness = 0; - ##endif + float intensity, edgeCloseness, alpha, stub; + uint decalType, uiStub; + bool isLandscape; + unpack_blood(input, screen, normal, stub, intensity, alpha, stub, edgeCloseness, uiStub, decalType, isLandscape); - float decalType = input.decal_type_and_landscape__frame__rndIndex.x >> 1; - float bloodNormalDominanceTerm = float(perGroupParams[decalType].bloodNormalDominanceTerm_edgeWidthScale & 0xFF)/255.0; - float bloodNormalBlend = max(edgeCloseness, bloodNormalDominanceTerm); + float thickness = min(1.0 - intensity - edgeCloseness, 0.93); - GBUFFER_OUTPUT gbuf = encode_gbuffer(output, 0, GET_SCREEN_POS(input.pos));//should be PointToEye - gbuf.normal_material.w = bloodNormalBlend * alpha3; - gbuf.smoothness_reflectance_metallTranslucency_shadow.w = lerp(0.9, 0.3, dryingTime) * alpha3; - return gbuf; + return apply_blood_puddle_resolve_ps(decalType, isLandscape, thickness, + edgeCloseness, normal, alpha); } } compile("target_vs", "blood_puddles_vs"); @@ -558,7 +547,9 @@ shader blood_puddles_debug float3 stub3; float stub, edgeCloseness; - unpack_blood(input, screen, stub3, stub, stub, stub, stub, edgeCloseness, stub); + uint uiStub; + bool bStub; + unpack_blood(input, screen, stub3, stub, stub, stub, stub, edgeCloseness, stub, uiStub, bStub); return float4(edgeCloseness.xxx, 1); } diff --git a/prog/daNetGameLibs/daGdp/render/placers/heightmapES.cpp.inl b/prog/daNetGameLibs/daGdp/render/placers/heightmapES.cpp.inl index 54ab974d5..08c2ea05f 100644 --- a/prog/daNetGameLibs/daGdp/render/placers/heightmapES.cpp.inl +++ b/prog/daNetGameLibs/daGdp/render/placers/heightmapES.cpp.inl @@ -279,12 +279,16 @@ static inline void heightmap_view_process_es(const dagdp::EventViewProcess &evt, maybeMergeLastVariant(); - for (auto &grid : builder.grids) + for (auto [i, grid] : enumerate(builder.grids)) { for (const auto &variant : grid.variants) grid.density = max(grid.density, variant.effectiveDensity); grid.tileWorldSize = TILE_INSTANCE_COUNT_1D / sqrtf(grid.density); + + // Make sure the seeds are different for different grids, even if the default seed 0 is specified. + // Otherwise, if the density is the same, objects may appear in exactly the same position. + grid.prngSeed += i; } for (auto &grid : builder.grids) diff --git a/prog/daNetGameLibs/distant_haze/render/distantHazeES.cpp.inl b/prog/daNetGameLibs/distant_haze/render/distantHazeES.cpp.inl index 25d1d4baf..d49643c24 100644 --- a/prog/daNetGameLibs/distant_haze/render/distantHazeES.cpp.inl +++ b/prog/daNetGameLibs/distant_haze/render/distantHazeES.cpp.inl @@ -156,7 +156,7 @@ dabfg::NodeHandle createDistantHazeNode(DistantHazeManager &distant_haze__manage auto cameraHndl = registry.readBlob("current_camera").handle(); auto hazeRenderedHndl = registry.modifyBlob("haze_rendered").handle(); - registry.requestRenderPass().depthRw("haze_depth").color({(type == DistantHazeNodeType::Normal) ? "haze_offset" : "haze_color"}); + registry.requestRenderPass().color({(type == DistantHazeNodeType::Normal) ? "haze_offset" : "haze_color", "haze_depth"}); auto depthForTransparencyHndl = registry.readTexture("depth_for_transparency").atStage(dabfg::Stage::PS).useAs(dabfg::Usage::SHADER_RESOURCE).handle(); diff --git a/prog/daNetGameLibs/heat_haze/render/heatHazeES.cpp.inl b/prog/daNetGameLibs/heat_haze/render/heatHazeES.cpp.inl index 690e7e8d2..25cb74841 100644 --- a/prog/daNetGameLibs/heat_haze/render/heatHazeES.cpp.inl +++ b/prog/daNetGameLibs/heat_haze/render/heatHazeES.cpp.inl @@ -41,19 +41,12 @@ static dabfg::NodeHandle makeHeatHazeRenderClearNode(HeatHazeRenderer *heatHazeR // Only supported in WT G_ASSERT(!heatHazeRenderer->isHazeAppliedManual()); - uint32_t flags = 0; - for (auto format : {TEXFMT_DEPTH24, TEXFMT_DEPTH16}) - if (d3d::check_texformat(format | TEXCF_RTARGET | TEXCF_ESRAM_ONLY)) - { - flags = format | TEXCF_RTARGET | TEXCF_ESRAM_ONLY; - break; - } - auto hazeRenderedHndl = registry.createBlob("haze_rendered", dabfg::History::No).handle(); - auto hazeDepthHndl = registry.createTexture2d("haze_depth", dabfg::History::No, {flags, hazeResolution}) - .atStage(dabfg::Stage::PS) - .useAs(dabfg::Usage::COLOR_ATTACHMENT) - .handle(); + auto hazeDepthHndl = + registry.createTexture2d("haze_depth", dabfg::History::No, {TEXFMT_R16F | TEXCF_RTARGET | TEXCF_ESRAM_ONLY, hazeResolution}) + .atStage(dabfg::Stage::PS) + .useAs(dabfg::Usage::COLOR_ATTACHMENT) + .handle(); auto hazeOffsetHndl = registry diff --git a/prog/daNetGameLibs/hero_cockpit/render/hero_cockpit.das b/prog/daNetGameLibs/hero_cockpit/render/hero_cockpit.das index b9831aa65..a3fc149d4 100644 --- a/prog/daNetGameLibs/hero_cockpit/render/hero_cockpit.das +++ b/prog/daNetGameLibs/hero_cockpit/render/hero_cockpit.das @@ -24,8 +24,10 @@ struct QueryHeroWtmAndBoxForRender resWofs : float4 // vec3f resWofs resLboxMin, resLboxMax : float4 // bbox3f resLbox resReady : bool + resFlags : uint8 + _paddingMid : uint8[14] // alignof(HeroWtmAndBox)==16, so we add 14 bytes padding here onlyWeapons : bool - _paddingPost : uint8[12] // alignof(QueryHeroWtmAndBoxForRender)==16, so we add 12 bytes padding here + _paddingPost : uint8[15] // alignof(QueryHeroWtmAndBoxForRender)==16, so we add 15 bytes padding here def get_hero_cockpit_vec_impl(hero_cockpit__gunMaxLength, hero_cockpit__traceMaxBias, hero_cockpit__startFadeBeforeIntersection, hero_cockpit__fadeInterval, diff --git a/prog/daNetGameLibs/local_tone_mapping/render/localToneMappingSubscriptionES.cpp.gen.es.cpp b/prog/daNetGameLibs/local_tone_mapping/render/localToneMappingSubscriptionES.cpp.gen.es.cpp index a49588ca1..065561b17 100644 --- a/prog/daNetGameLibs/local_tone_mapping/render/localToneMappingSubscriptionES.cpp.gen.es.cpp +++ b/prog/daNetGameLibs/local_tone_mapping/render/localToneMappingSubscriptionES.cpp.gen.es.cpp @@ -26,29 +26,3 @@ static ecs::EntitySystemDesc register_local_tone_mapping_for_postfx_es_es_desc ecs::EventSetBuilder::build(), 0 ,"render"); -static constexpr ecs::ComponentDesc init_local_tone_mapping_samplers_node_es_comps[] = -{ -//start of 1 rw components at [0] - {ECS_HASH("local_tone_mapping__samplers_node"), ecs::ComponentTypeInfo()} -}; -static void init_local_tone_mapping_samplers_node_es_all_events(const ecs::Event &__restrict evt, const ecs::QueryView &__restrict components) -{ - auto comp = components.begin(), compE = components.end(); G_ASSERT(comp!=compE); do - init_local_tone_mapping_samplers_node_es(evt - , ECS_RW_COMP(init_local_tone_mapping_samplers_node_es_comps, "local_tone_mapping__samplers_node", dabfg::NodeHandle) - ); - while (++comp != compE); -} -static ecs::EntitySystemDesc init_local_tone_mapping_samplers_node_es_es_desc -( - "init_local_tone_mapping_samplers_node_es", - "prog/daNetGameLibs/local_tone_mapping/render/localToneMappingSubscriptionES.cpp.inl", - ecs::EntitySystemOps(nullptr, init_local_tone_mapping_samplers_node_es_all_events), - make_span(init_local_tone_mapping_samplers_node_es_comps+0, 1)/*rw*/, - empty_span(), - empty_span(), - empty_span(), - ecs::EventSetBuilder::build(), - 0 -,"render"); diff --git a/prog/daNetGameLibs/local_tone_mapping/render/localToneMappingSubscriptionES.cpp.inl b/prog/daNetGameLibs/local_tone_mapping/render/localToneMappingSubscriptionES.cpp.inl index 20a42b5de..b21bcfc94 100644 --- a/prog/daNetGameLibs/local_tone_mapping/render/localToneMappingSubscriptionES.cpp.inl +++ b/prog/daNetGameLibs/local_tone_mapping/render/localToneMappingSubscriptionES.cpp.inl @@ -15,16 +15,3 @@ static void register_local_tone_mapping_for_postfx_es(const RegisterPostfxResour .atStage(dabfg::Stage::POST_RASTER) .bindToShaderVar("exposure_tex"); } - - -ECS_TAG(render) -ECS_ON_EVENT(on_appear) -static void init_local_tone_mapping_samplers_node_es(const ecs::Event &, dabfg::NodeHandle &local_tone_mapping__samplers_node) -{ - local_tone_mapping__samplers_node = - (dabfg::root() / "local_tone_mapping").registerNode("samplers", DABFG_PP_NODE_SRC, [](dabfg::Registry registry) { - d3d::SamplerInfo smpInfo; - smpInfo.address_mode_u = smpInfo.address_mode_v = smpInfo.address_mode_w = d3d::AddressMode::Clamp; - registry.create("clamp_sampler", dabfg::History::No).blob(d3d::request_sampler(smpInfo)); - }); -} diff --git a/prog/daNetGameLibs/local_tone_mapping/render/local_tone_mapping.das b/prog/daNetGameLibs/local_tone_mapping/render/local_tone_mapping.das index b7a2c9395..69c5fb633 100644 --- a/prog/daNetGameLibs/local_tone_mapping/render/local_tone_mapping.das +++ b/prog/daNetGameLibs/local_tone_mapping/render/local_tone_mapping.das @@ -168,11 +168,9 @@ def register_upsample_nodes(var local_tone_mapping__upsample_nodes : NodeHandleV registry |> read(format("exposures_%d", srcIndex)) |> texture |> atStage(Stage COMPUTE) |> bindToShaderVar("exposures_tex") registry |> read(format("weights_%d", srcIndex)) |> texture |> atStage(Stage COMPUTE) |> bindToShaderVar("weights_tex") - registry |> read("clamp_sampler") |> blob(type) |> bindToShaderVar("weights_tex_samplerstate") |> bindToShaderVar("exposures_tex_samplerstate") if !lastNode registry |> read(format("exposure_multiplier_%d", inversedIndex + 1)) |> texture |> atStage(Stage COMPUTE) |> bindToShaderVar("accumulated_tex") registry |> read(format("exposures_%d", srcIndex + 1)) |> texture |> atStage(Stage COMPUTE) |> bindToShaderVar("coarse_exposures_tex") - registry |> read("clamp_sampler") |> blob(type) |> bindToShaderVar("accumulated_tex_samplerstate") |> bindToShaderVar("coarse_exposures_tex_samplerstate") var displayMip = firstNode ? local_tone_mapping__display_mip % MIPS_FOR_ONE_PASS : 0 @@ -210,7 +208,11 @@ def register_filter_node(var local_tone_mapping__filter_node : NodeHandle&; local_tone_mapping__filter_node <- (root() / "local_tone_mapping") |> registerNode("filter") <| @(var registry : Registry) registry |> read("exposure_multiplier_tex") |> texture |> atStage(Stage POST_RASTER) |> bindToShaderVar("exposure_tex") registry |> read((local_tone_mapping__hq_enabled ? "frame_for_postfx" : "downsampled_color")) |> texture |> atStage(Stage POST_RASTER) |> bindToShaderVar("frame_tex") - registry |> read("clamp_sampler") |> blob(type) |> bindToShaderVar("frame_tex_samplerstate") + let defaultSampler <- d3d_request_sampler() <| $(var smpInfo : SamplerInfo#) + smpInfo.address_mode_u = AddressMode Clamp + smpInfo.address_mode_v = AddressMode Clamp + smpInfo.address_mode_w = AddressMode Clamp + registry |> create("clamp_sampler", History No) |> blob(defaultSampler) |> bindToShaderVar("frame_tex_samplerstate") let scale = local_tone_mapping__hq_enabled ? local_tone_mapping__hq_final_tex_scale : local_tone_mapping__lq_final_tex_scale let texFormat = TEXFMT_R16F | TEXCF_ESRAM_ONLY diff --git a/prog/daNetGameLibs/local_tone_mapping/shaders/upsample.dshl b/prog/daNetGameLibs/local_tone_mapping/shaders/upsample.dshl index 70ccd8493..a14666172 100644 --- a/prog/daNetGameLibs/local_tone_mapping/shaders/upsample.dshl +++ b/prog/daNetGameLibs/local_tone_mapping/shaders/upsample.dshl @@ -20,12 +20,12 @@ shader local_tone_mapping_upsample bool hasAccumulated = upsample_mode != first_iter && upsample_mode != single_pass; local float4 tex_size = get_dimensions(exposures_tex, 0); (cs) { - weights_tex@smp2d = weights_tex; - exposures_tex@smp2d = exposures_tex; + weights_tex@tex2d = weights_tex; + exposures_tex@tex2d = exposures_tex; boostLocalContrast@i1 = boostLocalContrast; tex_size@f2 = tex_size; - accumulated_tex@smp2d = accumulated_tex; - coarse_exposures_tex@smp2d = coarse_exposures_tex; + accumulated_tex@tex2d = accumulated_tex; + coarse_exposures_tex@tex2d = coarse_exposures_tex; base_mip@i1 = base_mip; } hlsl(cs) { diff --git a/prog/daNetGameLibs/pathfinder/main/pathfinder_common.das b/prog/daNetGameLibs/pathfinder/main/pathfinder_common.das index e9b3290c5..a7ad6fc89 100644 --- a/prog/daNetGameLibs/pathfinder/main/pathfinder_common.das +++ b/prog/daNetGameLibs/pathfinder/main/pathfinder_common.das @@ -12,21 +12,21 @@ require math.maybe_pos public def get_lower_navmesh_pos(position : float3; horz_extents : float; is_valid : block<(pos : float3) : bool>) : MaybePos var minY = FLT_MAX - var res = [[MaybePos invalid=null]] + var res = MaybePos() query_navmesh_projections(position, float3(horz_extents, FLT_MAX, horz_extents), /*points num*/8) <| $(positions) for pos in positions if pos.y < minY && invoke(is_valid, pos) - res = [[MaybePos pos=pos]] + res = MaybePos(pos) minY = pos.y return res def get_lower_navmesh_pos_in_radius(position : float3; radius : float; is_valid : block<(pos : float3) : bool>) : MaybePos var minY = FLT_MAX - var res = [[MaybePos invalid=null]] + var res = MaybePos() query_navmesh_projections(position, float3(radius), /*points num*/8) <| $(positions) for pos in positions if pos.y < minY && invoke(is_valid, pos) - res = [[MaybePos pos=pos]] + res = MaybePos(pos) minY = pos.y return res @@ -34,7 +34,7 @@ def find_reachable_nav_point_around(start_pos, center : float3; radius : float; return find_nav_point_around(start_pos, center, radius, tries, is_valid, false) def find_nav_point_around(start_pos, center : float3; radius : float; tries : int; is_valid : block<(pos : float3) : bool>; accept_partial : bool = false) : MaybePos - var res = [[MaybePos invalid=null]] + var res = MaybePos() // TODO: project start pos to navmesh using() <| $(var path_corridor : dtPathCorridor) path_corridor |> init_path_corridor() @@ -56,7 +56,7 @@ def find_nav_point_around(start_pos, center : float3; radius : float; tries : in inp.includeFlags |= int(PolyFlag POLYFLAG_JUMP) let pathRes = set_path_corridor(path_corridor, inp, null) if pathRes != FindPathResult FPR_FAILED && (accept_partial || pathRes != FindPathResult FPR_PARTIAL) - res = [[MaybePos pos=pos]] + res = MaybePos(pos) if res is pos break diff --git a/prog/daNetGameLibs/scope/render/scopeAimRenderES.cpp.gen.es.cpp b/prog/daNetGameLibs/scope/render/scopeAimRenderES.cpp.gen.es.cpp index 1361b3bf6..51e80a931 100644 --- a/prog/daNetGameLibs/scope/render/scopeAimRenderES.cpp.gen.es.cpp +++ b/prog/daNetGameLibs/scope/render/scopeAimRenderES.cpp.gen.es.cpp @@ -3,6 +3,8 @@ static constexpr ecs::component_t bindedCamera_get_type(); static ecs::LTComponentList bindedCamera_component(ECS_HASH("bindedCamera"), bindedCamera_get_type(), "prog/daNetGameLibs/scope/render/scopeAimRenderES.cpp.inl", "", 0); static constexpr ecs::component_t gunmod__distortionParams_get_type(); static ecs::LTComponentList gunmod__distortionParams_component(ECS_HASH("gunmod__distortionParams"), gunmod__distortionParams_get_type(), "prog/daNetGameLibs/scope/render/scopeAimRenderES.cpp.inl", "", 0); +static constexpr ecs::component_t gunmod__lensBrightness_get_type(); +static ecs::LTComponentList gunmod__lensBrightness_component(ECS_HASH("gunmod__lensBrightness"), gunmod__lensBrightness_get_type(), "prog/daNetGameLibs/scope/render/scopeAimRenderES.cpp.inl", "", 0); static constexpr ecs::component_t gunmod__lensLocalX_get_type(); static ecs::LTComponentList gunmod__lensLocalX_component(ECS_HASH("gunmod__lensLocalX"), gunmod__lensLocalX_get_type(), "prog/daNetGameLibs/scope/render/scopeAimRenderES.cpp.inl", "", 0); static constexpr ecs::component_t gunmod__lensLocalY_get_type(); @@ -607,6 +609,7 @@ inline void prepare_scope_aim_rendering_data_ecs_query(Callable function) } static constexpr ecs::component_t bindedCamera_get_type(){return ecs::ComponentTypeInfo::type; } static constexpr ecs::component_t gunmod__distortionParams_get_type(){return ecs::ComponentTypeInfo::type; } +static constexpr ecs::component_t gunmod__lensBrightness_get_type(){return ecs::ComponentTypeInfo::type; } static constexpr ecs::component_t gunmod__lensLocalX_get_type(){return ecs::ComponentTypeInfo::type; } static constexpr ecs::component_t gunmod__lensLocalY_get_type(){return ecs::ComponentTypeInfo::type; } static constexpr ecs::component_t gunmod__lensLocalZ_get_type(){return ecs::ComponentTypeInfo::type; } diff --git a/prog/daNetGameLibs/scope/render/scopeAimRenderES.cpp.inl b/prog/daNetGameLibs/scope/render/scopeAimRenderES.cpp.inl index 5a77867a2..5a1e9968e 100644 --- a/prog/daNetGameLibs/scope/render/scopeAimRenderES.cpp.inl +++ b/prog/daNetGameLibs/scope/render/scopeAimRenderES.cpp.inl @@ -427,6 +427,8 @@ void render_lens_optics( ShaderGlobal::set_int(lens_detail_levelVarId, LENS_DETAIL_FULL); ShaderGlobal::set_int(lens_render_modeVarId, LENS_RENDER_OPTICS); + float lensBrightness = ECS_GET_OR(scopeAimData.entityWithScopeLensEid, gunmod__lensBrightness, 1.0f); + ShaderGlobal::set_real(lens_brighthnessVarId, lensBrightness); Point3 params = ECS_GET_OR(scopeAimData.entityWithScopeLensEid, gunmod__distortionParams, Point3(0.8f, 0.7f, 0.07f)); ShaderGlobal::set_color4(lens_distortion_paramsVarId, Color4(params.x, params.y, params.z, 0.0f)); Point3 lensLocalX = ECS_GET_OR(scopeAimData.entityWithScopeLensEid, gunmod__lensLocalX, Point3(1, 0, 0)); diff --git a/prog/daNetGameLibs/scope/shaders/scope_lens.dshl b/prog/daNetGameLibs/scope/shaders/scope_lens.dshl index b68b3330f..7c2794c7d 100644 --- a/prog/daNetGameLibs/scope/shaders/scope_lens.dshl +++ b/prog/daNetGameLibs/scope/shaders/scope_lens.dshl @@ -13,6 +13,7 @@ interval lens_render_mode: render_optics < 1, render_frame < 2, render_depth < 3 int render_scope_collimator = 1; interval render_scope_collimator: no < 1, yes; float lens_dof_depth = 0.5; +float lens_brighthness = 1.0; // Start radius coefficient, distortion strength, aberration strength. float4 lens_distortion_params = (0.9, 0.7, 0.07, 0); // cylinder len mul, cylinder shade radius norm, cylinder fading strength, collimator fading strength @@ -380,6 +381,7 @@ shader scope_lens, dynamic_crosshair screen_pos_to_texcoord@f2 = (screen_pos_to_texcoord.x, screen_pos_to_texcoord.y, 0, 0); scope_phys_params@f3 = (scope_radius, scope_length, 1.0 / scope_radius, 0); scope_lens_albedo@f4 = scope_lens_albedo; + lens_brighthness@f1 = lens_brighthness; lens_distortion_params@f3 = lens_distortion_params; lens_shading_params@f4 = lens_shading_params; lens_shading_params2@f3 = lens_shading_params2; @@ -522,6 +524,32 @@ shader scope_lens, dynamic_crosshair } #endif + half3 apply_lens_color(half3 color, half shade_factor) + { + ##if lens_detail_level != full_night_vision && special_vision != thermal_vision + shade_factor = min(shade_factor, lens_brighthness); + ##endif + + return color * shade_factor; + } + + half3 apply_lens_reflection(half3 color, VsOutput input, float4 screenpos, half shade_factor) + { + half3 reflections = half3(0,0,0); + ##if lens_detail_level != full_night_vision && special_vision != thermal_vision + reflections = apply_glass_ps(input, screenpos, half4(0, 0, 0, 1), 1).rgb; + ##endif + + half reflectionAlpha = 0; + ##if lens_detail_level == only_reflections + reflectionAlpha = (1 - shade_factor) * get_scope_lens_albedo().a; + ##else + reflectionAlpha = 0.005; + ##endif + + return color + reflections * get_scope_lens_albedo().rgb * reflectionAlpha; + } + float4 scope_lens_ps(VsOutput input HW_USE_SCREEN_POS INPUT_VFACE) : SV_Target0 { #if SET_UP_MULTIDRAW @@ -558,12 +586,9 @@ shader scope_lens, dynamic_crosshair ##endif ##endif - color *= shadeFactor; - ##if lens_detail_level != full_night_vision && special_vision != thermal_vision - half4 reflection = apply_glass_ps(input, screenpos, half4(0, 0, 0, 1), 1); - color += reflection.rgb * (1 - shadeFactor) * get_scope_lens_albedo().rgb * get_scope_lens_albedo().a; - ##endif + color = apply_lens_color(color, shadeFactor); + color = apply_lens_reflection(color, input, screenpos, shadeFactor); ##if (special_vision == thermal_vision && lens_detail_level == only_reflections) const half glass_temperature = 20.0/255.0; diff --git a/prog/daNetGameLibs/sound/common_sounds/es/game_effect_sound_tag.das b/prog/daNetGameLibs/sound/common_sounds/es/game_effect_sound_tag.das index b54ea64b1..48c8c2dc9 100644 --- a/prog/daNetGameLibs/sound/common_sounds/es/game_effect_sound_tag.das +++ b/prog/daNetGameLibs/sound/common_sounds/es/game_effect_sound_tag.das @@ -6,25 +6,25 @@ require sound_utils.modules.sound_player_common def game_effect_sound_tag_set(evt : Event; game_effect_sound__tag : string; game_effect__attachedTo : EntityId) - ecs::query(game_effect__attachedTo) <| $ [es] (var sound_tags : Object&) - raise_sound_tag(game_effect_sound__tag, sound_tags) + ecs::query(game_effect__attachedTo) <| $ [es] (var sound_flags : Object&) + raise_sound_tag(game_effect_sound__tag, sound_flags) [es(tag=sound, on_appear)] def sound_tags_entity_appear(evt : Event; eid : EntityId; - var sound_tags : Object&) + var sound_flags : Object&) ecs::query() <| $ [es] (game_effect_sound__tag : string; game_effect__attachedTo : EntityId) if game_effect__attachedTo != eid return - raise_sound_tag(game_effect_sound__tag, sound_tags) + raise_sound_tag(game_effect_sound__tag, sound_flags) [es(tag=sound, on_disappear)] def game_effect_sound_tag_unset(evt : Event; game_effect_sound__tag : string; game_effect__attachedTo : EntityId) - ecs::query(game_effect__attachedTo) <| $ [es] (var sound_tags : Object&) - clear_sound_tag(game_effect_sound__tag, sound_tags) + ecs::query(game_effect__attachedTo) <| $ [es] (var sound_flags : Object&) + clear_sound_tag(game_effect_sound__tag, sound_flags) diff --git a/prog/daNetGameLibs/sound/sound_utils/es/sound_debug.das b/prog/daNetGameLibs/sound/sound_utils/es/sound_debug.das index 3d51c5990..92dee7b5d 100644 --- a/prog/daNetGameLibs/sound/sound_utils/es/sound_debug.das +++ b/prog/daNetGameLibs/sound/sound_utils/es/sound_debug.das @@ -26,22 +26,23 @@ def sound_debug_draw_visual_labels(evt : Event) add_debug_text_mark(it.pos, "radius={it.radius} name={it.name}", -1, 0., E3DCOLOR(0xFFFF00FF)) -[es(no_order, tag=sound, on_event=EventSoundDrawDebug)] -def sound_debug_draw(evt : Event; - eid : EntityId; - is_watched_sound : bool = false; - sound_tags : Object const?; - sound_event_group : SoundEventGroup const?; - human_voice_effect__activeEffects : Object const?; - [[shared_comp]] human_voice_effect__allOrderedEffects : StringList const?; - sound_control__allowSound : bool = true; - sound_control__inRange : bool = true; - sound_control__soundEnabled : bool = true; - human_speech__voiceIdx = -1; - squad_member__memberIdx = -1; - squad_member__squad : EntityId; - team = -1; - transform : float3x4) +[es(no_order, tag=sound, on_event=EventSoundDrawDebug, REQUIRE=humanSound)] +def human_sound_debug_draw(evt : Event; + eid : EntityId; + is_watched_sound : bool = false; + sound_tags : Object const?; + sound_event_group : SoundEventGroup const?; + human_voice_effect__activeEffects : Object const?; + [[shared_comp]] human_voice_effect__allOrderedEffects : StringList const?; + sound_control__allowSound : bool = true; + sound_control__inRange : bool = true; + sound_control__soundEnabled : bool = true; + human_speech__voiceIdx = -1; + squad_member__memberIdx = -1; + squad_member__squad = INVALID_ENTITY_ID; + human_speech__locale = ""; + team = -1; + transform : float3x4) if !sound_control__inRange return @@ -78,6 +79,9 @@ def sound_debug_draw(evt : Event; if sound_event_group != null && (is_watched_sound || get_num_sounds(*sound_event_group) > 0) text += "sound group:{get_num_sounds(*sound_event_group)} " + if !empty(human_speech__locale) + text += "loc={human_speech__locale} " + if human_speech__voiceIdx >= 0 text += "voice=#{human_speech__voiceIdx} " text += "member=#{squad_member__memberIdx} " @@ -107,6 +111,17 @@ def sound_debug_console_sound_play(path : string; duration = 5.) abandon(handle, duration) +[console_cmd(name="snd.play_pos")] +def sound_debug_console_sound_play_pos(path : string; x, y, z : float; duration = 5.) + var handle = soundEvent::play("", path, float3(x, y, z)) + if is_valid_handle_value(handle) + sound_debug("snd.play '{path}' is3d={is_3d(handle)}; maxRange={get_max_distance(handle)}; isOneshot={is_oneshot(handle)}") + if is_oneshot(handle) + abandon(handle) + else + abandon(handle, duration) + + [console_cmd(name="snd.enum_events")] def sound_debug_console_enum_events() sound_debug_enum_events() diff --git a/prog/daNetGameLibs/sound/sound_utils/es/sound_tags.das b/prog/daNetGameLibs/sound/sound_utils/es/sound_tags.das new file mode 100644 index 000000000..6c2f478db --- /dev/null +++ b/prog/daNetGameLibs/sound/sound_utils/es/sound_tags.das @@ -0,0 +1,17 @@ +require ecs + + +[es(tag=sound, on_appear, track=(sound_flags, sound_mods))] +def sound_tags_apply(evt : Event; + sound_flags : Object; + sound_mods : EidList; + var sound_tags : Object&) + + sound_tags |> clear() + + sound_tags := sound_flags + + for eid in sound_mods + query(eid) <| $ [es] (sound_mod_tags : StringList) + for tag in sound_mod_tags + sound_tags |> set(string(tag), true) diff --git a/prog/daNetGameLibs/sound/sound_utils/templates/sound_utils.template.blk b/prog/daNetGameLibs/sound/sound_utils/templates/sound_utils.template.blk index f2fb1f305..6aba44553 100644 --- a/prog/daNetGameLibs/sound/sound_utils/templates/sound_utils.template.blk +++ b/prog/daNetGameLibs/sound/sound_utils/templates/sound_utils.template.blk @@ -172,11 +172,19 @@ sound_irqs{ _tags:t="sound" } } + sound_tags{ + "sound_flags:object"{ + _tags:t="sound" + } + "sound_mods:list"{ + _tags:t="sound" + } "sound_tags:object"{ _tags:t="sound" } - _tracked:t="sound_tags" + _tracked:t="sound_flags" + _tracked:t="sound_mods" } sound_player_components{ diff --git a/prog/daNetGameLibs/volfog_mask/shaders/volfog_mask.dshl b/prog/daNetGameLibs/volfog_mask/shaders/volfog_mask.dshl index df00dfbb9..7711a3336 100644 --- a/prog/daNetGameLibs/volfog_mask/shaders/volfog_mask.dshl +++ b/prog/daNetGameLibs/volfog_mask/shaders/volfog_mask.dshl @@ -1,3 +1,3 @@ texture volfog_mask_tex always_referenced; -texture volfog_mask_tex_samplerstate always_referenced; +sampler volfog_mask_tex_samplerstate; float4 world_to_volfog_mask always_referenced; diff --git a/prog/dagorInclude/anim/dag_animBlend.h b/prog/dagorInclude/anim/dag_animBlend.h index 2daa1dd1b..5d926783a 100644 --- a/prog/dagorInclude/anim/dag_animBlend.h +++ b/prog/dagorInclude/anim/dag_animBlend.h @@ -17,6 +17,7 @@ #include #include #include +#include #include // forward declarations for external classes and structures @@ -112,6 +113,9 @@ class IAnimBlendNode : public DObject virtual void debugSetIrqPos(const char * /*irq_name*/, float /*rel_pos*/) {} + virtual void initChilds(AnimationGraph & /*graph*/, const DataBlock & /*settings*/, const char * /*nm_suffix*/) {} + virtual void checkHasLoop(AnimationGraph & /*graph*/, eastl::bitvector<> & /*visited_nodes*/) {} + private: int abnId; }; diff --git a/prog/dagorInclude/anim/dag_animBlendCtrl.h b/prog/dagorInclude/anim/dag_animBlendCtrl.h index b01bb3729..3b855bbef 100644 --- a/prog/dagorInclude/anim/dag_animBlendCtrl.h +++ b/prog/dagorInclude/anim/dag_animBlendCtrl.h @@ -90,6 +90,8 @@ class AnimBlendCtrl_1axis : public IAnimBlendNode int getParamId() const { return paramId; } static void createNode(AnimationGraph &graph, const DataBlock &blk, const char *nm_suffix); + virtual void initChilds(AnimationGraph &graph, const DataBlock &blk, const char *nm_suffix) override; + virtual void checkHasLoop(AnimationGraph &graph, eastl::bitvector<> &visited_nodes) override; }; @@ -174,6 +176,8 @@ class AnimBlendCtrl_RandomSwitcher : public IAnimBlendNode int getRepParamId() const { return repParamId; } static void createNode(AnimationGraph &graph, const DataBlock &blk, const char *nm_suffix); + virtual void initChilds(AnimationGraph &graph, const DataBlock &blk, const char *nm_suffix) override; + virtual void checkHasLoop(AnimationGraph &graph, eastl::bitvector<> &nodes_state) override; }; // @@ -233,6 +237,8 @@ class AnimBlendCtrl_ParametricSwitcher : public IAnimBlendNode int getParamId() const { return paramId; } static void createNode(AnimationGraph &graph, const DataBlock &blk, const char *nm_suffix); + virtual void initChilds(AnimationGraph &graph, const DataBlock &blk, const char *nm_suffix) override; + virtual void checkHasLoop(AnimationGraph &graph, eastl::bitvector<> &nodes_state) override; }; // @@ -286,6 +292,8 @@ class AnimBlendCtrl_Hub : public IAnimBlendNode int getParamId() const { return paramId; } static void createNode(AnimationGraph &graph, const DataBlock &blk, const char *nm_suffix); + virtual void initChilds(AnimationGraph &graph, const DataBlock &blk, const char *nm_suffix) override; + virtual void checkHasLoop(AnimationGraph &graph, eastl::bitvector<> &nodes_state) override; protected: inline const float *getProps(IPureAnimStateHolder &st); @@ -336,6 +344,8 @@ class AnimBlendCtrl_Blender : public IAnimBlendNode int getParamId() const { return paramId; } static void createNode(AnimationGraph &graph, const DataBlock &blk); + virtual void initChilds(AnimationGraph &graph, const DataBlock &blk, const char *nm_suffix) override; + virtual void checkHasLoop(AnimationGraph &graph, eastl::bitvector<> &nodes_state) override; }; // @@ -373,6 +383,8 @@ class AnimBlendCtrl_BinaryIndirectSwitch : public IAnimBlendNode int getParamId() const { return paramId; } static void createNode(AnimationGraph &graph, const DataBlock &blk); + virtual void initChilds(AnimationGraph &graph, const DataBlock &blk, const char *nm_suffix) override; + virtual void checkHasLoop(AnimationGraph &graph, eastl::bitvector<> &nodes_state) override; }; // @@ -427,6 +439,8 @@ class AnimBlendCtrl_LinearPoly : public IAnimBlendNode int getParamId() const { return paramId; } static void createNode(AnimationGraph &graph, const DataBlock &blk, const char *nm_suffix); + virtual void initChilds(AnimationGraph &graph, const DataBlock &blk, const char *nm_suffix) override; + virtual void checkHasLoop(AnimationGraph &graph, eastl::bitvector<> &nodes_state) override; protected: static int anim_point_p0_cmp(const AnimPoint *p1, const AnimPoint *p2); diff --git a/prog/dagorInclude/drv/3d/dag_commands.h b/prog/dagorInclude/drv/3d/dag_commands.h index a77cddb46..07299c936 100644 --- a/prog/dagorInclude/drv/3d/dag_commands.h +++ b/prog/dagorInclude/drv/3d/dag_commands.h @@ -414,6 +414,20 @@ enum class Drv3dCommand DELAY_SYNC, CONTINUE_SYNC, + // + // Changes GPU queue/pipeline where order dependant action commands will be submitted + // i.e. dispatches, draws, and mostly any commands that execute work on GPU and require GPU lock + // Represents queue+command buffer combo of low level graphics APIs + // Must be called under GPU lock + // Effect of this command do not "revert" back on some automatic basis, yet + // device reset/queue flush restores queue to default (graphics) + // GpuPipeline parameters of d3d:: API calls are ignored when this command is in effect + // + // par1: GpuPipeline - target queue/pipeline where commands will be submitted after this command + // + // returns 1 if driver switched queue, otherwise returns 0 + CHANGE_QUEUE, + USER = 1000, }; diff --git a/prog/dagorInclude/drv/3d/dag_consts.h b/prog/dagorInclude/drv/3d/dag_consts.h index 3f0183c11..f129d91a5 100644 --- a/prog/dagorInclude/drv/3d/dag_consts.h +++ b/prog/dagorInclude/drv/3d/dag_consts.h @@ -49,7 +49,8 @@ enum ShaderStage enum class GpuPipeline { GRAPHICS, - ASYNC_COMPUTE + ASYNC_COMPUTE, + TRANSFER }; // general limitations diff --git a/prog/dagorInclude/math/dag_mathBase.h b/prog/dagorInclude/math/dag_mathBase.h index 90baf1603..3a076a5b0 100644 --- a/prog/dagorInclude/math/dag_mathBase.h +++ b/prog/dagorInclude/math/dag_mathBase.h @@ -190,7 +190,7 @@ template struct DisablePointersInMath; template -INLINE T clamp(T t, const T min_val, const T max_val) +[[nodiscard]] INLINE T clamp(T t, const T min_val, const T max_val) { DisablePointersInMath(); if (t < min_val) @@ -200,6 +200,51 @@ INLINE T clamp(T t, const T min_val, const T max_val) return max_val; } +template +inline void clamp_inplace(T &t, const T min_val, const T max_val) +{ + DisablePointersInMath(); + if (t < min_val) + t = min_val; + if (t <= max_val) + return; + t = max_val; +} + +template +[[nodiscard]] inline T1 clamp_max(const T1 value, const T2 p_max) +{ + DisablePointersInMath(); + if (value > (T1)p_max) + return (T1)p_max; + return value; +} + +template +[[nodiscard]] inline T1 clamp_min(const T1 value, const T2 p_min) +{ + DisablePointersInMath(); + if (value < (T1)p_min) + return (T1)p_min; + return value; +} + +template +inline void clamp_max_inplace(T1 &value, const T2 p_max) +{ + DisablePointersInMath(); + if (value > (T1)p_max) + value = (T1)p_max; +} + +template +inline void clamp_min_inplace(T1 &value, const T2 p_min) +{ + DisablePointersInMath(); + if (value < (T1)p_min) + value = (T1)p_min; +} + // fast versions, |Relative Error| <= 1.5 * 2^(-12) #if _TARGET_SIMD_SSE INLINE float fastinvsqrt(float x) { return _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(x))); } diff --git a/prog/dagorInclude/osApiWrappers/dag_dynLib.h b/prog/dagorInclude/osApiWrappers/dag_dynLib.h index 5d6875df7..b3e53fba1 100644 --- a/prog/dagorInclude/osApiWrappers/dag_dynLib.h +++ b/prog/dagorInclude/osApiWrappers/dag_dynLib.h @@ -4,6 +4,7 @@ // #pragma once +#include #include KRNLIMP void *os_dll_load(const char *filename); @@ -20,11 +21,13 @@ KRNLIMP bool os_dll_close(void *handle); // Otherwise, returns nullptr, and the buffer is not touched. KRNLIMP const char *os_dll_get_dll_name_from_addr(char *out_buf, size_t out_buf_size, const void *addr); -struct DagorDllCloser +struct DagorDynLibCloser { void operator()(void *handle) { handle ? (void)os_dll_close(handle) : (void)0; } }; +using DagorDynLibHolder = eastl::unique_ptr; + #include #if _TARGET_PC_WIN | _TARGET_XBOX diff --git a/prog/dagorInclude/shaders/dag_shaderResUnitedData.h b/prog/dagorInclude/shaders/dag_shaderResUnitedData.h index 79fa8a741..c758b5938 100644 --- a/prog/dagorInclude/shaders/dag_shaderResUnitedData.h +++ b/prog/dagorInclude/shaders/dag_shaderResUnitedData.h @@ -193,7 +193,7 @@ class ShaderResUnitedVdata mutable std::mutex hintsMutex; int noDiscardFrames = 120; int keepIfNeedLodFrames = 600; - int requestLodsByDistanceFrames = 60; + int requestLodsByDistanceFrames = 0; unitedvdata::BufConfig getHints() const; diff --git a/prog/dagorInclude/workCycle/dag_workCycle.h b/prog/dagorInclude/workCycle/dag_workCycle.h index 51c8dd3ae..1ea05318f 100644 --- a/prog/dagorInclude/workCycle/dag_workCycle.h +++ b/prog/dagorInclude/workCycle/dag_workCycle.h @@ -15,6 +15,9 @@ void dagor_work_cycle(); //! must be used before any on-screen rendering outside of work cycle void dagor_work_cycle_flush_pending_frame(); +// Return false if draw is going to be skipped (minimized fullscreen, occluded window, etc...) +bool dagor_work_cycle_is_need_to_draw(); + //! process system events //! NOTE: it is called also from dagor_idle_cycle() void dagor_process_sys_messages(bool input_only = false); diff --git a/prog/dagorInclude/workCycle/dag_workCyclePerf.h b/prog/dagorInclude/workCycle/dag_workCyclePerf.h index 1c79c22ac..c0342f360 100644 --- a/prog/dagorInclude/workCycle/dag_workCyclePerf.h +++ b/prog/dagorInclude/workCycle/dag_workCyclePerf.h @@ -70,18 +70,6 @@ inline void mark_cpu_only_cycle_end() } } -inline void mark_cpu_only_cycle_pause() -{ - if (!cpu_only_cycle_record_enabled) - return; - - if (ref_cpu_only_cycle_start != 0) - { - last_cpu_only_cycle_time_usec = get_time_usec(ref_cpu_only_cycle_start); - summed_cpu_only_cycle_time += last_cpu_only_cycle_time_usec; - } -} - void reset_summed_cpu_only_cycle_time(); float get_avg_cpu_only_cycle_time_usec(); } // namespace workcycleperf diff --git a/prog/engine/anim/animGraph.cpp b/prog/engine/anim/animGraph.cpp index 31fbd96ef..a0d03d419 100644 --- a/prog/engine/anim/animGraph.cpp +++ b/prog/engine/anim/animGraph.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -1722,18 +1723,10 @@ static void add_bn(AnimationGraph &graph, const DataBlock &blk, const char *nm_s else if (dd_stricmp(blk.getBlockName(), "footLockerIK") == 0) FootLockerIKCtrl::createNode(graph, blk); - else if (dd_stricmp(blk.getBlockName(), "alias") == 0) - { - IAnimBlendNode *n = graph.getBlendNodePtr(blk.getStr("origin"), nm_suffix); - if (!n && blk.getBool("allowSuffixless", false)) - n = graph.getBlendNodePtr(blk.getStr("origin")); - graph.registerBlendNode(n, blk.getStr("name"), nm_suffix); - } - else if (dd_stricmp(blk.getBlockName(), "animateAndProcNode") == 0) createNodeApbAnimateAndPostBlendProc(graph, blk, nm_suffix, add_bn); - else + else if (dd_stricmp(blk.getBlockName(), "alias") != 0) { logerr("unknown BlendNode class <%s>", blk.getBlockName()); AnimBlendNodeNull::createNode(graph, blk); @@ -1742,6 +1735,92 @@ static void add_bn(AnimationGraph &graph, const DataBlock &blk, const char *nm_s fatal_context_pop(); } +struct ControllerDependencyLoadHelper +{ + Ptr node; + const DataBlock *settings; + const char *nodeMaskSuffix; +}; + +static const char *controller_names_with_dependecy[] = { + "linear", "linearPoly", "randomSwitch", "paramSwitch", "paramSwitchS", "hub", "blender", "BIS"}; + +static bool controller_has_dependency(const char *block_name) +{ + return lup(block_name, controller_names_with_dependecy, countof(controller_names_with_dependecy)) != -1; +} + +static bool find_and_replce_alias_origin(dag::Vector &controllers, int selected_idx, + bool allow_suffixless = false) +{ + ControllerDependencyLoadHelper &controller = controllers[selected_idx]; + const char *originName = controller.settings->getStr("origin"); + for (int i = selected_idx + 1; i < controllers.size(); ++i) + { + // try find origin with equal name field and with allow_suffixless or bouth null or equal suffix + if (dd_stricmp(originName, controllers[i].settings->getStr("name")) == 0) + if (allow_suffixless || (!controller.nodeMaskSuffix && !controllers[i].nodeMaskSuffix) || + (controller.nodeMaskSuffix && controllers[i].nodeMaskSuffix && + dd_stricmp(controller.nodeMaskSuffix, controllers[i].nodeMaskSuffix) == 0)) + { + ControllerDependencyLoadHelper tempController = controllers[i]; + controllers.erase(controllers.begin() + i); + controllers.insert(controllers.begin() + selected_idx, tempController); + return true; + } + } + + return false; +} + +static void init_alias_controllers(dag::Vector &controllers, AnimationGraph &graph) +{ + int aliasChangeOrderingCount = 0; + for (int i = 0; i < controllers.size(); ++i) + { + const char *originName = controllers[i].settings->getStr("origin"); + const char *nodeName = controllers[i].settings->getStr("name"); + IAnimBlendNode *node = graph.getBlendNodePtr(originName, controllers[i].nodeMaskSuffix); + if (!node) + { + if (i + aliasChangeOrderingCount >= controllers.size()) + { + // Skip node with loop for init other alias nodes + ANIM_ERR("Find loop in alias nodes, node: %s suffix: %s, with origin: %s", nodeName, controllers[i].nodeMaskSuffix, + originName); + aliasChangeOrderingCount = 0; + continue; + } + if (find_and_replce_alias_origin(controllers, i)) + { + ++aliasChangeOrderingCount; + --i; + continue; + } + } + + bool allowSuffixless = controllers[i].settings->getBool("allowSuffixless", false); + if (!node && allowSuffixless) + node = graph.getBlendNodePtr(originName); + + if (node) + { + aliasChangeOrderingCount = 0; + graph.registerBlendNode(node, nodeName, controllers[i].nodeMaskSuffix); + } + else if (allowSuffixless) + { + if (find_and_replce_alias_origin(controllers, i, allowSuffixless)) + { + ++aliasChangeOrderingCount; + --i; + } + } + else + ANIM_ERR("Can't find %s node for alias node with name: %s", originName, nodeName); + } +} + static bool load_generic_graph(AnimationGraph &graph, const DataBlock &blk, dag::ConstSpan anim_list, const Tab &nodesWithIgnoredAnimation) { @@ -1932,6 +2011,8 @@ static bool load_generic_graph(AnimationGraph &graph, const DataBlock &blk, dag: } // append other controllers + dag::Vector controllersWithDependency; + dag::Vector aliasControllers; nid = blk.getNameId("AnimBlendCtrl"); for (i = 0; i < blk.blockCount(); i++) if (blk.getBlock(i)->getBlockNameId() == nid) @@ -1941,29 +2022,58 @@ static bool load_generic_graph(AnimationGraph &graph, const DataBlock &blk, dag: continue; for (j = 0; j < b->blockCount(); j++) { - AnimNodeMaskApplyFilter nmFilter(*b->getBlock(j)); - const char *anim_name = b->getBlock(j)->getStr("name", NULL); + const DataBlock *settings = b->getBlock(j); + AnimNodeMaskApplyFilter nmFilter(*settings); + const char *anim_name = settings->getStr("name", nullptr); if (!nmFilter.isNameRejected("")) - add_bn(graph, *b->getBlock(j), NULL); + { + add_bn(graph, *settings, nullptr); + if (controller_has_dependency(settings->getBlockName())) + controllersWithDependency.emplace_back( + ControllerDependencyLoadHelper{graph.getBlendNodePtr(anim_name, nullptr), settings, nullptr}); + else if (dd_stricmp(settings->getBlockName(), "alias") == 0) + aliasControllers.emplace_back(ControllerDependencyLoadHelper{nullptr, settings, nullptr}); + } else if (anim_name) graph.registerBlendNode(nullAnim, anim_name); - bool def_split_chans = - strstr("linear linearPoly randomSwitch paramSwitch paramSwitchS alias", b->getBlock(j)->getBlockName()) != NULL; - if (b->getBlock(j)->getBool("splitChans", def_split_chans)) + bool def_split_chans = strstr("linear linearPoly randomSwitch paramSwitch paramSwitchS alias", settings->getBlockName()); + if (settings->getBool("splitChans", def_split_chans)) if (int chan_cnt = graph.getStDest().size()) for (int k = 0; k < chan_cnt; k++) if (graph.getStDest()[k].defNodemaskIdx >= 0) { const char *nm_name = nodemask[graph.getStDest()[k].defNodemaskIdx]->name; if (!nmFilter.isNameRejected(nm_name)) - add_bn(graph, *b->getBlock(j), nm_name); + { + add_bn(graph, *settings, nm_name); + if (controller_has_dependency(settings->getBlockName())) + controllersWithDependency.emplace_back( + ControllerDependencyLoadHelper{graph.getBlendNodePtr(anim_name, nm_name), settings, nm_name}); + else if (dd_stricmp(settings->getBlockName(), "alias") == 0) + aliasControllers.emplace_back(ControllerDependencyLoadHelper{nullptr, settings, nm_name}); + } else if (anim_name) graph.registerBlendNode(nullAnim, anim_name, nm_name); } } } + init_alias_controllers(aliasControllers, graph); + + for (ControllerDependencyLoadHelper &controller : controllersWithDependency) + { + fatal_context_push(String(256, "ctrl: %s", controller.settings->getStr("name", "n/a"))); + controller.node->initChilds(graph, *controller.settings, controller.nodeMaskSuffix); + fatal_context_pop(); + } + + eastl::bitvector<> animNodeState; + animNodeState.resize(graph.getAnimNodeCount(), false); + + for (ControllerDependencyLoadHelper &controller : controllersWithDependency) + controller.node->checkHasLoop(graph, animNodeState); + // clear nodemask clear_all_ptr_items_and_shrink(nodemask); @@ -2260,6 +2370,7 @@ void AnimBlendNodeNull::createNode(AnimationGraph &graph, const DataBlock &blk) graph.registerBlendNode(new AnimBlendNodeNull, name); } + void AnimBlendCtrl_1axis::createNode(AnimationGraph &graph, const DataBlock &blk, const char *nm_suffix) { const char *name = blk.getStr("name", NULL); @@ -2278,6 +2389,11 @@ void AnimBlendCtrl_1axis::createNode(AnimationGraph &graph, const DataBlock &blk var_name = String("var") + name; AnimBlendCtrl_1axis *node = new AnimBlendCtrl_1axis(graph, var_name); + graph.registerBlendNode(node, name, nm_suffix); +} + +void AnimBlendCtrl_1axis::initChilds(AnimationGraph &graph, const DataBlock &blk, const char *nm_suffix) +{ int child_nid = blk.getNameId("child"), i; if (child_nid != -1) for (i = 0; i < blk.blockCount(); i++) @@ -2288,7 +2404,7 @@ void AnimBlendCtrl_1axis::createNode(AnimationGraph &graph, const DataBlock &blk if (!nm) { ANIM_ERR(" is not defined in hub child"); - delete node; + graph.unregisterBlendNode(this); return; } @@ -2297,12 +2413,37 @@ void AnimBlendCtrl_1axis::createNode(AnimationGraph &graph, const DataBlock &blk { if (!is_ignoring_unavailable_resources()) ANIM_ERR("blend node <%s> (suffix=%s) not found!", nm, nm_suffix); - delete node; + graph.unregisterBlendNode(this); return; } - node->addBlendNode(n, cblk->getReal("start", 0), cblk->getReal("end", 1.0f)); + addBlendNode(n, cblk->getReal("start", 0), cblk->getReal("end", 1.0f)); } - graph.registerBlendNode(node, name, nm_suffix); +} + +void AnimBlendCtrl_1axis::checkHasLoop(AnimationGraph &graph, eastl::bitvector<> &visited_nodes) +{ + int id = getAnimNodeId(); + if (id == -1) + return; + + visited_nodes[id] = true; + for (const AnimSlice &child : slice) + { + int childId = child.node->getAnimNodeId(); + if (childId == -1) + continue; + + if (visited_nodes[childId]) + { + ANIM_ERR("Find loop in controller childs, controller: %s, parent: %s", graph.getAnimNodeName(childId), + graph.getAnimNodeName(id)); + slice.clear(); + break; + } + else + child.node->checkHasLoop(graph, visited_nodes); + } + visited_nodes[id] = false; } void AnimBlendCtrl_LinearPoly::createNode(AnimationGraph &graph, const DataBlock &blk, const char *nm_suffix) @@ -2327,6 +2468,12 @@ void AnimBlendCtrl_LinearPoly::createNode(AnimationGraph &graph, const DataBlock node->enclosed = blk.getBool("enclosed", false); node->paramTau = blk.getReal("paramTau", 0.0f); node->paramSpeed = blk.getReal("paramSpeed", 0.0f); + graph.registerBlendNode(node, name, nm_suffix); +} + +void AnimBlendCtrl_LinearPoly::initChilds(AnimationGraph &graph, const DataBlock &blk, const char *nm_suffix) +{ + const char *name = blk.getStr("name"); int child_nid = blk.getNameId("child"), i; if (child_nid != -1) for (i = 0; i < blk.blockCount(); i++) @@ -2347,9 +2494,34 @@ void AnimBlendCtrl_LinearPoly::createNode(AnimationGraph &graph, const DataBlock ANIM_ERR("blend node <%s> (suffix=%s) not found!", nm, nm_suffix); return; } - node->addBlendNode(n, cblk->getReal("val", 0), graph, name); + addBlendNode(n, cblk->getReal("val", 0), graph, name); } - graph.registerBlendNode(node, name, nm_suffix); +} + +void AnimBlendCtrl_LinearPoly::checkHasLoop(AnimationGraph &graph, eastl::bitvector<> &visited_nodes) +{ + int id = getAnimNodeId(); + if (id == -1) + return; + + visited_nodes[id] = true; + for (const AnimPoint &child : poly) + { + int childId = child.node->getAnimNodeId(); + if (childId == -1) + continue; + + if (visited_nodes[childId]) + { + ANIM_ERR("Find loop in controller childs, controller: %s, parent: %s", graph.getAnimNodeName(childId), + graph.getAnimNodeName(id)); + poly.clear(); + break; + } + else + child.node->checkHasLoop(graph, visited_nodes); + } + visited_nodes[id] = false; } void AnimBlendCtrl_Fifo3::createNode(AnimationGraph &graph, const DataBlock &blk) @@ -2387,6 +2559,11 @@ void AnimBlendCtrl_RandomSwitcher::createNode(AnimationGraph &graph, const DataB AnimBlendCtrl_RandomSwitcher *node = new AnimBlendCtrl_RandomSwitcher(graph, var_name); + graph.registerBlendNode(node, name, nm_suffix); +} + +void AnimBlendCtrl_RandomSwitcher::initChilds(AnimationGraph &graph, const DataBlock &blk, const char *nm_suffix) +{ // create anim list const DataBlock *cblk = blk.getBlockByName("weight"); const DataBlock *rblk = blk.getBlockByName("maxrepeat"); @@ -2407,13 +2584,37 @@ void AnimBlendCtrl_RandomSwitcher::createNode(AnimationGraph &graph, const DataB LOGERR_CTX("blend node <%s> (suffix=%s) not found!", nm, nm_suffix); continue; } - node->addBlendNode(n, cblk->getReal(i), rblk ? rblk->getInt(nm, 1) : 1); + addBlendNode(n, cblk->getReal(i), rblk ? rblk->getInt(nm, 1) : 1); } } - node->recalcWeights(); + recalcWeights(); +} - graph.registerBlendNode(node, name, nm_suffix); +void AnimBlendCtrl_RandomSwitcher::checkHasLoop(AnimationGraph &graph, eastl::bitvector<> &visited_nodes) +{ + int id = getAnimNodeId(); + if (id == -1) + return; + + visited_nodes[id] = true; + for (const RandomAnim &child : list) + { + int childId = child.node->getAnimNodeId(); + if (childId == -1) + continue; + + if (visited_nodes[childId]) + { + ANIM_ERR("Find loop in controller childs, controller: %s, parent: %s", graph.getAnimNodeName(childId), + graph.getAnimNodeName(id)); + list.clear(); + break; + } + else + child.node->checkHasLoop(graph, visited_nodes); + } + visited_nodes[id] = false; } void AnimBlendCtrl_ParametricSwitcher::createNode(AnimationGraph &graph, const DataBlock &blk, const char *nm_suffix) @@ -2435,12 +2636,25 @@ void AnimBlendCtrl_ParametricSwitcher::createNode(AnimationGraph &graph, const D AnimBlendCtrl_ParametricSwitcher *node = new AnimBlendCtrl_ParametricSwitcher(graph, var_name, blk.getStr("varname_residual", NULL)); - // create anim list node->morphTime = blk.getReal("morphTime", 0.15f); + graph.registerBlendNode(node, name, nm_suffix); +} + +void AnimBlendCtrl_ParametricSwitcher::initChilds(AnimationGraph &graph, const DataBlock &blk, const char *nm_suffix) +{ + const char *name = blk.getStr("name"); + const char *_vname = blk.getStr("varname", nullptr); + String var_name; + + if (_vname) + var_name = _vname; + else + var_name = String("var") + name; const DataBlock *cblk = blk.getBlockByName("nodes"); bool has_single = false; + // create anim list if (cblk) { for (int i = 0; i < cblk->blockCount(); i++) @@ -2467,7 +2681,7 @@ void AnimBlendCtrl_ParametricSwitcher::createNode(AnimationGraph &graph, const D r1 = eval + 0.1f; } } - node->addBlendNode(n, min(r0, r1), max(r1, r0), bv, graph, name); + addBlendNode(n, min(r0, r1), max(r1, r0), bv, graph, name); if (n->isSubOf(AnimBlendNodeSingleLeafCID)) has_single = true; } @@ -2534,7 +2748,7 @@ void AnimBlendCtrl_ParametricSwitcher::createNode(AnimationGraph &graph, const D int eval = AnimV20::getEnumValueByName(enum_nm); if (eval < 0) ANIM_ERR("missing enum <%s>", enum_nm); - node->addBlendNode(n, (eval >= 0) ? eval - 0.1f : 0, (eval >= 0) ? eval + 0.1f : 0, 0, graph, var_name); + addBlendNode(n, (eval >= 0) ? eval - 0.1f : 0, (eval >= 0) ? eval + 0.1f : 0, 0, graph, var_name); if (n->isSubOf(AnimBlendNodeSingleLeafCID)) has_single = true; } @@ -2549,17 +2763,41 @@ void AnimBlendCtrl_ParametricSwitcher::createNode(AnimationGraph &graph, const D } } if (dd_stricmp(blk.getBlockName(), "paramSwitchS") == 0) - node->continuousAnimMode = false; + continuousAnimMode = false; - if (has_single && node->continuousAnimMode) + if (has_single && continuousAnimMode) { logerr("paramSwitch %s has single anims, but tuned for continuous mode", name); - for (int i = 0; i < node->list.size(); i++) - logerr(" node[%d]=%s, %s", i, graph.getBlendNodeName(node->list[i].node), - node->list[i].node->isSubOf(AnimBlendNodeSingleLeafCID) ? "single" : "continuous"); + for (int i = 0; i < list.size(); i++) + logerr(" node[%d]=%s, %s", i, graph.getBlendNodeName(list[i].node), + list[i].node->isSubOf(AnimBlendNodeSingleLeafCID) ? "single" : "continuous"); } +} - graph.registerBlendNode(node, name, nm_suffix); +void AnimBlendCtrl_ParametricSwitcher::checkHasLoop(AnimationGraph &graph, eastl::bitvector<> &visited_nodes) +{ + int id = getAnimNodeId(); + if (id == -1) + return; + + visited_nodes[id] = true; + for (const ItemAnim &child : list) + { + int childId = child.node->getAnimNodeId(); + if (childId == -1) + continue; + + if (visited_nodes[childId]) + { + ANIM_ERR("Find loop in controller childs, controller: %s, parent: %s", graph.getAnimNodeName(childId), + graph.getAnimNodeName(id)); + list.clear(); + break; + } + else + child.node->checkHasLoop(graph, visited_nodes); + } + visited_nodes[id] = false; } void AnimBlendCtrl_Hub::createNode(AnimationGraph &graph, const DataBlock &blk, const char *nm_suffix) @@ -2571,20 +2809,25 @@ void AnimBlendCtrl_Hub::createNode(AnimationGraph &graph, const DataBlock &blk, return; } - String var_name = String("var") + name; - AnimBlendCtrl_Hub *node = new AnimBlendCtrl_Hub; - int child_nid = blk.getNameId("child"), i; - if (child_nid != -1) - for (i = 0; i < blk.blockCount(); i++) - if (blk.getBlock(i)->getBlockNameId() == child_nid) + graph.registerBlendNode(node, name, nm_suffix); +} + +void AnimBlendCtrl_Hub::initChilds(AnimationGraph &graph, const DataBlock &blk, const char *nm_suffix) +{ + const char *name = blk.getStr("name"); + String varName = String("var") + name; + int childNid = blk.getNameId("child"); + if (childNid != -1) + for (int i = 0; i < blk.blockCount(); i++) + if (blk.getBlock(i)->getBlockNameId() == childNid) { const DataBlock *cblk = blk.getBlock(i); const char *nm = cblk->getStr("name", NULL); if (!nm) { - delete node; - ANIM_ERR(" is not defined in hub child"); + graph.unregisterBlendNode(this); + ANIM_ERR("field is not defined in <%s> hub child", name); return; } @@ -2600,7 +2843,7 @@ void AnimBlendCtrl_Hub::createNode(AnimationGraph &graph, const DataBlock &blk, const bool isOptional = cblk->getBool("optional", false); if (!isOptional) { - delete node; + graph.unregisterBlendNode(this); if (!is_ignoring_unavailable_resources()) ANIM_ERR("blend node <%s> (suffix=%s) not found!", nm, nm_suffix); return; @@ -2608,21 +2851,44 @@ void AnimBlendCtrl_Hub::createNode(AnimationGraph &graph, const DataBlock &blk, else continue; } - node->addBlendNode(n, cblk->getBool("enabled", true), cblk->getReal("weight", 1.0f)); + addBlendNode(n, cblk->getBool("enabled", true), cblk->getReal("weight", 1.0f)); } if (!blk.getBool("const", false)) - node->finalizeInit(graph, var_name); - graph.registerBlendNode(node, name, nm_suffix); + finalizeInit(graph, varName); } + +void AnimBlendCtrl_Hub::checkHasLoop(AnimationGraph &graph, eastl::bitvector<> &visited_nodes) +{ + int id = getAnimNodeId(); + if (id == -1) + return; + + visited_nodes[id] = true; + for (const Ptr child : nodes) + { + int childId = child->getAnimNodeId(); + if (childId == -1) + continue; + + if (visited_nodes[childId]) + { + ANIM_ERR("Find loop in controller childs, controller: %s, parent: %s", graph.getAnimNodeName(childId), + graph.getAnimNodeName(id)); + nodes.clear(); + break; + } + else + child->checkHasLoop(graph, visited_nodes); + } + visited_nodes[id] = false; +} + void AnimBlendCtrl_Blender::createNode(AnimationGraph &graph, const DataBlock &blk) { const char *name = blk.getStr("name", NULL); const char *_vname = blk.getStr("varname", NULL); String var_name; - const char *anim; - IAnimBlendNode *n; - if (!name) { ANIM_ERR("not found 'name' param"); @@ -2635,6 +2901,17 @@ void AnimBlendCtrl_Blender::createNode(AnimationGraph &graph, const DataBlock &b var_name = String("var") + name; AnimBlendCtrl_Blender *node = new AnimBlendCtrl_Blender(graph, var_name); + node->setDuration(blk.getReal("duration", 1.0f)); + node->setBlendTime(blk.getReal("morph", 1.0f)); + + graph.registerBlendNode(node, name); +} + +void AnimBlendCtrl_Blender::initChilds(AnimationGraph &graph, const DataBlock &blk, const char * /*nm_suffix*/) +{ + const char *anim; + IAnimBlendNode *n; + anim = blk.getStr("node1", NULL); if (anim) { @@ -2642,10 +2919,10 @@ void AnimBlendCtrl_Blender::createNode(AnimationGraph &graph, const DataBlock &b if (!n) { ANIM_ERR("blend node <%s> not found!", anim); - delete node; + graph.unregisterBlendNode(this); return; } - node->setBlendNode(0, n); + setBlendNode(0, n); } anim = blk.getStr("node2", NULL); if (anim) @@ -2654,24 +2931,46 @@ void AnimBlendCtrl_Blender::createNode(AnimationGraph &graph, const DataBlock &b if (!n) { ANIM_ERR("blend node <%s> not found!", anim); - delete node; + graph.unregisterBlendNode(this); return; } - node->setBlendNode(1, n); + setBlendNode(1, n); } - node->setDuration(blk.getReal("duration", 1.0f)); - node->setBlendTime(blk.getReal("morph", 1.0f)); +} - graph.registerBlendNode(node, name); +void AnimBlendCtrl_Blender::checkHasLoop(AnimationGraph &graph, eastl::bitvector<> &visited_nodes) +{ + int id = getAnimNodeId(); + if (id == -1) + return; + + visited_nodes[id] = true; + for (const Ptr child : node) + { + int childId = child->getAnimNodeId(); + if (childId == -1) + continue; + + if (visited_nodes[childId]) + { + ANIM_ERR("Find loop in controller childs, controller: %s, parent: %s", graph.getAnimNodeName(childId), + graph.getAnimNodeName(id)); + node[0] = nullptr; + node[1] = nullptr; + break; + } + else + child->checkHasLoop(graph, visited_nodes); + } + visited_nodes[id] = false; } + void AnimBlendCtrl_BinaryIndirectSwitch::createNode(AnimationGraph &graph, const DataBlock &blk) { const char *name = blk.getStr("name", NULL); const char *_vname = blk.getStr("varname", NULL); String var_name; - const char *anim; - IAnimBlendNode *n1, *n2, *ctrl; if (!name) { @@ -2687,10 +2986,18 @@ void AnimBlendCtrl_BinaryIndirectSwitch::createNode(AnimationGraph &graph, const AnimBlendCtrl_BinaryIndirectSwitch *node = new AnimBlendCtrl_BinaryIndirectSwitch(graph, var_name, blk.getInt("maskAnd", 0), blk.getInt("maskEq", 0)); + graph.registerBlendNode(node, name); +} + +void AnimBlendCtrl_BinaryIndirectSwitch::initChilds(AnimationGraph &graph, const DataBlock &blk, const char * /*nm_suffix*/) +{ + const char *anim; + IAnimBlendNode *n1, *n2, *ctrl; + anim = blk.getStr("node1", NULL); if (!anim) { - delete node; + graph.unregisterBlendNode(this); ANIM_ERR("node1 not defined!"); return; } @@ -2698,7 +3005,7 @@ void AnimBlendCtrl_BinaryIndirectSwitch::createNode(AnimationGraph &graph, const n1 = graph.getBlendNodePtr(anim); if (!n1) { - delete node; + graph.unregisterBlendNode(this); ANIM_ERR("blend node <%s> not found!", anim); return; } @@ -2706,14 +3013,14 @@ void AnimBlendCtrl_BinaryIndirectSwitch::createNode(AnimationGraph &graph, const anim = blk.getStr("node2", NULL); if (!anim) { - delete node; + graph.unregisterBlendNode(this); ANIM_ERR("node1 not defined!"); return; } n2 = graph.getBlendNodePtr(anim); if (!n2) { - delete node; + graph.unregisterBlendNode(this); ANIM_ERR("blend node <%s> not found!", anim); return; } @@ -2721,28 +3028,53 @@ void AnimBlendCtrl_BinaryIndirectSwitch::createNode(AnimationGraph &graph, const anim = blk.getStr("fifo", NULL); if (!anim) { - delete node; + graph.unregisterBlendNode(this); ANIM_ERR("node1 not defined!"); return; } ctrl = graph.getBlendNodePtr(anim); if (!ctrl) { - delete node; + graph.unregisterBlendNode(this); ANIM_ERR("blend node <%s> (fifo) not found!", anim); return; } if (!ctrl->isSubOf(AnimBlendCtrl_Fifo3CID)) { - delete node; + graph.unregisterBlendNode(this); ANIM_ERR("blend node <%s> is not fifo3!", anim); return; } - node->setBlendNodes(n1, blk.getReal("morph1", 0.0f), n2, blk.getReal("morph2", 0.0f)); - node->setFifoCtrl((AnimBlendCtrl_Fifo3 *)ctrl); + setBlendNodes(n1, blk.getReal("morph1", 0.0f), n2, blk.getReal("morph2", 0.0f)); + setFifoCtrl((AnimBlendCtrl_Fifo3 *)ctrl); +} - graph.registerBlendNode(node, name); +void AnimBlendCtrl_BinaryIndirectSwitch::checkHasLoop(AnimationGraph &graph, eastl::bitvector<> &visited_nodes) +{ + int id = getAnimNodeId(); + if (id == -1) + return; + + visited_nodes[id] = true; + for (const Ptr child : node) + { + int childId = child->getAnimNodeId(); + if (childId == -1) + continue; + + if (visited_nodes[childId]) + { + ANIM_ERR("Find loop in controller childs, controller: %s, parent: %s", graph.getAnimNodeName(childId), + graph.getAnimNodeName(id)); + node[0] = nullptr; + node[1] = nullptr; + break; + } + else + child->checkHasLoop(graph, visited_nodes); + } + visited_nodes[id] = false; } void AnimBlendCtrl_SetMotionMatchingTag::createNode(AnimationGraph &graph, const DataBlock &blk, const char *nm_suffix) diff --git a/prog/engine/anim/animIKCtrl.cpp b/prog/engine/anim/animIKCtrl.cpp index 25cd7d70c..766907f2e 100644 --- a/prog/engine/anim/animIKCtrl.cpp +++ b/prog/engine/anim/animIKCtrl.cpp @@ -91,7 +91,7 @@ void AnimV20::LegsIKCtrl::process(IPureAnimStateHolder &st, real wt, GeomNodeTre mat44f animcharTmCorrected = animcharTm; animcharTmCorrected.col0 = animcharTm.col2; animcharTmCorrected.col2 = animcharTm.col0; - vec3f dir = animcharTm.col2; + vec3f dir = v_norm3(animcharTm.col2); Point3_vec4 kneeOffset = crawlKneeOffsetVec; kneeOffset[2] *= i == 0 ? -1 : 1; vec3f pt = v_add(v_mat44_mul_vec3p(tree.getRootWtmRel(), v_and(knee_p, v_cast_vec4f(V_CI_MASK1110))), wofs); diff --git a/prog/engine/drv/drv3d_DX11/rtarget.cpp b/prog/engine/drv/drv3d_DX11/rtarget.cpp index 125d39812..fc562b2a8 100644 --- a/prog/engine/drv/drv3d_DX11/rtarget.cpp +++ b/prog/engine/drv/drv3d_DX11/rtarget.cpp @@ -612,9 +612,13 @@ bool d3d::clearview(int write_mask, E3DCOLOR c, float z_value, uint32_t stencil_ { CHECK_MAIN_THREAD(); - flush_all(false); - RenderState &rs = g_render_state; + // Disable flushing of render state to avoid unnecessary validation of render state. + // Anyway we don't render here and can flush this part later. + bool rasterizerModified = rs.rasterizerModified; + bool depthStencilModified = rs.depthStencilModified; + rs.rasterizerModified = rs.depthStencilModified = false; + flush_all(false); int targetW = 1, targetH = 1; @@ -671,6 +675,9 @@ bool d3d::clearview(int write_mask, E3DCOLOR c, float z_value, uint32_t stencil_ savedRs.restore(); } + rs.rasterizerModified = rasterizerModified; + rs.depthStencilModified = depthStencilModified; + return true; } diff --git a/prog/engine/drv/drv3d_DX11/states.cpp b/prog/engine/drv/drv3d_DX11/states.cpp index 1e9efccd3..e5e352948 100644 --- a/prog/engine/drv/drv3d_DX11/states.cpp +++ b/prog/engine/drv/drv3d_DX11/states.cpp @@ -163,7 +163,7 @@ void flush_states(RenderState &rs) #if DAGOR_DBGLEVEL > 0 if (currentState->sourceShaderRenderState.forcedSampleCount > 0 && rs.nextRtState.isDepthUsed()) { - DAG_FATAL("Forced sample count is used when depth RT is set! FSC will be disabled"); + D3D_ERROR("Forced sample count is used when depth RT is set! FSC will be disabled"); shaders::RenderState fixedState = currentState->sourceShaderRenderState; fixedState.forcedSampleCount = 0; s = render_states.get(render_states.emplaceOne(shader_render_state_to_driver_render_state(fixedState)))->rasterState; diff --git a/prog/engine/drv/drv3d_DX12/amdFsrD3D12_windows.cpp b/prog/engine/drv/drv3d_DX12/amdFsrD3D12_windows.cpp index 8ff04da79..f53343d99 100644 --- a/prog/engine/drv/drv3d_DX12/amdFsrD3D12_windows.cpp +++ b/prog/engine/drv/drv3d_DX12/amdFsrD3D12_windows.cpp @@ -155,10 +155,23 @@ class FSRD3D12Win : public FSR String getVersionString() const override { return upscalingVersionString; } - void recover() { initUpscaling(contextArgs); } + void preRecover() + { + auto tmpContextArgs = contextArgs; + teardownUpscaling(); + contextArgs = tmpContextArgs; + } + + void recover() + { + // The regular tear down resets the mode to off, but the preRecover keeps the mode + // and the mode isn't off here have to restore the fsr context and reinitialize the object + if (amd::fSRD3D12Win->getUpscalingMode() != amd::FSR::UpscalingMode::Off) + initUpscaling(contextArgs); + } private: - eastl::unique_ptr fsrModule; + DagorDynLibHolder fsrModule; PfnFfxCreateContext createContext = nullptr; PfnFfxDestroyContext destroyContext = nullptr; @@ -182,7 +195,7 @@ FSR *createD3D12Win() { return new FSRD3D12Win; } static void fsr3_before_reset(bool full_reset) { if (full_reset && amd::fSRD3D12Win) - amd::fSRD3D12Win->teardownUpscaling(); + amd::fSRD3D12Win->preRecover(); } static void fsr3_after_reset(bool full_reset) diff --git a/prog/engine/drv/drv3d_DX12/debug/break_point.h b/prog/engine/drv/drv3d_DX12/debug/break_point.h index 097996d9f..f50ea4196 100644 --- a/prog/engine/drv/drv3d_DX12/debug/break_point.h +++ b/prog/engine/drv/drv3d_DX12/debug/break_point.h @@ -35,9 +35,15 @@ class Controller : public call_stack::ExecutionContextDataStore, public call_sta return false; } +#if !DX12_NULL_CALL_STACK_CAPTURE + bool isBreakPoint(const call_stack::null::CommandData &) { return false; } +#endif + public: void breakNow() { __debugbreak(); } - void setCommandData(const call_stack::CommandData &call_stack_info, const char *name) + + template + void setCommandData(const CommandType &call_stack_info, const char *name) { BaseType::setCommandData(call_stack_info, name); if (isBreakPoint(call_stack_info)) diff --git a/prog/engine/drv/drv3d_DX12/debug/call_stack.h b/prog/engine/drv/drv3d_DX12/debug/call_stack.h index 34cec9b1d..10126fa8d 100644 --- a/prog/engine/drv/drv3d_DX12/debug/call_stack.h +++ b/prog/engine/drv/drv3d_DX12/debug/call_stack.h @@ -18,5 +18,6 @@ using namespace full_stack; using namespace return_address; #else using namespace null; +#define DX12_NULL_CALL_STACK_CAPTURE 1 #endif } // namespace drv3d_dx12::debug::call_stack \ No newline at end of file diff --git a/prog/engine/drv/drv3d_DX12/debug/call_stack_full_stack.h b/prog/engine/drv/drv3d_DX12/debug/call_stack_full_stack.h index 984045048..769c144e7 100644 --- a/prog/engine/drv/drv3d_DX12/debug/call_stack_full_stack.h +++ b/prog/engine/drv/drv3d_DX12/debug/call_stack_full_stack.h @@ -49,6 +49,7 @@ class ExecutionContextDataStore data = update; lastCommandName = name; } + void setCommandData(const null::CommandData &, const char *) {} const char *getLastCommandName() const { return lastCommandName; } }; @@ -110,6 +111,8 @@ class Reporter buffer.append(str.data(), str.length()); } + void append(String &, const char *, const null::CommandData &) {} + eastl::string_view resolve(const CommandData &data) { return doResolve(data); } }; } // namespace drv3d_dx12::debug::call_stack::full_stack diff --git a/prog/engine/drv/drv3d_DX12/debug/call_stack_return_address.h b/prog/engine/drv/drv3d_DX12/debug/call_stack_return_address.h index 91ba74bb0..9b4125119 100644 --- a/prog/engine/drv/drv3d_DX12/debug/call_stack_return_address.h +++ b/prog/engine/drv/drv3d_DX12/debug/call_stack_return_address.h @@ -40,6 +40,7 @@ class ExecutionContextDataStore "STORE_RETURN_ADDRESS() call is missing on the d3d interface.", name); } + void setCommandData(const null::CommandData &, const char *) {} const char *getLastCommandName() const { return lastCommandName; } }; @@ -89,6 +90,8 @@ class Reporter buffer.append(str.data(), str.length()); } + void append(String &, const char *, const null::CommandData &) {} + eastl::string_view resolve(const CommandData &data) { return doResolve(data); } }; } // namespace drv3d_dx12::debug::call_stack::return_address diff --git a/prog/engine/drv/drv3d_DX12/debug/call_stack_selectable.h b/prog/engine/drv/drv3d_DX12/debug/call_stack_selectable.h index 4b021eddc..2ab054ab4 100644 --- a/prog/engine/drv/drv3d_DX12/debug/call_stack_selectable.h +++ b/prog/engine/drv/drv3d_DX12/debug/call_stack_selectable.h @@ -60,6 +60,7 @@ class ExecutionContextDataStore data = update; lastCommandName = name; } + void setCommandData(const null::CommandData &, const char *) {} const char *getLastCommandName() const { return lastCommandName; } }; @@ -162,6 +163,8 @@ class Reporter : protected null::Reporter, protected return_address::Reporter, p } } + void append(String &, const char *, const null::CommandData &) {} + eastl::string_view resolve(const CommandData &data) { switch (data.activeMember) diff --git a/prog/engine/drv/drv3d_DX12/debug/frame_command_logger.cpp b/prog/engine/drv/drv3d_DX12/debug/frame_command_logger.cpp index 77873ba08..7e5f5a78c 100644 --- a/prog/engine/drv/drv3d_DX12/debug/frame_command_logger.cpp +++ b/prog/engine/drv/drv3d_DX12/debug/frame_command_logger.cpp @@ -579,13 +579,13 @@ void append_arg(String &target, T const &, const char *type) result = "Cmd" #Name; \ result.aprintf(128, " (%s)", cmd.is_primary() ? "primary" : "secondary"); -#define DX12_BEGIN_CONTEXT_COMMAND(Name) \ +#define DX12_BEGIN_CONTEXT_COMMAND(IsPrimary, Name) \ const char *cmdToStr(String &result, debug::call_stack::Reporter &call_stack_reporter, const Cmd##Name &cmd) \ { \ G_UNUSED(cmd); \ DX12_STORE_CONTEXT_COMMAND_NAME_AND_PRIMACY(Name) -#define DX12_BEGIN_CONTEXT_COMMAND_EXT_1(Name, Param0Type, Param0Name) \ +#define DX12_BEGIN_CONTEXT_COMMAND_EXT_1(IsPrimary, Name, Param0Type, Param0Name) \ const char *cmdToStr(String &result, debug::call_stack::Reporter &call_stack_reporter, \ const ExtendedVariant ¶m) \ { \ @@ -593,16 +593,14 @@ void append_arg(String &target, T const &, const char *type) G_UNUSED(cmd); \ DX12_STORE_CONTEXT_COMMAND_NAME_AND_PRIMACY(Name) -#define DX12_BEGIN_CONTEXT_COMMAND_EXT_2(Name, Param0Type, Param0Name, Param1Type, Param1Name) \ - const char *cmdToStr(String &result, debug::call_stack::Reporter &call_stack_reporter, \ - const ExtendedVariant2 ¶m) \ - { \ - auto &cmd = param.cmd; \ - G_UNUSED(cmd); \ +#define DX12_BEGIN_CONTEXT_COMMAND_EXT_2(IsPrimary, Name, Param0Type, Param0Name, Param1Type, Param1Name) \ + const char *cmdToStr(String &result, debug::call_stack::Reporter &call_stack_reporter, \ + const ExtendedVariant2 ¶m) \ + { \ + auto &cmd = param.cmd; \ + G_UNUSED(cmd); \ DX12_STORE_CONTEXT_COMMAND_NAME_AND_PRIMACY(Name) -#define DX12_CONTEXT_COMMAND_IS_PRIMARY(isPrimary) - #define DX12_CONTEXT_COMMAND_PARAM(type, name) \ { \ result += "\n> " #name "="; \ @@ -629,7 +627,6 @@ void append_arg(String &target, T const &, const char *type) #undef DX12_BEGIN_CONTEXT_COMMAND #undef DX12_BEGIN_CONTEXT_COMMAND_EXT_1 #undef DX12_BEGIN_CONTEXT_COMMAND_EXT_2 -#undef DX12_CONTEXT_COMMAND_IS_PRIMARY #undef DX12_END_CONTEXT_COMMAND #undef DX12_CONTEXT_COMMAND_PARAM #undef DX12_CONTEXT_COMMAND_PARAM_ARRAY diff --git a/prog/engine/drv/drv3d_DX12/device_context.cpp b/prog/engine/drv/drv3d_DX12/device_context.cpp index b3277bc4f..e905a2e75 100644 --- a/prog/engine/drv/drv3d_DX12/device_context.cpp +++ b/prog/engine/drv/drv3d_DX12/device_context.cpp @@ -50,7 +50,7 @@ U &resolve(T &, U &u) #define DX12_CONTEXT_COMMAND_IMPLEMENTATION 1 // mark cmd and ctx as unused to avoid errors when the implementation does not use anything // RenderWork is private to DeviceContext, use template to work around that -#define DX12_BEGIN_CONTEXT_COMMAND(Name) \ +#define DX12_BEGIN_CONTEXT_COMMAND(IsPrimary, Name) \ template \ void execute(const Cmd##Name &cmd, D &debug, T &ctx) \ { \ @@ -58,7 +58,7 @@ U &resolve(T &, U &u) G_UNUSED(ctx); \ debug.setCommandData(cmd, "Cmd" #Name); -#define DX12_BEGIN_CONTEXT_COMMAND_EXT_1(Name, Param0Type, Param0Name) \ +#define DX12_BEGIN_CONTEXT_COMMAND_EXT_1(IsPrimary, Name, Param0Type, Param0Name) \ template \ void execute(const ExtendedVariant ¶m, D &debug, T &ctx) \ { \ @@ -69,20 +69,18 @@ U &resolve(T &, U &u) G_UNUSED(ctx); \ debug.setCommandData(cmd, "Cmd" #Name); -#define DX12_BEGIN_CONTEXT_COMMAND_EXT_2(Name, Param0Type, Param0Name, Param1Type, Param1Name) \ - template \ - void execute(const ExtendedVariant2 ¶m, D &debug, T &ctx) \ - { \ - auto &cmd = param.cmd; \ - auto &Param0Name = param.p0; \ - auto &Param1Name = param.p1; \ - G_UNUSED(Param0Name); \ - G_UNUSED(cmd); \ - G_UNUSED(ctx); \ +#define DX12_BEGIN_CONTEXT_COMMAND_EXT_2(IsPrimary, Name, Param0Type, Param0Name, Param1Type, Param1Name) \ + template \ + void execute(const ExtendedVariant2 ¶m, D &debug, T &ctx) \ + { \ + auto &cmd = param.cmd; \ + auto &Param0Name = param.p0; \ + auto &Param1Name = param.p1; \ + G_UNUSED(Param0Name); \ + G_UNUSED(cmd); \ + G_UNUSED(ctx); \ debug.setCommandData(cmd, "Cmd" #Name); -#define DX12_CONTEXT_COMMAND_IS_PRIMARY(isPrimary) - #define DX12_END_CONTEXT_COMMAND } // make an alias so we do not need to write cmd. #define DX12_CONTEXT_COMMAND_PARAM(type, name) \ @@ -95,7 +93,6 @@ U &resolve(T &, U &u) #undef DX12_BEGIN_CONTEXT_COMMAND #undef DX12_BEGIN_CONTEXT_COMMAND_EXT_1 #undef DX12_BEGIN_CONTEXT_COMMAND_EXT_2 -#undef DX12_CONTEXT_COMMAND_IS_PRIMARY #undef DX12_END_CONTEXT_COMMAND #undef DX12_CONTEXT_COMMAND_PARAM #undef DX12_CONTEXT_COMMAND_PARAM_ARRAY @@ -615,7 +612,7 @@ void DeviceContext::addDebugBreakString(eastl::string_view str) { auto cmd = make_command(); DX12_LOCK_FRONT(); - commandStream.pushBack(cmd, str.data(), str.size()); + commandStream.pushBack(cmd, str.data(), str.size()); immediateModeExecute(); } @@ -623,7 +620,7 @@ void DeviceContext::removeDebugBreakString(eastl::string_view str) { auto cmd = make_command(); DX12_LOCK_FRONT(); - commandStream.pushBack(cmd, str.data(), str.size()); + commandStream.pushBack(cmd, str.data(), str.size()); immediateModeExecute(); } @@ -1221,10 +1218,9 @@ void report_metrics(VariantContainerVisitMetricsCollector &metrics) if (totalCount.value()) { static const char *cmdNames[metrics.command_count]{ -#define DX12_BEGIN_CONTEXT_COMMAND(name) "Cmd" #name, -#define DX12_BEGIN_CONTEXT_COMMAND_EXT_1(name, param0Type, param0Name) "Cmd" #name, -#define DX12_BEGIN_CONTEXT_COMMAND_EXT_2(name, param0Type, param0Name, param1Type, param1Name) "Cmd" #name, -#define DX12_CONTEXT_COMMAND_IS_PRIMARY(isPrimary) +#define DX12_BEGIN_CONTEXT_COMMAND(isPrimary, name) "Cmd" #name, +#define DX12_BEGIN_CONTEXT_COMMAND_EXT_1(isPrimary, name, param0Type, param0Name) "Cmd" #name, +#define DX12_BEGIN_CONTEXT_COMMAND_EXT_2(isPrimary, name, param0Type, param0Name, param1Type, param1Name) "Cmd" #name, #define DX12_END_CONTEXT_COMMAND #define DX12_CONTEXT_COMMAND_PARAM(type, name) #define DX12_CONTEXT_COMMAND_PARAM_ARRAY(type, name, size) @@ -1232,7 +1228,6 @@ void report_metrics(VariantContainerVisitMetricsCollector &metrics) #undef DX12_BEGIN_CONTEXT_COMMAND #undef DX12_BEGIN_CONTEXT_COMMAND_EXT_1 #undef DX12_BEGIN_CONTEXT_COMMAND_EXT_2 -#undef DX12_CONTEXT_COMMAND_IS_PRIMARY #undef DX12_END_CONTEXT_COMMAND #undef DX12_CONTEXT_COMMAND_PARAM #undef DX12_CONTEXT_COMMAND_PARAM_ARRAY @@ -1370,7 +1365,7 @@ void DeviceContext::setConstBuffer(uint32_t stage, size_t unit, const ConstBuffe #if DX12_VALIDATE_STREAM_CB_USAGE_WITHOUT_INITIALIZATION nameLength = strlen(name); #endif - commandStream.pushBack(cmd, name, nameLength); + commandStream.pushBack(cmd, name, nameLength); immediateModeExecute(); } @@ -1630,7 +1625,7 @@ void DeviceContext::pushEvent(const char *name) auto cmd = make_command(); DX12_LOCK_FRONT(); - commandStream.pushBack(cmd, name, length); + commandStream.pushBack(cmd, name, length); immediateModeExecute(); } @@ -3234,12 +3229,12 @@ void DeviceContext::mapTileToResource(BaseTex *tex, ResourceHeap *heap, const Ti auto extraBatch = mapping_count % batchSize; for (size_t i = 0; i < fullBatches; ++i, mapping += batchSize) { - commandStream.pushBack(cmd, mapping, batchSize); + commandStream.pushBack(cmd, mapping, batchSize); immediateModeExecute(); } if (extraBatch) { - commandStream.pushBack(cmd, mapping, extraBatch); + commandStream.pushBack(cmd, mapping, extraBatch); immediateModeExecute(); } diff --git a/prog/engine/drv/drv3d_DX12/device_context.h b/prog/engine/drv/drv3d_DX12/device_context.h index 4088862d1..617bdd147 100644 --- a/prog/engine/drv/drv3d_DX12/device_context.h +++ b/prog/engine/drv/drv3d_DX12/device_context.h @@ -130,7 +130,15 @@ class DeviceContext : protected ResourceUsageHistoryDataSetDebugger, template T make_command(Args &&...args) { - return T{this->generateCommandData(), eastl::forward(args)...}; + const bool isPrimary = T::is_primary(); + if constexpr (isPrimary) + { + return T{this->generateCommandData(), eastl::forward(args)...}; + } + else + { + return T{{}, eastl::forward(args)...}; + } } // Warning: intentionally not spinlock, since it has extremely bad behaviour diff --git a/prog/engine/drv/drv3d_DX12/device_context_cmd.h b/prog/engine/drv/drv3d_DX12/device_context_cmd.h index 4ef2fc26a..bc4f04831 100644 --- a/prog/engine/drv/drv3d_DX12/device_context_cmd.h +++ b/prog/engine/drv/drv3d_DX12/device_context_cmd.h @@ -27,24 +27,30 @@ namespace drv3d_dx12 { -#define DX12_BEGIN_CONTEXT_COMMAND(name) \ - struct Cmd##name : debug::call_stack::CommandData \ - { +#define DX12_CONTEXT_COMMAND_COMMAND_DATA(isPrimary) \ + eastl::conditional_t -#define DX12_BEGIN_CONTEXT_COMMAND_EXT_1(name, param0Type, param0Name) \ - struct Cmd##name : debug::call_stack::CommandData \ - { - -#define DX12_BEGIN_CONTEXT_COMMAND_EXT_2(name, param0Type, param0Name, param1Type, param1Name) \ - struct Cmd##name : debug::call_stack::CommandData \ - { - -#define DX12_CONTEXT_COMMAND_IS_PRIMARY(IsPrimary) \ +#define DX12_CONTEXT_COMMAND_IS_PRIMARY(isPrimary) \ static constexpr bool is_primary() \ { \ - return IsPrimary; \ + return isPrimary; \ } +#define DX12_BEGIN_CONTEXT_COMMAND(isPrimary, name) \ + struct Cmd##name : DX12_CONTEXT_COMMAND_COMMAND_DATA(isPrimary) \ + { \ + DX12_CONTEXT_COMMAND_IS_PRIMARY(isPrimary) + +#define DX12_BEGIN_CONTEXT_COMMAND_EXT_1(isPrimary, name, param0Type, param0Name) \ + struct Cmd##name : DX12_CONTEXT_COMMAND_COMMAND_DATA(isPrimary) \ + { \ + DX12_CONTEXT_COMMAND_IS_PRIMARY(isPrimary) + +#define DX12_BEGIN_CONTEXT_COMMAND_EXT_2(isPrimary, name, param0Type, param0Name, param1Type, param1Name) \ + struct Cmd##name : DX12_CONTEXT_COMMAND_COMMAND_DATA(isPrimary) \ + { \ + DX12_CONTEXT_COMMAND_IS_PRIMARY(isPrimary) + #define DX12_END_CONTEXT_COMMAND \ } \ ; @@ -55,21 +61,20 @@ namespace drv3d_dx12 #undef DX12_BEGIN_CONTEXT_COMMAND #undef DX12_BEGIN_CONTEXT_COMMAND_EXT_1 #undef DX12_BEGIN_CONTEXT_COMMAND_EXT_2 -#undef DX12_CONTEXT_COMMAND_IS_PRIMARY #undef DX12_END_CONTEXT_COMMAND #undef DX12_CONTEXT_COMMAND_PARAM #undef DX12_CONTEXT_COMMAND_PARAM_ARRAY +#undef DX12_CONTEXT_COMMAND_IS_PRIMARY #if _TARGET_XBOX #include "device_context_xbox.h" #endif using AnyCommandPack = TypePack< -#define DX12_BEGIN_CONTEXT_COMMAND(name) Cmd##name, -#define DX12_BEGIN_CONTEXT_COMMAND_EXT_1(name, param0Type, param0Name) ExtendedVariant, -#define DX12_BEGIN_CONTEXT_COMMAND_EXT_2(name, param0Type, param0Name, param1Type, param1Name) \ +#define DX12_BEGIN_CONTEXT_COMMAND(isPrimary, name) Cmd##name, +#define DX12_BEGIN_CONTEXT_COMMAND_EXT_1(isPrimary, name, param0Type, param0Name) ExtendedVariant, +#define DX12_BEGIN_CONTEXT_COMMAND_EXT_2(isPrimary, name, param0Type, param0Name, param1Type, param1Name) \ ExtendedVariant2, -#define DX12_CONTEXT_COMMAND_IS_PRIMARY(isPrimary) #define DX12_END_CONTEXT_COMMAND #define DX12_CONTEXT_COMMAND_PARAM(type, name) #define DX12_CONTEXT_COMMAND_PARAM_ARRAY(type, name, size) @@ -77,7 +82,6 @@ using AnyCommandPack = TypePack< #undef DX12_BEGIN_CONTEXT_COMMAND #undef DX12_BEGIN_CONTEXT_COMMAND_EXT_1 #undef DX12_BEGIN_CONTEXT_COMMAND_EXT_2 -#undef DX12_CONTEXT_COMMAND_IS_PRIMARY #undef DX12_END_CONTEXT_COMMAND #undef DX12_CONTEXT_COMMAND_PARAM #undef DX12_CONTEXT_COMMAND_PARAM_ARRAY diff --git a/prog/engine/drv/drv3d_DX12/device_context_cmd.inc.h b/prog/engine/drv/drv3d_DX12/device_context_cmd.inc.h index 5a8e5bfcf..7c0bf488e 100644 --- a/prog/engine/drv/drv3d_DX12/device_context_cmd.inc.h +++ b/prog/engine/drv/drv3d_DX12/device_context_cmd.inc.h @@ -2,8 +2,7 @@ /* Note: commands are sorted according to actual execution frequency (in order to help CPU's branch target predictor) */ -DX12_BEGIN_CONTEXT_COMMAND(DrawIndexed) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, DrawIndexed) DX12_CONTEXT_COMMAND_PARAM(D3D12_PRIMITIVE_TOPOLOGY, top) DX12_CONTEXT_COMMAND_PARAM(uint32_t, indexStart) DX12_CONTEXT_COMMAND_PARAM(uint32_t, count) @@ -22,8 +21,7 @@ DX12_BEGIN_CONTEXT_COMMAND(DrawIndexed) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(SetVertexRootConstant) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetVertexRootConstant) DX12_CONTEXT_COMMAND_PARAM(uint32_t, offset) DX12_CONTEXT_COMMAND_PARAM(uint32_t, value) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -31,8 +29,7 @@ DX12_BEGIN_CONTEXT_COMMAND(SetVertexRootConstant) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND_EXT_1(SetUniformBuffer, char, name) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND_EXT_1(false, SetUniformBuffer, char, name) DX12_CONTEXT_COMMAND_PARAM(uint32_t, stage) DX12_CONTEXT_COMMAND_PARAM(uint32_t, unit) DX12_CONTEXT_COMMAND_PARAM(ConstBufferSetupInformationStream, buffer) @@ -42,8 +39,7 @@ DX12_BEGIN_CONTEXT_COMMAND_EXT_1(SetUniformBuffer, char, name) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(SetSRVTexture) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetSRVTexture) DX12_CONTEXT_COMMAND_PARAM(uint32_t, stage) DX12_CONTEXT_COMMAND_PARAM(uint32_t, unit) DX12_CONTEXT_COMMAND_PARAM(Image *, image) @@ -56,8 +52,7 @@ DX12_BEGIN_CONTEXT_COMMAND(SetSRVTexture) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(SetSampler) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetSampler) DX12_CONTEXT_COMMAND_PARAM(uint32_t, stage) DX12_CONTEXT_COMMAND_PARAM(uint32_t, unit) DX12_CONTEXT_COMMAND_PARAM(D3D12_CPU_DESCRIPTOR_HANDLE, sampler) @@ -67,8 +62,7 @@ DX12_BEGIN_CONTEXT_COMMAND(SetSampler) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(SetSRVBuffer) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetSRVBuffer) DX12_CONTEXT_COMMAND_PARAM(uint32_t, stage) DX12_CONTEXT_COMMAND_PARAM(uint32_t, unit) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndShaderResourceView, buffer) @@ -78,8 +72,7 @@ DX12_BEGIN_CONTEXT_COMMAND(SetSRVBuffer) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(SetGraphicsProgram) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetGraphicsProgram) DX12_CONTEXT_COMMAND_PARAM(GraphicsProgramID, program) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -87,8 +80,7 @@ DX12_BEGIN_CONTEXT_COMMAND(SetGraphicsProgram) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(SetConstRegisterBuffer) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetConstRegisterBuffer) DX12_CONTEXT_COMMAND_PARAM(HostDeviceSharedMemoryRegion, update) DX12_CONTEXT_COMMAND_PARAM(uint32_t, stage) @@ -97,8 +89,7 @@ DX12_BEGIN_CONTEXT_COMMAND(SetConstRegisterBuffer) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(TextureBarrier) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, TextureBarrier) DX12_CONTEXT_COMMAND_PARAM(Image *, image) DX12_CONTEXT_COMMAND_PARAM(SubresourceRange, subResRange) DX12_CONTEXT_COMMAND_PARAM(uint32_t, texFlags) @@ -111,8 +102,7 @@ DX12_BEGIN_CONTEXT_COMMAND(TextureBarrier) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(SetPixelRootConstant) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetPixelRootConstant) DX12_CONTEXT_COMMAND_PARAM(uint32_t, offset) DX12_CONTEXT_COMMAND_PARAM(uint32_t, value) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -120,8 +110,7 @@ DX12_BEGIN_CONTEXT_COMMAND(SetPixelRootConstant) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(SetStaticRenderState) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetStaticRenderState) DX12_CONTEXT_COMMAND_PARAM(StaticRenderStateID, ident) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION ctx.setStaticRenderState(ident); @@ -129,8 +118,7 @@ DX12_BEGIN_CONTEXT_COMMAND(SetStaticRenderState) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(SetFramebuffer) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetFramebuffer) DX12_CONTEXT_COMMAND_PARAM_ARRAY(Image *, imageList, Driver3dRenderTarget::MAX_SIMRT + 1) DX12_CONTEXT_COMMAND_PARAM_ARRAY(ImageViewState, viewList, Driver3dRenderTarget::MAX_SIMRT + 1) DX12_CONTEXT_COMMAND_PARAM_ARRAY(D3D12_CPU_DESCRIPTOR_HANDLE, viewDescriptors, Driver3dRenderTarget::MAX_SIMRT + 1) @@ -179,8 +167,7 @@ DX12_BEGIN_CONTEXT_COMMAND(SetFramebuffer) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(BufferBarrier) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, BufferBarrier) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReference, buffer) DX12_CONTEXT_COMMAND_PARAM(ResourceBarrier, barrier) DX12_CONTEXT_COMMAND_PARAM(GpuPipeline, queue) @@ -191,8 +178,7 @@ DX12_BEGIN_CONTEXT_COMMAND(BufferBarrier) DX12_END_CONTEXT_COMMAND #if D3D_HAS_RAY_TRACING -DX12_BEGIN_CONTEXT_COMMAND(AsBarrier) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, AsBarrier) DX12_CONTEXT_COMMAND_PARAM(RaytraceAccelerationStructure *, as) DX12_CONTEXT_COMMAND_PARAM(GpuPipeline, queue) @@ -202,8 +188,7 @@ DX12_BEGIN_CONTEXT_COMMAND(AsBarrier) DX12_END_CONTEXT_COMMAND #endif -DX12_BEGIN_CONTEXT_COMMAND(SetVertexBuffer) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetVertexBuffer) DX12_CONTEXT_COMMAND_PARAM(uint32_t, stream) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndAddressRange, buffer) DX12_CONTEXT_COMMAND_PARAM(uint32_t, stride) @@ -213,8 +198,7 @@ DX12_BEGIN_CONTEXT_COMMAND(SetVertexBuffer) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(Draw) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, Draw) DX12_CONTEXT_COMMAND_PARAM(D3D12_PRIMITIVE_TOPOLOGY, top) DX12_CONTEXT_COMMAND_PARAM(uint32_t, start) DX12_CONTEXT_COMMAND_PARAM(uint32_t, count) @@ -231,8 +215,7 @@ DX12_BEGIN_CONTEXT_COMMAND(Draw) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(SetInputLayout) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetInputLayout) DX12_CONTEXT_COMMAND_PARAM(InputLayoutID, ident) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -241,8 +224,7 @@ DX12_BEGIN_CONTEXT_COMMAND(SetInputLayout) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(SetUAVBuffer) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetUAVBuffer) DX12_CONTEXT_COMMAND_PARAM(uint32_t, stage) DX12_CONTEXT_COMMAND_PARAM(uint32_t, unit) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndUnorderedResourceView, buffer) @@ -252,8 +234,7 @@ DX12_BEGIN_CONTEXT_COMMAND(SetUAVBuffer) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(SetUAVTexture) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetUAVTexture) DX12_CONTEXT_COMMAND_PARAM(uint32_t, stage) DX12_CONTEXT_COMMAND_PARAM(uint32_t, unit) DX12_CONTEXT_COMMAND_PARAM(Image *, image) @@ -265,8 +246,7 @@ DX12_BEGIN_CONTEXT_COMMAND(SetUAVTexture) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(SetComputeProgram) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetComputeProgram) DX12_CONTEXT_COMMAND_PARAM(ProgramID, program) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -274,16 +254,14 @@ DX12_BEGIN_CONTEXT_COMMAND(SetComputeProgram) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND_EXT_1(SetViewports, ViewportState, viewports) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND_EXT_1(false, SetViewports, ViewportState, viewports) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION ctx.updateViewports(viewports); #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(Dispatch) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, Dispatch) DX12_CONTEXT_COMMAND_PARAM(uint32_t, x) DX12_CONTEXT_COMMAND_PARAM(uint32_t, y) DX12_CONTEXT_COMMAND_PARAM(uint32_t, z) @@ -296,8 +274,7 @@ DX12_BEGIN_CONTEXT_COMMAND(Dispatch) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(SetIndexBuffer) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetIndexBuffer) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndAddressRange, buffer) DX12_CONTEXT_COMMAND_PARAM(DXGI_FORMAT, type) @@ -307,8 +284,7 @@ DX12_BEGIN_CONTEXT_COMMAND(SetIndexBuffer) DX12_END_CONTEXT_COMMAND #if D3D_HAS_RAY_TRACING -DX12_BEGIN_CONTEXT_COMMAND(RaytraceBuildTopAccelerationStructure) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, RaytraceBuildTopAccelerationStructure) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndAddress, scratchBuffer) DX12_CONTEXT_COMMAND_PARAM(RaytraceAccelerationStructure *, as) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndAddress, instanceBuffer) @@ -327,8 +303,7 @@ DX12_END_CONTEXT_COMMAND #endif #if D3D_HAS_RAY_TRACING -DX12_BEGIN_CONTEXT_COMMAND(RaytraceCopyAccelerationStructure) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, RaytraceCopyAccelerationStructure) DX12_CONTEXT_COMMAND_PARAM(RaytraceAccelerationStructure *, dst) DX12_CONTEXT_COMMAND_PARAM(RaytraceAccelerationStructure *, src) DX12_CONTEXT_COMMAND_PARAM(bool, compact) @@ -340,8 +315,7 @@ DX12_BEGIN_CONTEXT_COMMAND(RaytraceCopyAccelerationStructure) DX12_END_CONTEXT_COMMAND #endif -DX12_BEGIN_CONTEXT_COMMAND(MipMapGenSource) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, MipMapGenSource) DX12_CONTEXT_COMMAND_PARAM(Image *, image) DX12_CONTEXT_COMMAND_PARAM(MipMapIndex, mip) DX12_CONTEXT_COMMAND_PARAM(ArrayLayerIndex, array) @@ -351,8 +325,7 @@ DX12_BEGIN_CONTEXT_COMMAND(MipMapGenSource) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(BlitImage) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, BlitImage) DX12_CONTEXT_COMMAND_PARAM(Image *, src) DX12_CONTEXT_COMMAND_PARAM(Image *, dst) DX12_CONTEXT_COMMAND_PARAM(ImageViewState, srcView) @@ -369,8 +342,7 @@ DX12_BEGIN_CONTEXT_COMMAND(BlitImage) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(DispatchIndirect) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, DispatchIndirect) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndOffset, buffer) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -383,8 +355,7 @@ DX12_END_CONTEXT_COMMAND #if !_TARGET_XBOXONE // Assuming this will be used a lot in the future this may be moved up after profiling -DX12_BEGIN_CONTEXT_COMMAND(DispatchMesh) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, DispatchMesh) DX12_CONTEXT_COMMAND_PARAM(uint32_t, x) DX12_CONTEXT_COMMAND_PARAM(uint32_t, y) DX12_CONTEXT_COMMAND_PARAM(uint32_t, z) @@ -400,8 +371,7 @@ DX12_BEGIN_CONTEXT_COMMAND(DispatchMesh) DX12_END_CONTEXT_COMMAND // Assuming this will be used a lot in the future this may be moved up after profiling -DX12_BEGIN_CONTEXT_COMMAND(DispatchMeshIndirect) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, DispatchMeshIndirect) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndOffset, arguments) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndOffset, count) DX12_CONTEXT_COMMAND_PARAM(uint32_t, stride) @@ -417,8 +387,7 @@ DX12_BEGIN_CONTEXT_COMMAND(DispatchMeshIndirect) DX12_END_CONTEXT_COMMAND #endif -DX12_BEGIN_CONTEXT_COMMAND(ClearRenderTargets) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, ClearRenderTargets) DX12_CONTEXT_COMMAND_PARAM(ViewportState, viewport) DX12_CONTEXT_COMMAND_PARAM(uint32_t, clearMask) DX12_CONTEXT_COMMAND_PARAM(float, clearDepth) @@ -431,8 +400,7 @@ DX12_BEGIN_CONTEXT_COMMAND(ClearRenderTargets) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(SetSRVNull) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetSRVNull) DX12_CONTEXT_COMMAND_PARAM(uint32_t, stage) DX12_CONTEXT_COMMAND_PARAM(uint32_t, unit) @@ -441,8 +409,7 @@ DX12_BEGIN_CONTEXT_COMMAND(SetSRVNull) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(SetUAVNull) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetUAVNull) DX12_CONTEXT_COMMAND_PARAM(uint32_t, stage) DX12_CONTEXT_COMMAND_PARAM(uint32_t, unit) @@ -451,8 +418,7 @@ DX12_BEGIN_CONTEXT_COMMAND(SetUAVNull) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(ClearBufferInt) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, ClearBufferInt) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndClearView, buffer) DX12_CONTEXT_COMMAND_PARAM_ARRAY(uint32_t, values, 4) @@ -462,8 +428,7 @@ DX12_BEGIN_CONTEXT_COMMAND(ClearBufferInt) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(CopyImage) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, CopyImage) DX12_CONTEXT_COMMAND_PARAM(Image *, src) DX12_CONTEXT_COMMAND_PARAM(Image *, dst) DX12_CONTEXT_COMMAND_PARAM(ImageCopy, region) @@ -473,8 +438,7 @@ DX12_BEGIN_CONTEXT_COMMAND(CopyImage) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(ResolveMultiSampleImage) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, ResolveMultiSampleImage) DX12_CONTEXT_COMMAND_PARAM(Image *, src) DX12_CONTEXT_COMMAND_PARAM(Image *, dst) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -483,8 +447,7 @@ DX12_BEGIN_CONTEXT_COMMAND(ResolveMultiSampleImage) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(EndCPUTextureAccess) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, EndCPUTextureAccess) DX12_CONTEXT_COMMAND_PARAM(Image *, texture) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -493,8 +456,7 @@ DX12_BEGIN_CONTEXT_COMMAND(EndCPUTextureAccess) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(UpdateBuffer) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, UpdateBuffer) DX12_CONTEXT_COMMAND_PARAM(HostDeviceSharedMemoryRegion, source) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndOffset, dest) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -503,8 +465,7 @@ DX12_BEGIN_CONTEXT_COMMAND(UpdateBuffer) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(DrawIndirect) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, DrawIndirect) DX12_CONTEXT_COMMAND_PARAM(D3D12_PRIMITIVE_TOPOLOGY, top) DX12_CONTEXT_COMMAND_PARAM(uint32_t, count) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndOffset, buffer) @@ -520,8 +481,7 @@ DX12_BEGIN_CONTEXT_COMMAND(DrawIndirect) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(BeginCPUTextureAccess) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, BeginCPUTextureAccess) DX12_CONTEXT_COMMAND_PARAM(Image *, texture) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -530,8 +490,7 @@ DX12_BEGIN_CONTEXT_COMMAND(BeginCPUTextureAccess) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(RegisterStaticRenderState) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, RegisterStaticRenderState) DX12_CONTEXT_COMMAND_PARAM(StaticRenderStateID, ident) DX12_CONTEXT_COMMAND_PARAM(RenderStateSystem::StaticState, state) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -541,8 +500,7 @@ DX12_BEGIN_CONTEXT_COMMAND(RegisterStaticRenderState) DX12_END_CONTEXT_COMMAND #if D3D_HAS_RAY_TRACING -DX12_BEGIN_CONTEXT_COMMAND(SetRaytraceProgram) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetRaytraceProgram) DX12_CONTEXT_COMMAND_PARAM(ProgramID, program) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -551,8 +509,7 @@ DX12_BEGIN_CONTEXT_COMMAND(SetRaytraceProgram) DX12_END_CONTEXT_COMMAND #endif -DX12_BEGIN_CONTEXT_COMMAND(ClearDepthStencilTexture) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, ClearDepthStencilTexture) DX12_CONTEXT_COMMAND_PARAM(Image *, image) DX12_CONTEXT_COMMAND_PARAM(ImageViewState, viewState) DX12_CONTEXT_COMMAND_PARAM(D3D12_CPU_DESCRIPTOR_HANDLE, viewDescriptor) @@ -566,8 +523,7 @@ DX12_BEGIN_CONTEXT_COMMAND(ClearDepthStencilTexture) DX12_END_CONTEXT_COMMAND #if !_TARGET_XBOXONE -DX12_BEGIN_CONTEXT_COMMAND(SetVariableRateShading) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetVariableRateShading) DX12_CONTEXT_COMMAND_PARAM(D3D12_SHADING_RATE, constantRate) DX12_CONTEXT_COMMAND_PARAM(D3D12_SHADING_RATE_COMBINER, vertexCombiner) DX12_CONTEXT_COMMAND_PARAM(D3D12_SHADING_RATE_COMBINER, pixelCombiner) @@ -578,16 +534,14 @@ DX12_BEGIN_CONTEXT_COMMAND(SetVariableRateShading) DX12_END_CONTEXT_COMMAND #endif -DX12_BEGIN_CONTEXT_COMMAND(BeginConditionalRender) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, BeginConditionalRender) DX12_CONTEXT_COMMAND_PARAM(PredicateInfo, pi) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION ctx.beginConditionalRender(pi); #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(BeginSurvey) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, BeginSurvey) DX12_CONTEXT_COMMAND_PARAM(PredicateInfo, pi) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -595,8 +549,7 @@ DX12_BEGIN_CONTEXT_COMMAND(BeginSurvey) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(SetBlendConstantFactor) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetBlendConstantFactor) DX12_CONTEXT_COMMAND_PARAM(E3DCOLOR, constant) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -604,8 +557,7 @@ DX12_BEGIN_CONTEXT_COMMAND(SetBlendConstantFactor) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(SetDepthBoundsRange) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetDepthBoundsRange) DX12_CONTEXT_COMMAND_PARAM(float, from) DX12_CONTEXT_COMMAND_PARAM(float, to) @@ -614,8 +566,7 @@ DX12_BEGIN_CONTEXT_COMMAND(SetDepthBoundsRange) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(SetPolygonLineEnable) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetPolygonLineEnable) DX12_CONTEXT_COMMAND_PARAM(bool, enable) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -624,8 +575,7 @@ DX12_BEGIN_CONTEXT_COMMAND(SetPolygonLineEnable) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(SetStencilRef) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetStencilRef) DX12_CONTEXT_COMMAND_PARAM(uint8_t, ref) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -633,8 +583,7 @@ DX12_BEGIN_CONTEXT_COMMAND(SetStencilRef) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(SetScissorEnable) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetScissorEnable) DX12_CONTEXT_COMMAND_PARAM(bool, enable) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -642,16 +591,14 @@ DX12_BEGIN_CONTEXT_COMMAND(SetScissorEnable) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND_EXT_1(SetScissorRects, D3D12_RECT, rects) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND_EXT_1(false, SetScissorRects, D3D12_RECT, rects) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION ctx.setScissorRects(rects); #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(DrawIndexedIndirect) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, DrawIndexedIndirect) DX12_CONTEXT_COMMAND_PARAM(D3D12_PRIMITIVE_TOPOLOGY, top) DX12_CONTEXT_COMMAND_PARAM(uint32_t, count) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndOffset, buffer) @@ -668,8 +615,7 @@ DX12_BEGIN_CONTEXT_COMMAND(DrawIndexedIndirect) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(DrawUserData) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, DrawUserData) DX12_CONTEXT_COMMAND_PARAM(D3D12_PRIMITIVE_TOPOLOGY, top) DX12_CONTEXT_COMMAND_PARAM(uint32_t, count) DX12_CONTEXT_COMMAND_PARAM(uint32_t, stride) @@ -685,8 +631,7 @@ DX12_BEGIN_CONTEXT_COMMAND(DrawUserData) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(DrawIndexedUserData) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, DrawIndexedUserData) DX12_CONTEXT_COMMAND_PARAM(D3D12_PRIMITIVE_TOPOLOGY, top) DX12_CONTEXT_COMMAND_PARAM(uint32_t, count) DX12_CONTEXT_COMMAND_PARAM(uint32_t, vertexStride) @@ -704,8 +649,7 @@ DX12_BEGIN_CONTEXT_COMMAND(DrawIndexedUserData) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(CopyBuffer) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, CopyBuffer) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndOffset, source) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndOffset, dest) DX12_CONTEXT_COMMAND_PARAM(uint32_t, dataSize) @@ -716,8 +660,7 @@ DX12_BEGIN_CONTEXT_COMMAND(CopyBuffer) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(ClearBufferFloat) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, ClearBufferFloat) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndClearView, buffer) DX12_CONTEXT_COMMAND_PARAM_ARRAY(float, values, 4) @@ -727,24 +670,21 @@ DX12_BEGIN_CONTEXT_COMMAND(ClearBufferFloat) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND_EXT_1(PushEvent, char, text) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND_EXT_1(true, PushEvent, char, text) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION ctx.pushEvent(text); #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(PopEvent) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, PopEvent) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION ctx.popEvent(); #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(ClearColorTexture) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, ClearColorTexture) DX12_CONTEXT_COMMAND_PARAM(Image *, image) DX12_CONTEXT_COMMAND_PARAM(ImageViewState, viewState) DX12_CONTEXT_COMMAND_PARAM(D3D12_CPU_DESCRIPTOR_HANDLE, viewDescriptor) @@ -757,8 +697,7 @@ DX12_BEGIN_CONTEXT_COMMAND(ClearColorTexture) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(ClearUAVTextureI) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, ClearUAVTextureI) DX12_CONTEXT_COMMAND_PARAM(Image *, image) DX12_CONTEXT_COMMAND_PARAM(ImageViewState, view) DX12_CONTEXT_COMMAND_PARAM(D3D12_CPU_DESCRIPTOR_HANDLE, viewDescriptor) @@ -770,8 +709,7 @@ DX12_BEGIN_CONTEXT_COMMAND(ClearUAVTextureI) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(ClearUAVTextureF) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, ClearUAVTextureF) DX12_CONTEXT_COMMAND_PARAM(Image *, image) DX12_CONTEXT_COMMAND_PARAM(ImageViewState, view) DX12_CONTEXT_COMMAND_PARAM(D3D12_CPU_DESCRIPTOR_HANDLE, viewDescriptor) @@ -783,8 +721,7 @@ DX12_BEGIN_CONTEXT_COMMAND(ClearUAVTextureF) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(FlushWithFence) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, FlushWithFence) DX12_CONTEXT_COMMAND_PARAM(uint64_t, progress) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -793,8 +730,7 @@ DX12_BEGIN_CONTEXT_COMMAND(FlushWithFence) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(EndSurvey) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, EndSurvey) DX12_CONTEXT_COMMAND_PARAM(PredicateInfo, pi) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -802,8 +738,7 @@ DX12_BEGIN_CONTEXT_COMMAND(EndSurvey) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(FinishFrame) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, FinishFrame) DX12_CONTEXT_COMMAND_PARAM(uint64_t, progress) DX12_CONTEXT_COMMAND_PARAM(uint32_t, latencyFrameId) DX12_CONTEXT_COMMAND_PARAM(uint32_t, frontFrameId) @@ -817,8 +752,7 @@ DX12_BEGIN_CONTEXT_COMMAND(FinishFrame) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(InsertTimestampQuery) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, InsertTimestampQuery) DX12_CONTEXT_COMMAND_PARAM(Query *, query) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -826,16 +760,14 @@ DX12_BEGIN_CONTEXT_COMMAND(InsertTimestampQuery) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(EndConditionalRender) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, EndConditionalRender) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION ctx.endConditionalRender(); #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(AddVertexShader) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, AddVertexShader) DX12_CONTEXT_COMMAND_PARAM(ShaderID, id) DX12_CONTEXT_COMMAND_PARAM(VertexShaderModule *, sci) @@ -844,8 +776,7 @@ DX12_BEGIN_CONTEXT_COMMAND(AddVertexShader) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(AddPixelShader) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, AddPixelShader) DX12_CONTEXT_COMMAND_PARAM(ShaderID, id) DX12_CONTEXT_COMMAND_PARAM(PixelShaderModule *, sci) @@ -854,8 +785,7 @@ DX12_BEGIN_CONTEXT_COMMAND(AddPixelShader) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(AddComputeProgram) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, AddComputeProgram) DX12_CONTEXT_COMMAND_PARAM(ProgramID, id) DX12_CONTEXT_COMMAND_PARAM(ComputeShaderModule *, csm) DX12_CONTEXT_COMMAND_PARAM(CSPreloaded, preloaded) @@ -865,8 +795,7 @@ DX12_BEGIN_CONTEXT_COMMAND(AddComputeProgram) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(AddGraphicsProgram) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, AddGraphicsProgram) DX12_CONTEXT_COMMAND_PARAM(GraphicsProgramID, program) DX12_CONTEXT_COMMAND_PARAM(ShaderID, vs) DX12_CONTEXT_COMMAND_PARAM(ShaderID, fs) @@ -876,8 +805,7 @@ DX12_BEGIN_CONTEXT_COMMAND(AddGraphicsProgram) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND_EXT_1(PlaceAftermathMarker, char, string) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND_EXT_1(true, PlaceAftermathMarker, char, string) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION ctx.writeToDebug(string); @@ -885,8 +813,7 @@ DX12_BEGIN_CONTEXT_COMMAND_EXT_1(PlaceAftermathMarker, char, string) DX12_END_CONTEXT_COMMAND #if D3D_HAS_RAY_TRACING -DX12_BEGIN_CONTEXT_COMMAND(TraceRays) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, TraceRays) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndRange, rayGenTable) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndRange, missTable) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndRange, hitTable) @@ -904,8 +831,7 @@ DX12_BEGIN_CONTEXT_COMMAND(TraceRays) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(SetRaytraceAccelerationStructure) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetRaytraceAccelerationStructure) DX12_CONTEXT_COMMAND_PARAM(uint32_t, stage) DX12_CONTEXT_COMMAND_PARAM(uint32_t, unit) DX12_CONTEXT_COMMAND_PARAM(RaytraceAccelerationStructure *, as) @@ -915,9 +841,8 @@ DX12_BEGIN_CONTEXT_COMMAND(SetRaytraceAccelerationStructure) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND_EXT_2(RaytraceBuildBottomAccelerationStructure, D3D12_RAYTRACING_GEOMETRY_DESC, geometryDescriptions, +DX12_BEGIN_CONTEXT_COMMAND_EXT_2(true, RaytraceBuildBottomAccelerationStructure, D3D12_RAYTRACING_GEOMETRY_DESC, geometryDescriptions, RaytraceGeometryDescriptionBufferResourceReferenceSet, resourceReferences) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndAddress, scratchBuffer) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndAddress, compactedSize) DX12_CONTEXT_COMMAND_PARAM(RaytraceAccelerationStructure *, as) @@ -933,8 +858,7 @@ DX12_BEGIN_CONTEXT_COMMAND_EXT_2(RaytraceBuildBottomAccelerationStructure, D3D12 #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(AddRaytraceProgram) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, AddRaytraceProgram) DX12_CONTEXT_COMMAND_PARAM(ProgramID, program) DX12_CONTEXT_COMMAND_PARAM(const ShaderID *, shaders) DX12_CONTEXT_COMMAND_PARAM(const RaytraceShaderGroup *, shaderGroups) @@ -948,8 +872,7 @@ DX12_BEGIN_CONTEXT_COMMAND(AddRaytraceProgram) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(CopyRaytraceShaderGroupHandlesToMemory) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, CopyRaytraceShaderGroupHandlesToMemory) DX12_CONTEXT_COMMAND_PARAM(ProgramID, program) DX12_CONTEXT_COMMAND_PARAM(uint32_t, firstGroup) DX12_CONTEXT_COMMAND_PARAM(uint32_t, groupCount) @@ -964,8 +887,7 @@ DX12_END_CONTEXT_COMMAND #endif -DX12_BEGIN_CONTEXT_COMMAND(ChangePresentMode) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, ChangePresentMode) DX12_CONTEXT_COMMAND_PARAM(PresentationMode, presentMode) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -973,8 +895,7 @@ DX12_BEGIN_CONTEXT_COMMAND(ChangePresentMode) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND_EXT_1(UpdateVertexShaderName, char, name) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND_EXT_1(false, UpdateVertexShaderName, char, name) DX12_CONTEXT_COMMAND_PARAM(ShaderID, shader) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -982,8 +903,7 @@ DX12_BEGIN_CONTEXT_COMMAND_EXT_1(UpdateVertexShaderName, char, name) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND_EXT_1(UpdatePixelShaderName, char, name) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND_EXT_1(false, UpdatePixelShaderName, char, name) DX12_CONTEXT_COMMAND_PARAM(ShaderID, shader) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -991,8 +911,7 @@ DX12_BEGIN_CONTEXT_COMMAND_EXT_1(UpdatePixelShaderName, char, name) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(SetComputeRootConstant) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetComputeRootConstant) DX12_CONTEXT_COMMAND_PARAM(uint32_t, offset) DX12_CONTEXT_COMMAND_PARAM(uint32_t, value) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -1001,8 +920,7 @@ DX12_BEGIN_CONTEXT_COMMAND(SetComputeRootConstant) DX12_END_CONTEXT_COMMAND #if D3D_HAS_RAY_TRACING -DX12_BEGIN_CONTEXT_COMMAND(SetRaytraceRootConstant) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetRaytraceRootConstant) DX12_CONTEXT_COMMAND_PARAM(uint32_t, offset) DX12_CONTEXT_COMMAND_PARAM(uint32_t, value) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -1011,24 +929,21 @@ DX12_BEGIN_CONTEXT_COMMAND(SetRaytraceRootConstant) DX12_END_CONTEXT_COMMAND #endif -DX12_BEGIN_CONTEXT_COMMAND(BeginVisibilityQuery) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, BeginVisibilityQuery) DX12_CONTEXT_COMMAND_PARAM(Query *, query) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION ctx.beginVisibilityQuery(query); #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(EndVisibilityQuery) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, EndVisibilityQuery) DX12_CONTEXT_COMMAND_PARAM(Query *, query) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION ctx.endVisibilityQuery(query); #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND_EXT_1(TextureReadBack, BufferImageCopy, regions) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND_EXT_1(true, TextureReadBack, BufferImageCopy, regions) DX12_CONTEXT_COMMAND_PARAM(Image *, image) DX12_CONTEXT_COMMAND_PARAM(HostDeviceSharedMemoryRegion, cpuMemory) DX12_CONTEXT_COMMAND_PARAM(DeviceQueueType, queue) @@ -1039,8 +954,7 @@ DX12_BEGIN_CONTEXT_COMMAND_EXT_1(TextureReadBack, BufferImageCopy, regions) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(BufferReadBack) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, BufferReadBack) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndRange, buffer) DX12_CONTEXT_COMMAND_PARAM(HostDeviceSharedMemoryRegion, cpuMemory) DX12_CONTEXT_COMMAND_PARAM(size_t, offset) @@ -1052,8 +966,7 @@ DX12_BEGIN_CONTEXT_COMMAND(BufferReadBack) DX12_END_CONTEXT_COMMAND #if !_TARGET_XBOXONE -DX12_BEGIN_CONTEXT_COMMAND(SetVariableRateShadingTexture) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, SetVariableRateShadingTexture) DX12_CONTEXT_COMMAND_PARAM(Image *, texture) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -1062,8 +975,7 @@ DX12_BEGIN_CONTEXT_COMMAND(SetVariableRateShadingTexture) DX12_END_CONTEXT_COMMAND #endif -DX12_BEGIN_CONTEXT_COMMAND(RegisterInputLayout) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, RegisterInputLayout) DX12_CONTEXT_COMMAND_PARAM(InputLayoutID, ident) DX12_CONTEXT_COMMAND_PARAM(InputLayout, layout) @@ -1072,8 +984,7 @@ DX12_BEGIN_CONTEXT_COMMAND(RegisterInputLayout) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(CreateDlssFeature) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, CreateDlssFeature) DX12_CONTEXT_COMMAND_PARAM(bool, stereo_render) DX12_CONTEXT_COMMAND_PARAM(int, output_width) DX12_CONTEXT_COMMAND_PARAM(int, output_height) @@ -1084,8 +995,7 @@ DX12_BEGIN_CONTEXT_COMMAND(CreateDlssFeature) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(ReleaseDlssFeature) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, ReleaseDlssFeature) DX12_CONTEXT_COMMAND_PARAM(bool, stereo_render) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -1094,8 +1004,7 @@ DX12_BEGIN_CONTEXT_COMMAND(ReleaseDlssFeature) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(ExecuteDlss) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, ExecuteDlss) DX12_CONTEXT_COMMAND_PARAM(nv::DlssParams, dlss_params) DX12_CONTEXT_COMMAND_PARAM(int, view_index) DX12_CONTEXT_COMMAND_PARAM(uint32_t, frame_id) @@ -1106,8 +1015,7 @@ DX12_BEGIN_CONTEXT_COMMAND(ExecuteDlss) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(ExecuteDlssG) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, ExecuteDlssG) DX12_CONTEXT_COMMAND_PARAM(nv::DlssGParams, dlss_g_params) DX12_CONTEXT_COMMAND_PARAM(int, view_index) @@ -1117,8 +1025,7 @@ DX12_BEGIN_CONTEXT_COMMAND(ExecuteDlssG) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(ExecuteXess) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, ExecuteXess) DX12_CONTEXT_COMMAND_PARAM(XessParamsDx12, params) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -1127,8 +1034,7 @@ DX12_BEGIN_CONTEXT_COMMAND(ExecuteXess) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(DispatchFSR2) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, DispatchFSR2) DX12_CONTEXT_COMMAND_PARAM(Fsr2ParamsDx12, params) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -1137,8 +1043,7 @@ DX12_BEGIN_CONTEXT_COMMAND(DispatchFSR2) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(DispatchFSR) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, DispatchFSR) DX12_CONTEXT_COMMAND_PARAM(amd::FSR *, fsr) DX12_CONTEXT_COMMAND_PARAM(FSRUpscalingArgs, params) @@ -1148,8 +1053,7 @@ DX12_BEGIN_CONTEXT_COMMAND(DispatchFSR) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND_EXT_1(BeginCapture, wchar_t, name) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND_EXT_1(true, BeginCapture, wchar_t, name) DX12_CONTEXT_COMMAND_PARAM(UINT, flags) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -1157,15 +1061,13 @@ DX12_BEGIN_CONTEXT_COMMAND_EXT_1(BeginCapture, wchar_t, name) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(EndCapture) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, EndCapture) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION ctx.endCapture(); #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND_EXT_1(CaptureNextFrames, wchar_t, name) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND_EXT_1(true, CaptureNextFrames, wchar_t, name) DX12_CONTEXT_COMMAND_PARAM(UINT, flags) DX12_CONTEXT_COMMAND_PARAM(int, frame_count) @@ -1174,8 +1076,7 @@ DX12_BEGIN_CONTEXT_COMMAND_EXT_1(CaptureNextFrames, wchar_t, name) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(RemoveVertexShader) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, RemoveVertexShader) DX12_CONTEXT_COMMAND_PARAM(ShaderID, shader) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -1183,8 +1084,7 @@ DX12_BEGIN_CONTEXT_COMMAND(RemoveVertexShader) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(RemovePixelShader) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, RemovePixelShader) DX12_CONTEXT_COMMAND_PARAM(ShaderID, shader) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -1192,8 +1092,7 @@ DX12_BEGIN_CONTEXT_COMMAND(RemovePixelShader) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(DeleteProgram) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, DeleteProgram) DX12_CONTEXT_COMMAND_PARAM(ProgramID, program) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -1201,8 +1100,7 @@ DX12_BEGIN_CONTEXT_COMMAND(DeleteProgram) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(DeleteGraphicsProgram) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, DeleteGraphicsProgram) DX12_CONTEXT_COMMAND_PARAM(GraphicsProgramID, program) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -1210,16 +1108,14 @@ DX12_BEGIN_CONTEXT_COMMAND(DeleteGraphicsProgram) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND_EXT_1(DeleteQueries, Query *, queries) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND_EXT_1(true, DeleteQueries, Query *, queries) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION ctx.deleteQueries(queries); #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(HostToDeviceMemoryCopy) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, HostToDeviceMemoryCopy) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndRange, gpuMemory) DX12_CONTEXT_COMMAND_PARAM(HostDeviceSharedMemoryRegion, cpuMemory) DX12_CONTEXT_COMMAND_PARAM(size_t, cpuOffset) @@ -1230,8 +1126,7 @@ DX12_BEGIN_CONTEXT_COMMAND(HostToDeviceMemoryCopy) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(InitializeTextureState) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, InitializeTextureState) DX12_CONTEXT_COMMAND_PARAM(D3D12_RESOURCE_STATES, state) DX12_CONTEXT_COMMAND_PARAM(ValueRange, idRange) @@ -1240,8 +1135,7 @@ DX12_BEGIN_CONTEXT_COMMAND(InitializeTextureState) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND_EXT_1(UploadTexture, BufferImageCopy, regions) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND_EXT_1(true, UploadTexture, BufferImageCopy, regions) DX12_CONTEXT_COMMAND_PARAM(Image *, texture) DX12_CONTEXT_COMMAND_PARAM(HostDeviceSharedMemoryRegion, cpuMemory) DX12_CONTEXT_COMMAND_PARAM(DeviceQueueType, queue) @@ -1254,8 +1148,7 @@ DX12_BEGIN_CONTEXT_COMMAND_EXT_1(UploadTexture, BufferImageCopy, regions) DX12_END_CONTEXT_COMMAND #if _TARGET_XBOX -DX12_BEGIN_CONTEXT_COMMAND(UpdateFrameInterval) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, UpdateFrameInterval) DX12_CONTEXT_COMMAND_PARAM(int32_t, freqLevel) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -1264,8 +1157,7 @@ DX12_BEGIN_CONTEXT_COMMAND(UpdateFrameInterval) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(ResummarizeHtile) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, ResummarizeHtile) DX12_CONTEXT_COMMAND_PARAM(ID3D12Resource *, depth) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -1277,28 +1169,24 @@ DX12_END_CONTEXT_COMMAND #endif // this command only exists to wake up a potentially sleeping worker -DX12_BEGIN_CONTEXT_COMMAND(WorkerPing) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, WorkerPing) DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(Terminate) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, Terminate) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION ctx.terminateWorker(); #endif DX12_END_CONTEXT_COMMAND #if _TARGET_XBOX -DX12_BEGIN_CONTEXT_COMMAND(EnterSuspendState) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, EnterSuspendState) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION ctx.enterSuspendState(); #endif DX12_END_CONTEXT_COMMAND #endif -DX12_BEGIN_CONTEXT_COMMAND_EXT_1(WriteDebugMessage, char, message) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND_EXT_1(true, WriteDebugMessage, char, message) DX12_CONTEXT_COMMAND_PARAM(int, severity) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -1306,8 +1194,7 @@ DX12_BEGIN_CONTEXT_COMMAND_EXT_1(WriteDebugMessage, char, message) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(BindlessSetResourceDescriptor) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, BindlessSetResourceDescriptor) DX12_CONTEXT_COMMAND_PARAM(uint32_t, slot) DX12_CONTEXT_COMMAND_PARAM(D3D12_CPU_DESCRIPTOR_HANDLE, descriptor) @@ -1317,8 +1204,7 @@ DX12_BEGIN_CONTEXT_COMMAND(BindlessSetResourceDescriptor) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(BindlessSetTextureDescriptor) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, BindlessSetTextureDescriptor) DX12_CONTEXT_COMMAND_PARAM(uint32_t, slot) DX12_CONTEXT_COMMAND_PARAM(Image *, texture) DX12_CONTEXT_COMMAND_PARAM(D3D12_CPU_DESCRIPTOR_HANDLE, view) @@ -1329,8 +1215,7 @@ DX12_BEGIN_CONTEXT_COMMAND(BindlessSetTextureDescriptor) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(BindlessSetSamplerDescriptor) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, BindlessSetSamplerDescriptor) DX12_CONTEXT_COMMAND_PARAM(uint32_t, slot) DX12_CONTEXT_COMMAND_PARAM(D3D12_CPU_DESCRIPTOR_HANDLE, descriptor) @@ -1340,8 +1225,7 @@ DX12_BEGIN_CONTEXT_COMMAND(BindlessSetSamplerDescriptor) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(BindlessCopyResourceDescriptors) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, BindlessCopyResourceDescriptors) DX12_CONTEXT_COMMAND_PARAM(uint32_t, src) DX12_CONTEXT_COMMAND_PARAM(uint32_t, dst) DX12_CONTEXT_COMMAND_PARAM(uint32_t, count) @@ -1352,8 +1236,7 @@ DX12_BEGIN_CONTEXT_COMMAND(BindlessCopyResourceDescriptors) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(RegisterFrameCompleteEvent) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, RegisterFrameCompleteEvent) DX12_CONTEXT_COMMAND_PARAM(os_event_t, event) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -1361,8 +1244,7 @@ DX12_BEGIN_CONTEXT_COMMAND(RegisterFrameCompleteEvent) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(RegisterFrameEventsCallback) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, RegisterFrameEventsCallback) DX12_CONTEXT_COMMAND_PARAM(FrameEvents *, callback) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -1371,8 +1253,7 @@ DX12_BEGIN_CONTEXT_COMMAND(RegisterFrameEventsCallback) DX12_END_CONTEXT_COMMAND #if !DX12_USE_AUTO_PROMOTE_AND_DECAY -DX12_BEGIN_CONTEXT_COMMAND(ResetBufferState) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, ResetBufferState) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReference, buffer) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -1382,8 +1263,7 @@ DX12_BEGIN_CONTEXT_COMMAND(ResetBufferState) DX12_END_CONTEXT_COMMAND #endif -DX12_BEGIN_CONTEXT_COMMAND(AddSwapchainView) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, AddSwapchainView) DX12_CONTEXT_COMMAND_PARAM(Image *, image) DX12_CONTEXT_COMMAND_PARAM(ImageViewInfo, view) @@ -1395,8 +1275,7 @@ DX12_END_CONTEXT_COMMAND #if _TARGET_PC_WIN -DX12_BEGIN_CONTEXT_COMMAND(OnDeviceError) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, OnDeviceError) DX12_CONTEXT_COMMAND_PARAM(HRESULT, removerReason) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -1405,15 +1284,13 @@ DX12_BEGIN_CONTEXT_COMMAND(OnDeviceError) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(OnSwapchainSwapCompleted) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, OnSwapchainSwapCompleted) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION ctx.onSwapchainSwapCompleted(); #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(CommandFence) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, CommandFence) DX12_CONTEXT_COMMAND_PARAM(std::atomic_bool &, signal) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION ctx.commandFence(signal); @@ -1423,8 +1300,7 @@ DX12_END_CONTEXT_COMMAND #endif #if _TARGET_PC_WIN -DX12_BEGIN_CONTEXT_COMMAND(BeginTileMapping) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, BeginTileMapping) DX12_CONTEXT_COMMAND_PARAM(Image *, tex) DX12_CONTEXT_COMMAND_PARAM(ID3D12Heap *, heap) DX12_CONTEXT_COMMAND_PARAM(size_t, heapBase) @@ -1434,8 +1310,7 @@ DX12_BEGIN_CONTEXT_COMMAND(BeginTileMapping) #endif #else -DX12_BEGIN_CONTEXT_COMMAND(BeginTileMapping) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, BeginTileMapping) DX12_CONTEXT_COMMAND_PARAM(Image *, tex) DX12_CONTEXT_COMMAND_PARAM(uintptr_t, address) DX12_CONTEXT_COMMAND_PARAM(uint64_t, size) @@ -1446,22 +1321,19 @@ DX12_BEGIN_CONTEXT_COMMAND(BeginTileMapping) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND_EXT_1(AddTileMappings, TileMapping, mapping) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND_EXT_1(true, AddTileMappings, TileMapping, mapping) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION ctx.addTileMappings(mapping.data(), mapping.size()); #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(EndTileMapping) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, EndTileMapping) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION ctx.endTileMapping(); #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(ActivateBuffer) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, ActivateBuffer) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndAddressRangeWithClearView, buffer) DX12_CONTEXT_COMMAND_PARAM(ResourceMemory, memory) DX12_CONTEXT_COMMAND_PARAM(ResourceActivationAction, action) @@ -1474,8 +1346,7 @@ DX12_BEGIN_CONTEXT_COMMAND(ActivateBuffer) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(ActivateTexture) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, ActivateTexture) DX12_CONTEXT_COMMAND_PARAM(Image *, texture) DX12_CONTEXT_COMMAND_PARAM(ResourceActivationAction, action) DX12_CONTEXT_COMMAND_PARAM(ResourceClearValue, clearValue) @@ -1489,8 +1360,7 @@ DX12_BEGIN_CONTEXT_COMMAND(ActivateTexture) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(DeactivateBuffer) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, DeactivateBuffer) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndAddressRange, buffer) DX12_CONTEXT_COMMAND_PARAM(ResourceMemory, memory) DX12_CONTEXT_COMMAND_PARAM(GpuPipeline, queue) @@ -1500,8 +1370,7 @@ DX12_BEGIN_CONTEXT_COMMAND(DeactivateBuffer) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(DeactivateTexture) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, DeactivateTexture) DX12_CONTEXT_COMMAND_PARAM(Image *, texture) DX12_CONTEXT_COMMAND_PARAM(GpuPipeline, queue) @@ -1510,8 +1379,7 @@ DX12_BEGIN_CONTEXT_COMMAND(DeactivateTexture) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(AliasFlush) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, AliasFlush) DX12_CONTEXT_COMMAND_PARAM(GpuPipeline, queue) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -1521,8 +1389,7 @@ DX12_BEGIN_CONTEXT_COMMAND(AliasFlush) DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(TwoPhaseCopyBuffer) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, TwoPhaseCopyBuffer) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndOffset, source) DX12_CONTEXT_COMMAND_PARAM(uint64_t, destinationOffset) DX12_CONTEXT_COMMAND_PARAM(ScratchBuffer, scratchMemory) @@ -1534,8 +1401,7 @@ DX12_BEGIN_CONTEXT_COMMAND(TwoPhaseCopyBuffer) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(MoveBuffer) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, MoveBuffer) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndOffset, from) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReferenceAndRange, to) @@ -1545,8 +1411,7 @@ DX12_BEGIN_CONTEXT_COMMAND(MoveBuffer) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(MoveTexture) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, MoveTexture) DX12_CONTEXT_COMMAND_PARAM(Image *, from) DX12_CONTEXT_COMMAND_PARAM(Image *, to) @@ -1556,8 +1421,7 @@ DX12_BEGIN_CONTEXT_COMMAND(MoveTexture) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(TransitionBuffer) - DX12_CONTEXT_COMMAND_IS_PRIMARY(false) +DX12_BEGIN_CONTEXT_COMMAND(false, TransitionBuffer) DX12_CONTEXT_COMMAND_PARAM(BufferResourceReference, buffer) DX12_CONTEXT_COMMAND_PARAM(D3D12_RESOURCE_STATES, state) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -1565,8 +1429,7 @@ DX12_BEGIN_CONTEXT_COMMAND(TransitionBuffer) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(ResizeImageMipMapTransfer) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, ResizeImageMipMapTransfer) DX12_CONTEXT_COMMAND_PARAM(Image *, src) DX12_CONTEXT_COMMAND_PARAM(Image *, dst) DX12_CONTEXT_COMMAND_PARAM(MipMapRange, mipMapRange) @@ -1578,31 +1441,27 @@ DX12_BEGIN_CONTEXT_COMMAND(ResizeImageMipMapTransfer) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(DebugBreak) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, DebugBreak) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION ctx.debugBreak(); #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND_EXT_1(AddDebugBreakString, char, str) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND_EXT_1(true, AddDebugBreakString, char, str) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION ctx.addDebugBreakString(str); #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND_EXT_1(RemoveDebugBreakString, char, str) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND_EXT_1(true, RemoveDebugBreakString, char, str) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION ctx.removeDebugBreakString(str); #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND_EXT_1(AddShaderGroup, char, name) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND_EXT_1(true, AddShaderGroup, char, name) DX12_CONTEXT_COMMAND_PARAM(uint32_t, group) DX12_CONTEXT_COMMAND_PARAM(ScriptedShadersBinDumpOwner *, dump) DX12_CONTEXT_COMMAND_PARAM(ShaderID, nullPixelShader) @@ -1613,8 +1472,7 @@ DX12_BEGIN_CONTEXT_COMMAND_EXT_1(AddShaderGroup, char, name) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(RemoveShaderGroup) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, RemoveShaderGroup) DX12_CONTEXT_COMMAND_PARAM(uint32_t, group) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -1623,8 +1481,7 @@ DX12_BEGIN_CONTEXT_COMMAND(RemoveShaderGroup) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(LoadComputeShaderFromDump) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, LoadComputeShaderFromDump) DX12_CONTEXT_COMMAND_PARAM(ProgramID, program) #if DX12_CONTEXT_COMMAND_IMPLEMENTATION @@ -1633,8 +1490,7 @@ DX12_BEGIN_CONTEXT_COMMAND(LoadComputeShaderFromDump) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(CompilePipelineSet) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, CompilePipelineSet) DX12_CONTEXT_COMMAND_PARAM(eastl::span, inputLayouts) DX12_CONTEXT_COMMAND_PARAM(eastl::span, staticRenderStates) DX12_CONTEXT_COMMAND_PARAM(eastl::span, framebufferLayouts) @@ -1653,8 +1509,7 @@ DX12_BEGIN_CONTEXT_COMMAND(CompilePipelineSet) #endif DX12_END_CONTEXT_COMMAND -DX12_BEGIN_CONTEXT_COMMAND(CompilePipelineSet2) - DX12_CONTEXT_COMMAND_IS_PRIMARY(true) +DX12_BEGIN_CONTEXT_COMMAND(true, CompilePipelineSet2) DX12_CONTEXT_COMMAND_PARAM(eastl::span, inputLayouts) DX12_CONTEXT_COMMAND_PARAM(eastl::span, staticRenderStates) DX12_CONTEXT_COMMAND_PARAM(eastl::span, framebufferLayouts) diff --git a/prog/engine/drv/drv3d_DX12/device_queue.cpp b/prog/engine/drv/drv3d_DX12/device_queue.cpp index 5e0305ad9..650751921 100644 --- a/prog/engine/drv/drv3d_DX12/device_queue.cpp +++ b/prog/engine/drv/drv3d_DX12/device_queue.cpp @@ -1,9 +1,10 @@ // Copyright (C) Gaijin Games KFT. All rights reserved. -#include "device_queue.h" - #include +#include "device_queue.h" +#include "device.h" + using namespace drv3d_dx12; #if _TARGET_XBOX @@ -147,3 +148,51 @@ void DeviceQueueGroup::shutdown() } DeviceQueue::~DeviceQueue() {} + +bool drv3d_dx12::wait_for_frame_progress_with_event_slow_path(DeviceQueueGroup &qs, uint64_t progress, HANDLE event, const char *what) +{ +#if LOCK_PROFILER_ENABLED + using namespace da_profiler; + static desc_id_t wffpdesc = + add_description(DA_PROFILE_FILE_NAMES ? __FILE__ : nullptr, __LINE__, IsWait, "DX12_waitForFrameProgress"); + ScopeLockProfiler lp(wffpdesc); +#endif + if (!qs.waitForFrameProgress(progress, event)) + { + return false; + } + + auto result = WaitForSingleObject(event, MAX_WAIT_OBJECT_TIMEOUT_MS); + while (result == WAIT_TIMEOUT) + { + if (get_device().isInErrorState()) + { + logdbg("DX12: While waiting for frame progress %u - %s, WaitForSingleObject(%p, MAX_WAIT_OBJECT_TIMEOUT_MS) returned " + "WAIT_TIMEOUT, but device is in error state, return false to avoid infinite loops", + progress, what, event); + return false; + } + logdbg("DX12: While waiting for frame progress %u - %s, WaitForSingleObject(%p, MAX_WAIT_OBJECT_TIMEOUT_MS) returned " + "WAIT_TIMEOUT, continue", + progress, what, event); + result = WaitForSingleObject(event, MAX_WAIT_OBJECT_TIMEOUT_MS); + } + + if (WAIT_OBJECT_0 == result) + { + return true; + } + if (DAGOR_UNLIKELY(WAIT_FAILED == result)) + { + logwarn("DX12: While waiting for frame progress %u - %s, WaitForSingleObject(%p, MAX_WAIT_OBJECT_TIMEOUT_MS) " + "failed with 0x%08X, trying to continue with alternatives", + progress, what, event, GetLastError()); + } + if (qs.checkFrameProgress() >= progress) + { + logdbg("DX12: Progress check allowed continuation"); + return true; + } + logdbg("DX12: Calling SetEventOnCompletion with nullptr"); + return qs.waitForFrameProgress(progress, nullptr); +} diff --git a/prog/engine/drv/drv3d_DX12/device_queue.h b/prog/engine/drv/drv3d_DX12/device_queue.h index 53f8e2ea3..9f7dd70b0 100644 --- a/prog/engine/drv/drv3d_DX12/device_queue.h +++ b/prog/engine/drv/drv3d_DX12/device_queue.h @@ -257,38 +257,7 @@ class DeviceQueueGroup // Some driver/device struggle with long running frames and then suddenly // WaitForSingleObject returns errors that make no sense. // This functions handles this with some fall back strategies. -inline DAGOR_NOINLINE bool wait_for_frame_progress_with_event_slow_path(DeviceQueueGroup &qs, uint64_t progress, HANDLE event, - const char *what) -{ -#if LOCK_PROFILER_ENABLED - using namespace da_profiler; - static desc_id_t wffpdesc = - add_description(DA_PROFILE_FILE_NAMES ? __FILE__ : nullptr, __LINE__, IsWait, "DX12_waitForFrameProgress"); - ScopeLockProfiler lp(wffpdesc); -#endif - if (!qs.waitForFrameProgress(progress, event)) - { - return false; - } - auto result = WaitForSingleObject(event, INFINITE); - if (WAIT_OBJECT_0 == result) - { - return true; - } - if (DAGOR_UNLIKELY(WAIT_FAILED == result)) - { - logwarn("DX12: While waiting for frame progress %u - %s, WaitForSingleObject(%p, INFINITE) " - "failed with 0x%08X, trying to continue with alternatives", - progress, what, event, GetLastError()); - } - if (qs.checkFrameProgress() >= progress) - { - logdbg("DX12: Progress check allowed continuation"); - return true; - } - logdbg("DX12: Calling SetEventOnCompletion with nullptr"); - return qs.waitForFrameProgress(progress, nullptr); -} +bool wait_for_frame_progress_with_event_slow_path(DeviceQueueGroup &qs, uint64_t progress, HANDLE event, const char *what); __forceinline bool wait_for_frame_progress_with_event(DeviceQueueGroup &qs, uint64_t progress, HANDLE event, const char *what) { diff --git a/prog/engine/drv/drv3d_DX12/variant_vector.h b/prog/engine/drv/drv3d_DX12/variant_vector.h index 22c56cb83..d5bc8a307 100644 --- a/prog/engine/drv/drv3d_DX12/variant_vector.h +++ b/prog/engine/drv/drv3d_DX12/variant_vector.h @@ -998,7 +998,7 @@ class VariantContainerBase, IType> : public VariantContainerM using DT = typename eastl::decay::type; using UsedTypeHandler = TypeHandler; // Prevents creation of meta types - G_STATIC_ASSERT(UsedTypeHandler::size != 0); + G_STATIC_ASSERT(UsedTypeHandler::is_valid); MemoryWriter m{pos}; m.write(TypeIndexOf::value); UsedTypeHandler::copyConstruct(m, value); @@ -1030,7 +1030,7 @@ class VariantContainerBase, IType> : public VariantContainerM } template - static void moveConstructAt(DataStoreType *pos, T &&value, P0 *p0, size_t p0_count) + static void moveConstructAt(DataStoreType *pos, T &&value, const P0 *p0, size_t p0_count) { using DT = typename eastl::decay::type; using DP0 = typename eastl::decay::type; @@ -1947,20 +1947,7 @@ class VariantRingBufferT, IType> : public VariantContainerBas } template - Iterator pushBack(const T &v, bool wake_executor = true) - { - auto sizeNeeded = this->template calculateTotalSpaceForTypeSize(); - - auto allocResult = allocateSpace(sizeNeeded); - - this->template copyConstructAt(&store[allocResult % size], v); - - commitSpace(allocResult, sizeNeeded, wake_executor); - return {Iterator{*this, *allocResult}}; - } - - template - Iterator pushBack(T &&v, bool wake_executor = true) + Iterator pushBack(T &&v, bool wake_executor = eastl::decay_t::is_primary()) { auto sizeNeeded = this->template calculateTotalSpaceForTypeSize(); @@ -2098,20 +2085,7 @@ class VariantRingBufferT, IType> : public VariantContainerBas } template - Iterator pushBack(const T &v, const P0 *p0, size_t p0_count) - { - auto sizeNeeded = this->template calculateTotalSpaceForExtenedVariant(p0_count); - - auto allocResult = allocateSpace(sizeNeeded); - - this->template copyConstructAt(&store[allocResult % size], v, p0, p0_count); - - commitSpace(allocResult, sizeNeeded); - return {Iterator{*this, allocResult}}; - } - - template - Iterator pushBack(T &&v, P0 *p0, size_t p0_count) + Iterator pushBack(T &&v, const P0 *p0, size_t p0_count) { auto sizeNeeded = this->template calculateTotalSpaceForExtenedVariant(p0_count); @@ -2119,21 +2093,7 @@ class VariantRingBufferT, IType> : public VariantContainerBas this->template moveConstructAt(&store[allocResult % size], eastl::forward(v), p0, p0_count); - commitSpace(allocResult, sizeNeeded); - return {Iterator{*this, allocResult}}; - } - - template - Iterator pushBack(const T &v, size_t p0_count, G0 g0) - { - using P0 = decltype(g0(0)); - auto sizeNeeded = this->template calculateTotalSpaceForExtenedVariant(p0_count); - - auto allocResult = allocateSpace(sizeNeeded); - - this->template copyConstructDataGeneratorAt(&store[allocResult % size], eastl::move(v), p0_count, g0); - - commitSpace(allocResult, sizeNeeded); + commitSpace(allocResult, sizeNeeded, eastl::decay_t::is_primary()); return {Iterator{*this, allocResult}}; } @@ -2147,7 +2107,7 @@ class VariantRingBufferT, IType> : public VariantContainerBas this->template moveConstructDataGeneratorAt(&store[allocResult % size], eastl::forward(v), p0_count, g0); - commitSpace(allocResult, sizeNeeded); + commitSpace(allocResult, sizeNeeded, eastl::decay_t::is_primary()); return {Iterator{*this, allocResult}}; } @@ -2160,7 +2120,7 @@ class VariantRingBufferT, IType> : public VariantContainerBas this->template copyConstructAt(&store[allocResult % size], v, p0, p0_count, p1, p1_count); - commitSpace(allocResult, sizeNeeded); + commitSpace(allocResult, sizeNeeded, T::is_primary()); return {Iterator{*this, allocResult}}; } @@ -2175,7 +2135,7 @@ class VariantRingBufferT, IType> : public VariantContainerBas this->template copyConstructExtended2DataGenerator(&store[allocResult % size], v, p0_count, g); - commitSpace(allocResult, sizeNeeded); + commitSpace(allocResult, sizeNeeded, T::is_primary()); return {Iterator{*this, allocResult}}; } diff --git a/prog/engine/drv/drv3d_DX12/xess_wrapper.cpp b/prog/engine/drv/drv3d_DX12/xess_wrapper.cpp index 54399c07c..ef8a36629 100644 --- a/prog/engine/drv/drv3d_DX12/xess_wrapper.cpp +++ b/prog/engine/drv/drv3d_DX12/xess_wrapper.cpp @@ -286,7 +286,7 @@ class XessWrapperImpl xess_2d_t m_renderResolution = {0, 0}; XessState m_state = XessState::DISABLED; - eastl::unique_ptr libxess; + DagorDynLibHolder libxess; decltype(::xessD3D12CreateContext) *xessD3D12CreateContext; decltype(::xessGetProperties) *xessGetProperties; decltype(::xessD3D12Init) *xessD3D12Init; diff --git a/prog/engine/drv/drv3d_Metal/render.h b/prog/engine/drv/drv3d_Metal/render.h index 702d8a57b..d8d0e52d2 100644 --- a/prog/engine/drv/drv3d_Metal/render.h +++ b/prog/engine/drv/drv3d_Metal/render.h @@ -777,7 +777,8 @@ class Render Compute, Acceleration }; - inline void ensureHaveEncoderExceptRender(id cmdBuf, EncoderType type, bool wait = true) + inline void ensureHaveEncoderExceptRender(id cmdBuf, EncoderType type, bool wait = true, + const char *label = nullptr) { #define KILL_ENCODER(t, enc) \ if (type != t) \ @@ -806,10 +807,20 @@ class Render need_change_rt = 1; } if (type == EncoderType::Blit && !blitEncoder) + { blitEncoder = [cmdBuf blitCommandEncoder]; +#if DAGOR_DBGLEVEL > 0 + if (label) + blitEncoder.label = [NSString stringWithUTF8String:label]; +#endif + } if (type == EncoderType::Compute && !computeEncoder) { computeEncoder = [cmdBuf computeCommandEncoder]; +#if DAGOR_DBGLEVEL > 0 + if (label) + computeEncoder.label = [NSString stringWithUTF8String:label]; +#endif stages[STAGE_CS].reset(); prepareBindlessResourcesCompute(computeEncoder); } diff --git a/prog/engine/drv/drv3d_Metal/render.mm b/prog/engine/drv/drv3d_Metal/render.mm index 32caed597..17564ca09 100644 --- a/prog/engine/drv/drv3d_Metal/render.mm +++ b/prog/engine/drv/drv3d_Metal/render.mm @@ -1307,7 +1307,7 @@ static void PatchShader(int shader, int num_reg, int num_tex) for (int i = 0; i < buffers2copy.size(); ++i) { bool need_set = render.computeEncoder == nil; - ensureHaveEncoderExceptRender(cmdBuf, Render::EncoderType::Compute, false); + ensureHaveEncoderExceptRender(cmdBuf, Render::EncoderType::Compute, false, "CopyBuffer"); if (need_set) [computeEncoder setComputePipelineState:copy_cs_pipeline]; @@ -1331,7 +1331,7 @@ static void PatchShader(int shader, int num_reg, int num_tex) bool needBlit = textures2upload.size() || regions2copy.size() || textures2clear.size() || buffers2clear.size(); if (needBlit) - ensureHaveEncoderExceptRender(cmdBuf, Render::EncoderType::Blit, false); + ensureHaveEncoderExceptRender(cmdBuf, Render::EncoderType::Blit, false, "CopyTextures"); for (int i = 0; i < buffers2clear.size(); ++i) { @@ -2036,7 +2036,7 @@ static void PatchShader(int shader, int num_reg, int num_tex) Buffer *buf = (Buffer*)buff; if ((val[0] == 0 || val[0] == 0xffffffff)) { - ensureHaveEncoderExceptRender(commandBuffer, Render::EncoderType::Blit); + ensureHaveEncoderExceptRender(commandBuffer, Render::EncoderType::Blit, false, "ClearBuffer"); G_ASSERT(buf->getDynamicOffset() == 0); [blitEncoder fillBuffer : buf->getBuffer() range : NSMakeRange(0, buf->bufSize) @@ -2049,7 +2049,7 @@ static void PatchShader(int shader, int num_reg, int num_tex) stages[STAGE_CS].reset(); current_cs_pipeline = nullptr; } - ensureHaveEncoderExceptRender(commandBuffer, Render::EncoderType::Compute); + ensureHaveEncoderExceptRender(commandBuffer, Render::EncoderType::Compute, false, "ClearBuffer"); if (current_cs_pipeline != clear_cs_pipeline) [computeEncoder setComputePipelineState:clear_cs_pipeline]; @@ -2151,7 +2151,7 @@ static void PatchShader(int shader, int num_reg, int num_tex) { checkRenderAcquired(); - ensureHaveEncoderExceptRender(commandBuffer, Render::EncoderType::Blit); + ensureHaveEncoderExceptRender(commandBuffer, Render::EncoderType::Blit, false, "GenerateMips"); G_ASSERT(tex); [blitEncoder generateMipmapsForTexture : tex->apiTex->texture]; @@ -2192,7 +2192,7 @@ static inline bool is_depth_format(unsigned int f) return; } - ensureHaveEncoderExceptRender(commandBuffer, Render::EncoderType::Blit); + ensureHaveEncoderExceptRender(commandBuffer, Render::EncoderType::Blit, false, "CopyTex"); MTLOrigin origin = { 0, 0, 0 }; MTLSize size = { 1, 1, 1 }; @@ -2257,7 +2257,7 @@ static inline bool is_depth_format(unsigned int f) { checkRenderAcquired(); - ensureHaveEncoderExceptRender(commandBuffer, Render::EncoderType::Blit); + ensureHaveEncoderExceptRender(commandBuffer, Render::EncoderType::Blit, false, "CopyTexRegion"); doTexCopyRegion(region); } @@ -2346,7 +2346,7 @@ static inline bool is_depth_format(unsigned int f) Buffer* dst = (Buffer*)dstb; Buffer* src = (Buffer*)srcb; - ensureHaveEncoderExceptRender(commandBuffer, Render::EncoderType::Blit); + ensureHaveEncoderExceptRender(commandBuffer, Render::EncoderType::Blit, false, "CopyBuffer"); G_ASSERT(dst); G_ASSERTF(dst->getDynamicOffset() == 0, "Buffer %s should have zero dynamic offset, but got %d", dst->getResName(), @@ -3145,7 +3145,7 @@ static void fillAttachment(MTLRenderPassAttachmentDescriptor* desc, const Render { checkRenderAcquired(); - ensureHaveEncoderExceptRender(commandBuffer, Render::EncoderType::Blit); + ensureHaveEncoderExceptRender(commandBuffer, Render::EncoderType::Blit, false, "ReadbackTexture"); MTLSize size = {(uint32_t)w, (uint32_t)h, (uint32_t)d}; MTLOrigin origin = {0, 0, 0}; diff --git a/prog/engine/drv/drv3d_Metal/shadersPreCache.mm b/prog/engine/drv/drv3d_Metal/shadersPreCache.mm index e2eba45ca..9b5ec17a1 100644 --- a/prog/engine/drv/drv3d_Metal/shadersPreCache.mm +++ b/prog/engine/drv/drv3d_Metal/shadersPreCache.mm @@ -762,7 +762,7 @@ static inline void clearCache(const String &path, const String ¤t_cache) [func retain]; #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200 && DAGOR_DBGLEVEL > 0 - func.label = [[NSString alloc] initWithBytes:shader.entry length : strlen(shader.entry) encoding : NSUTF8StringEncoding]; + func.label = [NSString stringWithUTF8String : name.c_str()]; #endif } else @@ -1071,8 +1071,17 @@ static inline void clearCache(const String &path, const String ¤t_cache) return nullptr; } + MTLComputePipelineDescriptor* desc = [[MTLComputePipelineDescriptor alloc] init]; + desc.computeFunction = func; +#if DAGOR_DBGLEVEL > 0 + desc.label = func.label; +#endif + NSError *error = nil; - id csPipeline = [render.device newComputePipelineStateWithFunction : func error : &error]; + id csPipeline = [render.device newComputePipelineStateWithDescriptor : desc + options : MTLPipelineOptionNone + reflection : nil + error : &error]; if (!csPipeline) { D3D_ERROR("Failed to created cs pipeline state, error %s", [[error localizedDescription] UTF8String]); diff --git a/prog/engine/drv/drv3d_commonCode/hangHandler.dshl b/prog/engine/drv/drv3d_commonCode/hangHandler.dshl index 2ed9a7e07..b770c7874 100644 --- a/prog/engine/drv/drv3d_commonCode/hangHandler.dshl +++ b/prog/engine/drv/drv3d_commonCode/hangHandler.dshl @@ -1,5 +1,7 @@ include "shader_global.dshl" +int gpu_hang_uav_no = 7; + shader hang_gpu_cs { supports none; @@ -9,10 +11,12 @@ shader hang_gpu_cs { dont_render; } - - hlsl(cs) { - RWTexture2D< uint > gpu_hang_uav : register(u7); + (cs) { + gpu_hang_uav@uav : register(gpu_hang_uav_no) hlsl { RWTexture2D gpu_hang_uav@uav; } + } + + hlsl(cs) { [numthreads( 32, 32, 1 )] void hang_gpu() { diff --git a/prog/engine/drv/drv3d_vulkan/amdFsrVulkan.cpp b/prog/engine/drv/drv3d_vulkan/amdFsrVulkan.cpp index 94fd392ad..80175cd51 100644 --- a/prog/engine/drv/drv3d_vulkan/amdFsrVulkan.cpp +++ b/prog/engine/drv/drv3d_vulkan/amdFsrVulkan.cpp @@ -173,7 +173,7 @@ class FSRVulkan : public FSR bool isFrameGenerationSupported() const override { return false; } private: - eastl::unique_ptr fsrModule; + DagorDynLibHolder fsrModule; PfnFfxCreateContext createContext = nullptr; PfnFfxDestroyContext destroyContext = nullptr; diff --git a/prog/engine/drv/drv3d_vulkan/backend_interop.h b/prog/engine/drv/drv3d_vulkan/backend_interop.h index 8b453c662..8527ef32a 100644 --- a/prog/engine/drv/drv3d_vulkan/backend_interop.h +++ b/prog/engine/drv/drv3d_vulkan/backend_interop.h @@ -13,6 +13,8 @@ struct BackendInterop std::atomic lastGPUCompletedReplayWorkId{0}; // sync tracker capture request and status std::atomic syncCaptureRequest{0}; + // toggle multi queue submit support in realtime + std::atomic toggleMultiQueueSubmit{0}; }; diff --git a/prog/engine/drv/drv3d_vulkan/d3d/command.cpp b/prog/engine/drv/drv3d_vulkan/d3d/command.cpp index 693aab71e..c688b021c 100644 --- a/prog/engine/drv/drv3d_vulkan/d3d/command.cpp +++ b/prog/engine/drv/drv3d_vulkan/d3d/command.cpp @@ -27,6 +27,7 @@ #include "resource_upload_limit.h" #include "device_context.h" #include "timeline_latency.h" +#include "command.h" #if DAGOR_DBGLEVEL > 0 #include "3d/dag_resourceDump.h" @@ -279,10 +280,10 @@ int d3d::driver_command(Drv3dCommand command, void *par1, void *par2, [[maybe_un case Drv3dCommand::GET_INSTANCE: *(VkInstance *)par1 = drv3d_vulkan::Globals::VK::dev.getInstance().get(); return 1; case Drv3dCommand::GET_PHYSICAL_DEVICE: *(VkPhysicalDevice *)par1 = drv3d_vulkan::Globals::VK::phy.device; return 1; case Drv3dCommand::GET_QUEUE_FAMILY_INDEX: - *(uint32_t *)par1 = drv3d_vulkan::Globals::VK::que[DeviceQueueType::GRAPHICS].getFamily(); + *(uint32_t *)par1 = drv3d_vulkan::Globals::VK::queue[DeviceQueueType::GRAPHICS].getFamily(); return 1; case Drv3dCommand::GET_QUEUE_INDEX: - *(uint32_t *)par1 = drv3d_vulkan::Globals::VK::que[DeviceQueueType::GRAPHICS].getIndex(); + *(uint32_t *)par1 = drv3d_vulkan::Globals::VK::queue[DeviceQueueType::GRAPHICS].getIndex(); return 1; case Drv3dCommand::EXECUTE_FSR: Globals::ctx.executeFSR((amd::FSR *)par1, *(const amd::FSR::UpscalingArgs *)par2); return 1; case Drv3dCommand::MAKE_TEXTURE: @@ -471,6 +472,11 @@ int d3d::driver_command(Drv3dCommand command, void *par1, void *par2, [[maybe_un return 0; #endif } + case Drv3dCommand::CHANGE_QUEUE: + { + d3d_command_change_queue(static_cast((intptr_t)par1)); + return 1; + } default: break; }; diff --git a/prog/engine/drv/drv3d_vulkan/d3d/command.h b/prog/engine/drv/drv3d_vulkan/d3d/command.h new file mode 100644 index 000000000..c63d901ec --- /dev/null +++ b/prog/engine/drv/drv3d_vulkan/d3d/command.h @@ -0,0 +1,13 @@ +// Copyright (C) Gaijin Games KFT. All rights reserved. +#pragma once + +// helper to route commands into more semantic related modules + +#include + +namespace drv3d_vulkan +{ + +void d3d_command_change_queue(GpuPipeline gpu_pipeline); + +} // namespace drv3d_vulkan \ No newline at end of file diff --git a/prog/engine/drv/drv3d_vulkan/d3d/init.cpp b/prog/engine/drv/drv3d_vulkan/d3d/init.cpp index e6a740521..5545f19fc 100644 --- a/prog/engine/drv/drv3d_vulkan/d3d/init.cpp +++ b/prog/engine/drv/drv3d_vulkan/d3d/init.cpp @@ -585,7 +585,7 @@ struct InitCtx if (!device_has_all_required_extensions(Globals::VK::dev, [](const char *name) { logwarn("vulkan: Missing device extension %s", name); })) return reject("some required extensions where not loaded (broken driver)"); - Globals::VK::que = DeviceQueueGroup(Globals::VK::dev, queueGroupInfo); + Globals::VK::queue = DeviceQueueGroup(Globals::VK::dev, queueGroupInfo); initCfg(); initMemory(); diff --git a/prog/engine/drv/drv3d_vulkan/d3d/sync.cpp b/prog/engine/drv/drv3d_vulkan/d3d/sync.cpp index 7f2773011..876bec58d 100644 --- a/prog/engine/drv/drv3d_vulkan/d3d/sync.cpp +++ b/prog/engine/drv/drv3d_vulkan/d3d/sync.cpp @@ -5,9 +5,48 @@ #include "globals.h" #include "global_lock.h" #include "device_context.h" +#include "driver_config.h" +#include "command.h" using namespace drv3d_vulkan; +namespace +{ + +DeviceQueueType gpu_pipeline_to_device_queue_type(GpuPipeline pipe) +{ + if (pipe == GpuPipeline::ASYNC_COMPUTE) + return DeviceQueueType::COMPUTE; + else + return DeviceQueueType::GRAPHICS; +} + +// use alloc less approach for fence handle +// pack replay ID and local frame fence index +struct PrefixedFenceHandle +{ + // underlying type must fit to external + static_assert(sizeof(GPUFENCEHANDLE) >= sizeof(uint32_t)); + static constexpr uint32_t fenceBits = 8; + static constexpr uint32_t fenceMask = (1 << fenceBits) - 1; + static constexpr uint32_t frameMask = ~fenceMask; + + GPUFENCEHANDLE val; + GPUFENCEHANDLE toDriver() { return val; } + uint32_t toIdx() { return val & fenceMask; } + + GPUFENCEHANDLE getThisFramePrefix() { return ((Frontend::replay->id << fenceBits) & frameMask); } + bool verify() { return getThisFramePrefix() == (val & frameMask); } + + PrefixedFenceHandle(uint32_t idx) : val(getThisFramePrefix() | idx) + { + G_ASSERTF(idx < fenceMask, "vulkan: too much user fences per frame, adjust masking"); + } + PrefixedFenceHandle(GPUFENCEHANDLE user_fence) : val(user_fence) {} +}; + +} // anonymous namespace + // TODO: move implementation out of device context class void d3d::resource_barrier(ResourceBarrierDesc desc, GpuPipeline gpu_pipeline /*= GpuPipeline::GRAPHICS*/) @@ -15,3 +54,30 @@ void d3d::resource_barrier(ResourceBarrierDesc desc, GpuPipeline gpu_pipeline /* if (Globals::lock.isAcquired()) Globals::ctx.resourceBarrier(desc, gpu_pipeline); } + +void drv3d_vulkan::d3d_command_change_queue(GpuPipeline gpu_pipeline) +{ + VERIFY_GLOBAL_LOCK_ACQUIRED(); + + Globals::ctx.dispatchCommand({(int)gpu_pipeline_to_device_queue_type(gpu_pipeline)}); +} + +GPUFENCEHANDLE d3d::insert_fence(GpuPipeline gpu_pipeline) +{ + VERIFY_GLOBAL_LOCK_ACQUIRED(); + + uint32_t rawSignalIdx = Frontend::replay->userSignalCount++; + Globals::ctx.dispatchCommand({rawSignalIdx, (int)gpu_pipeline_to_device_queue_type(gpu_pipeline)}); + return PrefixedFenceHandle{rawSignalIdx}.toDriver(); +} + +void d3d::insert_wait_on_fence(GPUFENCEHANDLE &fence, GpuPipeline gpu_pipeline) //-V669 +{ + VERIFY_GLOBAL_LOCK_ACQUIRED(); + PrefixedFenceHandle userFence(fence); + + // old signal from different job! + if (!userFence.verify()) + return; + Globals::ctx.dispatchCommand({userFence.toIdx(), (int)gpu_pipeline_to_device_queue_type(gpu_pipeline)}); +} \ No newline at end of file diff --git a/prog/engine/drv/drv3d_vulkan/d3d/unimplemented.cpp b/prog/engine/drv/drv3d_vulkan/d3d/unimplemented.cpp index 254c873aa..671644e8b 100644 --- a/prog/engine/drv/drv3d_vulkan/d3d/unimplemented.cpp +++ b/prog/engine/drv/drv3d_vulkan/d3d/unimplemented.cpp @@ -40,11 +40,6 @@ void d3d::dispatch_mesh_indirect_count(Sbuffer * /*args*/, uint32_t /*args_strid G_ASSERT_RETURN(!"VK: dispatch_mesh not implemented yet", ); } -// pipe fences - -GPUFENCEHANDLE d3d::insert_fence(GpuPipeline /*gpu_pipeline*/) { return 0; } -void d3d::insert_wait_on_fence(GPUFENCEHANDLE & /*fence*/, GpuPipeline /*gpu_pipeline*/) {} - // multi views bool d3d::setviews(dag::ConstSpan /* viewports */) diff --git a/prog/engine/drv/drv3d_vulkan/debug_ui.cpp b/prog/engine/drv/drv3d_vulkan/debug_ui.cpp index 34c0b1b35..ff7670e41 100644 --- a/prog/engine/drv/drv3d_vulkan/debug_ui.cpp +++ b/prog/engine/drv/drv3d_vulkan/debug_ui.cpp @@ -14,6 +14,8 @@ #include "pipeline/manager.h" #include "device_context.h" #include "execution_timings.h" +#include "backend.h" +#include "backend_interop.h" using namespace drv3d_vulkan; @@ -471,6 +473,14 @@ void drv3d_vulkan::debug_ui_misc() if (ImGui::Button("Switch execution mode")) Globals::ctx.toggleWorkerThread(); + + size_t multiQueueOverride = Backend::interop.toggleMultiQueueSubmit.load(std::memory_order_relaxed); + if (Globals::cfg.bits.allowMultiQueue || multiQueueOverride) + { + ImGui::TextUnformatted(multiQueueOverride % 2 ? "MultiQueueSubmit: no" : "MultiQueueSubmit: yes"); + if (ImGui::Button("Toggle multi queue submit")) + ++Backend::interop.toggleMultiQueueSubmit; + } } #endif diff --git a/prog/engine/drv/drv3d_vulkan/debug_ui_sync.cpp b/prog/engine/drv/drv3d_vulkan/debug_ui_sync.cpp index d37632cdc..c91ee7a49 100644 --- a/prog/engine/drv/drv3d_vulkan/debug_ui_sync.cpp +++ b/prog/engine/drv/drv3d_vulkan/debug_ui_sync.cpp @@ -47,6 +47,7 @@ bool requestCapture = false; bool settleNodes = false; bool requestedCapture = false; bool resetView = false; +bool moveInputsToOutputs = true; struct GraphLayout { @@ -132,6 +133,12 @@ void wnd_header() activeLayout = swapCoord ? xTimeLayout : yTimeLayout; settleNodes = true; } + ImGui::SameLine(); + if (ImGui::Button("Toggle input-to-output move")) + { + moveInputsToOutputs = !moveInputsToOutputs; + settleNodes = true; + } } bool request_capture_data_and_wait() @@ -350,6 +357,7 @@ void settle_nodes() } // move inputs closer to outputs when possible (independant branches, branch join to bigger branch) + if (moveInputsToOutputs) { for (uint32_t l = 0; l < capt.steps.size() * 2; ++l) { @@ -520,7 +528,7 @@ void drv3d_vulkan::debug_ui_sync() for (ExecutionSyncCapture::SyncStep &i : capt.steps) { NodeEditor::BeginNode(i.visNode); - ImGui::Text("Step %u [buffer %u, que %u] %s", i.idx, i.dstBuffer, i.dstQue, i.async ? "async" : ""); + ImGui::Text("Step %u [buffer %u, queue %u]", i.idx, i.dstBuffer, i.dstQue); if (i.invalidOrdering) ImGui::Text("Ordering sorting failed %u", i.invalidOrdering); NodeEditor::BeginPin(i.visBufPin, NodeEditor::PinKind::Output); diff --git a/prog/engine/drv/drv3d_vulkan/device_context.cpp b/prog/engine/drv/drv3d_vulkan/device_context.cpp index 6718ce913..0bdbf6f80 100644 --- a/prog/engine/drv/drv3d_vulkan/device_context.cpp +++ b/prog/engine/drv/drv3d_vulkan/device_context.cpp @@ -570,7 +570,7 @@ void DeviceContext::shutdown() // no more commands can be executed after this point executionMode = ExecutionMode::INVALID; // consume semaphores that noone will wait for anymore - Globals::VK::que[DeviceQueueType::GRAPHICS].consumeWaitSemaphores(Backend::gpuJob.get()); + Globals::VK::queue.consumeWaitSemaphores(Backend::gpuJob.get()); Backend::bindless.shutdown(vkDev); Backend::pipelineCompiler.shutdown(); diff --git a/prog/engine/drv/drv3d_vulkan/device_context/execution_context.cpp b/prog/engine/drv/drv3d_vulkan/device_context/execution_context.cpp index 514a3093d..23685456d 100644 --- a/prog/engine/drv/drv3d_vulkan/device_context/execution_context.cpp +++ b/prog/engine/drv/drv3d_vulkan/device_context/execution_context.cpp @@ -18,6 +18,7 @@ #include "stacked_profile_events.h" #include "predicted_latency_waiter.h" #include "texture.h" +#include using namespace drv3d_vulkan; @@ -205,19 +206,60 @@ void ExecutionContext::imageBarrier(Image *img, ResourceBarrier d3d_barrier, uin } } -void ExecutionContext::switchFrameCore(DeviceQueueType target_queue, bool async) +void ExecutionContext::waitForUploadOnCurrentBuffer() +{ + size_t queueBit = 1 << (uint32_t)frameCoreQueue; + if (queueBit & uploadQueueWaitMask) + return; + + if (transferUploadBuffer) + addQueueDep(transferUploadBuffer, scratch.cmdListsToSubmit.size()); + if (graphicsUploadBuffer) + addQueueDep(graphicsUploadBuffer, scratch.cmdListsToSubmit.size()); + + uploadQueueWaitMask |= queueBit; +} + +void ExecutionContext::waitUserQueueSignal(int idx, DeviceQueueType target_queue) +{ + ExecutionScratch::UserQueueSignal &usignal = scratch.userQueueSignals[idx]; + // already waited for this signal on target queue + if (usignal.waitedOnQueuesMask & (1 << (uint32_t)target_queue)) + return; + addQueueDep(scratch.userQueueSignals[idx].bufferIdx, lastBufferIdxOnQueue[(uint32_t)target_queue]); + // mark waited + usignal.waitedOnQueuesMask |= (1 << (uint32_t)target_queue); +} + +void ExecutionContext::recordUserQueueSignal(int idx, DeviceQueueType target_queue) +{ + G_UNUSED(idx); + G_ASSERTF(scratch.userQueueSignals.size() == idx, "vulkan: back to front queue signal sequencing broken expected %u, got %u", + scratch.userQueueSignals.size(), idx); + scratch.userQueueSignals.push_back({lastBufferIdxOnQueue[(uint32_t)target_queue], 0}); +} + +void ExecutionContext::switchFrameCoreForQueueChange(DeviceQueueType target_queue) { // override any queue to graphics if multi queue is not enabled if (!Globals::cfg.bits.allowMultiQueue) - { target_queue = DeviceQueueType::GRAPHICS; - async = false; - } + // switch buffer only if queue changes + if (frameCoreQueue == target_queue) + return; + + completeSyncForQueueChange(); + switchFrameCore(target_queue); + waitForUploadOnCurrentBuffer(); +} + +void ExecutionContext::switchFrameCore(DeviceQueueType target_queue) +{ // note: first switch will push empty buffer, that is used to replace later on for preFrame - scratch.cmdListsToSubmit.push_back({frameCoreQueue, frameCore, frameCoreAsync, false /*externalWaitPoint*/}); + scratch.cmdListsToSubmit.push_back({frameCoreQueue, frameCore}); frameCoreQueue = target_queue; - frameCoreAsync = async; allocFrameCore(); + lastBufferIdxOnQueue[(uint32_t)target_queue] = scratch.cmdListsToSubmit.size(); } void ExecutionContext::allocFrameCore() @@ -289,7 +331,7 @@ void ExecutionContext::cleanupMemory() { TIME_PROFILE(vulkan_make_syscopy); - switchFrameCore(DeviceQueueType::GRAPHICS, false); + switchFrameCore(DeviceQueueType::GRAPHICS); { WinAutoLock lk(Globals::Mem::mutex); do @@ -323,14 +365,24 @@ void ExecutionContext::cleanupMemory() frameCore = VulkanNullHandle(); } +void ExecutionContext::completeSyncForQueueChange() +{ + if (!Globals::cfg.bits.allowMultiQueue) + return; + + Backend::sync.completeOnQueue(frameCore, vkDev, data.id); +} + void ExecutionContext::prepareFrameCore() { + if (size_t multiQueueOverride = Backend::interop.toggleMultiQueueSubmit.load(std::memory_order_relaxed)) + Globals::cfg.bits.allowMultiQueue = (multiQueueOverride % 2) == 0; + G_ASSERTF(is_null(frameCore), "vulkan: execution context already prepared for command execution"); TIME_PROFILE(vulkan_pre_frame_core); // not tied to command buffer Backend::bindless.advance(); - // queue fork point bool needGraphicsUpload = data.unorderedImageColorClears.size() || data.unorderedImageDepthStencilClears.size() || data.imageUploads.size() || data.unorderedImageCopies.size(); bool needTransferUpload = data.bufferUploads.size() || data.orderedBufferUploads.size(); @@ -338,23 +390,29 @@ void ExecutionContext::prepareFrameCore() if (needGraphicsUpload) { // can't live on transfer queue (or can't always live) and followup queue should be graphics after prepare - switchFrameCore(DeviceQueueType::GRAPHICS, needTransferUpload); + switchFrameCoreForQueueChange(DeviceQueueType::GRAPHICS); writeExectionChekpointNonCommandStream(frameCore, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, MARKER_NCMD_START); flushUnorderedImageColorClears(); flushUnorderedImageDepthStencilClears(); flushImageUploads(); flushUnorderedImageCopies(); + + graphicsUploadBuffer = scratch.cmdListsToSubmit.size(); } if (needTransferUpload) { - switchFrameCore(DeviceQueueType::TRANSFER, true); + switchFrameCoreForQueueChange(DeviceQueueType::TRANSFER); writeExectionChekpointNonCommandStream(frameCore, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, MARKER_NCMD_START_TRANSFER_UPLOAD); flushBufferUploads(frameCore); flushOrderedBufferUploads(frameCore); + + transferUploadBuffer = scratch.cmdListsToSubmit.size(); } - // join point or initial frame core allocation - switchFrameCore(DeviceQueueType::GRAPHICS, false); + + uploadQueueWaitMask = 0; + switchFrameCoreForQueueChange(DeviceQueueType::GRAPHICS); + writeExectionChekpointNonCommandStream(frameCore, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, MARKER_NCMD_TIMESTAMPS_RESET_QUEUE_READBACKS); data.timestampQueryBlock->ensureSizesAndResetStatus(frameCore); @@ -672,89 +730,229 @@ void ExecutionContext::flushPostFrameCommands() writeExectionChekpointNonCommandStream(postFrame, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, MARKER_NCMD_FRAME_END_SYNC); } -void ExecutionContext::enqueueCommandListsToMultipleQueues(ThreadedFence *fence) +void ExecutionContext::stackUpCommandBuffers() { FrameInfo &frame = Backend::gpuJob.get(); - - uint32_t submitOrder = 0; - DeviceQueueType activeQue = DeviceQueueType::INVALID; - bool activeQueList[(uint32_t)DeviceQueueType::COUNT] = {}; - bool activeAsync = false; + DeviceQueueType activeQueue = DeviceQueueType::INVALID; + int32_t lastSubmitsOnQueues[(uint32_t)DeviceQueueType::COUNT] = {}; + for (int32_t &i : lastSubmitsOnQueues) + i = -1; + int32_t submitIdx = 0; for (ExecutionScratch::CommandBufferSubmit &i : scratch.cmdListsToSubmit) { + // ignore empty buffers, that faciliate optional reordered commands if (is_null(i.handle)) continue; - if (activeQue != i.queue || activeAsync != i.async) - scratch.submitGraph.push_back({{}, {}, i.queue, i.async && (activeAsync == i.async) ? submitOrder : ++submitOrder, false}); - activeQue = i.queue; - activeAsync = i.async; - scratch.submitGraph.back().cbs.push_back(i.handle); - scratch.submitGraph.back().fenceWait |= i.externalWaitPoint; + // any queue change or signal/wait is candidate for separate queue submit + // in some cases we can continue "old" submit to previously seen queue, to avoid useless waits + if ((activeQueue != i.queue) || i.signals || i.waits || submitIdx < 0) + { + // if we don't wait on this buffer, we can append to last submit after switching queues + if (i.waits == 0 && lastSubmitsOnQueues[(uint32_t)i.queue] >= 0) + { + submitIdx = lastSubmitsOnQueues[(uint32_t)i.queue]; + // patch data for dep logic + scratch.submitGraph[submitIdx].originalSignalId = (uint32_t)(&i - scratch.cmdListsToSubmit.begin()); + } + else + { + submitIdx = scratch.submitGraph.size(); + lastSubmitsOnQueues[(uint32_t)i.queue] = submitIdx; + scratch.submitGraph.push_back({{}, {}, {}, 0, i.queue, (uint32_t)(&i - scratch.cmdListsToSubmit.begin()), + (uint32_t)(&i - scratch.cmdListsToSubmit.begin()), false}); + } + } + activeQueue = i.queue; + scratch.submitGraph[submitIdx].cbs.push_back(i.handle); + // if queue submit signals something, we can't add more buffers after that + // because it will break following waits on other queues (will happen too late) + G_ASSERTF(scratch.submitGraph[submitIdx].signalsCount == 0, + "vulkan: queue submit item should contain zero signals on append to it!"); + scratch.submitGraph[submitIdx].signalsCount += i.signals; + // if we signal, we can't append followup buffers + if (i.signals) + { + lastSubmitsOnQueues[(uint32_t)i.queue] = -1; + submitIdx = -1; + } } - StaticTab frameJoinPoints; - DeviceQueueType fenceWaitQue = DeviceQueueType::INVALID; + // last submit should happen with fence, due to overall restrictions of driver + // completed fence = completed anything for user perspective + scratch.submitGraph.back().fenceWait = true; + // fill signals buffer ahead of time for (ExecutionScratch::QueueSubmitItem &i : scratch.submitGraph) + for (int j = 0; j < i.signalsCount; ++j) + i.signals.push_back(frame.allocSemaphore(Globals::VK::dev)); +} + +void ExecutionContext::sortAndCountDependencies() +{ + eastl::sort(scratch.cmdListsSubmitDeps.begin(), scratch.cmdListsSubmitDeps.end(), + [](const ExecutionScratch::CommandBufferSubmitDeps &l, const ExecutionScratch::CommandBufferSubmitDeps &r) // + { return l.from < r.from; }); + + for (ExecutionScratch::CommandBufferSubmitDeps &i : scratch.cmdListsSubmitDeps) + { + ++scratch.cmdListsToSubmit[i.from].signals; + ++scratch.cmdListsToSubmit[i.to].waits; + } +} + +// next gpu job should start after prev gpu job last work item +// track and put semaphores for all active queues on this frame to guarantie that +// otherwise gpu jobs can overlap +struct FrameEndQueueJoin +{ + eastl::bitset<(uint32_t)DeviceQueueType::COUNT> activeQueueList; + uint32_t frameJoinPoints = 0; + DeviceQueueType fenceWaitQueue = DeviceQueueType::INVALID; + + void markActiveQueue(DeviceQueueType queue) { activeQueueList.set(static_cast(queue)); } + + void addSignals(ExecutionScratch::QueueSubmitItem &target) { - i.semaphore.push_back(frame.allocSemaphore(vkDev)); + G_ASSERTF(frameJoinPoints == 0, "vulkan: frame joint points already populated, should not happen twice"); + FrameInfo &frame = Backend::gpuJob.get(); + frameJoinPoints = activeQueueList.count(); + for (uint32_t i = 0; i < frameJoinPoints; ++i) + target.signals.push_back(frame.allocSemaphore(Globals::VK::dev)); + fenceWaitQueue = target.queue; + } - bool consumedOn[(int)DeviceQueueType::COUNT] = {}; - for (ExecutionScratch::QueueSubmitItem &j : scratch.submitGraph) + void addWaits(ExecutionScratch::QueueSubmitItem &target) + { + if (frameJoinPoints) { - if (j.order > i.order && i.que != j.que && !consumedOn[(int)j.que]) + // check for double wait or mismatch somewhere + G_ASSERTF(frameJoinPoints == target.signals.size(), + "vulkan: mismatched signals size %u vs %u, should be equal to added one in add signals", frameJoinPoints, + target.signals.size()); + for (uint32_t i : LsbVisitor{activeQueueList.to_uint32()}) { - i.semaphore.push_back(frame.allocSemaphore(vkDev)); - Globals::VK::que[j.que].addSubmitSemaphore(i.semaphore.back(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); - consumedOn[(int)j.que] = true; + G_ASSERTF(!target.signals.empty(), "vulkan: frame queue join signaled more than it supposed to"); + Globals::VK::queue[static_cast(i)].addSubmitSemaphore(target.signals.back(), + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); + target.signals.pop_back(); } } + } +}; + +void ExecutionContext::enqueueCommandListsToMultipleQueues(ThreadedFence *fence) +{ + TIME_PROFILE(vulkan_queue_submits); + FrameInfo &frame = Backend::gpuJob.get(); + + // sum up waits and signals for each buffer submit and sort dependencies to reduce complexity of submit logic + sortAndCountDependencies(); + // generate queue submits, consisting of continous block of command lists + // while following dependencies + stackUpCommandBuffers(); + + FrameEndQueueJoin queueJoin; + ExecutionScratch::CommandBufferSubmitDeps *depPtr = scratch.cmdListsSubmitDeps.begin(); + // NOTE: this logic will fail if earlier submit wants sync to later submit, hopefully triggering some of assert checks + for (ExecutionScratch::QueueSubmitItem &i : scratch.submitGraph) + { + queueJoin.markActiveQueue(i.queue); if (fence && i.fenceWait) - { - for (uint32_t j = (uint32_t)DeviceQueueType::ZERO; j < (uint32_t)DeviceQueueType::COUNT; ++j) - { - if (!activeQueList[j] || static_cast(j) == i.que) - continue; - i.semaphore.push_back(frame.allocSemaphore(vkDev)); - frameJoinPoints.push_back(i.semaphore.back()); - } - } + queueJoin.addSignals(i); DeviceQueue::TrimmedSubmitInfo si = {}; si.pCommandBuffers = ary(i.cbs.data()); si.commandBufferCount = i.cbs.size(); - si.pSignalSemaphores = ary(i.semaphore.data()); - si.signalSemaphoreCount = i.semaphore.size(); - activeQueList[static_cast(i.que)] |= true; + si.pSignalSemaphores = ary(i.signals.data()); + si.signalSemaphoreCount = i.signals.size(); + + // add submit semaphores from buffer because wait can happen after other submits on same queue + for (VulkanSemaphoreHandle j : i.submitSemaphores) + Globals::VK::queue[i.queue].addSubmitSemaphore(j, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); + if (fence && i.fenceWait) { - Globals::VK::que[i.que].submit(vkDev, frame, si, fence->get()); + Globals::VK::queue[i.queue].submit(vkDev, frame, si, fence->get()); fence->setAsSubmited(); - fenceWaitQue = i.que; } else - { - Globals::VK::que[i.que].submit(vkDev, frame, si); - } + Globals::VK::queue[i.queue].submit(vkDev, frame, si); - // affects next submit - Globals::VK::que[i.que].addSubmitSemaphore(i.semaphore[0], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); - } - - // join queues on frame end - if (frameJoinPoints.size()) - { - for (uint32_t j = (uint32_t)DeviceQueueType::ZERO; j < (uint32_t)DeviceQueueType::COUNT; ++j) + ExecutionScratch::CommandBufferSubmitDeps *depRangeRestart = nullptr; + // add submit semaphores for related dst deps, using dynamic loop ranges + while (depPtr < scratch.cmdListsSubmitDeps.end()) { - if (!activeQueList[j] || static_cast(j) == fenceWaitQue || frameJoinPoints.empty()) + if (depPtr->from != i.originalSignalId) + { + if (!depRangeRestart) + depRangeRestart = depPtr; + ++depPtr; continue; - Globals::VK::que[static_cast(j)].addSubmitSemaphore(frameJoinPoints.back(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); - frameJoinPoints.pop_back(); + } + ExecutionScratch::QueueSubmitItem *k = &i; + ++k; + while (k < scratch.submitGraph.end()) + { + if (k->originalWaitId != depPtr->to) + { + ++k; + continue; + } + k->submitSemaphores.push_back(i.signals.back()); + i.signals.pop_back(); + if (i.signals.empty()) + break; + ++k; + } + ++depPtr; } + // submits merged over queue switch, restart search range as it can "skip" some deps + if (depRangeRestart) + depPtr = depRangeRestart; + // join queues on frame end + // NOTE: specially inside loop, to avoid leaving some work "floating" somewhere after fence + queueJoin.addWaits(i); + // all signals on this submit must be used for related waits, otherwise something is broken + G_ASSERTF(i.signals.empty(), "vulkan: some signals are not consumed!"); } - scratch.submitGraph.clear(); + scratch.cmdListsSubmitDeps.clear(); + scratch.cmdListsToSubmit.clear(); + scratch.userQueueSignals.clear(); +} + +void ExecutionContext::addQueueDep(uint32_t src_submit, uint32_t dst_submit) +{ + // nothing to wait in this case + if (src_submit == 0 || dst_submit == 0) + return; + G_ASSERTF(src_submit != dst_submit, "vulkan: wrong dependency between queues detected src equal dst %u == %u", src_submit, + dst_submit); + scratch.cmdListsSubmitDeps.push_back({src_submit, dst_submit}); +} + +void ExecutionContext::joinQueuesToSubmitFence() +{ + // all buffers that we used on gpu job, must be completed after fence wait + // to make sure of this + // add dependency for each final command buffer on every unique queue where we never "joined" workloads + for (uint32_t i : lastBufferIdxOnQueue) + { + // queue was fully inactive + if (!i) + continue; + // last queues buffer is one we will wait with fence + if (i == (scratch.cmdListsToSubmit.size() - 1)) + continue; + // last buffer signals semaphore that is waited for someone + bool signaling = false; + for (ExecutionScratch::CommandBufferSubmitDeps &j : scratch.cmdListsSubmitDeps) + signaling |= j.from == i; + if (signaling) + continue; + addQueueDep(i, scratch.cmdListsToSubmit.size() - 1); + } } void ExecutionContext::flush(ThreadedFence *fence) @@ -776,10 +974,16 @@ void ExecutionContext::flush(ThreadedFence *fence) scratch.cmdListsToSubmit[0].handle = preFrame; } - + // transfer queue is very limited, not fitting for all post frame commands + // splitting it into different submits is also non effective + // so live on graphics, but with "split" for possible end frame overlapping + switchFrameCore(DeviceQueueType::GRAPHICS); flushPostFrameCommands(); // no more command buffers after this point! so push last active one in list to submit - scratch.cmdListsToSubmit.push_back({frameCoreQueue, frameCore, frameCoreAsync, true /*externalWaitPoint*/}); + scratch.cmdListsToSubmit.push_back({frameCoreQueue, frameCore}); + + // if work diverged around frame end, must sync it to ensure buffers are completed before fence wait + joinQueuesToSubmitFence(); // finalize command buffers for (ExecutionScratch::CommandBufferSubmit &i : scratch.cmdListsToSubmit) @@ -789,7 +993,6 @@ void ExecutionContext::flush(ThreadedFence *fence) } enqueueCommandListsToMultipleQueues(fence); - scratch.cmdListsToSubmit.clear(); onFrameCoreReset(); Backend::gpuJob.get().pendingTimestamps = data.timestampQueryBlock; Backend::gpuJob.get().replayId = data.id; @@ -1530,7 +1733,7 @@ bool ExecutionContext::interruptFrameCore() Backend::State::exec.set(ActiveExecutionStage::CUSTOM); applyStateChanges(); - switchFrameCore(DeviceQueueType::GRAPHICS, false); + switchFrameCore(frameCoreQueue); onFrameCoreReset(); return true; diff --git a/prog/engine/drv/drv3d_vulkan/device_context/render_pass.cpp b/prog/engine/drv/drv3d_vulkan/device_context/render_pass.cpp index 40894b552..8d1f2e7d8 100644 --- a/prog/engine/drv/drv3d_vulkan/device_context/render_pass.cpp +++ b/prog/engine/drv/drv3d_vulkan/device_context/render_pass.cpp @@ -304,6 +304,9 @@ void ExecutionContext::nativeRenderPassChanged() void ExecutionContext::performSyncToPreviousCommandList() { + // reorder should not cross queue boundaries, should be guarantied via buffer interruption, but that's weak + // so ensure everything is ok via assert + G_ASSERTF(scratch.cmdListsToSubmit.back().queue == frameCoreQueue, "vulkan: reordering barriers over different queues"); // When recording commands of a pass, we need to place barriers before // the current render pass. This is achieved by splitting the command // list and recording the pass commands into a new list, but submitting @@ -318,7 +321,7 @@ void ExecutionContext::interruptFrameCoreForRenderPassStart() return; // called from applyStateChanges, so front is processed and back graphics is forced to be applied via setDirty // i.e. after cmd buffer switch all state should be reapplied properly - switchFrameCore(DeviceQueueType::GRAPHICS, false); + switchFrameCore(frameCoreQueue); // only non re-applied state is one we don't track with tracked state approach // invalidate them by hand Backend::State::exec.set({}); diff --git a/prog/engine/drv/drv3d_vulkan/device_context_cmd.inc b/prog/engine/drv/drv3d_vulkan/device_context_cmd.inc index 847ed73ae..8ba52ecaa 100644 --- a/prog/engine/drv/drv3d_vulkan/device_context_cmd.inc +++ b/prog/engine/drv/drv3d_vulkan/device_context_cmd.inc @@ -1362,4 +1362,47 @@ VULKAN_BEGIN_CONTEXT_COMMAND(DelaySyncCompletion) ctx.performSyncToPreviousCommandList(); } #endif -VULKAN_END_CONTEXT_COMMAND \ No newline at end of file +VULKAN_END_CONTEXT_COMMAND + +VULKAN_BEGIN_CONTEXT_COMMAND(QueueSwitch) + VULKAN_CONTEXT_COMMAND_PARAM(int, queue) +#if VULKAN_CONTEXT_COMMAND_IMPLEMENTATION + if (!Globals::cfg.bits.allowMultiQueue) + return; + if ((int)ctx.frameCoreQueue == queue) + return; + + VulkanCommandBufferHandle frameCoreOld = ctx.frameCore; + ctx.beginCustomStage("QueueSwitch"); + G_UNUSED(frameCoreOld); + G_ASSERTF(frameCoreOld == ctx.frameCore, "vulkan: should have not interrupted frame core here!"); + ctx.switchFrameCoreForQueueChange((DeviceQueueType)queue); + ctx.onFrameCoreReset(); +#endif +VULKAN_END_CONTEXT_COMMAND + +VULKAN_BEGIN_CONTEXT_COMMAND(QueueSignal) + VULKAN_CONTEXT_COMMAND_PARAM(uint32_t, signalIdx) + VULKAN_CONTEXT_COMMAND_PARAM(int, queue) +#if VULKAN_CONTEXT_COMMAND_IMPLEMENTATION + if (!Globals::cfg.bits.allowMultiQueue) + return; + ctx.recordUserQueueSignal(signalIdx, (DeviceQueueType)queue); +#endif +VULKAN_END_CONTEXT_COMMAND + +VULKAN_BEGIN_CONTEXT_COMMAND(QueueWait) + VULKAN_CONTEXT_COMMAND_PARAM(uint32_t, signalIdx) + VULKAN_CONTEXT_COMMAND_PARAM(int, queue) +#if VULKAN_CONTEXT_COMMAND_IMPLEMENTATION + if (!Globals::cfg.bits.allowMultiQueue) + return; + + // interrupt command buffer on wait, to avoid waiting for previous work together with next work + VulkanCommandBufferHandle frameCoreOld = ctx.frameCore; + ctx.beginCustomStage("QueueWait"); + if (frameCoreOld == ctx.frameCore) + ctx.interruptFrameCore(); + ctx.waitUserQueueSignal(signalIdx, (DeviceQueueType)queue); +#endif +VULKAN_END_CONTEXT_COMMAND diff --git a/prog/engine/drv/drv3d_vulkan/device_queue.cpp b/prog/engine/drv/drv3d_vulkan/device_queue.cpp index fd2ae88a4..606643297 100644 --- a/prog/engine/drv/drv3d_vulkan/device_queue.cpp +++ b/prog/engine/drv/drv3d_vulkan/device_queue.cpp @@ -25,6 +25,7 @@ const char *queue_type_to_name(DeviceQueueType type) case DeviceQueueType::GRAPHICS: return "graphics"; case DeviceQueueType::COMPUTE: return "compute"; case DeviceQueueType::TRANSFER: return "transfer"; + case DeviceQueueType::ASYNC_GRAPHICS: return "async graphics"; default: break; } return ""; @@ -56,7 +57,8 @@ VkQueueFlags get_queue_flags_for_type(DeviceQueueType type) { switch (type) { - case DeviceQueueType::GRAPHICS: return VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT; + case DeviceQueueType::GRAPHICS: + case DeviceQueueType::ASYNC_GRAPHICS: return VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT; case DeviceQueueType::COMPUTE: return VK_QUEUE_COMPUTE_BIT; case DeviceQueueType::TRANSFER: return VK_QUEUE_TRANSFER_BIT; default: break; @@ -72,6 +74,7 @@ DeviceQueueType get_fallback_for(DeviceQueueType type) switch (type) { case DeviceQueueType::GRAPHICS: return DeviceQueueType::INVALID; + case DeviceQueueType::ASYNC_GRAPHICS: case DeviceQueueType::COMPUTE: return DeviceQueueType::GRAPHICS; case DeviceQueueType::TRANSFER: return DeviceQueueType::COMPUTE; default: break; diff --git a/prog/engine/drv/drv3d_vulkan/device_queue.h b/prog/engine/drv/drv3d_vulkan/device_queue.h index fc5881eb6..49bfee8e8 100644 --- a/prog/engine/drv/drv3d_vulkan/device_queue.h +++ b/prog/engine/drv/drv3d_vulkan/device_queue.h @@ -4,22 +4,13 @@ #include #include "vulkan_device.h" +#include "driver.h" namespace drv3d_vulkan { struct FrameInfo; -enum class DeviceQueueType -{ - GRAPHICS, - COMPUTE, - TRANSFER, - - COUNT, - INVALID = COUNT, - ZERO = GRAPHICS -}; class DeviceQueue { WinCritSec mutex; @@ -28,8 +19,8 @@ class DeviceQueue uint32_t index = -1; uint32_t timestampBits = 0; - StaticTab submitSemaphores; - StaticTab submitSemaphoresLocation; + Tab submitSemaphores; + Tab submitSemaphoresLocation; void clearSubmitSemaphores() { @@ -123,6 +114,11 @@ class DeviceQueueGroup DeviceQueueGroup(VulkanDevice &device, const Info &info); inline DeviceQueue &operator[](DeviceQueueType type) { return *group[static_cast(type)]; } inline const DeviceQueue &operator[](DeviceQueueType type) const { return *group[static_cast(type)]; } + void consumeWaitSemaphores(FrameInfo &gpu_frame) + { + for (DeviceQueue *i : group) + i->consumeWaitSemaphores(gpu_frame); + } }; inline bool operator==(DeviceQueueGroup::Info::Queue l, DeviceQueueGroup::Info::Queue r) diff --git a/prog/engine/drv/drv3d_vulkan/driver.h b/prog/engine/drv/drv3d_vulkan/driver.h index 82e0b6b47..be0adf9fa 100644 --- a/prog/engine/drv/drv3d_vulkan/driver.h +++ b/prog/engine/drv/drv3d_vulkan/driver.h @@ -52,6 +52,18 @@ enum class ActiveExecutionStage #endif }; +enum class DeviceQueueType +{ + GRAPHICS, + COMPUTE, + TRANSFER, + ASYNC_GRAPHICS, + + COUNT, + INVALID = COUNT, + ZERO = GRAPHICS +}; + #if D3D_HAS_RAY_TRACING #define STAGE_MAX_ACTIVE STAGE_MAX_EXT #else diff --git a/prog/engine/drv/drv3d_vulkan/driver_config.cpp b/prog/engine/drv/drv3d_vulkan/driver_config.cpp index ec66fbd4e..708d21918 100644 --- a/prog/engine/drv/drv3d_vulkan/driver_config.cpp +++ b/prog/engine/drv/drv3d_vulkan/driver_config.cpp @@ -94,7 +94,7 @@ void DriverConfig::fillConfigBits(const DataBlock *cfg) void DriverConfig::fillDeviceBits() { has.gpuTimestamps = !(Globals::VK::phy.properties.limits.timestampComputeAndGraphics == VK_FALSE || - Globals::VK::que[DeviceQueueType::GRAPHICS].getTimestampBits() < 1); + Globals::VK::queue[DeviceQueueType::GRAPHICS].getTimestampBits() < 1); has.fragmentShaderUAV = VK_FALSE != Globals::VK::phy.features.fragmentStoresAndAtomics; has.depthBoundsTest = VK_FALSE != Globals::VK::phy.features.depthBounds; has.anisotropicSampling = VK_FALSE != Globals::VK::phy.features.samplerAnisotropy; diff --git a/prog/engine/drv/drv3d_vulkan/execution_context.h b/prog/engine/drv/drv3d_vulkan/execution_context.h index a887dd45d..7d44b6f53 100644 --- a/prog/engine/drv/drv3d_vulkan/execution_context.h +++ b/prog/engine/drv/drv3d_vulkan/execution_context.h @@ -67,7 +67,6 @@ class ExecutionContext VulkanCommandBufferHandle frameCore = VulkanHandle(); DeviceQueueType frameCoreQueue = DeviceQueueType::INVALID; - bool frameCoreAsync = false; typedef ContextedPipelineBarrier PrimaryPipelineBarrier; typedef ContextedPipelineBarrier SecondaryPipelineBarrier; @@ -79,11 +78,20 @@ class ExecutionContext void reportMissingPipelineComponent(const char *component); void queueImageResidencyRestore(Image *img); void writeExectionChekpoint(VulkanCommandBufferHandle cb, VkPipelineStageFlagBits stage); + void recordUserQueueSignal(int idx, DeviceQueueType target_queue); + void waitUserQueueSignal(int idx, DeviceQueueType target_queue); private: // temporal "pooled" contents static ExecutionScratch scratch; + size_t lastBufferIdxOnQueue[(uint32_t)DeviceQueueType::COUNT] = {}; + // upload mutliqueue deps + size_t transferUploadBuffer = 0; + size_t graphicsUploadBuffer = 0; + size_t uploadQueueWaitMask = ~0; + void waitForUploadOnCurrentBuffer(); + void finishAllGPUWorkItems(); enum { @@ -123,6 +131,10 @@ class ExecutionContext void flushUnorderedImageCopies(); void flushUploads(); void flushPostFrameCommands(); + + void stackUpCommandBuffers(); + void sortAndCountDependencies(); + void joinQueuesToSubmitFence(); void enqueueCommandListsToMultipleQueues(ThreadedFence *fence); void printMemoryStatistics(); @@ -130,14 +142,12 @@ class ExecutionContext void applyStateChanges(); void applyQueuedDiscards(); - void switchFrameCore(DeviceQueueType target_queue, bool async); - void onFrameCoreReset(); - #if VULKAN_VALIDATION_COLLECT_CALLER > 0 static thread_local ExecutionContext *tlsDbgActiveInstance; #endif public: + void addQueueDep(uint32_t src_submit, uint32_t dst_submit); ExecutionContext() = delete; ~ExecutionContext(); ExecutionContext(const ExecutionContext &) = delete; @@ -157,6 +167,10 @@ class ExecutionContext void endCmd(); FramebufferState &getFramebufferState(); + void completeSyncForQueueChange(); + void switchFrameCoreForQueueChange(DeviceQueueType target_queue); + void switchFrameCore(DeviceQueueType target_queue); + void onFrameCoreReset(); // processes out-of-order parts of frame that can affect orderd frame void prepareFrameCore(); void flush(ThreadedFence *fence); diff --git a/prog/engine/drv/drv3d_vulkan/execution_markers.cpp b/prog/engine/drv/drv3d_vulkan/execution_markers.cpp index 501f0a86b..38eae423a 100644 --- a/prog/engine/drv/drv3d_vulkan/execution_markers.cpp +++ b/prog/engine/drv/drv3d_vulkan/execution_markers.cpp @@ -83,7 +83,7 @@ void ExecutionMarkers::check() VulkanDevice &vkDev = Globals::VK::dev; if (vkDev.hasExtension()) { - VulkanQueueHandle grQueue = Globals::VK::que[DeviceQueueType::GRAPHICS].getHandle(); + VulkanQueueHandle grQueue = Globals::VK::queue[DeviceQueueType::GRAPHICS].getHandle(); debug("Checking execution makers - VK_NV_device_diagnostic_checkpoints:"); debug("Next id would be: %08lX", commandIndex); diff --git a/prog/engine/drv/drv3d_vulkan/execution_scratch.h b/prog/engine/drv/drv3d_vulkan/execution_scratch.h index 49833a27e..8ca2a9a88 100644 --- a/prog/engine/drv/drv3d_vulkan/execution_scratch.h +++ b/prog/engine/drv/drv3d_vulkan/execution_scratch.h @@ -32,20 +32,37 @@ struct ExecutionScratch { DeviceQueueType queue; VulkanCommandBufferHandle handle; - bool async; - bool externalWaitPoint; + uint32_t signals; + uint32_t waits; }; eastl::vector cmdListsToSubmit; + struct CommandBufferSubmitDeps + { + uint32_t from; + uint32_t to; + }; + eastl::vector cmdListsSubmitDeps; + struct QueueSubmitItem { Tab cbs; - StaticTab semaphore; - DeviceQueueType que; - uint32_t order; + Tab signals; + Tab submitSemaphores; + uint32_t signalsCount; + DeviceQueueType queue; + uint32_t originalSignalId; + uint32_t originalWaitId; bool fenceWait; }; Tab submitGraph; + + struct UserQueueSignal + { + size_t bufferIdx; + uint8_t waitedOnQueuesMask; + }; + eastl::vector userQueueSignals; }; } // namespace drv3d_vulkan diff --git a/prog/engine/drv/drv3d_vulkan/execution_sync.cpp b/prog/engine/drv/drv3d_vulkan/execution_sync.cpp index c1bca3ff0..e9d3cf813 100644 --- a/prog/engine/drv/drv3d_vulkan/execution_sync.cpp +++ b/prog/engine/drv/drv3d_vulkan/execution_sync.cpp @@ -504,6 +504,13 @@ void ExecutionSyncTracker::clearOps() #endif } +void ExecutionSyncTracker::completeOnQueue(VulkanCommandBufferHandle cmd_buffer, const VulkanDevice &dev, size_t gpu_work_id) +{ + completeNeeded(cmd_buffer, dev); + G_ASSERTF(!delayCompletion, "vulkan: sync delay must not be interrupted by GPU job change"); + + workItemEndBarrier(cmd_buffer, dev, gpu_work_id); +} void ExecutionSyncTracker::completeAll(VulkanCommandBufferHandle cmd_buffer, const VulkanDevice &dev, size_t gpu_work_id) { @@ -515,6 +522,13 @@ void ExecutionSyncTracker::completeAll(VulkanCommandBufferHandle cmd_buffer, con OpUid::frame_end(); Backend::syncCapture.reset(); + workItemEndBarrier(cmd_buffer, dev, gpu_work_id); + + nativeRPIndex = 0; +} + +void ExecutionSyncTracker::workItemEndBarrier(VulkanCommandBufferHandle cmd_buffer, const VulkanDevice &dev, size_t gpu_work_id) +{ if (allCompleted()) { clearOps(); @@ -589,8 +603,6 @@ void ExecutionSyncTracker::completeAll(VulkanCommandBufferHandle cmd_buffer, con barrier.submit(cmd_buffer); clearOps(); - - nativeRPIndex = 0; } bool ExecutionSyncTracker::anyNonProcessed() diff --git a/prog/engine/drv/drv3d_vulkan/execution_sync.h b/prog/engine/drv/drv3d_vulkan/execution_sync.h index afdd7cf88..be5a28629 100644 --- a/prog/engine/drv/drv3d_vulkan/execution_sync.h +++ b/prog/engine/drv/drv3d_vulkan/execution_sync.h @@ -371,11 +371,13 @@ class ExecutionSyncTracker void completeNeeded(VulkanCommandBufferHandle cmd_buffer, const VulkanDevice &dev); void completeAll(VulkanCommandBufferHandle cmd_buffer, const VulkanDevice &dev, size_t gpu_work_id); + void completeOnQueue(VulkanCommandBufferHandle cmd_buffer, const VulkanDevice &dev, size_t gpu_work_id); bool anyNonProcessed(); bool allCompleted(); void aliasSync(Resource *lobj, VkPipelineStageFlags stage); private: + void workItemEndBarrier(VulkanCommandBufferHandle cmd_buffer, const VulkanDevice &dev, size_t gpu_work_id); void addImageAccessImpl(LogicAddress laddr, Image *img, VkImageLayout layout, ImageArea area, bool nrp_attachment, bool discard); void clearOps(); diff --git a/prog/engine/drv/drv3d_vulkan/execution_sync_capture.cpp b/prog/engine/drv/drv3d_vulkan/execution_sync_capture.cpp index 19729a9eb..826e82cc5 100644 --- a/prog/engine/drv/drv3d_vulkan/execution_sync_capture.cpp +++ b/prog/engine/drv/drv3d_vulkan/execution_sync_capture.cpp @@ -15,9 +15,8 @@ void ExecutionSyncCapture::addSyncStep() currentLocalSyncStepOpIdx = 0; DeviceQueueType syncStepQueue = Backend::State::exec.getExecutionContext().frameCoreQueue; steps.push_back({currentVisNode++, currentVisPin++, currentVisPin++, Backend::sync.getCaller(), - Backend::gpuJob->commandBuffers[syncStepQueue].pendingCommandBuffers.size(), (uint32_t)syncStepQueue, - Backend::State::exec.getExecutionContext().frameCoreAsync, currentSyncStep, 0, currentVisPin++, currentVisPin++, currentVisPin++, - 0, 0, 0}); + Backend::gpuJob->commandBuffers[syncStepQueue].pendingCommandBuffers.size(), (uint32_t)syncStepQueue, currentSyncStep, 0, + currentVisPin++, currentVisPin++, currentVisPin++, 0, 0, 0}); currentSyncStep++; } void ExecutionSyncCapture::addOp(ExecutionSyncTracker::OpUid uid, LogicAddress laddr, Resource *res, diff --git a/prog/engine/drv/drv3d_vulkan/execution_sync_capture.h b/prog/engine/drv/drv3d_vulkan/execution_sync_capture.h index 0f50dbd88..1526783fc 100644 --- a/prog/engine/drv/drv3d_vulkan/execution_sync_capture.h +++ b/prog/engine/drv/drv3d_vulkan/execution_sync_capture.h @@ -19,7 +19,6 @@ struct ExecutionSyncCapture ExecutionSyncTracker::OpCaller caller; uint32_t dstBuffer; uint32_t dstQue; - bool async; uint32_t idx; uint32_t visIndepSeq; uint32_t visIdepSeqPin; diff --git a/prog/engine/drv/drv3d_vulkan/frame_info.cpp b/prog/engine/drv/drv3d_vulkan/frame_info.cpp index 82114046e..66b322ccf 100644 --- a/prog/engine/drv/drv3d_vulkan/frame_info.cpp +++ b/prog/engine/drv/drv3d_vulkan/frame_info.cpp @@ -14,11 +14,12 @@ using namespace drv3d_vulkan; -void FrameInfo::QueueCommandBuffers::init(DeviceQueueType queue) +void FrameInfo::QueueCommandBuffers::init(DeviceQueueType target_queue) { VulkanDevice &vkDev = Globals::VK::dev; + queue = target_queue; - uint32_t cmdQFamily = Globals::VK::que[queue].getFamily(); + uint32_t cmdQFamily = Globals::VK::queue[queue].getFamily(); bool resetCmdPool = Globals::cfg.bits.resetCommandPools; VkCommandPoolCreateInfo cpci; @@ -54,7 +55,7 @@ VulkanCommandBufferHandle FrameInfo::QueueCommandBuffers::allocateCommandBuffer( if (Globals::cfg.debugLevel > 0) Globals::Dbg::naming.setCommandBufferName(cmd, - String(32, "Frame %u Pending order %u", Backend::gpuJob->index, pendingCommandBuffers.size())); + String(64, "Frame %u Pending order %u Queue %u", Backend::gpuJob->index, pendingCommandBuffers.size(), (uint32_t)queue)); return cmd; } @@ -109,7 +110,7 @@ void FrameInfo::CommandBuffersGroup::init() { if (Globals::cfg.bits.allowMultiQueue) { - for (uint32_t i = (uint32_t)DeviceQueueType::ZERO; i < (uint32_t)DeviceQueueType::COUNT; ++i) + for (uint32_t i = 0; i < (uint32_t)DeviceQueueType::COUNT; ++i) group[i].init(static_cast(i)); } else diff --git a/prog/engine/drv/drv3d_vulkan/frame_info.h b/prog/engine/drv/drv3d_vulkan/frame_info.h index 6323d2ec6..623ee3241 100644 --- a/prog/engine/drv/drv3d_vulkan/frame_info.h +++ b/prog/engine/drv/drv3d_vulkan/frame_info.h @@ -30,11 +30,12 @@ struct FrameInfo struct QueueCommandBuffers { + DeviceQueueType queue; VulkanCommandPoolHandle commandPool; Tab freeCommandBuffers; Tab pendingCommandBuffers; - void init(DeviceQueueType queue); + void init(DeviceQueueType target_queue); VulkanCommandBufferHandle allocateCommandBuffer(); void shutdown(); void finishCmdBuffers(); @@ -68,7 +69,6 @@ struct FrameInfo void finishDescriptorSetReset(); void finishSemaphores(); void finishGpuWork(); - void finishCmdBuffers(); void finishCleanups(); // internal state diff --git a/prog/engine/drv/drv3d_vulkan/globals.cpp b/prog/engine/drv/drv3d_vulkan/globals.cpp index d4bf3bff1..6b8d4b0a3 100644 --- a/prog/engine/drv/drv3d_vulkan/globals.cpp +++ b/prog/engine/drv/drv3d_vulkan/globals.cpp @@ -74,7 +74,7 @@ thread_local uint32_t GlobalDriverLock::acquired = 0; VulkanLoader Globals::VK::loader; VulkanDevice Globals::VK::dev; -DeviceQueueGroup Globals::VK::que; +DeviceQueueGroup Globals::VK::queue; PhysicalDeviceSet Globals::VK::phy; FormatUtil Globals::VK::fmt; BufferAlignment Globals::VK::bufAlign; diff --git a/prog/engine/drv/drv3d_vulkan/globals.h b/prog/engine/drv/drv3d_vulkan/globals.h index 1e4c73617..9f3012e12 100644 --- a/prog/engine/drv/drv3d_vulkan/globals.h +++ b/prog/engine/drv/drv3d_vulkan/globals.h @@ -97,7 +97,7 @@ struct Globals static VulkanLoader loader; static VulkanDevice dev; static VulkanInstance inst; - static DeviceQueueGroup que; + static DeviceQueueGroup queue; static PhysicalDeviceSet phy; static FormatUtil fmt; static BufferAlignment bufAlign; diff --git a/prog/engine/drv/drv3d_vulkan/render_work.cpp b/prog/engine/drv/drv3d_vulkan/render_work.cpp index 2c3fb2f93..a595b7950 100644 --- a/prog/engine/drv/drv3d_vulkan/render_work.cpp +++ b/prog/engine/drv/drv3d_vulkan/render_work.cpp @@ -324,6 +324,7 @@ void RenderWork::cleanup() commandCallers.clear(); #endif generateFaultReport = false; + userSignalCount = 0; } void RenderWork::processCommands(ExecutionContext &ctx) diff --git a/prog/engine/drv/drv3d_vulkan/render_work.h b/prog/engine/drv/drv3d_vulkan/render_work.h index f3d789be8..d4b8826e7 100644 --- a/prog/engine/drv/drv3d_vulkan/render_work.h +++ b/prog/engine/drv/drv3d_vulkan/render_work.h @@ -117,6 +117,7 @@ struct RenderWork size_t id = 0; uint32_t frontFrameIndex = 0; + uint32_t userSignalCount = 0; eastl::vector bufferUploads; eastl::vector bufferUploadCopies; diff --git a/prog/engine/drv/drv3d_vulkan/swapchain.cpp b/prog/engine/drv/drv3d_vulkan/swapchain.cpp index 0c040f8a5..367d7415a 100644 --- a/prog/engine/drv/drv3d_vulkan/swapchain.cpp +++ b/prog/engine/drv/drv3d_vulkan/swapchain.cpp @@ -250,7 +250,7 @@ bool Swapchain::acquireSwapImage(FrameInfo &frame) if (checkVkSwapchainError(rc, "vkAcquireNextImageKHR")) { - Globals::VK::que[DeviceQueueType::GRAPHICS].addSubmitSemaphore(syncSemaphore, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); + Globals::VK::queue[DeviceQueueType::GRAPHICS].addSubmitSemaphore(syncSemaphore, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); // we can't read from it later on, so set layout as underfined to ignore contents on later usage for faster transitioning swapImages[colorTargetIndex]->layout.set(0, 0, VK_IMAGE_LAYOUT_UNDEFINED); return true; @@ -818,7 +818,7 @@ void Swapchain::present(ExecutionContext &) if (currentState == SWP_HEADLESS) { DeviceQueue::TrimmedSubmitInfo si = {}; - Globals::VK::que[DeviceQueueType::GRAPHICS].submit(Globals::VK::dev, frame, si); + Globals::VK::queue[DeviceQueueType::GRAPHICS].submit(Globals::VK::dev, frame, si); } if (currentState == SWP_PRESENT) @@ -831,7 +831,7 @@ void Swapchain::present(ExecutionContext &) VkResult result; { TIME_PROFILE(vulkan_swapchain_present); - result = Globals::VK::que[DeviceQueueType::GRAPHICS].present(Globals::VK::dev, frame, pi); + result = Globals::VK::queue[DeviceQueueType::GRAPHICS].present(Globals::VK::dev, frame, pi); } if (checkVkSwapchainError(result, "vkQueuePresent")) diff --git a/prog/engine/gameRes/grpData.h b/prog/engine/gameRes/grpData.h index 63bf4ab70..c2c3e5bb3 100644 --- a/prog/engine/gameRes/grpData.h +++ b/prog/engine/gameRes/grpData.h @@ -25,14 +25,15 @@ struct ResData uint16_t resId, refResIdCnt; PatchablePtr refResIdPtr; - static void cvtRecInplaceVer2to3(ResData *data, unsigned size) + static void cvtRecInplaceVer2to3(ResData *_data, unsigned size) { - for (ResDataV2 *old = (ResDataV2 *)data; size > 0; old++, data++, size--) + volatile ResData *data = _data; // we update data inplace using overlapping pointers, prevent unsafe optimizations + for (auto old = (volatile ResDataV2 *)data; size > 0; old++, data++, size--) { data->classId = old->classId; data->resId = old->resId; data->refResIdCnt = old->refResIdCnt; - data->refResIdPtr.setPtr((void *)(uintptr_t)old->refResIdOfs); + ((ResData *)data)->refResIdPtr.setPtr((void *)(uintptr_t)old->refResIdOfs); } } }; diff --git a/prog/engine/imgui/imgui.dshl b/prog/engine/imgui/imgui.dshl index 49c1303f7..65814ceba 100644 --- a/prog/engine/imgui/imgui.dshl +++ b/prog/engine/imgui/imgui.dshl @@ -32,6 +32,7 @@ float imgui_a_max = 1; int imgui_mip_level = 0; +int custom_sampler_const_no = 5; int imgui_use_custom_sampler = 0; interval imgui_use_custom_sampler: no < 1, yes; @@ -136,8 +137,11 @@ shader imgui } compile("target_vs", "imgui_vs"); + (ps) { + custom_sampler@sampler : register(custom_sampler_const_no); + } + hlsl(ps) { - SamplerState custom_sampler : register(s5); void handle_channel(inout float c, uint mask, uint index) { diff --git a/prog/engine/imgui/imguiImpl.cpp b/prog/engine/imgui/imguiImpl.cpp index e85e44640..5bae39776 100644 --- a/prog/engine/imgui/imguiImpl.cpp +++ b/prog/engine/imgui/imguiImpl.cpp @@ -484,6 +484,7 @@ eastl::optional map_dagor_key_to_imgui(int humap_key) case HumanInput::DKEY_RSHIFT: return ImGuiKey_RightShift; case HumanInput::DKEY_RCONTROL: return ImGuiKey_RightCtrl; case HumanInput::DKEY_RALT: return ImGuiKey_RightAlt; + case HumanInput::DKEY_SLASH: return ImGuiKey_Slash; case HumanInput::DKEY_A: return ImGuiKey_A; case HumanInput::DKEY_B: return ImGuiKey_B; case HumanInput::DKEY_C: return ImGuiKey_C; @@ -563,6 +564,7 @@ int map_imgui_key_to_dagor(int imgui_key) case ImGuiKey_RightShift: return HumanInput::DKEY_RSHIFT; case ImGuiKey_RightCtrl: return HumanInput::DKEY_RCONTROL; case ImGuiKey_RightAlt: return HumanInput::DKEY_RALT; + case ImGuiKey_Slash: return HumanInput::DKEY_SLASH; case ImGuiKey_A: return HumanInput::DKEY_A; case ImGuiKey_B: return HumanInput::DKEY_B; case ImGuiKey_C: return HumanInput::DKEY_C; diff --git a/prog/engine/math/mathAng.cpp b/prog/engine/math/mathAng.cpp index 98d306f1e..c9f94e9c0 100644 --- a/prog/engine/math/mathAng.cpp +++ b/prog/engine/math/mathAng.cpp @@ -9,8 +9,8 @@ //============================================================================== void euler_to_quat(real heading, real attitude, real bank, Quat &quat) { - vec3f angles = v_make_vec3f(bank, heading, attitude); - v_stu(&quat.x, v_quat_from_euler_yzx(angles)); + vec4f angles = v_make_vec4f(heading, attitude, bank, bank); + v_stu(&quat.x, v_quat_from_euler(angles)); } void euler_heading_to_quat(real heading, Quat &quat) diff --git a/prog/engine/osApiWrappers/stackHlpGet.cpp b/prog/engine/osApiWrappers/stackHlpGet.cpp index 32df18dad..685d40597 100644 --- a/prog/engine/osApiWrappers/stackHlpGet.cpp +++ b/prog/engine/osApiWrappers/stackHlpGet.cpp @@ -86,8 +86,12 @@ const char *stackhlp_get_call_stack(char *buf, int out_buf_sz, const void *const } unsigned stack_size = get_stack_size(stack, max_size); - - lbw.aprintf("Call stack (%d frames, BP: %p):\n", stack_size, stackhlp_get_bp()); + void *imgBase = stackhlp_get_bp(); + IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)imgBase; + IMAGE_NT_HEADERS *nthdr = (IMAGE_NT_HEADERS *)((BYTE *)dos + dos->e_lfanew); + intptr_t delta = intptr_t(imgBase) - intptr_t(nthdr->OptionalHeader.ImageBase); + lbw.aprintf("Call stack (%d frames, imgbase: %zX, reloc delta %c%zX):\n", stack_size, intptr_t(imgBase), delta < 0 ? '-' : '+', + abs(delta)); // All DbgHelp functions are single threaded. // https://docs.microsoft.com/en-us/windows/win32/api/dbghelp/nf-dbghelp-undecoratesymbolname @@ -172,8 +176,13 @@ const char *stackhlp_get_call_stack(char *buf, int out_buf_sz, const void *const } unsigned stack_size = get_stack_size(stack, max_size); + void *imgBase = stackhlp_get_bp(); + IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)imgBase; + IMAGE_NT_HEADERS *nthdr = (IMAGE_NT_HEADERS *)((BYTE *)dos + dos->e_lfanew); + intptr_t delta = intptr_t(imgBase) - intptr_t(nthdr->OptionalHeader.ImageBase); - lbw.aprintf("Call stack (%d frames, BP: %p), addresses only:\n", stack_size, stackhlp_get_bp()); + lbw.aprintf("Call stack (%d frames, imgbase: %X, reloc delta %c%X), addresses only:\n", stack_size, imgBase, delta < 0 ? '-' : '+', + abs(delta)); for (int i = 0; i < stack_size; i++) { diff --git a/prog/engine/shaders/scriptSElem.cpp b/prog/engine/shaders/scriptSElem.cpp index 0ab69aa09..0d8c4fdc6 100644 --- a/prog/engine/shaders/scriptSElem.cpp +++ b/prog/engine/shaders/scriptSElem.cpp @@ -845,18 +845,17 @@ void (*scripted_shader_element_on_before_resource_used)(const ShaderElement *sel static void scripted_shader_element_on_before_resource_used(const ShaderElement *, const D3dResource *, const char *){}; #endif -static __forceinline void exec_stcode(dag::ConstSpan cod, const shaderbindump::ShaderCode::Pass *__restrict code_cp, +static __forceinline void exec_stcode(uint16_t stcodeId, const shaderbindump::ShaderCode::Pass *__restrict code_cp, const ScriptedShaderElement &__restrict this_elem) { - alignas(16) real vpr_const[32 * 4]; - alignas(16) real fsh_const[32 * 4]; + alignas(16) real vpr_const[64][4]; + alignas(16) real fsh_const[64][4]; alignas(16) real vregs[MAX_TEMP_REGS]; char *regs = (char *)vregs; - uint32_t vpr_c_mask = 0; - uint32_t fsh_c_mask = 0; + uint64_t vpr_c_mask = 0, fsh_c_mask = 0; -#define SHL1(y) 1 << (y) -#define SHLF(y) 0xF << (y) +#define SHL1(y) 1ull << (y) +#define SHLF(y) 0xFull << (y) STCODE_PROFILE_BEGIN(); @@ -868,6 +867,7 @@ static __forceinline void exec_stcode(dag::ConstSpan cod, const shaderbindu shader_assert::ScopedShaderAssert scoped_shader_assert(this_elem.shClass); const uint8_t *vars = this_elem.getVars(); + dag::ConstSpan cod = shBinDump().stcode[stcodeId]; const int *__restrict codp = cod.data(), *__restrict codp_end = codp + cod.size(); for (; codp < codp_end; codp++) { @@ -894,10 +894,9 @@ static __forceinline void exec_stcode(dag::ConstSpan cod, const shaderbindu const uint32_t ind = shaderopcode::getOp2p1(opc); const uint32_t ofs = shaderopcode::getOp2p2(opc); VEC_ALIGN(ofs, 4); - if (ind < 32) + if (ind < countof(vpr_const)) { - // memcpy(&vpr_const[ind<<2], get_reg_ptr(regs, ofs), 4*sizeof(real)); - v_st(&vpr_const[ind << 2], v_ld(get_reg_ptr(regs, ofs))); + v_st(&vpr_const[ind], v_ld(get_reg_ptr(regs, ofs))); vpr_c_mask |= SHL1(ind); } else @@ -914,10 +913,9 @@ static __forceinline void exec_stcode(dag::ConstSpan cod, const shaderbindu const uint32_t ind = shaderopcode::getOp2p1(opc); const uint32_t ofs = shaderopcode::getOp2p2(opc); VEC_ALIGN(ofs, 4); - if (ind < 32) + if (ind < countof(fsh_const)) { - // memcpy(&fsh_const[ind<<2], get_reg_ptr(regs, ofs), 4*sizeof(real)); - v_st(&fsh_const[ind << 2], v_ld(get_reg_ptr(regs, ofs))); + v_st(&fsh_const[ind], v_ld(get_reg_ptr(regs, ofs))); fsh_c_mask |= SHL1(ind); } else @@ -1083,7 +1081,7 @@ static __forceinline void exec_stcode(dag::ConstSpan cod, const shaderbindu #if D3D_HAS_RAY_TRACING d3d::set_top_acceleration_structure(ShaderStage(stage), slot, tlas); #else - logerr("exec_stcode: SHCOD_TLAS ignored for shader %s", (const char *)this_elem.shClass.name); + logerr("%s(%d): SHCOD_TLAS ignored for shader %s", __FUNCTION__, stcodeId, (const char *)this_elem.shClass.name); #endif stcode::dbg::record_set_tlas(stcode::dbg::RecordType::REFERENCE, stage, slot, tlas); @@ -1166,9 +1164,9 @@ static __forceinline void exec_stcode(dag::ConstSpan cod, const shaderbindu process_tm_for_drv_consts(gtm); - if (ind < 29) + if (ind <= countof(vpr_const) - 4) { - memcpy(&vpr_const[ind << 2], gtm[0], sizeof(real) * 4 * 4); + memcpy(&vpr_const[ind], gtm[0], sizeof(real) * 4 * 4); vpr_c_mask |= SHLF(ind); } else @@ -1352,7 +1350,7 @@ static __forceinline void exec_stcode(dag::ConstSpan cod, const shaderbindu } break; default: - DAG_FATAL("exec_stcode: illegal instruction %u %s (index=%d)", shaderopcode::getOp(opc), + DAG_FATAL("%s(%d): illegal instruction %u %s (index=%d)", __FUNCTION__, stcodeId, shaderopcode::getOp(opc), ShUtils::shcod_tokname(shaderopcode::getOp(opc)), codp - cod.data()); } } @@ -1360,17 +1358,19 @@ static __forceinline void exec_stcode(dag::ConstSpan cod, const shaderbindu while (fsh_c_mask) { auto start = __ctz_unsafe(fsh_c_mask); - auto end = __ctz(fsh_c_mask + (1u << start)); - fsh_c_mask &= uint64_t(eastl::numeric_limits::max()) << end; - d3d::set_ps_const(start, fsh_const + start * 4, end - start); + auto tmp = fsh_c_mask + (1ull << start); + auto end = tmp ? __ctz_unsafe(tmp) : 64; + fsh_c_mask &= tmp ? (eastl::numeric_limits::max() << end) : 0; + d3d::set_ps_const(start, fsh_const[start], end - start); } while (vpr_c_mask) { auto start = __ctz_unsafe(vpr_c_mask); - auto end = __ctz(vpr_c_mask + (1u << start)); - vpr_c_mask &= uint64_t(eastl::numeric_limits::max()) << end; - d3d::set_vs_const(start, vpr_const + start * 4, end - start); + auto tmp = vpr_c_mask + (1ull << start); + auto end = tmp ? __ctz_unsafe(tmp) : 64; + vpr_c_mask &= tmp ? (eastl::numeric_limits::max() << end) : 0; + d3d::set_vs_const(start, vpr_const[start], end - start); } MEASURE_STCODE_PERF_END; @@ -1557,14 +1557,14 @@ void ScriptedShaderElement::execute_chosen_stcode(uint16_t stcodeId, const shade #if VALIDATE_CPP_STCODE // Collect records if (stcode::execution_mode() == stcode::ExecutionMode::TEST_CPP_AGAINST_BYTECODE) - exec_stcode(shBinDump().stcode[stcodeId], cPass, *this); + exec_stcode(stcodeId, cPass, *this); #endif stcode::dbg::validate_accumulated_records(stcodeId, shClass.name.data()); #else - exec_stcode(shBinDump().stcode[stcodeId], cPass, *this); + exec_stcode(stcodeId, cPass, *this); #endif } diff --git a/prog/engine/shaders/shFunc.cpp b/prog/engine/shaders/shFunc.cpp index 8b6950663..98ea652d7 100644 --- a/prog/engine/shaders/shFunc.cpp +++ b/prog/engine/shaders/shFunc.cpp @@ -104,10 +104,14 @@ void callFunction(FunctionId id, int out_reg, const int *in_regs, char *regs) case BF_GET_VIEWPORT: { - int x = 0, y = 0, w = 0, h = 0; - float zn = 0, zf = 0; - d3d::getview(x, y, w, h, zn, zf); - COLOROUT(x, y, w, h); + union + { + vec4i v; + int i[4]; + } vp; // Intentionally not inited for perf reasons + float _1, _2; + G_VERIFY(d3d::getview(vp.i[0], vp.i[1], vp.i[2], vp.i[3], _1, _2)); + set_vec_reg(v_cvti_vec4f(vp.v), regs, out_reg); break; } diff --git a/prog/engine/shaders/shaderResUnitedData.cpp b/prog/engine/shaders/shaderResUnitedData.cpp index 9e76a6a41..17d415f13 100644 --- a/prog/engine/shaders/shaderResUnitedData.cpp +++ b/prog/engine/shaders/shaderResUnitedData.cpp @@ -1110,7 +1110,7 @@ void ShaderResUnitedVdata::discardUnusedResToFreeReqMemNoLock(bool forced) continue; if (res->getQlReqLodEff() <= res->getQlBestLod()) continue; - if (res->getQlReqLFU() + requestLodsByDistanceFrames >= dagor_frame_no()) + if (requestLodsByDistanceFrames > 0 && res->getQlReqLFU() + requestLodsByDistanceFrames >= dagor_frame_no()) continue; downgradeRes(res, res->getQlReqLodEff()); @@ -1317,7 +1317,12 @@ bool ShaderResUnitedVdata::addRes(dag::Span res) String _1; buildStatusStrNoLock(_1, /*full_res_list*/ true, resolve_game_resource_name); } - logmessage(bad_tight_detected ? LOGLEVEL_ERR : LOGLEVEL_WARN, +#if DAGOR_DBGLEVEL > 0 + int loglev = bad_tight_detected ? LOGLEVEL_ERR : LOGLEVEL_WARN; +#else + int loglev = LOGLEVEL_WARN; +#endif + logmessage(loglev, "unitedVdata<%s>: arranged %d res in tight buffers:%s; setup *.gameparams.blk unitedVdata.%s{} ! now %d VBs, %s", RES::getStaticClassName(), resList.size() - prev_res_count, tight_stats, RES::getStaticClassName(), buf.getVbCount(), buf.getStatStr()); diff --git a/prog/engine/workCycle/workCycle.cpp b/prog/engine/workCycle/workCycle.cpp index ce718bdd4..a75dd747e 100644 --- a/prog/engine/workCycle/workCycle.cpp +++ b/prog/engine/workCycle/workCycle.cpp @@ -82,6 +82,20 @@ static void act(); static void draw(bool enable_stereo, int elapsed_usec, float gametime_elapsed, bool call_before_render = true, bool draw_gui = true); static bool present(bool updateScreenNeeded); +static bool is_minimized_fullscreen() +{ + return !workcycle_internal::application_active && dgs_get_window_mode() == WindowMode::FULLSCREEN_EXCLUSIVE; +} + +bool dagor_work_cycle_is_need_to_draw() +{ +#if _TARGET_XBOX + return true; +#else + return !(is_minimized_fullscreen() || occluded_window); +#endif +} + void dagor_work_cycle() { workcycleperf::mark_cpu_only_cycle_start(); @@ -120,9 +134,7 @@ void dagor_work_cycle() ::dagor_idle_cycle(); - const bool minimizedFullscreen = - !workcycle_internal::application_active && dgs_get_window_mode() == WindowMode::FULLSCREEN_EXCLUSIVE; - if (DAGOR_UNLIKELY(minimizedFullscreen && ::dgs_dont_use_cpu_in_background)) + if (DAGOR_UNLIKELY(is_minimized_fullscreen() && ::dgs_dont_use_cpu_in_background)) { ResourceChecker::report(); if (tql::on_frame_finished) @@ -243,7 +255,7 @@ void dagor_work_cycle() // no sense in drawing something that can never be drawn and seen (unless it's XB1 in which case this assumption is not true) #if !_TARGET_XBOX - if (DAGOR_UNLIKELY(minimizedFullscreen || occluded_window)) + if (DAGOR_UNLIKELY(!dagor_work_cycle_is_need_to_draw())) { d3d::GpuAutoLock gpuLock; d3d::driver_command(Drv3dCommand::PROCESS_APP_INACTIVE_UPDATE, &occluded_window); diff --git a/prog/gameLibs/asyncHTTPClient/curl.cpp b/prog/gameLibs/asyncHTTPClient/curl.cpp index 855cc75ce..3ef549cb8 100644 --- a/prog/gameLibs/asyncHTTPClient/curl.cpp +++ b/prog/gameLibs/asyncHTTPClient/curl.cpp @@ -598,6 +598,11 @@ void abort_request(RequestId req_id) void abort_all_requests(AbortMode mode) { + // this function is called during xbox suspend. + // it could happen even before init or after shutdown. + if (!mutex) + return; + eastl::list aborted; { WinAutoLock lock(*mutex); diff --git a/prog/gameLibs/bvh/bvh.cpp b/prog/gameLibs/bvh/bvh.cpp index 491b41107..31c05ae8b 100644 --- a/prog/gameLibs/bvh/bvh.cpp +++ b/prog/gameLibs/bvh/bvh.cpp @@ -40,6 +40,8 @@ static constexpr float animation_distance_rate = 20; static constexpr bool showProceduralBLASBuildCount = false; +static bool per_frame_processing_enabled = true; + #if DAGOR_DBGLEVEL > 0 extern bool bvh_gpuobject_enable; extern bool bvh_grass_enable; @@ -279,6 +281,13 @@ static __forceinline void realign(mat43f &mat, vec4f s1, vec4f s2, vec4f s3) mat.row2 = v_sub(mat.row2, s3); } +bool has_enough_vram_for_rt() +{ + return (d3d::driver_command(Drv3dCommand::GET_VIDEO_MEMORY_BUDGET) >= + dgs_get_settings()->getBlockByNameEx("graphics")->getInt("bvhMinRequiredMemoryGB", 5) * 1100 * 1000); // intentionally not + // 1024 +} + bool is_available() { if (dgs_get_settings()->getBlockByNameEx("gameplay")->getBool("enableVR", false)) @@ -292,9 +301,7 @@ bool is_available() #elif _TARGET_PC if (!d3d::is_inited()) return true; - static bool hasEnoughVRAM = - (d3d::driver_command(Drv3dCommand::GET_VIDEO_MEMORY_BUDGET) >= - dgs_get_settings()->getBlockByNameEx("graphics")->getInt("bvhMinRequiredMemoryGB", 5) * 1100 * 1000); // intentionally not 1024 + static bool hasEnoughVRAM = has_enough_vram_for_rt(); #else static bool hasEnoughVRAM = false; #endif @@ -886,9 +893,14 @@ static void patch_per_instance_data(Context::HWInstanceMap &instances, dag::Vect void process_meshes(ContextId context_id, BuildBudget budget) { + if (!per_frame_processing_enabled) + { + logdbg("[BVH] Device is in reset mode."); + return; + } TIME_D3D_PROFILE_NAME(bvh_process_meshes, String(128, "bvh_process_meshes for %s", context_id->name.data())); - HANDLE_LOST_DEVICE_STATE(context_id, ); + CHECK_LOST_DEVICE_STATE(); handle_pending_mesh_actions(context_id); @@ -948,9 +960,7 @@ void process_meshes(ContextId context_id, BuildBudget budget) RaytraceGeometryDescription desc[2]; memset(&desc, 0, sizeof(desc)); desc[0].type = RaytraceGeometryDescription::Type::TRIANGLES; - HANDLE_LOST_DEVICE_STATE(mesh.processedVertices, ); desc[0].data.triangles.vertexBuffer = mesh.processedVertices.get(); - HANDLE_LOST_DEVICE_STATE(mesh.processedIndices, ); desc[0].data.triangles.indexBuffer = mesh.processedIndices.get(); desc[0].data.triangles.vertexCount = mesh.vertexCount; desc[0].data.triangles.vertexStride = meta.texcoordNormalColorOffsetAndVertexStride & 255; @@ -1150,6 +1160,11 @@ void process_meshes(ContextId context_id, BuildBudget budget) void build(ContextId context_id, const TMatrix &itm, const TMatrix4 &projTm, const Point3 &camera_pos, const Point3 &light_direction) { + if (!per_frame_processing_enabled) + { + logdbg("[BVH] Device is in reset mode."); + return; + } CHECK_LOST_DEVICE_STATE(); TIME_D3D_PROFILE_NAME(bvh_build, String(128, "bvh_build for %s", context_id->name.data())); @@ -2092,5 +2107,6 @@ void finalize_async_atmosphere_update(ContextId context_id) upload_atmosphere(context_id); } } +void enable_per_frame_processing(bool enable) { per_frame_processing_enabled = enable; } } // namespace bvh \ No newline at end of file diff --git a/prog/gameLibs/bvh/bvh_fx.cpp b/prog/gameLibs/bvh/bvh_fx.cpp index b1d019726..96c51ecdd 100644 --- a/prog/gameLibs/bvh/bvh_fx.cpp +++ b/prog/gameLibs/bvh/bvh_fx.cpp @@ -143,7 +143,7 @@ struct BVHConnection : public bvh::BVHConnection void textureUsed(TEXTUREID texture_id) override { - static int reg_no = ShaderGlobal::get_int(get_shader_variable_id("dafx_modfx_bvh_meta_id_regno")); + static int reg_no = ShaderGlobal::get_slot_by_name("dafx_modfx_bvh_meta_id_regno"); int metaAllocId = get_particle_meta(*contexts.begin(), texture_id); int reg[] = {metaAllocId, 0, 0, 0}; diff --git a/prog/gameLibs/bvh/stub/bvh_stub.cpp b/prog/gameLibs/bvh/stub/bvh_stub.cpp index dbc7b06ae..89450b196 100644 --- a/prog/gameLibs/bvh/stub/bvh_stub.cpp +++ b/prog/gameLibs/bvh/stub/bvh_stub.cpp @@ -4,6 +4,8 @@ namespace bvh { +bool has_enough_vram_for_rt() { return false; } + bool is_available() { return false; } void init(elem_rules_fn) {} @@ -68,4 +70,5 @@ void set_grass_range(ContextId, float) {} void ChannelParser::enum_shader_channel(int, int, int, int, int, ChannelModifier, int) {} +void enable_per_frame_processing(bool) {} } // namespace bvh \ No newline at end of file diff --git a/prog/gameLibs/daFx/commandQueue.h b/prog/gameLibs/daFx/commandQueue.h index 6c5493c20..3e282c27a 100644 --- a/prog/gameLibs/daFx/commandQueue.h +++ b/prog/gameLibs/daFx/commandQueue.h @@ -42,7 +42,7 @@ struct CommandQueue struct InstanceVisibility { InstanceId iid; - bool visible; + uint32_t visibility; }; struct InstanceValue diff --git a/prog/gameLibs/daFx/context.cpp b/prog/gameLibs/daFx/context.cpp index 623f2787c..117679519 100644 --- a/prog/gameLibs/daFx/context.cpp +++ b/prog/gameLibs/daFx/context.cpp @@ -407,6 +407,11 @@ void prepare_workers(Context &ctx, float dt, bool main_pass, int begin_sid, int } stat_inc(ctx.stats.activeInstances); + + if (flags & SYS_CPU_SIMULATION_REQ) + stat_add(ctx.stats.cpuElemTotalSimLods[simLod], simulationState.count); + else if (flags & SYS_GPU_SIMULATION_REQ) + stat_add(ctx.stats.gpuElemTotalSimLods[simLod], simulationState.count); } for (int i = 0; i < ctx.cfg.max_system_depth; ++i) @@ -1134,6 +1139,12 @@ void finish_update_gpu_only(ContextId cid, bool update_gpu_fetch, bool beforeRen stat_add(ctx.stats.cpuDispatchCalls, ctx.asyncStats.cpuDispatchCalls); stat_add(ctx.stats.gpuDispatchCalls, ctx.asyncStats.gpuDispatchCalls); + for (int i = 0; i < Config::max_simulation_lods; ++i) + { + stat_add(ctx.stats.cpuElemProcessedByLods[i], ctx.asyncStats.cpuElemProcessedByLods[i]); + stat_add(ctx.stats.gpuElemProcessedByLods[i], ctx.asyncStats.gpuElemProcessedByLods[i]); + } + gather_system_usage_stats(ctx); if (!ctx.simulationIsPaused) ctx.currentFrame++; @@ -1333,6 +1344,20 @@ void get_stats(ContextId cid, Stats &out_s) out_s = ctx.stats; } +void format_lod_list(eastl::string &out_s, eastl::array &lods, + eastl::array &padding) +{ + constexpr int frameHistory = 200; // to prevert stats flickering on rows count change + + for (int i = 0; i < lods.size(); ++i) + { + int c = lods[i]; + if (padding[i] > 0) + out_s.append_sprintf(" lod_%d: %4d\n", i, c); + padding[i] = c > 0 ? frameHistory : max(padding[i] - 1, 0); + } +} + void get_stats_as_string(ContextId cid, eastl::string &out_s) { out_s = eastl::string(); @@ -1355,7 +1380,13 @@ void get_stats_as_string(ContextId cid, eastl::string &out_s) ADDV(cpuRenderWorkers); ADDV(cpuElemProcessed); + + static eastl::array cpuElemProcessedPadding = {}; + format_lod_list(out_s, ctx.stats.cpuElemProcessedByLods, cpuElemProcessedPadding); + ADDV(gpuElemProcessed); + static eastl::array gpuElemProcessedPadding = {}; + format_lod_list(out_s, ctx.stats.gpuElemProcessedByLods, gpuElemProcessedPadding); ADDV(renderDrawCalls); ADDV(renderSwitchBuffers); @@ -1377,6 +1408,14 @@ void get_stats_as_string(ContextId cid, eastl::string &out_s) ADDV(totalInstances); ADDV(activeInstances); + out_s.append_sprintf("CPU sim elems total by lods: %\n"); + static eastl::array cpuElemTotalSimLodsPadding = {}; + format_lod_list(out_s, ctx.stats.cpuElemTotalSimLods, cpuElemTotalSimLodsPadding); + + out_s.append_sprintf("GPU sim elems total by lods: %\n"); + static eastl::array gpuElemTotalSimLodsPadding = {}; + format_lod_list(out_s, ctx.stats.gpuElemTotalSimLods, gpuElemTotalSimLodsPadding); + out_s.append_sprintf("queue create: %3d / destroy: %3d / reset: %3d\n", s.queue[1].createInstance, s.queue[1].destroyInstance, s.queue[1].resetInstance); diff --git a/prog/gameLibs/daFx/context.h b/prog/gameLibs/daFx/context.h index d08a7c3e0..857cbade1 100644 --- a/prog/gameLibs/daFx/context.h +++ b/prog/gameLibs/daFx/context.h @@ -81,6 +81,9 @@ struct AsyncStats volatile int gpuElemProcessed; volatile int cpuDispatchCalls; volatile int gpuDispatchCalls; + + eastl::array cpuElemProcessedByLods; + eastl::array gpuElemProcessedByLods; }; using WorkersByDepth = eastl::array, Config::max_system_depth>; diff --git a/prog/gameLibs/daFx/culling.cpp b/prog/gameLibs/daFx/culling.cpp index 2a69c8ea5..aff3939e0 100644 --- a/prog/gameLibs/daFx/culling.cpp +++ b/prog/gameLibs/daFx/culling.cpp @@ -44,6 +44,7 @@ CullingId create_culling_state(ContextId cid, const eastl::vector & cull.sortings[tag] = i.sortingType; cull.shadingRates[tag] = i.vrsRate; cull.discardThreshold[tag] = i.screenAreaDiscardThreshold; + cull.visibilityMask = i.visibilityMask; G_ASSERT(i.vrsRate <= 2); // basic VRS supports only 1xN - 2xN rates DBG_OPT(" render_tag: %s, sorting: %d", i.tag, (int)i.sortingType); } @@ -100,6 +101,16 @@ void clear_culling_state(ContextId cid, CullingId cull_id) cull->workers[i].clear(); } +uint32_t get_culling_state_visiblity_mask(ContextId cid, CullingId cullid) +{ + GET_CTX_RET(0); + + CullingState *cull = ctx.cullingStates.get(cullid); + G_ASSERT_RETURN(cull, 0); + + return cull->visibilityMask; +} + void remap_culling_state_tag(ContextId cid, CullingId cullid, const eastl::string &from, const eastl::string &to) { GET_CTX(); @@ -546,7 +557,10 @@ void update_culling_state(Context &ctx, CullingState *cull, const Frustum &frust { uint32_t &flags = stream.get(sid); - if ((flags & validationFlags) != validationFlags || (flags & SYS_EXPLICITLY_HIDDEN)) + if ((flags & validationFlags) != validationFlags) + continue; + + if ((stream.get(sid) & cull->visibilityMask) == 0) continue; if (stream.get(sid).aliveCount == 0) diff --git a/prog/gameLibs/daFx/culling.h b/prog/gameLibs/daFx/culling.h index f486aeab6..03f4fa66e 100644 --- a/prog/gameLibs/daFx/culling.h +++ b/prog/gameLibs/daFx/culling.h @@ -22,6 +22,7 @@ struct CullingState eastl::array vrsRemapTags; eastl::array shadingRates; eastl::array discardThreshold; + uint32_t visibilityMask = 0xffffffff; }; using CullingStates = GenerationReferencedData; diff --git a/prog/gameLibs/daFx/frameBoundaryBufferManager.cpp b/prog/gameLibs/daFx/frameBoundaryBufferManager.cpp index ce8a6ffe4..23cb64dc4 100644 --- a/prog/gameLibs/daFx/frameBoundaryBufferManager.cpp +++ b/prog/gameLibs/daFx/frameBoundaryBufferManager.cpp @@ -310,27 +310,33 @@ void FrameBoundaryBufferManager::updateFrameElems(unsigned int currect_frame) { TIME_D3D_PROFILE(fillBoundaryOptStartCs); - STATE_GUARD_NULLPTR(d3d::set_rwbuffer(STAGE_CS, 0, VALUE), frameBoundaryBufferTmp.getBuf()); + static int frame_boundary_tmp_uav_no = + ShaderGlobal::get_slot_by_name("dafx_fill_boundary_opt_start_frame_boundary_tmp_uav_no"); + STATE_GUARD_NULLPTR(d3d::set_rwbuffer(STAGE_CS, frame_boundary_tmp_uav_no, VALUE), frameBoundaryBufferTmp.getBuf()); res = res && fillBoundaryOptStartCs->dispatchThreads(DAFX_FLIPBOOK_MAX_KEYFRAME_DIM * DAFX_FLIPBOOK_MAX_KEYFRAME_DIM, 1, 1); } d3d::resource_barrier({frameBoundaryBufferTmp.getBuf(), RB_FLUSH_UAV | RB_STAGE_COMPUTE | RB_SOURCE_STAGE_COMPUTE}); if (approximateFill) { TIME_D3D_PROFILE(fillBoundaryApproxCs); - STATE_GUARD_NULLPTR(d3d::set_rwbuffer(STAGE_CS, 0, VALUE), frameBoundaryBufferTmp.getBuf()); + static int frame_boundary_tmp_uav_no = ShaderGlobal::get_slot_by_name("dafx_fill_boundary_approx_frame_boundary_tmp_uav_no"); + STATE_GUARD_NULLPTR(d3d::set_rwbuffer(STAGE_CS, frame_boundary_tmp_uav_no, VALUE), frameBoundaryBufferTmp.getBuf()); res = res && fillBoundaryApproxCs->dispatchThreads(textureSize.x / (elem.frameDim.x * DAFX_FRAME_BOUNDARY_BLOCK_SIZE * 2), textureSize.y / (elem.frameDim.y * DAFX_FRAME_BOUNDARY_BLOCK_SIZE * 2), elem.frameDim.x * elem.frameDim.y); } else { TIME_D3D_PROFILE(fillBoundaryOptCs); - STATE_GUARD_NULLPTR(d3d::set_rwbuffer(STAGE_CS, 0, VALUE), frameBoundaryBufferTmp.getBuf()); + static int frame_boundary_tmp_uav_no = ShaderGlobal::get_slot_by_name("dafx_fill_boundary_opt_frame_boundary_tmp_uav_no"); + STATE_GUARD_NULLPTR(d3d::set_rwbuffer(STAGE_CS, frame_boundary_tmp_uav_no, VALUE), frameBoundaryBufferTmp.getBuf()); res = res && fillBoundaryOptCs->dispatchThreads(textureSize.x, textureSize.y, 1); } d3d::resource_barrier({frameBoundaryBufferTmp.getBuf(), RB_RO_SRV | RB_STAGE_COMPUTE}); { TIME_D3D_PROFILE(fillBoundaryOptEndCs); - STATE_GUARD_NULLPTR(d3d::set_rwbuffer(STAGE_CS, 0, VALUE), frameBoundaryBuffer.getBuf()); + static int frame_boundary_result_uav_no = + ShaderGlobal::get_slot_by_name("dafx_fill_boundary_opt_end_frame_boundary_result_uav_no"); + STATE_GUARD_NULLPTR(d3d::set_rwbuffer(STAGE_CS, frame_boundary_result_uav_no, VALUE), frameBoundaryBuffer.getBuf()); res = res && fillBoundaryOptEndCs->dispatchThreads(elem.frameDim.x, elem.frameDim.y, 1); // if this one fails, the final result is still the same as before, no need to clear it } @@ -338,7 +344,9 @@ void FrameBoundaryBufferManager::updateFrameElems(unsigned int currect_frame) else { TIME_D3D_PROFILE(fillBoundaryLegacyCs); - STATE_GUARD_NULLPTR(d3d::set_rwbuffer(STAGE_CS, 0, VALUE), frameBoundaryBuffer.getBuf()); + static int frame_boundary_result_uav_no = + ShaderGlobal::get_slot_by_name("dafx_fill_boundary_legacy_frame_boundary_result_uav_no"); + STATE_GUARD_NULLPTR(d3d::set_rwbuffer(STAGE_CS, frame_boundary_result_uav_no, VALUE), frameBoundaryBuffer.getBuf()); const Region ®ion = frameBoundaryAllocator.get(elem.regionId); @@ -405,7 +413,8 @@ void FrameBoundaryBufferManager::updateDebugTexture() ShaderGlobal::set_color4(dafx_fill_boundary_paramsVarId, elem.frameDim.x, elem.frameDim.y, textureSize.x, textureSize.y); ShaderGlobal::set_int(dafx_fill_boundary_offsetVarId, region.offset); - STATE_GUARD_NULLPTR(d3d::set_rwtex(STAGE_CS, 0, VALUE, 0, 0), debugTexture.getTex2D()); + static int outputTex_uav_no = ShaderGlobal::get_slot_by_name("dafx_frame_boundary_debug_update_outputTex_uav_no"); + STATE_GUARD_NULLPTR(d3d::set_rwtex(STAGE_CS, outputTex_uav_no, VALUE, 0, 0), debugTexture.getTex2D()); updateDebugTexCs->dispatchThreads(DEBUG_TEX_SIZE, DEBUG_TEX_SIZE, 1); d3d::resource_barrier({debugTexture.getTex2D(), RB_RO_SRV | RB_STAGE_ALL_SHADERS, 0, 0}); @@ -434,7 +443,8 @@ void FrameBoundaryBufferManager::resetFrameBoundaryResult() ShaderGlobal::set_int(dafx_fill_boundary_countVarId, bufferElemCnt); { - STATE_GUARD_NULLPTR(d3d::set_rwbuffer(STAGE_CS, 0, VALUE), frameBoundaryBuffer.getBuf()); + static int frame_boundary_result_uav_no = ShaderGlobal::get_slot_by_name("dafx_clear_boundary_frame_boundary_result_uav_no"); + STATE_GUARD_NULLPTR(d3d::set_rwbuffer(STAGE_CS, frame_boundary_result_uav_no, VALUE), frameBoundaryBuffer.getBuf()); clearBoundaryCs->dispatchThreads(bufferElemCnt, 1, 1); } d3d::resource_barrier({frameBoundaryBuffer.getBuf(), RB_RO_SRV | RB_STAGE_PIXEL}); diff --git a/prog/gameLibs/daFx/instances.cpp b/prog/gameLibs/daFx/instances.cpp index 111f63792..e5b5d947c 100644 --- a/prog/gameLibs/daFx/instances.cpp +++ b/prog/gameLibs/daFx/instances.cpp @@ -213,6 +213,7 @@ InstanceId create_subinstance(Context &ctx, InstanceId queued_iid, const SystemT SETV(INST_RENDER_SORT_DEPTH, sys.renderSortDepth); SETV(INST_CULLING_ID, 0xffffffff); SETV(INST_LAST_VALID_BBOX_FRAME, ctx.currentFrame); + SETV(INST_VISIBILITY, 0xffffffff); if constexpr (INST_RENDERABLE_TRIS >= 0) *stream.getOpt(sid) = 0; @@ -566,6 +567,7 @@ inline void reset_subinstance(Context &ctx, int sid) flags = stream.get(sid); stream.get(sid) = flags; stream.get(sid) = ctx.currentFrame; + stream.get(sid) = 0xffffffff; if constexpr (INST_RENDERABLE_TRIS >= 0) *stream.getOpt(sid) = 0; @@ -1118,17 +1120,17 @@ bool get_instance_status(ContextId cid, InstanceId rid) return flags & SYS_ENABLED; } -void set_instance_visibility(ContextId cid, InstanceId iid, bool visible) +void set_instance_visibility(ContextId cid, InstanceId iid, uint32_t visibility) { GET_CTX(); G_ASSERT_RETURN(iid, ); os_spinlock_lock(&ctx.queueLock); - ctx.commandQueueNext.instanceVisibility.push_back({iid, visible}); + ctx.commandQueueNext.instanceVisibility.push_back({iid, visibility}); os_spinlock_unlock(&ctx.queueLock); } -void set_instance_visibility(Context &ctx, int sid, bool visible) +void set_instance_visibility(Context &ctx, int sid, uint32_t visibility) { if (sid == dummy_instance_sid) return; @@ -1136,15 +1138,11 @@ void set_instance_visibility(Context &ctx, int sid, bool visible) INST_TUPLE_LOCK_GUARD; InstanceGroups &stream = ctx.instances.groups; - uint32_t &flag = stream.get(sid); // -V758 - G_ASSERT(flag & SYS_VALID); - - flag &= ~SYS_EXPLICITLY_HIDDEN; - flag |= visible ? 0 : SYS_EXPLICITLY_HIDDEN; + stream.get(sid) = visibility; eastl::vector &subinstances = stream.get(sid); // -V758 for (int subSid : subinstances) - set_instance_visibility(ctx, subSid, visible); + set_instance_visibility(ctx, subSid, visibility); } void set_instance_visibility_from_queue(Context &ctx) @@ -1155,7 +1153,7 @@ void set_instance_visibility_from_queue(Context &ctx) INST_LIST_LOCK_GUARD; int *sid = ctx.instances.list.get(cq.iid); G_ASSERT_CONTINUE(sid); - set_instance_visibility(ctx, *sid, cq.visible); + set_instance_visibility(ctx, *sid, cq.visibility); } } diff --git a/prog/gameLibs/daFx/instances.h b/prog/gameLibs/daFx/instances.h index 45fb6de79..ab5127a04 100644 --- a/prog/gameLibs/daFx/instances.h +++ b/prog/gameLibs/daFx/instances.h @@ -117,6 +117,7 @@ enum : int INST_RENDER_SORT_DEPTH, INST_CULLING_ID, INST_LAST_VALID_BBOX_FRAME, + INST_VISIBILITY, #if DAFX_STAT INST_RENDERABLE_TRIS, @@ -195,12 +196,13 @@ using InstanceStream = eastl::tuple_vector, // INST_LOCAL_RES_VS eastl::vector, // INST_LOCAL_RES_PS - bbox3f, // INST_BBOX (this should be fine, since eastl::tuple_vector have alignment-friendly allocator) - Point4, // INST_POSITION - float, // INST_VIEW_DIST - int, // INST_RENDER_SORT_DEPTH - int, // INST_CULLING_ID - unsigned int // INST_LAST_VALID_BBOX_FRAME + bbox3f, // INST_BBOX (this should be fine, since eastl::tuple_vector have alignment-friendly allocator) + Point4, // INST_POSITION + float, // INST_VIEW_DIST + int, // INST_RENDER_SORT_DEPTH + int, // INST_CULLING_ID + unsigned int, // INST_LAST_VALID_BBOX_FRAME + unsigned int // INST_VISIBILITY #if DAFX_STAT , diff --git a/prog/gameLibs/daFx/shaders.cpp b/prog/gameLibs/daFx/shaders.cpp index bccbcbc52..4865179cf 100644 --- a/prog/gameLibs/daFx/shaders.cpp +++ b/prog/gameLibs/daFx/shaders.cpp @@ -113,6 +113,7 @@ int update_cpu_tasks(Context &ctx, const eastl::vector &workers, int start, dispatches.reserve(count); int cpuElemProcessed = 0; + eastl::array cpuElemProcessedByLods = {}; InstanceGroups &stream = ctx.instances.groups; G_STATIC_ASSERT(Config::max_simulation_lods <= 8); // we can use more, but then we need to change packing, or change it to 1 << lod @@ -146,9 +147,12 @@ int update_cpu_tasks(Context &ctx, const eastl::vector &workers, int start, ddesc.aliveStartAndCount = inst.aliveStart | (inst.aliveCount << 16); ddesc.rndSeedAndCullingId = (uint32_hash(rnd + sid + ddesc.startAndCount) % 0xff) | (stream.get(sid) << 8); cpuElemProcessed += state.count; + cpuElemProcessedByLods[lod] += state.count; } interlocked_add(ctx.asyncStats.cpuElemProcessed, cpuElemProcessed); + for (int i = 0; i < cpuElemProcessedByLods.size(); ++i) + interlocked_add(ctx.asyncStats.cpuElemProcessedByLods[i], cpuElemProcessedByLods[i]); if (dispatches.empty()) return 0; @@ -232,6 +236,7 @@ void update_gpu_tasks(Context &ctx, const eastl::vector &workers) dispatches.reserve(workers.size()); int gpuElemProcessed = 0; + eastl::array gpuElemProcessedByLods = {}; InstanceGroups &stream = ctx.instances.groups; // prep all dispatches @@ -264,9 +269,12 @@ void update_gpu_tasks(Context &ctx, const eastl::vector &workers) ddesc.aliveStartAndCount = inst.aliveStart | (inst.aliveCount << 16); ddesc.rndSeedAndCullingId = (uint32_hash(rnd + sid + ddesc.startAndCount) % 0xff) | (stream.get(sid) << 8); gpuElemProcessed += state.count; + gpuElemProcessedByLods[lod] += state.count; } interlocked_add(ctx.asyncStats.gpuElemProcessed, gpuElemProcessed); + for (int i = 0; i < gpuElemProcessedByLods.size(); ++i) + interlocked_add(ctx.asyncStats.gpuElemProcessedByLods[i], gpuElemProcessedByLods[i]); if (dispatches.empty()) return; diff --git a/prog/gameLibs/daFx/systems.h b/prog/gameLibs/daFx/systems.h index c565b8970..18568a817 100644 --- a/prog/gameLibs/daFx/systems.h +++ b/prog/gameLibs/daFx/systems.h @@ -38,17 +38,16 @@ enum SYS_GPU_TRANFSER_PENDING = 1 << 13, SYS_VISIBLE = 1 << 14, - SYS_EXPLICITLY_HIDDEN = 1 << 15, - SYS_BBOX_VALID = 1 << 16, - SYS_CULL_FETCHED = 1 << 17, - SYS_RENDER_BUF_TAKEN = 1 << 18, + SYS_BBOX_VALID = 1 << 15, + SYS_CULL_FETCHED = 1 << 16, + SYS_RENDER_BUF_TAKEN = 1 << 17, - SYS_POS_VALID = 1 << 19, + SYS_POS_VALID = 1 << 18, - SYS_SKIP_SCREEN_PROJ_CULL_DISCARD = 1 << 20, + SYS_SKIP_SCREEN_PROJ_CULL_DISCARD = 1 << 19, - SYS_SKIP_SIMULATION_ON_THIS_FRAME = 1 << 21, - SYS_ALLOW_SIMULATION_LODS = 1 << 22, + SYS_SKIP_SIMULATION_ON_THIS_FRAME = 1 << 20, + SYS_ALLOW_SIMULATION_LODS = 1 << 21, }; struct SystemTemplate diff --git a/prog/gameLibs/daGI2/screenSpaceProbes.cpp b/prog/gameLibs/daGI2/screenSpaceProbes.cpp index 129659b32..df13719ba 100644 --- a/prog/gameLibs/daGI2/screenSpaceProbes.cpp +++ b/prog/gameLibs/daGI2/screenSpaceProbes.cpp @@ -11,7 +11,7 @@ #include #include #include -CONSOLE_INT_VAL("gi", sp_spatial_filter_passes, 2, 1, 5); +CONSOLE_INT_VAL("gi", sp_spatial_filter_passes, 3, 1, 5); CONSOLE_INT_VAL("gi", sp_placement_probes_iterations, -1, -1, 8); CONSOLE_BOOL_VAL("gi", sp_radiance_r11g11b10, true); CONSOLE_FLOAT_VAL_MINMAX("gi", sp_additional_probes_reserve, 0.75, 0.25, 4); diff --git a/prog/gameLibs/daGI2/shaders/screenProbes/screenspace_probes_trace.dshl b/prog/gameLibs/daGI2/shaders/screenProbes/screenspace_probes_trace.dshl index 6d47933f6..f533f666b 100644 --- a/prog/gameLibs/daGI2/shaders/screenProbes/screenspace_probes_trace.dshl +++ b/prog/gameLibs/daGI2/shaders/screenProbes/screenspace_probes_trace.dshl @@ -12,7 +12,7 @@ buffer screenspace_tile_classificator; macro NOISE(code) (code) { - sp_rand_decode@f3 = (1./(screenspace_probe_res.w*65535.), -(0.5+0.5/screenspace_probe_res.w)/screenspace_probe_res.w, 1./screenspace_probe_res.w, 0); + sp_rand_decode@f4 = (1./(screenspace_probe_res.w*65535.), -(0.5+0.5/screenspace_probe_res.w)/screenspace_probe_res.w, 1./screenspace_probe_res.w, 0.5/screenspace_probe_res.w); } hlsl(code) { #include @@ -21,14 +21,16 @@ macro NOISE(code) //[-0.5 0.5] texel (/w) float2 rand3D_Probe(uint3 v, uint2 oct_coord, uint frame) { - uint3 targetCoord = uint3(v.xy<<3, v.z) + uint3(oct_coord, 0); + uint3 targetCoord = uint3((v.xy)*13, v.z) + uint3(oct_coord, uint(screenspace_probes_temporal.y)); uint3 rand = pcg3d_hash_16bit(targetCoord); + //return ((rand.xy&7) - 3.5)/8.0*sp_rand_decode.z; //can be optimized further, by one mul as hammersley_rand16 can produce 0...65535 range //todo:We can also provide fixed spatial-temporal-coherent 2d blue noise return hammersley_rand16( frame, SP_TOTAL_JITTER_FRAMES, rand.xy )*sp_rand_decode.z + sp_rand_decode.y; } } endmacro + macro SP_JITTER_POS(code) HISTORY_ONLY_PROBE(code) hlsl (code) { @@ -135,10 +137,9 @@ shader calc_screenspace_radiance_cs, calc_screenspace_selected_radiance_cs float2 currentScreenTileLT = screen_tile_coord*screenspace_probe_res.z + 0.5f; float2 probeScreenCoord = min(currentScreenTileLT + coord_ofs, screenspace_probe_screen_limit.zw); //fixme: temporal - uint jitterFrame; - jitterFrame = sp_decodeTagRevAge(probe.allTag); + uint revAge = sp_decodeTagRevAge(probe.allTag); //we better store probe seed in probe, instead of calculating it, as it can sigfinicantly increase convergence - jitterFrame = jitterFrame ? SP_TAG_MAX_AGE - jitterFrame : (uint(screenspace_probes_temporal.y)&(TEMPORAL_PROBES_FRAMES-1)); //fixme: constant on the right + uint jitterFrame = revAge ? SP_TAG_MAX_AGE - revAge: (uint(screenspace_probes_temporal.y)%TEMPORAL_PROBES_FRAMES); //fixme: constant on the right //uint jitterFrame = validTemporal ? ((uint(screenspace_probes_temporal.y))&(TEMPORAL_PROBES_FRAMES-1)) : 0; //fixme: constant //todo: replace with small buffer with offsets @@ -157,6 +158,7 @@ shader calc_screenspace_radiance_cs, calc_screenspace_selected_radiance_cs float2 probeScreenUv = screenCoordToScreenUV(probeScreenCoord); float2 screenCoordJittered = min((returnJitterOffset(screen_tile_coord, randPos, jitterFrame))*screenspace_probe_res.z + currentScreenTileLT, screenspace_probe_screen_limit.zw); //try use jittered position + //todo: once per probe! { float rawDepth2 = loadGbufferDepth(screenCoordJittered); float normalizedW2 = linearize_z(rawDepth2, sp_zn_zfar.zw)/sp_zn_zfar.y; diff --git a/prog/gameLibs/daGI2/shaders/screen_gi_encoding.dshl b/prog/gameLibs/daGI2/shaders/screen_gi_encoding.dshl index e56770e80..b0c169112 100644 --- a/prog/gameLibs/daGI2/shaders/screen_gi_encoding.dshl +++ b/prog/gameLibs/daGI2/shaders/screen_gi_encoding.dshl @@ -1,18 +1,37 @@ int dagi_sp_has_exposure_assume = 1; interval dagi_sp_has_exposure_assume : always_rgbe < 1, can_be_r11g11b10; -macro DAGI_SCREEN_ENCODING(code) +hlsl { + #define GI_USE_HW_RGBE 0 + #define GI_USE_GAMMA2 1 + #define GI_USE_SW_RGBE 2 + #define GI_USE_NO_ENCODING 3 +} + +macro DAGI_NO_SCREEN_ENCODING(code) hlsl(code) { - ##if dagi_sp_has_exposure_assume == always_rgbe - #define GI_PACK_ALGO 0 - ##endif + #define GI_PACK_ALGO GI_USE_NO_ENCODING #include } endmacro -macro DAGI_NO_SCREEN_ENCODING(code) +macro DAGI_SW_RGBE_SCREEN_ENCODING(code) + hlsl(code) { + #define GI_PACK_ALGO GI_USE_SW_RGBE + #include + } +endmacro + +macro DAGI_HW_RGBE_SCREEN_ENCODING(code) + hlsl(code) { + #define GI_PACK_ALGO GI_USE_HW_RGBE + #include + } +endmacro + +macro DAGI_GAMMA2_SCREEN_ENCODING(code) hlsl(code) { - #define GI_PACK_ALGO 0 + #define GI_PACK_ALGO GI_USE_GAMMA2 #include } endmacro diff --git a/prog/gameLibs/daGI2/shaders/screen_gi_encoding.hlsl b/prog/gameLibs/daGI2/shaders/screen_gi_encoding.hlsl index df67a30e1..7e0b3d378 100644 --- a/prog/gameLibs/daGI2/shaders/screen_gi_encoding.hlsl +++ b/prog/gameLibs/daGI2/shaders/screen_gi_encoding.hlsl @@ -13,10 +13,6 @@ // but we can reduce a bit by sharing exponent between both colors, making it ~2.5% cost (or 50us) for encoding. decoding is just 10us // option 3) - use HW RGBE :) -#define GI_USE_HW_RGBE 0 -#define GI_USE_GAMMA2 1 -#define GI_USE_SW_RGBE 2 - // by default we should use SW RGBE. It is not that expensive and gives best quality // however, for now, for simplicity of formats compatibility, we keep GI_USE_GAMMA2 (as it is compatible with HW RGBE as well as gamma2) // adding SW support _by default_ is rather easy, but requires checking of assumption and gi_quality @@ -33,25 +29,32 @@ void encode_gi_colors(out GI_ENCODED_TYPE color1, out GI_ENCODED_TYPE color2, half3 rgb1, half3 rgb2) { - color1 = pow2(half3(rgb1.xy, rgb2.x)); - color2 = pow2(half3(rgb1.z, rgb2.zy)); // may be divide by ambient? + rgb1 = pow2(rgb1); + rgb2 = pow2(rgb2); + color1 = half3(rgb1.xy, rgb2.x); + color2 = half3(rgb1.z, rgb2.zy); // may be divide by ambient? } void decode_gi_colors(GI_ENCODED_TYPE color1, GI_ENCODED_TYPE color2, out half3 linear_rgb1, out half3 linear_rgb2) { - linear_rgb1 = sqrt(half3(color1.xy, color2.x)); - linear_rgb2 = sqrt(half3(color1.z, color2.zy)); + // safety is not needed, as we have to write everything we read in this pass + // however, nans are nasty! + color1 = sqrt(max(0, color1)); + color2 = sqrt(max(0, color2)); + linear_rgb1 = half3(color1.xy, color2.x); + linear_rgb2 = half3(color1.z, color2.zy); } void decode_weighted_colors(half4 r1, half4 g1, half4 b1, half4 r2, half4 g2, half4 b2, out half3 linear1, out half3 linear2, float4 weights) { - linear1.x = dot(sqrt(r1), weights); - linear1.y = dot(sqrt(g1), weights); - linear1.z = dot(sqrt(r2), weights); - - linear2.x = dot(sqrt(b1), weights); - linear2.y = dot(sqrt(b2), weights); - linear2.z = dot(sqrt(g2), weights); + //safety is needed as values that are read from previous are not guaranteed to be not nans (as we never write pixels with sky) + linear1.x = dot(sqrt(max(0, select(weights != 0, r1, half4(0,0,0,0)))), weights); + linear1.y = dot(sqrt(max(0, select(weights != 0, g1, half4(0,0,0,0)))), weights); + linear1.z = dot(sqrt(max(0, select(weights != 0, r2, half4(0,0,0,0)))), weights); + + linear2.x = dot(sqrt(max(0, select(weights != 0, b1, half4(0,0,0,0)))), weights); + linear2.y = dot(sqrt(max(0, select(weights != 0, b2, half4(0,0,0,0)))), weights); + linear2.z = dot(sqrt(max(0, select(weights != 0, g2, half4(0,0,0,0)))), weights); } #elif GI_PACK_ALGO == GI_USE_SW_RGBE @@ -111,9 +114,43 @@ void decode_weighted_colors(uint4 encoded1, uint4 encoded2, out half3 linear1, o linear1 += a*weights.w; linear2 += b*weights.w; } -#else +#elif GI_PACK_ALGO == GI_USE_HW_RGBE + +// no encoding (_probably_ hw rgbe5) + +#define GI_ENCODED_TYPE half3 +#define GI_ENCODED_CHANNELS 3 +#define GI_ENCODED_ATTR xyz + +void encode_gi_colors(out GI_ENCODED_TYPE color1, out GI_ENCODED_TYPE color2, half3 rgb1, half3 rgb2) +{ + color1 = half3(rgb1.xy, rgb2.x); + color2 = half3(rgb1.z, rgb2.zy); + // just in case it is still r11g11b10, swap ambient so it has same bits all over + //color1 = rgb1; + //color2 = rgb2; +} + +void decode_gi_colors(GI_ENCODED_TYPE color1, GI_ENCODED_TYPE color2, out half3 linear_rgb1, out half3 linear_rgb2) +{ + linear_rgb1 = half3(color1.xy, color2.x); + linear_rgb2 = half3(color1.z, color2.zy); +} + +void decode_weighted_colors(half4 r1, half4 g1, half4 b1, half4 r2, half4 g2, half4 b2, out half3 linear1, out half3 linear2, float4 weights) +{ + // NaNs are nasty, ensure we don't have those + linear1.x = dot(max(0, r1), weights); + linear1.y = dot(max(0, g1), weights); + linear1.z = dot(max(0, r2), weights); + linear2.x = dot(max(0, b1), weights); + linear2.y = dot(max(0, b2), weights); + linear2.z = dot(max(0, g2), weights); +} + +#elif GI_PACK_ALGO == GI_USE_NO_ENCODING -// no encoding (probably hw rgbe5) +// no encoding #define GI_ENCODED_TYPE half3 #define GI_ENCODED_CHANNELS 3 @@ -133,12 +170,12 @@ void decode_gi_colors(GI_ENCODED_TYPE color1, GI_ENCODED_TYPE color2, out half3 void decode_weighted_colors(half4 r1, half4 g1, half4 b1, half4 r2, half4 g2, half4 b2, out half3 linear1, out half3 linear2, float4 weights) { - linear1.x = dot(r1, weights); - linear1.y = dot(g1, weights); - linear1.z = dot(b1, weights); - linear2.x = dot(r2, weights); - linear2.y = dot(g2, weights); - linear2.z = dot(b2, weights); + linear1.x = dot(max(0, r1), weights); + linear1.y = dot(max(0, g1), weights); + linear1.z = dot(max(0, b1), weights); + linear2.x = dot(max(0, r2), weights); + linear2.y = dot(max(0, g2), weights); + linear2.z = dot(max(0, b2), weights); } #endif diff --git a/prog/gameLibs/daRg/behaviors/bhvDragAndDrop.cpp b/prog/gameLibs/daRg/behaviors/bhvDragAndDrop.cpp index eb5fdd2f5..c53167e2b 100644 --- a/prog/gameLibs/daRg/behaviors/bhvDragAndDrop.cpp +++ b/prog/gameLibs/daRg/behaviors/bhvDragAndDrop.cpp @@ -72,7 +72,9 @@ struct DragAndDropState BhvDragAndDrop bhv_drag_and_drop; -BhvDragAndDrop::BhvDragAndDrop() : Behavior(STAGE_BEFORE_RENDER, F_HANDLE_MOUSE | F_HANDLE_TOUCH | F_CAN_HANDLE_CLICKS) {} +BhvDragAndDrop::BhvDragAndDrop() : + Behavior(STAGE_BEFORE_RENDER, F_HANDLE_MOUSE | F_HANDLE_TOUCH | F_CAN_HANDLE_CLICKS), activeDrag(nullptr) +{} bool BhvDragAndDrop::willHandleClick(Element *elem) @@ -286,12 +288,15 @@ int BhvDragAndDrop::pointingEvent(ElementTree *etree, Element *elem, InputDevice return 0; if (accum_res & R_PROCESSED) return 0; + if (activeDrag != nullptr) + return 0; bool canDrag = !dropData.IsNull(); if (canDrag) { ddState->startDrag(device, pointer_id, pointer_pos, pointer_pos - elem->calcTransformedBbox().leftTop()); + activeDrag = ddState; elem->setGroupStateFlags(Element::S_DRAG); elem->updFlags(Element::F_ZORDER_ON_TOP, true); @@ -357,6 +362,8 @@ int BhvDragAndDrop::pointingEvent(ElementTree *etree, Element *elem, InputDevice elem->clearGroupStateFlags(Element::S_DRAG | activeStateFlag); + if (ddState == activeDrag) + activeDrag = nullptr; ddState->resetState(); if (elem->transform) elem->transform->translate.zero(); @@ -422,6 +429,8 @@ void BhvDragAndDrop::onDetach(Element *elem, DetachMode) callDragModeHandler(guiScene, elem, false); } + if (ddState == activeDrag) + activeDrag = nullptr; delete ddState; elem->props.storage.DeleteSlot(elem->csk->dragAndDropState); } @@ -444,6 +453,8 @@ int BhvDragAndDrop::onDeactivateInput(Element *elem, InputDevice device, int poi elem->updFlags(Element::F_ZORDER_ON_TOP, false); elem->clearGroupStateFlags(Element::S_DRAG | active_state_flags_for_device(ddState->activeDeviceId)); + if (ddState == activeDrag) + activeDrag = nullptr; ddState->resetState(); return R_REBUILD_RENDER_AND_INPUT_LISTS; diff --git a/prog/gameLibs/daRg/behaviors/bhvDragAndDrop.h b/prog/gameLibs/daRg/behaviors/bhvDragAndDrop.h index b3ad5fb1e..fa7ca25e5 100644 --- a/prog/gameLibs/daRg/behaviors/bhvDragAndDrop.h +++ b/prog/gameLibs/daRg/behaviors/bhvDragAndDrop.h @@ -37,6 +37,8 @@ class BhvDragAndDrop : public darg::Behavior const Point2 &pointer_pos, int accum_res); void applyPointerMove(const Point2 &pointer_pos, darg::DragAndDropState *ddState, darg::Element *elem, darg::ElementTree *etree, int activeStateFlag); + + DragAndDropState *activeDrag; }; diff --git a/prog/gameLibs/daRg/behaviors/bhvTextArea.cpp b/prog/gameLibs/daRg/behaviors/bhvTextArea.cpp index cb5118583..eacf15e26 100644 --- a/prog/gameLibs/daRg/behaviors/bhvTextArea.cpp +++ b/prog/gameLibs/daRg/behaviors/bhvTextArea.cpp @@ -5,10 +5,13 @@ #include #include #include +#include "guiScene.h" #include "textLayout.h" #include "textUtil.h" #include "dargDebugUtils.h" +#include "profiler.h" +#include namespace darg @@ -159,6 +162,9 @@ void BhvTextArea::onDelete(Element *elem) { deleteData(elem); } void BhvTextArea::recalc_content(const Element *elem, int /*axis*/, const Point2 &elem_size, Point2 &out_size) { + AutoProfileScope profile(GuiScene::get_from_elem(elem)->getProfiler(), M_RECALC_TEXTAREA); + TIME_PROFILE(bhv_textarea_recalc_content); + using namespace textlayout; out_size.zero(); diff --git a/prog/gameLibs/daRg/profiler.h b/prog/gameLibs/daRg/profiler.h index b63555613..b5fb2da9d 100644 --- a/prog/gameLibs/daRg/profiler.h +++ b/prog/gameLibs/daRg/profiler.h @@ -15,6 +15,8 @@ enum ProfilerMetricId M_BEFORE_RENDER_TOTAL, M_RENDER_TEXT, M_RENDER_9RECT, + M_RENDER_TEXTAREA, + M_RECALC_TEXTAREA, M_UPDATE_TOTAL, M_COMPONENT_SCRIPT, M_RENDER_LIST_REBUILD, diff --git a/prog/gameLibs/daRg/stdRendObj.cpp b/prog/gameLibs/daRg/stdRendObj.cpp index c1035efc8..df0e777e7 100644 --- a/prog/gameLibs/daRg/stdRendObj.cpp +++ b/prog/gameLibs/daRg/stdRendObj.cpp @@ -17,6 +17,7 @@ #include "scriptUtil.h" #include "textUtil.h" #include "profiler.h" +#include #include "dargDebugUtils.h" #include "robjMask.h" #include "robjDasCanvas.h" @@ -1434,6 +1435,9 @@ void RenderObjectProgressCircular::renderProgress(StdGuiRender::GuiContext &ctx, void RenderObjectTextArea::render(StdGuiRender::GuiContext &ctx, const Element *elem, const ElemRenderData *rdata, const RenderState &render_state) { + AutoProfileScope profile(GuiScene::get_from_elem(elem)->getProfiler(), M_RENDER_TEXTAREA); + TIME_PROFILE(bhv_render_textarea); + RobjParamsTextArea *params = static_cast(rdata->params); G_ASSERT(params); if (!params) @@ -1828,6 +1832,9 @@ bool RobjParamsBox::load(const Element *elem) borderColor = elem->props.getColor(elem->csk->borderColor); fillColor = elem->props.getColor(elem->csk->fillColor, E3DCOLOR(0, 0, 0, 0)); image = elem->props.getPicture(elem->csk->image); + keepAspect = resolve_keep_aspect(elem->props.scriptDesc.RawGetSlot(elem->csk->keepAspect)); + imageHalign = elem->props.getInt(elem->csk->imageHalign, ALIGN_CENTER); + imageValign = elem->props.getInt(elem->csk->imageValign, ALIGN_CENTER); fallbackImage = elem->props.getPicture(elem->csk->fallbackImage); flipX = elem->props.getBool(elem->csk->flipX); flipY = elem->props.getBool(elem->csk->flipY); @@ -2061,6 +2068,10 @@ void RenderObjectBox::render(StdGuiRender::GuiContext &ctx, const Element *elem, swap_vals(picLtTc.y, picRbTc.y); } + const Point2 picSz = PictureManager::get_picture_pix_size(pic.pic); + adjust_coord_for_image_aspect(picLt, picRb, picLtTc, picRbTc, rdata->pos, rdata->size, picSz, params->keepAspect, + params->imageHalign, params->imageValign); + ctx.render_rounded_image(picLt, picRb, picLtTc, picRbTc, fillColor, radius); ctx.reset_textures(); diff --git a/prog/gameLibs/das/math/maybe_pos.das b/prog/gameLibs/das/math/maybe_pos.das index 8f555d771..65fa6cb13 100644 --- a/prog/gameLibs/das/math/maybe_pos.das +++ b/prog/gameLibs/das/math/maybe_pos.das @@ -5,9 +5,25 @@ require math variant MaybePos pos : float3 - invalid : void? + invalid : bool + + +def MaybePos() + return MaybePos(invalid = true) + + +def MaybePos(pos : float3) + return MaybePos(pos = pos) variant MaybeTm tm : float3x4 - invalid : void? + invalid : bool + + +def MaybeTm() + return MaybeTm(invalid = true) + + +def MaybeTm(tm : float3x4) + return MaybeTm(tm = tm) diff --git a/prog/gameLibs/dasModules/common/dagorDebug3d.das b/prog/gameLibs/dasModules/common/dagorDebug3d.das index 41990838b..81436a9b7 100644 --- a/prog/gameLibs/dasModules/common/dagorDebug3d.das +++ b/prog/gameLibs/dasModules/common/dagorDebug3d.das @@ -2,43 +2,56 @@ options indenting = 2 require DagorDebug3D require DagorMath +let DEFAULT_DEBUG_COLOR = E3DCOLOR(0xffffffff) +let DEFAULT_DEBUG_FRAMES = 10 + [generic] -def draw_debug_line_buffered(p0, p1 : float3; color : E3DCOLOR; frames : int) +def draw_debug_line_buffered(p0, p1 : float3; color : E3DCOLOR = DEFAULT_DEBUG_COLOR; frames : int = DEFAULT_DEBUG_FRAMES) _builtin_draw_debug_line_buffered(p0, p1, color, frames) [generic] -def draw_debug_rect_buffered(p0, p1, p2 : float3; color : E3DCOLOR; frames : int) +def draw_debug_rect_buffered(p0, p1, p2 : float3; color : E3DCOLOR = DEFAULT_DEBUG_COLOR; frames : int = DEFAULT_DEBUG_FRAMES) _builtin_draw_debug_rect_buffered(p0, p1, p2, color, frames) [generic] -def draw_debug_box_buffered(box : BBox3; color : E3DCOLOR; frames : int) +def draw_debug_box_buffered(box : BBox3; color : E3DCOLOR = DEFAULT_DEBUG_COLOR; frames : int = DEFAULT_DEBUG_FRAMES) _builtin_draw_debug_box_buffered(box, color, frames) [generic] -def draw_debug_box_buffered(p1, p2 : float3; color : E3DCOLOR; frames : int) +def draw_debug_box_buffered(p1, p2 : float3; color : E3DCOLOR = DEFAULT_DEBUG_COLOR; frames : int = DEFAULT_DEBUG_FRAMES) let box = BBox3(p1, p2) _builtin_draw_debug_box_buffered(box, color, frames) [generic] -def draw_debug_box_buffered(p0, ax, ay, az : float3; color : E3DCOLOR; frames : int) +def draw_debug_box_buffered(p0, ax, ay, az : float3; color : E3DCOLOR = DEFAULT_DEBUG_COLOR; frames : int = DEFAULT_DEBUG_FRAMES) _builtin_draw_debug_box_buffered(p0, ax, ay, az, color, frames) [generic] -def draw_debug_box_buffered(box : BBox3; tm : float3x4; color : E3DCOLOR; frames : int) +def draw_debug_box_buffered(box : BBox3; tm : float3x4; color : E3DCOLOR = DEFAULT_DEBUG_COLOR; frames : int = DEFAULT_DEBUG_FRAMES) _builtin_draw_debug_box_buffered(box, tm, color, frames) [generic] -def draw_debug_elipse_buffered(pos, half_diag1, half_diag2 : float3; color : E3DCOLOR; segments : int; frames : int) +def draw_debug_elipse_buffered(pos, half_diag1, half_diag2 : float3; color : E3DCOLOR = DEFAULT_DEBUG_COLOR; segments : int = 24; frames : int = DEFAULT_DEBUG_FRAMES) _builtin_draw_debug_elipse_buffered(pos, half_diag1, half_diag2, color, segments, frames) [generic] -def draw_debug_circle_buffered(pos, norm : float3; radius; color : E3DCOLOR; segments : int; frames : int) +def draw_debug_circle_buffered(pos, norm : float3; radius; color : E3DCOLOR = DEFAULT_DEBUG_COLOR; segments : int = 24; frames : int = DEFAULT_DEBUG_FRAMES) _builtin_draw_debug_circle_buffered(pos, norm, float(radius), color, segments, frames) +// Can't add draw_debug_sphere_buffered overload with defaults as compiler wont be able to differentiate between +// (p0 : float3; radius; color : E3DCOLOR = DEFAULT_DEBUG_COLOR; segments : int = 24; frames : int = DEFAULT_DEBUG_FRAMES) +// and +// (p0 : float3; radius; color : E3DCOLOR = DEFAULT_DEBUG_COLOR; frames : int = DEFAULT_DEBUG_FRAMES) +// We can fix this by changing argument order here and all calls, but it's not really worth it? +[generic] +def draw_debug_sphere_buffered(p0 : float3; radius) + _builtin_draw_debug_sphere_buffered(p0, float(radius), DEFAULT_DEBUG_COLOR, 24, DEFAULT_DEBUG_FRAMES) + [generic] def draw_debug_sphere_buffered(p0 : float3; radius; color : E3DCOLOR; segments : int; frames : int) _builtin_draw_debug_sphere_buffered(p0, float(radius), color, segments, frames) + [generic] def draw_debug_sphere_buffered(p : float3x4; radius; color : E3DCOLOR; segments : int; frames : int) _builtin_draw_debug_sphere_buffered(p[3], float(radius), color, segments, frames) @@ -48,43 +61,43 @@ def draw_debug_sphere_buffered(p0 : float3; radius; color : E3DCOLOR; frames : i _builtin_draw_debug_sphere_buffered(p0, float(radius), color, 12, frames) [generic] -def draw_debug_tube_buffered(p0, p1 : float3; radius; color : E3DCOLOR; segs : int; circle_density; frames : int) +def draw_debug_tube_buffered(p0, p1 : float3; radius; color : E3DCOLOR = DEFAULT_DEBUG_COLOR; segs : int = 24; circle_density = 0.1; frames : int = DEFAULT_DEBUG_FRAMES) _builtin_draw_debug_tube_buffered(p0, p1, float(radius), color, segs, float(circle_density), frames) [generic] -def draw_debug_cone_buffered(p0, p1 : float3; radius; color : E3DCOLOR; segs : int; frames : int) +def draw_debug_cone_buffered(p0, p1 : float3; radius; color : E3DCOLOR = DEFAULT_DEBUG_COLOR; segs : int = 24; frames : int = DEFAULT_DEBUG_FRAMES) _builtin_draw_debug_cone_buffered(p0, p1, float(radius), color, segs, frames) [generic] -def draw_debug_capsule_buffered(p0, p1 : float3; radius; color : E3DCOLOR; segments : int; frames : int) +def draw_debug_capsule_buffered(p0, p1 : float3; radius; color : E3DCOLOR = DEFAULT_DEBUG_COLOR; segments : int = 24; frames : int = DEFAULT_DEBUG_FRAMES) _builtin_draw_debug_capsule_buffered(p0, p1, float(radius), color, segments, frames) [generic] -def draw_debug_arrow_buffered(from, to : float3; color : E3DCOLOR; frames : int) +def draw_debug_arrow_buffered(from, to : float3; color : E3DCOLOR = DEFAULT_DEBUG_COLOR; frames : int = DEFAULT_DEBUG_FRAMES) _builtin_draw_debug_arrow_buffered(from, to, color, frames) [generic] -def draw_cached_debug_quad(p0, p1, p2, p3 : float3; color : E3DCOLOR) +def draw_cached_debug_quad(p0, p1, p2, p3 : float3; color : E3DCOLOR = DEFAULT_DEBUG_COLOR) _builtin_draw_cached_debug_quad(p0, p1, p2, p3, color) [generic] -def draw_cached_debug_trilist(arr : array | float3[]; color : E3DCOLOR) +def draw_cached_debug_trilist(arr : array | float3[]; color : E3DCOLOR = DEFAULT_DEBUG_COLOR) verify(length(arr) % 3 == 0) _builtin_draw_cached_debug_trilist(unsafe(addr(arr[0])), length(arr) / 3, color) //Use negative radius to turn it upside down [generic] -def draw_debug_tetrapod_buffered(p0 : float3; radius; color : E3DCOLOR; frames : int) +def draw_debug_tetrapod_buffered(p0 : float3; radius; color : E3DCOLOR = DEFAULT_DEBUG_COLOR; frames : int = DEFAULT_DEBUG_FRAMES) _builtin_draw_debug_tetrapod_buffered(p0, float(radius), color, frames) [generic] -def draw_debug_tetrapod_buffered(p : float3x4; radius; color : E3DCOLOR; frames : int) +def draw_debug_tetrapod_buffered(p : float3x4; radius; color : E3DCOLOR = DEFAULT_DEBUG_COLOR; frames : int = DEFAULT_DEBUG_FRAMES) _builtin_draw_debug_tetrapod_buffered(p[3], float(radius), color, frames) [generic] -def draw_debug_tehedron_buffered(p0 : float3; radius; color : E3DCOLOR; frames : int) +def draw_debug_tehedron_buffered(p0 : float3; radius; color : E3DCOLOR = DEFAULT_DEBUG_COLOR; frames : int = DEFAULT_DEBUG_FRAMES) _builtin_draw_debug_tehedron_buffered(p0, float(radius), color, frames) [generic] -def draw_debug_tehedron_buffered(p : float3x4; radius; color : E3DCOLOR; frames : int) +def draw_debug_tehedron_buffered(p : float3x4; radius; color : E3DCOLOR = DEFAULT_DEBUG_COLOR; frames : int = DEFAULT_DEBUG_FRAMES) _builtin_draw_debug_tehedron_buffered(p[3], float(radius), color, frames) diff --git a/prog/gameLibs/dasModules/common/scriptsLoader.cpp b/prog/gameLibs/dasModules/common/scriptsLoader.cpp index 69e798a68..8c8017b58 100644 --- a/prog/gameLibs/dasModules/common/scriptsLoader.cpp +++ b/prog/gameLibs/dasModules/common/scriptsLoader.cpp @@ -117,7 +117,6 @@ bool DasScripts::loadScriptInternal(const das::string & policies.no_unsafe = sandboxMode; policies.no_aliasing = true; policies.strict_unsafe_delete = true; - policies.strict_smart_pointers = true; policies.stack = 4096; das::ProgramPtr program; diff --git a/prog/gameLibs/dasModules/phys/dacoll.cpp b/prog/gameLibs/dasModules/phys/dacoll.cpp index 949097416..657e61a58 100644 --- a/prog/gameLibs/dasModules/phys/dacoll.cpp +++ b/prog/gameLibs/dasModules/phys/dacoll.cpp @@ -254,14 +254,14 @@ class DacollModule final : public das::Module das::addExtern(*this, lib, "dacoll_use_capsule_collision", das::SideEffects::modifyExternal, "bind_dascript::use_capsule_collision"); - das::addExtern(*this, lib, "dacoll_shape_query_frt", das::SideEffects::accessExternal, - "bind_dascript::dacoll_shape_query_frt"); - das::addExtern(*this, lib, "dacoll_shape_query_lmesh", das::SideEffects::accessExternal, - "bind_dascript::dacoll_shape_query_lmesh"); - das::addExtern(*this, lib, "dacoll_shape_query_ri", das::SideEffects::accessExternal, - "bind_dascript::dacoll_shape_query_ri"); - das::addExtern(*this, lib, "dacoll_shape_query_world", das::SideEffects::accessExternal, - "bind_dascript::dacoll_shape_query_world"); + das::addExtern(*this, lib, "dacoll_shape_query_frt", + das::SideEffects::modifyArgumentAndAccessExternal, "bind_dascript::dacoll_shape_query_frt"); + das::addExtern(*this, lib, "dacoll_shape_query_lmesh", + das::SideEffects::modifyArgumentAndAccessExternal, "bind_dascript::dacoll_shape_query_lmesh"); + das::addExtern(*this, lib, "dacoll_shape_query_ri", + das::SideEffects::modifyArgumentAndAccessExternal, "bind_dascript::dacoll_shape_query_ri"); + das::addExtern(*this, lib, "dacoll_shape_query_world", + das::SideEffects::modifyArgumentAndAccessExternal, "bind_dascript::dacoll_shape_query_world"); das::addExtern(*this, lib, "dacoll_set_hmap_step", das::SideEffects::modifyExternal, "dacoll::set_hmap_step"); diff --git a/prog/gameLibs/dasModules/sound/aotSoundEvent.cpp b/prog/gameLibs/dasModules/sound/aotSoundEvent.cpp index 25727d6e1..2bfd4d3bc 100644 --- a/prog/gameLibs/dasModules/sound/aotSoundEvent.cpp +++ b/prog/gameLibs/dasModules/sound/aotSoundEvent.cpp @@ -273,6 +273,10 @@ class SoundEventModule final : public das::Module SND_BIND_FUN_EX(__get_max_distance, "get_max_distance", das::SideEffects::accessExternal); SND_BIND_FUN_EX(get_max_distance_by_name, "get_max_distance", das::SideEffects::accessExternal); + SND_BIND_FUN(set_occlusion_group, das::SideEffects::modifyExternal); + SND_BIND_FUN(set_occlusion_pos, das::SideEffects::modifyExternal); + SND_BIND_FUN(is_occlusion_inited, das::SideEffects::accessExternal); + SND_BIND_FUN_EX(das_query_visual_labels, "query_visual_labels", das::SideEffects::modifyExternal); SND_BIND_FUN(create_event_instance_stealing_group, das::SideEffects::modifyExternal); diff --git a/prog/gameLibs/decalMatrices/decalsMatrices.cpp b/prog/gameLibs/decalMatrices/decalsMatrices.cpp index 6c1837bac..3efbb84a4 100644 --- a/prog/gameLibs/decalMatrices/decalsMatrices.cpp +++ b/prog/gameLibs/decalMatrices/decalsMatrices.cpp @@ -262,7 +262,8 @@ bool DecalsMatrices::isMatrixRemoved(uint32_t matrix_id) const if (matrix_id == INVALID_MATRIX_ID) return false; matrix_id--; - G_ASSERT_RETURN(matrix_id < removedMatrices.size(), false); + G_ASSERTF_RETURN(matrix_id < removedMatrices.size(), false, + "DecalsMatrices::isMatrixRemoved oob: matrix_id >= removedMatrices.size. %d >= %d", matrix_id, removedMatrices.size()); return removedMatrices[matrix_id]; } diff --git a/prog/gameLibs/eventLog/errorLog.cpp b/prog/gameLibs/eventLog/errorLog.cpp index f5f4ebeb3..434de646f 100644 --- a/prog/gameLibs/eventLog/errorLog.cpp +++ b/prog/gameLibs/eventLog/errorLog.cpp @@ -138,9 +138,6 @@ void send_error_log(const char *error_message, ErrorLogSendParams const ¶ms) stackhelp::ext::CallStackCaptureStore extStack; stack.capture(); extStack.capture(); -#if _TARGET_PC_WIN - eventStr.append_sprintf("BP=%p\n", stackhlp_get_bp()); -#endif eventStr.append(get_call_stack_str(stack, extStack)); } diff --git a/prog/gameLibs/gamePhys/collision/rendinstCollision.cpp b/prog/gameLibs/gamePhys/collision/rendinstCollision.cpp index 0b7d99b6a..3aa5d762c 100644 --- a/prog/gameLibs/gamePhys/collision/rendinstCollision.cpp +++ b/prog/gameLibs/gamePhys/collision/rendinstCollision.cpp @@ -87,14 +87,9 @@ void update_ri_cache_in_volume_to_phys_world(const BBox3 &box) get_phys_world()->fetchSimRes(true); - TMatrix tm = TMatrix::IDENT; - tm.setcol(3, box.center()); - RIAddToWorldCB callback; - - BBox3 localBox(box.lim[0] - tm.getcol(3), box.lim[1] - tm.getcol(3)); - rendinst::testObjToRIGenIntersection(localBox, tm, callback, rendinst::GatherRiTypeFlag::RiGenAndExtra, nullptr /*cache*/, - PHYSMAT_INVALID, true /*unlock_in_cb*/); + rendinst::testObjToRIGenIntersection(box, callback, rendinst::GatherRiTypeFlag::RiGenAndExtra, nullptr /*cache*/, PHYSMAT_INVALID, + true /*unlock_in_cb*/); } bool test_collision_ri(const CollisionObject &co, const BBox3 &box, Tab &out_contacts, @@ -230,18 +225,11 @@ void shape_query_ri(const PhysBody *shape, const TMatrix &from, const TMatrix &t SweepCollisionCB sweepCb(shape, from, to, cast_mat_id, out, out_desc, filterCB); RICollisionCB callback(sweepCb); - - BBox3 box; // around from point - box += Point3(0.f, 0.f, 0.f); - box += to.getcol(3) - from.getcol(3); - box.inflate(rad); + Capsule capsule(from.getcol(3), to.getcol(3), rad); if (handle) { - mat44f vtm; - v_mat44_make_from_43cu_unsafe(vtm, from.array); - bbox3f castBox; - v_bbox3_init(castBox, vtm, v_ldu_bbox3(box)); + bbox3f castBox = capsule.getBoundingBox(); bool res = try_use_trace_cache(castBox, handle); BBox3 wbox; @@ -251,7 +239,7 @@ void shape_query_ri(const PhysBody *shape, const TMatrix &from, const TMatrix &t handle = nullptr; } - rendinst::testObjToRIGenIntersection(box, from, callback, rendinst::GatherRiTypeFlag::RiGenAndExtra, handle, cast_mat_id, + rendinst::testObjToRIGenIntersection(capsule, callback, rendinst::GatherRiTypeFlag::RiGenAndExtra, handle, cast_mat_id, true /*unlock_in_cb*/); #if DA_PROFILER_ENABLED DA_PROFILE_TAG(shape_query_ri, ": %u contacts", sweepCb.contactsNum); diff --git a/prog/gameLibs/gpuObjects/volumePlacerES.cpp.inl b/prog/gameLibs/gpuObjects/volumePlacerES.cpp.inl index 66ff01995..580857990 100644 --- a/prog/gameLibs/gpuObjects/volumePlacerES.cpp.inl +++ b/prog/gameLibs/gpuObjects/volumePlacerES.cpp.inl @@ -183,8 +183,8 @@ static void adjust_transform_to_border_offset(const Point2 *offset, int axis_ind float adjustedLength = axisLength - offsetV.x - offsetV.y; if (adjustedLength <= 0.0f) { - LOGERR_ONCE("GPUObjectsPlacer: box borders are too big for the object. Axis=%@, offset=%@, pos=%@", axis_index, offsetV, - transform.getcol(3)); + logerr("GPUObjectsPlacer: box borders are too big for the object. Axis=%@, length=%@, offset=%@, pos=%@", axis_index, axisLength, + offsetV, transform.getcol(3)); return; } transform.setcol(axis_index, axis * (adjustedLength / axisLength)); diff --git a/prog/gameLibs/heightmap/shaders/heightmap_common.dshl b/prog/gameLibs/heightmap/shaders/heightmap_common.dshl index 22da1c409..0988725d4 100644 --- a/prog/gameLibs/heightmap/shaders/heightmap_common.dshl +++ b/prog/gameLibs/heightmap/shaders/heightmap_common.dshl @@ -76,7 +76,16 @@ macro USE_HEIGHTMAP_COMMON_VS() float getHeight(float2 worldPosXZ) { float2 tc_low = calcTcLow(worldPosXZ); - float height = tex2Dlod(tex_hmap_low, float4(tc_low,0,0)).r; + + float2 tc_texels = tc_low * tex_hmap_low_size.xy - 0.5; + float2 tc_frac = frac(tc_texels); + float2 centerTc = (floor(tc_texels) + 1.0) * tex_hmap_low_size.zw; + float4 hmap4 = tex_hmap_low.GatherRed(tex_hmap_low_samplerstate, centerTc); + + float4 bilW = float4(1-tc_frac, tc_frac); + bilW = bilW.xzzx*bilW.wwyy; + + float height = dot(hmap4, bilW); #if has_high_texture float2 tc_high = worldPosXZ*world_to_hmap_high.xy + world_to_hmap_high.zw; float2 tc_high_sat = saturate(tc_high); @@ -384,6 +393,9 @@ endmacro macro INIT_WORLD_HEIGHTMAP_VS() (vs) { + tex_hmap_low_size@f4 = (get_dimensions(tex_hmap_low, 0).xy, + 1.0 / max(get_dimensions(tex_hmap_low, 0).x, 1), + 1.0 / max(get_dimensions(tex_hmap_low, 0).y, 1)); world_to_hmap_low@f4 = (world_to_hmap_low.x, world_to_hmap_low.y, world_to_hmap_low.z + 0.5*tex_hmap_inv_sizes.x, world_to_hmap_low.w+0.5*tex_hmap_inv_sizes.y); heightmap_region@f4 = heightmap_region; } diff --git a/prog/gameLibs/pathFinder/customNav.cpp b/prog/gameLibs/pathFinder/customNav.cpp index 4595a27b5..e963d41d8 100644 --- a/prog/gameLibs/pathFinder/customNav.cpp +++ b/prog/gameLibs/pathFinder/customNav.cpp @@ -196,6 +196,34 @@ void CustomNav::walkAreaTiles(const Area &area, T cb) } } +static void debug_log_tile_info(uint32_t tile_id) +{ + const dtNavMesh *navMesh = getNavMeshPtr(); + const int tileId = (int)tile_id; + if (!navMesh) + { + debug("nav tile id=%d: no navmesh", tileId); + return; + } + const int maxTiles = navMesh->getMaxTiles(); + if (tileId < 0 || tileId >= maxTiles) + { + debug("nav tile id=%d/%d: bad tile id", tileId, maxTiles); + return; + } + const dtMeshTile *tile = navMesh->getTile(tileId); + if (!tile || !tile->header) + { + debug("nav tile id=%d/%d: null", tileId, maxTiles); + return; + } + const dtMeshHeader *th = tile->header; + debug("nav tile id=%d: x=%d y=%d layer=%d pc=%d vc=%d mlc=%d dmc=%d dvc=%d dtc=%d bnc=%d occ=%d bmin(%f %f %f) bmax(%f %f %f)", + tileId, th->x, th->y, th->layer, th->polyCount, th->vertCount, th->maxLinkCount, th->detailMeshCount, th->detailVertCount, + th->detailTriCount, th->bvNodeCount, th->offMeshConCount, th->bmin[0], th->bmin[1], th->bmin[2], th->bmax[0], th->bmax[1], + th->bmax[2]); +} + void CustomNav::addAreaToTile(Area &area, uint32_t tile_id) { Tile &tile = tiles[tile_id]; @@ -206,7 +234,12 @@ void CustomNav::addAreaToTile(Area &area, uint32_t tile_id) if (DAGOR_UNLIKELY(a.id == area.id)) { logerr("a.id == area.id %d == %d for cylinder area in %s", a.id, area.id, __FUNCTION__); - debug("tile count %d and gen %d, tile_id %u", area.tileCount, area.generation, tile_id); + debug("tile count (%d vs %d) and gen (%d vs %d), tile_id %u", a.tileCount, area.tileCount, a.generation, area.generation, + tile_id); + debug_log_tile_info(tile_id); + BBox3 abb = a.getAABB(); + debug("customNav a bbox %f %f %f %f %f %f", abb.boxMin().x, abb.boxMin().y, abb.boxMin().z, abb.boxMax().x, abb.boxMax().y, + abb.boxMax().z); BBox3 bbox = area.getAABB(); debug("customNav area bbox %f %f %f %f %f %f", bbox.boxMin().x, bbox.boxMin().y, bbox.boxMin().z, bbox.boxMax().x, bbox.boxMax().y, bbox.boxMax().z); @@ -223,7 +256,12 @@ void CustomNav::addAreaToTile(Area &area, uint32_t tile_id) if (DAGOR_UNLIKELY(a.id == area.id)) { logerr("a.id == area.id %d == %d for box area in %s", a.id, area.id, __FUNCTION__); - debug("tile count %d and gen %d, tile_id %u", area.tileCount, area.generation, tile_id); + debug("tile count (%d vs %d) and gen (%d vs %d), tile_id %u", a.tileCount, area.tileCount, a.generation, area.generation, + tile_id); + debug_log_tile_info(tile_id); + BBox3 abb = a.getAABB(); + debug("customNav a bbox %f %f %f %f %f %f", abb.boxMin().x, abb.boxMin().y, abb.boxMin().z, abb.boxMax().x, abb.boxMax().y, + abb.boxMax().z); BBox3 bbox = area.getAABB(); debug("customNav area bbox %f %f %f %f %f %f", bbox.boxMin().x, bbox.boxMin().y, bbox.boxMin().z, bbox.boxMax().x, bbox.boxMax().y, bbox.boxMax().z); @@ -285,7 +323,12 @@ void CustomNav::restoreLostTiles() } } -void CustomNav::removeTile(uint32_t tile_id) { tiles.erase(tile_id); } +void CustomNav::removeTile(uint32_t tile_id) +{ + restoreLostTiles(); + + tiles.erase(tile_id); +} void CustomNav::areaRemoveFromTiles(Area &area, Tab &affected_tiles) { diff --git a/prog/gameLibs/pathFinder/tileCache/rebuildNavMesh.cpp b/prog/gameLibs/pathFinder/tileCache/rebuildNavMesh.cpp index 39b9e9506..fed6f3d8d 100644 --- a/prog/gameLibs/pathFinder/tileCache/rebuildNavMesh.cpp +++ b/prog/gameLibs/pathFinder/tileCache/rebuildNavMesh.cpp @@ -460,7 +460,7 @@ void collect_rendinst(const BBox3 &box, Tab &vertices, Tab &indices RendinstVertexDataCbGame cb(vertices, indices, transparent, navmeshLayers.pools, navmeshLayers.obstaclePools, navmeshLayers.materialPools, navmeshLayers.obstaclesSettings, obstacles); - rendinst::testObjToRIGenIntersection(box, TMatrix::IDENT, cb, rendinst::GatherRiTypeFlag::RiGenAndExtra); + rendinst::testObjToRIGenIntersection(box, cb, rendinst::GatherRiTypeFlag::RiGenAndExtra); cb.procAllCollision(); } diff --git a/prog/gameLibs/publicInclude/bvh/bvh.h b/prog/gameLibs/publicInclude/bvh/bvh.h index 635237d84..17a036f7a 100644 --- a/prog/gameLibs/publicInclude/bvh/bvh.h +++ b/prog/gameLibs/publicInclude/bvh/bvh.h @@ -487,6 +487,8 @@ struct ChannelParser : public ShaderChannelsEnumCB int stream) override; }; +bool has_enough_vram_for_rt(); + void set_enable(bool enable); bool is_available(); @@ -563,4 +565,5 @@ bool is_building(ContextId context_id); void set_grass_range(ContextId context_id, float range); +void enable_per_frame_processing(bool enable); } // namespace bvh \ No newline at end of file diff --git a/prog/gameLibs/publicInclude/daFx/dafx.h b/prog/gameLibs/publicInclude/daFx/dafx.h index 63cbb8df2..d80f9d12a 100644 --- a/prog/gameLibs/publicInclude/daFx/dafx.h +++ b/prog/gameLibs/publicInclude/daFx/dafx.h @@ -192,14 +192,16 @@ enum class SortingType : int struct CullingDesc { - CullingDesc(const eastl::string &t, SortingType s, int vrs_rate = 0, float screen_discard_threshold = 0) : - tag(t), sortingType(s), vrsRate(vrs_rate), screenAreaDiscardThreshold(screen_discard_threshold) + CullingDesc(const eastl::string &t, SortingType s, int vrs_rate = 0, float screen_discard_threshold = 0, + uint32_t visibility_mask = 0xffffffff) : + tag(t), sortingType(s), vrsRate(vrs_rate), screenAreaDiscardThreshold(screen_discard_threshold), visibilityMask(visibility_mask) {} int vrsRate; float screenAreaDiscardThreshold; eastl::string tag; SortingType sortingType; + uint32_t visibilityMask; }; struct SystemDesc @@ -272,6 +274,7 @@ void update_culling_state(ContextId cid, CullingId cullid, const Frustum &frustu void update_culling_state(ContextId cid, CullingId cullid, const Frustum &frustum, const mat44f &globtm, const Point3 &view_pos, Occlusion *(*occlusion_sync_wait_f)() = nullptr); void clear_culling_state(ContextId cid, CullingId cullid); +uint32_t get_culling_state_visiblity_mask(ContextId cid, CullingId cullid); void remap_culling_state_tag(ContextId cid, CullingId cullid, const eastl::string &from, const eastl::string &to); // pass same values // to reset remap uint32_t inverse_remap_tags_mask(ContextId cid, uint32_t tags_mask); @@ -323,7 +326,7 @@ void set_instance_pos(ContextId cid, InstanceId iid, const Point4 &pos); // for void set_instance_emission_rate(ContextId cid, InstanceId iid, float v); void set_instance_status(ContextId cid, InstanceId iid, bool enabled); bool get_instance_status(ContextId cid, InstanceId iid); -void set_instance_visibility(ContextId cid, InstanceId iid, bool visible); +void set_instance_visibility(ContextId cid, InstanceId iid, uint32_t visibility); bool is_instance_renderable_active(ContextId cid, InstanceId iid); bool is_instance_renderable_visible(ContextId cid, InstanceId iid); bool get_instance_value(ContextId cid, InstanceId iid, int offset, void *out_data, int size); @@ -469,6 +472,12 @@ struct Stats }; Queue queue[2]; // 2 last frames + eastl::array cpuElemProcessedByLods; + eastl::array gpuElemProcessedByLods; + + eastl::array cpuElemTotalSimLods; + eastl::array gpuElemTotalSimLods; + eastl::array drawCallsByRenderTags; }; diff --git a/prog/gameLibs/publicInclude/daRg/dag_stdRendObj.h b/prog/gameLibs/publicInclude/daRg/dag_stdRendObj.h index 27991b6f6..fa6f23c81 100644 --- a/prog/gameLibs/publicInclude/daRg/dag_stdRendObj.h +++ b/prog/gameLibs/publicInclude/daRg/dag_stdRendObj.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include @@ -23,6 +24,9 @@ class RobjParamsBox : public RendObjParams Point4 borderWidth; Point4 borderRadius; Picture *image = nullptr; + KeepAspectMode keepAspect = KEEP_ASPECT_NONE; + ElemAlign imageHalign = ALIGN_CENTER; + ElemAlign imageValign = ALIGN_CENTER; Picture *fallbackImage = nullptr; bool flipX = false; bool flipY = false; diff --git a/prog/gameLibs/publicInclude/dasModules/aotRendInst.h b/prog/gameLibs/publicInclude/dasModules/aotRendInst.h index c4e46344c..09ddf922a 100644 --- a/prog/gameLibs/publicInclude/dasModules/aotRendInst.h +++ b/prog/gameLibs/publicInclude/dasModules/aotRendInst.h @@ -215,14 +215,8 @@ inline void rendinst_foreachRIGenInBox(const BBox3 &box, bool test_riextra_col, inline void rendinst_foreachTreeInBox(const bbox3f &bbox, const das::TBlock &block, das::Context *context, das::LineInfoArg *at) { - Point3_vec4 bmin; - Point3_vec4 bmax; - v_st(&bmin.x, bbox.bmin); - v_st(&bmax.x, bbox.bmax); - - TMatrix tm = TMatrix::IDENT; - tm.setcol(3, (bmin + bmax) * 0.5); - BBox3 localBox(bmin - tm.getcol(3), bmax - tm.getcol(3)); + BBox3 bb; + v_stu_bbox3(bb, bbox); vec4f args[1]; context->invokeEx( @@ -246,7 +240,7 @@ inline void rendinst_foreachTreeInBox(const bbox3f &bbox, const das::TBlock #include #include +#include #include #include @@ -322,6 +323,15 @@ inline float __get_max_distance(const SoundEvent &sound_event) { return sndsys:: inline float get_max_distance_by_name(const char *name) { return sndsys::get_max_distance(name); } +inline void set_occlusion_group(sndsys::EventHandle handle, sndsys::occlusion::group_id_t group_id) +{ + sndsys::occlusion::set_event_group(handle, group_id); +} + +inline void set_occlusion_pos(sndsys::occlusion::group_id_t group_id, Point3 pos) { sndsys::occlusion::set_group_pos(group_id, pos); } + +inline bool is_occlusion_inited() { return sndsys::occlusion::is_inited(); } + inline bool das_query_visual_labels(const das::TBlock>> &block, das::Context *context, das::LineInfoArg *at) { diff --git a/prog/gameLibs/publicInclude/decalMatrices/decal_matrices_const.hlsli b/prog/gameLibs/publicInclude/decalMatrices/decal_matrices_const.hlsli index e53c2dbc4..20296b082 100644 --- a/prog/gameLibs/publicInclude/decalMatrices/decal_matrices_const.hlsli +++ b/prog/gameLibs/publicInclude/decalMatrices/decal_matrices_const.hlsli @@ -3,7 +3,7 @@ #define SPRAY_DECALS_MAX_MATRICES_COUNT 300 #define BILLBOARD_DECALS_MAX_MATRICES_COUNT 300 -#define BLOOD_PUDDLES_MAX_MATRICES_COUNT 300 +#define BLOOD_PUDDLES_MAX_MATRICES_COUNT 384 #define HEAT_SOURCE_DECALS_MAX_MATRICES_COUNT 1024 #endif \ No newline at end of file diff --git a/prog/gameLibs/publicInclude/eventLog/dag_netAssert.h b/prog/gameLibs/publicInclude/eventLog/dag_netAssert.h index f8f2b0ddb..3aab83937 100644 --- a/prog/gameLibs/publicInclude/eventLog/dag_netAssert.h +++ b/prog/gameLibs/publicInclude/eventLog/dag_netAssert.h @@ -16,15 +16,14 @@ extern bool fatal_on_net_assert; #include #include "eventLog.h" #if _TARGET_PC_WIN -#define NET_EVENT_STRING(str, exp_string) \ - String str; \ - { \ - stackhelp::CallStackCaptureStore<32> stack; \ - stackhelp::ext::CallStackCaptureStore extStack; \ - stack.capture(); \ - extStack.capture(); \ - str.printf(256, "%s:%s:\nBP=%p\nST:\n%s", event_log::get_net_assert_version(), exp_string, stackhlp_get_bp(), \ - get_call_stack_str(stack, extStack)); \ +#define NET_EVENT_STRING(str, exp_string) \ + String str; \ + { \ + stackhelp::CallStackCaptureStore<32> stack; \ + stackhelp::ext::CallStackCaptureStore extStack; \ + stack.capture(); \ + extStack.capture(); \ + str.printf(256, "%s:%s:\nST:\n%s", event_log::get_net_assert_version(), exp_string, get_call_stack_str(stack, extStack)); \ } #else #define NET_EVENT_STRING(str, exp_string) \ diff --git a/prog/gameLibs/publicInclude/gpuReadbackQuery/gpuReadbackQuerySystem.h b/prog/gameLibs/publicInclude/gpuReadbackQuery/gpuReadbackQuerySystem.h index 98359babd..47d41422e 100644 --- a/prog/gameLibs/publicInclude/gpuReadbackQuery/gpuReadbackQuerySystem.h +++ b/prog/gameLibs/publicInclude/gpuReadbackQuery/gpuReadbackQuerySystem.h @@ -15,6 +15,7 @@ #include #include #include +#include #include "3d/dag_sbufferIDHolder.h" #include "3d/dag_ringCPUQueryLock.h" #include "shaders/dag_computeShaders.h" @@ -152,6 +153,9 @@ template void GpuReadbackQuerySystem::update() { deleteReadQueries(); + + if (d3d::is_in_device_reset_now()) + return; dispatchNewQueries(); completeQueries(); } diff --git a/prog/gameLibs/publicInclude/quirrel/frp/dag_frp.h b/prog/gameLibs/publicInclude/quirrel/frp/dag_frp.h index 1c32af579..5087bb987 100644 --- a/prog/gameLibs/publicInclude/quirrel/frp/dag_frp.h +++ b/prog/gameLibs/publicInclude/quirrel/frp/dag_frp.h @@ -152,7 +152,8 @@ class ObservablesGraph int generation = 0; bool checkNestedObservable = false; bool forceImmutable = false; - bool defaultDeferred = true; + bool defaultDeferredComputed = true; + bool defaultDeferredWatched = true; bool doCollectSourcesRecursively = false; bool needRecalc = false; @@ -203,6 +204,15 @@ class BaseObservable virtual Sqrat::Object trace() { return Sqrat::Object(); } virtual HSQOBJECT getCurScriptInstance(); + inline bool getNeedImmediate() const { return needImmediate; } + void updateNeedImmediate(bool certainly_immediate); + inline bool getDeferred() const { return isDeferred; } + inline void setDeferred(bool v) + { + isDeferred = v; + updateNeedImmediate(!v); + } + void collectScriptSubscribers(Tab &container) const; protected: @@ -217,6 +227,8 @@ class BaseObservable bool isIteratingWatchers : 1; bool isInTrigger : 1; bool willNotify : 1; + bool isDeferred : 1; + bool needImmediate : 1; // ScriptValueObservable bool checkNestedObservable : 1; @@ -230,8 +242,6 @@ class BaseObservable bool needRecalc : 1; bool maybeRecalc : 1; bool isUsed : 1; - bool isDeferred : 1; - bool needImmediate : 1; bool isShuttingDown : 1; bool funcAcceptsCurVal : 1; }; @@ -369,16 +379,8 @@ class ComputedValue final : public ScriptValueObservable, public IStateWatcher, inline bool getNeedRecalc() const { return needRecalc; } inline bool getUsed() const { return isUsed; } void updateUsed(bool certainly_used); - inline bool getNeedImmediate() const { return needImmediate; } - void updateNeedImmediate(bool certainly_immediate); inline bool getMarked() const { return isMarked; } - inline bool getDeferred() const { return isDeferred; } - inline void setDeferred(bool v) - { - isDeferred = v; - updateNeedImmediate(!v); - } ComputedValue *addImplicitSource(ComputedValue *c) { @@ -399,6 +401,7 @@ class ComputedValue final : public ScriptValueObservable, public IStateWatcher, protected: friend class ObservablesGraph; + friend class BaseObservable; friend void graph_viewer(); Sqrat::Function func; dag::Vector sources; diff --git a/prog/gameLibs/publicInclude/rendInst/rendInstCollision.h b/prog/gameLibs/publicInclude/rendInst/rendInstCollision.h index 286dd3adb..e7fc0beef 100644 --- a/prog/gameLibs/publicInclude/rendInst/rendInstCollision.h +++ b/prog/gameLibs/publicInclude/rendInst/rendInstCollision.h @@ -79,6 +79,8 @@ struct OrientedObjectBox }; void testObjToRIGenIntersection(const BBox3 &obj_box, const TMatrix &obj_tm, RendInstCollisionCB &callback, GatherRiTypeFlags ri_types, const TraceMeshFaces *ri_cache = nullptr, PhysMat::MatID ray_mat = PHYSMAT_INVALID, bool unlock_in_cb = false); +void testObjToRIGenIntersection(const Capsule &obj_capsule, RendInstCollisionCB &callback, GatherRiTypeFlags ri_types, + const TraceMeshFaces *ri_cache = nullptr, PhysMat::MatID ray_mat = PHYSMAT_INVALID, bool unlock_in_cb = false); inline bool testObjectToRendinstIntersection(CollisionResource *object_res, const CollisionNodeFilter &filter, const TMatrix &object_tm, const Point3 &velocity, Point3 *intersected_object_pos, String *intersected_object_name, diff --git a/prog/gameLibs/publicInclude/rendInst/rendInstExtra.h b/prog/gameLibs/publicInclude/rendInst/rendInstExtra.h index d59a8ca04..16ba02c22 100644 --- a/prog/gameLibs/publicInclude/rendInst/rendInstExtra.h +++ b/prog/gameLibs/publicInclude/rendInst/rendInstExtra.h @@ -23,6 +23,7 @@ class RenderableInstanceLodsResource; class CollisionResource; struct RiGenVisibility; class DataBlock; +struct Capsule; namespace rendinst { @@ -135,6 +136,8 @@ void before_render(); struct RiGenCollidableData; using riex_collidable_t = dag::RelocatableFixedVector; void gatherRIGenExtraCollidable(riex_collidable_t &out_handles, const BBox3 &box, bool read_lock); +void gatherRIGenExtraCollidable(riex_collidable_t &out_handles, const BSphere3 &sphere, bool read_lock); +void gatherRIGenExtraCollidable(riex_collidable_t &out_handles, const Capsule &capsule, bool read_lock); void gatherRIGenExtraCollidable(riex_collidable_t &out_handles, const TMatrix &tm, const BBox3 &box, bool read_lock); void gatherRIGenExtraCollidable(riex_collidable_t &out_handles, const Point3 &p0, const Point3 &dir, float len, bool read_lock); void gatherRIGenExtraCollidableMin(riex_collidable_t &out_handles, bbox3f_cref box, float min_bsph_rad); diff --git a/prog/gameLibs/publicInclude/render/daBfg/bfg.h b/prog/gameLibs/publicInclude/render/daBfg/bfg.h index d87cd18b7..d0c53e330 100644 --- a/prog/gameLibs/publicInclude/render/daBfg/bfg.h +++ b/prog/gameLibs/publicInclude/render/daBfg/bfg.h @@ -36,7 +36,8 @@ NameSpace root(); void set_multiplexing_extents(multiplexing::Extents extents); /// \brief Executes the frame graph, possibly recompiling it. -void run_nodes(); +/// \details Return false if run is not possible (d3d device was lost for example) +bool run_nodes(); /// \brief Initializes the daBfg backend. void startup(); diff --git a/prog/gameLibs/publicInclude/render/daBfg/virtualResourceCreationSemiRequest.h b/prog/gameLibs/publicInclude/render/daBfg/virtualResourceCreationSemiRequest.h index 17ec09327..0e4f87ec2 100644 --- a/prog/gameLibs/publicInclude/render/daBfg/virtualResourceCreationSemiRequest.h +++ b/prog/gameLibs/publicInclude/render/daBfg/virtualResourceCreationSemiRequest.h @@ -129,8 +129,8 @@ class [[nodiscard]] VirtualResourceCreationSemiRequest VirtualResourceRequest blob() && { Base::blob(BlobDescription{tag_for(), sizeof(T), alignof(T), - // IMPORTANT: {} zero-initializes structs - +[](void *ptr) { new (ptr) T{}; }, // + // IMPORTANT: () zero-initializes structs + +[](void *ptr) { new (ptr) T(); }, // +[](void *ptr) { eastl::destroy_at(reinterpret_cast(ptr)); }, +[](void *ptr, const void *from) { if constexpr (eastl::is_copy_constructible::value) diff --git a/prog/gameLibs/publicInclude/render/heatHazeRenderer.h b/prog/gameLibs/publicInclude/render/heatHazeRenderer.h index 4c4d6295e..4b50c5989 100644 --- a/prog/gameLibs/publicInclude/render/heatHazeRenderer.h +++ b/prog/gameLibs/publicInclude/render/heatHazeRenderer.h @@ -66,7 +66,5 @@ class HeatHazeRenderer Point2 hazeLuminanceScale; eastl::unique_ptr hazeFxRenderer; - - shaders::UniqueOverrideStateId zFuncAlwaysStateId; shaders::UniqueOverrideStateId zDisabledBlendMinStateId; }; diff --git a/prog/gameLibs/publicInclude/render/motionVectorAccess.h b/prog/gameLibs/publicInclude/render/motionVectorAccess.h new file mode 100644 index 000000000..39595ae08 --- /dev/null +++ b/prog/gameLibs/publicInclude/render/motionVectorAccess.h @@ -0,0 +1,50 @@ +// +// Dagor Engine 6.5 - Game Libraries +// Copyright (C) Gaijin Games KFT. All rights reserved. +// +#pragma once + +#include +#include +#include +#include + +#include + +namespace motion_vector_access +{ + +struct CameraParams +{ + TMatrix view; + TMatrix viewInverse; + TMatrix4 projectionNoJitter; + Point3 position; + float znear; + float zfar; +}; + +struct HeroMatrixParams +{ + TMatrix worldToBBox; + TMatrix worldToPrevWorld; + bool canIgnoreBBox; +}; + +void set_params(const CameraParams ¤tCamera, const CameraParams &previousCamera, const Point2 ¤tJitter, + const Point2 &previousJitter, const eastl::optional &heroMatrixParams); + +// Chooses how motion vectors are calculated which has enourmous impact on both quality and performance +// In all cases UV+Z motion vectors are provided by the shader. +// Static: each sample is assumed to be static and reprojected from the previous frame +// Dynamic: each sample is read from the rendered motion vector texture and no reprojection is taking place +enum class MotionVectorType +{ + StaticUVZ, // For no motion vectors + DynamicUVStaticZ, // For 2D motion vectors, expensive due to Z needing reprojection + DynamicUVZ // For 3D motion vectors +}; + +void set_motion_vector_type(MotionVectorType type); + +} // namespace motion_vector_access \ No newline at end of file diff --git a/prog/gameLibs/publicInclude/soundSystem/fmodApi.h b/prog/gameLibs/publicInclude/soundSystem/fmodApi.h index ab59199e0..8fcc2ec79 100644 --- a/prog/gameLibs/publicInclude/soundSystem/fmodApi.h +++ b/prog/gameLibs/publicInclude/soundSystem/fmodApi.h @@ -33,6 +33,7 @@ using DescAndInstance = eastl::pair get_systems(); void setup_dagor_audiosys(); typedef bool (*EventInstanceCallback)(uint32_t cb_type, FMOD::Studio::EventInstance *event_instance, void *parameters, void *cb_data); diff --git a/prog/gameLibs/publicInclude/soundSystem/occlusion.h b/prog/gameLibs/publicInclude/soundSystem/occlusion.h new file mode 100644 index 000000000..d133024e0 --- /dev/null +++ b/prog/gameLibs/publicInclude/soundSystem/occlusion.h @@ -0,0 +1,17 @@ +// +// Dagor Engine 6.5 - Game Libraries +// Copyright (C) Gaijin Games KFT. All rights reserved. +// +#pragma once + +#include +#include + +namespace sndsys::occlusion +{ +using group_id_t = uint32_t; + +bool is_inited(); +void set_group_pos(group_id_t group_id, const Point3 &pos); +void set_event_group(EventHandle event_handle, group_id_t group_id); +} // namespace sndsys::occlusion diff --git a/prog/gameLibs/publicInclude/userSystemInfo/systemInfo.h b/prog/gameLibs/publicInclude/userSystemInfo/systemInfo.h index 694b4a4cd..7068955ee 100644 --- a/prog/gameLibs/publicInclude/userSystemInfo/systemInfo.h +++ b/prog/gameLibs/publicInclude/userSystemInfo/systemInfo.h @@ -72,6 +72,7 @@ void dump_dll_names(); ThermalStatus get_thermal_state(); // From normal (0) to the worse const char *to_string(ThermalStatus status); +int is_tablet(); int get_battery_capacity_mah(); float get_battery(); int get_is_charging(); diff --git a/prog/gameLibs/quirrel/frp/frp.cpp b/prog/gameLibs/quirrel/frp/frp.cpp index 211c1c5f7..b5355937e 100644 --- a/prog/gameLibs/quirrel/frp/frp.cpp +++ b/prog/gameLibs/quirrel/frp/frp.cpp @@ -775,26 +775,26 @@ bool ObservablesGraph::updateDeferred(String &err_msg) // mark queued for (auto o : notifyQueueCache.container) - if (auto c = o->getComputed()) + { + o->willNotify = true; + + if (auto c = o->getComputed(); c && (c->needRecalc || c->maybeRecalc)) + SET_MARKED(c); + + // notify non-Computed watchers + G_ASSERT(!o->isIteratingWatchers); + o->isIteratingWatchers = true; + for (IStateWatcher *w : o->watchers) { - c->willNotify = true; - if (c->needRecalc || c->maybeRecalc) - SET_MARKED(c); - - // notify non-Computed watchers - G_ASSERT(!c->isIteratingWatchers); - c->isIteratingWatchers = true; - for (IStateWatcher *w : c->watchers) + G_ASSERT(w); + if (!w->getComputed() && !w->onSourceObservableChanged()) { - G_ASSERT(w); - if (!w->getComputed() && !w->onSourceObservableChanged()) - { - ok = false; - select_err_msg(err_msg, "Error notifying watchers (deferred)"); - } + ok = false; + select_err_msg(err_msg, "Error notifying watchers (deferred)"); } - c->isIteratingWatchers = false; } + o->isIteratingWatchers = false; + } // propagate mark to leaves for (auto c : sortedGraph) @@ -1050,6 +1050,8 @@ BaseObservable::BaseObservable(ObservablesGraph *graph_, bool is_computed) : gra FRPDBG("@#@ BaseObservable::ctor(%p)", this); isComputed = is_computed; // Note: before `addObservable` G_ASSERT(graph); + isDeferred = graph ? (is_computed ? graph->defaultDeferredComputed : graph->defaultDeferredWatched) : false; + needImmediate = !isDeferred; if (graph) graph->addObservable(this); } @@ -1171,6 +1173,8 @@ bool BaseObservable::triggerRoot(String &err_msg, bool call_subscribers) // first level watchers only for (IStateWatcher *w : watchers) { + if (!needImmediate && !w->getComputed()) + continue; if (!w->onSourceObservableChanged()) { ok = false; @@ -1188,6 +1192,9 @@ bool BaseObservable::triggerRoot(String &err_msg, bool call_subscribers) #endif } + if (!needImmediate) + graph->deferredNotifyCache.add(this); + // all dependent watchers network (mind the leaves-to-root sorting order) for (auto it = sorted_deps.rbegin(); it != sorted_deps.rend(); ++it) { @@ -1204,7 +1211,7 @@ bool BaseObservable::triggerRoot(String &err_msg, bool call_subscribers) if (call_subscribers) { String subscribersErr; - if (!graph->callScriptSubscribers(this, subscribersErr)) + if (!graph->callScriptSubscribers(needImmediate ? this : nullptr, subscribersErr)) { ok = false; select_err_msg(err_msg, subscribersErr); @@ -1252,13 +1259,13 @@ void BaseObservable::subscribeWatcher(IStateWatcher *watcher) if (find_value_idx(watchers, watcher) < 0) { watchers.push_back(watcher); + auto watcherComp = watcher->getComputed(); + if (watcherComp && watcherComp->getNeedImmediate()) + updateNeedImmediate(true); if (auto thisComp = getComputed()) { - auto watcherComp = watcher->getComputed(); if (!watcherComp || watcherComp->getUsed()) thisComp->updateUsed(true); - if (watcherComp && watcherComp->getNeedImmediate()) - thisComp->updateNeedImmediate(true); } } } @@ -1271,12 +1278,12 @@ void BaseObservable::unsubscribeWatcher(IStateWatcher *watcher) FRPDBG("@#@ BaseObservable(%p)::unsubscribeWatcher(%p)", this, watcher); G_ASSERT(!isIteratingWatchers); erase_item_by_value(watchers, watcher); + if (auto watcherComp = watcher->getComputed(); watcherComp && watcherComp->getNeedImmediate()) + updateNeedImmediate(false); if (auto thisComp = getComputed()) { if (watchers.empty()) thisComp->updateUsed(false); - if (auto watcherComp = watcher->getComputed(); watcherComp && watcherComp->getNeedImmediate()) - thisComp->updateNeedImmediate(false); } } @@ -1830,8 +1837,6 @@ ComputedValue::ComputedValue(ObservablesGraph *g, Sqrat::Function func_, dag::Ve FRPDBG("@#@ ComputedValue::ctor(%p | %p)", this, (IStateWatcher *)this); funcAcceptsCurVal = pass_cur_val_to_cb; isStateValid = true; - isDeferred = graph->defaultDeferred; - needImmediate = !isDeferred; value = initial_value; value.FreezeSelf(); @@ -2374,16 +2379,13 @@ void ComputedValue::updateUsed(bool certainly_used) } -void ComputedValue::updateNeedImmediate(bool certainly_immediate) +void BaseObservable::updateNeedImmediate(bool certainly_immediate) { if (certainly_immediate) { if (needImmediate) return; needImmediate = true; - for (auto &s : sources) - if (auto c = s.observable->getComputed()) - c->updateNeedImmediate(true); } else { @@ -2399,9 +2401,13 @@ void ComputedValue::updateNeedImmediate(bool certainly_immediate) if (imm == needImmediate) return; needImmediate = imm; - for (auto &s : sources) - if (auto c = s.observable->getComputed()) - c->updateNeedImmediate(imm); + } + + if (isComputed) + { + bool imm = needImmediate; + for (auto &s : static_cast(this)->sources) + s.observable->updateNeedImmediate(imm); } } @@ -2595,7 +2601,9 @@ static SQInteger set_default_deferred(HSQUIRRELVM vm) ObservablesGraph *graph = ObservablesGraph::get_from_vm(vm); SQBool val; sq_getbool(vm, 2, &val); - graph->defaultDeferred = val; + graph->defaultDeferredComputed = val; + sq_getbool(vm, 3, &val); + graph->defaultDeferredWatched = val; return 0; } @@ -2657,6 +2665,8 @@ void bind_frp_classes(SqModules *module_mgr) .SquirrelFunc("subscribe", &BaseObservable::subscribe, 2, "xc") .SquirrelFunc("unsubscribe", &BaseObservable::unsubscribe, 2, "xc") .SquirrelFunc("dbgGetListeners", &BaseObservable::dbgGetListeners, 1, "x") + .Prop("deferred", &BaseObservable::getDeferred, &BaseObservable::setDeferred) + .Func("setDeferred", &BaseObservable::setDeferred) /**/; ///@class frp/Watched @@ -2695,8 +2705,6 @@ void bind_frp_classes(SqModules *module_mgr) .SquirrelFunc( "trigger", [](HSQUIRRELVM vm) { return sq_throwerror(vm, "Triggering computed observable is not allowed"); }, 0) .Prop("used", &ComputedValue::getUsed) - .Prop("deferred", &ComputedValue::getDeferred, &ComputedValue::setDeferred) - .Func("setDeferred", &ComputedValue::setDeferred) .Func("_noComputeErrorFor", &ComputedValue::addImplicitSource) .SquirrelFunc("getSources", ComputedValue::get_sources, 1, "x") /**/; @@ -2708,7 +2716,7 @@ void bind_frp_classes(SqModules *module_mgr) exports // .SquirrelFunc("set_nested_observable_debug", set_nested_observable_debug, 2, ".b") .SquirrelFunc("make_all_observables_immutable", make_all_observables_immutable, 2, ".b") - .SquirrelFunc("set_default_deferred", set_default_deferred, 2, ".b") + .SquirrelFunc("set_default_deferred", set_default_deferred, 2, ".bb") .SquirrelFunc("set_recursive_sources", set_recursive_sources, 2, ".b") .SquirrelFunc("set_slow_update_threshold_usec", set_slow_update_threshold_usec, 2, ".i") .SquirrelFunc("recalc_all_computed_values", recalc_all_computed_values, 1, ".") diff --git a/prog/gameLibs/rendInst/aot/stub.cpp b/prog/gameLibs/rendInst/aot/stub.cpp index 69b2f5caa..84c2ca743 100644 --- a/prog/gameLibs/rendInst/aot/stub.cpp +++ b/prog/gameLibs/rendInst/aot/stub.cpp @@ -41,11 +41,26 @@ int cloneRIGenExtraResIdx(const char *, const char *) { G_ASSERT_RETURN(false, 0 bool delRIGenExtra(riex_handle_t) { G_ASSERT_RETURN(false, false); } void foreachRIGenInBox(const BBox3 &, GatherRiTypeFlags, ForeachCB &) { G_ASSERT(0); } uint32_t setMaxNumRiCollisionCb(uint32_t) { G_ASSERT_RETURN(false, 0); }; +void testObjToRIGenIntersection(const BSphere3 &, RendInstCollisionCB &, GatherRiTypeFlags, const TraceMeshFaces *, PhysMat::MatID, + bool) +{ + G_ASSERT(0); +} +void testObjToRIGenIntersection(const BBox3 &, RendInstCollisionCB &, GatherRiTypeFlags, const TraceMeshFaces *, PhysMat::MatID, bool) +{ + G_ASSERT(0); +} void testObjToRIGenIntersection(const BBox3 &, const TMatrix &, RendInstCollisionCB &, GatherRiTypeFlags, const TraceMeshFaces *, PhysMat::MatID, bool) { G_ASSERT(0); } +void testObjToRIGenIntersection(const Capsule &, RendInstCollisionCB &, GatherRiTypeFlags, const TraceMeshFaces *, PhysMat::MatID, + bool) +{ + G_ASSERT(0); +} + const CollisionResource *getRiGenCollisionResource(const RendInstDesc &) { G_ASSERT_RETURN(false, nullptr); } void getRIGenExtra44(riex_handle_t, mat44f &) { G_ASSERT(0); } const char *getRIGenResName(const RendInstDesc &) { G_ASSERT_RETURN(false, nullptr); } diff --git a/prog/gameLibs/rendInst/rendInstGenCollision.cpp b/prog/gameLibs/rendInst/rendInstGenCollision.cpp index 976b680c7..8fb3a48a3 100644 --- a/prog/gameLibs/rendInst/rendInstGenCollision.cpp +++ b/prog/gameLibs/rendInst/rendInstGenCollision.cpp @@ -2120,6 +2120,14 @@ class BoundingsChecker if (v_bbox3_test_trasformed_box_intersect(local_box_b, boundingA.bbox, tmAtoB)) return true; } + if constexpr (eastl::is_same_v) + { + if (!v_bbox3_test_box_intersect(boundingA.getBoundingBox(), worldBoxB)) + return false; + bbox3f extB = worldBoxB; + v_bbox3_extend(extB, v_splats(boundingA.r)); + return v_test_segment_box_intersection(v_ldu(&boundingA.a.x), v_ldu(&boundingA.b.x), extB); + } return false; } @@ -2164,7 +2172,12 @@ static CheckBoxRIResultFlags testObjToRIGenIntersectionNoCache(int layer, const { VerifyReadLock lock(rendinst::ccExtra); lock.lockRead(); - gatherRIGenExtraCollidable(riexHandles, obj_world_aabb, false /*read_lock*/); + if constexpr (eastl::is_same_v) + gatherRIGenExtraCollidable(riexHandles, obj_bounding, false /*read_lock*/); + if constexpr (eastl::is_same_v || eastl::is_same_v) + gatherRIGenExtraCollidable(riexHandles, obj_world_aabb, false /*read_lock*/); + if constexpr (eastl::is_same_v) + gatherRIGenExtraCollidable(riexHandles, obj_bounding, false /*read_lock*/); bool ignoreRi = false; int prevRiType = -1; @@ -2221,6 +2234,9 @@ static CheckBoxRIResultFlags testObjToRIGenIntersectionNoCache(int layer, const DA_PROFILE_TAG(coll_tests, ": sph r %.1f; tested %u; %u tris", obj_bounding.r, testedNum, trianglesNum); if constexpr (eastl::is_same_v || eastl::is_same_v) DA_PROFILE_TAG(coll_tests, ": box r %.1f; tested %u; %u tris", obj_world_aabb.width().length() / 2.f, testedNum, trianglesNum); + if constexpr (eastl::is_same_v) + DA_PROFILE_TAG(coll_tests, ": cap %.1f r %.1f; tested %u; %u tris", length(obj_bounding.b - obj_bounding.a), obj_bounding.r, + testedNum, trianglesNum); #endif return result; //-V1020 The function exited without calling the 'lock.unlockRead' function. } @@ -2545,6 +2561,8 @@ static void testObjToRIGenIntersectionInternal(const bounding_type_t &bounding, objFullBBox = v_ldu_bbox3(bounding); if constexpr (eastl::is_same_v) v_bbox3_init(objFullBBox, bounding.tm, bounding.bbox); + if constexpr (eastl::is_same_v) + objFullBBox = bounding.getBoundingBox(); G_ASSERT(!v_bbox3_is_empty(objFullBBox)); // To consider: extract this code path to separate function @@ -2611,6 +2629,9 @@ static void testObjToRIGenIntersectionInternal(const bounding_type_t &bounding, if constexpr (eastl::is_same_v || eastl::is_same_v) DA_PROFILE_TAG(coll_tests, ": box r %.1f; tested %u/%u; %u tris", v_extract_x(v_length3_x(v_bbox3_size(objFullBBox))) / 2.f, testedNum, ri_cache->rendinstCache.size(), trianglesNum); + if constexpr (eastl::is_same_v) + DA_PROFILE_TAG(coll_tests, ": cap %.1f r %.1f; tested %u/%u; %u tris", length(bounding.b - bounding.a), bounding.r, + testedNum, ri_cache->rendinstCache.size(), trianglesNum); #endif } else @@ -2666,6 +2687,12 @@ void testObjToRIGenIntersection(const BBox3 &obj_box, const TMatrix &obj_tm, Ren testObjToRIGenIntersectionInternal(obb, callback, ri_types, ri_cache, ray_mat, unlock_in_cb); } +void testObjToRIGenIntersection(const Capsule &obj_capsule, RendInstCollisionCB &callback, GatherRiTypeFlags ri_types, + const TraceMeshFaces *ri_cache, PhysMat::MatID ray_mat, bool unlock_in_cb) +{ + testObjToRIGenIntersectionInternal(obj_capsule, callback, ri_types, ri_cache, ray_mat, unlock_in_cb); +} + CheckBoxRIResultFlags checkBoxToRIGenIntersection(const BBox3 &box) { CheckIntersectionStrat strat; diff --git a/prog/gameLibs/rendInst/rendInstGenExtra.cpp b/prog/gameLibs/rendInst/rendInstGenExtra.cpp index 5aa2faf35..2dce46a42 100644 --- a/prog/gameLibs/rendInst/rendInstGenExtra.cpp +++ b/prog/gameLibs/rendInst/rendInstGenExtra.cpp @@ -1517,17 +1517,50 @@ bool rendinst::damageRIGenExtra(riex_handle_t id, float dmg_pts, mat44f *out_des void rendinst::gatherRIGenExtraCollidable(riex_collidable_t &out_handles, const BBox3 &box, bool read_lock) DAG_TS_NO_THREAD_SAFETY_ANALYSIS { - if (read_lock) - rendinst::ccExtra.lockRead(); { + ScopedLockRead(read_lock ? &rendinst::ccExtra : nullptr); TIME_PROFILE_DEV(gather_riex_collidable_box); rigrid_find_in_box_by_bounding(riExtraGrid, v_ldu_bbox3(box), [&](RiGridObject object) { out_handles.push_back(object.handle); return false; }); } - if (read_lock) - rendinst::ccExtra.unlockRead(); + + if (!out_handles.empty()) + eastl::sort(out_handles.begin(), out_handles.end()); +} + +void rendinst::gatherRIGenExtraCollidable(riex_collidable_t &out_handles, const BSphere3 &sphere, bool read_lock) +{ + { + ScopedLockRead(read_lock ? &rendinst::ccExtra : nullptr); + TIME_PROFILE_DEV(gather_riex_collidable_box); + rigrid_find_in_sphere_by_bounding(riExtraGrid, sphere.c, sphere.r, [&](RiGridObject object) { + out_handles.push_back(object.handle); + return false; + }); + } + + if (!out_handles.empty()) + eastl::sort(out_handles.begin(), out_handles.end()); +} + +void rendinst::gatherRIGenExtraCollidable(riex_collidable_t &out_handles, const Capsule &capsule, bool read_lock) +{ + { + ScopedLockRead(read_lock ? &rendinst::ccExtra : nullptr); + TIME_PROFILE_DEV(gather_riex_collidable_ray); + auto collect = [&](RiGridObject object) { + out_handles.push_back(object.handle); + return false; + }; + Point3 dir = capsule.b - capsule.a; + float len = length(dir); + if (DAGOR_LIKELY(len > VERY_SMALL_NUMBER)) + rigrid_find_in_capsule_by_bounding(riExtraGrid, capsule.a, dir / len, len, capsule.r, collect); + else + rigrid_find_in_sphere_by_bounding(riExtraGrid, capsule.a, capsule.r, collect); + } if (!out_handles.empty()) eastl::sort(out_handles.begin(), out_handles.end()); @@ -1537,17 +1570,14 @@ void rendinst::gatherRIGenExtraCollidable(riex_collidable_t &out_handles, const void rendinst::gatherRIGenExtraCollidable(riex_collidable_t &out_handles, const TMatrix &tm, const BBox3 &box, bool read_lock) DAG_TS_NO_THREAD_SAFETY_ANALYSIS { - if (read_lock) - rendinst::ccExtra.lockRead(); { + ScopedLockRead(read_lock ? &rendinst::ccExtra : nullptr); TIME_PROFILE_DEV(gather_riex_collidable_transformed_box); rigrid_find_in_transformed_box_by_bounding(riExtraGrid, tm, box, [&](RiGridObject object) { out_handles.push_back(object.handle); return false; }); } - if (read_lock) - rendinst::ccExtra.unlockRead(); if (!out_handles.empty()) eastl::sort(out_handles.begin(), out_handles.end()); diff --git a/prog/gameLibs/rendInst/visibility/extraVisibility.cpp b/prog/gameLibs/rendInst/visibility/extraVisibility.cpp index a6aff3504..c22e76315 100644 --- a/prog/gameLibs/rendInst/visibility/extraVisibility.cpp +++ b/prog/gameLibs/rendInst/visibility/extraVisibility.cpp @@ -54,7 +54,7 @@ static inline T *append_data(SmallTab &data, const uint32_t vecs_count) return data.data() + cSize; } -// TODO: what is this? Why is it here??? +// TODO: what is this? Why is it here??? // it needs a header... namespace rendinst::gen { extern bool custom_trace_ray_earth(const Point3 &src, const Point3 &dir, real &dist); @@ -498,13 +498,17 @@ bool rendinst::prepareExtraVisibilityInternal(mat44f_cref globtm_cull, const Poi const int forcedExtraLod = -1; const uint32_t useFlags = RendinstTiledScene::HAVE_SHADOWS | visibleFlag; - vec4f dirFromSun = reinterpret_cast(rendinst::dir_from_sun); + alignas(16) Point4 dirFromSun = Point4(rendinst::dir_from_sun.x, rendinst::dir_from_sun.y, rendinst::dir_from_sun.z, 0.0f); + vec4f dirFromSunVec = v_ld(&dirFromSun.x); + vec4f sphereExtendDirection = V_C_UNIT_0100; - if (fabsf(rendinst::dir_from_sun.y) < 1.0f - 1e-6f) + vec4f sphereExtendCorrectionRadiusMul = v_zero(); // we trace a single point, instead of a sphere, so we need to correct the radius + if (fabsf(rendinst::dir_from_sun.y) < 1.0f - 1e-6f) // technically always true { - vec4f shadowSpaceLeftDirection = v_norm3(v_cross3(dirFromSun, V_C_UNIT_0100)); - vec4f shadowSpaceUpDirection = v_cross3(shadowSpaceLeftDirection, dirFromSun); + vec4f shadowSpaceLeftDirection = v_cross3(dirFromSunVec, V_C_UNIT_0100); + vec4f shadowSpaceUpDirection = v_norm3(v_cross3(shadowSpaceLeftDirection, dirFromSunVec)); sphereExtendDirection = shadowSpaceUpDirection; + sphereExtendCorrectionRadiusMul = v_sub(V_C_ONE, v_abs(v_perm_xbzw(shadowSpaceUpDirection, v_zero()))); // 1 - |x0z| } for (const auto &tiled_scene : riExTiledScenes.cscenes(firstScene, sceneCount)) @@ -534,18 +538,20 @@ bool rendinst::prepareExtraVisibilityInternal(mat44f_cref globtm_cull, const Poi tiled_scene.setDistanceMT(ni, instLightDist); } - vec3f lightDist = v_mul(v_cvt_vec4f(v_splatsi(instLightDist)), dirFromSun); + vec3f lightDist = v_mul(v_cvt_vec4f(v_splatsi(instLightDist)), dirFromSunVec); vec3f far_point = v_add(top_point, lightDist); bbox3f worldBox; - worldBox.bmin = v_min(far_point, v_sub(sphere, rad)); - worldBox.bmax = v_max(far_point, v_add(sphere, rad)); + vec4f sphereExtendCorrectionRadius = v_mul(sphereExtendCorrectionRadiusMul, rad); + worldBox.bmin = v_min(v_sub(far_point, sphereExtendCorrectionRadius), v_sub(sphere, rad)); + worldBox.bmax = v_max(v_add(far_point, sphereExtendCorrectionRadius), v_add(sphere, rad)); if (!use_occlusion->isVisibleBox(worldBox.bmin, worldBox.bmax)) // may be we should also use isOccludedBox here? return; } else // dynamic object { // replace with bounding sphere - if (use_occlusion->isOccludedSphere(sphere, v_splat_w(v_add(sphere, sphere)))) // + // this seems to be a giant hack with just using 2x radius + if (use_occlusion->isOccludedSphere(sphere, v_splat_w(v_add(sphere, sphere)))) return; } } diff --git a/prog/gameLibs/render/daBfg/api/cpp/bfg.cpp b/prog/gameLibs/render/daBfg/api/cpp/bfg.cpp index cf80edd2a..a3e267a2d 100644 --- a/prog/gameLibs/render/daBfg/api/cpp/bfg.cpp +++ b/prog/gameLibs/render/daBfg/api/cpp/bfg.cpp @@ -38,7 +38,7 @@ void update_external_state(ExternalState state) { Runtime::get().updateExternalS void set_multiplexing_extents(multiplexing::Extents extents) { Runtime::get().setMultiplexingExtents(extents); } -void run_nodes() { Runtime::get().runNodes(); } +bool run_nodes() { return Runtime::get().runNodes(); } void startup() { Runtime::startup(); } diff --git a/prog/gameLibs/render/daBfg/runtime/runtime.cpp b/prog/gameLibs/render/daBfg/runtime/runtime.cpp index 85219bf4d..774643fd4 100644 --- a/prog/gameLibs/render/daBfg/runtime/runtime.cpp +++ b/prog/gameLibs/render/daBfg/runtime/runtime.cpp @@ -484,12 +484,12 @@ void Runtime::updateDynamicResolution(int curr_frame) } } -void Runtime::runNodes() +bool Runtime::runNodes() { - if (d3d::device_lost(nullptr)) + if (DAGOR_UNLIKELY(d3d::device_lost(nullptr))) { logwarn("daBfg: frame was skipped due to an ongoing device reset"); - return; + return false; } TIME_D3D_PROFILE(ExecuteFrameGraph); @@ -542,6 +542,8 @@ void Runtime::runNodes() const auto &frameEvents = allResourceEvents[currFrame]; nodeExec->execute(prevFrame, currFrame, currentMultiplexingExtents, frameEvents, perNodeStateDeltas); + + return true; } void Runtime::invalidateHistory() diff --git a/prog/gameLibs/render/daBfg/runtime/runtime.h b/prog/gameLibs/render/daBfg/runtime/runtime.h index a67153a99..cf4335533 100644 --- a/prog/gameLibs/render/daBfg/runtime/runtime.h +++ b/prog/gameLibs/render/daBfg/runtime/runtime.h @@ -52,7 +52,7 @@ class Runtime InternalRegistry &getInternalRegistry() { return registry; } void updateExternalState(ExternalState state) { nodeExec->externalState = state; } void setMultiplexingExtents(multiplexing::Extents extents); - void runNodes(); + bool runNodes(); void markStageDirty(CompilationStage stage) { diff --git a/prog/gameLibs/render/denoiser/denoiser.cpp b/prog/gameLibs/render/denoiser/denoiser.cpp index 6d66207cf..938dd8d67 100644 --- a/prog/gameLibs/render/denoiser/denoiser.cpp +++ b/prog/gameLibs/render/denoiser/denoiser.cpp @@ -1290,6 +1290,9 @@ void denoise_ao(const AODenoiser ¶ms) ReblurSharedConstants reblurSharedConstants = make_reblur_shared_constants(params.hitDistParams, params.antilagSettings, false, width, height, true, false); + static_assert(offsetof(ReblurSharedConstants, rotator) % 16 == 0, + "`Point4 rotator` vector straddles 4-vector boundary of constant buffer."); + // Rotators Point4 rndScale = Point4(1, 1, 1, 1) + rand4sf() * 0.25f; Point4 rndAngle = rand4uf() * DegToRad(360.0f); @@ -2095,8 +2098,8 @@ static void denoise_reflection_relax(const ReflectionDenoiser ¶ms) struct PassData { RelaxSharedConstants relaxSharedConstants; - Point4 rotator; uint32_t padding; + Point4 rotator; } passData; float ca = cos(rndAngle.x); @@ -2108,6 +2111,8 @@ static void denoise_reflection_relax(const ReflectionDenoiser ¶ms) static_assert(sizeof(passData) % (4 * sizeof(float)) == 0, "RelaxSharedConstants size must be multiple of sizeof(float4) for d3d::set_cb0_data"); + static_assert(offsetof(PassData, rotator) % 16 == 0, "`Point4 rotator` vector straddles 4-vector boundary of constant buffer."); + d3d::set_sampler(STAGE_CS, 0, samplerNearestClamp); d3d::set_sampler(STAGE_CS, 1, samplerLinearClamp); diff --git a/prog/gameLibs/render/heatHaze/heatHazeRenderer.cpp b/prog/gameLibs/render/heatHaze/heatHazeRenderer.cpp index d133d2215..1a4752248 100644 --- a/prog/gameLibs/render/heatHaze/heatHazeRenderer.cpp +++ b/prog/gameLibs/render/heatHaze/heatHazeRenderer.cpp @@ -65,11 +65,6 @@ void HeatHazeRenderer::setUp(int haze_resolution_divisor) hazeFxId = ShaderGlobal::get_int_fast(haze_render_mode_id_id); shaders::OverrideState state; - state.set(shaders::OverrideState::Z_FUNC); - state.zFunc = CMPF_ALWAYS; - zFuncAlwaysStateId = shaders::overrides::create(state); - - state = shaders::OverrideState(); state.set(shaders::OverrideState::Z_TEST_DISABLE); state.set(shaders::OverrideState::Z_WRITE_DISABLE); state.set(shaders::OverrideState::BLEND_OP); @@ -121,7 +116,7 @@ void HeatHazeRenderer::renderHazeParticles(Texture *haze_depth, Texture *haze_of TextureInfo hazeOffsetInfo; haze_offset->getinfo(hazeOffsetInfo); - d3d::set_render_target({haze_depth, 0, 0}, DepthAccess::RW, {{haze_offset, 0, 0}}); + d3d::set_render_target({}, DepthAccess::RW, {{haze_offset, 0, 0}, {haze_depth, 0, 0}}); ShaderGlobal::set_color4(inv_distortion_resolutionVarId, 1.0f / hazeOffsetInfo.w, 1.0f / hazeOffsetInfo.h); ShaderGlobal::set_int(rendering_distortion_colorVarId, 0); @@ -129,7 +124,6 @@ void HeatHazeRenderer::renderHazeParticles(Texture *haze_depth, Texture *haze_of ShaderGlobal::set_real(haze_scene_depth_tex_lodVarId, depth_tex_lod); ShaderGlobal::setBlock(global_frame_block_id, ShaderGlobal::LAYER_FRAME); - shaders::overrides::set(zFuncAlwaysStateId); if (render_ri_haze) render_ri_haze(); @@ -140,7 +134,6 @@ void HeatHazeRenderer::renderHazeParticles(Texture *haze_depth, Texture *haze_of if (fx_render_modeVarId >= 0) ShaderGlobal::set_int(fx_render_modeVarId, 0); ShaderGlobal::setBlock(global_frame_block_id, ShaderGlobal::LAYER_FRAME); - shaders::overrides::reset(); } void HeatHazeRenderer::renderColorHaze(Texture *haze_color, RenderHazeParticlesCallback render_haze_particles, diff --git a/prog/gameLibs/render/jamfile b/prog/gameLibs/render/jamfile index e78e1d425..5699c11e1 100644 --- a/prog/gameLibs/render/jamfile +++ b/prog/gameLibs/render/jamfile @@ -107,6 +107,7 @@ Sources = vertexDensityOverlay.cpp grassify.cpp driverNetworkManager.cpp + motionVectorAccess.cpp ; UseProgLibs += diff --git a/prog/gameLibs/render/motionVectorAccess.cpp b/prog/gameLibs/render/motionVectorAccess.cpp new file mode 100644 index 000000000..4a9561c57 --- /dev/null +++ b/prog/gameLibs/render/motionVectorAccess.cpp @@ -0,0 +1,97 @@ +// Copyright (C) Gaijin Games KFT. All rights reserved. + +#include + +#include + +#include + +#define VARS_LIST \ + VAR(jitter_offset_uv) \ + VAR(uvz_to_prev_frame_uvz) \ + VAR(uvz_to_prev_frame_hero_bbox) \ + VAR(uvz_to_prev_frame_hero_uvz) \ + VAR(zn_zfar_current_prev) \ + VAR(motion_vector_type) \ + VAR(can_ignore_bbox) + +#define VAR(a) ShaderVariableInfo a##VarId(#a, true); +VARS_LIST +#undef VAR + +namespace motion_vector_access +{ + +static void set_hero_matrix_params(const HeroMatrixParams ¶ms, const TMatrix4 &uvzToWorldRel, const TMatrix4 &prevWorldToUvzRel) +{ + can_ignore_bboxVarId.set_int(params.canIgnoreBBox); + uvz_to_prev_frame_hero_bboxVarId.set_float4x4(uvzToWorldRel * params.worldToBBox); + uvz_to_prev_frame_hero_uvzVarId.set_float4x4(uvzToWorldRel * params.worldToPrevWorld * prevWorldToUvzRel); +} + +static void set_identity_hero_matrix_params() +{ + static const TMatrix4 disable_hero_bbox(0.0f, 0.0f, 0.0f, 2.0f, // + 0.0f, 0.0f, 0.0f, 2.0f, // + 0.0f, 0.0f, 0.0f, 2.0f, // + 0.0f, 0.0f, 0.0f, 2.0f); + + can_ignore_bboxVarId.set_int(1); + uvz_to_prev_frame_hero_bboxVarId.set_float4x4(disable_hero_bbox); + uvz_to_prev_frame_hero_uvzVarId.set_float4x4(TMatrix4::IDENT); +} + +static void set_reprojection_params(const CameraParams ¤tCamera, const CameraParams &previousCamera, + const eastl::optional &heroMatrixParams) +{ + // Doing calculations around view.viewPos increase precision robustness. + Point3 posDiff = currentCamera.position - previousCamera.position; + TMatrix viewItm_rel = currentCamera.viewInverse; + viewItm_rel.setcol(3, Point3(0, 0, 0)); + TMatrix prevViewTm_rel = previousCamera.view; + prevViewTm_rel.setcol(3, prevViewTm_rel % posDiff); + + float det; + TMatrix4 invProjTmNoJitter; + if (!inverse44(currentCamera.projectionNoJitter, invProjTmNoJitter, det)) + invProjTmNoJitter = TMatrix4::IDENT; + + static const TMatrix4 uvz_to_clip(2.0f, 0.0f, 0.0f, 0.0f, // + 0.0f, -2.0f, 0.0f, 0.0f, // + 0.0f, 0.0f, 1.0f, 0.0f, // + -1.0f, 1.0f, 0.0f, 1.0f); + + static const TMatrix4 clip_to_uvz(0.5f, 0.0f, 0.0f, 0.0f, // + 0.0f, -0.5f, 0.0f, 0.0f, // + 0.0f, 0.0f, 1.0f, 0.0f, // + 0.5f, 0.5f, 0.0f, 1.0f); + + + TMatrix4 uvzToWorldRel = uvz_to_clip * invProjTmNoJitter * viewItm_rel; + TMatrix4 prevWorldToUvzRel = TMatrix4(prevViewTm_rel) * previousCamera.projectionNoJitter * clip_to_uvz; + TMatrix4 uvzToPrevFrameUvz = uvzToWorldRel * prevWorldToUvzRel; + + uvz_to_prev_frame_uvzVarId.set_float4x4(uvzToPrevFrameUvz); + zn_zfar_current_prevVarId.set_color4(currentCamera.znear, currentCamera.zfar, previousCamera.znear, previousCamera.zfar); + + if (heroMatrixParams) + set_hero_matrix_params(*heroMatrixParams, uvzToWorldRel, prevWorldToUvzRel); + else + set_identity_hero_matrix_params(); +} + +static void set_jitter_params(const Point2 ¤tJitter, const Point2 &previousJitter) +{ + jitter_offset_uvVarId.set_color4(currentJitter.x, currentJitter.y, previousJitter.x, previousJitter.y); +} + +void set_params(const CameraParams ¤tCamera, const CameraParams &previousCamera, const Point2 ¤tJitter, + const Point2 &previousJitter, const eastl::optional &heroMatrixParams) +{ + set_jitter_params(currentJitter, previousJitter); + set_reprojection_params(currentCamera, previousCamera, heroMatrixParams); +} + +void set_motion_vector_type(MotionVectorType type) { motion_vector_typeVarId.set_int(static_cast(type)); } + +} // namespace motion_vector_access \ No newline at end of file diff --git a/prog/gameLibs/render/rtr/shaders/rtr.dshl b/prog/gameLibs/render/rtr/shaders/rtr.dshl index 53505bd66..b235679dc 100644 --- a/prog/gameLibs/render/rtr/shaders/rtr.dshl +++ b/prog/gameLibs/render/rtr/shaders/rtr.dshl @@ -548,6 +548,9 @@ shader rt_reflection float fxt = -1; trace_ray_fx_translucent(relPos, sampleDir, bias, isHit ? hitInfo.t : maxReflectionDistance, w, reflectionColor, fxt, 1, roughness > 0.01); + BRANCH + if (isHit) + calc_atmosphere(reflectionColor, hitInfo.position, hitInfo.t); if (!isHit && fxt > 0) reflectionDistance = fxt; @@ -670,7 +673,9 @@ shader rt_glass_reflection float fxt = -1; trace_ray_fx_translucent(relPos, sampleDir, 0, isHit ? hitInfo.t : maxReflectionDistance, w, reflectionColor, fxt); - + BRANCH + if (isHit) + calc_atmosphere(reflectionColor, hitInfo.position, hitInfo.t); texture2DAt(rt_glass_gbuffer, dtid) = float4(reflectionColor, 1); } } diff --git a/prog/gameLibs/render/shaders/flexible_scale_rasterization.dshl b/prog/gameLibs/render/shaders/flexible_scale_rasterization.dshl index ff547fdd1..e6ee77da0 100644 --- a/prog/gameLibs/render/shaders/flexible_scale_rasterization.dshl +++ b/prog/gameLibs/render/shaders/flexible_scale_rasterization.dshl @@ -16,23 +16,23 @@ macro USE_FSR(code) hlsl(code) { - RegularBuffer static_textures : BINDLESS_TEX_REGISTER; - RegularBuffer static_samplers : BINDLESS_SAMPLER_REGISTER; + RegularBuffer fsr_static_textures : BINDLESS_TEX_REGISTER; + RegularBuffer fsr_static_samplers : BINDLESS_SAMPLER_REGISTER; float2 linearToDistortedTc(float2 tc) { - Texture1D fsrLutH = static_textures[fsr_lut_id.x]; - Texture1D fsrLutV = static_textures[fsr_lut_id.x + 1]; - SamplerState smp = static_samplers[0]; + Texture1D fsrLutH = fsr_static_textures[fsr_lut_id.x]; + Texture1D fsrLutV = fsr_static_textures[fsr_lut_id.x + 1]; + SamplerState smp = fsr_static_samplers[0]; return float2(fsrLutH.Sample(smp, tc.x), fsrLutV.Sample(smp, tc.y)); } float2 distortedToLinearTc(float2 tc) { - Texture1D fsrLutH = static_textures[fsr_lut_id.y]; - Texture1D fsrLutV = static_textures[fsr_lut_id.y + 1]; - SamplerState smp = static_samplers[0]; + Texture1D fsrLutH = fsr_static_textures[fsr_lut_id.y]; + Texture1D fsrLutV = fsr_static_textures[fsr_lut_id.y + 1]; + SamplerState smp = fsr_static_samplers[0]; return float2(fsrLutH.Sample(smp, tc.x), fsrLutV.Sample(smp, tc.y)); } diff --git a/prog/gameLibs/render/shaders/get_mix_weight_inc.dshl b/prog/gameLibs/render/shaders/get_mix_weight_inc.dshl new file mode 100644 index 000000000..e6429ecc8 --- /dev/null +++ b/prog/gameLibs/render/shaders/get_mix_weight_inc.dshl @@ -0,0 +1,14 @@ +hlsl { + half get_mix_weight(half detail1_a, half detail2_a, half mask_weight) + { + half2 weights = half2(detail1_a*(1.0-mask_weight), detail2_a*mask_weight+0.000001); + weights *= weights; + weights *= weights; + half weight2 = weights.y * rcp(dot(weights, 1.h)); + + //make it more contrast! + half weight2_pow2 = weight2*weight2; + weight2 = (-2.666666666666667h*weight2_pow2 + (4.h*weight2 - 0.333333333333333h)*weight2); + return saturate(weight2); + } +} \ No newline at end of file diff --git a/prog/gameLibs/render/shaders/hardware_defines.dshl b/prog/gameLibs/render/shaders/hardware_defines.dshl index 2ed96c1c8..5d19faa28 100644 --- a/prog/gameLibs/render/shaders/hardware_defines.dshl +++ b/prog/gameLibs/render/shaders/hardware_defines.dshl @@ -831,6 +831,11 @@ hlsl { ##assert(uint(tc) < dim, "[%s:%.f] Out of bounds: Buffer '%s' has size (%.f), but access to (%.f)", file, ln, name, dim, tc); } + void checkBufferBoundsRange(int tc, uint range, uint dim, int file, int ln, int name) + { + ##assert(uint(tc) + range <= dim, "[%s:%.f] Out of bounds: Buffer '%s' has size (%.f), but access to [%.f, %.f) range", + file, ln, name, dim, tc, tc+range); + } void checkBufferBoundsStrided(int tc, uint dim, uint stride, int file, int ln, int name) { ##assert(uint(tc) < dim, "[%s:%.f] Out of bounds: Buffer '%s' has size (%.f) (elem stride (%.f)), but access to (%.f)", @@ -866,6 +871,10 @@ hlsl { #define CHECK_BUFFER_EXPR(a, tc) \ a.GetDimensions(bounds_check_dim), \ checkBufferBounds(tc, bounds_check_dim, _FILE_, __LINE__, -1) + #define CHECK_BUFFER_RANGE(range, file, ln, name) \ + uint dim; \ + a.GetDimensions(dim); \ + checkBufferBoundsRange(tc, range, dim, file, ln, name) #define CHECK_STRUCTURED_BUFFER(file, ln, name) \ uint dim, stride; \ a.GetDimensions(dim, stride); \ @@ -885,6 +894,7 @@ hlsl { #define CHECK_TEXTURE3D_EXPR(a, tc) 0 #define CHECK_BUFFER(file, ln, name) #define CHECK_BUFFER_EXPR(a, tc) 0 + #define CHECK_BUFFER_RANGE(range, file, ln, name) #define CHECK_STRUCTURED_BUFFER(file, ln, name) #define CHECK_STRUCTURED_BUFFER_EXPR(a, tc) 0 #define CHECK_STENCIL @@ -938,24 +948,24 @@ hlsl { uint loadBufferBase(StructuredBuffer a, int tc, int file, int ln, int name) { CHECK_STRUCTURED_BUFFER(file, ln, name); return a[tc];} uint loadBufferBase(RWStructuredBuffer a, int tc, int file, int ln, int name) { CHECK_STRUCTURED_BUFFER(file, ln, name); return a[tc];} - uint loadBufferBase(ByteAddressBuffer a, int tc, int file, int ln, int name) { CHECK_BUFFER(file, ln, name); return a.Load(tc); } - uint2 loadBuffer2Base(ByteAddressBuffer a, int tc, int file, int ln, int name) { CHECK_BUFFER(file, ln, name); return a.Load2(tc); } - uint3 loadBuffer3Base(ByteAddressBuffer a, int tc, int file, int ln, int name) { CHECK_BUFFER(file, ln, name); return a.Load3(tc); } - uint4 loadBuffer4Base(ByteAddressBuffer a, int tc, int file, int ln, int name) { CHECK_BUFFER(file, ln, name); return a.Load4(tc); } - uint loadBufferBase(RWByteAddressBuffer a, int tc, int file, int ln, int name) { CHECK_BUFFER(file, ln, name); return a.Load(tc); } - uint2 loadBuffer2Base(RWByteAddressBuffer a, int tc, int file, int ln, int name) { CHECK_BUFFER(file, ln, name); return a.Load2(tc); } - uint3 loadBuffer3Base(RWByteAddressBuffer a, int tc, int file, int ln, int name) { CHECK_BUFFER(file, ln, name); return a.Load3(tc); } - uint4 loadBuffer4Base(RWByteAddressBuffer a, int tc, int file, int ln, int name) { CHECK_BUFFER(file, ln, name); return a.Load4(tc); } + uint loadBufferBase(ByteAddressBuffer a, int tc, int file, int ln, int name) { CHECK_BUFFER_RANGE(4, file, ln, name); return a.Load(tc); } + uint2 loadBuffer2Base(ByteAddressBuffer a, int tc, int file, int ln, int name) { CHECK_BUFFER_RANGE(8, file, ln, name); return a.Load2(tc); } + uint3 loadBuffer3Base(ByteAddressBuffer a, int tc, int file, int ln, int name) { CHECK_BUFFER_RANGE(12, file, ln, name); return a.Load3(tc); } + uint4 loadBuffer4Base(ByteAddressBuffer a, int tc, int file, int ln, int name) { CHECK_BUFFER_RANGE(16, file, ln, name); return a.Load4(tc); } + uint loadBufferBase(RWByteAddressBuffer a, int tc, int file, int ln, int name) { CHECK_BUFFER_RANGE(4, file, ln, name); return a.Load(tc); } + uint2 loadBuffer2Base(RWByteAddressBuffer a, int tc, int file, int ln, int name) { CHECK_BUFFER_RANGE(8, file, ln, name); return a.Load2(tc); } + uint3 loadBuffer3Base(RWByteAddressBuffer a, int tc, int file, int ln, int name) { CHECK_BUFFER_RANGE(12, file, ln, name); return a.Load3(tc); } + uint4 loadBuffer4Base(RWByteAddressBuffer a, int tc, int file, int ln, int name) { CHECK_BUFFER_RANGE(16, file, ln, name); return a.Load4(tc); } #define loadBuffer(a, tc) loadBufferBase(a, tc, _FILE_, __LINE__, -1) #define loadBuffer2(a, tc) loadBuffer2Base(a, tc, _FILE_, __LINE__, -1) #define loadBuffer3(a, tc) loadBuffer3Base(a, tc, _FILE_, __LINE__, -1) #define loadBuffer4(a, tc) loadBuffer4Base(a, tc, _FILE_, __LINE__, -1) - void storeBufferBase(RWByteAddressBuffer a, int tc, uint value, int file, int ln, int name) { CHECK_BUFFER(file, ln, name); a.Store(tc, value); } - void storeBuffer2Base(RWByteAddressBuffer a, int tc, uint2 value, int file, int ln, int name) { CHECK_BUFFER(file, ln, name); a.Store2(tc, value); } - void storeBuffer3Base(RWByteAddressBuffer a, int tc, uint3 value, int file, int ln, int name) { CHECK_BUFFER(file, ln, name); a.Store3(tc, value); } - void storeBuffer4Base(RWByteAddressBuffer a, int tc, uint4 value, int file, int ln, int name) { CHECK_BUFFER(file, ln, name); a.Store4(tc, value); } + void storeBufferBase(RWByteAddressBuffer a, int tc, uint value, int file, int ln, int name) { CHECK_BUFFER_RANGE(4, file, ln, name); a.Store(tc, value); } + void storeBuffer2Base(RWByteAddressBuffer a, int tc, uint2 value, int file, int ln, int name) { CHECK_BUFFER_RANGE(8, file, ln, name); a.Store2(tc, value); } + void storeBuffer3Base(RWByteAddressBuffer a, int tc, uint3 value, int file, int ln, int name) { CHECK_BUFFER_RANGE(12, file, ln, name); a.Store3(tc, value); } + void storeBuffer4Base(RWByteAddressBuffer a, int tc, uint4 value, int file, int ln, int name) { CHECK_BUFFER_RANGE(16, file, ln, name); a.Store4(tc, value); } #define storeBuffer(a, tc, value) storeBufferBase(a, tc, value, _FILE_, __LINE__, -1) #define storeBuffer2(a, tc, value) storeBuffer2Base(a, tc, value, _FILE_, __LINE__, -1) @@ -1060,7 +1070,15 @@ hlsl { ##if hardware.bindless ##if hardware.ps4 || hardware.ps5 - #define BINDLESS_TEX_ARRAY(type, name, space) RegularBuffer name : BINDLESS_TEX_REGISTER; + #define BINDLESS_TEX_ARRAY(type, name, space)\ + struct StaticTexImpl ## name \ + {\ + type operator[](uint index) \ + {\ + return type(static_textures[index]);\ + }\ + };\ + static StaticTexImpl ## name name #define BINDLESS_SMP_ARRAY(type, name, space) RegularBuffer name : BINDLESS_SAMPLER_REGISTER; #define BINDLESS_BUF_ARRAY(type, name, space)\ RegularBuffer static_buffers_ ## space : BINDLESS_BUF_REGISTER; \ diff --git a/prog/gameLibs/render/shaders/motion_vector_access.dshl b/prog/gameLibs/render/shaders/motion_vector_access.dshl new file mode 100644 index 000000000..1932cf19e --- /dev/null +++ b/prog/gameLibs/render/shaders/motion_vector_access.dshl @@ -0,0 +1,158 @@ +include "shader_global.dshl" +include "gbuffer.dshl" +include "assert.dshl" + +texture downsampled_motion_vectors_tex; + +float4x4 uvz_to_prev_frame_uvz; +float4x4 uvz_to_prev_frame_hero_bbox; +float4x4 uvz_to_prev_frame_hero_uvz; +float4 jitter_offset_uv; +float4 zn_zfar_current_prev; + +int can_ignore_bbox = 0; + +int motion_vector_type = 0; +interval motion_vector_type: static_uvz<1, dynamic_uv_static_z<2, dynamic_uvz; + +interval motion_vector_texture_size_to_use: not_set < 1, full<2, downsampled; +assume motion_vector_texture_size_to_use = not_set; + +/* + * This module is responsible for handing out motion vectors. + * These motion vectors are always 3D regardless of the actual motion vector texture. + * No motion vector case is taken care of automatically, and so is the hero matrix. + * Usage: + * INIT_FETCH_MOTION_VECTOR(cs, full) + * USE_FETCH_MOTION_VECTOR(cs, full) // full or downsampled + * hlsl(cs){ + * ... + * float3 motion_vector = fetch_motion_vector_jittered(uv, depth); + * ... + * } + * + * Depth is absolutely necessary if the shader is expected to work in with reprojection as well. + * If it's not expected to work in such a case 0 can be passed as depth. + */ + +macro INIT_FETCH_MOTION_VECTOR(stage, source) + G_ASSERT(motion_vector_texture_size_to_use == not_set || motion_vector_texture_size_to_use == source, + "You are trying to motion vector access with different texture size than you initialized it with.") + + assume motion_vector_texture_size_to_use = source; + + if (motion_vector_type == dynamic_uv_static_z || motion_vector_type == dynamic_uvz) + { + if (motion_vector_texture_size_to_use == full) + { + INIT_READ_MOTION_BUFFER_BASE(stage) + } + else + { + (stage) { + downsampled_motion_vectors_tex@smp2d = downsampled_motion_vectors_tex; + } + } + } + + if (motion_vector_type == static_uvz || motion_vector_type == dynamic_uv_static_z) + { + (stage) { + uvz_to_prev_frame_uvz@f44 = {uvz_to_prev_frame_uvz}; + uvz_to_prev_frame_hero_bbox@f44 = {uvz_to_prev_frame_hero_bbox}; + uvz_to_prev_frame_hero_uvz@f44 = {uvz_to_prev_frame_hero_uvz}; + depth_linearization_slope@f2 = (1.0/zn_zfar_current_prev.yw); + depth_linearization_offset@f2 = (zn_zfar_current_prev.yw-zn_zfar_current_prev.xz)/(zn_zfar_current_prev.xz * zn_zfar_current_prev.yw); + can_ignore_bbox@i1 = can_ignore_bbox; + } + } + + (stage) { + currentFrameJitter@f2 = jitter_offset_uv.xy; + prevFrameJitter@f2 = jitter_offset_uv.zw; + currentToPrevFrameJitter@f2 = jitter_offset_uv.zw - jitter_offset_uv.xy; + } +endmacro + +// source is either full or downsampled +macro USE_FETCH_MOTION_VECTOR(stage, source) + G_ASSERT(motion_vector_texture_size_to_use == not_set || motion_vector_texture_size_to_use == source, + "You are trying to motion vector access with different texture size than you initialized it with.") + + assume motion_vector_texture_size_to_use = source; + + if ((motion_vector_type == dynamic_uv_static_z || motion_vector_type == dynamic_uvz) && motion_vector_texture_size_to_use == full) + { + USE_READ_MOTION_BUFFER_BASE(stage) + } + + hlsl(stage) { + + ##if motion_vector_type == static_uvz || motion_vector_type == dynamic_uv_static_z + bool is_in_hero_bbox(float2 uv, float depth) + { + float4 posRelToBBox = mul(uvz_to_prev_frame_hero_bbox, float4(uv, depth, 1)); + return all(abs(posRelToBBox / posRelToBBox.w) < 1); + } + + bool is_subject_to_hero_reprojection(float2 uv, float depth) + { + #ifdef GBUFFER_HAS_HERO_COCKPIT_BIT + bool result = isGbufferHeroCockpit(uv); + if (!can_ignore_bbox) + result = result | is_in_hero_bbox(uv, depth); + return result; + #else + return is_in_hero_bbox(uv, depth); + #endif + } + + float3 calculate_reprojected_motion_vector(float2 uv, float depth) + { + float4x4 reprojection = is_subject_to_hero_reprojection(uv, depth) ? uvz_to_prev_frame_hero_uvz : uvz_to_prev_frame_uvz; + float4 prevUVDepth = mul(reprojection, float4(uv, depth, 1)); + prevUVDepth /= prevUVDepth.w; + float2 depths = float2(depth, prevUVDepth.z); + float2 linearZ = rcp(depth_linearization_slope * depths + depth_linearization_offset); + return float3(prevUVDepth.xy - uv, linearZ.y - linearZ.x); + } + ##endif + + float3 fetch_motion_vector_unjittered(float2 uv, float depth) + { + ##if motion_vector_type == static_uvz + return calculate_reprojected_motion_vector(uv, depth); + ##elif motion_vector_type == dynamic_uv_static_z + ##if motion_vector_texture_size_to_use == full + float3 mv = readMotionBuffer(uv).xyz; + ##else + float3 mv = tex2Dlod(downsampled_motion_vectors_tex, float4(uv, 0, 0)).xyz; + ##endif + return float3(mv.xy, calculate_reprojected_motion_vector(uv, depth).z); + ##else + ##if motion_vector_texture_size_to_use == full + return readMotionBuffer(uv).xyz; + ##else + return tex2Dlod(downsampled_motion_vectors_tex, float4(uv, 0, 0)).xyz; + ##endif + ##endif + } + + float3 fetch_motion_vector_jittered(float2 uv, float depth) + { + return fetch_motion_vector_unjittered(uv, depth) + float3(currentToPrevFrameJitter, 0); + } + + float3 fetch_motion_vector_unjittered_to_jittered(float2 uv, float depth) + { + return fetch_motion_vector_unjittered(uv, depth) + float3(currentFrameJitter, 0); + } + + float3 fetch_motion_vector_jittered_to_unjittered(float2 uv, float depth) + { + return fetch_motion_vector_unjittered(uv, depth) - float3(currentFrameJitter, 0); + } + + } + +endmacro \ No newline at end of file diff --git a/prog/gameLibs/render/shaders/puddles_inc.dshl b/prog/gameLibs/render/shaders/puddles_inc.dshl index d2392820f..0f470065e 100644 --- a/prog/gameLibs/render/shaders/puddles_inc.dshl +++ b/prog/gameLibs/render/shaders/puddles_inc.dshl @@ -10,6 +10,14 @@ macro USE_PUDDLE_DISTANCES(code) puddles_params@f4 = (1.0 / max(0.01, puddles_params.y - puddles_params.x), -puddles_params.x / max(0.01, puddles_params.y - puddles_params.x), puddles_params.z, puddles_params.w); } + + hlsl (code) { + #define WETNESS_PUDDLE_SLOPE 0.002 + float get_puddle_slope_fade(float3 vertical_normal) + { + return ClampRange(vertical_normal.y, 1.0 - WETNESS_PUDDLE_SLOPE * 4, 1.0 - WETNESS_PUDDLE_SLOPE); + } + } endmacro macro USE_PUDDLES_WETNESS(code) @@ -20,17 +28,15 @@ macro USE_PUDDLES_WETNESS(code) hlsl (code) { #include "noise/Perlin2D.hlsl" - #define WETNESS_PUDDLE_SLOPE 0.002 - - bool check_puddles_conditions(float puddle_level, float eye_dist) + bool check_puddles_conditions(float puddle_level, float eye_dist, float3 vertical_normal) { - return puddle_level > 0.0 && (eye_dist * puddles_params.x + puddles_params.y) < 1.0; + return puddle_level > 0.0 && get_puddle_slope_fade(vertical_normal) > 0 && (eye_dist * puddles_params.x + puddles_params.y) < 1.0; } float get_puddles_wetness(float3 world_pos, float3 vertical_normal, float eye_dist, float puddle_level, float land_thickness, float land_deformation, float height, out float puddle_displacement) { // slope fade for puddle level - puddle_level *= ClampRange(vertical_normal.y, 1.0 - WETNESS_PUDDLE_SLOPE * 4, 1.0 - WETNESS_PUDDLE_SLOPE); + puddle_level *= get_puddle_slope_fade(vertical_normal); // puddle level remapped between hmap_displacement_down and land_thickness + hmap_displacement_up @@ -76,7 +82,7 @@ macro USE_LAND_WETNESS() bool check_land_wetness_conditions(float3 world_pos, float3 vertical_normal, float dist, float puddle_level, out float base_wetness, out float water_border) { base_wetness = get_base_wetness(world_pos, vertical_normal, water_border); - return base_wetness > 0 || (check_puddles_conditions(puddle_level, dist) && world_pos.y > get_wetness_water_level()); + return base_wetness > 0 || (check_puddles_conditions(puddle_level, dist, vertical_normal) && world_pos.y > get_wetness_water_level()); } float2 get_land_wetness(float3 world_pos, float3 vertical_normal, float dist, float puddle_level, float land_thickness, float land_deformation, float height, float base_wetness, float water_border) @@ -138,7 +144,6 @@ macro USE_LANDMESH_PUDDLES(code) } hlsl(code) { - #define WETNESS_PUDDLE_SLOPE 0.002 #define object_default_porosity porosity_params.x #define decal_default_porosity porosity_params.y @@ -148,7 +153,7 @@ macro USE_LANDMESH_PUDDLES(code) float puddleLevel = saturate((sample_tor_puddle(world_pos.xz) - 0.2) * 4 * puddle_influence); // slope fade for puddle level - puddleLevel *= ClampRange(vertical_normal.y, 1.0 - WETNESS_PUDDLE_SLOPE * 4, 1.0 - WETNESS_PUDDLE_SLOPE); + puddleLevel *= get_puddle_slope_fade(vertical_normal); float wetness = saturate(3*( puddleLevel - puddle_variance)); diff --git a/prog/gameLibs/render/shaders/rendinst_top_projection_inc.dshl b/prog/gameLibs/render/shaders/rendinst_top_projection_inc.dshl new file mode 100644 index 000000000..650cd7f14 --- /dev/null +++ b/prog/gameLibs/render/shaders/rendinst_top_projection_inc.dshl @@ -0,0 +1,31 @@ +include "shader_global.dshl" +include "get_mix_weight_inc.dshl" + +macro SETUP_TOP_PROJECTION(use_top_projection_texture) + static int top_projection = 0; + interval top_projection : top_projection_off < 1, top_projection_on; + + if (top_projection == top_projection_on) + { + static float top_projection_to = 0.0; + static float top_projection_detail2_modulate = 1.0; + static float top_projection_from = 0.0; + if (use_top_projection_texture) { + hlsl { + #define USE_TOP_PROJECTION_TEXTURE 1 + } + } + (ps) { top_projection_params@f4 = (1.0 / (top_projection_to-top_projection_from + 0.01), -top_projection_from / (top_projection_to-top_projection_from + 0.01), 1.0-top_projection_detail2_modulate, 0.0); } + + hlsl { + void apply_top_projection(half3 world_normal, half4 detail_color1, half4 detail_color2, half weight, out half weight2, inout half3 base_color) + { + float detail2_a_fade = saturate(world_normal.y*get_top_projection_params().x + get_top_projection_params().y); + weight2 = get_mix_weight(detail_color1.a, half(detail_color2.a * detail2_a_fade), weight); + + float modulate_koef = weight2 * get_top_projection_params().z; + base_color = lerp(base_color, half(DETAIL_TEX_MULTIPLIER_RCP).xxx, half(modulate_koef)); + } + } + } +endmacro \ No newline at end of file diff --git a/prog/gameLibs/render/shaders/tsr.dshl b/prog/gameLibs/render/shaders/tsr.dshl index cebf7fd32..ec3452190 100644 --- a/prog/gameLibs/render/shaders/tsr.dshl +++ b/prog/gameLibs/render/shaders/tsr.dshl @@ -31,9 +31,6 @@ shader tsr_cs INIT_REPROJECTED_MOTION_VECTORS(cs) USE_REPROJECTED_MOTION_VECTORS(cs) - INIT_READ_MOTION_BUFFER_BASE(cs) - USE_READ_MOTION_BUFFER_BASE(cs) - INIT_HERO_MATRIX(cs) USE_HERO_MATRIX(cs) diff --git a/prog/gameLibs/render/shaders/tsr_vr.dshl b/prog/gameLibs/render/shaders/tsr_vr.dshl index c294f46ec..a75fd1266 100644 --- a/prog/gameLibs/render/shaders/tsr_vr.dshl +++ b/prog/gameLibs/render/shaders/tsr_vr.dshl @@ -19,9 +19,6 @@ macro TSR_INCLUDES(code) INIT_READ_DEPTH_GBUFFER_BASE(code) USE_READ_DEPTH_GBUFFER_BASE(code) - INIT_READ_MOTION_BUFFER_BASE(code) - USE_READ_MOTION_BUFFER_BASE(code) - local float4 tsr_input_color_dimensions = get_dimensions(tsr_input_color, 0); (code) { diff --git a/prog/gameLibs/render/texDebug/texDebug.cpp b/prog/gameLibs/render/texDebug/texDebug.cpp index 5b8143aac..a2221ba3f 100644 --- a/prog/gameLibs/render/texDebug/texDebug.cpp +++ b/prog/gameLibs/render/texDebug/texDebug.cpp @@ -332,10 +332,11 @@ static float tex_sliceI_val(const TextureInfo &ti) static void set_image_mode(const ImDrawList *, const ImDrawCmd *cmd) { + static int custom_sampler_const_no = ShaderGlobal::get_slot_by_name("custom_sampler_const_no"); if ((int)(uintptr_t)cmd->UserCallbackData == -1) { ShaderGlobal::set_int(imgui_use_custom_sampler, 1); - d3d::set_sampler(STAGE_PS, 5, borderSampler); + d3d::set_sampler(STAGE_PS, custom_sampler_const_no, borderSampler); return; } @@ -371,7 +372,7 @@ static void set_image_mode(const ImDrawList *, const ImDrawCmd *cmd) auto diffTexId = get_managed_texture_id(selectedTextureNameForDiff.data()); ShaderGlobal::set_texture(imgui_tex_diff, diffTexId); - d3d::set_sampler(STAGE_PS, 5, pointSampler); + d3d::set_sampler(STAGE_PS, custom_sampler_const_no, pointSampler); } static void reset_image_mode(const ImDrawList *, const ImDrawCmd *) diff --git a/prog/gameLibs/render/volumetricLights/shaders/use_volfog.dshl b/prog/gameLibs/render/volumetricLights/shaders/use_volfog.dshl index 88b313755..8c6550d30 100644 --- a/prog/gameLibs/render/volumetricLights/shaders/use_volfog.dshl +++ b/prog/gameLibs/render/volumetricLights/shaders/use_volfog.dshl @@ -480,9 +480,6 @@ macro USE_VOLUMETRIC_LIGHT_TRANSPARENT(code) endmacro macro USE_VOLUMETRIC_LIGHT_SKY(code) - hlsl(code) { - #define DISTANT_FOG_USE_BILINEAR_SAMPLING 1 - } USE_VOLUMETRIC_LIGHT_INC(code) hlsl(code) { void apply_sky_custom_fog(inout half3 val, float2 screen_tc, float2 jittered_screen_tc) @@ -515,6 +512,8 @@ endmacro macro CUSTOM_FOG_SKY(code) INIT_VOLUMETRIC_LIGHT_COMMON() INIT_VOLUMETRIC_LIGHT_BASE(code) + INIT_VOLUMETRIC_LIGHT_DEPTH(code) + INIT_VOLUMETRIC_LIGHT_BLOCK(code) USE_VOLUMETRIC_LIGHT_SKY(code) endmacro diff --git a/prog/gameLibs/soundSystem/attributes.cpp b/prog/gameLibs/soundSystem/attributes.cpp index 51f9f4988..9d3604de6 100644 --- a/prog/gameLibs/soundSystem/attributes.cpp +++ b/prog/gameLibs/soundSystem/attributes.cpp @@ -53,6 +53,15 @@ bool has_sustain_point_impl(const FMOD::Studio::EventDescription &event_descript return hasSustainPoint; } +bool has_occlusion_impl(const FMOD::Studio::EventDescription &event_description) +{ + TIME_PROFILE_DEV(has_occlusion_impl); + FMOD_STUDIO_PARAMETER_DESCRIPTION paramDesc; + constexpr const char *occlusion_param_name = "occlusion"; + return FMOD_OK == event_description.getParameterDescriptionByName(occlusion_param_name, ¶mDesc) && + is_event_3d_impl(event_description); +} + float get_event_max_distance_impl(const FMOD::Studio::EventDescription &event_description) { TIME_PROFILE_DEV(get_event_max_distance); @@ -88,7 +97,8 @@ EventAttributes make_event_attributes(const FMOD::Studio::EventDescription &even G_ASSERT(banks::is_valid_event(*reinterpret_cast(&id))); #endif return EventAttributes(get_event_max_distance_impl(event_description), is_event_oneshot_impl(event_description), - is_event_3d_impl(event_description), has_sustain_point_impl(event_description), get_user_label_idx(event_description)); + is_event_3d_impl(event_description), has_sustain_point_impl(event_description), has_occlusion_impl(event_description), + get_user_label_idx(event_description)); } EventAttributes find_event_attributes(const char *path, size_t path_len) diff --git a/prog/gameLibs/soundSystem/debug.cpp b/prog/gameLibs/soundSystem/debug.cpp index 9f10662b9..ab7de75e9 100644 --- a/prog/gameLibs/soundSystem/debug.cpp +++ b/prog/gameLibs/soundSystem/debug.cpp @@ -26,6 +26,7 @@ #include "internal/events.h" #include "internal/streams.h" #include "internal/soundSystem.h" +#include "internal/occlusion.h" #include "internal/debug.h" static WinCritSec g_debug_trace_cs; @@ -629,6 +630,22 @@ static inline void draw_mem_stat(int &offset) fmem.currentalloced / 1024.f / 1024.f, fmem.maxalloced / 1024.f / 1024.f); } +static int g_occlusion_offset = 0; +static void draw_occlusion_src(FMOD::Studio::EventInstance *instance, occlusion::group_id_t group_id, const Point3 &, float value, + bool is_in_group, bool is_first_in_group) +{ + FrameStr name = "???"; + FMOD::Studio::EventDescription *description = nullptr; + if (FMOD_OK == instance->getDescription(&description)) + name = eastl::move(get_debug_name(*description)); + + g_occlusion_offset += print_format(g_offset.x, g_occlusion_offset, g_def_color, "%s %d %.2f %s", + is_first_in_group ? "(*)" + : is_in_group ? "(^)" + : "( )", + group_id, value, name.c_str()); +} + void debug_draw() { SNDSYS_IF_NOT_INITED_RETURN; @@ -675,6 +692,9 @@ void debug_draw() print_messages(); draw_streams(); + g_occlusion_offset = (StdGuiRender::get_viewport().leftTop.y + StdGuiRender::get_viewport().rightBottom.y) * 2 / 3; + occlusion::debug_enum_sources(&draw_occlusion_src); + StdGuiRender::reset_draw_str_attr(); StdGuiRender::flush_data(); } diff --git a/prog/gameLibs/soundSystem/events.cpp b/prog/gameLibs/soundSystem/events.cpp index 453d48ade..017e0e214 100644 --- a/prog/gameLibs/soundSystem/events.cpp +++ b/prog/gameLibs/soundSystem/events.cpp @@ -24,6 +24,7 @@ #include "internal/vars.h" #include "internal/events.h" #include "internal/pool.h" +#include "internal/occlusion.h" #include "internal/debug.h" namespace sndsys @@ -381,7 +382,7 @@ static __forceinline void set_3d_attr_impl(FMOD::Studio::EventInstance &event_in SOUND_VERIFY(event_instance.set3DAttributes(&attributes_3d)); } -static __forceinline void set_3d_attr_impl(EventHandle event_handle, const Attributes3D &attributes_3d) +static __forceinline void set_3d_attr_internal(EventHandle event_handle, const Attributes3D &attributes_3d) { FMOD::Studio::EventDescription *eventDescription = nullptr; FMOD::Studio::EventInstance *eventInstance = nullptr; @@ -389,7 +390,11 @@ static __forceinline void set_3d_attr_impl(EventHandle event_handle, const Attri if (!get_valid_event_impl(event_handle, eventDescription, eventInstance, attributes)) return; if (attributes.is3d()) + { set_3d_attr_impl(*eventInstance, attributes_3d); + if (attributes.hasOcclusion()) + occlusion::set_pos(*eventInstance, as_point3(attributes_3d.position)); + } } static bool allow_event_init(ieff_t flags, const Point3 *position, const EventAttributes &attributes) @@ -493,6 +498,9 @@ EventHandle init_event(const char *name, const char *path, ieff_t flags, const P return EventHandle(INVALID_SOUND_HANDLE); } + if (attributes.hasOcclusion() && position) + occlusion::append(descAndInstance.second, descAndInstance.first, *position); + return handle; } @@ -574,7 +582,13 @@ EventHandle init_event(const FMODGUID &event_id, const Point3 *position /* = nul } if (position != nullptr) + { set_3d_attr(handle, *position); + + if (attributes.hasOcclusion()) + occlusion::append(descAndInstance.second, descAndInstance.first, *position); + } + return handle; } @@ -824,6 +838,10 @@ static void abandon_impl(FMOD::Studio::EventInstance &event_instance, const Even stop_impl(event_instance, true); } } + + if (attributes.hasOcclusion()) + occlusion::erase(&event_instance, true); + release_event_instance(event_instance, false); } @@ -948,6 +966,9 @@ bool play_one_shot(const char *name, const char *path, const Point3 *position, i start_impl(*descAndInstance.second); + if (attributes.hasOcclusion() && position) + occlusion::apply_oneshot(*descAndInstance.second, *position, *get_system()); + abandon_impl(*descAndInstance.second, attributes); if (!attributes.isOneshot() || attributes.hasSustainPoint()) @@ -1099,18 +1120,18 @@ int get_timeline_position(EventHandle event_handle) return -1; } -void set_3d_attr(EventHandle event_handle, const Point3 &pos) { set_3d_attr_impl(event_handle, Attributes3D(pos)); } +void set_3d_attr(EventHandle event_handle, const Point3 &pos) { set_3d_attr_internal(event_handle, Attributes3D(pos)); } void set_3d_attr(EventHandle event_handle, const Point3 &pos, const Point3 &vel, const Point3 &ori, const Point3 &up) { - set_3d_attr_impl(event_handle, Attributes3D(pos, vel, ori, up)); + set_3d_attr_internal(event_handle, Attributes3D(pos, vel, ori, up)); } void set_3d_attr(EventHandle event_handle, const TMatrix4 &tm, const Point3 &vel) { - set_3d_attr_impl(event_handle, Attributes3D(tm, vel)); + set_3d_attr_internal(event_handle, Attributes3D(tm, vel)); } void set_3d_attr(EventHandle event_handle, const TMatrix &tm, const Point3 &vel) { - set_3d_attr_impl(event_handle, Attributes3D(tm, vel)); + set_3d_attr_internal(event_handle, Attributes3D(tm, vel)); } bool get_3d_attr(EventHandle event_handle, TMatrix &tm, Point3 &vel) diff --git a/prog/gameLibs/soundSystem/geometry.cpp b/prog/gameLibs/soundSystem/geometry.cpp index fd9147ab2..35fa074c7 100644 --- a/prog/gameLibs/soundSystem/geometry.cpp +++ b/prog/gameLibs/soundSystem/geometry.cpp @@ -372,6 +372,7 @@ const eastl::vector *get_geometry_faces(int geometry_id) #endif } +// debug Point2 get_geometry_occlusion(const Point3 &source, const Point3 &listener) { Point2 directReverb = {}; diff --git a/prog/gameLibs/soundSystem/internal/attributes.h b/prog/gameLibs/soundSystem/internal/attributes.h index cb7155437..a2d11aa53 100644 --- a/prog/gameLibs/soundSystem/internal/attributes.h +++ b/prog/gameLibs/soundSystem/internal/attributes.h @@ -27,6 +27,7 @@ class EventAttributes FLAG_ONESHOT = (1 << 0), FLAG_HAS_SUSTAIN_POINT = (1 << 1), FLAG_3D = (1 << 2), + FLAG_HAS_OCCLUSION = (1 << 3), FLAG_VALID = (1 << 7), // Bit to distinguish valid EventAttributes from invalid one (can be omitted if e.g. maxDistance can't be 0) }; @@ -42,6 +43,7 @@ class EventAttributes inline void setOneshot(bool is_oneshot) { setFlag(FLAG_ONESHOT, is_oneshot); } inline void set3d(bool is_3d) { setFlag(FLAG_3D, is_3d); } inline void setHasSustainPoint(bool has_cue) { setFlag(FLAG_HAS_SUSTAIN_POINT, has_cue); } + inline void setHasOcclusion(bool has_occlusion) { setFlag(FLAG_HAS_OCCLUSION, has_occlusion); } inline void setVisualLabel(int idx) { @@ -59,15 +61,18 @@ class EventAttributes inline bool isOneshot() const { return (flags & FLAG_ONESHOT) != 0; } inline bool is3d() const { return (flags & FLAG_3D) != 0; } inline bool hasSustainPoint() const { return (flags & FLAG_HAS_SUSTAIN_POINT) != 0; } + inline bool hasOcclusion() const { return (flags & FLAG_HAS_OCCLUSION) != 0; } inline int getVisualLabelIdx() const { return labelIdx; } EventAttributes() = default; - inline EventAttributes(float max_distance, bool is_oneshot, bool is_3d, bool has_sustain_point, int visual_label_idx) + inline EventAttributes(float max_distance, bool is_oneshot, bool is_3d, bool has_sustain_point, bool has_occlusion, + int visual_label_idx) { flags = FLAG_VALID; setMaxDistance(max_distance); setOneshot(is_oneshot); setHasSustainPoint(has_sustain_point); + setHasOcclusion(has_occlusion); set3d(is_3d); setVisualLabel(visual_label_idx); } @@ -78,6 +83,7 @@ class EventAttributes bool is_event_oneshot_impl(const FMOD::Studio::EventDescription &event_description); bool is_event_3d_impl(const FMOD::Studio::EventDescription &event_description); bool has_sustain_point_impl(const FMOD::Studio::EventDescription &event_description); +bool has_occlusion_impl(const FMOD::Studio::EventDescription &event_description); float get_event_max_distance_impl(const FMOD::Studio::EventDescription &event_description); EventAttributes find_event_attributes(const char *path, size_t path_len); diff --git a/prog/gameLibs/soundSystem/internal/occlusion.h b/prog/gameLibs/soundSystem/internal/occlusion.h new file mode 100644 index 000000000..2c64ea233 --- /dev/null +++ b/prog/gameLibs/soundSystem/internal/occlusion.h @@ -0,0 +1,39 @@ +// Copyright (C) Gaijin Games KFT. All rights reserved. +#pragma once + +#include + +class DataBlock; + +namespace FMOD +{ +class System; +namespace Studio +{ +class EventInstance; +class EventDescription; +} // namespace Studio +} // namespace FMOD + +namespace sndsys::occlusion +{ +void apply_oneshot(FMOD::Studio::EventInstance &instance, const Point3 &pos, FMOD::System &low_level_system); + +void set_pos(FMOD::Studio::EventInstance &instance, const Point3 &pos); + +void set_pos(group_id_t group_id, const Point3 &pos); + +void set_group(FMOD::Studio::EventInstance *instance, group_id_t group_id); + +void append(FMOD::Studio::EventInstance *instance, const FMOD::Studio::EventDescription *description, const Point3 &pos); + +void erase(FMOD::Studio::EventInstance *instance, bool apply_occlusion); + +void update(const Point3 &listener, FMOD::System &low_level_system); + +typedef void (*debug_enum_sources_t)(FMOD::Studio::EventInstance *, group_id_t, const Point3 &, float, bool, bool); + +void debug_enum_sources(debug_enum_sources_t); + +void init(const DataBlock &blk); +} // namespace sndsys::occlusion diff --git a/prog/gameLibs/soundSystem/jamfile b/prog/gameLibs/soundSystem/jamfile index ebdd9239e..7383c3c4a 100644 --- a/prog/gameLibs/soundSystem/jamfile +++ b/prog/gameLibs/soundSystem/jamfile @@ -43,6 +43,7 @@ Sources = eventInstanceStealing.cpp visualLabels.cpp geometry.cpp + occlusion.cpp ; if $(Config) = rel { diff --git a/prog/gameLibs/soundSystem/occlusion.cpp b/prog/gameLibs/soundSystem/occlusion.cpp new file mode 100644 index 000000000..589b3d237 --- /dev/null +++ b/prog/gameLibs/soundSystem/occlusion.cpp @@ -0,0 +1,366 @@ +// Copyright (C) Gaijin Games KFT. All rights reserved. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "internal/events.h" +#include "internal/fmodCompatibility.h" +#include "internal/occlusion.h" +#include "internal/debug.h" + +static WinCritSec g_occlusion_cs; +#define SNDSYS_OCCLUSION_BLOCK WinAutoLock occlusionLock(g_occlusion_cs); + +namespace sndsys::occlusion +{ +using fmod_instance_t = FMOD::Studio::EventInstance; + +static constexpr size_t g_sources_capacity = 64; +static constexpr group_id_t g_invalid_group_id = {}; +static constexpr float g_uninited_value = -1; +static constexpr float g_default_value = 0; + +static eastl::fixed_string g_occlusion_param_name; +static float g_near_attenuation = 0.f; +static float g_far_attenuation = 0.f; +static Point3 g_listener_pos = {}; +static std::atomic_bool g_occlusion_inited = ATOMIC_VAR_INIT(false); + +struct Source +{ + fmod_instance_t *instance = nullptr; + group_id_t groupId = g_invalid_group_id; + Point3 pos = {}; + VarId varId = {}; + float value = g_uninited_value; + + bool operator==(const Source &other) const { return instance == other.instance && groupId == other.groupId; } + bool operator!=(const Source &other) const { return instance != other.instance || groupId != other.groupId; } + bool operator<(const Source &other) const + { + return (groupId != other.groupId) ? (groupId < other.groupId) : (intptr_t(instance) < intptr_t(other.instance)); + } +}; + +/* legend: + * + * inst invalid_group_id pos tIdx=0 + * inst invalid_group_id pos tIdx=1 + * inst invalid_group_id pos tIdx=2 + * inst invalid_group_id pos tIdx=3 + * + * inst grp0 pos tIdx=4 + * inst grp0 ^ ^ + * inst grp0 ^ ^ + * + * inst grp1 pos tIdx=5 + * inst grp1 ^ ^ + * + * inst grp2 pos tIdx=6 + * inst grp2 ^ ^ + * inst grp2 ^ ^ + * inst grp2 ^ ^ + */ + +static eastl::vector_set, EASTLAllocatorType, + eastl::fixed_vector> + g_sources; + +struct FindAsGroupId : public eastl::binary_function +{ + bool operator()(group_id_t a, const Source &b) const { return a < b.groupId; } + bool operator()(const Source &a, group_id_t b) const { return a.groupId < b; } +}; + +static Source *find_first_source_in_group(group_id_t group_id) +{ + auto fnd = g_sources.find_as(group_id, FindAsGroupId()); + if (fnd == g_sources.end()) + return nullptr; + for (; fnd > g_sources.begin() && fnd[-1].groupId == fnd->groupId; --fnd) {} + G_ASSERT(fnd->groupId == group_id); + return fnd; +} + +static Source *find_source_by_instance_no_group(fmod_instance_t *instance) +{ + auto fnd = g_sources.find(Source{instance, g_invalid_group_id}); + if (fnd == g_sources.end()) + return nullptr; + G_ASSERT(instance == fnd->instance && fnd->groupId == g_invalid_group_id); + return fnd; +} + +static Source *find_source_by_instance_only(fmod_instance_t *instance) +{ + for (Source &src : g_sources) + if (src.instance == instance) + return &src; + return nullptr; +} + +static Source *get_next_source_in_group(Source *src) +{ + G_ASSERT(src >= g_sources.begin() && src < g_sources.end()); + if (src->groupId != g_invalid_group_id) + { + Source *next = src + 1; + if (next < g_sources.end() && next->groupId == src->groupId) + return next; + } + return nullptr; +} + +static bool is_in_group(Source &src) { return src.groupId != g_invalid_group_id; } + +static bool is_first_in_group(Source &src) +{ + if (!is_in_group(src)) + return false; + return (&src > g_sources.begin()) ? (&src - 1)->groupId != src.groupId : &src == g_sources.begin(); +} + +static void insert(const Source &value) +{ + const auto ins = g_sources.insert(value); + Source *src = ins.first; + G_ASSERT(ins.second && src >= g_sources.begin() && src < g_sources.end()); + if (Source *next = get_next_source_in_group(src)) + src->pos = next->pos; +} + +static void erase(Source *src) +{ + G_ASSERT(src >= g_sources.begin() && src < g_sources.end()); + if (Source *next = get_next_source_in_group(src)) + next->pos = src->pos; + g_sources.erase(src); +} + +void append(FMOD::Studio::EventInstance *instance, const FMOD::Studio::EventDescription *description_, const Point3 &pos) +{ + TIME_PROFILE_DEV(sndsys_occlusion_append); + if (!g_occlusion_inited) + return; + SNDSYS_OCCLUSION_BLOCK; + + FMOD_STUDIO_PARAMETER_DESCRIPTION desc; + SOUND_VERIFY(description_->getParameterDescriptionByName(g_occlusion_param_name.c_str(), &desc)); + const VarId varId = as_var_id(desc.id); + if (varId) + insert(Source{instance, g_invalid_group_id, pos, varId}); + else + logerr("missing var labeled '%s' in event '%s'", g_occlusion_param_name.c_str(), get_debug_name(*description_).c_str()); +} + +void set_pos(FMOD::Studio::EventInstance &instance, const Point3 &pos) +{ + if (!g_occlusion_inited) + return; + SNDSYS_OCCLUSION_BLOCK; + + if (Source *src = find_source_by_instance_no_group(&instance)) + src->pos = pos; +} + +void set_pos(group_id_t group_id, const Point3 &pos) +{ + if (!g_occlusion_inited) + return; + SNDSYS_OCCLUSION_BLOCK; + + if (Source *src = find_first_source_in_group(group_id)) + src->pos = pos; +} + +void set_group(FMOD::Studio::EventInstance *instance, group_id_t group_id) +{ + if (!g_occlusion_inited) + return; + SNDSYS_OCCLUSION_BLOCK; + + Source *src = find_source_by_instance_only(instance); + if (!src) + return; + + Source cpy = *src; + + cpy.groupId = group_id; + + erase(src); + + insert(cpy); +} + +static float make_occlusion_impl(const Point3 &pos, FMOD::System &low_level_system) +{ + TIME_PROFILE_DEV(sndsys_occlusion_make_occlusion); + + float value = 0.; + + const Point3 dir = pos - g_listener_pos; + + if (dir.lengthSq() < sqr(g_far_attenuation)) + { + SOUND_VERIFY(low_level_system.getGeometryOcclusion(&as_fmod_vector(pos), &as_fmod_vector(g_listener_pos), &value, nullptr)); + + value = cvt(dir.length(), g_near_attenuation, g_far_attenuation, value, 0.f); + + value = saturate(value); + } + + return value; +} + +static void set_occlusion(Source &src, float value) +{ + if (src.value != value) + { + src.value = value; + SOUND_VERIFY(src.instance->setParameterByID(as_fmod_param_id(src.varId), value)); + } +} + +void apply_oneshot(FMOD::Studio::EventInstance &instance, const Point3 &pos, FMOD::System &low_level_system) +{ + TIME_PROFILE_DEV(sndsys_occlusion_apply_oneshot); + if (!g_occlusion_inited) + return; + SNDSYS_OCCLUSION_BLOCK; + + if (!g_listener_pos.lengthSq()) + return; + + const float value = make_occlusion_impl(pos, low_level_system); + + if (value != g_default_value) + SOUND_VERIFY(instance.setParameterByName(g_occlusion_param_name.c_str(), value)); +} + +void erase(FMOD::Studio::EventInstance *instance, bool apply_occlusion) +{ + if (!g_occlusion_inited) + return; + SNDSYS_OCCLUSION_BLOCK; + if (Source *src = find_source_by_instance_only(instance)) + { + if (apply_occlusion) + if (src->value == g_uninited_value) + if (src->groupId == g_invalid_group_id) + if (src->instance->isValid()) + if (auto sys = fmodapi::get_system()) + { + // instance was created, and then was abandoned, but it still playing + set_occlusion(*src, make_occlusion_impl(src->pos, *sys)); + } + erase(src); + } +} + +static intptr_t g_cur_offset = 0; + +void update(const Point3 &listener, FMOD::System &low_level_system) +{ + TIME_PROFILE_DEV(sndsys_occlusion_update); + if (!g_occlusion_inited) + return; + SNDSYS_OCCLUSION_BLOCK; + g_listener_pos = listener; + if (!g_listener_pos.lengthSq()) + return; + + if (g_sources.empty()) + { + g_cur_offset = 0; + return; + } + + intptr_t tIdx = -1; + constexpr intptr_t traces = 4; + + g_cur_offset %= g_sources.size(); + const intptr_t a = g_cur_offset; + const intptr_t b = g_cur_offset + traces; + g_cur_offset += traces; + + float value = 0.f; + + for (intptr_t i = 0; i < g_sources.size();) + { + Source &src = g_sources[i]; + + if (!src.instance->isValid()) + { + erase(&src); + if (g_cur_offset >= g_sources.size()) + g_cur_offset -= g_sources.size(); + continue; + } + + if (is_first_in_group(src) || !is_in_group(src)) + { + ++tIdx; + + if (src.value == g_uninited_value || ((tIdx >= a && tIdx < b) || (tIdx + g_sources.size() >= a && tIdx + g_sources.size() < b))) + set_occlusion(src, make_occlusion_impl(src.pos, low_level_system)); + + value = src.value; + } + + set_occlusion(src, value); + + ++i; + } +} + +void debug_enum_sources(debug_enum_sources_t debug_enum_sources) +{ + if (!g_occlusion_inited) + return; + for (Source &src : g_sources) + debug_enum_sources(src.instance, src.groupId, src.pos, src.value, is_in_group(src), is_first_in_group(src)); +} + +void set_group_pos(group_id_t group_id, const Point3 &pos) +{ + if (!g_occlusion_inited) + return; + set_pos(group_id, pos); +} + +void set_event_group(EventHandle event_handle, group_id_t group_id) +{ + if (!g_occlusion_inited) + return; + if (fmod_instance_t *instance = fmodapi::get_instance(event_handle)) + set_group(instance, group_id); +} + +bool is_inited() { return g_occlusion_inited; } + +void init(const DataBlock &blk) +{ + SNDSYS_OCCLUSION_BLOCK; + + G_ASSERT(!g_occlusion_inited); + g_occlusion_inited = false; + g_occlusion_param_name = blk.getStr("occlusionParamName", "occlusion"); + G_ASSERT_RETURN(!g_occlusion_param_name.empty(), ); + + g_near_attenuation = blk.getReal("occlusionNearAttenuation", 40.f); + g_far_attenuation = blk.getReal("occlusionFarAttenuation", 45.f); + + g_occlusion_inited = true; +} + +} // namespace sndsys::occlusion diff --git a/prog/gameLibs/soundSystem/soundSystem.cpp b/prog/gameLibs/soundSystem/soundSystem.cpp index 034224e34..44cf2c9ee 100644 --- a/prog/gameLibs/soundSystem/soundSystem.cpp +++ b/prog/gameLibs/soundSystem/soundSystem.cpp @@ -24,6 +24,7 @@ #include "internal/streams.h" #include "internal/soundSystem.h" #include "internal/events.h" +#include "internal/occlusion.h" #include "internal/debug.h" #include @@ -530,9 +531,14 @@ bool init(const DataBlock &blk) } events_init(blk); + streams::init(blk, settings::virtual_vol_limit, g_low_level_system); + delayed::init(blk); + if (blk.getBool("occlusionEnabled", false)) + occlusion::init(blk); + eastl::basic_string memoryInfo; if (g_fixed_mem_pool) memoryInfo.sprintf("memory pool at 0x%p, size", g_memory_block); @@ -852,5 +858,10 @@ FMOD::Studio::System *get_studio_system() G_ASSERT_RETURN(is_inited(), nullptr); return g_system; } +eastl::pair get_systems() +{ + G_ASSERT_RETURN(is_inited(), {}); + return eastl::make_pair(g_low_level_system, g_system); +} } // namespace fmodapi } // namespace sndsys diff --git a/prog/gameLibs/soundSystem/stub/soundSystemStub.cpp b/prog/gameLibs/soundSystem/stub/soundSystemStub.cpp index 8ba129261..7a6c63714 100644 --- a/prog/gameLibs/soundSystem/stub/soundSystemStub.cpp +++ b/prog/gameLibs/soundSystem/stub/soundSystemStub.cpp @@ -12,6 +12,7 @@ #include #include #include +#include class DataBlock; @@ -33,6 +34,7 @@ namespace fmodapi { FMOD::System *get_system() { return nullptr; } FMOD::Studio::System *get_studio_system() { return nullptr; } +eastl::pair get_systems() { return {}; } FMOD::Studio::EventInstance *get_instance(EventHandle) { return nullptr; } FMOD::Studio::EventDescription *get_description(EventHandle) { return nullptr; } FMOD::Studio::EventDescription *get_description(const char *, const char *) { return nullptr; } @@ -204,6 +206,14 @@ int get_geometry_id(int) { return -1; } const eastl::vector *get_geometry_faces(int) { return nullptr; } void save_geometry_to_file(const char *) {} bool load_geometry_from_file(const char *) { return false; } - Point2 get_geometry_occlusion(const Point3 &, const Point3 &) { return {}; } + +// occlusion.cpp +namespace occlusion +{ +bool is_inited() { return false; } +void set_group_pos(group_id_t, const Point3 &) {} +void set_event_group(EventHandle, group_id_t) {} +} // namespace occlusion + } // namespace sndsys diff --git a/prog/gameLibs/soundSystem/update.cpp b/prog/gameLibs/soundSystem/update.cpp index 1121e57f5..7e44e7b7f 100644 --- a/prog/gameLibs/soundSystem/update.cpp +++ b/prog/gameLibs/soundSystem/update.cpp @@ -14,6 +14,7 @@ #include "internal/delayed.h" #include "internal/events.h" #include "internal/streams.h" +#include "internal/occlusion.h" #include "internal/debug.h" #include @@ -135,7 +136,11 @@ void end_update(float dt) streams::update(dt); - SOUND_VERIFY(get_studio_system()->update()); + const auto systemAndStudioSystem = get_systems(); + + occlusion::update(get_3d_listener_pos(), *systemAndStudioSystem.first); + + SOUND_VERIFY(systemAndStudioSystem.second->update()); banks::update(); } diff --git a/prog/gameLibs/spirv/compiler_dxc.cpp b/prog/gameLibs/spirv/compiler_dxc.cpp index 294cf9e9d..3bf986a5a 100644 --- a/prog/gameLibs/spirv/compiler_dxc.cpp +++ b/prog/gameLibs/spirv/compiler_dxc.cpp @@ -363,7 +363,7 @@ CompileToSpirVResult spirv::compileHLSL_DXC(dag::ConstSpan source, const c #elif _TARGET_PC_LINUX const String libPath = lookupPath + "libdxcompiler.so"; #endif - eastl::unique_ptr library; + DagorDynLibHolder library; library.reset(os_dll_load_deep_bind(libPath.c_str())); if (!library) { diff --git a/prog/gameLibs/userSystemInfo/systemInfo.cpp b/prog/gameLibs/userSystemInfo/systemInfo.cpp index 4914c06c5..f361066dd 100644 --- a/prog/gameLibs/userSystemInfo/systemInfo.cpp +++ b/prog/gameLibs/userSystemInfo/systemInfo.cpp @@ -1184,7 +1184,7 @@ int get_battery_from_device_list() const DataBlock *model = modelsBlk.getBlockByName(cpuModel.c_str()); if (!model) - return returnDefault("Unknown model"); + return returnDefault(String(-1, "Unknown model %s", cpuModel.c_str()).c_str()); return model->getInt("batterySize", UNKNOWN_CAPACITY); } @@ -1325,9 +1325,10 @@ ThermalStatus get_thermal_state() JAVA_METHOD(getBattery, float, JNI_SIGNATURE(JNI_FLOAT, )); JAVA_METHOD(getIsBatteryCharging, bool, JNI_SIGNATURE(JNI_BOOL, )); JAVA_METHOD(mAhBatteryCapacity, long, JNI_SIGNATURE(JNI_LONG, )); +JAVA_METHOD(isTablet, bool, JNI_SIGNATURE(JNI_BOOL, )); JAVA_APP_CONTEXT_CLASS(AppActivity, JAVA_CLASS_METHOD(getBattery), JAVA_CLASS_METHOD(getIsBatteryCharging), - JAVA_CLASS_METHOD(mAhBatteryCapacity)); + JAVA_CLASS_METHOD(mAhBatteryCapacity), JAVA_CLASS_METHOD(isTablet)); JAVA_THREAD_LOCAL_ENV(AppActivity); @@ -1602,6 +1603,19 @@ int get_network_connection_type() { return -1; } #endif +#if _TARGET_ANDROID +int is_tablet() +{ + if (JAVA_INIT_ENV) + return JAVA_CALL_RETURN(isTablet, JAVA_APP_CONTEXT, false); + return -1; +}; +#elif _TARGET_IOS +int is_tablet() { return ios_is_ipad(); } +#else +int is_tablet() { return -1; } +#endif + const char *to_string(ThermalStatus status) { switch (status) diff --git a/prog/gameLibs/userSystemInfo/userSystemInfo.cpp b/prog/gameLibs/userSystemInfo/userSystemInfo.cpp index bbd83a649..9e396ddce 100644 --- a/prog/gameLibs/userSystemInfo/userSystemInfo.cpp +++ b/prog/gameLibs/userSystemInfo/userSystemInfo.cpp @@ -272,6 +272,8 @@ void get_user_system_info(DataBlock *blk, const char *gfx_preset) cachedSysInfo.addBool("inlineRaytracingAvailable", systeminfo::get_inline_raytracing_available()); + cachedSysInfo.addInt("isTablet", systeminfo::is_tablet()); + blk->setFrom(&cachedSysInfo); } diff --git a/prog/scripts/genDasevents.das b/prog/scripts/genDasevents.das index b37d36ee3..5ca8a6d09 100644 --- a/prog/scripts/genDasevents.das +++ b/prog/scripts/genDasevents.das @@ -1,3 +1,4 @@ +options strict_smart_pointers = false require DagorFiles require ecs require strings @@ -72,14 +73,14 @@ typedef SqEventsData = table EnumsData = table> -def get_annotation(annotations : rtti::AnnotationList; tag : string) : smart_ptr +def get_annotation(var annotations : rtti::AnnotationList; tag : string) : smart_ptr for ann in annotations if ann.annotation.name == tag return ann return unsafe(reinterpret> null) -def has_annotation(annotations : rtti::AnnotationList; tag : string) +def has_annotation(var annotations : rtti::AnnotationList; tag : string) let ann <- get_annotation(annotations, tag) return ann != null @@ -148,7 +149,7 @@ def gen_cpp_event(cppEvents : EventsData; output, file_name : string; exclude_ev for eventData in process if verbose print(" ++ {eventData.fullName}") - let st & = eventData.st + var st & = eventData.st let ann <- st.annotations |> get_annotation("cpp_event") if ann != null let broadcast = ann.arguments |> get_bool_argument("broadcast") @@ -289,7 +290,7 @@ def get_sq_type(typ : smart_ptr) return "instance" // float3, ecs::Object, etc -def get_func_stub(name : string; fn : smart_ptr) +def get_func_stub(name : string; var fn : smart_ptr) var optionalArgsNum = 0 let n = length(fn.arguments) var i = n diff --git a/prog/scripts/rebuild_all_dasbindings.py b/prog/scripts/rebuild_all_dasbindings.py index c5ec0ea3c..33a2b8de6 100644 --- a/prog/scripts/rebuild_all_dasbindings.py +++ b/prog/scripts/rebuild_all_dasbindings.py @@ -20,7 +20,7 @@ def shell(cmd, print_stdout=True): ("jam -sPlatformArch=x86_64 -sRoot=../.. -f aot/jamfile",) }, {"wdir":"../../skyquake/prog/scripts","cmds": - ("genDasevents.bat",) + ("genDasevents_x86_64.bat",) }, {"wdir":"../../enlisted/prog","cmds": ("jam -sPlatformArch=x86_64 -sRoot=../.. -f aot/jamfile", "genDasevents.bat") @@ -44,6 +44,7 @@ def main(): wdir = e["wdir"] with pushd(wdir): for cmd in e["cmds"]: + print("exec cmd: '", cmd, "' wdir: '", wdir, "'") shell(cmd) def are_files_changed_after_format(): diff --git a/prog/scripts/sq/std/frp.nut b/prog/scripts/sq/std/frp.nut index 3f64e2b1a..3a8a7ebe4 100644 --- a/prog/scripts/sq/std/frp.nut +++ b/prog/scripts/sq/std/frp.nut @@ -1,7 +1,13 @@ from "frp" import Computed, Watched, FRP_INITIAL, FRP_DONT_CHECK_NESTED, set_nested_observable_debug, make_all_observables_immutable, recalc_all_computed_values, gather_graph_stats, update_deferred, set_default_deferred -// set_default_deferred(false) +// set_default_deferred(false, false) // Computed, Watched + +function WatchedImmediate(...) { + let w = Watched.acall([this].extend(vargv)) + w.setDeferred(false) + return w +} function ComputedImmediate(...) { let c = Computed.acall([this].extend(vargv)) @@ -195,6 +201,7 @@ return { Computed ComputedImmediate Watched + WatchedImmediate FRP_INITIAL FRP_DONT_CHECK_NESTED set_nested_observable_debug diff --git a/prog/tools/AssetViewer/animTree/controllers/hub.cpp b/prog/tools/AssetViewer/animTree/controllers/hub.cpp index 035dff6b6..d10e33df7 100644 --- a/prog/tools/AssetViewer/animTree/controllers/hub.cpp +++ b/prog/tools/AssetViewer/animTree/controllers/hub.cpp @@ -9,7 +9,7 @@ #include #include -static const bool DEFAULT_SPLIT_CHANS = true; +static const bool DEFAULT_SPLIT_CHANS = false; static const bool DEFAULT_OPTIONAL = false; static const bool DEFAULT_ENABLED = true; static const float DEFAULT_WEIGHT = 1.0f; diff --git a/prog/tools/AssetViewer/av_appwnd.h b/prog/tools/AssetViewer/av_appwnd.h index d5b523044..2fb271592 100644 --- a/prog/tools/AssetViewer/av_appwnd.h +++ b/prog/tools/AssetViewer/av_appwnd.h @@ -150,7 +150,7 @@ class AssetViewerApp : public GenericEditorAppWindow, virtual ModeType getGizmoModeType(); //{ return MODE_Move; } virtual BasisType getGizmoBasisType() { return BASIS_World; } virtual CenterType getGizmoCenterType() { return CENTER_Pivot; } - bool isGizmoOperationStarted() const; + virtual bool isGizmoOperationStarted() const override; // brush methods virtual void beginBrushPaint() {} diff --git a/prog/tools/AssetViewer/av_viewportWindow.cpp b/prog/tools/AssetViewer/av_viewportWindow.cpp index ac49eb3b3..d4846c5b8 100644 --- a/prog/tools/AssetViewer/av_viewportWindow.cpp +++ b/prog/tools/AssetViewer/av_viewportWindow.cpp @@ -3,6 +3,7 @@ #include "av_viewportWindow.h" #include "assetStats.h" #include "av_cm.h" +#include "av_appwnd.h" #include #include #include @@ -201,6 +202,11 @@ void AssetViewerViewportWindow::handleStatSettingsDialogChange(int pcb_id, bool ViewportWindow::handleStatSettingsDialogChange(pcb_id, value); } +bool AssetViewerViewportWindow::canStartInteractionWithViewport() +{ + return ViewportWindow::canStartInteractionWithViewport() && !get_app().isGizmoOperationStarted(); +} + int AssetViewerViewportWindow::getAssetStatByIndex(int index) { G_STATIC_ASSERT(AssetStatType::Count == 6); diff --git a/prog/tools/AssetViewer/av_viewportWindow.h b/prog/tools/AssetViewer/av_viewportWindow.h index 98638448c..5db1b5046 100644 --- a/prog/tools/AssetViewer/av_viewportWindow.h +++ b/prog/tools/AssetViewer/av_viewportWindow.h @@ -18,6 +18,7 @@ class AssetViewerViewportWindow : public ViewportWindow virtual void paint(int w, int h) override; virtual void fillStatSettingsDialog(ViewportWindowStatSettingsDialog &dialog) override; virtual void handleStatSettingsDialogChange(int pcb_id, bool value) override; + virtual bool canStartInteractionWithViewport() override; int getAssetStatByIndex(int index); static int getAssetStatIndexByName(const char *name); diff --git a/prog/tools/ShaderCompiler2/assemblyShader.cpp b/prog/tools/ShaderCompiler2/assemblyShader.cpp index e06a93168..8f24ebaa0 100644 --- a/prog/tools/ShaderCompiler2/assemblyShader.cpp +++ b/prog/tools/ShaderCompiler2/assemblyShader.cpp @@ -251,6 +251,11 @@ void AssembleShaderEvalCB::eval_static(static_var_decl &s) sv = append_items(sclass.stvar, 1); sclass.stvar[sv].type = t; sclass.stvar[sv].nameId = varNameId; + + if (sclass.stvarsAreDynamic.size() <= sv) + sclass.stvarsAreDynamic.resize(sv + 1); + sclass.stvarsAreDynamic[sv] = code.vars[v].dynamic; + const bool expectingInt = t == SHVT_INT || t == SHVT_INT4; Color4 val = expectingInt ? Color4{bitwise_cast(0), bitwise_cast(0), bitwise_cast(0), bitwise_cast(1)} : Color4{0, 0, 0, 1}; diff --git a/prog/tools/ShaderCompiler2/namedConst.cpp b/prog/tools/ShaderCompiler2/namedConst.cpp index eed5df65f..cc00bd2b0 100644 --- a/prog/tools/ShaderCompiler2/namedConst.cpp +++ b/prog/tools/ShaderCompiler2/namedConst.cpp @@ -736,7 +736,6 @@ void NamedConstBlock::buildStaticConstBufHlslDecl(String &out_text, const Merged { #if _CROSS_TARGET_C1 || _CROSS_TARGET_C2 - #elif _CROSS_TARGET_SPIRV bindlessProlog = "[[vk::binding(0, BINDLESS_TEXTURE_SET_META_ID)]] Texture2D static_textures[];\n" "[[vk::binding(0, BINDLESS_TEXTURE_SET_META_ID)]] TextureCube static_textures_cube[];\n" diff --git a/prog/tools/ShaderCompiler2/shCode.cpp b/prog/tools/ShaderCompiler2/shCode.cpp index 13174a178..5ccc576b8 100644 --- a/prog/tools/ShaderCompiler2/shCode.cpp +++ b/prog/tools/ShaderCompiler2/shCode.cpp @@ -70,6 +70,37 @@ unsigned int ShaderCode::getVertexStride() const return vertexStride; } +void ShaderClass::sortStaticVarsByMode() +{ + Tab> argvars{}; + argvars.reserve(stvar.size()); + int i = 0; + eastl::transform(stvar.cbegin(), stvar.cend(), argvars.begin(), [&i](const Var &var) { return eastl::make_pair(var, i++); }); + + // First statics, then dynamics, with as little reordering as possible + eastl::stable_partition(argvars.begin(), argvars.end(), [this](const auto &p) { return !stvarsAreDynamic[p.second]; }); + + // We don't need this data anymore, and no need to remap it + stvarsAreDynamic.clear(); + + Tab remapping(argvars.size()); + for (size_t i = 0; i < argvars.size(); ++i) + { + stvar[i] = argvars[i].first; + remapping[argvars[i].second] = i; + } + + // Now patch all stvarmaps for shader codes with the new mapping + for (ShaderCode *shcode : code) + { + if (shcode) + { + for (ShaderCode::StVarMap &mapping : shcode->stvarmap) + mapping.sv = remapping[mapping.sv]; + } + } +} + int ShaderClass::find_static_var(const int variable_name_id) { for (int i = 0; i < stvar.size(); ++i) diff --git a/prog/tools/ShaderCompiler2/shSemCode.cpp b/prog/tools/ShaderCompiler2/shSemCode.cpp index 8cb2315f7..564fed3ff 100644 --- a/prog/tools/ShaderCompiler2/shSemCode.cpp +++ b/prog/tools/ShaderCompiler2/shSemCode.cpp @@ -15,6 +15,7 @@ #include #include "linkShaders.h" #include "shCompiler.h" +#include #include @@ -49,6 +50,62 @@ ShaderSemCode::ShaderSemCode() : rm_alloc(4 << 20, 4 << 20) {} +void ShaderSemCode::initPassMap(int pass_id) +{ + if (vars.empty() || !passes[pass_id]) + return; + + passes[pass_id]->varmap.resize(vars.size()); + for (auto it = vars.begin(); it != vars.end(); ++it) + { + auto id = eastl::distance(vars.begin(), it); + passes[pass_id]->varmap[id] = id; + } +} + +void ShaderSemCode::mergeVars(Tab &&other_vars, Tab &&other_stvarmap, int pass_id) +{ + dag::VectorMap ownedVarsByNameId{}; + eastl::transform(vars.begin(), vars.end(), eastl::inserter(ownedVarsByNameId, ownedVarsByNameId.end()), + [this](Var &var) { return eastl::make_pair(var.nameId, &var); }); + + Tab otherStvarmapDirect{}; + otherStvarmapDirect.resize(other_stvarmap.size(), -1); + for (const StVarMap &mapping : other_stvarmap) + { + if (mapping.v >= otherStvarmapDirect.size()) + otherStvarmapDirect.resize(mapping.v + 1, -1); + otherStvarmapDirect[mapping.v] = mapping.sv; + } + + passes[pass_id]->varmap.reserve(passes[pass_id]->varmap.size() + other_vars.size()); + + for (auto it = other_vars.begin(); it != other_vars.end(); ++it) + { + auto stIt = ownedVarsByNameId.find(it->nameId); + Var *staticVar = nullptr; + if (stIt == ownedVarsByNameId.end()) + { + vars.push_back(eastl::move(*it)); + const int lastId = (int)(vars.size() - 1); + + staticVarRegs.add(vars.back().getName(), lastId); + + staticVar = vars.begin() + lastId; + int sv = otherStvarmapDirect[(int)eastl::distance(other_vars.begin(), it)]; + if (sv >= 0) + stvarmap.push_back({lastId, sv}); + } + else + { + staticVar = stIt->second; + staticVar->used = it->used ? true : staticVar->used; + } + + passes[pass_id]->varmap.push_back(eastl::distance(vars.data(), staticVar)); + } +} + ShaderCode *ShaderSemCode::generateShaderCode(const ShaderVariant::VariantTableSrc &dynVariants, StcodeShader &cppcode) { ShaderCode *code = new (midmem) ShaderCode(); @@ -98,12 +155,9 @@ ShaderCode *ShaderSemCode::generateShaderCode(const ShaderVariant::VariantTableS } // convert stvarmap - code->stvarmap.resize(stvarmap.size()); - for (int i = 0; i < code->stvarmap.size(); ++i) - { - code->stvarmap[i].v = cvar[stvarmap[i].v]; - code->stvarmap[i].sv = stvarmap[i].sv; - } + code->stvarmap.reserve(stvarmap.size()); + for (const StVarMap &mapping : stvarmap) + code->stvarmap.push_back({cvar[mapping.v], mapping.sv}); // convert passes tabutils::safeResize(code->passes, passes.size()); @@ -125,7 +179,7 @@ ShaderCode *ShaderSemCode::generateShaderCode(const ShaderVariant::VariantTableS if (otherPasses->pass) { ShaderCode::Pass p; - convert_passes(*otherPasses->pass, p, cvar, cppcode); + convert_passes(*otherPasses->pass, p, cvar, cppcode, otherPasses->varmap); int found = -1; for (int j = 0; j < all_passid.size(); j++) @@ -157,7 +211,7 @@ ShaderCode *ShaderSemCode::generateShaderCode(const ShaderVariant::VariantTableS return code; } -void ShaderSemCode::convert_stcode(dag::Span cod, Tab &cvar, StcodeRegisters &static_regs) +void ShaderSemCode::convert_stcode(dag::Span cod, Tab &cvar, StcodeRegisters &static_regs, const Tab &var_map) { for (int i = 0; i < cod.size(); i++) { @@ -220,7 +274,7 @@ void ShaderSemCode::convert_stcode(dag::Span cod, Tab &cvar, StcodeReg case SHCOD_GET_INT_TOREAL: case SHCOD_GET_IVEC_TOREAL: { - int vi = shaderopcode::getOp2p2s(cod[i]); + int vi = var_map[shaderopcode::getOp2p2s(cod[i])]; G_ASSERT(vi >= 0); cod[i] = shaderopcode::patchOp2p2(cod[i], cvar[vi]); // replace var id with var offset static_regs.patch(vi, cvar[vi]); @@ -232,7 +286,8 @@ void ShaderSemCode::convert_stcode(dag::Span cod, Tab &cvar, StcodeReg } } -void ShaderSemCode::convert_passes(ShaderSemCode::Pass &semP, ShaderCode::Pass &p, Tab &cvar, StcodeShader &cppcode) +void ShaderSemCode::convert_passes(ShaderSemCode::Pass &semP, ShaderCode::Pass &p, Tab &cvar, StcodeShader &cppcode, + const Tab &var_map) { if (semP.cs.size()) { @@ -262,7 +317,7 @@ void ShaderSemCode::convert_passes(ShaderSemCode::Pass &semP, ShaderCode::Pass & // convert state code static Tab stblkcode(tmpmem); stblkcode = semP.stblkcode; - convert_stcode(make_span(stblkcode), cvar, staticVarRegs); + convert_stcode(make_span(stblkcode), cvar, staticVarRegs, var_map); auto [blkcodeId, blkcodeIsNew] = add_stcode(stblkcode); p.stblkcodeNo = blkcodeId; @@ -271,7 +326,7 @@ void ShaderSemCode::convert_passes(ShaderSemCode::Pass &semP, ShaderCode::Pass & static Tab stcode(tmpmem); stcode = semP.stcode; - convert_stcode(make_span(stcode), cvar, staticVarRegs); + convert_stcode(make_span(stcode), cvar, staticVarRegs, var_map); auto [stcodeId, stcodeIsNew] = add_stcode(stcode); p.stcodeNo = stcodeId; if (stcodeIsNew) diff --git a/prog/tools/ShaderCompiler2/shSemCode.h b/prog/tools/ShaderCompiler2/shSemCode.h index 89fd65696..3c1bd7967 100644 --- a/prog/tools/ShaderCompiler2/shSemCode.h +++ b/prog/tools/ShaderCompiler2/shSemCode.h @@ -47,7 +47,7 @@ class ShaderSemCode void *terminal; bool used, dynamic, noWarnings; - Var() : nameId(-1), used(false), dynamic(false), noWarnings(false), terminal(NULL) {} + Var() : nameId(-1), terminal(NULL), used(false), dynamic(false), noWarnings(false) {} inline const char *getName() const { return VarMap::getName(nameId); }; }; @@ -227,6 +227,8 @@ class ShaderSemCode eastl::optional pass; Tab suppBlk; + Tab varmap; + PassTab() : suppBlk(codemem) {} }; @@ -251,14 +253,19 @@ class ShaderSemCode ShaderSemCode(); ~ShaderSemCode() = default; - const char *equal(ShaderSemCode &, bool compare_passes); + const char *equal(ShaderSemCode &, bool compare_passes_and_vars); void dump(); + void initPassMap(int pass_id); + void mergeVars(Tab &&other_vars, Tab &&other_stvarmap, int pass_id); + ShaderCode *generateShaderCode(const ShaderVariant::VariantTableSrc &dynVariants, StcodeShader &cppcode); private: - void convert_passes(ShaderSemCode::Pass &semP, ShaderCode::Pass &p, Tab &cvar, StcodeShader &cppcode); - static void convert_stcode(dag::Span cod, Tab &cvar, StcodeRegisters &static_regs); + void convert_passes(ShaderSemCode::Pass &semP, ShaderCode::Pass &p, Tab &cvar, StcodeShader &cppcode, const Tab &var_map); + static void convert_stcode(dag::Span cod, Tab &cvar, StcodeRegisters &static_regs, const Tab &var_map); + + static int find_var_in_tab(const Tab &vars, const int variable_id); }; #undef codemem diff --git a/prog/tools/ShaderCompiler2/shcode.h b/prog/tools/ShaderCompiler2/shcode.h index 1fc1e25ec..8d1a1d5b4 100644 --- a/prog/tools/ShaderCompiler2/shcode.h +++ b/prog/tools/ShaderCompiler2/shcode.h @@ -7,6 +7,7 @@ #include #include #include +#include #include "shaderSave.h" #include "shaderVariant.h" @@ -136,6 +137,7 @@ class ShaderClass }; SerializableTab stvar; SerializableTab shInitCode; + BINDUMP_NON_SERIALIZABLE(eastl::bitvector<> stvarsAreDynamic); bindump::string name; int64_t timestamp = -1; @@ -160,6 +162,10 @@ class ShaderClass clear_and_shrink(code); } + // First all static, then all dynamic to reduce posibility of material and shader layout mismatches + // After this function, stvarsAreDynamic field is invalidated, so it should be done after all var additions + void sortStaticVarsByMode(); + int find_static_var(const int variable_name_id); }; diff --git a/prog/tools/ShaderCompiler2/shsem.cpp b/prog/tools/ShaderCompiler2/shsem.cpp index 060de8f3e..199ebc86d 100644 --- a/prog/tools/ShaderCompiler2/shsem.cpp +++ b/prog/tools/ShaderCompiler2/shsem.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include using namespace ShaderParser; @@ -188,15 +189,29 @@ bool ShaderSemCode::Pass::equal(Pass &p) return true; } -const char *ShaderSemCode::equal(ShaderSemCode &c, bool compare_passes) +const char *ShaderSemCode::equal(ShaderSemCode &c, bool compare_passes_and_vars) { if (channel.size() != c.channel.size()) return "channel count"; if (!mem_eq(channel, c.channel.data())) return "channel data"; + if (regsize != c.regsize) + { + return "regsize"; + } + + if (initcode.size() != c.initcode.size()) + return "initcode count"; + if (!mem_eq(initcode, c.initcode.data())) + return "initcode data"; + + if (!compare_passes_and_vars) + return NULL; + if (vars.size() != c.vars.size()) return "variable count"; + int i; for (i = 0; i < vars.size(); ++i) { @@ -206,24 +221,11 @@ const char *ShaderSemCode::equal(ShaderSemCode &c, bool compare_passes) return "variable name"; } - if (regsize != c.regsize) - { - return "regsize"; - } - - if (initcode.size() != c.initcode.size()) - return "initcode count"; - if (!mem_eq(initcode, c.initcode.data())) - return "initcode data"; - if (stvarmap.size() != c.stvarmap.size()) return "stvarmap count"; if (!mem_eq(stvarmap, c.stvarmap.data())) return "stvarmap data"; - if (!compare_passes) - return NULL; - if (passes.size() != c.passes.size()) return "different number of dynamic variants"; @@ -498,38 +500,6 @@ static void shaderWarn(ShaderSyntaxParser &parser, const char *msg, Terminal *t) parser.get_lex_parser().set_warning(t->file_start, t->line_start, t->col_start, msg); } -struct VarUsageInfo -{ - String name; - bool used; - bool noWarnings; - Terminal *terminal; - - void fromVar(const ShaderSemCode::Var &var) - { - name = var.getName(); - terminal = (Terminal *)var.terminal; - used = var.used; - noWarnings = var.noWarnings; - } -}; - - -// check for variable usage -static void checkVarsUsage(const Tab &info, ShaderSyntaxParser &parser, ShaderVariant::VariantSrc *staticVariant) -{ - for (int i = 0; i < info.size(); ++i) - { - const VarUsageInfo &var = info[i]; - if (!var.used && !var.noWarnings) - { - if (strcmp("instancing_const_begin", var.name) != 0 && strcmp("instancing_const_end", var.name) != 0) - shaderWarn(parser, "variable '" + var.name + "' not used in static variant '" + staticVariant->getVarStringInfo() + "'", - var.terminal); - } - } -} - static bool validate_cs(ShaderClass *sclass, ShaderSemCode *ssc, int staticVariantCount) { bool has_cs = false, has_non_cs = false, has_void = false; @@ -675,7 +645,28 @@ static void add_shader(shader_decl *sh, ShaderSyntaxParser &parser, Terminal *sh get_memory_stats(stats, 2048); debug("%s", stats.str()); - Tab usageInfo(tmpmem); + struct VarUsageInfo + { + bool used; + bool noWarnings; + Terminal *terminal; + + void fromVar(const ShaderSemCode::Var &var) + { + terminal = (Terminal *)var.terminal; + used = var.used; + noWarnings = var.noWarnings; + } + }; + + // const char * is ok cause we use ids from VarMap inside it's lifetime + ska::flat_hash_map usageInfo{}; + auto addVarUsage = [&usageInfo](const ShaderSemCode::Var &var) { + auto [it, wasNew] = usageInfo.insert({var.getName(), VarUsageInfo{}}); + G_ASSERT(wasNew); + it->second.fromVar(var); + }; + Tab shInitCodeLast(tmpmem); if (stVarCB.shaderDebugModeEnabled) @@ -765,27 +756,23 @@ static void add_shader(shader_decl *sh, ShaderSyntaxParser &parser, Terminal *sh // first dynamic variant - store it ssc = eastl::move(parsedSsc); - usageInfo.resize(ssc->vars.size()); - for (int v = 0; v < usageInfo.size(); v++) - usageInfo[v].fromVar(ssc->vars[v]); + for (int v = 0; v < ssc->vars.size(); v++) + addVarUsage(ssc->vars[v]); + + ssc->initPassMap(d); } else { - // correct & check for variable usage - if (parsedSsc->vars.size() != ssc->vars.size()) - { - sh_debug(SHLOG_ERROR, "shader(%s): illegal dynamic variants: different variable count", shname->text); - } - else + // check for variable usage + for (const ShaderSemCode::Var &var : parsedSsc->vars) { - for (int v = 0; v < usageInfo.size(); ++v) + if (auto it = usageInfo.find(var.getName()); it != usageInfo.end()) { - ShaderSemCode::Var &var = parsedSsc->vars[v]; - VarUsageInfo &uv = usageInfo[v]; - - if (!uv.used) - uv.used = var.used; + if (!it->second.used) + it->second.used = var.used; } + else + addVarUsage(var); } // correct register count @@ -794,23 +781,25 @@ static void add_shader(shader_decl *sh, ShaderSyntaxParser &parser, Terminal *sh ssc->regsize = parsedSsc->regsize = (ssc->regsize > parsedSsc->regsize) ? ssc->regsize : parsedSsc->regsize; } - // check for equal static variants - const char *eqDesc = ssc->equal(*parsedSsc, false); - if (eqDesc != NULL) + if (ssc->passes[d]) { - sh_debug(SHLOG_ERROR, "shader(%s): illegal dynamic variants: different %s", shname->text, eqDesc); + sh_debug(SHLOG_ERROR, "shader(%s): dynamic variant already exists", shname->text); sh_set_current_dyn_variant(NULL); continue; } - if (ssc->passes[d]) + ssc->passes[d] = parsedSsc->passes[d]; + ssc->mergeVars(eastl::move(parsedSsc->vars), eastl::move(parsedSsc->stvarmap), d); + + // check for equal static variants + const char *eqDesc = ssc->equal(*parsedSsc, false); + if (eqDesc != NULL) { - sh_debug(SHLOG_ERROR, "shader(%s): dynamic variant already exists", shname->text); + sh_debug(SHLOG_ERROR, "shader(%s): illegal dynamic variants: different %s", shname->text, eqDesc); sh_set_current_dyn_variant(NULL); continue; } - ssc->passes[d] = parsedSsc->passes[d]; parsedSsc->passes[d] = NULL; parsedSsc.reset(); @@ -840,17 +829,28 @@ static void add_shader(shader_decl *sh, ShaderSyntaxParser &parser, Terminal *sh stVarCB.allRefStaticVars); render_stage_idx = (ssc->flags & SC_STAGE_IDX_MASK); + ssc->initPassMap(0); + if (!needRender) staticVariant->codeId = -1; - usageInfo.resize(ssc->vars.size()); - for (int v = 0; v < usageInfo.size(); v++) - usageInfo[v].fromVar(ssc->vars[v]); + for (int v = 0; v < ssc->vars.size(); v++) + addVarUsage(ssc->vars[v]); } if (needRender) { - checkVarsUsage(usageInfo, parser, staticVariant); + // check for variable usage + eastl::for_each(usageInfo.cbegin(), usageInfo.cend(), [&](const auto &pair) { + auto [name, var] = pair; + if (!var.used && !var.noWarnings) + { + if (strcmp("instancing_const_begin", name) != 0 && strcmp("instancing_const_end", name) != 0) + shaderWarn(parser, + "variable '" + String{name} + "' not used in static variant '" + staticVariant->getVarStringInfo() + "'", var.terminal); + } + }); + if ((ssc->flags & SC_STAGE_IDX_MASK) != render_stage_idx) sh_debug(SHLOG_WARNING, "shader(%s): staticvariant uses renderStageIdx=%d, while dynvariants uses %d", sclass->name.c_str(), (ssc->flags & SC_STAGE_IDX_MASK), render_stage_idx); @@ -914,6 +914,8 @@ static void add_shader(shader_decl *sh, ShaderSyntaxParser &parser, Terminal *sh if (has_first_static_variant) sclass->shInitCode = shInitCodeLast; + sclass->sortStaticVarsByMode(); + staticVariants.fillVariantTable(sclass->staticVariants); sh_set_current_variant(NULL); diff --git a/prog/tools/dargbox/gamebase/samples_prog/_basic/components/scrollbar.nut b/prog/tools/dargbox/gamebase/samples_prog/_basic/components/scrollbar.nut index 860560f28..e4f1b9a09 100644 --- a/prog/tools/dargbox/gamebase/samples_prog/_basic/components/scrollbar.nut +++ b/prog/tools/dargbox/gamebase/samples_prog/_basic/components/scrollbar.nut @@ -5,93 +5,83 @@ let calcKnobColor = @(sf) (sf & S_ACTIVE) ? Color(255,255,255) : Color(110, 120, 140, 160) let barWidth = sh(1) +let minKnobSizePart = 0.005 let barColor = Color(40, 40, 40, 160) -let calcBarSize = @(axis) axis == 0 ? [flex(), barWidth] : [barWidth, flex()] +let calcBarSize = @(isVertical) isVertical ? [barWidth, flex()] : [flex(), barWidth] -let mkScrollbar = function(scroll_handler, orientation=null, needReservePlace=true) { +function mkScrollbar(scroll_handler, orientation=null, needReservePlace=true) { let stateFlags = Watched(0) - let axis = orientation == O_VERTICAL ? 1 : 0 - - return function() { - let elem = scroll_handler.elem - - if (!elem) { - return { - key = scroll_handler - behavior = Behaviors.Slider - watch = scroll_handler - size = needReservePlace ? calcBarSize(axis) : null - } - } - - local contentSize, elemSize, scrollPos - if (axis == 0) { - contentSize = elem.getContentWidth() - elemSize = elem.getWidth() - scrollPos = elem.getScrollOffsX() - } - else { - contentSize = elem.getContentHeight() - elemSize = elem.getHeight() - scrollPos = elem.getScrollOffsY() - } - - if (contentSize <= elemSize) { - return { - key = scroll_handler - behavior = Behaviors.Slider - watch = scroll_handler - size = needReservePlace ? calcBarSize(axis) : null - } - } - - - let minV = 0 - let maxV = contentSize - elemSize - let fValue = scrollPos - - let knob = { - size = [flex(elemSize), flex(elemSize)] - color = calcKnobColor(stateFlags.get()) - key = "knob" - rendObj = ROBJ_SOLID - } + let isVertical = orientation == O_VERTICAL + let elemSize = isVertical + ? Computed(@() (scroll_handler.elem?.getHeight() ?? 0)) + : Computed(@() (scroll_handler.elem?.getWidth() ?? 0)) + let maxV = isVertical + ? Computed(@() (scroll_handler.elem?.getContentHeight() ?? 0) - elemSize.get()) + : Computed(@() (scroll_handler.elem?.getContentWidth() ?? 0) - elemSize.get()) + let fValue = isVertical + ? Computed(@() scroll_handler.elem?.getScrollOffsY() ?? 0) + : Computed(@() scroll_handler.elem?.getScrollOffsX() ?? 0) + let isElemFit = Computed(@() maxV.get() <= 0) + let knob = @() { + watch = stateFlags + key = "knob" + size = [flex(), flex()] + rendObj = ROBJ_SOLID + color = calcKnobColor(stateFlags.get()) + } + function view() { + let sizeMul = elemSize.get() == 0 || maxV.get() == 0 ? 1 + : elemSize.get() <= minKnobSizePart * maxV.get() ? 1.0 / maxV.get() / minKnobSizePart + : 1.0 / elemSize.get() return { - key = scroll_handler - behavior = Behaviors.Slider - color = barColor - rendObj = ROBJ_SOLID - - watch = [scroll_handler, stateFlags] - fValue - - knob - min = minV - max = maxV - unit = 1 - - flow = axis == 0 ? FLOW_HORIZONTAL : FLOW_VERTICAL + watch = [elemSize, maxV, fValue] + size = flex() + flow = isVertical ? FLOW_VERTICAL : FLOW_HORIZONTAL halign = ALIGN_CENTER valign = ALIGN_CENTER - pageScroll = (axis == 0 ? -1 : 1) * (maxV - minV) / 100.0 // TODO probably needed sync with container wheelStep option - - orientation - size = calcBarSize(axis) - children = [ - {size=[flex(fValue), flex(fValue)]} + { size = array(2, flex(fValue.get() * sizeMul)) } knob - {size=[flex(maxV-fValue), flex(maxV-fValue)]} + { size = array(2, flex((maxV.get() - fValue.get()) * sizeMul)) } ] + } + } - onChange = @(val) axis == 0 - ? scroll_handler.scrollToX(val) - : scroll_handler.scrollToY(val) + return { + isElemFit + function scrollComp() { + if (isElemFit.get()) + return { + watch = isElemFit + key = scroll_handler + behavior = Behaviors.Slider + size = needReservePlace ? calcBarSize(isVertical) : null + } + return { + watch = [isElemFit, maxV, elemSize] + key = scroll_handler + size = calcBarSize(isVertical) - onElemState = @(sf) stateFlags.set(sf) + behavior = Behaviors.Slider + orientation + fValue = fValue.get() + knob + min = 0 + max = maxV.get() + unit = 1 + pageScroll = (isVertical ? 1 : -1) * maxV.get() / 100.0 // TODO probably needed sync with container wheelStep option + onChange = @(val) isVertical ? scroll_handler.scrollToY(val) + : scroll_handler.scrollToX(val) + onElemState = @(sf) stateFlags.set(sf) + + rendObj = ROBJ_SOLID + color = barColor + + children = view + } } } } @@ -100,25 +90,25 @@ let makeSideScroll = kwarg(function(content, scrollAlign = ALIGN_RIGHT, orientat size = flex(), maxWidth = null, maxHeight = null, needReservePlace = true, scrollHandler=null, behaviors = null) { scrollHandler = scrollHandler ?? ScrollHandler() - function contentRoot() { - return { - size = flex() - behavior = [].extend(behaviors ?? []).append(Behaviors.WheelScroll, Behaviors.ScrollEvent) - scrollHandler - wheelStep = 0.8 - orientation - joystickScroll = true - maxHeight - maxWidth - children = content - } + let contentRoot = { + size = flex() + behavior = [].extend(behaviors ?? []).append(Behaviors.WheelScroll, Behaviors.ScrollEvent) + scrollHandler + wheelStep = 0.8 + orientation + joystickScroll = true + maxHeight + maxWidth + children = content } + let { isElemFit, scrollComp } = mkScrollbar(scrollHandler, orientation, needReservePlace) let children = scrollAlign == ALIGN_LEFT || scrollAlign == ALIGN_TOP - ? [mkScrollbar(scrollHandler, orientation, needReservePlace), contentRoot] - : [contentRoot, mkScrollbar(scrollHandler, orientation, needReservePlace)] + ? [scrollComp, contentRoot] + : [contentRoot, scrollComp] - return { + return @() { + watch = isElemFit size maxHeight maxWidth @@ -152,10 +142,10 @@ let makeHVScrolls = function(content, options = null ) { clipChildren = true children = [ contentRoot - mkScrollbar(scrollHandler, O_VERTICAL, needReservePlace) + mkScrollbar(scrollHandler, O_VERTICAL, needReservePlace).scrollComp ] } - mkScrollbar(scrollHandler, O_HORIZONTAL, needReservePlace) + mkScrollbar(scrollHandler, O_HORIZONTAL, needReservePlace).scrollComp ] } } @@ -174,7 +164,6 @@ let makeHorizScroll = function(content, options=null) { return { - mkScrollbar makeHorizScroll makeVertScroll makeHVScrolls diff --git a/prog/tools/libTools/EditorCore/ec_ViewportWindow.cpp b/prog/tools/libTools/EditorCore/ec_ViewportWindow.cpp index 465455b10..1a763202f 100644 --- a/prog/tools/libTools/EditorCore/ec_ViewportWindow.cpp +++ b/prog/tools/libTools/EditorCore/ec_ViewportWindow.cpp @@ -623,7 +623,7 @@ int ViewportWindow::windowProc(TEcHandle h_wnd, unsigned msg, TEcWParam w_param, input.mouseX = GET_X_LPARAM(l_param); input.mouseY = GET_Y_LPARAM(l_param); - if (mouseDownOnViewportAxis == ViewportAxisId::RotatorCircle && canInteractWithViewportAxis()) + if (mouseDownOnViewportAxis == ViewportAxisId::RotatorCircle) { processViewportAxisCameraRotation(l_param); return 0; @@ -681,7 +681,7 @@ int ViewportWindow::windowProc(TEcHandle h_wnd, unsigned msg, TEcWParam w_param, mouseButtonDown[ImGuiMouseButton_Left] = true; input.lmbPressed = true; - if (highlightedViewportAxisId != ViewportAxisId::None && canInteractWithViewportAxis()) + if (highlightedViewportAxisId != ViewportAxisId::None && canStartInteractionWithViewport()) { handleViewportAxisMouseLButtonDown(); return 0; @@ -1979,7 +1979,7 @@ void ViewportWindow::paint(int w, int h) getViewportSize(viewportSize.x, viewportSize.y); const bool rotating = mouseDownOnViewportAxis == ViewportAxisId::RotatorCircle; - const bool allowHighlight = !rotating && canInteractWithViewportAxis(); + const bool allowHighlight = (mouseDownOnViewportAxis != ViewportAxisId::None && !rotating) || canStartInteractionWithViewport(); const IPoint2 mousePos(input.mouseX, input.mouseY); ViewportAxis viewportAxis(viewport->getViewMatrix(), viewportSize); highlightedViewportAxisId = viewportAxis.draw(allowHighlight ? &mousePos : nullptr, rotating); @@ -2405,9 +2405,10 @@ void ViewportWindow::handleStatSettingsDialogChange(int pcb_id, bool value) handleStat3dStatSettingsDialogChange(pcb_id, value); } -bool ViewportWindow::canInteractWithViewportAxis() +bool ViewportWindow::canStartInteractionWithViewport() { - return isActive() && !rectSelect.active && !isMoveRotateAllowed && CCameraElem::getCamera() == CCameraElem::MAX_CAMERA; + return isActive() && !rectSelect.active && !isMoveRotateAllowed && mouseDownOnViewportAxis == ViewportAxisId::None && + CCameraElem::getCamera() == CCameraElem::MAX_CAMERA; } void ViewportWindow::handleViewportAxisMouseLButtonDown() @@ -2446,7 +2447,7 @@ void ViewportWindow::handleViewportAxisMouseLButtonUp() SetCursorPos(restoreCursorAtX, restoreCursorAtY); } - else if (highlightedViewportAxisId == mouseDownOnViewportAxis && canInteractWithViewportAxis()) + else if (highlightedViewportAxisId == mouseDownOnViewportAxis) { switch (highlightedViewportAxisId) //-V719 (The switch statement does not cover all values of the enum.) { diff --git a/prog/tools/libTools/ObjectEditor/ec_ObjectEditorBar.cpp b/prog/tools/libTools/ObjectEditor/ec_ObjectEditorBar.cpp index c5ffe74ac..fbd72e827 100644 --- a/prog/tools/libTools/ObjectEditor/ec_ObjectEditorBar.cpp +++ b/prog/tools/libTools/ObjectEditor/ec_ObjectEditorBar.cpp @@ -10,13 +10,6 @@ #include #include -static class DefObjectEditorPropParams -{ -public: - bool commonGroupMinimized; - DefObjectEditorPropParams() : commonGroupMinimized(false) {} -} defaultObjectEditorPropParams; - enum { ID_NAME = 10000, @@ -63,11 +56,7 @@ void ObjectEditorPropPanelBar::getObjects() void ObjectEditorPropPanelBar::onChange(int pcb_id, PropPanel::ContainerPropertyControl *panel) { - if (pcb_id == RenderableEditableObject::PID_COMMON_GROUP) - { - ::defaultObjectEditorPropParams.commonGroupMinimized = panel->getBool(pcb_id); - } - else if (pcb_id == ID_NAME) + if (pcb_id == ID_NAME) { objEd->renameObject(objEd->getSelected(0), panel->getText(pcb_id).str()); } @@ -118,7 +107,7 @@ void ObjectEditorPropPanelBar::fillPanel() PropPanel::ContainerPropertyControl *commonGrp = propPanel->createGroup(RenderableEditableObject::PID_COMMON_GROUP, "Common parameters"); - commonGrp->setBoolValue(::defaultObjectEditorPropParams.commonGroupMinimized); + commonGrp->setBoolValue(false); commonGrp->createEditBox(ID_NAME, "Name:", "", false); @@ -150,6 +139,20 @@ void ObjectEditorPropPanelBar::fillPanel() } +void ObjectEditorPropPanelBar::loadSettings(DataBlock &settings) +{ + if (propPanel) + propPanel->loadState(settings); +} + + +void ObjectEditorPropPanelBar::saveSettings(DataBlock &settings) const +{ + if (propPanel) + propPanel->saveState(settings); +} + + void ObjectEditorPropPanelBar::updateName(const char *name) { G_ASSERT(propPanel && "ObjectEditorPropPanelBar::fillPanel: ppanel is NULL!"); diff --git a/prog/tools/libTools/ObjectEditor/ec_objectEditor.cpp b/prog/tools/libTools/ObjectEditor/ec_objectEditor.cpp index 55506a2ba..e10b9c0b9 100644 --- a/prog/tools/libTools/ObjectEditor/ec_objectEditor.cpp +++ b/prog/tools/libTools/ObjectEditor/ec_objectEditor.cpp @@ -834,6 +834,7 @@ void ObjectEditor::setEditMode(int mode) void ObjectEditor::invalidateObjectProps() { + saveEditorPropBarSettings(); areObjectPropsValid = false; IEditorCoreEngine::get()->updateViewports(); IEditorCoreEngine::get()->invalidateViewportCache(); @@ -845,6 +846,7 @@ void ObjectEditor::updateObjectProps() if (!areObjectPropsValid && objectPropBar) { objectPropBar->fillPanel(); + objectPropBar->loadSettings(objectPropSettings); areObjectPropsValid = true; } } @@ -1436,6 +1438,16 @@ ObjectEditorPropPanelBar *ObjectEditor::createEditorPropBar(void *handle) } +void ObjectEditor::saveEditorPropBarSettings() +{ + if (objectPropBar) + { + objectPropSettings.reset(); + objectPropBar->saveSettings(objectPropSettings); + } +} + + void *ObjectEditor::onWmCreateWindow(int type) { switch (type) @@ -1447,6 +1459,7 @@ void *ObjectEditor::onWmCreateWindow(int type) objectPropBar = createEditorPropBar(nullptr); objectPropBar->fillPanel(); + objectPropBar->loadSettings(objectPropSettings); areObjectPropsValid = true; setButton(CM_OBJED_OBJPROP_PANEL, true); @@ -1463,6 +1476,7 @@ bool ObjectEditor::onWmDestroyWindow(void *window) { if (window == objectPropBar) { + saveEditorPropBarSettings(); del_it(objectPropBar); setButton(CM_OBJED_OBJPROP_PANEL, false); return true; @@ -1508,7 +1522,10 @@ void ObjectEditor::closeUi() G_ASSERT(manager); if (objectPropBar) + { + saveEditorPropBarSettings(); EDITORCORE->removePropPanel(objectPropBar); + } manager->unregisterWindowHandler(this); @@ -1560,6 +1577,21 @@ void ObjectEditor::showPanel() } +void ObjectEditor::loadPropPanelSettings(const DataBlock &settings) +{ + objectPropSettings.setFrom(&settings); + if (objectPropBar) + objectPropBar->loadSettings(objectPropSettings); +} + + +void ObjectEditor::savePropPanelSettings(DataBlock &settings) +{ + saveEditorPropBarSettings(); + settings.setFrom(&objectPropSettings); +} + + void ObjectEditor::setCreateMode(IObjectCreator *creator_) { del_it(creator); diff --git a/prog/tools/libTools/propPanel/control/fileEditBox.h b/prog/tools/libTools/propPanel/control/fileEditBox.h index f699c9416..e6234292a 100644 --- a/prog/tools/libTools/propPanel/control/fileEditBox.h +++ b/prog/tools/libTools/propPanel/control/fileEditBox.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "../scopedImguiBeginDisabled.h" #include #include @@ -14,7 +15,7 @@ namespace PropPanel { -class FileEditBoxPropertyControl : public PropertyControlBase +class FileEditBoxPropertyControl : public PropertyControlBase, public IDelayedCallbackHandler { public: FileEditBoxPropertyControl(ControlEventHandler *event_handler, ContainerPropertyControl *parent, int id, int x, int y, hdpi::Px w, @@ -131,8 +132,7 @@ class FileEditBoxPropertyControl : public PropertyControlBase { if (dialogMode == FS_DIALOG_NONE) { - PropertyControlBase::onWcClick(source); - onWcChange(nullptr); + request_delayed_callback(*this); return; } @@ -185,6 +185,12 @@ class FileEditBoxPropertyControl : public PropertyControlBase } } + virtual void onImguiDelayedCallback(void *user_data) override + { + PropertyControlBase::onWcClick(nullptr); + onWcChange(nullptr); + } + String controlCaption; String controlValue; bool controlEnabled = true; diff --git a/prog/tools/sceneTools/assetExp/daBuild.cpp b/prog/tools/sceneTools/assetExp/daBuild.cpp index 3989ba1c9..ae4fb4b21 100644 --- a/prog/tools/sceneTools/assetExp/daBuild.cpp +++ b/prog/tools/sceneTools/assetExp/daBuild.cpp @@ -143,7 +143,7 @@ static void makePack(DagorAssetMgr &mgr, dag::ConstSpan assets, da if (pkgBlk.paramCount() + pkgBlk.blockCount() > 0) { bool def = pkgBlk.getBool("defaultOn", true); - bool main = pkgBlk.getBool("::main", true); + bool main = pkgBlk.getBool("::main", profile ? pkgBlk.getBool(String(0, "::main.%s", profile), true) : true); for (int i = tex_pack.size() - 1; i >= tex_pack_init_cnt; i--) { @@ -709,7 +709,7 @@ bool exportAssets(DagorAssetMgr &mgr, const char *app_dir, unsigned targetCode, target_str, profile); if (pkid < 0) { - if (!pkgBlk.getBool("::main", true)) + if (!pkgBlk.getBool("::main", profile ? pkgBlk.getBool(String(0, "::main.%s", profile), true) : true)) { log.addMessage(IMPORTANT_NOTE, " Skip exporting main assets"); pack_list_fname = NULL; diff --git a/prog/tools/sceneTools/assetExp/exporters/exp_dynModel.cpp b/prog/tools/sceneTools/assetExp/exporters/exp_dynModel.cpp index c9126f039..f485e5a8e 100644 --- a/prog/tools/sceneTools/assetExp/exporters/exp_dynModel.cpp +++ b/prog/tools/sceneTools/assetExp/exporters/exp_dynModel.cpp @@ -161,7 +161,11 @@ class DynModelExporter : public IDagorAssetExporter if (const DataBlock *lodsToKeepBlk = dm_blk->getBlockByName("lodsToKeep")) { - int lodsToKeep = lodsToKeepBlk->getInt(cwr.getProfile() ? String(0, "profile.%s", cwr.getProfile()).c_str() : "profile.*", 16); + const char *pkname = a.getCustomPackageName(mkbindump::get_target_str(cwr.getTarget()), cwr.getProfile()); + int lodsToKeep = lodsToKeepBlk->getInt(pkname ? String(0, "package.%s", pkname).c_str() : "package.*", -1); + lodsToKeep = lodsToKeep >= 0 + ? lodsToKeep + : lodsToKeepBlk->getInt(cwr.getProfile() ? String(0, "profile.%s", cwr.getProfile()).c_str() : "profile.*", 16); for (int i = lodsBlk.blockCount() - 1; i >= 0; i--) if (lodsBlk.getBlock(i)->getBlockNameId() == nid) { diff --git a/prog/tools/sceneTools/assetExp/exporters/exp_rendInst.cpp b/prog/tools/sceneTools/assetExp/exporters/exp_rendInst.cpp index a2caa3c1f..75621c806 100644 --- a/prog/tools/sceneTools/assetExp/exporters/exp_rendInst.cpp +++ b/prog/tools/sceneTools/assetExp/exporters/exp_rendInst.cpp @@ -187,7 +187,11 @@ class RendInstExporter : public IDagorAssetExporter if (const DataBlock *lodsToKeepBlk = ri_blk->getBlockByName("lodsToKeep")) { - int lodsToKeep = lodsToKeepBlk->getInt(cwr.getProfile() ? String(0, "profile.%s", cwr.getProfile()).c_str() : "profile.*", 16); + const char *pkname = a.getCustomPackageName(mkbindump::get_target_str(cwr.getTarget()), cwr.getProfile()); + int lodsToKeep = lodsToKeepBlk->getInt(pkname ? String(0, "package.%s", pkname).c_str() : "package.*", -1); + lodsToKeep = lodsToKeep >= 0 + ? lodsToKeep + : lodsToKeepBlk->getInt(cwr.getProfile() ? String(0, "profile.%s", cwr.getProfile()).c_str() : "profile.*", 16); for (int i = lodsBlk.blockCount() - 1; i >= 0; i--) if (lodsBlk.getBlock(i)->getBlockNameId() == lodNameId) { diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlEntity.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlEntity.cpp index ed46599a2..f6a4d0ba5 100644 --- a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlEntity.cpp +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlEntity.cpp @@ -108,12 +108,8 @@ static class DefHMLEntityParams public: int placeTypeTab; bool placeTypeMixed; - bool seedGroupMinimized; bool splitCompRecursive; - - DefHMLEntityParams() : - placeTypeTab(PID_PLACE_TYPE_BTN_DROPDOWN), placeTypeMixed(false), seedGroupMinimized(true), splitCompRecursive(false) - {} + DefHMLEntityParams() : placeTypeTab(PID_PLACE_TYPE_BTN_DROPDOWN), placeTypeMixed(false), splitCompRecursive(false) {} } defaultHMLEntity; @@ -423,7 +419,7 @@ void LandscapeEntityObject::fillProps(PropPanel::ContainerPropertyControl &panel panel.createIndent(); PropPanel::ContainerPropertyControl *subGrp = panel.createGroup(PID_SEED_GROUP, "Seed"); - subGrp->setBoolValue(::defaultHMLEntity.seedGroupMinimized); + subGrp->setBoolValue(false); subGrp->createStatic(0, "Generate per-inst seed:"); subGrp->createButton(PID_GENERATE_PERINST_SEED, "Individual"); @@ -799,8 +795,6 @@ void LandscapeEntityObject::onPPChange(int pid, bool edit_finished, PropPanel::C rePlaceAllEntities(); } } - else if (pid == PID_SEED_GROUP) - ::defaultHMLEntity.seedGroupMinimized = panel.getBool(pid); else if (pid == PID_SEED && objects.size() == 1) { if (LandscapeEntityObject *p = RTTI_cast(objects[0])) diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlIGenEditorPlugin.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlIGenEditorPlugin.cpp index e0ca3aedb..d2a2a1194 100644 --- a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlIGenEditorPlugin.cpp +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlIGenEditorPlugin.cpp @@ -292,10 +292,15 @@ void HmapLandPlugin::unregistered() void HmapLandPlugin::loadSettings(const DataBlock &global_settings) { + objEd.loadPropPanelSettings(*global_settings.getBlockByNameEx("obj_prop")); objEd.loadOutlinerSettings(*global_settings.getBlockByNameEx("outliner")); } -void HmapLandPlugin::saveSettings(DataBlock &global_settings) { objEd.saveOutlinerSettings(*global_settings.addNewBlock("outliner")); } +void HmapLandPlugin::saveSettings(DataBlock &global_settings) +{ + objEd.savePropPanelSettings(*global_settings.addNewBlock("obj_prop")); + objEd.saveOutlinerSettings(*global_settings.addNewBlock("outliner")); +} bool HmapLandPlugin::onConsoleCommand(const char *cmd, dag::ConstSpan params) { diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSelTexDlg.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSelTexDlg.cpp index 942209595..e5220934a 100644 --- a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSelTexDlg.cpp +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSelTexDlg.cpp @@ -70,9 +70,9 @@ bool HmapLandPlugin::HmlSelTexDlg::execute() _panel->createButton(PID_CREATE_MASK, "Create mask..."); _panel->setFocusById(PID_TEX_LIST); _panel->getById(PID_TEX_LIST)->setHeight(_pxScaled(300)); - _panel->createSeparator(); _panel->setInt(PID_BPP_GROUP, reqBpp); + dlg->autoSize(); int ret = dlg->showDialog(); EDITORCORE->deleteDialog(dlg); return ret == PropPanel::DIALOG_ID_OK; diff --git a/prog/tools/sceneTools/daEditorX/de_appwnd.h b/prog/tools/sceneTools/daEditorX/de_appwnd.h index 5aec65535..2d390c626 100644 --- a/prog/tools/sceneTools/daEditorX/de_appwnd.h +++ b/prog/tools/sceneTools/daEditorX/de_appwnd.h @@ -277,6 +277,7 @@ class DagorEdAppWindow : public GenericEditorAppWindow, virtual ModeType getGizmoModeType(); virtual BasisType getGizmoBasisType(); virtual CenterType getGizmoCenterType(); + virtual bool isGizmoOperationStarted() const override; // brush routines virtual void beginBrushPaint(); diff --git a/prog/tools/sceneTools/daEditorX/de_engine.cpp b/prog/tools/sceneTools/daEditorX/de_engine.cpp index 454d9d9ab..0cc1c85a5 100644 --- a/prog/tools/sceneTools/daEditorX/de_engine.cpp +++ b/prog/tools/sceneTools/daEditorX/de_engine.cpp @@ -1256,6 +1256,9 @@ IDagorEd2Engine::ModeType DagorEdAppWindow::getGizmoModeType() { return gizmoEH- IDagorEd2Engine::CenterType DagorEdAppWindow::getGizmoCenterType() { return ged.tbManager->getCenterType(); } +bool DagorEdAppWindow::isGizmoOperationStarted() const { return gizmoEH->isStarted(); } + + void DagorEdAppWindow::setViewportZnearZfar(real zn, real zf) { ged.setZnearZfar(zn, zf); } diff --git a/prog/tools/sceneTools/daEditorX/de_viewportWindow.cpp b/prog/tools/sceneTools/daEditorX/de_viewportWindow.cpp index 6f23616c5..31eda61b8 100644 --- a/prog/tools/sceneTools/daEditorX/de_viewportWindow.cpp +++ b/prog/tools/sceneTools/daEditorX/de_viewportWindow.cpp @@ -2,6 +2,7 @@ #include "de_viewportWindow.h" #include "de_screenshotMetaInfoLoader.h" +#include #include #include #include @@ -26,3 +27,21 @@ bool DagorEdViewportWindow::onDropFiles(const dag::Vector &files) return true; } + +bool DagorEdViewportWindow::canStartInteractionWithViewport() +{ + if (!ViewportWindow::canStartInteractionWithViewport()) + return false; + + if (DAGORED2->isGizmoOperationStarted()) + return false; + + if (DAGORED2->isBrushPainting()) // This just tells if the brush is active. + { + const Brush *brush = DAGORED2->getBrush(); + if (brush && brush->isDrawingInProgress()) + return false; + } + + return true; +} diff --git a/prog/tools/sceneTools/daEditorX/de_viewportWindow.h b/prog/tools/sceneTools/daEditorX/de_viewportWindow.h index 11c712f27..ee4ca89fd 100644 --- a/prog/tools/sceneTools/daEditorX/de_viewportWindow.h +++ b/prog/tools/sceneTools/daEditorX/de_viewportWindow.h @@ -10,4 +10,5 @@ class DagorEdViewportWindow : public ViewportWindow private: virtual bool onDropFiles(const dag::Vector &files) override; + virtual bool canStartInteractionWithViewport() override; }; diff --git a/prog/tools/sceneTools/daEditorX/services/riMgr/riMgrServiceAces.cpp b/prog/tools/sceneTools/daEditorX/services/riMgr/riMgrServiceAces.cpp index 659c21fee..377621c9e 100644 --- a/prog/tools/sceneTools/daEditorX/services/riMgr/riMgrServiceAces.cpp +++ b/prog/tools/sceneTools/daEditorX/services/riMgr/riMgrServiceAces.cpp @@ -465,7 +465,7 @@ class RendinstGatherCollJob : public cpujobs::IJob RendinstVertexDataCbEditor cb(vertices, indices, transparent, navmeshLayers.pools, navmeshLayers.obstaclePools, navmeshLayers.materialPools, navmeshLayers.obstaclesSettings, obstacles); - rendinst::testObjToRIGenIntersection(box, TMatrix::IDENT, cb, rendinst::GatherRiTypeFlag::RiGenAndExtra); + rendinst::testObjToRIGenIntersection(box, cb, rendinst::GatherRiTypeFlag::RiGenAndExtra); transparent.reserve(cb.transparent.size()); vertices.reserve(cb.vertNum); indices.reserve(cb.indNum); @@ -1726,7 +1726,7 @@ class AcesRendInstEntityManagementService : public IEditorService, { RendinstVertexDataCbEditor cb(vertices, indices, transparent, navmeshLayers.pools, navmeshLayers.obstaclePools, navmeshLayers.materialPools, navmeshLayers.obstaclesSettings, obstacles); - rendinst::testObjToRIGenIntersection(box, TMatrix::IDENT, cb, rendinst::GatherRiTypeFlag::RiGenAndExtra); + rendinst::testObjToRIGenIntersection(box, cb, rendinst::GatherRiTypeFlag::RiGenAndExtra); cb.procFilteredCollision([&exclude_boxes](const rendinst::CollisionInfo &ci) { if (ci.collRes == nullptr) return false; diff --git a/prog/tools/sharedInclude/EditorCore/ec_ObjectEditor.h b/prog/tools/sharedInclude/EditorCore/ec_ObjectEditor.h index 22f4019e6..d6ed88e3d 100644 --- a/prog/tools/sharedInclude/EditorCore/ec_ObjectEditor.h +++ b/prog/tools/sharedInclude/EditorCore/ec_ObjectEditor.h @@ -128,6 +128,9 @@ class ObjectEditor : public IGizmoClient, bool isPanelShown() const { return objectPropBar != nullptr; } + void loadPropPanelSettings(const DataBlock &settings); + void savePropPanelSettings(DataBlock &settings); + /// Get Edit Mode. virtual int getEditMode() { return editMode; } @@ -401,6 +404,7 @@ class ObjectEditor : public IGizmoClient, IObjectCreator *creator; ObjectEditorPropPanelBar *objectPropBar; + DataBlock objectPropSettings; virtual void onAddObject(RenderableEditableObject &obj); virtual void _addObjects(RenderableEditableObject **obj, int num, bool use_undo); @@ -411,6 +415,8 @@ class ObjectEditor : public IGizmoClient, virtual ObjectEditorPropPanelBar *createEditorPropBar(void *handle); + virtual void saveEditorPropBarSettings(); + // IWndManagerWindowHandler virtual void *onWmCreateWindow(int type) override; virtual bool onWmDestroyWindow(void *window) override; @@ -520,6 +526,10 @@ class ObjectEditorPropPanelBar : public PropPanel::ControlEventHandler virtual void refillPanel(); virtual void updateName(const char *name); + // loadSettings must be called after fillPanel. + virtual void loadSettings(DataBlock &settings); + virtual void saveSettings(DataBlock &settings) const; + PropPanel::PanelWindowPropertyControl *getPanel() { G_ASSERT(propPanel); diff --git a/prog/tools/sharedInclude/EditorCore/ec_ViewportWindow.h b/prog/tools/sharedInclude/EditorCore/ec_ViewportWindow.h index 961b694f5..91bc193fd 100644 --- a/prog/tools/sharedInclude/EditorCore/ec_ViewportWindow.h +++ b/prog/tools/sharedInclude/EditorCore/ec_ViewportWindow.h @@ -444,7 +444,8 @@ class ViewportWindow : public IGenViewportWnd, public IMenuEventHandler, public void fillStat3dStatSettings(ViewportWindowStatSettingsDialog &dialog); void handleStat3dStatSettingsDialogChange(int pcb_id, bool value); - bool canInteractWithViewportAxis(); + virtual bool canStartInteractionWithViewport(); + void handleViewportAxisMouseLButtonDown(); void handleViewportAxisMouseLButtonUp(); void processViewportAxisCameraRotation(TEcLParam l_param); diff --git a/prog/tools/sharedInclude/EditorCore/ec_brush.h b/prog/tools/sharedInclude/EditorCore/ec_brush.h index dc4cab694..bc8b0b19f 100644 --- a/prog/tools/sharedInclude/EditorCore/ec_brush.h +++ b/prog/tools/sharedInclude/EditorCore/ec_brush.h @@ -188,6 +188,9 @@ class Brush /// @return @b true if brush is in repeat mode inline bool isRepeat() const { return autorepeat; } + /// Tests whether the brush is currently drawing (either with the left or the right mouse button). + /// @return @b true if drawing + bool isDrawingInProgress() const { return drawing || rightDrawing; } /// Set brush radius. /// @param[in] r - brush radius diff --git a/prog/tools/sharedInclude/EditorCore/ec_interface.h b/prog/tools/sharedInclude/EditorCore/ec_interface.h index dc0e91340..843047dcf 100644 --- a/prog/tools/sharedInclude/EditorCore/ec_interface.h +++ b/prog/tools/sharedInclude/EditorCore/ec_interface.h @@ -736,6 +736,11 @@ class IEditorCoreEngine /// Get Gizmo center type. ///@return Gizmo center type (see #CenterType) virtual CenterType getGizmoCenterType() = 0; + + /// Tests whether a gizmo operation is in progress. + /// (For example pressing the left mouse button on the translation gizmo and moving an object.) + ///@return @b true if operation is in progress + virtual bool isGizmoOperationStarted() const = 0; //@} diff --git a/prog/tools/sharedInclude/fx/toolsHeatHazeGlue.h b/prog/tools/sharedInclude/fx/toolsHeatHazeGlue.h index 647514412..2149c7e61 100644 --- a/prog/tools/sharedInclude/fx/toolsHeatHazeGlue.h +++ b/prog/tools/sharedInclude/fx/toolsHeatHazeGlue.h @@ -49,16 +49,8 @@ struct ToolsHeatHazeRendererGlue targetHazeOffset = dag::create_tex(nullptr, offsetTextureWidth, offsetTextureHeight, TEXFMT_A16B16G16R16F | TEXCF_RTARGET, 1, "haze_offset_tex"); - uint32_t flags = 0; - for (auto format : {TEXFMT_DEPTH24, TEXFMT_DEPTH16}) - if (d3d::check_texformat(format | TEXCF_RTARGET)) - { - flags = format | TEXCF_RTARGET; - break; - } - G_ASSERT(flags); - - targetHazeDepth = dag::create_tex(nullptr, offsetTextureWidth, offsetTextureHeight, flags, 1, "haze_depth_tex"); + targetHazeDepth = + dag::create_tex(nullptr, offsetTextureWidth, offsetTextureHeight, TEXFMT_R16F | TEXCF_RTARGET, 1, "haze_depth_tex"); targetHazeColor = dag::create_tex(nullptr, offsetTextureWidth, offsetTextureHeight, TEXFMT_DEFAULT | TEXCF_RTARGET, 1, "haze_color_tex"); diff --git a/samples/testGI/prog/shaders/source/ambient.dshl b/samples/testGI/prog/shaders/source/ambient.dshl index 840dd1d98..1ebcd334b 100644 --- a/samples/testGI/prog/shaders/source/ambient.dshl +++ b/samples/testGI/prog/shaders/source/ambient.dshl @@ -41,8 +41,10 @@ shader render_ambient screen_size@f4 = (1./screen_pos_to_texcoord.x, 1./screen_pos_to_texcoord.y,0,0); world_view_pos@f3 = world_view_pos; } - INIT_PRE_EXPOSURE(ps) - USE_PRE_EXPOSURE(ps) + INIT_HDR(ps) + USE_HDR(ps) + INIT_PREV_PRE_EXPOSURE(ps) + USE_PREV_PRE_EXPOSURE(ps) USE_POSTFX_VERTEX_POSITIONS() USE_AND_INIT_VIEW_VEC_VS() INIT_ZNZFAR() @@ -65,6 +67,11 @@ shader render_ambient //SAMPLE_IRRADIANCE_GRID(ps) //SAMPLE_RADIANCE_GRID(ps) + if (gi_quality != screen_probes) + { + DAGI_NO_SCREEN_ENCODING(ps) + } + if (gi_quality != off) { if (gi_quality == only_ao) @@ -243,15 +250,11 @@ shader render_ambient ##if (gi_quality == screen_probes) uint age; - half3 roughSpecular = specular; - reproject_ambient(lerp(0.05, 0.25, get_roughness_fade(linearRoughness)), 0.05, input.texcoord.xy, rawDepth, w, ambient, roughSpecular, age); - specular = lerp(roughSpecular, specular, saturate(smoothness*2 - 1)*0.9); - encode_gi_colors(output.ambient, output.specular, ambient, specular); + reproject_ambient(lerp(0.25, 0.1, linearRoughness), 0.1, input.texcoord.xy, rawDepth, w, ambient, specular, age); output.age = age; - ##else - output.ambient = ambient; - output.specular = specular; ##endif + + encode_gi_colors(output.ambient, output.specular, ambient, specular); return output; } } diff --git a/samples/testGI/prog/shaders/source/deferred_shadow.dshl b/samples/testGI/prog/shaders/source/deferred_shadow.dshl index 0b6cefc87..9768f942c 100644 --- a/samples/testGI/prog/shaders/source/deferred_shadow.dshl +++ b/samples/testGI/prog/shaders/source/deferred_shadow.dshl @@ -151,27 +151,25 @@ shader deferred_shadow_to_buffer } } - (ps) { - //todo: add later support for SW rgbe - /* - if (dagi_sp_has_exposure_assume == always_rgbe || gi_quality != screen_probes) - { + if (gi_quality != screen_probes || dagi_sp_has_exposure_assume == always_rgbe) + { + (ps) { screen_ambient@tex = screen_ambient hlsl { Texture2D screen_ambient@tex; }; screen_specular@tex = screen_specular hlsl { Texture2D screen_specular@tex; }; + } + if (gi_quality == screen_probes) + { + DAGI_HW_RGBE_SCREEN_ENCODING(ps) } else { + DAGI_NO_SCREEN_ENCODING(ps) + } + } else { + DAGI_SW_RGBE_SCREEN_ENCODING(ps) + (ps) { screen_ambient@tex = screen_ambient hlsl { Texture2D screen_ambient@tex; }; screen_specular@tex = screen_specular hlsl { Texture2D screen_specular@tex; }; - }*/ - screen_ambient@tex = screen_ambient hlsl { Texture2D screen_ambient@tex; }; - screen_specular@tex = screen_specular hlsl { Texture2D screen_specular@tex; }; - } - if (gi_quality == screen_probes) - { - DAGI_SCREEN_ENCODING(ps) - } else - { - DAGI_NO_SCREEN_ENCODING(ps) + } } if (oculus == oculus_on) diff --git a/samples/testGI/prog/shaders/source/reproject_gi.dshl b/samples/testGI/prog/shaders/source/reproject_gi.dshl index eb34e8be9..55bea77bd 100644 --- a/samples/testGI/prog/shaders/source/reproject_gi.dshl +++ b/samples/testGI/prog/shaders/source/reproject_gi.dshl @@ -9,24 +9,24 @@ texture prev_ambient_age; float4x4 ambient_reproject_tm; macro REPROJECT_GI(code) - DAGI_SCREEN_ENCODING(code) local float4 prev_gbuffer_depth_dim = get_dimensions(prev_gbuffer_depth, 0); - (ps) { - ambient_has_history@i1 = ambient_has_history; - - //todo: add later support for SW rgbe - /* - if (dagi_sp_has_exposure_assume == always_rgbe) - { - prev_ambient@tex = prev_ambient hlsl { Texture2D prev_ambient@tex; }; - prev_specular@tex = prev_specular hlsl { Texture2D prev_specular@tex; }; - } else - { + if (dagi_sp_has_exposure_assume == always_rgbe) + { + (ps) { + prev_ambient@tex = prev_ambient hlsl { Texture2D prev_ambient@tex; }; + prev_specular@tex = prev_specular hlsl { Texture2D prev_specular@tex; }; + } + DAGI_HW_RGBE_SCREEN_ENCODING(ps) + } else { + (ps) { prev_ambient@tex = prev_ambient hlsl { Texture2D prev_ambient@tex; }; prev_specular@tex = prev_specular hlsl { Texture2D prev_specular@tex; }; - }*/ - prev_ambient@tex = prev_ambient hlsl { Texture2D prev_ambient@tex; }; - prev_specular@tex = prev_specular hlsl { Texture2D prev_specular@tex; }; + } + DAGI_SW_RGBE_SCREEN_ENCODING(ps) + } + + (ps) { + ambient_has_history@i1 = ambient_has_history; prev_ambient_age@tex = prev_ambient_age hlsl { Texture2D prev_ambient_age@tex; }; diff --git a/samples/testGI/prog/test_app.cpp b/samples/testGI/prog/test_app.cpp index 8f0c47915..fdce23c32 100644 --- a/samples/testGI/prog/test_app.cpp +++ b/samples/testGI/prog/test_app.cpp @@ -181,6 +181,7 @@ typedef StrmSceneHolder scene_type_t; VAR(downsampled_checkerboard_depth_tex) \ VAR(downsampled_checkerboard_depth_tex_samplerstate) \ VAR(sphere_time) \ + VAR(dagi_sp_has_exposure_assume) \ VAR(prev_globtm_psf_0) \ VAR(prev_globtm_psf_1) \ VAR(prev_globtm_psf_2) \ @@ -662,10 +663,25 @@ class DemoGameScene final : public DagorGameScene, public IRenderDynamicCubeFace void initScreenGI(int w, int h) { const bool supportRGBE_RT = d3d::check_texformat(TEXFMT_R9G9B9E5 | TEXCF_RTARGET); - if (supportRGBE_RT) - gi_fmt = supportRGBE_RT ? TEXFMT_R9G9B9E5 : TEXFMT_R11G11B10F; + gi_fmt = supportRGBE_RT ? TEXFMT_R9G9B9E5 : TEXFMT_R11G11B10F; + if (gi_panel.gi_mode == SCREEN_PROBES) + { + if (ShaderGlobal::is_var_assumed(dagi_sp_has_exposure_assumeVarId) && + ShaderGlobal::get_interval_assumed_value(dagi_sp_has_exposure_assumeVarId)) + gi_fmt = supportRGBE_RT ? TEXFMT_R9G9B9E5 : TEXFMT_R11G11B10F; + else + gi_fmt = TEXFMT_R32UI; + } - ambient[0].close(); + if (ambient[0]) + { + TextureInfo ti; + ambient[0].getTex2D()->getinfo(ti); + if (ti.w != w || ti.h != h || ((ti.cflg & TEXFMT_MASK) != gi_fmt)) + ambient[0].close(); + } + if (ambient[0]) + return; ambient[0] = dag::create_tex(NULL, w, h, gi_fmt | TEXCF_RTARGET, 1, "screen_ambient0"); ambient[0]->texaddr(TEXADDR_CLAMP); screen_specular[0].close(); @@ -686,12 +702,12 @@ class DemoGameScene final : public DagorGameScene, public IRenderDynamicCubeFace void initGIReprojection(int w, int h) { - if (!gi_panel.reproject) + if (!screen_probes.reproject) { closeGIReprojection(); return; } - if (ambient[1] && gi_panel.reproject) + if (ambient[1] && screen_probes.reproject) { TextureInfo ti; ambient[1].getTex2D()->getinfo(ti); @@ -1604,6 +1620,7 @@ class DemoGameScene final : public DagorGameScene, public IRenderDynamicCubeFace initRes(w / (div + 1), h / (div + 1)); } initReflections(w, h); + initScreenGI(w, h); target->swapDepth(otherDepth); target->setVar(); ShaderGlobal::set_texture(prev_gbuffer_depthVarId, otherDepth.getTexId()); @@ -1901,7 +1918,7 @@ class DemoGameScene final : public DagorGameScene, public IRenderDynamicCubeFace TIME_D3D_PROFILE(ambientFixup) SCOPE_RENDER_TARGET; static TMatrix4 prevGlobTm; - const bool hasHistory = ambient[1] && gi_panel.reproject && validAmbientHistory; + const bool hasHistory = ambient[1] && screen_probes.reproject && validAmbientHistory; if (hasHistory) { @@ -2201,7 +2218,6 @@ class DemoGameScene final : public DagorGameScene, public IRenderDynamicCubeFace de3_imgui_init("Test GI", "Sky properties"); static GuiControlDesc skyGuiDesc[] = { - DECLARE_BOOL_CHECKBOX(gi_panel, reproject, false), DECLARE_BOOL_CHECKBOX(gi_panel, ssao, false), DECLARE_BOOL_CHECKBOX(gi_panel, gtao, false), DECLARE_INT_COMBOBOX(gi_panel, reflections, REFLECTIONS_ALL, REFLECTIONS_OFF, REFLECTIONS_SSR, REFLECTIONS_ALL), @@ -2216,6 +2232,7 @@ class DemoGameScene final : public DagorGameScene, public IRenderDynamicCubeFace DECLARE_FLOAT_SLIDER(sdf_panel, voxel0Size, 0.1, 1., 0.15, 0.1), DECLARE_FLOAT_SLIDER(sdf_panel, yResScale, 0.5, 1., 0.5, 0.1), DECLARE_FLOAT_SLIDER(screen_probes, temporality, 0, 1., 0.5, 0.01), + DECLARE_BOOL_CHECKBOX(screen_probes, reproject, true), DECLARE_INT_COMBOBOX(screen_probes, tileSize, screen_probes.tileSize, 8, 10, 12, 14, 16, 20, 24, 32), DECLARE_INT_COMBOBOX(screen_probes, radianceOctRes, 8, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16), DECLARE_BOOL_CHECKBOX(screen_probes, angleFiltering, false), @@ -2496,7 +2513,6 @@ class DemoGameScene final : public DagorGameScene, public IRenderDynamicCubeFace float dynamic_gi_quality = 1.0; float exposure = 1; bool fake_dynres = false; - bool reproject = true; } gi_panel; struct { @@ -2516,6 +2532,7 @@ class DemoGameScene final : public DagorGameScene, public IRenderDynamicCubeFace { int tileSize = 16, radianceOctRes = 8; float temporality = 0.5; + bool reproject = true; bool angleFiltering; } screen_probes;