From e02ca53f9946844d6b4bc057b50fd20dbcb6d2f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tur=C3=A1nszki=20J=C3=A1nos?= Date: Sat, 29 Apr 2023 15:44:06 +0200 Subject: [PATCH] GPU Video Decoding (#661) --- Editor/CMakeLists.txt | 1 + Editor/ComponentsWindow.cpp | 24 + Editor/ComponentsWindow.h | 2 + Editor/Editor.cpp | 52 + Editor/Editor_SOURCE.vcxitems | 2 + Editor/Editor_SOURCE.vcxitems.filters | 2 + Editor/IconDefinitions.h | 1 + Editor/OptionsWindow.cpp | 41 + Editor/OptionsWindow.h | 1 + Editor/SoundWindow.cpp | 1 - Editor/VideoWindow.cpp | 308 ++ Editor/VideoWindow.h | 31 + README.md | 8 + WickedEngine/CMakeLists.txt | 2 + WickedEngine/Utility/CMakeLists.txt | 14 + WickedEngine/Utility/D3D12MemAlloc.h | 13 +- .../dx12/D3D12TokenizedProgramFormat.hpp | 2627 ++++++++++++ WickedEngine/Utility/dx12/d3d12.h | 1353 ++++++- WickedEngine/Utility/dx12/d3d12sdklayers.h | 123 +- WickedEngine/Utility/dx12/d3dx12_barriers.h | 8 +- .../dx12/d3dx12_check_feature_support.h | 90 +- WickedEngine/Utility/dx12/d3dx12_core.h | 111 +- .../dx12/d3dx12_pipeline_state_stream.h | 212 +- .../dx12/d3dx12_property_format_table.h | 3 +- .../Utility/dx12/d3dx12_render_pass.h | 51 +- .../Utility/dx12/d3dx12_resource_helpers.h | 23 +- .../Utility/dx12/d3dx12_root_signature.h | 180 +- WickedEngine/Utility/dx12/dxcore.h | 41 + WickedEngine/Utility/dx12/dxcore_interface.h | 316 ++ WickedEngine/Utility/dx12/dxgiformat.h | 2 + WickedEngine/Utility/dxva.h | 146 + WickedEngine/Utility/h264.h | 952 +++++ WickedEngine/Utility/minimp4.h | 3506 +++++++++++++++++ WickedEngine/Utility/utility_common.cpp | 6 + WickedEngine/Utility/vk_mem_alloc.h | 174 +- WickedEngine/Utility/volk.c | 417 +- WickedEngine/Utility/volk.h | 284 +- WickedEngine/Utility/vulkan/vk_icd.h | 2 +- WickedEngine/Utility/vulkan/vk_layer.h | 8 - WickedEngine/Utility/vulkan/vk_platform.h | 2 +- .../vk_video/vulkan_video_codec_h264std.h | 2 +- .../vulkan_video_codec_h264std_decode.h | 2 +- .../vulkan_video_codec_h264std_encode.h | 33 +- .../vk_video/vulkan_video_codec_h265std.h | 2 +- .../vulkan_video_codec_h265std_decode.h | 2 +- .../vulkan_video_codec_h265std_encode.h | 30 +- .../vk_video/vulkan_video_codecs_common.h | 2 +- WickedEngine/Utility/vulkan/vulkan.h | 10 +- WickedEngine/Utility/vulkan/vulkan_android.h | 2 +- WickedEngine/Utility/vulkan/vulkan_beta.h | 272 +- WickedEngine/Utility/vulkan/vulkan_core.h | 405 +- WickedEngine/Utility/vulkan/vulkan_directfb.h | 2 +- WickedEngine/Utility/vulkan/vulkan_fuchsia.h | 2 +- WickedEngine/Utility/vulkan/vulkan_ggp.h | 2 +- WickedEngine/Utility/vulkan/vulkan_ios.h | 2 +- WickedEngine/Utility/vulkan/vulkan_macos.h | 2 +- WickedEngine/Utility/vulkan/vulkan_metal.h | 2 +- WickedEngine/Utility/vulkan/vulkan_screen.h | 2 +- WickedEngine/Utility/vulkan/vulkan_vi.h | 2 +- WickedEngine/Utility/vulkan/vulkan_wayland.h | 2 +- WickedEngine/Utility/vulkan/vulkan_win32.h | 2 +- WickedEngine/Utility/vulkan/vulkan_xcb.h | 2 +- WickedEngine/Utility/vulkan/vulkan_xlib.h | 2 +- .../Utility/vulkan/vulkan_xlib_xrandr.h | 2 +- WickedEngine/WickedEngine.h | 1 + WickedEngine/WickedEngine_SOURCE.vcxitems | 5 + .../WickedEngine_SOURCE.vcxitems.filters | 18 + WickedEngine/offlineshadercompiler.cpp | 3 + WickedEngine/shaders/Shaders_SOURCE.vcxitems | 4 + .../shaders/Shaders_SOURCE.vcxitems.filters | 3 + WickedEngine/shaders/yuv_to_rgbCS.hlsl | 29 + WickedEngine/wiApplication.cpp | 16 +- WickedEngine/wiEnums.h | 1 + WickedEngine/wiGraphics.h | 91 +- WickedEngine/wiGraphicsDevice.h | 13 +- WickedEngine/wiGraphicsDevice_DX12.cpp | 909 ++++- WickedEngine/wiGraphicsDevice_DX12.h | 56 +- WickedEngine/wiGraphicsDevice_Vulkan.cpp | 994 ++++- WickedEngine/wiGraphicsDevice_Vulkan.h | 57 +- WickedEngine/wiHelper.cpp | 14 +- WickedEngine/wiImage.cpp | 4 +- WickedEngine/wiImage.h | 2 + WickedEngine/wiJobSystem.cpp | 17 +- WickedEngine/wiJobSystem.h | 1 + WickedEngine/wiRenderPath3D.cpp | 29 + WickedEngine/wiRenderPath3D.h | 3 + WickedEngine/wiRenderer.cpp | 60 +- WickedEngine/wiRenderer.h | 8 + WickedEngine/wiResourceManager.cpp | 35 + WickedEngine/wiResourceManager.h | 4 + WickedEngine/wiScene.cpp | 58 + WickedEngine/wiScene.h | 6 + WickedEngine/wiScene_Components.cpp | 4 + WickedEngine/wiScene_Components.h | 26 + WickedEngine/wiScene_Serializers.cpp | 26 + WickedEngine/wiVersion.cpp | 3 +- WickedEngine/wiVideo.cpp | 679 ++++ WickedEngine/wiVideo.h | 109 + third_party_software.txt | 11 + 99 files changed, 14328 insertions(+), 899 deletions(-) create mode 100644 Editor/VideoWindow.cpp create mode 100644 Editor/VideoWindow.h create mode 100644 WickedEngine/Utility/dx12/D3D12TokenizedProgramFormat.hpp create mode 100644 WickedEngine/Utility/dx12/dxcore.h create mode 100644 WickedEngine/Utility/dx12/dxcore_interface.h create mode 100644 WickedEngine/Utility/dxva.h create mode 100644 WickedEngine/Utility/h264.h create mode 100644 WickedEngine/Utility/minimp4.h rename WickedEngine/Utility/{ => vulkan}/vk_video/vulkan_video_codec_h264std.h (99%) rename WickedEngine/Utility/{ => vulkan}/vk_video/vulkan_video_codec_h264std_decode.h (98%) rename WickedEngine/Utility/{ => vulkan}/vk_video/vulkan_video_codec_h264std_encode.h (82%) rename WickedEngine/Utility/{ => vulkan}/vk_video/vulkan_video_codec_h265std.h (99%) rename WickedEngine/Utility/{ => vulkan}/vk_video/vulkan_video_codec_h265std_decode.h (97%) rename WickedEngine/Utility/{ => vulkan}/vk_video/vulkan_video_codec_h265std_encode.h (86%) rename WickedEngine/Utility/{ => vulkan}/vk_video/vulkan_video_codecs_common.h (91%) create mode 100644 WickedEngine/shaders/yuv_to_rgbCS.hlsl create mode 100644 WickedEngine/wiVideo.cpp create mode 100644 WickedEngine/wiVideo.h diff --git a/Editor/CMakeLists.txt b/Editor/CMakeLists.txt index e56d042ab..d3a94ac45 100644 --- a/Editor/CMakeLists.txt +++ b/Editor/CMakeLists.txt @@ -24,6 +24,7 @@ set (SOURCE_FILES PaintToolWindow.cpp GraphicsWindow.cpp SoundWindow.cpp + VideoWindow.cpp SpringWindow.cpp ScriptWindow.cpp stdafx.cpp diff --git a/Editor/ComponentsWindow.cpp b/Editor/ComponentsWindow.cpp index 714daf172..514a35990 100644 --- a/Editor/ComponentsWindow.cpp +++ b/Editor/ComponentsWindow.cpp @@ -20,6 +20,7 @@ void ComponentsWindow::Create(EditorComponent* _editor) meshWnd.Create(editor); envProbeWnd.Create(editor); soundWnd.Create(editor); + videoWnd.Create(editor); decalWnd.Create(editor); lightWnd.Create(editor); animWnd.Create(editor); @@ -71,6 +72,7 @@ void ComponentsWindow::Create(EditorComponent* _editor) newComponentCombo.AddItem("Collider " ICON_COLLIDER, 18); newComponentCombo.AddItem("Camera " ICON_CAMERA, 20); newComponentCombo.AddItem("Object " ICON_OBJECT, 21); + newComponentCombo.AddItem("Video " ICON_VIDEO, 22); newComponentCombo.OnSelect([=](wi::gui::EventArgs args) { newComponentCombo.SetSelectedWithoutCallback(-1); if (editor->translator.selected.empty()) @@ -183,6 +185,10 @@ void ComponentsWindow::Create(EditorComponent* _editor) if (scene.objects.Contains(entity)) return; break; + case 22: + if (scene.videos.Contains(entity)) + return; + break; default: return; } @@ -279,6 +285,9 @@ void ComponentsWindow::Create(EditorComponent* _editor) case 21: scene.objects.Create(entity); break; + case 22: + scene.videos.Create(entity); + break; default: break; } @@ -297,6 +306,7 @@ void ComponentsWindow::Create(EditorComponent* _editor) AddWidget(&meshWnd); AddWidget(&envProbeWnd); AddWidget(&soundWnd); + AddWidget(&videoWnd); AddWidget(&decalWnd); AddWidget(&lightWnd); AddWidget(&animWnd); @@ -325,6 +335,7 @@ void ComponentsWindow::Create(EditorComponent* _editor) meshWnd.SetVisible(false); envProbeWnd.SetVisible(false); soundWnd.SetVisible(false); + videoWnd.SetVisible(false); decalWnd.SetVisible(false); lightWnd.SetVisible(false); animWnd.SetVisible(false); @@ -543,6 +554,19 @@ void ComponentsWindow::ResizeLayout() soundWnd.SetVisible(false); } + if (scene.videos.Contains(videoWnd.entity)) + { + videoWnd.SetVisible(true); + videoWnd.SetPos(pos); + videoWnd.SetSize(XMFLOAT2(width, videoWnd.GetScale().y)); + pos.y += videoWnd.GetSize().y; + pos.y += padding; + } + else + { + videoWnd.SetVisible(false); + } + if (scene.decals.Contains(decalWnd.entity)) { decalWnd.SetVisible(true); diff --git a/Editor/ComponentsWindow.h b/Editor/ComponentsWindow.h index fd1663854..53bc58296 100644 --- a/Editor/ComponentsWindow.h +++ b/Editor/ComponentsWindow.h @@ -11,6 +11,7 @@ #include "HairParticleWindow.h" #include "ForceFieldWindow.h" #include "SoundWindow.h" +#include "VideoWindow.h" #include "SpringWindow.h" #include "IKWindow.h" #include "TransformWindow.h" @@ -51,6 +52,7 @@ public: HairParticleWindow hairWnd; ForceFieldWindow forceFieldWnd; SoundWindow soundWnd; + VideoWindow videoWnd; SpringWindow springWnd; IKWindow ikWnd; TransformWindow transformWnd; diff --git a/Editor/Editor.cpp b/Editor/Editor.cpp index a981ee551..0cc54d5ca 100644 --- a/Editor/Editor.cpp +++ b/Editor/Editor.cpp @@ -1006,6 +1006,25 @@ void EditorComponent::Update(float dt) } } } + if (has_flag(optionsWnd.filter, OptionsWindow::Filter::Video)) + { + for (size_t i = 0; i < scene.videos.GetCount(); ++i) + { + Entity entity = scene.videos.GetEntity(i); + if (!scene.transforms.Contains(entity)) + continue; + const TransformComponent& transform = *scene.transforms.GetComponent(entity); + + XMVECTOR disV = XMVector3LinePointDistance(XMLoadFloat3(&pickRay.origin), XMLoadFloat3(&pickRay.origin) + XMLoadFloat3(&pickRay.direction), transform.GetPositionV()); + float dis = XMVectorGetX(disV); + if (dis > 0.01f && dis < wi::math::Distance(transform.GetPosition(), pickRay.origin) * 0.05f && dis < hovered.distance) + { + hovered = wi::scene::PickResult(); + hovered.entity = entity; + hovered.distance = dis; + } + } + } if (bone_picking) { for (size_t i = 0; i < scene.armatures.GetCount(); ++i) @@ -1471,6 +1490,7 @@ void EditorComponent::Update(float dt) componentsWnd.meshWnd.SetEntity(INVALID_ENTITY, -1); componentsWnd.materialWnd.SetEntity(INVALID_ENTITY); componentsWnd.soundWnd.SetEntity(INVALID_ENTITY); + componentsWnd.videoWnd.SetEntity(INVALID_ENTITY); componentsWnd.decalWnd.SetEntity(INVALID_ENTITY); componentsWnd.envProbeWnd.SetEntity(INVALID_ENTITY); componentsWnd.forceFieldWnd.SetEntity(INVALID_ENTITY); @@ -1513,6 +1533,7 @@ void EditorComponent::Update(float dt) componentsWnd.hairWnd.SetEntity(picked.entity); componentsWnd.lightWnd.SetEntity(picked.entity); componentsWnd.soundWnd.SetEntity(picked.entity); + componentsWnd.videoWnd.SetEntity(picked.entity); componentsWnd.decalWnd.SetEntity(picked.entity); componentsWnd.envProbeWnd.SetEntity(picked.entity); componentsWnd.forceFieldWnd.SetEntity(picked.entity); @@ -2244,6 +2265,36 @@ void EditorComponent::Render() const wi::font::Draw(ICON_SOUND, fp, cmd); } } + if (has_flag(optionsWnd.filter, OptionsWindow::Filter::Video)) + { + for (size_t i = 0; i < scene.videos.GetCount(); ++i) + { + Entity entity = scene.videos.GetEntity(i); + if (!scene.transforms.Contains(entity)) + continue; + const TransformComponent& transform = *scene.transforms.GetComponent(entity); + + fp.position = transform.GetPosition(); + fp.scaling = scaling * wi::math::Distance(transform.GetPosition(), camera.Eye); + fp.color = inactiveEntityColor; + + if (hovered.entity == entity) + { + fp.color = hoveredEntityColor; + } + for (auto& picked : translator.selected) + { + if (picked.entity == entity) + { + fp.color = selectedEntityColor; + break; + } + } + + + wi::font::Draw(ICON_VIDEO, fp, cmd); + } + } if (bone_picking) { static PipelineState pso; @@ -3317,6 +3368,7 @@ void EditorComponent::RefreshSceneList() componentsWnd.meshWnd.SetEntity(wi::ecs::INVALID_ENTITY, -1); componentsWnd.lightWnd.SetEntity(wi::ecs::INVALID_ENTITY); componentsWnd.soundWnd.SetEntity(wi::ecs::INVALID_ENTITY); + componentsWnd.videoWnd.SetEntity(wi::ecs::INVALID_ENTITY); componentsWnd.decalWnd.SetEntity(wi::ecs::INVALID_ENTITY); componentsWnd.envProbeWnd.SetEntity(wi::ecs::INVALID_ENTITY); componentsWnd.materialWnd.SetEntity(wi::ecs::INVALID_ENTITY); diff --git a/Editor/Editor_SOURCE.vcxitems b/Editor/Editor_SOURCE.vcxitems index 4a0a064a0..88bae06ba 100644 --- a/Editor/Editor_SOURCE.vcxitems +++ b/Editor/Editor_SOURCE.vcxitems @@ -123,6 +123,7 @@ + NotUsing @@ -181,6 +182,7 @@ + diff --git a/Editor/Editor_SOURCE.vcxitems.filters b/Editor/Editor_SOURCE.vcxitems.filters index 5fb73dc93..2c7400fae 100644 --- a/Editor/Editor_SOURCE.vcxitems.filters +++ b/Editor/Editor_SOURCE.vcxitems.filters @@ -88,6 +88,7 @@ + @@ -140,6 +141,7 @@ + diff --git a/Editor/IconDefinitions.h b/Editor/IconDefinitions.h index 91af0716a..509851de8 100644 --- a/Editor/IconDefinitions.h +++ b/Editor/IconDefinitions.h @@ -13,6 +13,7 @@ #define ICON_HAIR ICON_FA_SEEDLING #define ICON_FORCE ICON_FA_WIND #define ICON_SOUND ICON_FA_VOLUME_HIGH +#define ICON_VIDEO ICON_FA_FILM #define ICON_DECAL ICON_FA_NOTE_STICKY #define ICON_CAMERA ICON_FA_VIDEO #define ICON_ENVIRONMENTPROBE ICON_FA_EARTH_ASIA diff --git a/Editor/OptionsWindow.cpp b/Editor/OptionsWindow.cpp index 34b209dfc..5bf51168a 100644 --- a/Editor/OptionsWindow.cpp +++ b/Editor/OptionsWindow.cpp @@ -26,6 +26,7 @@ void OptionsWindow::Create(EditorComponent* _editor) newCombo.AddItem("Force " ICON_FORCE, 6); newCombo.AddItem("Decal " ICON_DECAL, 7); newCombo.AddItem("Sound " ICON_SOUND, 8); + newCombo.AddItem("Video " ICON_VIDEO, 19); newCombo.AddItem("Weather " ICON_WEATHER, 9); newCombo.AddItem("Emitter " ICON_EMITTER, 10); newCombo.AddItem("HairParticle " ICON_HAIR, 11); @@ -111,6 +112,33 @@ void OptionsWindow::Create(EditorComponent* _editor) return; } break; + case 19: + { + wi::helper::FileDialogParams params; + params.type = wi::helper::FileDialogParams::OPEN; + params.description = "Video"; + params.extensions = wi::resourcemanager::GetSupportedVideoExtensions(); + wi::helper::FileDialog(params, [=](std::string fileName) { + wi::eventhandler::Subscribe_Once(wi::eventhandler::EVENT_THREAD_SAFE_POINT, [=](uint64_t userdata) { + Entity entity = editor->GetCurrentScene().Entity_CreateVideo(wi::helper::GetFileNameFromPath(fileName), fileName); + + wi::Archive& archive = editor->AdvanceHistory(); + archive << EditorComponent::HISTORYOP_ADD; + editor->RecordSelection(archive); + + editor->ClearSelected(); + editor->AddSelected(entity); + + editor->RecordSelection(archive); + editor->RecordEntity(archive, entity); + + RefreshEntityTree(); + editor->componentsWnd.videoWnd.SetEntity(entity); + }); + }); + return; + } + break; case 9: pick.entity = CreateEntity(); scene.weathers.Create(pick.entity); @@ -191,6 +219,7 @@ void OptionsWindow::Create(EditorComponent* _editor) filterCombo.AddItem(ICON_ENVIRONMENTPROBE, (uint64_t)Filter::EnvironmentProbe); filterCombo.AddItem(ICON_DECAL, (uint64_t)Filter::Decal); filterCombo.AddItem(ICON_SOUND, (uint64_t)Filter::Sound); + filterCombo.AddItem(ICON_VIDEO, (uint64_t)Filter::Video); filterCombo.AddItem(ICON_WEATHER, (uint64_t)Filter::Weather); filterCombo.AddItem(ICON_POINTLIGHT, (uint64_t)Filter::Light); filterCombo.AddItem(ICON_ANIMATION, (uint64_t)Filter::Animation); @@ -463,6 +492,10 @@ void OptionsWindow::PushToEntityTree(wi::ecs::Entity entity, int level) { item.name += ICON_SOUND " "; } + if (scene.videos.Contains(entity)) + { + item.name += ICON_VIDEO " "; + } if (scene.decals.Contains(entity)) { item.name += ICON_DECAL " "; @@ -683,6 +716,14 @@ void OptionsWindow::RefreshEntityTree() } } + if (has_flag(filter, Filter::Video)) + { + for (size_t i = 0; i < scene.videos.GetCount(); ++i) + { + PushToEntityTree(scene.videos.GetEntity(i), 0); + } + } + if (has_flag(filter, Filter::Hairparticle)) { for (size_t i = 0; i < scene.hairs.GetCount(); ++i) diff --git a/Editor/OptionsWindow.h b/Editor/OptionsWindow.h index a95560586..c8ed576bc 100644 --- a/Editor/OptionsWindow.h +++ b/Editor/OptionsWindow.h @@ -46,6 +46,7 @@ public: Terrain = 1 << 19, Spring = 1 << 20, Humanoid = 1 << 21, + Video = 1 << 22, All = ~0ull, } filter = Filter::All; diff --git a/Editor/SoundWindow.cpp b/Editor/SoundWindow.cpp index 73f7110c8..da1d18ba9 100644 --- a/Editor/SoundWindow.cpp +++ b/Editor/SoundWindow.cpp @@ -1,6 +1,5 @@ #include "stdafx.h" #include "SoundWindow.h" -#include "wiAudio.h" using namespace wi::graphics; using namespace wi::ecs; diff --git a/Editor/VideoWindow.cpp b/Editor/VideoWindow.cpp new file mode 100644 index 000000000..f6113a966 --- /dev/null +++ b/Editor/VideoWindow.cpp @@ -0,0 +1,308 @@ +#include "stdafx.h" +#include "VideoWindow.h" + +using namespace wi::graphics; +using namespace wi::ecs; +using namespace wi::scene; + + +void VideoPreview::Render(const wi::Canvas& canvas, wi::graphics::CommandList cmd) const +{ + if (video == nullptr) + return; + + GraphicsDevice* device = wi::graphics::GetDevice(); + device->EventBegin("Video Preview", cmd); + + wi::image::Params params; + params.pos = translation; + params.siz = XMFLOAT2(scale.x, scale.y); + params.blendFlag = wi::enums::BLENDMODE_OPAQUE; + if (!video->videoinstance.output.texture.IsValid()) + { + params.color = wi::Color::Black(); + } + wi::image::Draw(&video->videoinstance.output.texture, params, cmd); + + device->EventEnd(cmd); +} + +void VideoWindow::Create(EditorComponent* _editor) +{ + editor = _editor; + wi::gui::Window::Create(ICON_VIDEO " Video", wi::gui::Window::WindowControls::COLLAPSE | wi::gui::Window::WindowControls::CLOSE); + SetSize(XMFLOAT2(440, 600)); + + closeButton.SetTooltip("Delete VideoComponent"); + OnClose([=](wi::gui::EventArgs args) { + + wi::Archive& archive = editor->AdvanceHistory(); + archive << EditorComponent::HISTORYOP_COMPONENT_DATA; + editor->RecordEntity(archive, entity); + + editor->GetCurrentScene().videos.Remove(entity); + + editor->RecordEntity(archive, entity); + + editor->optionsWnd.RefreshEntityTree(); + }); + + float x = 60; + float y = 0; + float hei = 18; + float step = hei + 2; + float wid = 200; + + + openButton.Create("Open File " ICON_OPEN); + openButton.SetTooltip("Open video file.\nSupported extensions: MP4"); + openButton.SetPos(XMFLOAT2(x, y)); + openButton.SetSize(XMFLOAT2(wid, hei)); + openButton.OnClick([&](wi::gui::EventArgs args) { + VideoComponent* video = editor->GetCurrentScene().videos.GetComponent(entity); + if (video != nullptr) + { + wi::helper::FileDialogParams params; + params.type = wi::helper::FileDialogParams::OPEN; + params.description = "Video (.mp4)"; + params.extensions = wi::resourcemanager::GetSupportedVideoExtensions(); + wi::helper::FileDialog(params, [=](std::string fileName) { + wi::eventhandler::Subscribe_Once(wi::eventhandler::EVENT_THREAD_SAFE_POINT, [=](uint64_t userdata) { + video->filename = fileName; + video->videoResource = wi::resourcemanager::Load(fileName, wi::resourcemanager::Flags::IMPORT_RETAIN_FILEDATA); + wi::video::CreateVideoInstance(&video->videoResource.GetVideo(), &video->videoinstance); + filenameLabel.SetText(wi::helper::GetFileNameFromPath(video->filename)); + }); + }); + } + }); + AddWidget(&openButton); + + filenameLabel.Create("Filename"); + filenameLabel.SetPos(XMFLOAT2(x, y += step)); + filenameLabel.SetSize(XMFLOAT2(wid, hei)); + AddWidget(&filenameLabel); + + playpauseButton.Create(ICON_PLAY); + playpauseButton.SetTooltip("Play/Pause selected video instance."); + playpauseButton.SetPos(XMFLOAT2(x, y += step)); + playpauseButton.SetSize(XMFLOAT2(wid, hei)); + playpauseButton.OnClick([&](wi::gui::EventArgs args) { + VideoComponent* video = editor->GetCurrentScene().videos.GetComponent(entity); + if (video != nullptr) + { + if (video->IsPlaying()) + { + video->Stop(); + playpauseButton.SetText(ICON_PLAY); + } + else + { + video->Play(); + playpauseButton.SetText(ICON_PAUSE); + } + } + }); + AddWidget(&playpauseButton); + + stopButton.Create(ICON_STOP); + stopButton.SetTooltip("Stop selected video instance."); + stopButton.SetPos(XMFLOAT2(x, y += step)); + stopButton.SetSize(XMFLOAT2(hei, hei)); + stopButton.OnClick([&](wi::gui::EventArgs args) { + VideoComponent* video = editor->GetCurrentScene().videos.GetComponent(entity); + if (video != nullptr) + { + video->Stop(); + video->videoinstance.current_frame = 0; + video->videoinstance.flags &= ~wi::video::VideoInstance::Flags::InitialFirstFrameDecoded; + video->videoinstance.flags &= ~wi::video::VideoInstance::Flags::Playing; + } + }); + AddWidget(&stopButton); + + loopedCheckbox.Create("Looped: "); + loopedCheckbox.SetTooltip("Enable looping for the selected video instance."); + loopedCheckbox.SetPos(XMFLOAT2(x, y += step)); + loopedCheckbox.SetSize(XMFLOAT2(hei, hei)); + loopedCheckbox.SetCheckText(ICON_LOOP); + loopedCheckbox.OnClick([&](wi::gui::EventArgs args) { + VideoComponent* video = editor->GetCurrentScene().videos.GetComponent(entity); + if (video != nullptr) + { + video->SetLooped(args.bValue); + } + }); + AddWidget(&loopedCheckbox); + + timerSlider.Create(0, 1, 0, 100000, "Timer: "); + timerSlider.SetSize(XMFLOAT2(hei, hei)); + timerSlider.OnSlide([&](wi::gui::EventArgs args) { + VideoComponent* video = editor->GetCurrentScene().videos.GetComponent(entity); + if (video != nullptr && video->videoResource.IsValid()) + { + const wi::video::Video& videofile = video->videoResource.GetVideo(); + int target_frame = int(float(args.fValue / videofile.duration_seconds) * videofile.frames_infos.size()); + for (size_t i = 0; i < videofile.frames_infos.size(); ++i) + { + auto& frame_info = videofile.frames_infos[i]; + if (i >= target_frame && frame_info.type == wi::graphics::VideoFrameType::Intra) + { + target_frame = (int)i; + break; + } + } + video->videoinstance.current_frame = target_frame; + video->videoinstance.flags |= wi::video::VideoInstance::Flags::DecoderReset; + video->videoinstance.flags &= ~wi::video::VideoInstance::Flags::InitialFirstFrameDecoded; + } + }); + AddWidget(&timerSlider); + + preview.SetSize(XMFLOAT2(160, 90)); + AddWidget(&preview); + + infoLabel.Create(""); + infoLabel.SetSize(XMFLOAT2(800, 600)); + AddWidget(&infoLabel); + + + SetMinimized(true); + SetVisible(false); + + SetEntity(INVALID_ENTITY); +} + +void VideoWindow::SetEntity(Entity entity) +{ + this->entity = entity; + Scene& scene = editor->GetCurrentScene(); + VideoComponent* video = scene.videos.GetComponent(entity); + NameComponent* name = scene.names.GetComponent(entity); + + preview.video = video; + + if (video != nullptr) + { + filenameLabel.SetText(wi::helper::GetFileNameFromPath(video->filename)); + playpauseButton.SetEnabled(true); + stopButton.SetEnabled(true); + loopedCheckbox.SetEnabled(true); + loopedCheckbox.SetCheck(video->IsLooped()); + if (video->IsPlaying()) + { + playpauseButton.SetText(ICON_PAUSE); + } + else + { + playpauseButton.SetText(ICON_PLAY); + } + + if (video->videoResource.IsValid()) + { + const wi::video::Video& videofile = video->videoResource.GetVideo(); + std::string str; + if (GetDevice()->CheckCapability(wi::graphics::GraphicsDeviceCapability::VIDEO_DECODE_H264)) + { + str += "GPU decode: Supported\n"; + } + else + { + str += "GPU decode: Not supported\n"; + } + str += "Audio track: not implemented\n"; + str += "Display buffers in use: " + std::to_string(video->videoinstance.output_textures_used.size()) + "\n\n"; + + str += "Tip: if you have a material on this entity, the material textures will be replaced by video. This way you can set video textures into the 3D scene.\n\n"; + + str += "title : " + videofile.title + "\n"; + str += "album : " + videofile.album + "\n"; + str += "artist : " + videofile.artist + "\n"; + str += "year : " + videofile.year + "\n"; + str += "comment : " + videofile.comment + "\n"; + str += "genre : " + videofile.genre + "\n"; + str += "width : " + std::to_string(videofile.width) + "\n"; + str += "height : " + std::to_string(videofile.height) + "\n"; + str += "duration : " + std::to_string(videofile.duration_seconds) + " seconds\n"; + str += "FPS : " + std::to_string(videofile.average_frames_per_second) + "\n"; + str += "bit rate : " + std::to_string(videofile.bit_rate) + "\n"; + str += "Picture Parameter Sets: " + std::to_string(videofile.pps_count) + "\n"; + str += "Sequence Parameter Sets: " + std::to_string(videofile.sps_count) + "\n"; + str += "Decode Picture Buffers: " + std::to_string(video->videoinstance.dpb.texture.desc.array_size) + "\n"; + infoLabel.SetText(str); + + timerSlider.SetRange(0, videofile.duration_seconds); + timerSlider.SetValue(float(video->videoinstance.current_frame) / float(videofile.frames_infos.size()) * videofile.duration_seconds); + } + } + else + { + filenameLabel.SetText(""); + playpauseButton.SetEnabled(false); + stopButton.SetEnabled(false); + loopedCheckbox.SetEnabled(false); + infoLabel.SetText(""); + } +} + +void VideoWindow::ResizeLayout() +{ + wi::gui::Window::ResizeLayout(); + const float padding = 4; + const float width = GetWidgetAreaSize().x; + float y = padding; + float jump = 20; + + auto add = [&](wi::gui::Widget& widget) { + if (!widget.IsVisible()) + return; + const float margin_left = 80; + const float margin_right = 40; + widget.SetPos(XMFLOAT2(margin_left, y)); + widget.SetSize(XMFLOAT2(width - margin_left - margin_right, widget.GetScale().y)); + y += widget.GetSize().y; + y += padding; + }; + auto add_right = [&](wi::gui::Widget& widget) { + if (!widget.IsVisible()) + return; + const float margin_right = 40; + widget.SetPos(XMFLOAT2(width - margin_right - widget.GetSize().x, y)); + y += widget.GetSize().y; + y += padding; + }; + auto add_fullwidth = [&](wi::gui::Widget& widget) { + if (!widget.IsVisible()) + return; + const float margin_left = padding; + const float margin_right = padding; + widget.SetPos(XMFLOAT2(margin_left, y)); + widget.SetSize(XMFLOAT2(width - margin_left - margin_right, widget.GetScale().y)); + y += widget.GetSize().y; + y += padding; + }; + + add_fullwidth(openButton); + add_fullwidth(filenameLabel); + + add_fullwidth(preview); + float h_aspect = 9.0f / 16.0f; + if (preview.video != nullptr && preview.video->videoResource.IsValid()) + { + const wi::video::Video& video = preview.video->videoResource.GetVideo(); + h_aspect = (float)video.height / (float)video.width; + } + preview.SetSize(XMFLOAT2(preview.GetSize().x, preview.GetSize().x * h_aspect)); + + add(playpauseButton); + loopedCheckbox.SetPos(XMFLOAT2(playpauseButton.GetPos().x - loopedCheckbox.GetSize().x - 2, playpauseButton.GetPos().y)); + stopButton.SetPos(XMFLOAT2(playpauseButton.GetPos().x + playpauseButton.GetSize().x + 2, playpauseButton.GetPos().y)); + stopButton.SetSize(XMFLOAT2(width - stopButton.GetPos().x - padding, playpauseButton.GetSize().y)); + + add(timerSlider); + + y += jump; + + add_fullwidth(infoLabel); +} + diff --git a/Editor/VideoWindow.h b/Editor/VideoWindow.h new file mode 100644 index 000000000..b8630fe9f --- /dev/null +++ b/Editor/VideoWindow.h @@ -0,0 +1,31 @@ +#pragma once +class EditorComponent; + +class VideoPreview : public wi::gui::Widget +{ +public: + wi::scene::VideoComponent* video = nullptr; + + void Render(const wi::Canvas& canvas, wi::graphics::CommandList cmd) const override; +}; + +class VideoWindow : public wi::gui::Window +{ +public: + void Create(EditorComponent* editor); + + EditorComponent* editor = nullptr; + wi::ecs::Entity entity = wi::ecs::INVALID_ENTITY; + void SetEntity(wi::ecs::Entity entity); + + wi::gui::Button openButton; + wi::gui::Label filenameLabel; + wi::gui::Button playpauseButton; + wi::gui::Button stopButton; + wi::gui::CheckBox loopedCheckbox; + VideoPreview preview; + wi::gui::Slider timerSlider; + wi::gui::Label infoLabel; + + void ResizeLayout() override; +}; diff --git a/README.md b/README.md index 41c13ea3d..9408b39ef 100644 --- a/README.md +++ b/README.md @@ -215,6 +215,14 @@ You can specify command line arguments (without any prefix) to switch between re gpuvalidation Use GPU Based Validation for graphics. This must be used together with the debugdevice argument. Currently DX12 only. + + gpu_verbose + Enable verbose GPU validation mode. + + + igpu + Prefer integrated GPU selection for graphics. By default, dedicated GPU selection will be preferred. + alwaysactive The application will not be paused when the window is in the background. diff --git a/WickedEngine/CMakeLists.txt b/WickedEngine/CMakeLists.txt index abcdecc12..023d4b10b 100644 --- a/WickedEngine/CMakeLists.txt +++ b/WickedEngine/CMakeLists.txt @@ -143,6 +143,7 @@ set(HEADER_FILES wiAllocator.h wiBVH.h wiLocalization.h + wiVideo.h ) add_library(${TARGET_NAME} ${WICKED_LIBRARY_TYPE} @@ -216,6 +217,7 @@ add_library(${TARGET_NAME} ${WICKED_LIBRARY_TYPE} wiConfig.cpp wiTerrain.cpp wiLocalization.cpp + wiVideo.cpp ${HEADER_FILES} ) add_library(WickedEngine ALIAS ${TARGET_NAME}) diff --git a/WickedEngine/Utility/CMakeLists.txt b/WickedEngine/Utility/CMakeLists.txt index 904cf5783..eccc82953 100644 --- a/WickedEngine/Utility/CMakeLists.txt +++ b/WickedEngine/Utility/CMakeLists.txt @@ -32,6 +32,7 @@ set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/flat_hash_map.hpp ${CMAKE_CURRENT_SOURCE_DIR}/pugixml.hpp ${CMAKE_CURRENT_SOURCE_DIR}/pugiconfig.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/h264.h ) install(FILES ${HEADER_FILES} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/WickedEngine/Utility/") @@ -91,6 +92,19 @@ set(HEADER_FILES_vulkan install(FILES ${HEADER_FILES_vulkan} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/WickedEngine/Utility/vulkan/") + +set(HEADER_FILES_vk_video + ${CMAKE_CURRENT_SOURCE_DIR}/vulkan/vk_video/vulkan_video_codec_h264std.h + ${CMAKE_CURRENT_SOURCE_DIR}/vulkan/vk_video/vulkan_video_codec_h264std_decode.h + ${CMAKE_CURRENT_SOURCE_DIR}/vulkan/vk_video/vulkan_video_codec_h264std_encode.h + ${CMAKE_CURRENT_SOURCE_DIR}/vulkan/vk_video/vulkan_video_codec_h265std.h + ${CMAKE_CURRENT_SOURCE_DIR}/vulkan/vk_video/vulkan_video_codec_h265std_decode.h + ${CMAKE_CURRENT_SOURCE_DIR}/vulkan/vk_video/vulkan_video_codec_h265std_encode.h + ${CMAKE_CURRENT_SOURCE_DIR}/vulkan/vk_video/vulkan_video_codecs_common.h + ) +install(FILES ${HEADER_FILES_vulkan} + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/WickedEngine/Utility/vulkan/vk_video/") + set(HEADER_FILES_encoder ${CMAKE_CURRENT_SOURCE_DIR}/basis_universal/encoder/apg_bmp.h diff --git a/WickedEngine/Utility/D3D12MemAlloc.h b/WickedEngine/Utility/D3D12MemAlloc.h index 4ab7be318..646b60dd5 100644 --- a/WickedEngine/Utility/D3D12MemAlloc.h +++ b/WickedEngine/Utility/D3D12MemAlloc.h @@ -59,9 +59,18 @@ Documentation of all members: D3D12MemAlloc.h */ // If using this library on a platform different than Windows PC or want to use different version of DXGI, -// you should include D3D12-compatible headers before this library on your own and define this macro. +// you should include D3D12-compatible headers before this library on your own and define +// D3D12MA_D3D12_HEADERS_ALREADY_INCLUDED. +// Alternatively, if you are targeting the open sourced DirectX headers, defining D3D12MA_USING_DIRECTX_HEADERS +// will include them rather the ones provided by the Windows SDK. #ifndef D3D12MA_D3D12_HEADERS_ALREADY_INCLUDED - #include + #if defined(D3D12MA_USING_DIRECTX_HEADERS) + #include + #include + #else + #include + #endif + #include #endif diff --git a/WickedEngine/Utility/dx12/D3D12TokenizedProgramFormat.hpp b/WickedEngine/Utility/dx12/D3D12TokenizedProgramFormat.hpp new file mode 100644 index 000000000..4d04c3a7a --- /dev/null +++ b/WickedEngine/Utility/dx12/D3D12TokenizedProgramFormat.hpp @@ -0,0 +1,2627 @@ +#pragma once +//********************************************************* +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License (MIT). +// +//********************************************************* +// +// High Level Goals +// +// - Serve as the runtime/DDI representation for all D3D11 tokenized code, +// for all classes of programs, including pixel program, vertex program, +// geometry program, etc. +// +// - Any information that HLSL needs to give to drivers is encoded in +// this token format in some form. +// +// - Enable common tools and source code for managing all tokenizable +// program formats. +// +// - Support extensible token definitions, allowing full customizations for +// specific program classes, while maintaining general conventions for all +// program models. +// +// - Binary backwards compatible with D3D10. Any token name that was originally +// defined with "D3D10" in it is unchanged; D3D11 only adds new tokens. +// +// ---------------------------------------------------------------------------- +// +// Low Level Feature Summary +// +// - DWORD based tokens always, for simplicity +// - Opcode token is generally a single DWORD, though there is a bit indicating +// if extended information (extra DWORD(s)) are present +// - Operand tokens are a completely self contained, extensible format, +// with scalar and 4-vector data types as first class citizens, but +// allowance for extension to n-component vectors. +// - Initial operand token identifies register type, register file +// structure/dimensionality and mode of indexing for each dimension, +// and choice of component selection mechanism (i.e. mask vs. swizzle etc). +// - Optional additional extended operand tokens can defined things like +// modifiers (which are not needed by default). +// - Operand's immediate index value(s), if needed, appear as subsequent DWORD +// values, and if relative addressing is specified, an additional completely +// self contained operand definition appears nested in the token sequence. +// +// ---------------------------------------------------------------------------- + +#include + +#pragma region Application Family +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) + +// ---------------------------------------------------------------------------- +// Version Token (VerTok) +// +// [07:00] minor version number (0-255) +// [15:08] major version number (0-255) +// [31:16] D3D10_SB_TOKENIZED_PROGRAM_TYPE +// +// ---------------------------------------------------------------------------- + +typedef enum D3D10_SB_TOKENIZED_PROGRAM_TYPE +{ + D3D10_SB_PIXEL_SHADER = 0, + D3D10_SB_VERTEX_SHADER = 1, + D3D10_SB_GEOMETRY_SHADER = 2, + + // D3D11 Shaders + D3D11_SB_HULL_SHADER = 3, + D3D11_SB_DOMAIN_SHADER = 4, + D3D11_SB_COMPUTE_SHADER = 5, + + // Subset of D3D12 Shaders where this field is referenced by runtime + // Entries from 6-12 are unique to state objects + // (e.g. library, callable and raytracing shaders) + D3D12_SB_MESH_SHADER = 13, + D3D12_SB_AMPLIFICATION_SHADER = 14, + + D3D11_SB_RESERVED0 = 0xFFF0 +} D3D10_SB_TOKENIZED_PROGRAM_TYPE; + +#define D3D10_SB_TOKENIZED_PROGRAM_TYPE_MASK 0xffff0000 +#define D3D10_SB_TOKENIZED_PROGRAM_TYPE_SHIFT 16 + +// DECODER MACRO: Retrieve program type from version token +#define DECODE_D3D10_SB_TOKENIZED_PROGRAM_TYPE(VerTok) ((D3D10_SB_TOKENIZED_PROGRAM_TYPE)(((VerTok)&D3D10_SB_TOKENIZED_PROGRAM_TYPE_MASK)>>D3D10_SB_TOKENIZED_PROGRAM_TYPE_SHIFT)) + +#define D3D10_SB_TOKENIZED_PROGRAM_MAJOR_VERSION_MASK 0x000000f0 +#define D3D10_SB_TOKENIZED_PROGRAM_MAJOR_VERSION_SHIFT 4 +#define D3D10_SB_TOKENIZED_PROGRAM_MINOR_VERSION_MASK 0x0000000f + +// DECODER MACRO: Retrieve major version # from version token +#define DECODE_D3D10_SB_TOKENIZED_PROGRAM_MAJOR_VERSION(VerTok) (((VerTok)&D3D10_SB_TOKENIZED_PROGRAM_MAJOR_VERSION_MASK)>>D3D10_SB_TOKENIZED_PROGRAM_MAJOR_VERSION_SHIFT) +// DECODER MACRO: Retrieve minor version # from version token +#define DECODE_D3D10_SB_TOKENIZED_PROGRAM_MINOR_VERSION(VerTok) ((VerTok)&D3D10_SB_TOKENIZED_PROGRAM_MINOR_VERSION_MASK) + +// ENCODER MACRO: Create complete VerTok +#define ENCODE_D3D10_SB_TOKENIZED_PROGRAM_VERSION_TOKEN(ProgType,MajorVer,MinorVer) ((((ProgType)<> D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH_SHIFT) + +// ENCODER MACRO: Store instruction length +// portion of OpcodeToken0, in # of DWORDs +// including the opcode token(s). +// Valid range is 1-127. +#define ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(Length) (((Length)<>D3D10_SB_INSTRUCTION_TEST_BOOLEAN_SHIFT)) +// ENCODER MACRO: Store "zero" or "nonzero" in the opcode +// specific control range of OpcodeToken0 +#define ENCODE_D3D10_SB_INSTRUCTION_TEST_BOOLEAN(Boolean) (((Boolean)<>D3D11_SB_INSTRUCTION_PRECISE_VALUES_SHIFT)) +// ENCODER MACRO: Given a set of +// D3D10_SB_OPERAND_4_COMPONENT_[X|Y|Z|W] values +// or'd together, encode them in OpcodeToken0. +#define ENCODE_D3D11_SB_INSTRUCTION_PRECISE_VALUES(ComponentMask) (((ComponentMask)<>D3D10_SB_RESINFO_INSTRUCTION_RETURN_TYPE_SHIFT)) +// ENCODER MACRO: Encode the return type for the resinfo instruction +// in the opcode specific control range of OpcodeToken0 +#define ENCODE_D3D10_SB_RESINFO_INSTRUCTION_RETURN_TYPE(ReturnType) (((ReturnType)<> D3D10_SB_OPCODE_EXTENDED_SHIFT) +// ENCODER MACRO: Store in OpcodeToken0 whether the opcode is extended +// by an additional opcode token. +#define ENCODE_D3D10_SB_OPCODE_EXTENDED(bExtended) (((bExtended)!=0)?D3D10_SB_OPCODE_EXTENDED_MASK:0) + +// ---------------------------------------------------------------------------- +// Extended Opcode Format (OpcodeToken1) +// +// If bit31 of an opcode token is set, the +// opcode has an additional extended opcode token DWORD +// directly following OpcodeToken0. Other tokens +// expected for the opcode, such as the operand +// token(s) always follow +// OpcodeToken0 AND OpcodeToken1..n (extended +// opcode tokens, if present). +// +// [05:00] D3D10_SB_EXTENDED_OPCODE_TYPE +// [30:06] if([05:00] == D3D10_SB_EXTENDED_OPCODE_SAMPLE_CONTROLS) +// { +// This custom opcode contains controls for SAMPLE. +// [08:06] Ignored, 0. +// [12:09] U texel immediate offset (4 bit 2's comp) (0 default) +// [16:13] V texel immediate offset (4 bit 2's comp) (0 default) +// [20:17] W texel immediate offset (4 bit 2's comp) (0 default) +// [30:14] Ignored, 0. +// } +// else if( [05:00] == D3D11_SB_EXTENDED_OPCODE_RESOURCE_DIM ) +// { +// [10:06] D3D10_SB_RESOURCE_DIMENSION +// [22:11] When dimension is D3D11_SB_RESOURCE_DIMENSION_STRUCTURED_BUFFER this holds the buffer stride, otherwise 0 +// [30:23] Ignored, 0. +// } +// else if( [05:00] == D3D11_SB_EXTENDED_OPCODE_RESOURCE_RETURN_TYPE ) +// { +// [09:06] D3D10_SB_RESOURCE_RETURN_TYPE for component X +// [13:10] D3D10_SB_RESOURCE_RETURN_TYPE for component Y +// [17:14] D3D10_SB_RESOURCE_RETURN_TYPE for component Z +// [21:18] D3D10_SB_RESOURCE_RETURN_TYPE for component W +// [30:22] Ignored, 0. +// } +// else +// { +// [30:04] Ignored, 0. +// } +// [31] 0 normally. 1 there is another extended opcode. Any number +// of extended opcode tokens can be chained. It is possible that some extended +// opcode tokens could include multiple DWORDS - that is defined +// on a case by case basis. +// +// ---------------------------------------------------------------------------- +typedef enum D3D10_SB_EXTENDED_OPCODE_TYPE +{ + D3D10_SB_EXTENDED_OPCODE_EMPTY = 0, + D3D10_SB_EXTENDED_OPCODE_SAMPLE_CONTROLS = 1, + D3D11_SB_EXTENDED_OPCODE_RESOURCE_DIM = 2, + D3D11_SB_EXTENDED_OPCODE_RESOURCE_RETURN_TYPE = 3, +} D3D10_SB_EXTENDED_OPCODE_TYPE; +#define D3D11_SB_MAX_SIMULTANEOUS_EXTENDED_OPCODES 3 + +#define D3D10_SB_EXTENDED_OPCODE_TYPE_MASK 0x0000003f + +// DECODER MACRO: Given an extended opcode +// token (OpcodeToken1), figure out what type +// of token it is (from D3D10_SB_EXTENDED_OPCODE_TYPE enum) +// to be able to interpret the rest of the token's contents. +#define DECODE_D3D10_SB_EXTENDED_OPCODE_TYPE(OpcodeToken1) ((D3D10_SB_EXTENDED_OPCODE_TYPE)((OpcodeToken1)&D3D10_SB_EXTENDED_OPCODE_TYPE_MASK)) + +// ENCODER MACRO: Store extended opcode token +// type in OpcodeToken1. +#define ENCODE_D3D10_SB_EXTENDED_OPCODE_TYPE(ExtOpcodeType) ((ExtOpcodeType)&D3D10_SB_EXTENDED_OPCODE_TYPE_MASK) + +typedef enum D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_COORD +{ + D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_U = 0, + D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_V = 1, + D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_W = 2, +} D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_COORD; +#define D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_COORD_MASK (3) +#define D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_SHIFT(Coord) (9+4*((Coord)&D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_COORD_MASK)) +#define D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_MASK(Coord) (0x0000000f<>(D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_SHIFT(Coord)))) + +// ENCODER MACRO: Store the immediate texel address offset +// for U or V or W Coord (D3D10_SB_ADDRESS_OFFSET_COORD) in an extended +// opcode token (OpcodeToken1) that has extended opcode +// type == D3D10_SB_EXTENDED_OPCODE_SAMPLE_CONTROLS (opcode type encoded separately) +// A 2's complement number is expected as input, from which the LSB 4 bits are extracted. +#define ENCODE_IMMEDIATE_D3D10_SB_ADDRESS_OFFSET(Coord,ImmediateOffset) (((ImmediateOffset)<>D3D11_SB_EXTENDED_RESOURCE_DIMENSION_SHIFT)) + +// ENCODER MACRO: Store resource dimension +// (D3D10_SB_RESOURCE_DIMENSION enum) into a +// an extended resource declaration token (D3D11_SB_EXTENDED_OPCODE_RESOURCE_DIM) +#define ENCODE_D3D11_SB_EXTENDED_RESOURCE_DIMENSION(ResourceDim) (((ResourceDim)<>D3D11_SB_EXTENDED_RESOURCE_DIMENSION_STRUCTURE_STRIDE_SHIFT) + +// ENCODER MACRO: Store resource dimension structure stride +// (12-bit unsigned integer) into a +// an extended resource declaration token (D3D11_SB_EXTENDED_OPCODE_RESOURCE_DIM) +#define ENCODE_D3D11_SB_EXTENDED_RESOURCE_DIMENSION_STRUCTURE_STRIDE(Stride) (((Stride)<> \ + (Component * D3D10_SB_RESOURCE_RETURN_TYPE_NUMBITS + D3D11_SB_EXTENDED_RESOURCE_RETURN_TYPE_SHIFT))&D3D10_SB_RESOURCE_RETURN_TYPE_MASK)) + +// ENCODER MACRO: Generate a resource return type for a component in an extended +// resource delcaration token (D3D11_SB_EXTENDED_OPCODE_RESOURCE_RETURN_TYPE) +#define ENCODE_D3D11_SB_EXTENDED_RESOURCE_RETURN_TYPE(ReturnType, Component) \ + (((ReturnType)&D3D10_SB_RESOURCE_RETURN_TYPE_MASK) << (Component * D3D10_SB_RESOURCE_RETURN_TYPE_NUMBITS + D3D11_SB_EXTENDED_RESOURCE_RETURN_TYPE_SHIFT)) + +// ---------------------------------------------------------------------------- +// Custom-Data Block Format +// +// DWORD 0 (CustomDataDescTok): +// [10:00] == D3D10_SB_OPCODE_CUSTOMDATA +// [31:11] == D3D10_SB_CUSTOMDATA_CLASS +// +// DWORD 1: +// 32-bit unsigned integer count of number +// of DWORDs in custom-data block, +// including DWORD 0 and DWORD 1. +// So the minimum value is 0x00000002, +// meaning empty custom-data. +// +// Layout of custom-data contents, for the various meta-data classes, +// not defined in this file. +// +// ---------------------------------------------------------------------------- + +typedef enum D3D10_SB_CUSTOMDATA_CLASS +{ + D3D10_SB_CUSTOMDATA_COMMENT = 0, + D3D10_SB_CUSTOMDATA_DEBUGINFO, + D3D10_SB_CUSTOMDATA_OPAQUE, + D3D10_SB_CUSTOMDATA_DCL_IMMEDIATE_CONSTANT_BUFFER, + D3D11_SB_CUSTOMDATA_SHADER_MESSAGE, + D3D11_SB_CUSTOMDATA_SHADER_CLIP_PLANE_CONSTANT_MAPPINGS_FOR_DX9, +} D3D10_SB_CUSTOMDATA_CLASS; + +#define D3D10_SB_CUSTOMDATA_CLASS_MASK 0xfffff800 +#define D3D10_SB_CUSTOMDATA_CLASS_SHIFT 11 +// DECODER MACRO: Find out what class of custom-data is present. +// The contents of the custom-data block are defined +// for each class of custom-data. +#define DECODE_D3D10_SB_CUSTOMDATA_CLASS(CustomDataDescTok) ((D3D10_SB_CUSTOMDATA_CLASS)(((CustomDataDescTok)&D3D10_SB_CUSTOMDATA_CLASS_MASK)>>D3D10_SB_CUSTOMDATA_CLASS_SHIFT)) +// ENCODER MACRO: Create complete CustomDataDescTok +#define ENCODE_D3D10_SB_CUSTOMDATA_CLASS(CustomDataClass) (ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_CUSTOMDATA)|(((CustomDataClass)<= D3D10_SB_OPERAND_INDEX_1D ) +// D3D10_SB_OPERAND_INDEX_REPRESENTATION for first operand index +// else +// Ignored, 0 +// [27:25] if( [21:20] >= D3D10_SB_OPERAND_INDEX_2D ) +// D3D10_SB_OPERAND_INDEX_REPRESENTATION for second operand index +// else +// Ignored, 0 +// [30:28] if( [21:20] == D3D10_SB_OPERAND_INDEX_3D ) +// D3D10_SB_OPERAND_INDEX_REPRESENTATION for third operand index +// else +// Ignored, 0 +// [31] 0 normally. 1 if extended operand definition, meaning next DWORD +// contains extended operand description. +// +// ---------------------------------------------------------------------------- + +// Number of components in data vector referred to by operand. +typedef enum D3D10_SB_OPERAND_NUM_COMPONENTS +{ + D3D10_SB_OPERAND_0_COMPONENT = 0, + D3D10_SB_OPERAND_1_COMPONENT = 1, + D3D10_SB_OPERAND_4_COMPONENT = 2, + D3D10_SB_OPERAND_N_COMPONENT = 3 // unused for now +} D3D10_SB_OPERAND_NUM_COMPONENTS; +#define D3D10_SB_OPERAND_NUM_COMPONENTS_MASK 0x00000003 + +// DECODER MACRO: Extract from OperandToken0 how many components +// the data vector referred to by the operand contains. +// (D3D10_SB_OPERAND_NUM_COMPONENTS enum) +#define DECODE_D3D10_SB_OPERAND_NUM_COMPONENTS(OperandToken0) ((D3D10_SB_OPERAND_NUM_COMPONENTS)((OperandToken0)&D3D10_SB_OPERAND_NUM_COMPONENTS_MASK)) + +// ENCODER MACRO: Define in OperandToken0 how many components +// the data vector referred to by the operand contains. +// (D3D10_SB_OPERAND_NUM_COMPONENTS enum). +#define ENCODE_D3D10_SB_OPERAND_NUM_COMPONENTS(NumComp) ((NumComp)&D3D10_SB_OPERAND_NUM_COMPONENTS_MASK) + +typedef enum D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE +{ + D3D10_SB_OPERAND_4_COMPONENT_MASK_MODE = 0, // mask 4 components + D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE_MODE = 1, // swizzle 4 components + D3D10_SB_OPERAND_4_COMPONENT_SELECT_1_MODE = 2, // select 1 of 4 components +} D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE; + +#define D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE_MASK 0x0000000c +#define D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE_SHIFT 2 + +// DECODER MACRO: For an operand representing 4component data, +// extract from OperandToken0 the method for selecting data from +// the 4 components (D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE). +#define DECODE_D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE(OperandToken0) ((D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE)(((OperandToken0)&D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE_MASK)>>D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE_SHIFT)) + +// ENCODER MACRO: For an operand representing 4component data, +// encode in OperandToken0 a value from D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE +#define ENCODE_D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE(SelectionMode) (((SelectionMode)<>(D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE_SHIFT+2*((DestComp)&D3D10_SB_4_COMPONENT_NAME_MASK)))&D3D10_SB_4_COMPONENT_NAME_MASK)) + +// ENCODER MACRO: Generate a 4 component swizzle given +// 4 D3D10_SB_4_COMPONENT_NAME source values for dest +// components x, y, z, w respectively. +#define ENCODE_D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE(XSrc,YSrc,ZSrc,WSrc) ((((XSrc)&D3D10_SB_4_COMPONENT_NAME_MASK)| \ + (((YSrc)&D3D10_SB_4_COMPONENT_NAME_MASK)<<2)| \ + (((ZSrc)&D3D10_SB_4_COMPONENT_NAME_MASK)<<4)| \ + (((WSrc)&D3D10_SB_4_COMPONENT_NAME_MASK)<<6) \ + )<>D3D10_SB_OPERAND_4_COMPONENT_SELECT_1_SHIFT)) + +// ENCODER MACRO: Given a D3D10_SB_4_COMPONENT_NAME selecting +// a single component for D3D10_SB_OPERAND_4_COMPONENT_SELECT_1_MODE, +// encode it into OperandToken0 +#define ENCODE_D3D10_SB_OPERAND_4_COMPONENT_SELECT_1(SelectedComp) (((SelectedComp)<>D3D10_SB_OPERAND_TYPE_SHIFT)) + +// ENCODER MACRO: Store operand type in OperandToken0. +#define ENCODE_D3D10_SB_OPERAND_TYPE(OperandType) (((OperandType)<>D3D10_SB_OPERAND_INDEX_DIMENSION_SHIFT)) + +// ENCODER MACRO: Store operand index dimension +// (D3D10_SB_OPERAND_INDEX_DIMENSION enum) in OperandToken0. +#define ENCODE_D3D10_SB_OPERAND_INDEX_DIMENSION(OperandIndexDim) (((OperandIndexDim)<>D3D10_SB_OPERAND_INDEX_REPRESENTATION_SHIFT(Dim))) + +// ENCODER MACRO: Store in OperandToken0 what representation +// an operand index is provided as (D3D10_SB_OPERAND_INDEX_REPRESENTATION enum), +// for index dimension [0], [1] or [2], depending on D3D10_SB_OPERAND_INDEX_DIMENSION. +#define ENCODE_D3D10_SB_OPERAND_INDEX_REPRESENTATION(Dim,IndexRepresentation) (((IndexRepresentation)<>D3D10_SB_OPERAND_EXTENDED_SHIFT) + +// ENCODER MACRO: Store in OperandToken0 whether the operand is extended +// by an additional operand token. +#define ENCODE_D3D10_SB_OPERAND_EXTENDED(bExtended) (((bExtended)!=0)?D3D10_SB_OPERAND_EXTENDED_MASK:0) + +// ---------------------------------------------------------------------------- +// Extended Instruction Operand Format (OperandToken1) +// +// If bit31 of an operand token is set, the +// operand has additional data in a second DWORD +// directly following OperandToken0. Other tokens +// expected for the operand, such as immmediate +// values or relative address operands (full +// operands in themselves) always follow +// OperandToken0 AND OperandToken1..n (extended +// operand tokens, if present). +// +// [05:00] D3D10_SB_EXTENDED_OPERAND_TYPE +// [16:06] if([05:00] == D3D10_SB_EXTENDED_OPERAND_MODIFIER) +// { +// [13:06] D3D10_SB_OPERAND_MODIFIER +// [16:14] Min Precision: D3D11_SB_OPERAND_MIN_PRECISION +// [17:17] Non-uniform: D3D12_SB_OPERAND_NON_UNIFORM +// } +// else +// { +// [17:06] Ignored, 0. +// } +// [30:18] Ignored, 0. +// [31] 0 normally. 1 if second order extended operand definition, +// meaning next DWORD contains yet ANOTHER extended operand +// description. Currently no second order extensions defined. +// This would be useful if a particular extended operand does +// not have enough space to store the required information in +// a single token and so is extended further. +// +// ---------------------------------------------------------------------------- + +typedef enum D3D10_SB_EXTENDED_OPERAND_TYPE +{ + D3D10_SB_EXTENDED_OPERAND_EMPTY = 0, // Might be used if this + // enum is full and + // further extended opcode + // is needed. + D3D10_SB_EXTENDED_OPERAND_MODIFIER = 1, +} D3D10_SB_EXTENDED_OPERAND_TYPE; +#define D3D10_SB_EXTENDED_OPERAND_TYPE_MASK 0x0000003f + +// DECODER MACRO: Given an extended operand +// token (OperandToken1), figure out what type +// of token it is (from D3D10_SB_EXTENDED_OPERAND_TYPE enum) +// to be able to interpret the rest of the token's contents. +#define DECODE_D3D10_SB_EXTENDED_OPERAND_TYPE(OperandToken1) ((D3D10_SB_EXTENDED_OPERAND_TYPE)((OperandToken1)&D3D10_SB_EXTENDED_OPERAND_TYPE_MASK)) + +// ENCODER MACRO: Store extended operand token +// type in OperandToken1. +#define ENCODE_D3D10_SB_EXTENDED_OPERAND_TYPE(ExtOperandType) ((ExtOperandType)&D3D10_SB_EXTENDED_OPERAND_TYPE_MASK) + +typedef enum D3D10_SB_OPERAND_MODIFIER +{ + D3D10_SB_OPERAND_MODIFIER_NONE = 0, // Nop. This is the implied + // default if the extended + // operand is not present for + // an operand for which source + // modifiers are meaningful + D3D10_SB_OPERAND_MODIFIER_NEG = 1, // Negate + D3D10_SB_OPERAND_MODIFIER_ABS = 2, // Absolute value, abs() + D3D10_SB_OPERAND_MODIFIER_ABSNEG = 3, // -abs() +} D3D10_SB_OPERAND_MODIFIER; +#define D3D10_SB_OPERAND_MODIFIER_MASK 0x00003fc0 +#define D3D10_SB_OPERAND_MODIFIER_SHIFT 6 + +// DECODER MACRO: Given a D3D10_SB_EXTENDED_OPERAND_MODIFIER +// extended token (OperandToken1), determine the source modifier +// (D3D10_SB_OPERAND_MODIFIER enum) +#define DECODE_D3D10_SB_OPERAND_MODIFIER(OperandToken1) ((D3D10_SB_OPERAND_MODIFIER)(((OperandToken1)&D3D10_SB_OPERAND_MODIFIER_MASK)>>D3D10_SB_OPERAND_MODIFIER_SHIFT)) + +// ENCODER MACRO: Generate a complete source modifier extended token +// (OperandToken1), given D3D10_SB_OPERAND_MODIFIER enum (the +// ext. operand type is also set to D3D10_SB_EXTENDED_OPERAND_MODIFIER). +#define ENCODE_D3D10_SB_EXTENDED_OPERAND_MODIFIER(SourceMod) ((((SourceMod)<> D3D11_SB_OPERAND_MIN_PRECISION_SHIFT)) + +// ENCODER MACRO: Encode minimum precision for execution +// into the extended operand token, OperandToken1 +#define ENCODE_D3D11_SB_OPERAND_MIN_PRECISION(MinPrecision) (((MinPrecision)<< D3D11_SB_OPERAND_MIN_PRECISION_SHIFT)& D3D11_SB_OPERAND_MIN_PRECISION_MASK) + + +// Non-uniform extended operand modifier. +#define D3D12_SB_OPERAND_NON_UNIFORM_MASK 0x00020000 +#define D3D12_SB_OPERAND_NON_UNIFORM_SHIFT 17 + +// DECODER MACRO: For an OperandToken1 that can specify a non-uniform operand +#define DECODE_D3D12_SB_OPERAND_NON_UNIFORM(OperandToken1) (((OperandToken1)& D3D12_SB_OPERAND_NON_UNIFORM_MASK)>> D3D12_SB_OPERAND_NON_UNIFORM_SHIFT) + +// ENCODER MACRO: Encode non-uniform state into the extended operand token, OperandToken1 +#define ENCODE_D3D12_SB_OPERAND_NON_UNIFORM(NonUniform) (((NonUniform)<< D3D12_SB_OPERAND_NON_UNIFORM_SHIFT)& D3D12_SB_OPERAND_NON_UNIFORM_MASK) + + +#define D3D10_SB_OPERAND_DOUBLE_EXTENDED_MASK 0x80000000 +#define D3D10_SB_OPERAND_DOUBLE_EXTENDED_SHIFT 31 +// DECODER MACRO: Determine if an extended operand token +// (OperandToken1) is further extended by yet another token +// (OperandToken2). Currently there are no secondary +// extended operand tokens. +#define DECODE_IS_D3D10_SB_OPERAND_DOUBLE_EXTENDED(OperandToken1) (((OperandToken1)&D3D10_SB_OPERAND_DOUBLE_EXTENDED_MASK)>>D3D10_SB_OPERAND_DOUBLE_EXTENDED_SHIFT) + +// ENCODER MACRO: Store in OperandToken1 whether the operand is extended +// by an additional operand token. Currently there are no secondary +// extended operand tokens. +#define ENCODE_D3D10_SB_OPERAND_DOUBLE_EXTENDED(bExtended) (((bExtended)!=0)?D3D10_SB_OPERAND_DOUBLE_EXTENDED_MASK:0) + +// ---------------------------------------------------------------------------- +// Name Token (NameToken) (used in declaration statements) +// +// [15:00] D3D10_SB_NAME enumeration +// [31:16] Reserved, 0 +// +// ---------------------------------------------------------------------------- +#define D3D10_SB_NAME_MASK 0x0000ffff + +// DECODER MACRO: Get the name from NameToken +#define DECODE_D3D10_SB_NAME(NameToken) ((D3D10_SB_NAME)((NameToken)&D3D10_SB_NAME_MASK)) + +// ENCODER MACRO: Generate a complete NameToken given a D3D10_SB_NAME +#define ENCODE_D3D10_SB_NAME(Name) ((Name)&D3D10_SB_NAME_MASK) + +//--------------------------------------------------------------------- +// Declaration Statements +// +// Declarations start with a standard opcode token, +// having opcode type being D3D10_SB_OPCODE_DCL*. +// Each particular declaration type has custom +// operand token(s), described below. +//--------------------------------------------------------------------- + +// ---------------------------------------------------------------------------- +// Global Flags Declaration +// +// OpcodeToken0: +// +// [10:00] D3D10_SB_OPCODE_DCL_GLOBAL_FLAGS +// [11:11] Refactoring allowed if bit set. +// [12:12] Enable double precision float ops. +// [13:13] Force early depth-stencil test. +// [14:14] Enable RAW and structured buffers in non-CS 4.x shaders. +// [15:15] Skip optimizations of shader IL when translating to native code +// [16:16] Enable minimum-precision data types +// [17:17] Enable 11.1 double-precision floating-point instruction extensions +// [18:18] Enable 11.1 non-double instruction extensions +// [23:19] Reserved for future flags. +// [30:24] Instruction length in DWORDs including the opcode token. == 1 +// [31] 0 normally. 1 if extended operand definition, meaning next DWORD +// contains extended operand description. This dcl is currently not +// extended. +// +// OpcodeToken0 is followed by no operands. +// +// ---------------------------------------------------------------------------- +#define D3D10_SB_GLOBAL_FLAG_REFACTORING_ALLOWED (1<<11) +#define D3D11_SB_GLOBAL_FLAG_ENABLE_DOUBLE_PRECISION_FLOAT_OPS (1<<12) +#define D3D11_SB_GLOBAL_FLAG_FORCE_EARLY_DEPTH_STENCIL (1<<13) +#define D3D11_SB_GLOBAL_FLAG_ENABLE_RAW_AND_STRUCTURED_BUFFERS (1<<14) +#define D3D11_1_SB_GLOBAL_FLAG_SKIP_OPTIMIZATION (1<<15) +#define D3D11_1_SB_GLOBAL_FLAG_ENABLE_MINIMUM_PRECISION (1<<16) +#define D3D11_1_SB_GLOBAL_FLAG_ENABLE_DOUBLE_EXTENSIONS (1<<17) +#define D3D11_1_SB_GLOBAL_FLAG_ENABLE_SHADER_EXTENSIONS (1<<18) +#define D3D12_SB_GLOBAL_FLAG_ALL_RESOURCES_BOUND (1<<19) + +#define D3D10_SB_GLOBAL_FLAGS_MASK 0x00fff800 + +// DECODER MACRO: Get global flags +#define DECODE_D3D10_SB_GLOBAL_FLAGS(OpcodeToken0) ((OpcodeToken0)&D3D10_SB_GLOBAL_FLAGS_MASK) + +// ENCODER MACRO: Encode global flags +#define ENCODE_D3D10_SB_GLOBAL_FLAGS(Flags) ((Flags)&D3D10_SB_GLOBAL_FLAGS_MASK) + +// ---------------------------------------------------------------------------- +// Resource Declaration (non multisampled) +// +// OpcodeToken0: +// +// [10:00] D3D10_SB_OPCODE_DCL_RESOURCE +// [15:11] D3D10_SB_RESOURCE_DIMENSION +// [23:16] Ignored, 0 +// [30:24] Instruction length in DWORDs including the opcode token. +// [31] 0 normally. 1 if extended operand definition, meaning next DWORD +// contains extended operand description. This dcl is currently not +// extended. +// +// OpcodeToken0 is followed by 2 operands on Shader Models 4.0 through 5.0: +// (1) an operand, starting with OperandToken0, defining which +// t# register (D3D10_SB_OPERAND_TYPE_RESOURCE) is being declared. +// (2) a Resource Return Type token (ResourceReturnTypeToken) +// +// OpcodeToken0 is followed by 3 operands on Shader Model 5.1 and later: +// (1) an operand, starting with OperandToken0, defining which +// t# register (D3D10_SB_OPERAND_TYPE_RESOURCE) is being declared. +// The indexing dimension for the register must be D3D10_SB_OPERAND_INDEX_DIMENSION_3D, +// and the meaning of the index dimensions are as follows: (t[:]) +// 1 : variable ID being declared +// 2 : the lower bound of the range of resources in the space +// 3 : the upper bound (inclusive) of this range +// As opposed to when the t# is used in shader instructions, where the register +// must be D3D10_SB_OPERAND_INDEX_DIMENSION_2D, and the meaning of the index +// dimensions are as follows: (t[]): +// 1 : variable ID being used (matches dcl) +// 2 : absolute index of resource within space (may be dynamically indexed) +// (2) a Resource Return Type token (ResourceReturnTypeToken) +// (3) a DWORD indicating the space index. +// +// ---------------------------------------------------------------------------- +#define D3D10_SB_RESOURCE_DIMENSION_MASK 0x0000F800 +#define D3D10_SB_RESOURCE_DIMENSION_SHIFT 11 + +// DECODER MACRO: Given a resource declaration token, +// (OpcodeToken0), determine the resource dimension +// (D3D10_SB_RESOURCE_DIMENSION enum) +#define DECODE_D3D10_SB_RESOURCE_DIMENSION(OpcodeToken0) ((D3D10_SB_RESOURCE_DIMENSION)(((OpcodeToken0)&D3D10_SB_RESOURCE_DIMENSION_MASK)>>D3D10_SB_RESOURCE_DIMENSION_SHIFT)) + +// ENCODER MACRO: Store resource dimension +// (D3D10_SB_RESOURCE_DIMENSION enum) into a +// a resource declaration token (OpcodeToken0) +#define ENCODE_D3D10_SB_RESOURCE_DIMENSION(ResourceDim) (((ResourceDim)<[:]) +// 1 : variable ID being declared +// 2 : the lower bound of the range of resources in the space +// 3 : the upper bound (inclusive) of this range +// As opposed to when the t# is used in shader instructions, where the register +// must be D3D10_SB_OPERAND_INDEX_DIMENSION_2D, and the meaning of the index +// dimensions are as follows: (t[]): +// 1 : variable ID being used (matches dcl) +// 2 : absolute index of resource within space (may be dynamically indexed) +// (2) a Resource Return Type token (ResourceReturnTypeToken) +// (3) a DWORD indicating the space index. +// +// ---------------------------------------------------------------------------- + +// use same macro for encoding/decoding resource dimension aas the non-msaa declaration + +#define D3D10_SB_RESOURCE_SAMPLE_COUNT_MASK 0x07F0000 +#define D3D10_SB_RESOURCE_SAMPLE_COUNT_SHIFT 16 + +// DECODER MACRO: Given a resource declaration token, +// (OpcodeToken0), determine the resource sample count (1..127) +#define DECODE_D3D10_SB_RESOURCE_SAMPLE_COUNT(OpcodeToken0) ((UINT)(((OpcodeToken0)&D3D10_SB_RESOURCE_SAMPLE_COUNT_MASK)>>D3D10_SB_RESOURCE_SAMPLE_COUNT_SHIFT)) + +// ENCODER MACRO: Store resource sample count up to 127 into a +// a resource declaration token (OpcodeToken0) +#define ENCODE_D3D10_SB_RESOURCE_SAMPLE_COUNT(SampleCount) (((SampleCount > 127 ? 127 : SampleCount)<> \ + (Component * D3D10_SB_RESOURCE_RETURN_TYPE_NUMBITS))&D3D10_SB_RESOURCE_RETURN_TYPE_MASK)) + +// ENCODER MACRO: Generate a resource return type for a component +#define ENCODE_D3D10_SB_RESOURCE_RETURN_TYPE(ReturnType, Component) \ + (((ReturnType)&D3D10_SB_RESOURCE_RETURN_TYPE_MASK) << (Component * D3D10_SB_RESOURCE_RETURN_TYPE_NUMBITS)) + +// ---------------------------------------------------------------------------- +// Sampler Declaration +// +// OpcodeToken0: +// +// [10:00] D3D10_SB_OPCODE_DCL_SAMPLER +// [14:11] D3D10_SB_SAMPLER_MODE +// [23:15] Ignored, 0 +// [30:24] Instruction length in DWORDs including the opcode token. +// [31] 0 normally. 1 if extended operand definition, meaning next DWORD +// contains extended operand description. This dcl is currently not +// extended. +// +// OpcodeToken0 is followed by 1 operand on Shader Models 4.0 through 5.0: +// (1) Operand starting with OperandToken0, defining which sampler +// (D3D10_SB_OPERAND_TYPE_SAMPLER) register # is being declared. +// +// OpcodeToken0 is followed by 2 operands on Shader Model 5.1 and later: +// (1) an operand, starting with OperandToken0, defining which +// s# register (D3D10_SB_OPERAND_TYPE_SAMPLER) is being declared. +// The indexing dimension for the register must be D3D10_SB_OPERAND_INDEX_DIMENSION_3D, +// and the meaning of the index dimensions are as follows: (s[:]) +// 1 : variable ID being declared +// 2 : the lower bound of the range of samplers in the space +// 3 : the upper bound (inclusive) of this range +// As opposed to when the s# is used in shader instructions, where the register +// must be D3D10_SB_OPERAND_INDEX_DIMENSION_2D, and the meaning of the index +// dimensions are as follows: (s[]): +// 1 : variable ID being used (matches dcl) +// 2 : absolute index of sampler within space (may be dynamically indexed) +// (2) a DWORD indicating the space index. +// +// ---------------------------------------------------------------------------- +typedef enum D3D10_SB_SAMPLER_MODE +{ + D3D10_SB_SAMPLER_MODE_DEFAULT = 0, + D3D10_SB_SAMPLER_MODE_COMPARISON = 1, + D3D10_SB_SAMPLER_MODE_MONO = 2, +} D3D10_SB_SAMPLER_MODE; + +#define D3D10_SB_SAMPLER_MODE_MASK 0x00007800 +#define D3D10_SB_SAMPLER_MODE_SHIFT 11 + +// DECODER MACRO: Find out if a Constant Buffer is going to be indexed or not +#define DECODE_D3D10_SB_SAMPLER_MODE(OpcodeToken0) ((D3D10_SB_SAMPLER_MODE)(((OpcodeToken0)&D3D10_SB_SAMPLER_MODE_MASK)>>D3D10_SB_SAMPLER_MODE_SHIFT)) + +// ENCODER MACRO: Generate a resource return type for a component +#define ENCODE_D3D10_SB_SAMPLER_MODE(SamplerMode) (((SamplerMode)<>D3D10_SB_INPUT_INTERPOLATION_MODE_SHIFT)) + +// ENCODER MACRO: Encode interpolation mode for a register. +#define ENCODE_D3D10_SB_INPUT_INTERPOLATION_MODE(InterpolationMode) (((InterpolationMode)<[:]) +// 1 : variable ID being declared +// 2 : the lower bound of the range of constant buffers in the space +// 3 : the upper bound (inclusive) of this range +// As opposed to when the cb#[] is used in shader instructions: (cb[][]) +// 1 : variable ID being used (matches dcl) +// 2 : absolute index of constant buffer within space (may be dynamically indexed) +// 3 : location of vector within constant buffer being referenced, +// which may also be dynamically indexed, with no access pattern flag required. +// (2) a DWORD indicating the size of the constant buffer as a count of 16-byte vectors. +// Each vector is 32-bit*4 elements == 128-bits == 16 bytes. +// If the size is specified as 0, the CB size is not known (any size CB +// can be bound to the slot). +// (3) a DWORD indicating the space index. +// +// ---------------------------------------------------------------------------- + +typedef enum D3D10_SB_CONSTANT_BUFFER_ACCESS_PATTERN +{ + D3D10_SB_CONSTANT_BUFFER_IMMEDIATE_INDEXED = 0, + D3D10_SB_CONSTANT_BUFFER_DYNAMIC_INDEXED = 1 +} D3D10_SB_CONSTANT_BUFFER_ACCESS_PATTERN; + +#define D3D10_SB_CONSTANT_BUFFER_ACCESS_PATTERN_MASK 0x00000800 +#define D3D10_SB_CONSTANT_BUFFER_ACCESS_PATTERN_SHIFT 11 + +// DECODER MACRO: Find out if a Constant Buffer is going to be indexed or not +#define DECODE_D3D10_SB_CONSTANT_BUFFER_ACCESS_PATTERN(OpcodeToken0) ((D3D10_SB_CONSTANT_BUFFER_ACCESS_PATTERN)(((OpcodeToken0)&D3D10_SB_CONSTANT_BUFFER_ACCESS_PATTERN_MASK)>>D3D10_SB_CONSTANT_BUFFER_ACCESS_PATTERN_SHIFT)) + +// ENCODER MACRO: Encode the access pattern for the Constant Buffer +#define ENCODE_D3D10_SB_D3D10_SB_CONSTANT_BUFFER_ACCESS_PATTERN(AccessPattern) (((AccessPattern)<>D3D10_SB_GS_INPUT_PRIMITIVE_SHIFT)) + +// ENCODER MACRO: Store primitive topology +// (D3D10_SB_PRIMITIVE enum) into a +// a primitive topology declaration token (OpcodeToken0) +#define ENCODE_D3D10_SB_GS_INPUT_PRIMITIVE(Prim) (((Prim)<>D3D10_SB_GS_OUTPUT_PRIMITIVE_TOPOLOGY_SHIFT)) + +// ENCODER MACRO: Store primitive topology +// (D3D10_SB_PRIMITIVE_TOPOLOGY enum) into a +// a primitive topology declaration token (OpcodeToken0) +#define ENCODE_D3D10_SB_GS_OUTPUT_PRIMITIVE_TOPOLOGY(PrimTopology) (((PrimTopology)<>D3D11_SB_INPUT_CONTROL_POINT_COUNT_SHIFT)) + +// ENCODER MACRO: Store input control point count into a declaration token +#define ENCODE_D3D11_SB_INPUT_CONTROL_POINT_COUNT(Count) (((Count)<>D3D11_SB_OUTPUT_CONTROL_POINT_COUNT_SHIFT)) + +// ENCODER MACRO: Store output control point count into a declaration token +#define ENCODE_D3D11_SB_OUTPUT_CONTROL_POINT_COUNT(Count) (((Count)<>D3D11_SB_TESS_DOMAIN_SHIFT)) + +// ENCODER MACRO: Store tessellator domain +// (D3D11_SB_TESSELLATOR_DOMAIN enum) into a +// a tessellator domain declaration token (OpcodeToken0) +#define ENCODE_D3D11_SB_TESS_DOMAIN(Domain) (((Domain)<>D3D11_SB_TESS_PARTITIONING_SHIFT)) + +// ENCODER MACRO: Store tessellator partitioning +// (D3D11_SB_TESSELLATOR_PARTITIONING enum) into a +// a tessellator partitioning declaration token (OpcodeToken0) +#define ENCODE_D3D11_SB_TESS_PARTITIONING(Partitioning) (((Partitioning)<>D3D11_SB_TESS_OUTPUT_PRIMITIVE_SHIFT)) + +// ENCODER MACRO: Store tessellator output primitive +// (D3D11_SB_TESSELLATOR_OUTPUT_PRIMITIVE enum) into a +// a tessellator output primitive declaration token (OpcodeToken0) +#define ENCODE_D3D11_SB_TESS_OUTPUT_PRIMITIVE(OutputPrimitive) (((OutputPrimitive)<>D3D10_SB_INSTRUCTION_RETURN_TYPE_SHIFT)) +// ENCODER MACRO: Encode the return type for instructions +// in the opcode specific control range of OpcodeToken0 +#define ENCODE_D3D10_SB_INSTRUCTION_RETURN_TYPE(ReturnType) (((ReturnType)<>D3D11_SB_INTERFACE_INDEXED_BIT_SHIFT) ? true : false) +#define ENCODE_D3D11_SB_INTERFACE_INDEXED_BIT(IndexedBit) (((IndexedBit)<>D3D11_SB_INTERFACE_TABLE_LENGTH_SHIFT)) +#define ENCODE_D3D11_SB_INTERFACE_TABLE_LENGTH(TableLength) (((TableLength)<>D3D11_SB_INTERFACE_ARRAY_LENGTH_SHIFT)) +#define ENCODE_D3D11_SB_INTERFACE_ARRAY_LENGTH(ArrayLength) (((ArrayLength)<[:]) +// 1 : variable ID being declared +// 2 : the lower bound of the range of UAV's in the space +// 3 : the upper bound (inclusive) of this range +// As opposed to when the u# is used in shader instructions, where the register +// must be D3D10_SB_OPERAND_INDEX_DIMENSION_2D, and the meaning of the index +// dimensions are as follows: (u[]): +// 1 : variable ID being used (matches dcl) +// 2 : absolute index of uav within space (may be dynamically indexed) +// (2) a Resource Return Type token (ResourceReturnTypeToken) +// (3) a DWORD indicating the space index. +// +// ---------------------------------------------------------------------------- +// UAV access scope flags +#define D3D11_SB_GLOBALLY_COHERENT_ACCESS 0x00010000 +#define D3D11_SB_ACCESS_COHERENCY_MASK 0x00010000 + +// DECODER MACRO: Retrieve flags for sync instruction from OpcodeToken0. +#define DECODE_D3D11_SB_ACCESS_COHERENCY_FLAGS(OperandToken0) ((OperandToken0)&D3D11_SB_ACCESS_COHERENCY_MASK) + +// ENCODER MACRO: Given a set of sync instruciton flags, encode them in OpcodeToken0. +#define ENCODE_D3D11_SB_ACCESS_COHERENCY_FLAGS(Flags) ((Flags)&D3D11_SB_ACCESS_COHERENCY_MASK) + +// Additional UAV access flags +#define D3D11_SB_RASTERIZER_ORDERED_ACCESS 0x00020000 + +// Resource flags mask. Use to retrieve all resource flags, including the order preserving counter. +#define D3D11_SB_RESOURCE_FLAGS_MASK (D3D11_SB_GLOBALLY_COHERENT_ACCESS|D3D11_SB_RASTERIZER_ORDERED_ACCESS|D3D11_SB_UAV_HAS_ORDER_PRESERVING_COUNTER) + +// DECODER MACRO: Retrieve UAV access flags for from OpcodeToken0. +#define DECODE_D3D11_SB_RESOURCE_FLAGS(OperandToken0) ((OperandToken0)&D3D11_SB_RESOURCE_FLAGS_MASK) + +// ENCODER MACRO: Given UAV access flags, encode them in OpcodeToken0. +#define ENCODE_D3D11_SB_RESOURCE_FLAGS(Flags) ((Flags)&D3D11_SB_RESOURCE_FLAGS_MASK) + +// ---------------------------------------------------------------------------- +// Raw Unordered Access View Declaration +// +// OpcodeToken0: +// +// [10:00] D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW +// [15:11] Ignored, 0 +// [16:16] D3D11_SB_GLOBALLY_COHERENT_ACCESS or 0 (LOCALLY_COHERENT) +// [17:17] D3D11_SB_RASTERIZER_ORDERED_ACCESS or 0 +// [23:18] Ignored, 0 +// [30:24] Instruction length in DWORDs including the opcode token. +// [31] 0 normally. 1 if extended operand definition, meaning next DWORD +// contains extended operand description. This dcl is currently not +// extended. +// +// OpcodeToken0 is followed by 1 operand on Shader Models 4.0 through 5.0: +// (1) an operand, starting with OperandToken0, defining which +// u# register (D3D11_SB_OPERAND_TYPE_UNORDERED_ACCESS_VIEW) is being declared. +// +// OpcodeToken0 is followed by 2 operands on Shader Model 5.1 and later: +// (1) an operand, starting with OperandToken0, defining which +// u# register (D3D11_SB_OPERAND_TYPE_UNORDERED_ACCESS_VIEW) is being declared. +// The indexing dimension for the register must be D3D10_SB_OPERAND_INDEX_DIMENSION_3D, +// and the meaning of the index dimensions are as follows: (u[:]) +// 1 : variable ID being declared +// 2 : the lower bound of the range of UAV's in the space +// 3 : the upper bound (inclusive) of this range +// As opposed to when the u# is used in shader instructions, where the register +// must be D3D10_SB_OPERAND_INDEX_DIMENSION_2D, and the meaning of the index +// dimensions are as follows: (u[]): +// 1 : variable ID being used (matches dcl) +// 2 : absolute index of uav within space (may be dynamically indexed) +// (2) a DWORD indicating the space index. +// +// ---------------------------------------------------------------------------- + +// ---------------------------------------------------------------------------- +// Structured Unordered Access View Declaration +// +// OpcodeToken0: +// +// [10:00] D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED +// [15:11] Ignored, 0 +// [16:16] D3D11_SB_GLOBALLY_COHERENT_ACCESS or 0 (LOCALLY_COHERENT) +// [17:17] D3D11_SB_RASTERIZER_ORDERED_ACCESS or 0 +// [22:18] Ignored, 0 +// [23:23] D3D11_SB_UAV_HAS_ORDER_PRESERVING_COUNTER or 0 +// +// The presence of this flag means that if a UAV is bound to the +// corresponding slot, it must have been created with +// D3D11_BUFFER_UAV_FLAG_COUNTER at the API. Also, the shader +// can contain either imm_atomic_alloc or _consume instructions +// operating on the given UAV. +// +// If this flag is not present, the shader can still contain +// either imm_atomic_alloc or imm_atomic_consume instructions for +// this UAV. But if such instructions are present in this case, +// and a UAV is bound corresponding slot, it must have been created +// with the D3D11_BUFFER_UAV_FLAG_APPEND flag at the API. +// Append buffers have a counter as well, but values returned +// to the shader are only valid for the lifetime of the shader +// invocation. +// +// [30:24] Instruction length in DWORDs including the opcode token. +// [31] 0 normally. 1 if extended operand definition, meaning next DWORD +// contains extended operand description. This dcl is currently not +// extended. +// +// OpcodeToken0 is followed by 2 operands: +// (1) an operand, starting with OperandToken0, defining which +// u# register (D3D11_SB_OPERAND_TYPE_UNORDERED_ACCESS_VIEW) is +// being declared. +// (2) a DWORD indicating UINT32 byte stride +// +// OpcodeToken0 is followed by 3 operands on Shader Model 5.1 and later: +// (1) an operand, starting with OperandToken0, defining which +// u# register (D3D11_SB_OPERAND_TYPE_UNORDERED_ACCESS_VIEW) is being declared. +// The indexing dimension for the register must be D3D10_SB_OPERAND_INDEX_DIMENSION_3D, +// and the meaning of the index dimensions are as follows: (u[:]) +// 1 : variable ID being declared +// 2 : the lower bound of the range of UAV's in the space +// 3 : the upper bound (inclusive) of this range +// As opposed to when the u# is used in shader instructions, where the register +// must be D3D10_SB_OPERAND_INDEX_DIMENSION_2D, and the meaning of the index +// dimensions are as follows: (u[]): +// 1 : variable ID being used (matches dcl) +// 2 : absolute index of uav within space (may be dynamically indexed) +// (2) a DWORD indicating UINT32 byte stride +// (3) a DWORD indicating the space index. +// +// ---------------------------------------------------------------------------- +// UAV flags +#define D3D11_SB_UAV_HAS_ORDER_PRESERVING_COUNTER 0x00800000 +#define D3D11_SB_UAV_FLAGS_MASK 0x00800000 + +// DECODER MACRO: Retrieve flags about UAV from OpcodeToken0. +#define DECODE_D3D11_SB_UAV_FLAGS(OperandToken0) ((OperandToken0)&D3D11_SB_UAV_FLAGS_MASK) + +// ENCODER MACRO: Given a set of UAV flags, encode them in OpcodeToken0. +#define ENCODE_D3D11_SB_UAV_FLAGS(Flags) ((Flags)&D3D11_SB_UAV_FLAGS_MASK) + +// ---------------------------------------------------------------------------- +// Raw Thread Group Shared Memory Declaration +// +// OpcodeToken0: +// +// [10:00] D3D11_SB_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW +// [23:11] Ignored, 0 +// [30:24] Instruction length in DWORDs including the opcode token. +// [31] 0 normally. 1 if extended operand definition, meaning next DWORD +// contains extended operand description. This dcl is currently not +// extended. +// +// OpcodeToken0 is followed by 2 operands: +// (1) an operand, starting with OperandToken0, defining which +// g# register (D3D11_SB_OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) is being declared. +// (2) a DWORD indicating the byte count, which must be a multiple of 4. +// +// ---------------------------------------------------------------------------- + +// ---------------------------------------------------------------------------- +// Structured Thread Group Shared Memory Declaration +// +// OpcodeToken0: +// +// [10:00] D3D11_SB_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED +// [23:11] Ignored, 0 +// [30:24] Instruction length in DWORDs including the opcode token. +// [31] 0 normally. 1 if extended operand definition, meaning next DWORD +// contains extended operand description. This dcl is currently not +// extended. +// +// OpcodeToken0 is followed by 3 operands: +// (1) an operand, starting with OperandToken0, defining which +// g# register (D3D11_SB_OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) is +// being declared. +// (2) a DWORD indicating UINT32 struct byte stride +// (3) a DWORD indicating UINT32 struct count +// +// ---------------------------------------------------------------------------- + +// ---------------------------------------------------------------------------- +// Raw Shader Resource View Declaration +// +// OpcodeToken0: +// +// [10:00] D3D11_SB_OPCODE_DCL_RESOURCE_RAW +// [23:11] Ignored, 0 +// [30:24] Instruction length in DWORDs including the opcode token. +// [31] 0 normally. 1 if extended operand definition, meaning next DWORD +// contains extended operand description. This dcl is currently not +// extended. +// +// OpcodeToken0 is followed by 1 operand: +// (1) an operand, starting with OperandToken0, defining which +// t# register (D3D10_SB_OPERAND_TYPE_RESOURCE) is being declared. +// +// OpcodeToken0 is followed by 2 operands on Shader Model 5.1 and later: +// (1) an operand, starting with OperandToken0, defining which +// t# register (D3D10_SB_OPERAND_TYPE_RESOURCE) is being declared. +// The indexing dimension for the register must be D3D10_SB_OPERAND_INDEX_DIMENSION_3D, +// and the meaning of the index dimensions are as follows: (t[:]) +// 1 : variable ID being declared +// 2 : the lower bound of the range of resources in the space +// 3 : the upper bound (inclusive) of this range +// As opposed to when the t# is used in shader instructions, where the register +// must be D3D10_SB_OPERAND_INDEX_DIMENSION_2D, and the meaning of the index +// dimensions are as follows: (t[]): +// 1 : variable ID being used (matches dcl) +// 2 : absolute index of resource within space (may be dynamically indexed) +// (2) a DWORD indicating the space index. +// +// ---------------------------------------------------------------------------- + +// ---------------------------------------------------------------------------- +// Structured Shader Resource View Declaration +// +// OpcodeToken0: +// +// [10:00] D3D11_SB_OPCODE_DCL_RESOURCE_STRUCTURED +// [23:11] Ignored, 0 +// [30:24] Instruction length in DWORDs including the opcode token. +// [31] 0 normally. 1 if extended operand definition, meaning next DWORD +// contains extended operand description. This dcl is currently not +// extended. +// +// OpcodeToken0 is followed by 2 operands: +// (1) an operand, starting with OperandToken0, defining which +// g# register (D3D10_SB_OPERAND_TYPE_RESOURCE) is +// being declared. +// (2) a DWORD indicating UINT32 struct byte stride +// +// OpcodeToken0 is followed by 3 operands on Shader Model 5.1 and later: +// (1) an operand, starting with OperandToken0, defining which +// t# register (D3D10_SB_OPERAND_TYPE_RESOURCE) is being declared. +// The indexing dimension for the register must be D3D10_SB_OPERAND_INDEX_DIMENSION_3D, +// and the meaning of the index dimensions are as follows: (t[:]) +// 1 : variable ID being declared +// 2 : the lower bound of the range of resources in the space +// 3 : the upper bound (inclusive) of this range +// As opposed to when the t# is used in shader instructions, where the register +// must be D3D10_SB_OPERAND_INDEX_DIMENSION_2D, and the meaning of the index +// dimensions are as follows: (t[]): +// 1 : variable ID being used (matches dcl) +// 2 : absolute index of resource within space (may be dynamically indexed) +// (2) a DWORD indicating UINT32 struct byte stride +// (3) a DWORD indicating the space index. +// +// ---------------------------------------------------------------------------- + +#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) */ +#pragma endregion diff --git a/WickedEngine/Utility/dx12/d3d12.h b/WickedEngine/Utility/dx12/d3d12.h index 78ee1f4b5..85382b19f 100644 --- a/WickedEngine/Utility/dx12/d3d12.h +++ b/WickedEngine/Utility/dx12/d3d12.h @@ -437,6 +437,13 @@ typedef interface ID3D12Device11 ID3D12Device11; #endif /* __ID3D12Device11_FWD_DEFINED__ */ +#ifndef __ID3D12Device12_FWD_DEFINED__ +#define __ID3D12Device12_FWD_DEFINED__ +typedef interface ID3D12Device12 ID3D12Device12; + +#endif /* __ID3D12Device12_FWD_DEFINED__ */ + + #ifndef __ID3D12VirtualizationGuestDevice_FWD_DEFINED__ #define __ID3D12VirtualizationGuestDevice_FWD_DEFINED__ typedef interface ID3D12VirtualizationGuestDevice ID3D12VirtualizationGuestDevice; @@ -514,6 +521,13 @@ typedef interface ID3D12GraphicsCommandList9 ID3D12GraphicsCommandList9; #endif /* __ID3D12GraphicsCommandList9_FWD_DEFINED__ */ +#ifndef __ID3D12DSRDeviceFactory_FWD_DEFINED__ +#define __ID3D12DSRDeviceFactory_FWD_DEFINED__ +typedef interface ID3D12DSRDeviceFactory ID3D12DSRDeviceFactory; + +#endif /* __ID3D12DSRDeviceFactory_FWD_DEFINED__ */ + + /* header files for imported files */ #include "oaidl.h" #include "ocidl.h" @@ -1046,7 +1060,7 @@ extern "C"{ #define D3D12_PIXEL_ADDRESS_RANGE_BIT_COUNT ( 15 ) -#define D3D12_PREVIEW_SDK_VERSION ( 707 ) +#define D3D12_PREVIEW_SDK_VERSION ( 710 ) #define D3D12_PRE_SCISSOR_PIXEL_ADDRESS_RANGE_BIT_COUNT ( 16 ) @@ -1179,7 +1193,7 @@ extern "C"{ #define D3D12_RS_SET_SHADING_RATE_COMBINER_COUNT ( 2 ) -#define D3D12_SDK_VERSION ( 608 ) +#define D3D12_SDK_VERSION ( 610 ) #define D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES ( 32 ) @@ -1664,6 +1678,29 @@ typedef struct D3D12_RASTERIZER_DESC1 D3D12_CONSERVATIVE_RASTERIZATION_MODE ConservativeRaster; } D3D12_RASTERIZER_DESC1; +typedef +enum D3D12_LINE_RASTERIZATION_MODE + { + D3D12_LINE_RASTERIZATION_MODE_ALIASED = 0, + D3D12_LINE_RASTERIZATION_MODE_ALPHA_ANTIALIASED = ( D3D12_LINE_RASTERIZATION_MODE_ALIASED + 1 ) , + D3D12_LINE_RASTERIZATION_MODE_QUADRILATERAL_WIDE = ( D3D12_LINE_RASTERIZATION_MODE_ALPHA_ANTIALIASED + 1 ) , + D3D12_LINE_RASTERIZATION_MODE_QUADRILATERAL_NARROW = ( D3D12_LINE_RASTERIZATION_MODE_QUADRILATERAL_WIDE + 1 ) + } D3D12_LINE_RASTERIZATION_MODE; + +typedef struct D3D12_RASTERIZER_DESC2 + { + D3D12_FILL_MODE FillMode; + D3D12_CULL_MODE CullMode; + BOOL FrontCounterClockwise; + FLOAT DepthBias; + FLOAT DepthBiasClamp; + FLOAT SlopeScaledDepthBias; + BOOL DepthClipEnable; + D3D12_LINE_RASTERIZATION_MODE LineRasterizationMode; + UINT ForcedSampleCount; + D3D12_CONSERVATIVE_RASTERIZATION_MODE ConservativeRaster; + } D3D12_RASTERIZER_DESC2; + extern RPC_IF_HANDLE __MIDL_itf_d3d12_0000_0000_v0_0_c_ifspec; @@ -2161,7 +2198,8 @@ enum D3D12_PIPELINE_STATE_SUBOBJECT_TYPE D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_MS = 25, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL2 = 26, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER1 = 27, - D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_MAX_VALID = ( D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER1 + 1 ) + D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER2 = 28, + D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_MAX_VALID = ( D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER2 + 1 ) } D3D12_PIPELINE_STATE_SUBOBJECT_TYPE; typedef @@ -2202,7 +2240,10 @@ enum D3D12_FEATURE D3D12_FEATURE_D3D12_OPTIONS13 = 42, D3D12_FEATURE_D3D12_OPTIONS14 = 43, D3D12_FEATURE_D3D12_OPTIONS15 = 44, - D3D12_FEATURE_D3D12_OPTIONS16 = 45 + D3D12_FEATURE_D3D12_OPTIONS16 = 45, + D3D12_FEATURE_D3D12_OPTIONS17 = 46, + D3D12_FEATURE_D3D12_OPTIONS18 = 47, + D3D12_FEATURE_D3D12_OPTIONS19 = 48 } D3D12_FEATURE; typedef @@ -2378,7 +2419,8 @@ enum D3D_ROOT_SIGNATURE_VERSION { D3D_ROOT_SIGNATURE_VERSION_1 = 0x1, D3D_ROOT_SIGNATURE_VERSION_1_0 = 0x1, - D3D_ROOT_SIGNATURE_VERSION_1_1 = 0x2 + D3D_ROOT_SIGNATURE_VERSION_1_1 = 0x2, + D3D_ROOT_SIGNATURE_VERSION_1_2 = 0x3 } D3D_ROOT_SIGNATURE_VERSION; typedef struct D3D12_FEATURE_DATA_ROOT_SIGNATURE @@ -2697,9 +2739,34 @@ typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS15 typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS16 { _Out_ BOOL DynamicDepthBiasSupported; - _Out_ BOOL Reserved; + _Out_ BOOL GPUUploadHeapSupported; } D3D12_FEATURE_DATA_D3D12_OPTIONS16; +typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS17 + { + _Out_ BOOL NonNormalizedCoordinateSamplersSupported; + _Out_ BOOL ManualWriteTrackingResourceSupported; + } D3D12_FEATURE_DATA_D3D12_OPTIONS17; + +typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS18 + { + _Out_ BOOL RenderPassesValid; + } D3D12_FEATURE_DATA_D3D12_OPTIONS18; + +typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS19 + { + BOOL MismatchingOutputDimensionsSupported; + UINT SupportedSampleCountsWithNoOutputs; + BOOL PointSamplingAddressesNeverRoundUp; + BOOL RasterizerDesc2Supported; + BOOL NarrowQuadrilateralLinesSupported; + BOOL AnisoFilterWithPointMipSupported; + UINT MaxSamplerDescriptorHeapSize; + UINT MaxSamplerDescriptorHeapSizeWithStaticSamplers; + UINT MaxViewDescriptorHeapSize; + _Out_ BOOL ComputeOnlyCustomHeapSupported; + } D3D12_FEATURE_DATA_D3D12_OPTIONS19; + typedef struct D3D12_RESOURCE_ALLOCATION_INFO { UINT64 SizeInBytes; @@ -2719,7 +2786,8 @@ enum D3D12_HEAP_TYPE D3D12_HEAP_TYPE_DEFAULT = 1, D3D12_HEAP_TYPE_UPLOAD = 2, D3D12_HEAP_TYPE_READBACK = 3, - D3D12_HEAP_TYPE_CUSTOM = 4 + D3D12_HEAP_TYPE_CUSTOM = 4, + D3D12_HEAP_TYPE_GPU_UPLOAD = 5 } D3D12_HEAP_TYPE; typedef @@ -2763,6 +2831,7 @@ enum D3D12_HEAP_FLAGS D3D12_HEAP_FLAG_ALLOW_SHADER_ATOMICS = 0x400, D3D12_HEAP_FLAG_CREATE_NOT_RESIDENT = 0x800, D3D12_HEAP_FLAG_CREATE_NOT_ZEROED = 0x1000, + D3D12_HEAP_FLAG_TOOLS_USE_MANUAL_WRITE_TRACKING = 0x2000, D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES = 0, D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS = 0xc0, D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES = 0x44, @@ -3275,6 +3344,7 @@ enum D3D12_FILTER D3D12_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x11, D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT = 0x14, D3D12_FILTER_MIN_MAG_MIP_LINEAR = 0x15, + D3D12_FILTER_MIN_MAG_ANISOTROPIC_MIP_POINT = 0x54, D3D12_FILTER_ANISOTROPIC = 0x55, D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT = 0x80, D3D12_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR = 0x81, @@ -3284,6 +3354,7 @@ enum D3D12_FILTER D3D12_FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x91, D3D12_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT = 0x94, D3D12_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR = 0x95, + D3D12_FILTER_COMPARISON_MIN_MAG_ANISOTROPIC_MIP_POINT = 0xd4, D3D12_FILTER_COMPARISON_ANISOTROPIC = 0xd5, D3D12_FILTER_MINIMUM_MIN_MAG_MIP_POINT = 0x100, D3D12_FILTER_MINIMUM_MIN_MAG_POINT_MIP_LINEAR = 0x101, @@ -3293,6 +3364,7 @@ enum D3D12_FILTER D3D12_FILTER_MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x111, D3D12_FILTER_MINIMUM_MIN_MAG_LINEAR_MIP_POINT = 0x114, D3D12_FILTER_MINIMUM_MIN_MAG_MIP_LINEAR = 0x115, + D3D12_FILTER_MINIMUM_MIN_MAG_ANISOTROPIC_MIP_POINT = 0x154, D3D12_FILTER_MINIMUM_ANISOTROPIC = 0x155, D3D12_FILTER_MAXIMUM_MIN_MAG_MIP_POINT = 0x180, D3D12_FILTER_MAXIMUM_MIN_MAG_POINT_MIP_LINEAR = 0x181, @@ -3302,6 +3374,7 @@ enum D3D12_FILTER D3D12_FILTER_MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x191, D3D12_FILTER_MAXIMUM_MIN_MAG_LINEAR_MIP_POINT = 0x194, D3D12_FILTER_MAXIMUM_MIN_MAG_MIP_LINEAR = 0x195, + D3D12_FILTER_MAXIMUM_MIN_MAG_ANISOTROPIC_MIP_POINT = 0x1d4, D3D12_FILTER_MAXIMUM_ANISOTROPIC = 0x1d5 } D3D12_FILTER; @@ -3348,6 +3421,13 @@ enum D3D12_FILTER_REDUCTION_TYPE D3D12_FILTER_TYPE_LINEAR, \ D3D12_FILTER_TYPE_LINEAR, \ reduction ) ) ) +#define D3D12_ENCODE_MIN_MAG_ANISOTROPIC_MIP_POINT_FILTER( reduction ) \ + ( ( D3D12_FILTER ) ( \ + D3D12_ANISOTROPIC_FILTERING_BIT | \ + D3D12_ENCODE_BASIC_FILTER( D3D12_FILTER_TYPE_LINEAR, \ + D3D12_FILTER_TYPE_LINEAR, \ + D3D12_FILTER_TYPE_POINT, \ + reduction ) ) ) #define D3D12_DECODE_MIN_FILTER( D3D12Filter ) \ ( ( D3D12_FILTER_TYPE ) \ ( ( ( D3D12Filter ) >> D3D12_MIN_FILTER_SHIFT ) & D3D12_FILTER_TYPE_MASK ) ) @@ -3365,8 +3445,7 @@ enum D3D12_FILTER_REDUCTION_TYPE #define D3D12_DECODE_IS_ANISOTROPIC_FILTER( D3D12Filter ) \ ( ( ( D3D12Filter ) & D3D12_ANISOTROPIC_FILTERING_BIT ) && \ ( D3D12_FILTER_TYPE_LINEAR == D3D12_DECODE_MIN_FILTER( D3D12Filter ) ) && \ - ( D3D12_FILTER_TYPE_LINEAR == D3D12_DECODE_MAG_FILTER( D3D12Filter ) ) && \ - ( D3D12_FILTER_TYPE_LINEAR == D3D12_DECODE_MIP_FILTER( D3D12Filter ) ) ) + ( D3D12_FILTER_TYPE_LINEAR == D3D12_DECODE_MAG_FILTER( D3D12Filter ) ) ) typedef enum D3D12_TEXTURE_ADDRESS_MODE { @@ -3395,7 +3474,8 @@ typedef enum D3D12_SAMPLER_FLAGS { D3D12_SAMPLER_FLAG_NONE = 0, - D3D12_SAMPLER_FLAG_UINT_BORDER_COLOR = 0x1 + D3D12_SAMPLER_FLAG_UINT_BORDER_COLOR = 0x1, + D3D12_SAMPLER_FLAG_NON_NORMALIZED_COORDINATES = 0x2 } D3D12_SAMPLER_FLAGS; DEFINE_ENUM_FLAG_OPERATORS( D3D12_SAMPLER_FLAGS ); @@ -3825,6 +3905,24 @@ typedef struct D3D12_STATIC_SAMPLER_DESC D3D12_SHADER_VISIBILITY ShaderVisibility; } D3D12_STATIC_SAMPLER_DESC; +typedef struct D3D12_STATIC_SAMPLER_DESC1 + { + D3D12_FILTER Filter; + D3D12_TEXTURE_ADDRESS_MODE AddressU; + D3D12_TEXTURE_ADDRESS_MODE AddressV; + D3D12_TEXTURE_ADDRESS_MODE AddressW; + FLOAT MipLODBias; + UINT MaxAnisotropy; + D3D12_COMPARISON_FUNC ComparisonFunc; + D3D12_STATIC_BORDER_COLOR BorderColor; + FLOAT MinLOD; + FLOAT MaxLOD; + UINT ShaderRegister; + UINT RegisterSpace; + D3D12_SHADER_VISIBILITY ShaderVisibility; + D3D12_SAMPLER_FLAGS Flags; + } D3D12_STATIC_SAMPLER_DESC1; + typedef struct D3D12_ROOT_SIGNATURE_DESC { UINT NumParameters; @@ -3900,6 +3998,15 @@ typedef struct D3D12_ROOT_SIGNATURE_DESC1 D3D12_ROOT_SIGNATURE_FLAGS Flags; } D3D12_ROOT_SIGNATURE_DESC1; +typedef struct D3D12_ROOT_SIGNATURE_DESC2 + { + UINT NumParameters; + _Field_size_full_(NumParameters) const D3D12_ROOT_PARAMETER1 *pParameters; + UINT NumStaticSamplers; + _Field_size_full_(NumStaticSamplers) const D3D12_STATIC_SAMPLER_DESC1 *pStaticSamplers; + D3D12_ROOT_SIGNATURE_FLAGS Flags; + } D3D12_ROOT_SIGNATURE_DESC2; + typedef struct D3D12_VERSIONED_ROOT_SIGNATURE_DESC { D3D_ROOT_SIGNATURE_VERSION Version; @@ -3907,6 +4014,7 @@ typedef struct D3D12_VERSIONED_ROOT_SIGNATURE_DESC { D3D12_ROOT_SIGNATURE_DESC Desc_1_0; D3D12_ROOT_SIGNATURE_DESC1 Desc_1_1; + D3D12_ROOT_SIGNATURE_DESC2 Desc_1_2; } ; } D3D12_VERSIONED_ROOT_SIGNATURE_DESC; @@ -14792,7 +14900,8 @@ enum D3D12_AUTO_BREADCRUMB_OP D3D12_AUTO_BREADCRUMB_OP_EXECUTEEXTENSIONCOMMAND = 41, D3D12_AUTO_BREADCRUMB_OP_DISPATCHMESH = 42, D3D12_AUTO_BREADCRUMB_OP_ENCODEFRAME = 43, - D3D12_AUTO_BREADCRUMB_OP_RESOLVEENCODEROUTPUTMETADATA = 44 + D3D12_AUTO_BREADCRUMB_OP_RESOLVEENCODEROUTPUTMETADATA = 44, + D3D12_AUTO_BREADCRUMB_OP_BARRIER = 45 } D3D12_AUTO_BREADCRUMB_OP; typedef struct D3D12_AUTO_BREADCRUMB_NODE @@ -19840,7 +19949,10 @@ enum D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_DISCARD = 0, D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE = ( D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_DISCARD + 1 ) , D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR = ( D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE + 1 ) , - D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_NO_ACCESS = ( D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR + 1 ) + D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_NO_ACCESS = ( D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR + 1 ) , + D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE_LOCAL_RENDER = ( D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_NO_ACCESS + 1 ) , + D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE_LOCAL_SRV = ( D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE_LOCAL_RENDER + 1 ) , + D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE_LOCAL_UAV = ( D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE_LOCAL_SRV + 1 ) } D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE; typedef struct D3D12_RENDER_PASS_BEGINNING_ACCESS_CLEAR_PARAMETERS @@ -19848,12 +19960,19 @@ typedef struct D3D12_RENDER_PASS_BEGINNING_ACCESS_CLEAR_PARAMETERS D3D12_CLEAR_VALUE ClearValue; } D3D12_RENDER_PASS_BEGINNING_ACCESS_CLEAR_PARAMETERS; +typedef struct D3D12_RENDER_PASS_BEGINNING_ACCESS_PRESERVE_LOCAL_PARAMETERS + { + UINT AdditionalWidth; + UINT AdditionalHeight; + } D3D12_RENDER_PASS_BEGINNING_ACCESS_PRESERVE_LOCAL_PARAMETERS; + typedef struct D3D12_RENDER_PASS_BEGINNING_ACCESS { D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE Type; union { D3D12_RENDER_PASS_BEGINNING_ACCESS_CLEAR_PARAMETERS Clear; + D3D12_RENDER_PASS_BEGINNING_ACCESS_PRESERVE_LOCAL_PARAMETERS PreserveLocal; } ; } D3D12_RENDER_PASS_BEGINNING_ACCESS; @@ -19863,7 +19982,10 @@ enum D3D12_RENDER_PASS_ENDING_ACCESS_TYPE D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_DISCARD = 0, D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE = ( D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_DISCARD + 1 ) , D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_RESOLVE = ( D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE + 1 ) , - D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_NO_ACCESS = ( D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_RESOLVE + 1 ) + D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_NO_ACCESS = ( D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_RESOLVE + 1 ) , + D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE_LOCAL_RENDER = ( D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_NO_ACCESS + 1 ) , + D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE_LOCAL_SRV = ( D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE_LOCAL_RENDER + 1 ) , + D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE_LOCAL_UAV = ( D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE_LOCAL_SRV + 1 ) } D3D12_RENDER_PASS_ENDING_ACCESS_TYPE; typedef struct D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_SUBRESOURCE_PARAMETERS @@ -19886,12 +20008,19 @@ typedef struct D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_PARAMETERS BOOL PreserveResolveSource; } D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_PARAMETERS; +typedef struct D3D12_RENDER_PASS_ENDING_ACCESS_PRESERVE_LOCAL_PARAMETERS + { + UINT AdditionalWidth; + UINT AdditionalHeight; + } D3D12_RENDER_PASS_ENDING_ACCESS_PRESERVE_LOCAL_PARAMETERS; + typedef struct D3D12_RENDER_PASS_ENDING_ACCESS { D3D12_RENDER_PASS_ENDING_ACCESS_TYPE Type; union { D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_PARAMETERS Resolve; + D3D12_RENDER_PASS_ENDING_ACCESS_PRESERVE_LOCAL_PARAMETERS PreserveLocal; } ; } D3D12_RENDER_PASS_ENDING_ACCESS; @@ -19917,7 +20046,9 @@ enum D3D12_RENDER_PASS_FLAGS D3D12_RENDER_PASS_FLAG_NONE = 0, D3D12_RENDER_PASS_FLAG_ALLOW_UAV_WRITES = 0x1, D3D12_RENDER_PASS_FLAG_SUSPENDING_PASS = 0x2, - D3D12_RENDER_PASS_FLAG_RESUMING_PASS = 0x4 + D3D12_RENDER_PASS_FLAG_RESUMING_PASS = 0x4, + D3D12_RENDER_PASS_FLAG_BIND_READ_ONLY_DEPTH = 0x8, + D3D12_RENDER_PASS_FLAG_BIND_READ_ONLY_STENCIL = 0x10 } D3D12_RENDER_PASS_FLAGS; DEFINE_ENUM_FLAG_OPERATORS( D3D12_RENDER_PASS_FLAGS ); @@ -22331,7 +22462,7 @@ EXTERN_C const IID IID_ID3D12Device10; _In_opt_ const D3D12_CLEAR_VALUE *pOptimizedClearValue, _In_opt_ ID3D12ProtectedResourceSession *pProtectedSession, UINT32 NumCastableFormats, - _In_opt_count_(NumCastableFormats) DXGI_FORMAT *pCastableFormats, + _In_opt_count_(NumCastableFormats) const DXGI_FORMAT *pCastableFormats, REFIID riidResource, _COM_Outptr_opt_ void **ppvResource) = 0; @@ -22342,7 +22473,7 @@ EXTERN_C const IID IID_ID3D12Device10; D3D12_BARRIER_LAYOUT InitialLayout, _In_opt_ const D3D12_CLEAR_VALUE *pOptimizedClearValue, UINT32 NumCastableFormats, - _In_opt_count_(NumCastableFormats) DXGI_FORMAT *pCastableFormats, + _In_opt_count_(NumCastableFormats) const DXGI_FORMAT *pCastableFormats, REFIID riid, _COM_Outptr_opt_ void **ppvResource) = 0; @@ -22352,7 +22483,7 @@ EXTERN_C const IID IID_ID3D12Device10; _In_opt_ const D3D12_CLEAR_VALUE *pOptimizedClearValue, _In_opt_ ID3D12ProtectedResourceSession *pProtectedSession, UINT32 NumCastableFormats, - _In_opt_count_(NumCastableFormats) DXGI_FORMAT *pCastableFormats, + _In_opt_count_(NumCastableFormats) const DXGI_FORMAT *pCastableFormats, REFIID riid, _COM_Outptr_opt_ void **ppvResource) = 0; @@ -23000,7 +23131,7 @@ EXTERN_C const IID IID_ID3D12Device10; _In_opt_ const D3D12_CLEAR_VALUE *pOptimizedClearValue, _In_opt_ ID3D12ProtectedResourceSession *pProtectedSession, UINT32 NumCastableFormats, - _In_opt_count_(NumCastableFormats) DXGI_FORMAT *pCastableFormats, + _In_opt_count_(NumCastableFormats) const DXGI_FORMAT *pCastableFormats, REFIID riidResource, _COM_Outptr_opt_ void **ppvResource); @@ -23013,7 +23144,7 @@ EXTERN_C const IID IID_ID3D12Device10; D3D12_BARRIER_LAYOUT InitialLayout, _In_opt_ const D3D12_CLEAR_VALUE *pOptimizedClearValue, UINT32 NumCastableFormats, - _In_opt_count_(NumCastableFormats) DXGI_FORMAT *pCastableFormats, + _In_opt_count_(NumCastableFormats) const DXGI_FORMAT *pCastableFormats, REFIID riid, _COM_Outptr_opt_ void **ppvResource); @@ -23025,7 +23156,7 @@ EXTERN_C const IID IID_ID3D12Device10; _In_opt_ const D3D12_CLEAR_VALUE *pOptimizedClearValue, _In_opt_ ID3D12ProtectedResourceSession *pProtectedSession, UINT32 NumCastableFormats, - _In_opt_count_(NumCastableFormats) DXGI_FORMAT *pCastableFormats, + _In_opt_count_(NumCastableFormats) const DXGI_FORMAT *pCastableFormats, REFIID riid, _COM_Outptr_opt_ void **ppvResource); @@ -23990,7 +24121,7 @@ EXTERN_C const IID IID_ID3D12Device11; _In_opt_ const D3D12_CLEAR_VALUE *pOptimizedClearValue, _In_opt_ ID3D12ProtectedResourceSession *pProtectedSession, UINT32 NumCastableFormats, - _In_opt_count_(NumCastableFormats) DXGI_FORMAT *pCastableFormats, + _In_opt_count_(NumCastableFormats) const DXGI_FORMAT *pCastableFormats, REFIID riidResource, _COM_Outptr_opt_ void **ppvResource); @@ -24003,7 +24134,7 @@ EXTERN_C const IID IID_ID3D12Device11; D3D12_BARRIER_LAYOUT InitialLayout, _In_opt_ const D3D12_CLEAR_VALUE *pOptimizedClearValue, UINT32 NumCastableFormats, - _In_opt_count_(NumCastableFormats) DXGI_FORMAT *pCastableFormats, + _In_opt_count_(NumCastableFormats) const DXGI_FORMAT *pCastableFormats, REFIID riid, _COM_Outptr_opt_ void **ppvResource); @@ -24015,7 +24146,7 @@ EXTERN_C const IID IID_ID3D12Device11; _In_opt_ const D3D12_CLEAR_VALUE *pOptimizedClearValue, _In_opt_ ID3D12ProtectedResourceSession *pProtectedSession, UINT32 NumCastableFormats, - _In_opt_count_(NumCastableFormats) DXGI_FORMAT *pCastableFormats, + _In_opt_count_(NumCastableFormats) const DXGI_FORMAT *pCastableFormats, REFIID riid, _COM_Outptr_opt_ void **ppvResource); @@ -24327,6 +24458,1054 @@ EXTERN_C const IID IID_ID3D12Device11; #endif /* __ID3D12Device11_INTERFACE_DEFINED__ */ +#ifndef __ID3D12Device12_INTERFACE_DEFINED__ +#define __ID3D12Device12_INTERFACE_DEFINED__ + +/* interface ID3D12Device12 */ +/* [unique][local][object][uuid] */ + + +EXTERN_C const IID IID_ID3D12Device12; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5af5c532-4c91-4cd0-b541-15a405395fc5") + ID3D12Device12 : public ID3D12Device11 + { + public: +#if defined(_MSC_VER) || !defined(_WIN32) + virtual D3D12_RESOURCE_ALLOCATION_INFO STDMETHODCALLTYPE GetResourceAllocationInfo3( + UINT visibleMask, + UINT numResourceDescs, + _In_reads_(numResourceDescs) const D3D12_RESOURCE_DESC1 *pResourceDescs, + _In_opt_count_(numResourceDescs) const UINT32 *pNumCastableFormats, + _In_opt_count_(numResourceDescs) const DXGI_FORMAT *const *ppCastableFormats, + _Out_writes_opt_(numResourceDescs) D3D12_RESOURCE_ALLOCATION_INFO1 *pResourceAllocationInfo1) = 0; +#else + virtual D3D12_RESOURCE_ALLOCATION_INFO *STDMETHODCALLTYPE GetResourceAllocationInfo3( + D3D12_RESOURCE_ALLOCATION_INFO * RetVal, + UINT visibleMask, + UINT numResourceDescs, + _In_reads_(numResourceDescs) const D3D12_RESOURCE_DESC1 *pResourceDescs, + _In_opt_count_(numResourceDescs) const UINT32 *pNumCastableFormats, + _In_opt_count_(numResourceDescs) const DXGI_FORMAT *const *ppCastableFormats, + _Out_writes_opt_(numResourceDescs) D3D12_RESOURCE_ALLOCATION_INFO1 *pResourceAllocationInfo1) = 0; +#endif + + }; + + +#else /* C style interface */ + + typedef struct ID3D12Device12Vtbl + { + BEGIN_INTERFACE + + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ID3D12Device12 * This, + REFIID riid, + _COM_Outptr_ void **ppvObject); + + DECLSPEC_XFGVIRT(IUnknown, AddRef) + ULONG ( STDMETHODCALLTYPE *AddRef )( + ID3D12Device12 * This); + + DECLSPEC_XFGVIRT(IUnknown, Release) + ULONG ( STDMETHODCALLTYPE *Release )( + ID3D12Device12 * This); + + DECLSPEC_XFGVIRT(ID3D12Object, GetPrivateData) + HRESULT ( STDMETHODCALLTYPE *GetPrivateData )( + ID3D12Device12 * This, + _In_ REFGUID guid, + _Inout_ UINT *pDataSize, + _Out_writes_bytes_opt_( *pDataSize ) void *pData); + + DECLSPEC_XFGVIRT(ID3D12Object, SetPrivateData) + HRESULT ( STDMETHODCALLTYPE *SetPrivateData )( + ID3D12Device12 * This, + _In_ REFGUID guid, + _In_ UINT DataSize, + _In_reads_bytes_opt_( DataSize ) const void *pData); + + DECLSPEC_XFGVIRT(ID3D12Object, SetPrivateDataInterface) + HRESULT ( STDMETHODCALLTYPE *SetPrivateDataInterface )( + ID3D12Device12 * This, + _In_ REFGUID guid, + _In_opt_ const IUnknown *pData); + + DECLSPEC_XFGVIRT(ID3D12Object, SetName) + HRESULT ( STDMETHODCALLTYPE *SetName )( + ID3D12Device12 * This, + _In_z_ LPCWSTR Name); + + DECLSPEC_XFGVIRT(ID3D12Device, GetNodeCount) + UINT ( STDMETHODCALLTYPE *GetNodeCount )( + ID3D12Device12 * This); + + DECLSPEC_XFGVIRT(ID3D12Device, CreateCommandQueue) + HRESULT ( STDMETHODCALLTYPE *CreateCommandQueue )( + ID3D12Device12 * This, + _In_ const D3D12_COMMAND_QUEUE_DESC *pDesc, + REFIID riid, + _COM_Outptr_ void **ppCommandQueue); + + DECLSPEC_XFGVIRT(ID3D12Device, CreateCommandAllocator) + HRESULT ( STDMETHODCALLTYPE *CreateCommandAllocator )( + ID3D12Device12 * This, + _In_ D3D12_COMMAND_LIST_TYPE type, + REFIID riid, + _COM_Outptr_ void **ppCommandAllocator); + + DECLSPEC_XFGVIRT(ID3D12Device, CreateGraphicsPipelineState) + HRESULT ( STDMETHODCALLTYPE *CreateGraphicsPipelineState )( + ID3D12Device12 * This, + _In_ const D3D12_GRAPHICS_PIPELINE_STATE_DESC *pDesc, + REFIID riid, + _COM_Outptr_ void **ppPipelineState); + + DECLSPEC_XFGVIRT(ID3D12Device, CreateComputePipelineState) + HRESULT ( STDMETHODCALLTYPE *CreateComputePipelineState )( + ID3D12Device12 * This, + _In_ const D3D12_COMPUTE_PIPELINE_STATE_DESC *pDesc, + REFIID riid, + _COM_Outptr_ void **ppPipelineState); + + DECLSPEC_XFGVIRT(ID3D12Device, CreateCommandList) + HRESULT ( STDMETHODCALLTYPE *CreateCommandList )( + ID3D12Device12 * This, + _In_ UINT nodeMask, + _In_ D3D12_COMMAND_LIST_TYPE type, + _In_ ID3D12CommandAllocator *pCommandAllocator, + _In_opt_ ID3D12PipelineState *pInitialState, + REFIID riid, + _COM_Outptr_ void **ppCommandList); + + DECLSPEC_XFGVIRT(ID3D12Device, CheckFeatureSupport) + HRESULT ( STDMETHODCALLTYPE *CheckFeatureSupport )( + ID3D12Device12 * This, + D3D12_FEATURE Feature, + _Inout_updates_bytes_(FeatureSupportDataSize) void *pFeatureSupportData, + UINT FeatureSupportDataSize); + + DECLSPEC_XFGVIRT(ID3D12Device, CreateDescriptorHeap) + HRESULT ( STDMETHODCALLTYPE *CreateDescriptorHeap )( + ID3D12Device12 * This, + _In_ const D3D12_DESCRIPTOR_HEAP_DESC *pDescriptorHeapDesc, + REFIID riid, + _COM_Outptr_ void **ppvHeap); + + DECLSPEC_XFGVIRT(ID3D12Device, GetDescriptorHandleIncrementSize) + UINT ( STDMETHODCALLTYPE *GetDescriptorHandleIncrementSize )( + ID3D12Device12 * This, + _In_ D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapType); + + DECLSPEC_XFGVIRT(ID3D12Device, CreateRootSignature) + HRESULT ( STDMETHODCALLTYPE *CreateRootSignature )( + ID3D12Device12 * This, + _In_ UINT nodeMask, + _In_reads_(blobLengthInBytes) const void *pBlobWithRootSignature, + _In_ SIZE_T blobLengthInBytes, + REFIID riid, + _COM_Outptr_ void **ppvRootSignature); + + DECLSPEC_XFGVIRT(ID3D12Device, CreateConstantBufferView) + void ( STDMETHODCALLTYPE *CreateConstantBufferView )( + ID3D12Device12 * This, + _In_opt_ const D3D12_CONSTANT_BUFFER_VIEW_DESC *pDesc, + _In_ D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor); + + DECLSPEC_XFGVIRT(ID3D12Device, CreateShaderResourceView) + void ( STDMETHODCALLTYPE *CreateShaderResourceView )( + ID3D12Device12 * This, + _In_opt_ ID3D12Resource *pResource, + _In_opt_ const D3D12_SHADER_RESOURCE_VIEW_DESC *pDesc, + _In_ D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor); + + DECLSPEC_XFGVIRT(ID3D12Device, CreateUnorderedAccessView) + void ( STDMETHODCALLTYPE *CreateUnorderedAccessView )( + ID3D12Device12 * This, + _In_opt_ ID3D12Resource *pResource, + _In_opt_ ID3D12Resource *pCounterResource, + _In_opt_ const D3D12_UNORDERED_ACCESS_VIEW_DESC *pDesc, + _In_ D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor); + + DECLSPEC_XFGVIRT(ID3D12Device, CreateRenderTargetView) + void ( STDMETHODCALLTYPE *CreateRenderTargetView )( + ID3D12Device12 * This, + _In_opt_ ID3D12Resource *pResource, + _In_opt_ const D3D12_RENDER_TARGET_VIEW_DESC *pDesc, + _In_ D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor); + + DECLSPEC_XFGVIRT(ID3D12Device, CreateDepthStencilView) + void ( STDMETHODCALLTYPE *CreateDepthStencilView )( + ID3D12Device12 * This, + _In_opt_ ID3D12Resource *pResource, + _In_opt_ const D3D12_DEPTH_STENCIL_VIEW_DESC *pDesc, + _In_ D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor); + + DECLSPEC_XFGVIRT(ID3D12Device, CreateSampler) + void ( STDMETHODCALLTYPE *CreateSampler )( + ID3D12Device12 * This, + _In_ const D3D12_SAMPLER_DESC *pDesc, + _In_ D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor); + + DECLSPEC_XFGVIRT(ID3D12Device, CopyDescriptors) + void ( STDMETHODCALLTYPE *CopyDescriptors )( + ID3D12Device12 * This, + _In_ UINT NumDestDescriptorRanges, + _In_reads_(NumDestDescriptorRanges) const D3D12_CPU_DESCRIPTOR_HANDLE *pDestDescriptorRangeStarts, + _In_reads_opt_(NumDestDescriptorRanges) const UINT *pDestDescriptorRangeSizes, + _In_ UINT NumSrcDescriptorRanges, + _In_reads_(NumSrcDescriptorRanges) const D3D12_CPU_DESCRIPTOR_HANDLE *pSrcDescriptorRangeStarts, + _In_reads_opt_(NumSrcDescriptorRanges) const UINT *pSrcDescriptorRangeSizes, + _In_ D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapsType); + + DECLSPEC_XFGVIRT(ID3D12Device, CopyDescriptorsSimple) + void ( STDMETHODCALLTYPE *CopyDescriptorsSimple )( + ID3D12Device12 * This, + _In_ UINT NumDescriptors, + _In_ D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptorRangeStart, + _In_ D3D12_CPU_DESCRIPTOR_HANDLE SrcDescriptorRangeStart, + _In_ D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapsType); + + DECLSPEC_XFGVIRT(ID3D12Device, GetResourceAllocationInfo) +#if !defined(_WIN32) + D3D12_RESOURCE_ALLOCATION_INFO ( STDMETHODCALLTYPE *GetResourceAllocationInfo )( + ID3D12Device12 * This, + _In_ UINT visibleMask, + _In_ UINT numResourceDescs, + _In_reads_(numResourceDescs) const D3D12_RESOURCE_DESC *pResourceDescs); + +#else + D3D12_RESOURCE_ALLOCATION_INFO *( STDMETHODCALLTYPE *GetResourceAllocationInfo )( + ID3D12Device12 * This, + D3D12_RESOURCE_ALLOCATION_INFO * RetVal, + _In_ UINT visibleMask, + _In_ UINT numResourceDescs, + _In_reads_(numResourceDescs) const D3D12_RESOURCE_DESC *pResourceDescs); + +#endif + + DECLSPEC_XFGVIRT(ID3D12Device, GetCustomHeapProperties) +#if !defined(_WIN32) + D3D12_HEAP_PROPERTIES ( STDMETHODCALLTYPE *GetCustomHeapProperties )( + ID3D12Device12 * This, + _In_ UINT nodeMask, + D3D12_HEAP_TYPE heapType); + +#else + D3D12_HEAP_PROPERTIES *( STDMETHODCALLTYPE *GetCustomHeapProperties )( + ID3D12Device12 * This, + D3D12_HEAP_PROPERTIES * RetVal, + _In_ UINT nodeMask, + D3D12_HEAP_TYPE heapType); + +#endif + + DECLSPEC_XFGVIRT(ID3D12Device, CreateCommittedResource) + HRESULT ( STDMETHODCALLTYPE *CreateCommittedResource )( + ID3D12Device12 * This, + _In_ const D3D12_HEAP_PROPERTIES *pHeapProperties, + D3D12_HEAP_FLAGS HeapFlags, + _In_ const D3D12_RESOURCE_DESC *pDesc, + D3D12_RESOURCE_STATES InitialResourceState, + _In_opt_ const D3D12_CLEAR_VALUE *pOptimizedClearValue, + REFIID riidResource, + _COM_Outptr_opt_ void **ppvResource); + + DECLSPEC_XFGVIRT(ID3D12Device, CreateHeap) + HRESULT ( STDMETHODCALLTYPE *CreateHeap )( + ID3D12Device12 * This, + _In_ const D3D12_HEAP_DESC *pDesc, + REFIID riid, + _COM_Outptr_opt_ void **ppvHeap); + + DECLSPEC_XFGVIRT(ID3D12Device, CreatePlacedResource) + HRESULT ( STDMETHODCALLTYPE *CreatePlacedResource )( + ID3D12Device12 * This, + _In_ ID3D12Heap *pHeap, + UINT64 HeapOffset, + _In_ const D3D12_RESOURCE_DESC *pDesc, + D3D12_RESOURCE_STATES InitialState, + _In_opt_ const D3D12_CLEAR_VALUE *pOptimizedClearValue, + REFIID riid, + _COM_Outptr_opt_ void **ppvResource); + + DECLSPEC_XFGVIRT(ID3D12Device, CreateReservedResource) + HRESULT ( STDMETHODCALLTYPE *CreateReservedResource )( + ID3D12Device12 * This, + _In_ const D3D12_RESOURCE_DESC *pDesc, + D3D12_RESOURCE_STATES InitialState, + _In_opt_ const D3D12_CLEAR_VALUE *pOptimizedClearValue, + REFIID riid, + _COM_Outptr_opt_ void **ppvResource); + + DECLSPEC_XFGVIRT(ID3D12Device, CreateSharedHandle) + HRESULT ( STDMETHODCALLTYPE *CreateSharedHandle )( + ID3D12Device12 * This, + _In_ ID3D12DeviceChild *pObject, + _In_opt_ const SECURITY_ATTRIBUTES *pAttributes, + DWORD Access, + _In_opt_ LPCWSTR Name, + _Out_ HANDLE *pHandle); + + DECLSPEC_XFGVIRT(ID3D12Device, OpenSharedHandle) + HRESULT ( STDMETHODCALLTYPE *OpenSharedHandle )( + ID3D12Device12 * This, + _In_ HANDLE NTHandle, + REFIID riid, + _COM_Outptr_opt_ void **ppvObj); + + DECLSPEC_XFGVIRT(ID3D12Device, OpenSharedHandleByName) + HRESULT ( STDMETHODCALLTYPE *OpenSharedHandleByName )( + ID3D12Device12 * This, + _In_ LPCWSTR Name, + DWORD Access, + /* [annotation][out] */ + _Out_ HANDLE *pNTHandle); + + DECLSPEC_XFGVIRT(ID3D12Device, MakeResident) + HRESULT ( STDMETHODCALLTYPE *MakeResident )( + ID3D12Device12 * This, + UINT NumObjects, + _In_reads_(NumObjects) ID3D12Pageable *const *ppObjects); + + DECLSPEC_XFGVIRT(ID3D12Device, Evict) + HRESULT ( STDMETHODCALLTYPE *Evict )( + ID3D12Device12 * This, + UINT NumObjects, + _In_reads_(NumObjects) ID3D12Pageable *const *ppObjects); + + DECLSPEC_XFGVIRT(ID3D12Device, CreateFence) + HRESULT ( STDMETHODCALLTYPE *CreateFence )( + ID3D12Device12 * This, + UINT64 InitialValue, + D3D12_FENCE_FLAGS Flags, + REFIID riid, + _COM_Outptr_ void **ppFence); + + DECLSPEC_XFGVIRT(ID3D12Device, GetDeviceRemovedReason) + HRESULT ( STDMETHODCALLTYPE *GetDeviceRemovedReason )( + ID3D12Device12 * This); + + DECLSPEC_XFGVIRT(ID3D12Device, GetCopyableFootprints) + void ( STDMETHODCALLTYPE *GetCopyableFootprints )( + ID3D12Device12 * This, + _In_ const D3D12_RESOURCE_DESC *pResourceDesc, + _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, + _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources, + UINT64 BaseOffset, + _Out_writes_opt_(NumSubresources) D3D12_PLACED_SUBRESOURCE_FOOTPRINT *pLayouts, + _Out_writes_opt_(NumSubresources) UINT *pNumRows, + _Out_writes_opt_(NumSubresources) UINT64 *pRowSizeInBytes, + _Out_opt_ UINT64 *pTotalBytes); + + DECLSPEC_XFGVIRT(ID3D12Device, CreateQueryHeap) + HRESULT ( STDMETHODCALLTYPE *CreateQueryHeap )( + ID3D12Device12 * This, + _In_ const D3D12_QUERY_HEAP_DESC *pDesc, + REFIID riid, + _COM_Outptr_opt_ void **ppvHeap); + + DECLSPEC_XFGVIRT(ID3D12Device, SetStablePowerState) + HRESULT ( STDMETHODCALLTYPE *SetStablePowerState )( + ID3D12Device12 * This, + BOOL Enable); + + DECLSPEC_XFGVIRT(ID3D12Device, CreateCommandSignature) + HRESULT ( STDMETHODCALLTYPE *CreateCommandSignature )( + ID3D12Device12 * This, + _In_ const D3D12_COMMAND_SIGNATURE_DESC *pDesc, + _In_opt_ ID3D12RootSignature *pRootSignature, + REFIID riid, + _COM_Outptr_opt_ void **ppvCommandSignature); + + DECLSPEC_XFGVIRT(ID3D12Device, GetResourceTiling) + void ( STDMETHODCALLTYPE *GetResourceTiling )( + ID3D12Device12 * This, + _In_ ID3D12Resource *pTiledResource, + _Out_opt_ UINT *pNumTilesForEntireResource, + _Out_opt_ D3D12_PACKED_MIP_INFO *pPackedMipDesc, + _Out_opt_ D3D12_TILE_SHAPE *pStandardTileShapeForNonPackedMips, + _Inout_opt_ UINT *pNumSubresourceTilings, + _In_ UINT FirstSubresourceTilingToGet, + _Out_writes_(*pNumSubresourceTilings) D3D12_SUBRESOURCE_TILING *pSubresourceTilingsForNonPackedMips); + + DECLSPEC_XFGVIRT(ID3D12Device, GetAdapterLuid) +#if !defined(_WIN32) + LUID ( STDMETHODCALLTYPE *GetAdapterLuid )( + ID3D12Device12 * This); + +#else + LUID *( STDMETHODCALLTYPE *GetAdapterLuid )( + ID3D12Device12 * This, + LUID * RetVal); + +#endif + + DECLSPEC_XFGVIRT(ID3D12Device1, CreatePipelineLibrary) + HRESULT ( STDMETHODCALLTYPE *CreatePipelineLibrary )( + ID3D12Device12 * This, + _In_reads_(BlobLength) const void *pLibraryBlob, + SIZE_T BlobLength, + REFIID riid, + _COM_Outptr_ void **ppPipelineLibrary); + + DECLSPEC_XFGVIRT(ID3D12Device1, SetEventOnMultipleFenceCompletion) + HRESULT ( STDMETHODCALLTYPE *SetEventOnMultipleFenceCompletion )( + ID3D12Device12 * This, + _In_reads_(NumFences) ID3D12Fence *const *ppFences, + _In_reads_(NumFences) const UINT64 *pFenceValues, + UINT NumFences, + D3D12_MULTIPLE_FENCE_WAIT_FLAGS Flags, + HANDLE hEvent); + + DECLSPEC_XFGVIRT(ID3D12Device1, SetResidencyPriority) + HRESULT ( STDMETHODCALLTYPE *SetResidencyPriority )( + ID3D12Device12 * This, + UINT NumObjects, + _In_reads_(NumObjects) ID3D12Pageable *const *ppObjects, + _In_reads_(NumObjects) const D3D12_RESIDENCY_PRIORITY *pPriorities); + + DECLSPEC_XFGVIRT(ID3D12Device2, CreatePipelineState) + HRESULT ( STDMETHODCALLTYPE *CreatePipelineState )( + ID3D12Device12 * This, + const D3D12_PIPELINE_STATE_STREAM_DESC *pDesc, + REFIID riid, + _COM_Outptr_ void **ppPipelineState); + + DECLSPEC_XFGVIRT(ID3D12Device3, OpenExistingHeapFromAddress) + HRESULT ( STDMETHODCALLTYPE *OpenExistingHeapFromAddress )( + ID3D12Device12 * This, + _In_ const void *pAddress, + REFIID riid, + _COM_Outptr_ void **ppvHeap); + + DECLSPEC_XFGVIRT(ID3D12Device3, OpenExistingHeapFromFileMapping) + HRESULT ( STDMETHODCALLTYPE *OpenExistingHeapFromFileMapping )( + ID3D12Device12 * This, + _In_ HANDLE hFileMapping, + REFIID riid, + _COM_Outptr_ void **ppvHeap); + + DECLSPEC_XFGVIRT(ID3D12Device3, EnqueueMakeResident) + HRESULT ( STDMETHODCALLTYPE *EnqueueMakeResident )( + ID3D12Device12 * This, + D3D12_RESIDENCY_FLAGS Flags, + UINT NumObjects, + _In_reads_(NumObjects) ID3D12Pageable *const *ppObjects, + _In_ ID3D12Fence *pFenceToSignal, + UINT64 FenceValueToSignal); + + DECLSPEC_XFGVIRT(ID3D12Device4, CreateCommandList1) + HRESULT ( STDMETHODCALLTYPE *CreateCommandList1 )( + ID3D12Device12 * This, + _In_ UINT nodeMask, + _In_ D3D12_COMMAND_LIST_TYPE type, + _In_ D3D12_COMMAND_LIST_FLAGS flags, + REFIID riid, + _COM_Outptr_ void **ppCommandList); + + DECLSPEC_XFGVIRT(ID3D12Device4, CreateProtectedResourceSession) + HRESULT ( STDMETHODCALLTYPE *CreateProtectedResourceSession )( + ID3D12Device12 * This, + _In_ const D3D12_PROTECTED_RESOURCE_SESSION_DESC *pDesc, + _In_ REFIID riid, + _COM_Outptr_ void **ppSession); + + DECLSPEC_XFGVIRT(ID3D12Device4, CreateCommittedResource1) + HRESULT ( STDMETHODCALLTYPE *CreateCommittedResource1 )( + ID3D12Device12 * This, + _In_ const D3D12_HEAP_PROPERTIES *pHeapProperties, + D3D12_HEAP_FLAGS HeapFlags, + _In_ const D3D12_RESOURCE_DESC *pDesc, + D3D12_RESOURCE_STATES InitialResourceState, + _In_opt_ const D3D12_CLEAR_VALUE *pOptimizedClearValue, + _In_opt_ ID3D12ProtectedResourceSession *pProtectedSession, + REFIID riidResource, + _COM_Outptr_opt_ void **ppvResource); + + DECLSPEC_XFGVIRT(ID3D12Device4, CreateHeap1) + HRESULT ( STDMETHODCALLTYPE *CreateHeap1 )( + ID3D12Device12 * This, + _In_ const D3D12_HEAP_DESC *pDesc, + _In_opt_ ID3D12ProtectedResourceSession *pProtectedSession, + REFIID riid, + _COM_Outptr_opt_ void **ppvHeap); + + DECLSPEC_XFGVIRT(ID3D12Device4, CreateReservedResource1) + HRESULT ( STDMETHODCALLTYPE *CreateReservedResource1 )( + ID3D12Device12 * This, + _In_ const D3D12_RESOURCE_DESC *pDesc, + D3D12_RESOURCE_STATES InitialState, + _In_opt_ const D3D12_CLEAR_VALUE *pOptimizedClearValue, + _In_opt_ ID3D12ProtectedResourceSession *pProtectedSession, + REFIID riid, + _COM_Outptr_opt_ void **ppvResource); + + DECLSPEC_XFGVIRT(ID3D12Device4, GetResourceAllocationInfo1) +#if !defined(_WIN32) + D3D12_RESOURCE_ALLOCATION_INFO ( STDMETHODCALLTYPE *GetResourceAllocationInfo1 )( + ID3D12Device12 * This, + UINT visibleMask, + UINT numResourceDescs, + _In_reads_(numResourceDescs) const D3D12_RESOURCE_DESC *pResourceDescs, + _Out_writes_opt_(numResourceDescs) D3D12_RESOURCE_ALLOCATION_INFO1 *pResourceAllocationInfo1); + +#else + D3D12_RESOURCE_ALLOCATION_INFO *( STDMETHODCALLTYPE *GetResourceAllocationInfo1 )( + ID3D12Device12 * This, + D3D12_RESOURCE_ALLOCATION_INFO * RetVal, + UINT visibleMask, + UINT numResourceDescs, + _In_reads_(numResourceDescs) const D3D12_RESOURCE_DESC *pResourceDescs, + _Out_writes_opt_(numResourceDescs) D3D12_RESOURCE_ALLOCATION_INFO1 *pResourceAllocationInfo1); + +#endif + + DECLSPEC_XFGVIRT(ID3D12Device5, CreateLifetimeTracker) + HRESULT ( STDMETHODCALLTYPE *CreateLifetimeTracker )( + ID3D12Device12 * This, + _In_ ID3D12LifetimeOwner *pOwner, + REFIID riid, + _COM_Outptr_ void **ppvTracker); + + DECLSPEC_XFGVIRT(ID3D12Device5, RemoveDevice) + void ( STDMETHODCALLTYPE *RemoveDevice )( + ID3D12Device12 * This); + + DECLSPEC_XFGVIRT(ID3D12Device5, EnumerateMetaCommands) + HRESULT ( STDMETHODCALLTYPE *EnumerateMetaCommands )( + ID3D12Device12 * This, + _Inout_ UINT *pNumMetaCommands, + _Out_writes_opt_(*pNumMetaCommands) D3D12_META_COMMAND_DESC *pDescs); + + DECLSPEC_XFGVIRT(ID3D12Device5, EnumerateMetaCommandParameters) + HRESULT ( STDMETHODCALLTYPE *EnumerateMetaCommandParameters )( + ID3D12Device12 * This, + _In_ REFGUID CommandId, + _In_ D3D12_META_COMMAND_PARAMETER_STAGE Stage, + _Out_opt_ UINT *pTotalStructureSizeInBytes, + _Inout_ UINT *pParameterCount, + _Out_writes_opt_(*pParameterCount) D3D12_META_COMMAND_PARAMETER_DESC *pParameterDescs); + + DECLSPEC_XFGVIRT(ID3D12Device5, CreateMetaCommand) + HRESULT ( STDMETHODCALLTYPE *CreateMetaCommand )( + ID3D12Device12 * This, + _In_ REFGUID CommandId, + _In_ UINT NodeMask, + _In_reads_bytes_opt_(CreationParametersDataSizeInBytes) const void *pCreationParametersData, + _In_ SIZE_T CreationParametersDataSizeInBytes, + REFIID riid, + _COM_Outptr_ void **ppMetaCommand); + + DECLSPEC_XFGVIRT(ID3D12Device5, CreateStateObject) + HRESULT ( STDMETHODCALLTYPE *CreateStateObject )( + ID3D12Device12 * This, + const D3D12_STATE_OBJECT_DESC *pDesc, + REFIID riid, + _COM_Outptr_ void **ppStateObject); + + DECLSPEC_XFGVIRT(ID3D12Device5, GetRaytracingAccelerationStructurePrebuildInfo) + void ( STDMETHODCALLTYPE *GetRaytracingAccelerationStructurePrebuildInfo )( + ID3D12Device12 * This, + _In_ const D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS *pDesc, + _Out_ D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO *pInfo); + + DECLSPEC_XFGVIRT(ID3D12Device5, CheckDriverMatchingIdentifier) + D3D12_DRIVER_MATCHING_IDENTIFIER_STATUS ( STDMETHODCALLTYPE *CheckDriverMatchingIdentifier )( + ID3D12Device12 * This, + _In_ D3D12_SERIALIZED_DATA_TYPE SerializedDataType, + _In_ const D3D12_SERIALIZED_DATA_DRIVER_MATCHING_IDENTIFIER *pIdentifierToCheck); + + DECLSPEC_XFGVIRT(ID3D12Device6, SetBackgroundProcessingMode) + HRESULT ( STDMETHODCALLTYPE *SetBackgroundProcessingMode )( + ID3D12Device12 * This, + D3D12_BACKGROUND_PROCESSING_MODE Mode, + D3D12_MEASUREMENTS_ACTION MeasurementsAction, + _In_opt_ HANDLE hEventToSignalUponCompletion, + _Out_opt_ BOOL *pbFurtherMeasurementsDesired); + + DECLSPEC_XFGVIRT(ID3D12Device7, AddToStateObject) + HRESULT ( STDMETHODCALLTYPE *AddToStateObject )( + ID3D12Device12 * This, + const D3D12_STATE_OBJECT_DESC *pAddition, + ID3D12StateObject *pStateObjectToGrowFrom, + REFIID riid, + _COM_Outptr_ void **ppNewStateObject); + + DECLSPEC_XFGVIRT(ID3D12Device7, CreateProtectedResourceSession1) + HRESULT ( STDMETHODCALLTYPE *CreateProtectedResourceSession1 )( + ID3D12Device12 * This, + _In_ const D3D12_PROTECTED_RESOURCE_SESSION_DESC1 *pDesc, + _In_ REFIID riid, + _COM_Outptr_ void **ppSession); + + DECLSPEC_XFGVIRT(ID3D12Device8, GetResourceAllocationInfo2) +#if !defined(_WIN32) + D3D12_RESOURCE_ALLOCATION_INFO ( STDMETHODCALLTYPE *GetResourceAllocationInfo2 )( + ID3D12Device12 * This, + UINT visibleMask, + UINT numResourceDescs, + _In_reads_(numResourceDescs) const D3D12_RESOURCE_DESC1 *pResourceDescs, + _Out_writes_opt_(numResourceDescs) D3D12_RESOURCE_ALLOCATION_INFO1 *pResourceAllocationInfo1); + +#else + D3D12_RESOURCE_ALLOCATION_INFO *( STDMETHODCALLTYPE *GetResourceAllocationInfo2 )( + ID3D12Device12 * This, + D3D12_RESOURCE_ALLOCATION_INFO * RetVal, + UINT visibleMask, + UINT numResourceDescs, + _In_reads_(numResourceDescs) const D3D12_RESOURCE_DESC1 *pResourceDescs, + _Out_writes_opt_(numResourceDescs) D3D12_RESOURCE_ALLOCATION_INFO1 *pResourceAllocationInfo1); + +#endif + + DECLSPEC_XFGVIRT(ID3D12Device8, CreateCommittedResource2) + HRESULT ( STDMETHODCALLTYPE *CreateCommittedResource2 )( + ID3D12Device12 * This, + _In_ const D3D12_HEAP_PROPERTIES *pHeapProperties, + D3D12_HEAP_FLAGS HeapFlags, + _In_ const D3D12_RESOURCE_DESC1 *pDesc, + D3D12_RESOURCE_STATES InitialResourceState, + _In_opt_ const D3D12_CLEAR_VALUE *pOptimizedClearValue, + _In_opt_ ID3D12ProtectedResourceSession *pProtectedSession, + REFIID riidResource, + _COM_Outptr_opt_ void **ppvResource); + + DECLSPEC_XFGVIRT(ID3D12Device8, CreatePlacedResource1) + HRESULT ( STDMETHODCALLTYPE *CreatePlacedResource1 )( + ID3D12Device12 * This, + _In_ ID3D12Heap *pHeap, + UINT64 HeapOffset, + _In_ const D3D12_RESOURCE_DESC1 *pDesc, + D3D12_RESOURCE_STATES InitialState, + _In_opt_ const D3D12_CLEAR_VALUE *pOptimizedClearValue, + REFIID riid, + _COM_Outptr_opt_ void **ppvResource); + + DECLSPEC_XFGVIRT(ID3D12Device8, CreateSamplerFeedbackUnorderedAccessView) + void ( STDMETHODCALLTYPE *CreateSamplerFeedbackUnorderedAccessView )( + ID3D12Device12 * This, + _In_opt_ ID3D12Resource *pTargetedResource, + _In_opt_ ID3D12Resource *pFeedbackResource, + _In_ D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor); + + DECLSPEC_XFGVIRT(ID3D12Device8, GetCopyableFootprints1) + void ( STDMETHODCALLTYPE *GetCopyableFootprints1 )( + ID3D12Device12 * This, + _In_ const D3D12_RESOURCE_DESC1 *pResourceDesc, + _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, + _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources, + UINT64 BaseOffset, + _Out_writes_opt_(NumSubresources) D3D12_PLACED_SUBRESOURCE_FOOTPRINT *pLayouts, + _Out_writes_opt_(NumSubresources) UINT *pNumRows, + _Out_writes_opt_(NumSubresources) UINT64 *pRowSizeInBytes, + _Out_opt_ UINT64 *pTotalBytes); + + DECLSPEC_XFGVIRT(ID3D12Device9, CreateShaderCacheSession) + HRESULT ( STDMETHODCALLTYPE *CreateShaderCacheSession )( + ID3D12Device12 * This, + _In_ const D3D12_SHADER_CACHE_SESSION_DESC *pDesc, + REFIID riid, + _COM_Outptr_opt_ void **ppvSession); + + DECLSPEC_XFGVIRT(ID3D12Device9, ShaderCacheControl) + HRESULT ( STDMETHODCALLTYPE *ShaderCacheControl )( + ID3D12Device12 * This, + D3D12_SHADER_CACHE_KIND_FLAGS Kinds, + D3D12_SHADER_CACHE_CONTROL_FLAGS Control); + + DECLSPEC_XFGVIRT(ID3D12Device9, CreateCommandQueue1) + HRESULT ( STDMETHODCALLTYPE *CreateCommandQueue1 )( + ID3D12Device12 * This, + _In_ const D3D12_COMMAND_QUEUE_DESC *pDesc, + REFIID CreatorID, + REFIID riid, + _COM_Outptr_ void **ppCommandQueue); + + DECLSPEC_XFGVIRT(ID3D12Device10, CreateCommittedResource3) + HRESULT ( STDMETHODCALLTYPE *CreateCommittedResource3 )( + ID3D12Device12 * This, + _In_ const D3D12_HEAP_PROPERTIES *pHeapProperties, + D3D12_HEAP_FLAGS HeapFlags, + _In_ const D3D12_RESOURCE_DESC1 *pDesc, + D3D12_BARRIER_LAYOUT InitialLayout, + _In_opt_ const D3D12_CLEAR_VALUE *pOptimizedClearValue, + _In_opt_ ID3D12ProtectedResourceSession *pProtectedSession, + UINT32 NumCastableFormats, + _In_opt_count_(NumCastableFormats) const DXGI_FORMAT *pCastableFormats, + REFIID riidResource, + _COM_Outptr_opt_ void **ppvResource); + + DECLSPEC_XFGVIRT(ID3D12Device10, CreatePlacedResource2) + HRESULT ( STDMETHODCALLTYPE *CreatePlacedResource2 )( + ID3D12Device12 * This, + _In_ ID3D12Heap *pHeap, + UINT64 HeapOffset, + _In_ const D3D12_RESOURCE_DESC1 *pDesc, + D3D12_BARRIER_LAYOUT InitialLayout, + _In_opt_ const D3D12_CLEAR_VALUE *pOptimizedClearValue, + UINT32 NumCastableFormats, + _In_opt_count_(NumCastableFormats) const DXGI_FORMAT *pCastableFormats, + REFIID riid, + _COM_Outptr_opt_ void **ppvResource); + + DECLSPEC_XFGVIRT(ID3D12Device10, CreateReservedResource2) + HRESULT ( STDMETHODCALLTYPE *CreateReservedResource2 )( + ID3D12Device12 * This, + _In_ const D3D12_RESOURCE_DESC *pDesc, + D3D12_BARRIER_LAYOUT InitialLayout, + _In_opt_ const D3D12_CLEAR_VALUE *pOptimizedClearValue, + _In_opt_ ID3D12ProtectedResourceSession *pProtectedSession, + UINT32 NumCastableFormats, + _In_opt_count_(NumCastableFormats) const DXGI_FORMAT *pCastableFormats, + REFIID riid, + _COM_Outptr_opt_ void **ppvResource); + + DECLSPEC_XFGVIRT(ID3D12Device11, CreateSampler2) + void ( STDMETHODCALLTYPE *CreateSampler2 )( + ID3D12Device12 * This, + _In_ const D3D12_SAMPLER_DESC2 *pDesc, + _In_ D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor); + + DECLSPEC_XFGVIRT(ID3D12Device12, GetResourceAllocationInfo3) +#if !defined(_WIN32) + D3D12_RESOURCE_ALLOCATION_INFO ( STDMETHODCALLTYPE *GetResourceAllocationInfo3 )( + ID3D12Device12 * This, + UINT visibleMask, + UINT numResourceDescs, + _In_reads_(numResourceDescs) const D3D12_RESOURCE_DESC1 *pResourceDescs, + _In_opt_count_(numResourceDescs) const UINT32 *pNumCastableFormats, + _In_opt_count_(numResourceDescs) const DXGI_FORMAT *const *ppCastableFormats, + _Out_writes_opt_(numResourceDescs) D3D12_RESOURCE_ALLOCATION_INFO1 *pResourceAllocationInfo1); + +#else + D3D12_RESOURCE_ALLOCATION_INFO *( STDMETHODCALLTYPE *GetResourceAllocationInfo3 )( + ID3D12Device12 * This, + D3D12_RESOURCE_ALLOCATION_INFO * RetVal, + UINT visibleMask, + UINT numResourceDescs, + _In_reads_(numResourceDescs) const D3D12_RESOURCE_DESC1 *pResourceDescs, + _In_opt_count_(numResourceDescs) const UINT32 *pNumCastableFormats, + _In_opt_count_(numResourceDescs) const DXGI_FORMAT *const *ppCastableFormats, + _Out_writes_opt_(numResourceDescs) D3D12_RESOURCE_ALLOCATION_INFO1 *pResourceAllocationInfo1); + +#endif + + END_INTERFACE + } ID3D12Device12Vtbl; + + interface ID3D12Device12 + { + CONST_VTBL struct ID3D12Device12Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ID3D12Device12_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ID3D12Device12_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ID3D12Device12_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ID3D12Device12_GetPrivateData(This,guid,pDataSize,pData) \ + ( (This)->lpVtbl -> GetPrivateData(This,guid,pDataSize,pData) ) + +#define ID3D12Device12_SetPrivateData(This,guid,DataSize,pData) \ + ( (This)->lpVtbl -> SetPrivateData(This,guid,DataSize,pData) ) + +#define ID3D12Device12_SetPrivateDataInterface(This,guid,pData) \ + ( (This)->lpVtbl -> SetPrivateDataInterface(This,guid,pData) ) + +#define ID3D12Device12_SetName(This,Name) \ + ( (This)->lpVtbl -> SetName(This,Name) ) + + +#define ID3D12Device12_GetNodeCount(This) \ + ( (This)->lpVtbl -> GetNodeCount(This) ) + +#define ID3D12Device12_CreateCommandQueue(This,pDesc,riid,ppCommandQueue) \ + ( (This)->lpVtbl -> CreateCommandQueue(This,pDesc,riid,ppCommandQueue) ) + +#define ID3D12Device12_CreateCommandAllocator(This,type,riid,ppCommandAllocator) \ + ( (This)->lpVtbl -> CreateCommandAllocator(This,type,riid,ppCommandAllocator) ) + +#define ID3D12Device12_CreateGraphicsPipelineState(This,pDesc,riid,ppPipelineState) \ + ( (This)->lpVtbl -> CreateGraphicsPipelineState(This,pDesc,riid,ppPipelineState) ) + +#define ID3D12Device12_CreateComputePipelineState(This,pDesc,riid,ppPipelineState) \ + ( (This)->lpVtbl -> CreateComputePipelineState(This,pDesc,riid,ppPipelineState) ) + +#define ID3D12Device12_CreateCommandList(This,nodeMask,type,pCommandAllocator,pInitialState,riid,ppCommandList) \ + ( (This)->lpVtbl -> CreateCommandList(This,nodeMask,type,pCommandAllocator,pInitialState,riid,ppCommandList) ) + +#define ID3D12Device12_CheckFeatureSupport(This,Feature,pFeatureSupportData,FeatureSupportDataSize) \ + ( (This)->lpVtbl -> CheckFeatureSupport(This,Feature,pFeatureSupportData,FeatureSupportDataSize) ) + +#define ID3D12Device12_CreateDescriptorHeap(This,pDescriptorHeapDesc,riid,ppvHeap) \ + ( (This)->lpVtbl -> CreateDescriptorHeap(This,pDescriptorHeapDesc,riid,ppvHeap) ) + +#define ID3D12Device12_GetDescriptorHandleIncrementSize(This,DescriptorHeapType) \ + ( (This)->lpVtbl -> GetDescriptorHandleIncrementSize(This,DescriptorHeapType) ) + +#define ID3D12Device12_CreateRootSignature(This,nodeMask,pBlobWithRootSignature,blobLengthInBytes,riid,ppvRootSignature) \ + ( (This)->lpVtbl -> CreateRootSignature(This,nodeMask,pBlobWithRootSignature,blobLengthInBytes,riid,ppvRootSignature) ) + +#define ID3D12Device12_CreateConstantBufferView(This,pDesc,DestDescriptor) \ + ( (This)->lpVtbl -> CreateConstantBufferView(This,pDesc,DestDescriptor) ) + +#define ID3D12Device12_CreateShaderResourceView(This,pResource,pDesc,DestDescriptor) \ + ( (This)->lpVtbl -> CreateShaderResourceView(This,pResource,pDesc,DestDescriptor) ) + +#define ID3D12Device12_CreateUnorderedAccessView(This,pResource,pCounterResource,pDesc,DestDescriptor) \ + ( (This)->lpVtbl -> CreateUnorderedAccessView(This,pResource,pCounterResource,pDesc,DestDescriptor) ) + +#define ID3D12Device12_CreateRenderTargetView(This,pResource,pDesc,DestDescriptor) \ + ( (This)->lpVtbl -> CreateRenderTargetView(This,pResource,pDesc,DestDescriptor) ) + +#define ID3D12Device12_CreateDepthStencilView(This,pResource,pDesc,DestDescriptor) \ + ( (This)->lpVtbl -> CreateDepthStencilView(This,pResource,pDesc,DestDescriptor) ) + +#define ID3D12Device12_CreateSampler(This,pDesc,DestDescriptor) \ + ( (This)->lpVtbl -> CreateSampler(This,pDesc,DestDescriptor) ) + +#define ID3D12Device12_CopyDescriptors(This,NumDestDescriptorRanges,pDestDescriptorRangeStarts,pDestDescriptorRangeSizes,NumSrcDescriptorRanges,pSrcDescriptorRangeStarts,pSrcDescriptorRangeSizes,DescriptorHeapsType) \ + ( (This)->lpVtbl -> CopyDescriptors(This,NumDestDescriptorRanges,pDestDescriptorRangeStarts,pDestDescriptorRangeSizes,NumSrcDescriptorRanges,pSrcDescriptorRangeStarts,pSrcDescriptorRangeSizes,DescriptorHeapsType) ) + +#define ID3D12Device12_CopyDescriptorsSimple(This,NumDescriptors,DestDescriptorRangeStart,SrcDescriptorRangeStart,DescriptorHeapsType) \ + ( (This)->lpVtbl -> CopyDescriptorsSimple(This,NumDescriptors,DestDescriptorRangeStart,SrcDescriptorRangeStart,DescriptorHeapsType) ) +#if !defined(_WIN32) + +#define ID3D12Device12_GetResourceAllocationInfo(This,visibleMask,numResourceDescs,pResourceDescs) \ + ( (This)->lpVtbl -> GetResourceAllocationInfo(This,visibleMask,numResourceDescs,pResourceDescs) ) +#else +#define ID3D12Device12_GetResourceAllocationInfo(This,RetVal,visibleMask,numResourceDescs,pResourceDescs) \ + ( (This)->lpVtbl -> GetResourceAllocationInfo(This,RetVal,visibleMask,numResourceDescs,pResourceDescs) ) +#endif +#if !defined(_WIN32) + +#define ID3D12Device12_GetCustomHeapProperties(This,nodeMask,heapType) \ + ( (This)->lpVtbl -> GetCustomHeapProperties(This,nodeMask,heapType) ) +#else +#define ID3D12Device12_GetCustomHeapProperties(This,RetVal,nodeMask,heapType) \ + ( (This)->lpVtbl -> GetCustomHeapProperties(This,RetVal,nodeMask,heapType) ) +#endif + +#define ID3D12Device12_CreateCommittedResource(This,pHeapProperties,HeapFlags,pDesc,InitialResourceState,pOptimizedClearValue,riidResource,ppvResource) \ + ( (This)->lpVtbl -> CreateCommittedResource(This,pHeapProperties,HeapFlags,pDesc,InitialResourceState,pOptimizedClearValue,riidResource,ppvResource) ) + +#define ID3D12Device12_CreateHeap(This,pDesc,riid,ppvHeap) \ + ( (This)->lpVtbl -> CreateHeap(This,pDesc,riid,ppvHeap) ) + +#define ID3D12Device12_CreatePlacedResource(This,pHeap,HeapOffset,pDesc,InitialState,pOptimizedClearValue,riid,ppvResource) \ + ( (This)->lpVtbl -> CreatePlacedResource(This,pHeap,HeapOffset,pDesc,InitialState,pOptimizedClearValue,riid,ppvResource) ) + +#define ID3D12Device12_CreateReservedResource(This,pDesc,InitialState,pOptimizedClearValue,riid,ppvResource) \ + ( (This)->lpVtbl -> CreateReservedResource(This,pDesc,InitialState,pOptimizedClearValue,riid,ppvResource) ) + +#define ID3D12Device12_CreateSharedHandle(This,pObject,pAttributes,Access,Name,pHandle) \ + ( (This)->lpVtbl -> CreateSharedHandle(This,pObject,pAttributes,Access,Name,pHandle) ) + +#define ID3D12Device12_OpenSharedHandle(This,NTHandle,riid,ppvObj) \ + ( (This)->lpVtbl -> OpenSharedHandle(This,NTHandle,riid,ppvObj) ) + +#define ID3D12Device12_OpenSharedHandleByName(This,Name,Access,pNTHandle) \ + ( (This)->lpVtbl -> OpenSharedHandleByName(This,Name,Access,pNTHandle) ) + +#define ID3D12Device12_MakeResident(This,NumObjects,ppObjects) \ + ( (This)->lpVtbl -> MakeResident(This,NumObjects,ppObjects) ) + +#define ID3D12Device12_Evict(This,NumObjects,ppObjects) \ + ( (This)->lpVtbl -> Evict(This,NumObjects,ppObjects) ) + +#define ID3D12Device12_CreateFence(This,InitialValue,Flags,riid,ppFence) \ + ( (This)->lpVtbl -> CreateFence(This,InitialValue,Flags,riid,ppFence) ) + +#define ID3D12Device12_GetDeviceRemovedReason(This) \ + ( (This)->lpVtbl -> GetDeviceRemovedReason(This) ) + +#define ID3D12Device12_GetCopyableFootprints(This,pResourceDesc,FirstSubresource,NumSubresources,BaseOffset,pLayouts,pNumRows,pRowSizeInBytes,pTotalBytes) \ + ( (This)->lpVtbl -> GetCopyableFootprints(This,pResourceDesc,FirstSubresource,NumSubresources,BaseOffset,pLayouts,pNumRows,pRowSizeInBytes,pTotalBytes) ) + +#define ID3D12Device12_CreateQueryHeap(This,pDesc,riid,ppvHeap) \ + ( (This)->lpVtbl -> CreateQueryHeap(This,pDesc,riid,ppvHeap) ) + +#define ID3D12Device12_SetStablePowerState(This,Enable) \ + ( (This)->lpVtbl -> SetStablePowerState(This,Enable) ) + +#define ID3D12Device12_CreateCommandSignature(This,pDesc,pRootSignature,riid,ppvCommandSignature) \ + ( (This)->lpVtbl -> CreateCommandSignature(This,pDesc,pRootSignature,riid,ppvCommandSignature) ) + +#define ID3D12Device12_GetResourceTiling(This,pTiledResource,pNumTilesForEntireResource,pPackedMipDesc,pStandardTileShapeForNonPackedMips,pNumSubresourceTilings,FirstSubresourceTilingToGet,pSubresourceTilingsForNonPackedMips) \ + ( (This)->lpVtbl -> GetResourceTiling(This,pTiledResource,pNumTilesForEntireResource,pPackedMipDesc,pStandardTileShapeForNonPackedMips,pNumSubresourceTilings,FirstSubresourceTilingToGet,pSubresourceTilingsForNonPackedMips) ) +#if !defined(_WIN32) + +#define ID3D12Device12_GetAdapterLuid(This) \ + ( (This)->lpVtbl -> GetAdapterLuid(This) ) +#else +#define ID3D12Device12_GetAdapterLuid(This,RetVal) \ + ( (This)->lpVtbl -> GetAdapterLuid(This,RetVal) ) +#endif + + +#define ID3D12Device12_CreatePipelineLibrary(This,pLibraryBlob,BlobLength,riid,ppPipelineLibrary) \ + ( (This)->lpVtbl -> CreatePipelineLibrary(This,pLibraryBlob,BlobLength,riid,ppPipelineLibrary) ) + +#define ID3D12Device12_SetEventOnMultipleFenceCompletion(This,ppFences,pFenceValues,NumFences,Flags,hEvent) \ + ( (This)->lpVtbl -> SetEventOnMultipleFenceCompletion(This,ppFences,pFenceValues,NumFences,Flags,hEvent) ) + +#define ID3D12Device12_SetResidencyPriority(This,NumObjects,ppObjects,pPriorities) \ + ( (This)->lpVtbl -> SetResidencyPriority(This,NumObjects,ppObjects,pPriorities) ) + + +#define ID3D12Device12_CreatePipelineState(This,pDesc,riid,ppPipelineState) \ + ( (This)->lpVtbl -> CreatePipelineState(This,pDesc,riid,ppPipelineState) ) + + +#define ID3D12Device12_OpenExistingHeapFromAddress(This,pAddress,riid,ppvHeap) \ + ( (This)->lpVtbl -> OpenExistingHeapFromAddress(This,pAddress,riid,ppvHeap) ) + +#define ID3D12Device12_OpenExistingHeapFromFileMapping(This,hFileMapping,riid,ppvHeap) \ + ( (This)->lpVtbl -> OpenExistingHeapFromFileMapping(This,hFileMapping,riid,ppvHeap) ) + +#define ID3D12Device12_EnqueueMakeResident(This,Flags,NumObjects,ppObjects,pFenceToSignal,FenceValueToSignal) \ + ( (This)->lpVtbl -> EnqueueMakeResident(This,Flags,NumObjects,ppObjects,pFenceToSignal,FenceValueToSignal) ) + + +#define ID3D12Device12_CreateCommandList1(This,nodeMask,type,flags,riid,ppCommandList) \ + ( (This)->lpVtbl -> CreateCommandList1(This,nodeMask,type,flags,riid,ppCommandList) ) + +#define ID3D12Device12_CreateProtectedResourceSession(This,pDesc,riid,ppSession) \ + ( (This)->lpVtbl -> CreateProtectedResourceSession(This,pDesc,riid,ppSession) ) + +#define ID3D12Device12_CreateCommittedResource1(This,pHeapProperties,HeapFlags,pDesc,InitialResourceState,pOptimizedClearValue,pProtectedSession,riidResource,ppvResource) \ + ( (This)->lpVtbl -> CreateCommittedResource1(This,pHeapProperties,HeapFlags,pDesc,InitialResourceState,pOptimizedClearValue,pProtectedSession,riidResource,ppvResource) ) + +#define ID3D12Device12_CreateHeap1(This,pDesc,pProtectedSession,riid,ppvHeap) \ + ( (This)->lpVtbl -> CreateHeap1(This,pDesc,pProtectedSession,riid,ppvHeap) ) + +#define ID3D12Device12_CreateReservedResource1(This,pDesc,InitialState,pOptimizedClearValue,pProtectedSession,riid,ppvResource) \ + ( (This)->lpVtbl -> CreateReservedResource1(This,pDesc,InitialState,pOptimizedClearValue,pProtectedSession,riid,ppvResource) ) +#if !defined(_WIN32) + +#define ID3D12Device12_GetResourceAllocationInfo1(This,visibleMask,numResourceDescs,pResourceDescs,pResourceAllocationInfo1) \ + ( (This)->lpVtbl -> GetResourceAllocationInfo1(This,visibleMask,numResourceDescs,pResourceDescs,pResourceAllocationInfo1) ) +#else +#define ID3D12Device12_GetResourceAllocationInfo1(This,RetVal,visibleMask,numResourceDescs,pResourceDescs,pResourceAllocationInfo1) \ + ( (This)->lpVtbl -> GetResourceAllocationInfo1(This,RetVal,visibleMask,numResourceDescs,pResourceDescs,pResourceAllocationInfo1) ) +#endif + + +#define ID3D12Device12_CreateLifetimeTracker(This,pOwner,riid,ppvTracker) \ + ( (This)->lpVtbl -> CreateLifetimeTracker(This,pOwner,riid,ppvTracker) ) + +#define ID3D12Device12_RemoveDevice(This) \ + ( (This)->lpVtbl -> RemoveDevice(This) ) + +#define ID3D12Device12_EnumerateMetaCommands(This,pNumMetaCommands,pDescs) \ + ( (This)->lpVtbl -> EnumerateMetaCommands(This,pNumMetaCommands,pDescs) ) + +#define ID3D12Device12_EnumerateMetaCommandParameters(This,CommandId,Stage,pTotalStructureSizeInBytes,pParameterCount,pParameterDescs) \ + ( (This)->lpVtbl -> EnumerateMetaCommandParameters(This,CommandId,Stage,pTotalStructureSizeInBytes,pParameterCount,pParameterDescs) ) + +#define ID3D12Device12_CreateMetaCommand(This,CommandId,NodeMask,pCreationParametersData,CreationParametersDataSizeInBytes,riid,ppMetaCommand) \ + ( (This)->lpVtbl -> CreateMetaCommand(This,CommandId,NodeMask,pCreationParametersData,CreationParametersDataSizeInBytes,riid,ppMetaCommand) ) + +#define ID3D12Device12_CreateStateObject(This,pDesc,riid,ppStateObject) \ + ( (This)->lpVtbl -> CreateStateObject(This,pDesc,riid,ppStateObject) ) + +#define ID3D12Device12_GetRaytracingAccelerationStructurePrebuildInfo(This,pDesc,pInfo) \ + ( (This)->lpVtbl -> GetRaytracingAccelerationStructurePrebuildInfo(This,pDesc,pInfo) ) + +#define ID3D12Device12_CheckDriverMatchingIdentifier(This,SerializedDataType,pIdentifierToCheck) \ + ( (This)->lpVtbl -> CheckDriverMatchingIdentifier(This,SerializedDataType,pIdentifierToCheck) ) + + +#define ID3D12Device12_SetBackgroundProcessingMode(This,Mode,MeasurementsAction,hEventToSignalUponCompletion,pbFurtherMeasurementsDesired) \ + ( (This)->lpVtbl -> SetBackgroundProcessingMode(This,Mode,MeasurementsAction,hEventToSignalUponCompletion,pbFurtherMeasurementsDesired) ) + + +#define ID3D12Device12_AddToStateObject(This,pAddition,pStateObjectToGrowFrom,riid,ppNewStateObject) \ + ( (This)->lpVtbl -> AddToStateObject(This,pAddition,pStateObjectToGrowFrom,riid,ppNewStateObject) ) + +#define ID3D12Device12_CreateProtectedResourceSession1(This,pDesc,riid,ppSession) \ + ( (This)->lpVtbl -> CreateProtectedResourceSession1(This,pDesc,riid,ppSession) ) + +#if !defined(_WIN32) + +#define ID3D12Device12_GetResourceAllocationInfo2(This,visibleMask,numResourceDescs,pResourceDescs,pResourceAllocationInfo1) \ + ( (This)->lpVtbl -> GetResourceAllocationInfo2(This,visibleMask,numResourceDescs,pResourceDescs,pResourceAllocationInfo1) ) +#else +#define ID3D12Device12_GetResourceAllocationInfo2(This,RetVal,visibleMask,numResourceDescs,pResourceDescs,pResourceAllocationInfo1) \ + ( (This)->lpVtbl -> GetResourceAllocationInfo2(This,RetVal,visibleMask,numResourceDescs,pResourceDescs,pResourceAllocationInfo1) ) +#endif + +#define ID3D12Device12_CreateCommittedResource2(This,pHeapProperties,HeapFlags,pDesc,InitialResourceState,pOptimizedClearValue,pProtectedSession,riidResource,ppvResource) \ + ( (This)->lpVtbl -> CreateCommittedResource2(This,pHeapProperties,HeapFlags,pDesc,InitialResourceState,pOptimizedClearValue,pProtectedSession,riidResource,ppvResource) ) + +#define ID3D12Device12_CreatePlacedResource1(This,pHeap,HeapOffset,pDesc,InitialState,pOptimizedClearValue,riid,ppvResource) \ + ( (This)->lpVtbl -> CreatePlacedResource1(This,pHeap,HeapOffset,pDesc,InitialState,pOptimizedClearValue,riid,ppvResource) ) + +#define ID3D12Device12_CreateSamplerFeedbackUnorderedAccessView(This,pTargetedResource,pFeedbackResource,DestDescriptor) \ + ( (This)->lpVtbl -> CreateSamplerFeedbackUnorderedAccessView(This,pTargetedResource,pFeedbackResource,DestDescriptor) ) + +#define ID3D12Device12_GetCopyableFootprints1(This,pResourceDesc,FirstSubresource,NumSubresources,BaseOffset,pLayouts,pNumRows,pRowSizeInBytes,pTotalBytes) \ + ( (This)->lpVtbl -> GetCopyableFootprints1(This,pResourceDesc,FirstSubresource,NumSubresources,BaseOffset,pLayouts,pNumRows,pRowSizeInBytes,pTotalBytes) ) + + +#define ID3D12Device12_CreateShaderCacheSession(This,pDesc,riid,ppvSession) \ + ( (This)->lpVtbl -> CreateShaderCacheSession(This,pDesc,riid,ppvSession) ) + +#define ID3D12Device12_ShaderCacheControl(This,Kinds,Control) \ + ( (This)->lpVtbl -> ShaderCacheControl(This,Kinds,Control) ) + +#define ID3D12Device12_CreateCommandQueue1(This,pDesc,CreatorID,riid,ppCommandQueue) \ + ( (This)->lpVtbl -> CreateCommandQueue1(This,pDesc,CreatorID,riid,ppCommandQueue) ) + + +#define ID3D12Device12_CreateCommittedResource3(This,pHeapProperties,HeapFlags,pDesc,InitialLayout,pOptimizedClearValue,pProtectedSession,NumCastableFormats,pCastableFormats,riidResource,ppvResource) \ + ( (This)->lpVtbl -> CreateCommittedResource3(This,pHeapProperties,HeapFlags,pDesc,InitialLayout,pOptimizedClearValue,pProtectedSession,NumCastableFormats,pCastableFormats,riidResource,ppvResource) ) + +#define ID3D12Device12_CreatePlacedResource2(This,pHeap,HeapOffset,pDesc,InitialLayout,pOptimizedClearValue,NumCastableFormats,pCastableFormats,riid,ppvResource) \ + ( (This)->lpVtbl -> CreatePlacedResource2(This,pHeap,HeapOffset,pDesc,InitialLayout,pOptimizedClearValue,NumCastableFormats,pCastableFormats,riid,ppvResource) ) + +#define ID3D12Device12_CreateReservedResource2(This,pDesc,InitialLayout,pOptimizedClearValue,pProtectedSession,NumCastableFormats,pCastableFormats,riid,ppvResource) \ + ( (This)->lpVtbl -> CreateReservedResource2(This,pDesc,InitialLayout,pOptimizedClearValue,pProtectedSession,NumCastableFormats,pCastableFormats,riid,ppvResource) ) + + +#define ID3D12Device12_CreateSampler2(This,pDesc,DestDescriptor) \ + ( (This)->lpVtbl -> CreateSampler2(This,pDesc,DestDescriptor) ) + +#if !defined(_WIN32) + +#define ID3D12Device12_GetResourceAllocationInfo3(This,visibleMask,numResourceDescs,pResourceDescs,pNumCastableFormats,ppCastableFormats,pResourceAllocationInfo1) \ + ( (This)->lpVtbl -> GetResourceAllocationInfo3(This,visibleMask,numResourceDescs,pResourceDescs,pNumCastableFormats,ppCastableFormats,pResourceAllocationInfo1) ) +#else +#define ID3D12Device12_GetResourceAllocationInfo3(This,RetVal,visibleMask,numResourceDescs,pResourceDescs,pNumCastableFormats,ppCastableFormats,pResourceAllocationInfo1) \ + ( (This)->lpVtbl -> GetResourceAllocationInfo3(This,RetVal,visibleMask,numResourceDescs,pResourceDescs,pNumCastableFormats,ppCastableFormats,pResourceAllocationInfo1) ) +#endif + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ID3D12Device12_INTERFACE_DEFINED__ */ + + #ifndef __ID3D12VirtualizationGuestDevice_INTERFACE_DEFINED__ #define __ID3D12VirtualizationGuestDevice_INTERFACE_DEFINED__ @@ -24519,7 +25698,7 @@ EXTERN_C const IID IID_ID3D12Tools; #endif /* __ID3D12Tools_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_d3d12_0000_0057 */ +/* interface __MIDL_itf_d3d12_0000_0058 */ /* [local] */ typedef struct D3D12_SUBRESOURCE_DATA @@ -24647,6 +25826,7 @@ DEFINE_GUID(CLSID_D3D12Tools, 0xe38216b1, 0x3c8c, 0x4833, DEFINE_GUID(CLSID_D3D12DeviceRemovedExtendedData, 0x4a75bbc4, 0x9ff4, 0x4ad8, 0x9f, 0x18, 0xab, 0xae, 0x84, 0xdc, 0x5f, 0xf2); DEFINE_GUID(CLSID_D3D12SDKConfiguration, 0x7cda6aca, 0xa03e, 0x49c8, 0x94, 0x58, 0x03, 0x34, 0xd2, 0x0e, 0x07, 0xce); DEFINE_GUID(CLSID_D3D12DeviceFactory, 0x114863bf, 0xc386, 0x4aee, 0xb3, 0x9d, 0x8f, 0x0b, 0xbb, 0x06, 0x29, 0x55); +DEFINE_GUID(CLSID_D3D12DSRDeviceFactory, 0x7f9bdcac, 0xf629, 0x455e, 0xab, 0x13, 0xa8, 0x07, 0xfb, 0xe9, 0xab, 0xa4); typedef HRESULT (WINAPI* PFN_D3D12_GET_INTERFACE)( _In_ REFCLSID, _In_ REFIID, _COM_Outptr_opt_ void** ); @@ -24654,8 +25834,8 @@ HRESULT WINAPI D3D12GetInterface( _In_ REFCLSID rclsid, _In_ REFIID riid, _COM_O -extern RPC_IF_HANDLE __MIDL_itf_d3d12_0000_0057_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_d3d12_0000_0057_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_d3d12_0000_0058_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_d3d12_0000_0058_v0_0_s_ifspec; #ifndef __ID3D12SDKConfiguration_INTERFACE_DEFINED__ #define __ID3D12SDKConfiguration_INTERFACE_DEFINED__ @@ -24850,7 +26030,7 @@ EXTERN_C const IID IID_ID3D12SDKConfiguration1; #endif /* __ID3D12SDKConfiguration1_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_d3d12_0000_0059 */ +/* interface __MIDL_itf_d3d12_0000_0060 */ /* [local] */ typedef @@ -24865,8 +26045,8 @@ enum D3D12_DEVICE_FACTORY_FLAGS DEFINE_ENUM_FLAG_OPERATORS( D3D12_DEVICE_FACTORY_FLAGS ); -extern RPC_IF_HANDLE __MIDL_itf_d3d12_0000_0059_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_d3d12_0000_0059_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_d3d12_0000_0060_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_d3d12_0000_0060_v0_0_s_ifspec; #ifndef __ID3D12DeviceFactory_INTERFACE_DEFINED__ #define __ID3D12DeviceFactory_INTERFACE_DEFINED__ @@ -25027,7 +26207,7 @@ EXTERN_C const IID IID_ID3D12DeviceFactory; #endif /* __ID3D12DeviceFactory_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_d3d12_0000_0060 */ +/* interface __MIDL_itf_d3d12_0000_0061 */ /* [local] */ typedef @@ -25058,8 +26238,8 @@ typedef struct D3D12_DEVICE_CONFIGURATION_DESC -extern RPC_IF_HANDLE __MIDL_itf_d3d12_0000_0060_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_d3d12_0000_0060_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_d3d12_0000_0061_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_d3d12_0000_0061_v0_0_s_ifspec; #ifndef __ID3D12DeviceConfiguration_INTERFACE_DEFINED__ #define __ID3D12DeviceConfiguration_INTERFACE_DEFINED__ @@ -25205,7 +26385,7 @@ EXTERN_C const IID IID_ID3D12DeviceConfiguration; #endif /* __ID3D12DeviceConfiguration_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_d3d12_0000_0061 */ +/* interface __MIDL_itf_d3d12_0000_0062 */ /* [local] */ typedef @@ -25245,8 +26425,8 @@ enum D3D12_SHADING_RATE_COMBINER -extern RPC_IF_HANDLE __MIDL_itf_d3d12_0000_0061_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_d3d12_0000_0061_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_d3d12_0000_0062_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_d3d12_0000_0062_v0_0_s_ifspec; #ifndef __ID3D12GraphicsCommandList5_INTERFACE_DEFINED__ #define __ID3D12GraphicsCommandList5_INTERFACE_DEFINED__ @@ -26081,7 +27261,7 @@ EXTERN_C const IID IID_ID3D12GraphicsCommandList5; #endif /* __ID3D12GraphicsCommandList5_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_d3d12_0000_0062 */ +/* interface __MIDL_itf_d3d12_0000_0063 */ /* [local] */ typedef struct D3D12_DISPATCH_MESH_ARGUMENTS @@ -26093,8 +27273,8 @@ typedef struct D3D12_DISPATCH_MESH_ARGUMENTS -extern RPC_IF_HANDLE __MIDL_itf_d3d12_0000_0062_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_d3d12_0000_0062_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_d3d12_0000_0063_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_d3d12_0000_0063_v0_0_s_ifspec; #ifndef __ID3D12GraphicsCommandList6_INTERFACE_DEFINED__ #define __ID3D12GraphicsCommandList6_INTERFACE_DEFINED__ @@ -29534,7 +30714,96 @@ EXTERN_C const IID IID_ID3D12GraphicsCommandList9; #endif /* __ID3D12GraphicsCommandList9_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_d3d12_0000_0066 */ +#ifndef __ID3D12DSRDeviceFactory_INTERFACE_DEFINED__ +#define __ID3D12DSRDeviceFactory_INTERFACE_DEFINED__ + +/* interface ID3D12DSRDeviceFactory */ +/* [unique][local][object][uuid] */ + + +EXTERN_C const IID IID_ID3D12DSRDeviceFactory; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("51ee7783-6426-4428-b182-42f3541fca71") + ID3D12DSRDeviceFactory : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateDSRDevice( + ID3D12Device *pD3D12Device, + UINT NodeMask, + REFIID riid, + _COM_Outptr_ void **ppvDSRDevice) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ID3D12DSRDeviceFactoryVtbl + { + BEGIN_INTERFACE + + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ID3D12DSRDeviceFactory * This, + REFIID riid, + _COM_Outptr_ void **ppvObject); + + DECLSPEC_XFGVIRT(IUnknown, AddRef) + ULONG ( STDMETHODCALLTYPE *AddRef )( + ID3D12DSRDeviceFactory * This); + + DECLSPEC_XFGVIRT(IUnknown, Release) + ULONG ( STDMETHODCALLTYPE *Release )( + ID3D12DSRDeviceFactory * This); + + DECLSPEC_XFGVIRT(ID3D12DSRDeviceFactory, CreateDSRDevice) + HRESULT ( STDMETHODCALLTYPE *CreateDSRDevice )( + ID3D12DSRDeviceFactory * This, + ID3D12Device *pD3D12Device, + UINT NodeMask, + REFIID riid, + _COM_Outptr_ void **ppvDSRDevice); + + END_INTERFACE + } ID3D12DSRDeviceFactoryVtbl; + + interface ID3D12DSRDeviceFactory + { + CONST_VTBL struct ID3D12DSRDeviceFactoryVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ID3D12DSRDeviceFactory_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ID3D12DSRDeviceFactory_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ID3D12DSRDeviceFactory_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ID3D12DSRDeviceFactory_CreateDSRDevice(This,pD3D12Device,NodeMask,riid,ppvDSRDevice) \ + ( (This)->lpVtbl -> CreateDSRDevice(This,pD3D12Device,NodeMask,riid,ppvDSRDevice) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ID3D12DSRDeviceFactory_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_d3d12_0000_0068 */ /* [local] */ #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) */ @@ -29594,6 +30863,7 @@ DEFINE_GUID(IID_ID3D12ShaderCacheSession,0x28e2495d,0x0f64,0x4ae4,0xa6,0xec,0x12 DEFINE_GUID(IID_ID3D12Device9,0x4c80e962,0xf032,0x4f60,0xbc,0x9e,0xeb,0xc2,0xcf,0xa1,0xd8,0x3c); DEFINE_GUID(IID_ID3D12Device10,0x517f8718,0xaa66,0x49f9,0xb0,0x2b,0xa7,0xab,0x89,0xc0,0x60,0x31); DEFINE_GUID(IID_ID3D12Device11,0x5405c344,0xd457,0x444e,0xb4,0xdd,0x23,0x66,0xe4,0x5a,0xee,0x39); +DEFINE_GUID(IID_ID3D12Device12,0x5af5c532,0x4c91,0x4cd0,0xb5,0x41,0x15,0xa4,0x05,0x39,0x5f,0xc5); DEFINE_GUID(IID_ID3D12VirtualizationGuestDevice,0xbc66d368,0x7373,0x4943,0x87,0x57,0xfc,0x87,0xdc,0x79,0xe4,0x76); DEFINE_GUID(IID_ID3D12Tools,0x7071e1f0,0xe84b,0x4b33,0x97,0x4f,0x12,0xfa,0x49,0xde,0x65,0xc5); DEFINE_GUID(IID_ID3D12SDKConfiguration,0xe9eb5314,0x33aa,0x42b2,0xa7,0x18,0xd7,0x7f,0x58,0xb1,0xf1,0xc7); @@ -29605,10 +30875,11 @@ DEFINE_GUID(IID_ID3D12GraphicsCommandList6,0xc3827890,0xe548,0x4cfa,0x96,0xcf,0x DEFINE_GUID(IID_ID3D12GraphicsCommandList7,0xdd171223,0x8b61,0x4769,0x90,0xe3,0x16,0x0c,0xcd,0xe4,0xe2,0xc1); DEFINE_GUID(IID_ID3D12GraphicsCommandList8,0xee936ef9,0x599d,0x4d28,0x93,0x8e,0x23,0xc4,0xad,0x05,0xce,0x51); DEFINE_GUID(IID_ID3D12GraphicsCommandList9,0x34ed2808,0xffe6,0x4c2b,0xb1,0x1a,0xca,0xbd,0x2b,0x0c,0x59,0xe1); +DEFINE_GUID(IID_ID3D12DSRDeviceFactory,0x51ee7783,0x6426,0x4428,0xb1,0x82,0x42,0xf3,0x54,0x1f,0xca,0x71); -extern RPC_IF_HANDLE __MIDL_itf_d3d12_0000_0066_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_d3d12_0000_0066_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_d3d12_0000_0068_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_d3d12_0000_0068_v0_0_s_ifspec; /* Additional Prototypes for ALL interfaces */ diff --git a/WickedEngine/Utility/dx12/d3d12sdklayers.h b/WickedEngine/Utility/dx12/d3d12sdklayers.h index 08388d9ae..908ecc046 100644 --- a/WickedEngine/Utility/dx12/d3d12sdklayers.h +++ b/WickedEngine/Utility/dx12/d3d12sdklayers.h @@ -171,6 +171,13 @@ typedef interface ID3D12SharingContract ID3D12SharingContract; #endif /* __ID3D12SharingContract_FWD_DEFINED__ */ +#ifndef __ID3D12ManualWriteTrackingResource_FWD_DEFINED__ +#define __ID3D12ManualWriteTrackingResource_FWD_DEFINED__ +typedef interface ID3D12ManualWriteTrackingResource ID3D12ManualWriteTrackingResource; + +#endif /* __ID3D12ManualWriteTrackingResource_FWD_DEFINED__ */ + + #ifndef __ID3D12InfoQueue_FWD_DEFINED__ #define __ID3D12InfoQueue_FWD_DEFINED__ typedef interface ID3D12InfoQueue ID3D12InfoQueue; @@ -2237,7 +2244,92 @@ EXTERN_C const IID IID_ID3D12SharingContract; #endif /* __ID3D12SharingContract_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_d3d12sdklayers_0000_0017 */ +#ifndef __ID3D12ManualWriteTrackingResource_INTERFACE_DEFINED__ +#define __ID3D12ManualWriteTrackingResource_INTERFACE_DEFINED__ + +/* interface ID3D12ManualWriteTrackingResource */ +/* [unique][local][object][uuid] */ + + +EXTERN_C const IID IID_ID3D12ManualWriteTrackingResource; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("86ca3b85-49ad-4b6e-aed5-eddb18540f41") + ID3D12ManualWriteTrackingResource : public IUnknown + { + public: + virtual void STDMETHODCALLTYPE TrackWrite( + UINT Subresource, + _In_opt_ const D3D12_RANGE *pWrittenRange) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ID3D12ManualWriteTrackingResourceVtbl + { + BEGIN_INTERFACE + + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ID3D12ManualWriteTrackingResource * This, + REFIID riid, + _COM_Outptr_ void **ppvObject); + + DECLSPEC_XFGVIRT(IUnknown, AddRef) + ULONG ( STDMETHODCALLTYPE *AddRef )( + ID3D12ManualWriteTrackingResource * This); + + DECLSPEC_XFGVIRT(IUnknown, Release) + ULONG ( STDMETHODCALLTYPE *Release )( + ID3D12ManualWriteTrackingResource * This); + + DECLSPEC_XFGVIRT(ID3D12ManualWriteTrackingResource, TrackWrite) + void ( STDMETHODCALLTYPE *TrackWrite )( + ID3D12ManualWriteTrackingResource * This, + UINT Subresource, + _In_opt_ const D3D12_RANGE *pWrittenRange); + + END_INTERFACE + } ID3D12ManualWriteTrackingResourceVtbl; + + interface ID3D12ManualWriteTrackingResource + { + CONST_VTBL struct ID3D12ManualWriteTrackingResourceVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ID3D12ManualWriteTrackingResource_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ID3D12ManualWriteTrackingResource_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ID3D12ManualWriteTrackingResource_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ID3D12ManualWriteTrackingResource_TrackWrite(This,Subresource,pWrittenRange) \ + ( (This)->lpVtbl -> TrackWrite(This,Subresource,pWrittenRange) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ID3D12ManualWriteTrackingResource_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_d3d12sdklayers_0000_0018 */ /* [local] */ typedef @@ -3200,8 +3292,18 @@ enum D3D12_MESSAGE_ID D3D12_MESSAGE_ID_DYNAMIC_DEPTH_BIAS_NO_PIPELINE = 1367, D3D12_MESSAGE_ID_DYNAMIC_INDEX_BUFFER_STRIP_CUT_FLAG_MISSING = 1368, D3D12_MESSAGE_ID_DYNAMIC_INDEX_BUFFER_STRIP_CUT_NO_PIPELINE = 1369, + D3D12_MESSAGE_ID_NONNORMALIZED_COORDINATE_SAMPLING_NOT_SUPPORTED = 1370, D3D12_MESSAGE_ID_INVALID_CAST_TARGET = 1371, - D3D12_MESSAGE_ID_D3D12_MESSAGES_END = ( D3D12_MESSAGE_ID_INVALID_CAST_TARGET + 1 ) + D3D12_MESSAGE_ID_RENDER_PASS_COMMANDLIST_INVALID_END_STATE = 1372, + D3D12_MESSAGE_ID_RENDER_PASS_COMMANDLIST_INVALID_START_STATE = 1373, + D3D12_MESSAGE_ID_RENDER_PASS_MISMATCHING_ACCESS = 1374, + D3D12_MESSAGE_ID_RENDER_PASS_MISMATCHING_LOCAL_PRESERVE_PARAMETERS = 1375, + D3D12_MESSAGE_ID_RENDER_PASS_LOCAL_PRESERVE_RENDER_PARAMETERS_ERROR = 1376, + D3D12_MESSAGE_ID_RENDER_PASS_LOCAL_DEPTH_STENCIL_ERROR = 1377, + D3D12_MESSAGE_ID_DRAW_POTENTIALLY_OUTSIDE_OF_VALID_RENDER_AREA = 1378, + D3D12_MESSAGE_ID_CREATERASTERIZERSTATE_INVALID_LINERASTERIZATIONMODE = 1379, + D3D12_MESSAGE_ID_CREATERESOURCE_INVALIDALIGNMENT_SMALLRESOURCE = 1380, + D3D12_MESSAGE_ID_D3D12_MESSAGES_END = ( D3D12_MESSAGE_ID_CREATERESOURCE_INVALIDALIGNMENT_SMALLRESOURCE + 1 ) } D3D12_MESSAGE_ID; typedef struct D3D12_MESSAGE @@ -3232,8 +3334,8 @@ typedef struct D3D12_INFO_QUEUE_FILTER #define D3D12_INFO_QUEUE_DEFAULT_MESSAGE_COUNT_LIMIT 1024 -extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0017_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0017_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0018_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0018_v0_0_s_ifspec; #ifndef __ID3D12InfoQueue_INTERFACE_DEFINED__ #define __ID3D12InfoQueue_INTERFACE_DEFINED__ @@ -3678,7 +3780,7 @@ EXTERN_C const IID IID_ID3D12InfoQueue; #endif /* __ID3D12InfoQueue_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_d3d12sdklayers_0000_0018 */ +/* interface __MIDL_itf_d3d12sdklayers_0000_0019 */ /* [local] */ typedef @@ -3698,8 +3800,8 @@ typedef void ( __stdcall *D3D12MessageFunc )( -extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0018_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0018_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0019_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0019_v0_0_s_ifspec; #ifndef __ID3D12InfoQueue1_INTERFACE_DEFINED__ #define __ID3D12InfoQueue1_INTERFACE_DEFINED__ @@ -4075,7 +4177,7 @@ EXTERN_C const IID IID_ID3D12InfoQueue1; #endif /* __ID3D12InfoQueue1_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_d3d12sdklayers_0000_0019 */ +/* interface __MIDL_itf_d3d12sdklayers_0000_0020 */ /* [local] */ #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) */ @@ -4097,12 +4199,13 @@ DEFINE_GUID(IID_ID3D12DebugCommandList,0x09e0bf36,0x54ac,0x484f,0x88,0x47,0x4b,0 DEFINE_GUID(IID_ID3D12DebugCommandList2,0xaeb575cf,0x4e06,0x48be,0xba,0x3b,0xc4,0x50,0xfc,0x96,0x65,0x2e); DEFINE_GUID(IID_ID3D12DebugCommandList3,0x197d5e15,0x4d37,0x4d34,0xaf,0x78,0x72,0x4c,0xd7,0x0f,0xdb,0x1f); DEFINE_GUID(IID_ID3D12SharingContract,0x0adf7d52,0x929c,0x4e61,0xad,0xdb,0xff,0xed,0x30,0xde,0x66,0xef); +DEFINE_GUID(IID_ID3D12ManualWriteTrackingResource,0x86ca3b85,0x49ad,0x4b6e,0xae,0xd5,0xed,0xdb,0x18,0x54,0x0f,0x41); DEFINE_GUID(IID_ID3D12InfoQueue,0x0742a90b,0xc387,0x483f,0xb9,0x46,0x30,0xa7,0xe4,0xe6,0x14,0x58); DEFINE_GUID(IID_ID3D12InfoQueue1,0x2852dd88,0xb484,0x4c0c,0xb6,0xb1,0x67,0x16,0x85,0x00,0xe6,0x00); -extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0019_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0019_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0020_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0020_v0_0_s_ifspec; /* Additional Prototypes for ALL interfaces */ diff --git a/WickedEngine/Utility/dx12/d3dx12_barriers.h b/WickedEngine/Utility/dx12/d3dx12_barriers.h index 0c17c2d65..2c2b135a6 100644 --- a/WickedEngine/Utility/dx12/d3dx12_barriers.h +++ b/WickedEngine/Utility/dx12/d3dx12_barriers.h @@ -37,8 +37,8 @@ struct CD3DX12_RESOURCE_BARRIER : public D3D12_RESOURCE_BARRIER return result; } static inline CD3DX12_RESOURCE_BARRIER Aliasing( - _In_ ID3D12Resource* pResourceBefore, - _In_ ID3D12Resource* pResourceAfter) noexcept + _In_opt_ ID3D12Resource* pResourceBefore, + _In_opt_ ID3D12Resource* pResourceAfter) noexcept { CD3DX12_RESOURCE_BARRIER result = {}; D3D12_RESOURCE_BARRIER &barrier = result; @@ -48,7 +48,7 @@ struct CD3DX12_RESOURCE_BARRIER : public D3D12_RESOURCE_BARRIER return result; } static inline CD3DX12_RESOURCE_BARRIER UAV( - _In_ ID3D12Resource* pResource) noexcept + _In_opt_ ID3D12Resource* pResource) noexcept { CD3DX12_RESOURCE_BARRIER result = {}; D3D12_RESOURCE_BARRIER &barrier = result; @@ -184,9 +184,9 @@ public: pGlobalBarriers = pBarriers; } }; - #endif // D3D12_SDK_VERSION >= 608 + #endif // defined( __cplusplus ) #endif // __D3DX12_BARRIERS_H__ diff --git a/WickedEngine/Utility/dx12/d3dx12_check_feature_support.h b/WickedEngine/Utility/dx12/d3dx12_check_feature_support.h index b193a4c5c..94272e934 100644 --- a/WickedEngine/Utility/dx12/d3dx12_check_feature_support.h +++ b/WickedEngine/Utility/dx12/d3dx12_check_feature_support.h @@ -1,4 +1,4 @@ -//********************************************************* +//********************************************************* // // Copyright (c) Microsoft Corporation. // Licensed under the MIT License (MIT). @@ -204,6 +204,28 @@ public: // Function declaration // D3D12_OPTIONS16 BOOL DynamicDepthBiasSupported() const noexcept; #endif +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609) + BOOL GPUUploadHeapSupported() const noexcept; + + // D3D12_OPTIONS17 + BOOL NonNormalizedCoordinateSamplersSupported() const noexcept; + BOOL ManualWriteTrackingResourceSupported() const noexcept; + + // D3D12_OPTIONS18 + BOOL RenderPassesValid() const noexcept; +#endif + +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 610) + BOOL MismatchingOutputDimensionsSupported() const noexcept; + UINT SupportedSampleCountsWithNoOutputs() const noexcept; + BOOL PointSamplingAddressesNeverRoundUp() const noexcept; + BOOL RasterizerDesc2Supported() const noexcept; + BOOL NarrowQuadrilateralLinesSupported() const noexcept; + BOOL AnisoFilterWithPointMipSupported() const noexcept; + UINT MaxSamplerDescriptorHeapSize() const noexcept; + UINT MaxSamplerDescriptorHeapSizeWithStaticSamplers() const noexcept; + UINT MaxViewDescriptorHeapSize() const noexcept; +#endif private: // Private structs and helpers declaration struct ProtectedResourceSessionTypesLocal : D3D12_FEATURE_DATA_PROTECTED_RESOURCE_SESSION_TYPES @@ -279,6 +301,15 @@ private: // Member data #if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 608) D3D12_FEATURE_DATA_D3D12_OPTIONS16 m_dOptions16; #endif +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609) + D3D12_FEATURE_DATA_D3D12_OPTIONS17 m_dOptions17; +#endif +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609) + D3D12_FEATURE_DATA_D3D12_OPTIONS18 m_dOptions18; +#endif +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 610) + D3D12_FEATURE_DATA_D3D12_OPTIONS19 m_dOptions19; +#endif }; // Implementations for CD3DX12FeatureSupport functions @@ -358,6 +389,15 @@ inline CD3DX12FeatureSupport::CD3DX12FeatureSupport() noexcept #if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 608) , m_dOptions16{} #endif +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609) +, m_dOptions17{} +#endif +#if defined (D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609) +, m_dOptions18{} +#endif +#if defined (D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 610) +, m_dOptions19{} +#endif {} inline HRESULT CD3DX12FeatureSupport::Init(ID3D12Device* pDevice) @@ -496,6 +536,29 @@ inline HRESULT CD3DX12FeatureSupport::Init(ID3D12Device* pDevice) } #endif +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609) + if (FAILED(m_pDevice->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS17, &m_dOptions17, sizeof(m_dOptions17)))) + { + m_dOptions17 = {}; + } + + if (FAILED(m_pDevice->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS18, &m_dOptions18, sizeof(m_dOptions18)))) + { + m_dOptions18.RenderPassesValid = false; + } +#endif + +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 610) + if (FAILED(m_pDevice->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS19, &m_dOptions19, sizeof(m_dOptions19)))) + { + m_dOptions19 = {}; + m_dOptions19.SupportedSampleCountsWithNoOutputs = 1; + m_dOptions19.MaxSamplerDescriptorHeapSize = D3D12_MAX_SHADER_VISIBLE_SAMPLER_HEAP_SIZE; + m_dOptions19.MaxSamplerDescriptorHeapSizeWithStaticSamplers = D3D12_MAX_SHADER_VISIBLE_SAMPLER_HEAP_SIZE; + m_dOptions19.MaxViewDescriptorHeapSize = D3D12_MAX_SHADER_VISIBLE_DESCRIPTOR_HEAP_SIZE_TIER_1; + } +#endif + // Initialize per-node feature support data structures const UINT uNodeCount = m_pDevice->GetNodeCount(); m_dProtectedResourceSessionSupport.resize(uNodeCount); @@ -840,6 +903,28 @@ FEATURE_SUPPORT_GET(BOOL, m_dOptions15, DynamicIndexBufferStripCutSupported); // 45: Options16 FEATURE_SUPPORT_GET(BOOL, m_dOptions16, DynamicDepthBiasSupported); #endif +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609) +FEATURE_SUPPORT_GET(BOOL, m_dOptions16, GPUUploadHeapSupported); + +// 46: Options17 +FEATURE_SUPPORT_GET(BOOL, m_dOptions17, NonNormalizedCoordinateSamplersSupported); +FEATURE_SUPPORT_GET(BOOL, m_dOptions17, ManualWriteTrackingResourceSupported); + +// 47: Option18 +FEATURE_SUPPORT_GET(BOOL, m_dOptions18, RenderPassesValid); +#endif + +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 610) +FEATURE_SUPPORT_GET(BOOL, m_dOptions19, MismatchingOutputDimensionsSupported); +FEATURE_SUPPORT_GET(UINT, m_dOptions19, SupportedSampleCountsWithNoOutputs); +FEATURE_SUPPORT_GET(BOOL, m_dOptions19, PointSamplingAddressesNeverRoundUp); +FEATURE_SUPPORT_GET(BOOL, m_dOptions19, RasterizerDesc2Supported); +FEATURE_SUPPORT_GET(BOOL, m_dOptions19, NarrowQuadrilateralLinesSupported); +FEATURE_SUPPORT_GET(BOOL, m_dOptions19, AnisoFilterWithPointMipSupported); +FEATURE_SUPPORT_GET(UINT, m_dOptions19, MaxSamplerDescriptorHeapSize); +FEATURE_SUPPORT_GET(UINT, m_dOptions19, MaxSamplerDescriptorHeapSizeWithStaticSamplers); +FEATURE_SUPPORT_GET(UINT, m_dOptions19, MaxViewDescriptorHeapSize); +#endif // Helper function to decide the highest shader model supported by the system // Stores the result in m_dShaderModel @@ -897,6 +982,9 @@ inline HRESULT CD3DX12FeatureSupport::QueryHighestRootSignatureVersion() const D3D_ROOT_SIGNATURE_VERSION allRootSignatureVersions[] = { +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609) + D3D_ROOT_SIGNATURE_VERSION_1_2, +#endif D3D_ROOT_SIGNATURE_VERSION_1_1, D3D_ROOT_SIGNATURE_VERSION_1_0, D3D_ROOT_SIGNATURE_VERSION_1, diff --git a/WickedEngine/Utility/dx12/d3dx12_core.h b/WickedEngine/Utility/dx12/d3dx12_core.h index 2848e8fba..593f7637a 100644 --- a/WickedEngine/Utility/dx12/d3dx12_core.h +++ b/WickedEngine/Utility/dx12/d3dx12_core.h @@ -620,6 +620,112 @@ struct CD3DX12_RASTERIZER_DESC1 : public D3D12_RASTERIZER_DESC1 }; #endif // D3D12_SDK_VERSION >= 608 +//------------------------------------------------------------------------------------------------ +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 610) +struct CD3DX12_RASTERIZER_DESC2 : public D3D12_RASTERIZER_DESC2 +{ + CD3DX12_RASTERIZER_DESC2() = default; + explicit CD3DX12_RASTERIZER_DESC2(const D3D12_RASTERIZER_DESC2& o) noexcept : + D3D12_RASTERIZER_DESC2(o) + + { + } + explicit CD3DX12_RASTERIZER_DESC2(const D3D12_RASTERIZER_DESC1& o) noexcept + { + FillMode = o.FillMode; + CullMode = o.CullMode; + FrontCounterClockwise = o.FrontCounterClockwise; + DepthBias = o.DepthBias; + DepthBiasClamp = o.DepthBiasClamp; + SlopeScaledDepthBias = o.SlopeScaledDepthBias; + DepthClipEnable = o.DepthClipEnable; + LineRasterizationMode = D3D12_LINE_RASTERIZATION_MODE_ALIASED; + if (o.MultisampleEnable) + { + LineRasterizationMode = D3D12_LINE_RASTERIZATION_MODE_QUADRILATERAL_WIDE; + } + else if (o.AntialiasedLineEnable) + { + LineRasterizationMode = D3D12_LINE_RASTERIZATION_MODE_ALPHA_ANTIALIASED; + } + ForcedSampleCount = o.ForcedSampleCount; + ConservativeRaster = o.ConservativeRaster; + } + explicit CD3DX12_RASTERIZER_DESC2(const D3D12_RASTERIZER_DESC& o) noexcept + : CD3DX12_RASTERIZER_DESC2(CD3DX12_RASTERIZER_DESC1(o)) + { + } + explicit CD3DX12_RASTERIZER_DESC2(CD3DX12_DEFAULT) noexcept + { + FillMode = D3D12_FILL_MODE_SOLID; + CullMode = D3D12_CULL_MODE_BACK; + FrontCounterClockwise = FALSE; + DepthBias = D3D12_DEFAULT_DEPTH_BIAS; + DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP; + SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS; + DepthClipEnable = TRUE; + LineRasterizationMode = D3D12_LINE_RASTERIZATION_MODE_ALIASED; + ForcedSampleCount = 0; + ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; + } + explicit CD3DX12_RASTERIZER_DESC2( + D3D12_FILL_MODE fillMode, + D3D12_CULL_MODE cullMode, + BOOL frontCounterClockwise, + FLOAT depthBias, + FLOAT depthBiasClamp, + FLOAT slopeScaledDepthBias, + BOOL depthClipEnable, + D3D12_LINE_RASTERIZATION_MODE lineRasterizationMode, + UINT forcedSampleCount, + D3D12_CONSERVATIVE_RASTERIZATION_MODE conservativeRaster) noexcept + { + FillMode = fillMode; + CullMode = cullMode; + FrontCounterClockwise = frontCounterClockwise; + DepthBias = depthBias; + DepthBiasClamp = depthBiasClamp; + SlopeScaledDepthBias = slopeScaledDepthBias; + DepthClipEnable = depthClipEnable; + LineRasterizationMode = lineRasterizationMode; + ForcedSampleCount = forcedSampleCount; + ConservativeRaster = conservativeRaster; + } + + + operator D3D12_RASTERIZER_DESC1() const noexcept + { + D3D12_RASTERIZER_DESC1 o; + + o.FillMode = FillMode; + o.CullMode = CullMode; + o.FrontCounterClockwise = FrontCounterClockwise; + o.DepthBias = DepthBias; + o.DepthBiasClamp = DepthBiasClamp; + o.SlopeScaledDepthBias = SlopeScaledDepthBias; + o.DepthClipEnable = DepthClipEnable; + o.MultisampleEnable = FALSE; + o.AntialiasedLineEnable = FALSE; + if (LineRasterizationMode == D3D12_LINE_RASTERIZATION_MODE_ALPHA_ANTIALIASED) + { + o.AntialiasedLineEnable = TRUE; + } + else if (LineRasterizationMode != D3D12_LINE_RASTERIZATION_MODE_ALIASED) + { + o.MultisampleEnable = TRUE; + } + o.ForcedSampleCount = ForcedSampleCount; + o.ConservativeRaster = ConservativeRaster; + + return o; + } + operator D3D12_RASTERIZER_DESC() const noexcept + { + return (D3D12_RASTERIZER_DESC)CD3DX12_RASTERIZER_DESC1((D3D12_RASTERIZER_DESC1)*this); + } +}; +#endif // D3D12_SDK_VERSION >= 610 + //------------------------------------------------------------------------------------------------ struct CD3DX12_RESOURCE_ALLOCATION_INFO : public D3D12_RESOURCE_ALLOCATION_INFO { @@ -669,6 +775,9 @@ struct CD3DX12_HEAP_PROPERTIES : public D3D12_HEAP_PROPERTIES bool IsCPUAccessible() const noexcept { return Type == D3D12_HEAP_TYPE_UPLOAD || Type == D3D12_HEAP_TYPE_READBACK +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609) + || Type == D3D12_HEAP_TYPE_GPU_UPLOAD +#endif || (Type == D3D12_HEAP_TYPE_CUSTOM && (CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE || CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_BACK)); } @@ -1423,4 +1532,4 @@ struct CD3DX12_RT_FORMAT_ARRAY : public D3D12_RT_FORMAT_ARRAY memcpy(RTFormats, pFormats, sizeof(RTFormats)); // assumes ARRAY_SIZE(pFormats) == ARRAY_SIZE(RTFormats) } -}; +}; \ No newline at end of file diff --git a/WickedEngine/Utility/dx12/d3dx12_pipeline_state_stream.h b/WickedEngine/Utility/dx12/d3dx12_pipeline_state_stream.h index bd0f512b2..f061e7959 100644 --- a/WickedEngine/Utility/dx12/d3dx12_pipeline_state_stream.h +++ b/WickedEngine/Utility/dx12/d3dx12_pipeline_state_stream.h @@ -69,6 +69,9 @@ typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< CD3DX12_RASTERIZER_DESC, #if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 608) typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< CD3DX12_RASTERIZER_DESC1, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER1, CD3DX12_DEFAULT> CD3DX12_PIPELINE_STATE_STREAM_RASTERIZER1; #endif +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 610) +typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< CD3DX12_RASTERIZER_DESC2, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER2, CD3DX12_DEFAULT> CD3DX12_PIPELINE_STATE_STREAM_RASTERIZER2; +#endif typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_RT_FORMAT_ARRAY, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RENDER_TARGET_FORMATS> CD3DX12_PIPELINE_STATE_STREAM_RENDER_TARGET_FORMATS; typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< DXGI_SAMPLE_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_DESC, DefaultSampleDesc> CD3DX12_PIPELINE_STATE_STREAM_SAMPLE_DESC; typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< UINT, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_MASK, DefaultSampleMask> CD3DX12_PIPELINE_STATE_STREAM_SAMPLE_MASK; @@ -105,7 +108,10 @@ struct ID3DX12PipelineParserCallbacks virtual void DSVFormatCb(DXGI_FORMAT) {} virtual void RasterizerStateCb(const D3D12_RASTERIZER_DESC&) {} #if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 608) - virtual void RasterizerState2Cb(const D3D12_RASTERIZER_DESC1&) {} + virtual void RasterizerState1Cb(const D3D12_RASTERIZER_DESC1&) {} +#endif +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 610) + virtual void RasterizerState2Cb(const D3D12_RASTERIZER_DESC2&) {} #endif virtual void RTVFormatsCb(const D3D12_RT_FORMAT_ARRAY&) {} virtual void SampleDescCb(const DXGI_SAMPLE_DESC&) {} @@ -141,6 +147,131 @@ struct D3DX12_MESH_SHADER_PIPELINE_STATE_DESC D3D12_PIPELINE_STATE_FLAGS Flags; }; +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 610) +// Use CD3DX12_PIPELINE_STATE_STREAM5 for D3D12_RASTERIZER_DESC2 when CheckFeatureSupport returns true for Options19::RasterizerDesc2Supported is true +// Use CD3DX12_PIPELINE_STATE_STREAM4 for D3D12_RASTERIZER_DESC1 when CheckFeatureSupport returns true for Options16::DynamicDepthBiasSupported is true +// Use CD3DX12_PIPELINE_STATE_STREAM3 for D3D12_DEPTH_STENCIL_DESC2 when CheckFeatureSupport returns true for Options14::IndependentFrontAndBackStencilSupported is true +// Use CD3DX12_PIPELINE_STATE_STREAM2 for OS Build 19041+ (where there is a new mesh shader pipeline). +// Use CD3DX12_PIPELINE_STATE_STREAM1 for OS Build 16299+ (where there is a new view instancing subobject). +// Use CD3DX12_PIPELINE_STATE_STREAM for OS Build 15063+ support. +struct CD3DX12_PIPELINE_STATE_STREAM5 +{ + CD3DX12_PIPELINE_STATE_STREAM5() = default; + // Mesh and amplification shaders must be set manually, since they do not have representation in D3D12_GRAPHICS_PIPELINE_STATE_DESC + CD3DX12_PIPELINE_STATE_STREAM5(const D3D12_GRAPHICS_PIPELINE_STATE_DESC& Desc) noexcept + : Flags(Desc.Flags) + , NodeMask(Desc.NodeMask) + , pRootSignature(Desc.pRootSignature) + , InputLayout(Desc.InputLayout) + , IBStripCutValue(Desc.IBStripCutValue) + , PrimitiveTopologyType(Desc.PrimitiveTopologyType) + , VS(Desc.VS) + , GS(Desc.GS) + , StreamOutput(Desc.StreamOutput) + , HS(Desc.HS) + , DS(Desc.DS) + , PS(Desc.PS) + , BlendState(CD3DX12_BLEND_DESC(Desc.BlendState)) + , DepthStencilState(CD3DX12_DEPTH_STENCIL_DESC2(Desc.DepthStencilState)) + , DSVFormat(Desc.DSVFormat) + , RasterizerState(CD3DX12_RASTERIZER_DESC2(Desc.RasterizerState)) + , RTVFormats(CD3DX12_RT_FORMAT_ARRAY(Desc.RTVFormats, Desc.NumRenderTargets)) + , SampleDesc(Desc.SampleDesc) + , SampleMask(Desc.SampleMask) + , CachedPSO(Desc.CachedPSO) + , ViewInstancingDesc(CD3DX12_VIEW_INSTANCING_DESC(CD3DX12_DEFAULT())) + {} + CD3DX12_PIPELINE_STATE_STREAM5(const D3DX12_MESH_SHADER_PIPELINE_STATE_DESC& Desc) noexcept + : Flags(Desc.Flags) + , NodeMask(Desc.NodeMask) + , pRootSignature(Desc.pRootSignature) + , PrimitiveTopologyType(Desc.PrimitiveTopologyType) + , PS(Desc.PS) + , AS(Desc.AS) + , MS(Desc.MS) + , BlendState(CD3DX12_BLEND_DESC(Desc.BlendState)) + , DepthStencilState(CD3DX12_DEPTH_STENCIL_DESC2(Desc.DepthStencilState)) + , DSVFormat(Desc.DSVFormat) + , RasterizerState(CD3DX12_RASTERIZER_DESC2(Desc.RasterizerState)) + , RTVFormats(CD3DX12_RT_FORMAT_ARRAY(Desc.RTVFormats, Desc.NumRenderTargets)) + , SampleDesc(Desc.SampleDesc) + , SampleMask(Desc.SampleMask) + , CachedPSO(Desc.CachedPSO) + , ViewInstancingDesc(CD3DX12_VIEW_INSTANCING_DESC(CD3DX12_DEFAULT())) + {} + CD3DX12_PIPELINE_STATE_STREAM5(const D3D12_COMPUTE_PIPELINE_STATE_DESC& Desc) noexcept + : Flags(Desc.Flags) + , NodeMask(Desc.NodeMask) + , pRootSignature(Desc.pRootSignature) + , CS(CD3DX12_SHADER_BYTECODE(Desc.CS)) + , CachedPSO(Desc.CachedPSO) + { + static_cast(DepthStencilState).DepthEnable = false; + } + CD3DX12_PIPELINE_STATE_STREAM_FLAGS Flags; + CD3DX12_PIPELINE_STATE_STREAM_NODE_MASK NodeMask; + CD3DX12_PIPELINE_STATE_STREAM_ROOT_SIGNATURE pRootSignature; + CD3DX12_PIPELINE_STATE_STREAM_INPUT_LAYOUT InputLayout; + CD3DX12_PIPELINE_STATE_STREAM_IB_STRIP_CUT_VALUE IBStripCutValue; + CD3DX12_PIPELINE_STATE_STREAM_PRIMITIVE_TOPOLOGY PrimitiveTopologyType; + CD3DX12_PIPELINE_STATE_STREAM_VS VS; + CD3DX12_PIPELINE_STATE_STREAM_GS GS; + CD3DX12_PIPELINE_STATE_STREAM_STREAM_OUTPUT StreamOutput; + CD3DX12_PIPELINE_STATE_STREAM_HS HS; + CD3DX12_PIPELINE_STATE_STREAM_DS DS; + CD3DX12_PIPELINE_STATE_STREAM_PS PS; + CD3DX12_PIPELINE_STATE_STREAM_AS AS; + CD3DX12_PIPELINE_STATE_STREAM_MS MS; + CD3DX12_PIPELINE_STATE_STREAM_CS CS; + CD3DX12_PIPELINE_STATE_STREAM_BLEND_DESC BlendState; + CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL2 DepthStencilState; + CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL_FORMAT DSVFormat; + CD3DX12_PIPELINE_STATE_STREAM_RASTERIZER2 RasterizerState; + CD3DX12_PIPELINE_STATE_STREAM_RENDER_TARGET_FORMATS RTVFormats; + CD3DX12_PIPELINE_STATE_STREAM_SAMPLE_DESC SampleDesc; + CD3DX12_PIPELINE_STATE_STREAM_SAMPLE_MASK SampleMask; + CD3DX12_PIPELINE_STATE_STREAM_CACHED_PSO CachedPSO; + CD3DX12_PIPELINE_STATE_STREAM_VIEW_INSTANCING ViewInstancingDesc; + + D3D12_GRAPHICS_PIPELINE_STATE_DESC GraphicsDescV0() const noexcept + { + D3D12_GRAPHICS_PIPELINE_STATE_DESC D; + D.Flags = this->Flags; + D.NodeMask = this->NodeMask; + D.pRootSignature = this->pRootSignature; + D.InputLayout = this->InputLayout; + D.IBStripCutValue = this->IBStripCutValue; + D.PrimitiveTopologyType = this->PrimitiveTopologyType; + D.VS = this->VS; + D.GS = this->GS; + D.StreamOutput = this->StreamOutput; + D.HS = this->HS; + D.DS = this->DS; + D.PS = this->PS; + D.BlendState = this->BlendState; + D.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC2(D3D12_DEPTH_STENCIL_DESC2(this->DepthStencilState)); + D.DSVFormat = this->DSVFormat; + D.RasterizerState = CD3DX12_RASTERIZER_DESC2(D3D12_RASTERIZER_DESC2(this->RasterizerState)); + D.NumRenderTargets = D3D12_RT_FORMAT_ARRAY(this->RTVFormats).NumRenderTargets; + memcpy(D.RTVFormats, D3D12_RT_FORMAT_ARRAY(this->RTVFormats).RTFormats, sizeof(D.RTVFormats)); + D.SampleDesc = this->SampleDesc; + D.SampleMask = this->SampleMask; + D.CachedPSO = this->CachedPSO; + return D; + } + D3D12_COMPUTE_PIPELINE_STATE_DESC ComputeDescV0() const noexcept + { + D3D12_COMPUTE_PIPELINE_STATE_DESC D; + D.Flags = this->Flags; + D.NodeMask = this->NodeMask; + D.pRootSignature = this->pRootSignature; + D.CS = this->CS; + D.CachedPSO = this->CachedPSO; + return D; + } +}; +#endif // D3D12_SDK_VERSION >= 610 + #if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 608) // Use CD3DX12_PIPELINE_STATE_STREAM4 for D3D12_RASTERIZER_DESC1 when CheckFeatureSupport returns true for Options16::DynamicDepthBiasSupported is true // Use CD3DX12_PIPELINE_STATE_STREAM3 for D3D12_DEPTH_STENCIL_DESC2 when CheckFeatureSupport returns true for Options14::IndependentFrontAndBackStencilSupported is true @@ -955,7 +1086,7 @@ struct CD3DX12_PIPELINE_STATE_STREAM4_PARSE_HELPER : public ID3DX12PipelineParse } } void RasterizerStateCb(const D3D12_RASTERIZER_DESC& RasterizerState) override { PipelineStream.RasterizerState = CD3DX12_RASTERIZER_DESC1(RasterizerState); } - void RasterizerState2Cb(const D3D12_RASTERIZER_DESC1& RasterizerState) override { PipelineStream.RasterizerState = CD3DX12_RASTERIZER_DESC1(RasterizerState); } + void RasterizerState1Cb(const D3D12_RASTERIZER_DESC1& RasterizerState) override { PipelineStream.RasterizerState = CD3DX12_RASTERIZER_DESC1(RasterizerState); } void RTVFormatsCb(const D3D12_RT_FORMAT_ARRAY& RTVFormats) override { PipelineStream.RTVFormats = RTVFormats; } void SampleDescCb(const DXGI_SAMPLE_DESC& SampleDesc) override { PipelineStream.SampleDesc = SampleDesc; } void SampleMaskCb(UINT SampleMask) override { PipelineStream.SampleMask = SampleMask; } @@ -967,6 +1098,75 @@ private: }; #endif // D3D12_SDK_VERSION >= 608 +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 610) +struct CD3DX12_PIPELINE_STATE_STREAM5_PARSE_HELPER : public ID3DX12PipelineParserCallbacks +{ + CD3DX12_PIPELINE_STATE_STREAM5 PipelineStream; + CD3DX12_PIPELINE_STATE_STREAM5_PARSE_HELPER() noexcept + : SeenDSS(false) + { + // Adjust defaults to account for absent members. + PipelineStream.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + + // Depth disabled if no DSV format specified. + static_cast(PipelineStream.DepthStencilState).DepthEnable = false; + } + + // ID3DX12PipelineParserCallbacks + void FlagsCb(D3D12_PIPELINE_STATE_FLAGS Flags) override { PipelineStream.Flags = Flags; } + void NodeMaskCb(UINT NodeMask) override { PipelineStream.NodeMask = NodeMask; } + void RootSignatureCb(ID3D12RootSignature* pRootSignature) override { PipelineStream.pRootSignature = pRootSignature; } + void InputLayoutCb(const D3D12_INPUT_LAYOUT_DESC& InputLayout) override { PipelineStream.InputLayout = InputLayout; } + void IBStripCutValueCb(D3D12_INDEX_BUFFER_STRIP_CUT_VALUE IBStripCutValue) override { PipelineStream.IBStripCutValue = IBStripCutValue; } + void PrimitiveTopologyTypeCb(D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimitiveTopologyType) override { PipelineStream.PrimitiveTopologyType = PrimitiveTopologyType; } + void VSCb(const D3D12_SHADER_BYTECODE& VS) override { PipelineStream.VS = VS; } + void GSCb(const D3D12_SHADER_BYTECODE& GS) override { PipelineStream.GS = GS; } + void StreamOutputCb(const D3D12_STREAM_OUTPUT_DESC& StreamOutput) override { PipelineStream.StreamOutput = StreamOutput; } + void HSCb(const D3D12_SHADER_BYTECODE& HS) override { PipelineStream.HS = HS; } + void DSCb(const D3D12_SHADER_BYTECODE& DS) override { PipelineStream.DS = DS; } + void PSCb(const D3D12_SHADER_BYTECODE& PS) override { PipelineStream.PS = PS; } + void CSCb(const D3D12_SHADER_BYTECODE& CS) override { PipelineStream.CS = CS; } + void ASCb(const D3D12_SHADER_BYTECODE& AS) override { PipelineStream.AS = AS; } + void MSCb(const D3D12_SHADER_BYTECODE& MS) override { PipelineStream.MS = MS; } + void BlendStateCb(const D3D12_BLEND_DESC& BlendState) override { PipelineStream.BlendState = CD3DX12_BLEND_DESC(BlendState); } + void DepthStencilStateCb(const D3D12_DEPTH_STENCIL_DESC& DepthStencilState) override + { + PipelineStream.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC2(DepthStencilState); + SeenDSS = true; + } + void DepthStencilState1Cb(const D3D12_DEPTH_STENCIL_DESC1& DepthStencilState) override + { + PipelineStream.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC2(DepthStencilState); + SeenDSS = true; + } + void DepthStencilState2Cb(const D3D12_DEPTH_STENCIL_DESC2& DepthStencilState) override + { + PipelineStream.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC2(DepthStencilState); + SeenDSS = true; + } + void DSVFormatCb(DXGI_FORMAT DSVFormat) override + { + PipelineStream.DSVFormat = DSVFormat; + if (!SeenDSS && DSVFormat != DXGI_FORMAT_UNKNOWN) + { + // Re-enable depth for the default state. + static_cast(PipelineStream.DepthStencilState).DepthEnable = true; + } + } + void RasterizerStateCb(const D3D12_RASTERIZER_DESC& RasterizerState) override { PipelineStream.RasterizerState = CD3DX12_RASTERIZER_DESC2(RasterizerState); } + void RasterizerState1Cb(const D3D12_RASTERIZER_DESC1& RasterizerState) override { PipelineStream.RasterizerState = CD3DX12_RASTERIZER_DESC2(RasterizerState); } + void RasterizerState2Cb(const D3D12_RASTERIZER_DESC2& RasterizerState) override { PipelineStream.RasterizerState = CD3DX12_RASTERIZER_DESC2(RasterizerState); } + void RTVFormatsCb(const D3D12_RT_FORMAT_ARRAY& RTVFormats) override { PipelineStream.RTVFormats = RTVFormats; } + void SampleDescCb(const DXGI_SAMPLE_DESC& SampleDesc) override { PipelineStream.SampleDesc = SampleDesc; } + void SampleMaskCb(UINT SampleMask) override { PipelineStream.SampleMask = SampleMask; } + void ViewInstancingCb(const D3D12_VIEW_INSTANCING_DESC& ViewInstancingDesc) override { PipelineStream.ViewInstancingDesc = CD3DX12_VIEW_INSTANCING_DESC(ViewInstancingDesc); } + void CachedPSOCb(const D3D12_CACHED_PIPELINE_STATE& CachedPSO) override { PipelineStream.CachedPSO = CachedPSO; } + +private: + bool SeenDSS; +}; +#endif // D3D12_SDK_VERSION >= 610 + struct CD3DX12_PIPELINE_STATE_STREAM_PARSE_HELPER : public ID3DX12PipelineParserCallbacks { CD3DX12_PIPELINE_STATE_STREAM1 PipelineStream; @@ -1129,9 +1329,15 @@ inline HRESULT D3DX12ParsePipelineStream(const D3D12_PIPELINE_STATE_STREAM_DESC& break; #if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 608) case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER1: - pCallbacks->RasterizerState2Cb(*reinterpret_cast(pStream)); + pCallbacks->RasterizerState1Cb(*reinterpret_cast(pStream)); SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM4::RasterizerState); break; +#endif +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 610) + case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER2: + pCallbacks->RasterizerState2Cb(*reinterpret_cast(pStream)); + SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM5::RasterizerState); + break; #endif case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL: pCallbacks->DepthStencilStateCb(*reinterpret_cast(pStream)); diff --git a/WickedEngine/Utility/dx12/d3dx12_property_format_table.h b/WickedEngine/Utility/dx12/d3dx12_property_format_table.h index fc0560d35..301100c03 100644 --- a/WickedEngine/Utility/dx12/d3dx12_property_format_table.h +++ b/WickedEngine/Utility/dx12/d3dx12_property_format_table.h @@ -80,7 +80,7 @@ public: static UINT GetWidthAlignment (DXGI_FORMAT Format); static UINT GetHeightAlignment (DXGI_FORMAT Format); static UINT GetDepthAlignment (DXGI_FORMAT Format); - static BOOL Planar (DXGI_FORMAT Format); + static BOOL Planar (DXGI_FORMAT Format); static BOOL NonOpaquePlanar (DXGI_FORMAT Format); static BOOL YUV (DXGI_FORMAT Format); static BOOL Opaque (DXGI_FORMAT Format); @@ -120,4 +120,5 @@ private: static const FORMAT_DETAIL* GetFormatDetail (DXGI_FORMAT Format); }; + #endif \ No newline at end of file diff --git a/WickedEngine/Utility/dx12/d3dx12_render_pass.h b/WickedEngine/Utility/dx12/d3dx12_render_pass.h index 942ede7f5..fc032f86c 100644 --- a/WickedEngine/Utility/dx12/d3dx12_render_pass.h +++ b/WickedEngine/Utility/dx12/d3dx12_render_pass.h @@ -12,11 +12,28 @@ #endif #include "d3d12.h" +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609) +inline bool operator==(const D3D12_RENDER_PASS_BEGINNING_ACCESS_PRESERVE_LOCAL_PARAMETERS& a, const D3D12_RENDER_PASS_ENDING_ACCESS_PRESERVE_LOCAL_PARAMETERS& b) noexcept +{ + return ((a.AdditionalWidth == b.AdditionalWidth) && (a.AdditionalHeight == b.AdditionalHeight)); +} + +inline bool operator==(const D3D12_RENDER_PASS_BEGINNING_ACCESS_PRESERVE_LOCAL_PARAMETERS& a, const D3D12_RENDER_PASS_BEGINNING_ACCESS_PRESERVE_LOCAL_PARAMETERS& b) noexcept +{ + return ((a.AdditionalWidth == b.AdditionalWidth) && (a.AdditionalHeight == b.AdditionalHeight)); +} + +inline bool operator==(const D3D12_RENDER_PASS_ENDING_ACCESS_PRESERVE_LOCAL_PARAMETERS& a, const D3D12_RENDER_PASS_ENDING_ACCESS_PRESERVE_LOCAL_PARAMETERS& b) noexcept +{ + return ((a.AdditionalWidth == b.AdditionalWidth) && (a.AdditionalHeight == b.AdditionalHeight)); +} +#endif inline bool operator==( const D3D12_RENDER_PASS_BEGINNING_ACCESS_CLEAR_PARAMETERS &a, const D3D12_RENDER_PASS_BEGINNING_ACCESS_CLEAR_PARAMETERS &b) noexcept { return a.ClearValue == b.ClearValue; } + inline bool operator==( const D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_PARAMETERS &a, const D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_PARAMETERS &b) noexcept { if (a.pSrcResource != b.pSrcResource) return false; @@ -27,18 +44,46 @@ inline bool operator==( const D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_PARAMETERS if (a.PreserveResolveSource != b.PreserveResolveSource) return false; return true; } + inline bool operator==( const D3D12_RENDER_PASS_BEGINNING_ACCESS &a, const D3D12_RENDER_PASS_BEGINNING_ACCESS &b) noexcept { if (a.Type != b.Type) return false; - if (a.Type == D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR && !(a.Clear == b.Clear)) return false; + switch (a.Type) + { + case D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR: + if (!(a.Clear == b.Clear)) return false; + break; +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609) + case D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE_LOCAL_RENDER: + case D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE_LOCAL_SRV: + case D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE_LOCAL_UAV: + if (!(a.PreserveLocal == b.PreserveLocal)) return false; + break; +#endif + } return true; } -inline bool operator==( const D3D12_RENDER_PASS_ENDING_ACCESS &a, const D3D12_RENDER_PASS_ENDING_ACCESS &b) noexcept + +inline bool operator==(const D3D12_RENDER_PASS_ENDING_ACCESS& a, const D3D12_RENDER_PASS_ENDING_ACCESS& b) noexcept { if (a.Type != b.Type) return false; - if (a.Type == D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_RESOLVE && !(a.Resolve == b.Resolve)) return false; + switch (a.Type) + { + case D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_RESOLVE: + if (!(a.Resolve == b.Resolve)) return false; + break; +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609) + case D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE_LOCAL_RENDER: + case D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE_LOCAL_SRV: + case D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE_LOCAL_UAV: + if (!(a.PreserveLocal == b.PreserveLocal)) return false; + break; +#endif + } + return true; } + inline bool operator==( const D3D12_RENDER_PASS_RENDER_TARGET_DESC &a, const D3D12_RENDER_PASS_RENDER_TARGET_DESC &b) noexcept { if (a.cpuDescriptor.ptr != b.cpuDescriptor.ptr) return false; diff --git a/WickedEngine/Utility/dx12/d3dx12_resource_helpers.h b/WickedEngine/Utility/dx12/d3dx12_resource_helpers.h index 685d7e678..902ec0cd6 100644 --- a/WickedEngine/Utility/dx12/d3dx12_resource_helpers.h +++ b/WickedEngine/Utility/dx12/d3dx12_resource_helpers.h @@ -400,10 +400,11 @@ inline const CD3DX12_RESOURCE_DESC1* D3DX12ConditionallyExpandAPIDesc( return D3DX12ConditionallyExpandAPIDesc(static_cast(LclDesc), static_cast(pDesc)); } +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 606) //------------------------------------------------------------------------------------------------ -// The difference between D3DX12GetCopyableFootprints and ID3D12Device::GetCopyableFootprints +// The difference between D3DX12GetCopyableFootprints and ID3D12Device::GetCopyableFootprints // is that this one loses a lot of error checking by assuming the arguments are correct -inline bool D3DX12GetCopyableFootprints( +inline bool D3DX12GetCopyableFootprints( _In_ const D3D12_RESOURCE_DESC1& ResourceDesc, _In_range_(0, D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, _In_range_(0, D3D12_REQ_SUBRESOURCES - FirstSubresource) UINT NumSubresources, @@ -470,16 +471,16 @@ inline bool D3DX12GetCopyableFootprints( UINT MinPlaneRowPitch = 0; D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::CalculateMinimumRowMajorRowPitch(PlaneFormat, MinPlanePitchWidth, MinPlaneRowPitch); - // Formats with more than one plane choose a larger pitch alignment to ensure that each plane begins on the row + // Formats with more than one plane choose a larger pitch alignment to ensure that each plane begins on the row // immediately following the previous plane while still adhering to subresource alignment restrictions. - static_assert( D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT >= D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - && ((D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT % D3D12_TEXTURE_DATA_PITCH_ALIGNMENT) == 0), + static_assert( D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT >= D3D12_TEXTURE_DATA_PITCH_ALIGNMENT + && ((D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT % D3D12_TEXTURE_DATA_PITCH_ALIGNMENT) == 0), "D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT must be >= and evenly divisible by D3D12_TEXTURE_DATA_PITCH_ALIGNMENT." ); - Placement.RowPitch = D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::Planar(Format) + Placement.RowPitch = D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::Planar(Format) ? D3DX12Align< UINT >( MinPlaneRowPitch, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT ) : D3DX12Align< UINT >( MinPlaneRowPitch, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT ); - + if (pRowSizeInBytes) { UINT PlaneRowSize = 0; @@ -499,7 +500,7 @@ inline bool D3DX12GetCopyableFootprints( D3DX12_ASSERT(Height % HeightAlignment == 0); NumRows = Height / HeightAlignment; } - + if (pNumRows) { pNumRows[uSubRes] = NumRows; @@ -522,7 +523,7 @@ inline bool D3DX12GetCopyableFootprints( } bResourceOverflow = bResourceOverflow || bOverflow; } - + // Overflow error if (bResourceOverflow) { @@ -556,7 +557,7 @@ inline bool D3DX12GetCopyableFootprints( //------------------------------------------------------------------------------------------------ inline D3D12_RESOURCE_DESC1 D3DX12ResourceDesc0ToDesc1(D3D12_RESOURCE_DESC const& desc0) { - D3D12_RESOURCE_DESC1 desc1; + D3D12_RESOURCE_DESC1 desc1; desc1.Dimension = desc0.Dimension; desc1.Alignment = desc0.Alignment; desc1.Width = desc0.Width; @@ -597,3 +598,5 @@ inline bool D3DX12GetCopyableFootprints( pRowSizeInBytes, pTotalBytes); } + +#endif // D3D12_SDK_VERSION >= 606 diff --git a/WickedEngine/Utility/dx12/d3dx12_root_signature.h b/WickedEngine/Utility/dx12/d3dx12_root_signature.h index 9d3589733..48b347093 100644 --- a/WickedEngine/Utility/dx12/d3dx12_root_signature.h +++ b/WickedEngine/Utility/dx12/d3dx12_root_signature.h @@ -361,6 +361,120 @@ struct CD3DX12_STATIC_SAMPLER_DESC : public D3D12_STATIC_SAMPLER_DESC } }; +//------------------------------------------------------------------------------------------------ +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609) +struct CD3DX12_STATIC_SAMPLER_DESC1 : public D3D12_STATIC_SAMPLER_DESC1 +{ + CD3DX12_STATIC_SAMPLER_DESC1() = default; + explicit CD3DX12_STATIC_SAMPLER_DESC1(const D3D12_STATIC_SAMPLER_DESC &o) noexcept + { + memcpy(this, &o, sizeof(D3D12_STATIC_SAMPLER_DESC)); + Flags = D3D12_SAMPLER_FLAGS::D3D12_SAMPLER_FLAG_NONE; + } + explicit CD3DX12_STATIC_SAMPLER_DESC1(const D3D12_STATIC_SAMPLER_DESC1 & o) noexcept : + D3D12_STATIC_SAMPLER_DESC1(o) + {} + CD3DX12_STATIC_SAMPLER_DESC1( + UINT shaderRegister, + D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC, + D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + FLOAT mipLODBias = 0, + UINT maxAnisotropy = 16, + D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL, + D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE, + FLOAT minLOD = 0.f, + FLOAT maxLOD = D3D12_FLOAT32_MAX, + D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, + UINT registerSpace = 0, + D3D12_SAMPLER_FLAGS flags = D3D12_SAMPLER_FLAGS::D3D12_SAMPLER_FLAG_NONE) noexcept + { + Init( + shaderRegister, + filter, + addressU, + addressV, + addressW, + mipLODBias, + maxAnisotropy, + comparisonFunc, + borderColor, + minLOD, + maxLOD, + shaderVisibility, + registerSpace, + flags); + } + + static inline void Init( + _Out_ D3D12_STATIC_SAMPLER_DESC1 &samplerDesc, + UINT shaderRegister, + D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC, + D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + FLOAT mipLODBias = 0, + UINT maxAnisotropy = 16, + D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL, + D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE, + FLOAT minLOD = 0.f, + FLOAT maxLOD = D3D12_FLOAT32_MAX, + D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, + UINT registerSpace = 0, + D3D12_SAMPLER_FLAGS flags = D3D12_SAMPLER_FLAGS::D3D12_SAMPLER_FLAG_NONE) noexcept + { + samplerDesc.ShaderRegister = shaderRegister; + samplerDesc.Filter = filter; + samplerDesc.AddressU = addressU; + samplerDesc.AddressV = addressV; + samplerDesc.AddressW = addressW; + samplerDesc.MipLODBias = mipLODBias; + samplerDesc.MaxAnisotropy = maxAnisotropy; + samplerDesc.ComparisonFunc = comparisonFunc; + samplerDesc.BorderColor = borderColor; + samplerDesc.MinLOD = minLOD; + samplerDesc.MaxLOD = maxLOD; + samplerDesc.ShaderVisibility = shaderVisibility; + samplerDesc.RegisterSpace = registerSpace; + samplerDesc.Flags = flags; + } + inline void Init( + UINT shaderRegister, + D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC, + D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + FLOAT mipLODBias = 0, + UINT maxAnisotropy = 16, + D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL, + D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE, + FLOAT minLOD = 0.f, + FLOAT maxLOD = D3D12_FLOAT32_MAX, + D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, + UINT registerSpace = 0, + D3D12_SAMPLER_FLAGS flags = D3D12_SAMPLER_FLAGS::D3D12_SAMPLER_FLAG_NONE) noexcept + { + Init( + *this, + shaderRegister, + filter, + addressU, + addressV, + addressW, + mipLODBias, + maxAnisotropy, + comparisonFunc, + borderColor, + minLOD, + maxLOD, + shaderVisibility, + registerSpace, + flags); + } +}; +#endif // D3D12_SDK_VERSION >= 609 + //------------------------------------------------------------------------------------------------ struct CD3DX12_ROOT_SIGNATURE_DESC : public D3D12_ROOT_SIGNATURE_DESC { @@ -653,6 +767,13 @@ struct CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC : public D3D12_VERSIONED_ROOT_SIGNA Version = D3D_ROOT_SIGNATURE_VERSION_1_1; Desc_1_1 = o; } +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609) + explicit CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(const D3D12_ROOT_SIGNATURE_DESC2& o) noexcept + { + Version = D3D_ROOT_SIGNATURE_VERSION_1_2; + Desc_1_2 = o; + } +#endif CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC( UINT numParameters, _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters, @@ -727,6 +848,24 @@ struct CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC : public D3D12_VERSIONED_ROOT_SIGNA desc.Desc_1_1.pStaticSamplers = _pStaticSamplers; desc.Desc_1_1.Flags = flags; } + +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609) + static inline void Init_1_2( + _Out_ D3D12_VERSIONED_ROOT_SIGNATURE_DESC& desc, + UINT numParameters, + _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER1* _pParameters, + UINT numStaticSamplers = 0, + _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC1* _pStaticSamplers = nullptr, + D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE) noexcept + { + desc.Version = D3D_ROOT_SIGNATURE_VERSION_1_2; + desc.Desc_1_2.NumParameters = numParameters; + desc.Desc_1_2.pParameters = _pParameters; + desc.Desc_1_2.NumStaticSamplers = numStaticSamplers; + desc.Desc_1_2.pStaticSamplers = _pStaticSamplers; + desc.Desc_1_2.Flags = flags; + } +#endif }; //------------------------------------------------------------------------------------------------ @@ -876,6 +1015,9 @@ inline HRESULT D3DX12SerializeVersionedRootSignature( return D3D12SerializeRootSignature(&pRootSignatureDesc->Desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob); case D3D_ROOT_SIGNATURE_VERSION_1_1: +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609) + case D3D_ROOT_SIGNATURE_VERSION_1_2: +#endif { HRESULT hr = S_OK; const D3D12_ROOT_SIGNATURE_DESC1& desc_1_1 = pRootSignatureDesc->Desc_1_1; @@ -942,9 +1084,36 @@ inline HRESULT D3DX12SerializeVersionedRootSignature( } } + D3D12_STATIC_SAMPLER_DESC* pStaticSamplers = nullptr; +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609) + if (desc_1_1.NumStaticSamplers > 0 && pRootSignatureDesc->Version == D3D_ROOT_SIGNATURE_VERSION_1_2) + { + const SIZE_T SamplersSize = sizeof(D3D12_STATIC_SAMPLER_DESC) * desc_1_1.NumStaticSamplers; + pStaticSamplers = static_cast(HeapAlloc(GetProcessHeap(), 0, SamplersSize)); + + if (pStaticSamplers == nullptr) + { + hr = E_OUTOFMEMORY; + } + else + { + const D3D12_ROOT_SIGNATURE_DESC2& desc_1_2 = pRootSignatureDesc->Desc_1_2; + for (UINT n = 0; n < desc_1_1.NumStaticSamplers; ++n) + { + if ((desc_1_2.pStaticSamplers[n].Flags & ~D3D12_SAMPLER_FLAG_UINT_BORDER_COLOR) != 0) + { + hr = E_INVALIDARG; + break; + } + memcpy(pStaticSamplers + n, desc_1_2.pStaticSamplers + n, sizeof(D3D12_STATIC_SAMPLER_DESC)); + } + } + } +#endif + if (SUCCEEDED(hr)) { - const CD3DX12_ROOT_SIGNATURE_DESC desc_1_0(desc_1_1.NumParameters, pParameters_1_0, desc_1_1.NumStaticSamplers, desc_1_1.pStaticSamplers, desc_1_1.Flags); + const CD3DX12_ROOT_SIGNATURE_DESC desc_1_0(desc_1_1.NumParameters, pParameters_1_0, desc_1_1.NumStaticSamplers, pStaticSamplers == nullptr ? desc_1_1.pStaticSamplers : pStaticSamplers, desc_1_1.Flags); hr = D3D12SerializeRootSignature(&desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob); } @@ -960,12 +1129,21 @@ inline HRESULT D3DX12SerializeVersionedRootSignature( } HeapFree(GetProcessHeap(), 0, pParameters); } + + if (pStaticSamplers) + { + HeapFree(GetProcessHeap(), 0, pStaticSamplers); + } + return hr; } } break; case D3D_ROOT_SIGNATURE_VERSION_1_1: +#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609) + case D3D_ROOT_SIGNATURE_VERSION_1_2: +#endif return D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob); } diff --git a/WickedEngine/Utility/dx12/dxcore.h b/WickedEngine/Utility/dx12/dxcore.h new file mode 100644 index 000000000..4244eaa60 --- /dev/null +++ b/WickedEngine/Utility/dx12/dxcore.h @@ -0,0 +1,41 @@ +/************************************************************ +* * +* Copyright (c) Microsoft Corporation. * +* Licensed under the MIT license. * +* * +************************************************************/ + +#ifndef _DXCOREEXTMODULE_H_ +#define _DXCOREEXTMODULE_H_ + +#include +#include "dxcore_interface.h" + +#pragma region Application Family or OneCore Family +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM) + +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN10) + +STDAPI +DXCoreCreateAdapterFactory( + REFIID riid, + _COM_Outptr_ void** ppvFactory +); + +template +HRESULT +DXCoreCreateAdapterFactory( + _COM_Outptr_ T** ppvFactory +) +{ + return DXCoreCreateAdapterFactory(IID_PPV_ARGS(ppvFactory)); +} + +#endif // (_WIN32_WINNT >= _WIN32_WINNT_WIN10) + +#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM) */ +#pragma endregion + +#endif // _DXCOREEXTMODULE_H_ + + diff --git a/WickedEngine/Utility/dx12/dxcore_interface.h b/WickedEngine/Utility/dx12/dxcore_interface.h new file mode 100644 index 000000000..b487fe13f --- /dev/null +++ b/WickedEngine/Utility/dx12/dxcore_interface.h @@ -0,0 +1,316 @@ +// +// DXCore Interface +// Copyright (C) Microsoft Corporation. +// Licensed under the MIT license. +// + +#ifndef __dxcore_interface_h__ +#define __dxcore_interface_h__ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#include + +#ifdef __cplusplus + +#define _FACDXCORE 0x880 +#define MAKE_DXCORE_HRESULT( code ) MAKE_HRESULT( 1, _FACDXCORE, code ) + +enum class DXCoreAdapterProperty : uint32_t +{ + InstanceLuid = 0, + DriverVersion = 1, + DriverDescription = 2, + HardwareID = 3, // Use HardwareIDParts instead, if available. + KmdModelVersion = 4, + ComputePreemptionGranularity = 5, + GraphicsPreemptionGranularity = 6, + DedicatedAdapterMemory = 7, + DedicatedSystemMemory = 8, + SharedSystemMemory = 9, + AcgCompatible = 10, + IsHardware = 11, + IsIntegrated = 12, + IsDetachable = 13, + HardwareIDParts = 14 +}; + +enum class DXCoreAdapterState : uint32_t +{ + IsDriverUpdateInProgress = 0, + AdapterMemoryBudget = 1 +}; + +enum class DXCoreSegmentGroup : uint32_t +{ + Local = 0, + NonLocal = 1 +}; + +enum class DXCoreNotificationType : uint32_t +{ + AdapterListStale = 0, + AdapterNoLongerValid = 1, + AdapterBudgetChange = 2, + AdapterHardwareContentProtectionTeardown = 3 +}; + +enum class DXCoreAdapterPreference : uint32_t +{ + Hardware = 0, + MinimumPower = 1, + HighPerformance = 2 +}; + +struct DXCoreHardwareID +{ + uint32_t vendorID; + uint32_t deviceID; + uint32_t subSysID; + uint32_t revision; +}; + +struct DXCoreHardwareIDParts +{ + uint32_t vendorID; + uint32_t deviceID; + uint32_t subSystemID; + uint32_t subVendorID; + uint32_t revisionID; +}; + +struct DXCoreAdapterMemoryBudgetNodeSegmentGroup +{ + uint32_t nodeIndex; + DXCoreSegmentGroup segmentGroup; +}; + +struct DXCoreAdapterMemoryBudget +{ + uint64_t budget; + uint64_t currentUsage; + uint64_t availableForReservation; + uint64_t currentReservation; +}; + +typedef void (STDMETHODCALLTYPE *PFN_DXCORE_NOTIFICATION_CALLBACK)( + DXCoreNotificationType notificationType, + _In_ IUnknown *object, + _In_opt_ void *context); + +static_assert(sizeof(bool) == 1, "bool assumed as one byte"); + +DEFINE_GUID(IID_IDXCoreAdapterFactory, 0x78ee5945, 0xc36e, 0x4b13, 0xa6, 0x69, 0x00, 0x5d, 0xd1, 0x1c, 0x0f, 0x06); +DEFINE_GUID(IID_IDXCoreAdapterList, 0x526c7776, 0x40e9, 0x459b, 0xb7, 0x11, 0xf3, 0x2a, 0xd7, 0x6d, 0xfc, 0x28); +DEFINE_GUID(IID_IDXCoreAdapter, 0xf0db4c7f, 0xfe5a, 0x42a2, 0xbd, 0x62, 0xf2, 0xa6, 0xcf, 0x6f, 0xc8, 0x3e); +DEFINE_GUID(DXCORE_ADAPTER_ATTRIBUTE_D3D11_GRAPHICS, 0x8c47866b, 0x7583, 0x450d, 0xf0, 0xf0, 0x6b, 0xad, 0xa8, 0x95, 0xaf, 0x4b); +DEFINE_GUID(DXCORE_ADAPTER_ATTRIBUTE_D3D12_GRAPHICS, 0x0c9ece4d, 0x2f6e, 0x4f01, 0x8c, 0x96, 0xe8, 0x9e, 0x33, 0x1b, 0x47, 0xb1); +DEFINE_GUID(DXCORE_ADAPTER_ATTRIBUTE_D3D12_CORE_COMPUTE, 0x248e2800, 0xa793, 0x4724, 0xab, 0xaa, 0x23, 0xa6, 0xde, 0x1b, 0xe0, 0x90); + +/* interface IDXCoreAdapter */ +MIDL_INTERFACE("f0db4c7f-fe5a-42a2-bd62-f2a6cf6fc83e") +IDXCoreAdapter : public IUnknown +{ +public: + virtual bool STDMETHODCALLTYPE IsValid() = 0; + + virtual bool STDMETHODCALLTYPE IsAttributeSupported( + REFGUID attributeGUID) = 0; + + virtual bool STDMETHODCALLTYPE IsPropertySupported( + DXCoreAdapterProperty property) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetProperty( + DXCoreAdapterProperty property, + size_t bufferSize, + _Out_writes_bytes_(bufferSize) void *propertyData) = 0; + + template + HRESULT GetProperty( + DXCoreAdapterProperty property, + _Out_writes_bytes_(sizeof(T)) T *propertyData) + { + return GetProperty(property, + sizeof(T), + (void*)propertyData); + } + + virtual HRESULT STDMETHODCALLTYPE GetPropertySize( + DXCoreAdapterProperty property, + _Out_ size_t *bufferSize) = 0; + + virtual bool STDMETHODCALLTYPE IsQueryStateSupported( + DXCoreAdapterState property) = 0; + + virtual HRESULT STDMETHODCALLTYPE QueryState( + DXCoreAdapterState state, + size_t inputStateDetailsSize, + _In_reads_bytes_opt_(inputStateDetailsSize) const void *inputStateDetails, + size_t outputBufferSize, + _Out_writes_bytes_(outputBufferSize) void *outputBuffer) = 0; + + template + HRESULT QueryState( + DXCoreAdapterState state, + _In_reads_bytes_opt_(sizeof(T1)) const T1 *inputStateDetails, + _Out_writes_bytes_(sizeof(T2)) T2 *outputBuffer) + { + return QueryState(state, + sizeof(T1), + (const void*)inputStateDetails, + sizeof(T2), + (void*)outputBuffer); + } + + template + HRESULT QueryState( + DXCoreAdapterState state, + _Out_writes_bytes_(sizeof(T)) T *outputBuffer) + { + return QueryState(state, + 0, + nullptr, + sizeof(T), + (void*)outputBuffer); + } + + virtual bool STDMETHODCALLTYPE IsSetStateSupported( + DXCoreAdapterState property) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetState( + DXCoreAdapterState state, + size_t inputStateDetailsSize, + _In_reads_bytes_opt_(inputStateDetailsSize) const void *inputStateDetails, + size_t inputDataSize, + _In_reads_bytes_(inputDataSize) const void *inputData) = 0; + + template + HRESULT SetState( + DXCoreAdapterState state, + const T1 *inputStateDetails, + const T2 *inputData) + { + return SetState(state, + sizeof(T1), + (const void*)inputStateDetails, + sizeof(T2), + (const void*)inputData); + } + + virtual HRESULT STDMETHODCALLTYPE GetFactory( + REFIID riid, + _COM_Outptr_ void** ppvFactory + ) = 0; + + template + HRESULT GetFactory( + _COM_Outptr_ T** ppvFactory + ) + { + return GetFactory(IID_PPV_ARGS(ppvFactory)); + } +}; + +/* interface IDXCoreAdapterList */ +MIDL_INTERFACE("526c7776-40e9-459b-b711-f32ad76dfc28") +IDXCoreAdapterList : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE GetAdapter( + uint32_t index, + REFIID riid, + _COM_Outptr_ void **ppvAdapter) = 0; + + template + HRESULT STDMETHODCALLTYPE GetAdapter( + uint32_t index, + _COM_Outptr_ T **ppvAdapter) + { + return GetAdapter(index, + IID_PPV_ARGS(ppvAdapter)); + } + + virtual uint32_t STDMETHODCALLTYPE GetAdapterCount() = 0; + + virtual bool STDMETHODCALLTYPE IsStale() = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFactory( + REFIID riid, + _COM_Outptr_ void** ppvFactory + ) = 0; + + template + HRESULT GetFactory( + _COM_Outptr_ T** ppvFactory + ) + { + return GetFactory(IID_PPV_ARGS(ppvFactory)); + } + + virtual HRESULT STDMETHODCALLTYPE Sort( + uint32_t numPreferences, + _In_reads_(numPreferences) const DXCoreAdapterPreference* preferences) = 0; + + virtual bool STDMETHODCALLTYPE IsAdapterPreferenceSupported( + DXCoreAdapterPreference preference) = 0; +}; + +/* interface IDXCoreAdapterFactory */ +MIDL_INTERFACE("78ee5945-c36e-4b13-a669-005dd11c0f06") +IDXCoreAdapterFactory : public IUnknown +{ +public: + + virtual HRESULT STDMETHODCALLTYPE CreateAdapterList( + uint32_t numAttributes, + _In_reads_(numAttributes) const GUID *filterAttributes, + REFIID riid, + _COM_Outptr_ void **ppvAdapterList) = 0; + + template + HRESULT STDMETHODCALLTYPE CreateAdapterList( + uint32_t numAttributes, + _In_reads_(numAttributes) const GUID *filterAttributes, + _COM_Outptr_ T **ppvAdapterList) + { + return CreateAdapterList(numAttributes, + filterAttributes, + IID_PPV_ARGS(ppvAdapterList)); + } + + virtual HRESULT STDMETHODCALLTYPE GetAdapterByLuid( + const LUID &adapterLUID, + REFIID riid, + _COM_Outptr_ void **ppvAdapter) = 0; + + template + HRESULT STDMETHODCALLTYPE GetAdapterByLuid( + const LUID &adapterLUID, + _COM_Outptr_ T **ppvAdapter) + { + return GetAdapterByLuid(adapterLUID, + IID_PPV_ARGS(ppvAdapter)); + } + + virtual bool STDMETHODCALLTYPE IsNotificationTypeSupported( + DXCoreNotificationType notificationType) = 0; + + virtual HRESULT STDMETHODCALLTYPE RegisterEventNotification( + _In_ IUnknown *dxCoreObject, + DXCoreNotificationType notificationType, + _In_ PFN_DXCORE_NOTIFICATION_CALLBACK callbackFunction, + _In_opt_ void *callbackContext, + _Out_ uint32_t *eventCookie) = 0; + + virtual HRESULT STDMETHODCALLTYPE UnregisterEventNotification( + uint32_t eventCookie) = 0; +}; + +#endif // __cplusplus + +#endif // __dxcore_interface_h__ + + diff --git a/WickedEngine/Utility/dx12/dxgiformat.h b/WickedEngine/Utility/dx12/dxgiformat.h index 52aae1b2b..83e6c0775 100644 --- a/WickedEngine/Utility/dx12/dxgiformat.h +++ b/WickedEngine/Utility/dx12/dxgiformat.h @@ -135,6 +135,8 @@ typedef enum DXGI_FORMAT DXGI_FORMAT_SAMPLER_FEEDBACK_MIN_MIP_OPAQUE = 189, DXGI_FORMAT_SAMPLER_FEEDBACK_MIP_REGION_USED_OPAQUE = 190, + DXGI_FORMAT_A4B4G4R4_UNORM = 191, + DXGI_FORMAT_FORCE_UINT = 0xffffffff } DXGI_FORMAT; diff --git a/WickedEngine/Utility/dxva.h b/WickedEngine/Utility/dxva.h new file mode 100644 index 000000000..5ea714708 --- /dev/null +++ b/WickedEngine/Utility/dxva.h @@ -0,0 +1,146 @@ +#ifndef DXVA_H +#define DXVA_H +// This is a minimal version of dxva.h from the Windows SDK +// It contains only the bare necessary structures for interoping with DirectX Video APIs + +/* H.264/AVC picture entry data structure */ +#pragma pack(push, BeforeDXVApacking, 1) +typedef struct _DXVA_PicEntry_H264 { + union { + struct { + UCHAR Index7Bits : 7; + UCHAR AssociatedFlag : 1; + }; + UCHAR bPicEntry; + }; +} DXVA_PicEntry_H264, * LPDXVA_PicEntry_H264; /* 1 byte */ +#pragma pack(pop, BeforeDXVApacking) + +/* H.264/AVC picture parameters structure */ +#pragma pack(push, BeforeDXVApacking, 1) +typedef struct _DXVA_PicParams_H264 { + USHORT wFrameWidthInMbsMinus1; + USHORT wFrameHeightInMbsMinus1; + DXVA_PicEntry_H264 CurrPic; /* flag is bot field flag */ + UCHAR num_ref_frames; + + union { + struct { + USHORT field_pic_flag : 1; + USHORT MbaffFrameFlag : 1; + USHORT residual_colour_transform_flag : 1; + USHORT sp_for_switch_flag : 1; + USHORT chroma_format_idc : 2; + USHORT RefPicFlag : 1; + USHORT constrained_intra_pred_flag : 1; + + USHORT weighted_pred_flag : 1; + USHORT weighted_bipred_idc : 2; + USHORT MbsConsecutiveFlag : 1; + USHORT frame_mbs_only_flag : 1; + USHORT transform_8x8_mode_flag : 1; + USHORT MinLumaBipredSize8x8Flag : 1; + USHORT IntraPicFlag : 1; + }; + USHORT wBitFields; + }; + UCHAR bit_depth_luma_minus8; + UCHAR bit_depth_chroma_minus8; + + USHORT Reserved16Bits; + UINT StatusReportFeedbackNumber; + + DXVA_PicEntry_H264 RefFrameList[16]; /* flag LT */ + INT CurrFieldOrderCnt[2]; + INT FieldOrderCntList[16][2]; + + CHAR pic_init_qs_minus26; + CHAR chroma_qp_index_offset; /* also used for QScb */ + CHAR second_chroma_qp_index_offset; /* also for QScr */ + UCHAR ContinuationFlag; + + /* remainder for parsing */ + CHAR pic_init_qp_minus26; + UCHAR num_ref_idx_l0_active_minus1; + UCHAR num_ref_idx_l1_active_minus1; + UCHAR Reserved8BitsA; + + USHORT FrameNumList[16]; + UINT UsedForReferenceFlags; + USHORT NonExistingFrameFlags; + USHORT frame_num; + + UCHAR log2_max_frame_num_minus4; + UCHAR pic_order_cnt_type; + UCHAR log2_max_pic_order_cnt_lsb_minus4; + UCHAR delta_pic_order_always_zero_flag; + + UCHAR direct_8x8_inference_flag; + UCHAR entropy_coding_mode_flag; + UCHAR pic_order_present_flag; + UCHAR num_slice_groups_minus1; + + UCHAR slice_group_map_type; + UCHAR deblocking_filter_control_present_flag; + UCHAR redundant_pic_cnt_present_flag; + UCHAR Reserved8BitsB; + + USHORT slice_group_change_rate_minus1; + + UCHAR SliceGroupMap[810]; /* 4b/sgmu, Size BT.601 */ + +} DXVA_PicParams_H264, * LPDXVA_PicParams_H264; +#pragma pack(pop, BeforeDXVApacking) + +/* H.264/AVC quantization weighting matrix data structure */ +#pragma pack(push, BeforeDXVApacking, 1) +typedef struct _DXVA_Qmatrix_H264 { + UCHAR bScalingLists4x4[6][16]; + UCHAR bScalingLists8x8[2][64]; + +} DXVA_Qmatrix_H264, * LPDXVA_Qmatrix_H264; +#pragma pack(pop, BeforeDXVApacking) + +/* H.264/AVC slice control data structure - short form */ +#pragma pack(push, BeforeDXVApacking, 1) +typedef struct _DXVA_Slice_H264_Short { + UINT BSNALunitDataLocation; /* type 1..5 */ + UINT SliceBytesInBuffer; /* for off-host parse */ + USHORT wBadSliceChopping; /* for off-host parse */ +} DXVA_Slice_H264_Short, * LPDXVA_Slice_H264_Short; +#pragma pack(pop, BeforeDXVApacking) + +/* H.264/AVC picture entry data structure - long form */ +#pragma pack(push, BeforeDXVApacking, 1) +typedef struct _DXVA_Slice_H264_Long { + UINT BSNALunitDataLocation; /* type 1..5 */ + UINT SliceBytesInBuffer; /* for off-host parse */ + USHORT wBadSliceChopping; /* for off-host parse */ + + USHORT first_mb_in_slice; + USHORT NumMbsForSlice; + + USHORT BitOffsetToSliceData; /* after CABAC alignment */ + + UCHAR slice_type; + UCHAR luma_log2_weight_denom; + UCHAR chroma_log2_weight_denom; + UCHAR num_ref_idx_l0_active_minus1; + UCHAR num_ref_idx_l1_active_minus1; + CHAR slice_alpha_c0_offset_div2; + CHAR slice_beta_offset_div2; + UCHAR Reserved8Bits; + DXVA_PicEntry_H264 RefPicList[2][32]; /* L0 & L1 */ + SHORT Weights[2][32][3][2]; /* L0 & L1; Y, Cb, Cr */ + CHAR slice_qs_delta; + /* rest off-host parse */ + CHAR slice_qp_delta; + UCHAR redundant_pic_cnt; + UCHAR direct_spatial_mv_pred_flag; + UCHAR cabac_init_idc; + UCHAR disable_deblocking_filter_idc; + USHORT slice_id; +} DXVA_Slice_H264_Long, * LPDXVA_Slice_H264_Long; +#pragma pack(pop, BeforeDXVApacking) + +#endif // DXVA_H diff --git a/WickedEngine/Utility/h264.h b/WickedEngine/Utility/h264.h new file mode 100644 index 000000000..ef3e2cb77 --- /dev/null +++ b/WickedEngine/Utility/h264.h @@ -0,0 +1,952 @@ +#ifndef H264_H +#define H264_H +// Minimal H264 video parser +// Read the H264 specification: Rec. ITU-T H.264 (08/2021) +// The following library was used as reference: https://github.com/aizvorski/h264bitstream/ +// +// Use this to parse metadata information about a H264 video before passing it to a decoder. +// You can use the following functions to access H264 information: +// +// Create a bitstream to consume binary data: +// Bitstream bs; +// bs.init(data, size); +// +// Then you can read a NAL header after you detected a new NAL unit (starts with h264::start_code bytes): +// void read_nal_header(NALHeader* nal, Bitstream* b); +// +// After the NAL unit type was determined, you can use the following functions to read PPS, SPS and SliceHeaders (depending on NAL unit type): +// void read_pps(PPS* pps, Bitstream* b); +// void read_sps(SPS* sps, Bitstream* b); +// void read_slice_header(SliceHeader* sh, NALHeader* nal, const PPS* pps_array, const SPS* sps_array, Bitstream* b); +// +// Do this before you include this file in *one* C++ file to create the implementation: +// #define H264_IMPLEMENTATION + +#include + +namespace h264 { + static constexpr uint8_t nal_start_code[] = { 0,0,1 }; + + struct SPS + { + int profile_idc; + int constraint_set0_flag; + int constraint_set1_flag; + int constraint_set2_flag; + int constraint_set3_flag; + int constraint_set4_flag; + int constraint_set5_flag; + int reserved_zero_2bits; + int level_idc; + int seq_parameter_set_id; + int chroma_format_idc; + int separate_colour_plane_flag; + int bit_depth_luma_minus8; + int bit_depth_chroma_minus8; + int qpprime_y_zero_transform_bypass_flag; + int seq_scaling_matrix_present_flag; + int seq_scaling_list_present_flag[8]; + int ScalingList4x4[6][16]; + int UseDefaultScalingMatrix4x4Flag[6]; + int ScalingList8x8[2][64]; + int UseDefaultScalingMatrix8x8Flag[2]; + int log2_max_frame_num_minus4; + int pic_order_cnt_type; + int log2_max_pic_order_cnt_lsb_minus4; + int delta_pic_order_always_zero_flag; + int offset_for_non_ref_pic; + int offset_for_top_to_bottom_field; + int num_ref_frames_in_pic_order_cnt_cycle; + int offset_for_ref_frame[256]; + int num_ref_frames; + int gaps_in_frame_num_value_allowed_flag; + int pic_width_in_mbs_minus1; + int pic_height_in_map_units_minus1; + int frame_mbs_only_flag; + int mb_adaptive_frame_field_flag; + int direct_8x8_inference_flag; + int frame_cropping_flag; + int frame_crop_left_offset; + int frame_crop_right_offset; + int frame_crop_top_offset; + int frame_crop_bottom_offset; + int vui_parameters_present_flag; + + struct + { + int aspect_ratio_info_present_flag; + int aspect_ratio_idc; + int sar_width; + int sar_height; + int overscan_info_present_flag; + int overscan_appropriate_flag; + int video_signal_type_present_flag; + int video_format; + int video_full_range_flag; + int colour_description_present_flag; + int colour_primaries; + int transfer_characteristics; + int matrix_coefficients; + int chroma_loc_info_present_flag; + int chroma_sample_loc_type_top_field; + int chroma_sample_loc_type_bottom_field; + int timing_info_present_flag; + int num_units_in_tick; + int time_scale; + int fixed_frame_rate_flag; + int nal_hrd_parameters_present_flag; + int vcl_hrd_parameters_present_flag; + int low_delay_hrd_flag; + int pic_struct_present_flag; + int bitstream_restriction_flag; + int motion_vectors_over_pic_boundaries_flag; + int max_bytes_per_pic_denom; + int max_bits_per_mb_denom; + int log2_max_mv_length_horizontal; + int log2_max_mv_length_vertical; + int num_reorder_frames; + int max_dec_frame_buffering; + } vui; + + struct + { + int cpb_cnt_minus1; + int bit_rate_scale; + int cpb_size_scale; + int bit_rate_value_minus1[32]; + int cpb_size_value_minus1[32]; + int cbr_flag[32]; + int initial_cpb_removal_delay_length_minus1; + int cpb_removal_delay_length_minus1; + int dpb_output_delay_length_minus1; + int time_offset_length; + } hrd; + }; + + struct PPS + { + int pic_parameter_set_id; + int seq_parameter_set_id; + int entropy_coding_mode_flag; + int pic_order_present_flag; + int num_slice_groups_minus1; + int slice_group_map_type; + int run_length_minus1[8]; + int top_left[8]; + int bottom_right[8]; + int slice_group_change_direction_flag; + int slice_group_change_rate_minus1; + int pic_size_in_map_units_minus1; + int slice_group_id[256]; + int num_ref_idx_l0_active_minus1; + int num_ref_idx_l1_active_minus1; + int weighted_pred_flag; + int weighted_bipred_idc; + int pic_init_qp_minus26; + int pic_init_qs_minus26; + int chroma_qp_index_offset; + int deblocking_filter_control_present_flag; + int constrained_intra_pred_flag; + int redundant_pic_cnt_present_flag; + + int _more_rbsp_data_present; + + int transform_8x8_mode_flag; + int pic_scaling_matrix_present_flag; + int pic_scaling_list_present_flag[8]; + int ScalingList4x4[6][16]; + int UseDefaultScalingMatrix4x4Flag[6]; + int ScalingList8x8[2][64]; + int UseDefaultScalingMatrix8x8Flag[2]; + int second_chroma_qp_index_offset; + }; + + enum SH_SLICE_TYPE + { + SH_SLICE_TYPE_P = 0, + SH_SLICE_TYPE_B = 1, + SH_SLICE_TYPE_I = 2, + SH_SLICE_TYPE_SP = 3, + SH_SLICE_TYPE_SI = 4, + + // The *_ONLY slice types indicate that all other slices in that picture are of the same type + SH_SLICE_TYPE_P_ONLY = 5, + SH_SLICE_TYPE_B_ONLY = 6, + SH_SLICE_TYPE_I_ONLY = 7, + SH_SLICE_TYPE_SP_ONLY = 8, + SH_SLICE_TYPE_SI_ONLY = 9, + }; + struct SliceHeader + { + int first_mb_in_slice; + int slice_type; + int pic_parameter_set_id; + int frame_num; + int field_pic_flag; + int bottom_field_flag; + int idr_pic_id; + int pic_order_cnt_lsb; + int delta_pic_order_cnt_bottom; + int delta_pic_order_cnt[2]; + int redundant_pic_cnt; + int direct_spatial_mv_pred_flag; + int num_ref_idx_active_override_flag; + int num_ref_idx_l0_active_minus1; + int num_ref_idx_l1_active_minus1; + int cabac_init_idc; + int slice_qp_delta; + int sp_for_switch_flag; + int slice_qs_delta; + int disable_deblocking_filter_idc; + int slice_alpha_c0_offset_div2; + int slice_beta_offset_div2; + int slice_group_change_cycle; + + struct + { + int luma_log2_weight_denom; + int chroma_log2_weight_denom; + int luma_weight_l0_flag[64]; + int luma_weight_l0[64]; + int luma_offset_l0[64]; + int chroma_weight_l0_flag[64]; + int chroma_weight_l0[64][2]; + int chroma_offset_l0[64][2]; + int luma_weight_l1_flag[64]; + int luma_weight_l1[64]; + int luma_offset_l1[64]; + int chroma_weight_l1_flag[64]; + int chroma_weight_l1[64][2]; + int chroma_offset_l1[64][2]; + } pwt; // predictive weight table + + struct + { + int ref_pic_list_reordering_flag_l0; + struct + { + int reordering_of_pic_nums_idc[64]; + int abs_diff_pic_num_minus1[64]; + int long_term_pic_num[64]; + } reorder_l0; + int ref_pic_list_reordering_flag_l1; + struct + { + int reordering_of_pic_nums_idc[64]; + int abs_diff_pic_num_minus1[64]; + int long_term_pic_num[64]; + } reorder_l1; + } rplr; // ref pic list reorder + + struct + { + int no_output_of_prior_pics_flag; + int long_term_reference_flag; + int adaptive_ref_pic_marking_mode_flag; + int memory_management_control_operation[64]; + int difference_of_pic_nums_minus1[64]; + int long_term_pic_num[64]; + int long_term_frame_idx[64]; + int max_long_term_frame_idx_plus1[64]; + } drpm; // decoded ref pic marking + + }; + + enum NAL_REF_IDC + { + NAL_REF_IDC_PRIORITY_HIGHEST = 3, + NAL_REF_IDC_PRIORITY_HIGH = 2, + NAL_REF_IDC_PRIORITY_LOW = 1, + NAL_REF_IDC_PRIORITY_DISPOSABLE = 0, + }; + enum NAL_UNIT_TYPE + { + NAL_UNIT_TYPE_UNSPECIFIED = 0, // Unspecified + NAL_UNIT_TYPE_CODED_SLICE_NON_IDR = 1, // Coded slice of a non-IDR picture + NAL_UNIT_TYPE_CODED_SLICE_DATA_PARTITION_A = 2, // Coded slice data partition A + NAL_UNIT_TYPE_CODED_SLICE_DATA_PARTITION_B = 3, // Coded slice data partition B + NAL_UNIT_TYPE_CODED_SLICE_DATA_PARTITION_C = 4, // Coded slice data partition C + NAL_UNIT_TYPE_CODED_SLICE_IDR = 5, // Coded slice of an IDR picture + NAL_UNIT_TYPE_SEI = 6, // Supplemental enhancement information (SEI) + NAL_UNIT_TYPE_SPS = 7, // Sequence parameter set + NAL_UNIT_TYPE_PPS = 8, // Picture parameter set + NAL_UNIT_TYPE_AUD = 9, // Access unit delimiter + NAL_UNIT_TYPE_END_OF_SEQUENCE = 10, // End of sequence + NAL_UNIT_TYPE_END_OF_STREAM = 11, // End of stream + NAL_UNIT_TYPE_FILLER = 12, // Filler data + NAL_UNIT_TYPE_SPS_EXT = 13, // Sequence parameter set extension + NAL_UNIT_TYPE_CODED_SLICE_AUX = 19, // Coded slice of an auxiliary coded picture without partitioning + }; + struct NALHeader + { + NAL_REF_IDC idc; + NAL_UNIT_TYPE type; + }; + + struct Bitstream + { + const uint8_t* start; + const uint8_t* p; + const uint8_t* end; + int bits_left; + + constexpr void init(const uint8_t* buf, size_t size) + { + start = buf; + p = buf; + end = buf + size; + bits_left = 8; + } + constexpr bool byte_aligned() + { + return bits_left == 8; + } + constexpr bool eof() { if (p >= end) { return true; } else { return false; } } + constexpr uint32_t u1() + { + uint32_t r = 0; + bits_left--; + if (!eof()) + { + r = ((*(p)) >> bits_left) & 0x01; + } + if (bits_left == 0) + { + p++; + bits_left = 8; + } + return r; + } + constexpr uint32_t u(int n) + { + uint32_t r = 0; + for (int i = 0; i < n; i++) + { + r |= (u1() << (n - i - 1)); + } + return r; + } + constexpr uint32_t ue() + { + int32_t r = 0; + int i = 0; + + while ((u1() == 0) && (i < 32) && (!eof())) + { + i++; + } + r = u(i); + r += (1 << i) - 1; + return r; + } + constexpr int32_t se() + { + int32_t r = ue(); + if (r & 0x01) + { + r = (r + 1) / 2; + } + else + { + r = -(r / 2); + } + return r; + } + }; + + void read_nal_header(NALHeader* nal, Bitstream* b); + void read_pps(PPS* pps, Bitstream* b); + void read_sps(SPS* sps, Bitstream* b); + void read_slice_header(SliceHeader* sh, NALHeader* nal, const PPS* pps_array, const SPS* sps_array, Bitstream* b); + +#ifdef H264_IMPLEMENTATION + void read_nal_header(NALHeader* nal, Bitstream* b) + { + uint32_t forbidden_zero_bit = b->u(1); + assert(forbidden_zero_bit == 0); + nal->idc = (h264::NAL_REF_IDC)b->u(2); + nal->type = (h264::NAL_UNIT_TYPE)b->u(5); + } + void read_scaling_list(Bitstream* b, int* scalingList, int sizeOfScalingList, int* useDefaultScalingMatrixFlag) + { + int lastScale = 8; + int nextScale = 8; + int delta_scale; + for (int j = 0; j < sizeOfScalingList; j++) + { + if (nextScale != 0) + { + if (0) + { + nextScale = scalingList[j]; + if (*useDefaultScalingMatrixFlag) { nextScale = 0; } + delta_scale = (nextScale - lastScale) % 256; + } + + delta_scale = b->se(); + + if (1) + { + nextScale = (lastScale + delta_scale + 256) % 256; + *useDefaultScalingMatrixFlag = (j == 0 && nextScale == 0); + } + } + if (1) + { + scalingList[j] = (nextScale == 0) ? lastScale : nextScale; + } + lastScale = scalingList[j]; + } + } + void read_hrd_parameters(SPS* sps, Bitstream* b) + { + sps->hrd.cpb_cnt_minus1 = b->ue(); + sps->hrd.bit_rate_scale = b->u(4); + sps->hrd.cpb_size_scale = b->u(4); + for (int SchedSelIdx = 0; SchedSelIdx <= sps->hrd.cpb_cnt_minus1; SchedSelIdx++) + { + sps->hrd.bit_rate_value_minus1[SchedSelIdx] = b->ue(); + sps->hrd.cpb_size_value_minus1[SchedSelIdx] = b->ue(); + sps->hrd.cbr_flag[SchedSelIdx] = b->u1(); + } + sps->hrd.initial_cpb_removal_delay_length_minus1 = b->u(5); + sps->hrd.cpb_removal_delay_length_minus1 = b->u(5); + sps->hrd.dpb_output_delay_length_minus1 = b->u(5); + sps->hrd.time_offset_length = b->u(5); + } + void read_rbsp_trailing_bits(Bitstream* b) + { + /* rbsp_stop_one_bit */ b->u(1); + + while (!b->byte_aligned()) + { + /* rbsp_alignment_zero_bit */ b->u(1); + } + } + void read_vui_parameters(SPS* sps, Bitstream* b) + { + sps->vui.aspect_ratio_info_present_flag = b->u1(); + if (sps->vui.aspect_ratio_info_present_flag) + { + sps->vui.aspect_ratio_idc = b->u(8); + if (sps->vui.aspect_ratio_idc == 255) // Extended_SAR + { + sps->vui.sar_width = b->u(16); + sps->vui.sar_height = b->u(16); + } + } + sps->vui.overscan_info_present_flag = b->u1(); + if (sps->vui.overscan_info_present_flag) + { + sps->vui.overscan_appropriate_flag = b->u1(); + } + sps->vui.video_signal_type_present_flag = b->u1(); + if (sps->vui.video_signal_type_present_flag) + { + sps->vui.video_format = b->u(3); + sps->vui.video_full_range_flag = b->u1(); + sps->vui.colour_description_present_flag = b->u1(); + if (sps->vui.colour_description_present_flag) + { + sps->vui.colour_primaries = b->u(8); + sps->vui.transfer_characteristics = b->u(8); + sps->vui.matrix_coefficients = b->u(8); + } + } + sps->vui.chroma_loc_info_present_flag = b->u1(); + if (sps->vui.chroma_loc_info_present_flag) + { + sps->vui.chroma_sample_loc_type_top_field = b->ue(); + sps->vui.chroma_sample_loc_type_bottom_field = b->ue(); + } + sps->vui.timing_info_present_flag = b->u1(); + if (sps->vui.timing_info_present_flag) + { + sps->vui.num_units_in_tick = b->u(32); + sps->vui.time_scale = b->u(32); + sps->vui.fixed_frame_rate_flag = b->u1(); + } + sps->vui.nal_hrd_parameters_present_flag = b->u1(); + if (sps->vui.nal_hrd_parameters_present_flag) + { + read_hrd_parameters(sps, b); + } + sps->vui.vcl_hrd_parameters_present_flag = b->u1(); + if (sps->vui.vcl_hrd_parameters_present_flag) + { + read_hrd_parameters(sps, b); + } + if (sps->vui.nal_hrd_parameters_present_flag || sps->vui.vcl_hrd_parameters_present_flag) + { + sps->vui.low_delay_hrd_flag = b->u1(); + } + sps->vui.pic_struct_present_flag = b->u1(); + sps->vui.bitstream_restriction_flag = b->u1(); + if (sps->vui.bitstream_restriction_flag) + { + sps->vui.motion_vectors_over_pic_boundaries_flag = b->u1(); + sps->vui.max_bytes_per_pic_denom = b->ue(); + sps->vui.max_bits_per_mb_denom = b->ue(); + sps->vui.log2_max_mv_length_horizontal = b->ue(); + sps->vui.log2_max_mv_length_vertical = b->ue(); + sps->vui.num_reorder_frames = b->ue(); + sps->vui.max_dec_frame_buffering = b->ue(); + } + } + int intlog2(int x) + { + int log = 0; + if (x < 0) { x = 0; } + while ((x >> log) > 0) + { + log++; + } + if (log > 0 && x == 1 << (log - 1)) { log--; } + return log; + } + int more_rbsp_data(Bitstream* b) + { + // no more data + if (b->eof()) { return 0; } + + Bitstream bs_tmp = *b; // make copy + + // no rbsp_stop_bit yet + if (bs_tmp.u1() == 0) { return 1; } + + while (!bs_tmp.eof()) + { + // A later bit was 1, it wasn't the rsbp_stop_bit + if (bs_tmp.u1() == 1) { return 1; } + } + + // All following bits were 0, it was the rsbp_stop_bit + return 0; + } + void read_sps(SPS* sps, Bitstream* b) + { + sps->profile_idc = b->u(8); + sps->constraint_set0_flag = b->u1(); + sps->constraint_set1_flag = b->u1(); + sps->constraint_set2_flag = b->u1(); + sps->constraint_set3_flag = b->u1(); + sps->constraint_set4_flag = b->u1(); + sps->constraint_set5_flag = b->u1(); + /* reserved_zero_2bits */ b->u(2); + sps->level_idc = b->u(8); + sps->seq_parameter_set_id = b->ue(); + + if (sps->profile_idc == 100 || sps->profile_idc == 110 || + sps->profile_idc == 122 || sps->profile_idc == 144) + { + sps->chroma_format_idc = b->ue(); + if (sps->chroma_format_idc == 3) + { + sps->separate_colour_plane_flag = b->u1(); + } + sps->bit_depth_luma_minus8 = b->ue(); + sps->bit_depth_chroma_minus8 = b->ue(); + sps->qpprime_y_zero_transform_bypass_flag = b->u1(); + sps->seq_scaling_matrix_present_flag = b->u1(); + if (sps->seq_scaling_matrix_present_flag) + { + for (int i = 0; i < 8; i++) + { + sps->seq_scaling_list_present_flag[i] = b->u1(); + if (sps->seq_scaling_list_present_flag[i]) + { + if (i < 6) + { + read_scaling_list(b, sps->ScalingList4x4[i], 16, + &(sps->UseDefaultScalingMatrix4x4Flag[i])); + } + else + { + read_scaling_list(b, sps->ScalingList8x8[i - 6], 64, + &(sps->UseDefaultScalingMatrix8x8Flag[i - 6])); + } + } + } + } + } + sps->log2_max_frame_num_minus4 = b->ue(); + sps->pic_order_cnt_type = b->ue(); + if (sps->pic_order_cnt_type == 0) + { + sps->log2_max_pic_order_cnt_lsb_minus4 = b->ue(); + } + else if (sps->pic_order_cnt_type == 1) + { + sps->delta_pic_order_always_zero_flag = b->u1(); + sps->offset_for_non_ref_pic = b->se(); + sps->offset_for_top_to_bottom_field = b->se(); + sps->num_ref_frames_in_pic_order_cnt_cycle = b->ue(); + for (int i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; i++) + { + sps->offset_for_ref_frame[i] = b->se(); + } + } + sps->num_ref_frames = b->ue(); + sps->gaps_in_frame_num_value_allowed_flag = b->u1(); + sps->pic_width_in_mbs_minus1 = b->ue(); + sps->pic_height_in_map_units_minus1 = b->ue(); + sps->frame_mbs_only_flag = b->u1(); + if (!sps->frame_mbs_only_flag) + { + sps->mb_adaptive_frame_field_flag = b->u1(); + } + sps->direct_8x8_inference_flag = b->u1(); + sps->frame_cropping_flag = b->u1(); + if (sps->frame_cropping_flag) + { + sps->frame_crop_left_offset = b->ue(); + sps->frame_crop_right_offset = b->ue(); + sps->frame_crop_top_offset = b->ue(); + sps->frame_crop_bottom_offset = b->ue(); + } + sps->vui_parameters_present_flag = b->u1(); + if (sps->vui_parameters_present_flag) + { + read_vui_parameters(sps, b); + } + read_rbsp_trailing_bits(b); + } + void read_pps(PPS* pps, Bitstream* b) + { + pps->pic_parameter_set_id = b->ue(); + pps->seq_parameter_set_id = b->ue(); + pps->entropy_coding_mode_flag = b->u1(); + pps->pic_order_present_flag = b->u1(); + pps->num_slice_groups_minus1 = b->ue(); + + if (pps->num_slice_groups_minus1 > 0) + { + pps->slice_group_map_type = b->ue(); + if (pps->slice_group_map_type == 0) + { + for (int i_group = 0; i_group <= pps->num_slice_groups_minus1; i_group++) + { + pps->run_length_minus1[i_group] = b->ue(); + } + } + else if (pps->slice_group_map_type == 2) + { + for (int i_group = 0; i_group < pps->num_slice_groups_minus1; i_group++) + { + pps->top_left[i_group] = b->ue(); + pps->bottom_right[i_group] = b->ue(); + } + } + else if (pps->slice_group_map_type == 3 || + pps->slice_group_map_type == 4 || + pps->slice_group_map_type == 5) + { + pps->slice_group_change_direction_flag = b->u1(); + pps->slice_group_change_rate_minus1 = b->ue(); + } + else if (pps->slice_group_map_type == 6) + { + pps->pic_size_in_map_units_minus1 = b->ue(); + for (int i = 0; i <= pps->pic_size_in_map_units_minus1; i++) + { + int v = intlog2(pps->num_slice_groups_minus1 + 1); + pps->slice_group_id[i] = b->u(v); + } + } + } + pps->num_ref_idx_l0_active_minus1 = b->ue(); + pps->num_ref_idx_l1_active_minus1 = b->ue(); + pps->weighted_pred_flag = b->u1(); + pps->weighted_bipred_idc = b->u(2); + pps->pic_init_qp_minus26 = b->se(); + pps->pic_init_qs_minus26 = b->se(); + pps->chroma_qp_index_offset = b->se(); + pps->deblocking_filter_control_present_flag = b->u1(); + pps->constrained_intra_pred_flag = b->u1(); + pps->redundant_pic_cnt_present_flag = b->u1(); + + int have_more_data = 0; + if (1) { have_more_data = more_rbsp_data(b); } + if (0) + { + have_more_data = (pps->transform_8x8_mode_flag | pps->pic_scaling_matrix_present_flag | pps->second_chroma_qp_index_offset) != 0; + } + + if (have_more_data) + { + pps->transform_8x8_mode_flag = b->u1(); + pps->pic_scaling_matrix_present_flag = b->u1(); + if (pps->pic_scaling_matrix_present_flag) + { + for (int i = 0; i < 6 + 2 * pps->transform_8x8_mode_flag; i++) + { + pps->pic_scaling_list_present_flag[i] = b->u1(); + if (pps->pic_scaling_list_present_flag[i]) + { + if (i < 6) + { + read_scaling_list(b, pps->ScalingList4x4[i], 16, + &(pps->UseDefaultScalingMatrix4x4Flag[i])); + } + else + { + read_scaling_list(b, pps->ScalingList8x8[i - 6], 64, + &(pps->UseDefaultScalingMatrix8x8Flag[i - 6])); + } + } + } + } + pps->second_chroma_qp_index_offset = b->se(); + } + read_rbsp_trailing_bits(b); + } + int is_slice_type(int slice_type, int cmp_type) + { + if (slice_type >= 5) { slice_type -= 5; } + if (cmp_type >= 5) { cmp_type -= 5; } + if (slice_type == cmp_type) { return 1; } + else { return 0; } + } + void read_ref_pic_list_reordering(SliceHeader* sh, Bitstream* b) + { + if (!is_slice_type(sh->slice_type, SH_SLICE_TYPE_I) && !is_slice_type(sh->slice_type, SH_SLICE_TYPE_SI)) + { + sh->rplr.ref_pic_list_reordering_flag_l0 = b->u1(); + if (sh->rplr.ref_pic_list_reordering_flag_l0) + { + int n = -1; + do + { + n++; + sh->rplr.reorder_l0.reordering_of_pic_nums_idc[n] = b->ue(); + if (sh->rplr.reorder_l0.reordering_of_pic_nums_idc[n] == 0 || + sh->rplr.reorder_l0.reordering_of_pic_nums_idc[n] == 1) + { + sh->rplr.reorder_l0.abs_diff_pic_num_minus1[n] = b->ue(); + } + else if (sh->rplr.reorder_l0.reordering_of_pic_nums_idc[n] == 2) + { + sh->rplr.reorder_l0.long_term_pic_num[n] = b->ue(); + } + } while (sh->rplr.reorder_l0.reordering_of_pic_nums_idc[n] != 3 && !b->eof()); + } + } + if (is_slice_type(sh->slice_type, SH_SLICE_TYPE_B)) + { + sh->rplr.ref_pic_list_reordering_flag_l1 = b->u1(); + if (sh->rplr.ref_pic_list_reordering_flag_l1) + { + int n = -1; + do + { + n++; + sh->rplr.reorder_l1.reordering_of_pic_nums_idc[n] = b->ue(); + if (sh->rplr.reorder_l1.reordering_of_pic_nums_idc[n] == 0 || + sh->rplr.reorder_l1.reordering_of_pic_nums_idc[n] == 1) + { + sh->rplr.reorder_l1.abs_diff_pic_num_minus1[n] = b->ue(); + } + else if (sh->rplr.reorder_l1.reordering_of_pic_nums_idc[n] == 2) + { + sh->rplr.reorder_l1.long_term_pic_num[n] = b->ue(); + } + } while (sh->rplr.reorder_l1.reordering_of_pic_nums_idc[n] != 3 && !b->eof()); + } + } + } + void read_pred_weight_table(SliceHeader* sh, const SPS* sps, const PPS* pps, Bitstream* b) + { + int i, j; + + sh->pwt.luma_log2_weight_denom = b->ue(); + if (sps->chroma_format_idc != 0) + { + sh->pwt.chroma_log2_weight_denom = b->ue(); + } + for (i = 0; i <= pps->num_ref_idx_l0_active_minus1; i++) + { + sh->pwt.luma_weight_l0_flag[i] = b->u1(); + if (sh->pwt.luma_weight_l0_flag[i]) + { + sh->pwt.luma_weight_l0[i] = b->se(); + sh->pwt.luma_offset_l0[i] = b->se(); + } + if (sps->chroma_format_idc != 0) + { + sh->pwt.chroma_weight_l0_flag[i] = b->u1(); + if (sh->pwt.chroma_weight_l0_flag[i]) + { + for (j = 0; j < 2; j++) + { + sh->pwt.chroma_weight_l0[i][j] = b->se(); + sh->pwt.chroma_offset_l0[i][j] = b->se(); + } + } + } + } + if (is_slice_type(sh->slice_type, SH_SLICE_TYPE_B)) + { + for (i = 0; i <= pps->num_ref_idx_l1_active_minus1; i++) + { + sh->pwt.luma_weight_l1_flag[i] = b->u1(); + if (sh->pwt.luma_weight_l1_flag[i]) + { + sh->pwt.luma_weight_l1[i] = b->se(); + sh->pwt.luma_offset_l1[i] = b->se(); + } + if (sps->chroma_format_idc != 0) + { + sh->pwt.chroma_weight_l1_flag[i] = b->u1(); + if (sh->pwt.chroma_weight_l1_flag[i]) + { + for (j = 0; j < 2; j++) + { + sh->pwt.chroma_weight_l1[i][j] = b->se(); + sh->pwt.chroma_offset_l1[i][j] = b->se(); + } + } + } + } + } + } + void read_dec_ref_pic_marking(SliceHeader* sh, NALHeader* nal, Bitstream* b) + { + if (nal->type == 5) + { + sh->drpm.no_output_of_prior_pics_flag = b->u1(); + sh->drpm.long_term_reference_flag = b->u1(); + } + else + { + sh->drpm.adaptive_ref_pic_marking_mode_flag = b->u1(); + if (sh->drpm.adaptive_ref_pic_marking_mode_flag) + { + int n = -1; + do + { + n++; + sh->drpm.memory_management_control_operation[n] = b->ue(); + if (sh->drpm.memory_management_control_operation[n] == 1 || + sh->drpm.memory_management_control_operation[n] == 3) + { + sh->drpm.difference_of_pic_nums_minus1[n] = b->ue(); + } + if (sh->drpm.memory_management_control_operation[n] == 2) + { + sh->drpm.long_term_pic_num[n] = b->ue(); + } + if (sh->drpm.memory_management_control_operation[n] == 3 || + sh->drpm.memory_management_control_operation[n] == 6) + { + sh->drpm.long_term_frame_idx[n] = b->ue(); + } + if (sh->drpm.memory_management_control_operation[n] == 4) + { + sh->drpm.max_long_term_frame_idx_plus1[n] = b->ue(); + } + } while (sh->drpm.memory_management_control_operation[n] != 0 && !b->eof()); + } + } + } + void read_slice_header(SliceHeader* sh, NALHeader* nal, const PPS* pps_array, const SPS* sps_array, Bitstream* b) + { + sh->first_mb_in_slice = b->ue(); + sh->slice_type = b->ue(); + sh->pic_parameter_set_id = b->ue(); + + const PPS* pps = pps_array + sh->pic_parameter_set_id; + const SPS* sps = sps_array + pps->seq_parameter_set_id; + + sh->frame_num = b->u(sps->log2_max_frame_num_minus4 + 4); // was u(v) + if (!sps->frame_mbs_only_flag) + { + sh->field_pic_flag = b->u1(); + if (sh->field_pic_flag) + { + sh->bottom_field_flag = b->u1(); + } + } + if (nal->type == 5) + { + sh->idr_pic_id = b->ue(); + } + if (sps->pic_order_cnt_type == 0) + { + sh->pic_order_cnt_lsb = b->u(sps->log2_max_pic_order_cnt_lsb_minus4 + 4); // was u(v) + if (pps->pic_order_present_flag && !sh->field_pic_flag) + { + sh->delta_pic_order_cnt_bottom = b->se(); + } + } + if (sps->pic_order_cnt_type == 1 && !sps->delta_pic_order_always_zero_flag) + { + sh->delta_pic_order_cnt[0] = b->se(); + if (pps->pic_order_present_flag && !sh->field_pic_flag) + { + sh->delta_pic_order_cnt[1] = b->se(); + } + } + if (pps->redundant_pic_cnt_present_flag) + { + sh->redundant_pic_cnt = b->ue(); + } + if (is_slice_type(sh->slice_type, SH_SLICE_TYPE_B)) + { + sh->direct_spatial_mv_pred_flag = b->u1(); + } + if (is_slice_type(sh->slice_type, SH_SLICE_TYPE_P) || is_slice_type(sh->slice_type, SH_SLICE_TYPE_SP) || is_slice_type(sh->slice_type, SH_SLICE_TYPE_B)) + { + sh->num_ref_idx_active_override_flag = b->u1(); + if (sh->num_ref_idx_active_override_flag) + { + sh->num_ref_idx_l0_active_minus1 = b->ue(); + if (is_slice_type(sh->slice_type, SH_SLICE_TYPE_B)) + { + sh->num_ref_idx_l1_active_minus1 = b->ue(); + } + } + } + read_ref_pic_list_reordering(sh, b); + if ((pps->weighted_pred_flag && (is_slice_type(sh->slice_type, SH_SLICE_TYPE_P) || is_slice_type(sh->slice_type, SH_SLICE_TYPE_SP))) || + (pps->weighted_bipred_idc == 1 && is_slice_type(sh->slice_type, SH_SLICE_TYPE_B))) + { + read_pred_weight_table(sh, sps, pps, b); + } + if (nal->idc != 0) + { + read_dec_ref_pic_marking(sh, nal, b); + } + if (pps->entropy_coding_mode_flag && !is_slice_type(sh->slice_type, SH_SLICE_TYPE_I) && !is_slice_type(sh->slice_type, SH_SLICE_TYPE_SI)) + { + sh->cabac_init_idc = b->ue(); + } + sh->slice_qp_delta = b->se(); + if (is_slice_type(sh->slice_type, SH_SLICE_TYPE_SP) || is_slice_type(sh->slice_type, SH_SLICE_TYPE_SI)) + { + if (is_slice_type(sh->slice_type, SH_SLICE_TYPE_SP)) + { + sh->sp_for_switch_flag = b->u1(); + } + sh->slice_qs_delta = b->se(); + } + if (pps->deblocking_filter_control_present_flag) + { + sh->disable_deblocking_filter_idc = b->ue(); + if (sh->disable_deblocking_filter_idc != 1) + { + sh->slice_alpha_c0_offset_div2 = b->se(); + sh->slice_beta_offset_div2 = b->se(); + } + } + if (pps->num_slice_groups_minus1 > 0 && + pps->slice_group_map_type >= 3 && pps->slice_group_map_type <= 5) + { + int v = intlog2(pps->pic_size_in_map_units_minus1 + pps->slice_group_change_rate_minus1 + 1); + sh->slice_group_change_cycle = b->u(v); + } + } +#endif // H264_IMPLEMENTATION + +} + +#endif // H264_H diff --git a/WickedEngine/Utility/minimp4.h b/WickedEngine/Utility/minimp4.h new file mode 100644 index 000000000..2b47fc44f --- /dev/null +++ b/WickedEngine/Utility/minimp4.h @@ -0,0 +1,3506 @@ +#ifndef MINIMP4_H +#define MINIMP4_H +/* + https://github.com/aspt/mp4 + https://github.com/lieff/minimp4 + To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. + This software is distributed without any warranty. + See . +*/ + +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#define strdup _strdup +#endif // _WIN32 + +#ifdef __cplusplus +extern "C" { +#endif + +#define MINIMP4_MIN(x, y) ((x) < (y) ? (x) : (y)) + +/************************************************************************/ +/* Build configuration */ +/************************************************************************/ + +#define FIX_BAD_ANDROID_META_BOX 1 + +#define MAX_CHUNKS_DEPTH 64 // Max chunks nesting level + +#define MINIMP4_MAX_SPS 32 +#define MINIMP4_MAX_PPS 256 + +#define MINIMP4_TRANSCODE_SPS_ID 1 + +// Support indexing of MP4 files over 4 GB. +// If disabled, files with 64-bit offset fields is still supported, +// but error signaled if such field contains too big offset +// This switch affect return type of MP4D_frame_offset() function +#define MINIMP4_ALLOW_64BIT 1 + +#define MP4D_TRACE_SUPPORTED 0 // Debug trace +#define MP4D_TRACE_TIMESTAMPS 1 +// Support parsing of supplementary information, not necessary for decoding: +// duration, language, bitrate, metadata tags, etc +#define MP4D_INFO_SUPPORTED 1 + +// Enable code, which prints to stdout supplementary MP4 information: +#define MP4D_PRINT_INFO_SUPPORTED 0 + +#define MP4D_AVC_SUPPORTED 1 +#define MP4D_HEVC_SUPPORTED 1 +#define MP4D_TIMESTAMPS_SUPPORTED 1 + +// Enable TrackFragmentBaseMediaDecodeTimeBox support +#define MP4D_TFDT_SUPPORT 0 + +/************************************************************************/ +/* Some values of MP4(E/D)_track_t->object_type_indication */ +/************************************************************************/ +// MPEG-4 AAC (all profiles) +#define MP4_OBJECT_TYPE_AUDIO_ISO_IEC_14496_3 0x40 +// MPEG-2 AAC, Main profile +#define MP4_OBJECT_TYPE_AUDIO_ISO_IEC_13818_7_MAIN_PROFILE 0x66 +// MPEG-2 AAC, LC profile +#define MP4_OBJECT_TYPE_AUDIO_ISO_IEC_13818_7_LC_PROFILE 0x67 +// MPEG-2 AAC, SSR profile +#define MP4_OBJECT_TYPE_AUDIO_ISO_IEC_13818_7_SSR_PROFILE 0x68 +// H.264 (AVC) video +#define MP4_OBJECT_TYPE_AVC 0x21 +// H.265 (HEVC) video +#define MP4_OBJECT_TYPE_HEVC 0x23 +// http://www.mp4ra.org/object.html 0xC0-E0 && 0xE2 - 0xFE are specified as "user private" +#define MP4_OBJECT_TYPE_USER_PRIVATE 0xC0 + +/************************************************************************/ +/* API error codes */ +/************************************************************************/ +#define MP4E_STATUS_OK 0 +#define MP4E_STATUS_BAD_ARGUMENTS -1 +#define MP4E_STATUS_NO_MEMORY -2 +#define MP4E_STATUS_FILE_WRITE_ERROR -3 +#define MP4E_STATUS_ONLY_ONE_DSI_ALLOWED -4 + +/************************************************************************/ +/* Sample kind for MP4E_put_sample() */ +/************************************************************************/ +#define MP4E_SAMPLE_DEFAULT 0 // (beginning of) audio or video frame +#define MP4E_SAMPLE_RANDOM_ACCESS 1 // mark sample as random access point (key frame) +#define MP4E_SAMPLE_CONTINUATION 2 // Not a sample, but continuation of previous sample (new slice) + +/************************************************************************/ +/* Portable 64-bit type definition */ +/************************************************************************/ + +#if MINIMP4_ALLOW_64BIT + typedef uint64_t boxsize_t; +#else + typedef unsigned int boxsize_t; +#endif +typedef boxsize_t MP4D_file_offset_t; + +/************************************************************************/ +/* Some values of MP4D_track_t->handler_type */ +/************************************************************************/ +// Video track : 'vide' +#define MP4D_HANDLER_TYPE_VIDE 0x76696465 +// Audio track : 'soun' +#define MP4D_HANDLER_TYPE_SOUN 0x736F756E +// General MPEG-4 systems streams (without specific handler). +// Used for private stream, as suggested in http://www.mp4ra.org/handler.html +#define MP4E_HANDLER_TYPE_GESM 0x6765736D + + +#define HEVC_NAL_VPS 32 +#define HEVC_NAL_SPS 33 +#define HEVC_NAL_PPS 34 +#define HEVC_NAL_BLA_W_LP 16 +#define HEVC_NAL_CRA_NUT 21 + +/************************************************************************/ +/* Data structures */ +/************************************************************************/ + +typedef struct MP4E_mux_tag MP4E_mux_t; + +typedef enum +{ + e_audio, + e_video, + e_private +} track_media_kind_t; + +typedef struct +{ + // MP4 object type code, which defined codec class for the track. + // See MP4E_OBJECT_TYPE_* values for some codecs + unsigned object_type_indication; + + // Track language: 3-char ISO 639-2T code: "und", "eng", "rus", "jpn" etc... + unsigned char language[4]; + + track_media_kind_t track_media_kind; + + // 90000 for video, sample rate for audio + unsigned time_scale; + unsigned default_duration; + + union + { + struct + { + // number of channels in the audio track. + unsigned channelcount; + } a; + + struct + { + int width; + int height; + } v; + } u; + +} MP4E_track_t; + +typedef struct MP4D_sample_to_chunk_t_tag MP4D_sample_to_chunk_t; + +typedef struct +{ + /************************************************************************/ + /* mandatory public data */ + /************************************************************************/ + // How many 'samples' in the track + // The 'sample' is MP4 term, denoting audio or video frame + unsigned sample_count; + + // Decoder-specific info (DSI) data + unsigned char *dsi; + + // DSI data size + unsigned dsi_bytes; + + // MP4 object type code + // case 0x00: return "Forbidden"; + // case 0x01: return "Systems ISO/IEC 14496-1"; + // case 0x02: return "Systems ISO/IEC 14496-1"; + // case 0x20: return "Visual ISO/IEC 14496-2"; + // case 0x40: return "Audio ISO/IEC 14496-3"; + // case 0x60: return "Visual ISO/IEC 13818-2 Simple Profile"; + // case 0x61: return "Visual ISO/IEC 13818-2 Main Profile"; + // case 0x62: return "Visual ISO/IEC 13818-2 SNR Profile"; + // case 0x63: return "Visual ISO/IEC 13818-2 Spatial Profile"; + // case 0x64: return "Visual ISO/IEC 13818-2 High Profile"; + // case 0x65: return "Visual ISO/IEC 13818-2 422 Profile"; + // case 0x66: return "Audio ISO/IEC 13818-7 Main Profile"; + // case 0x67: return "Audio ISO/IEC 13818-7 LC Profile"; + // case 0x68: return "Audio ISO/IEC 13818-7 SSR Profile"; + // case 0x69: return "Audio ISO/IEC 13818-3"; + // case 0x6A: return "Visual ISO/IEC 11172-2"; + // case 0x6B: return "Audio ISO/IEC 11172-3"; + // case 0x6C: return "Visual ISO/IEC 10918-1"; + unsigned object_type_indication; + +#if MP4D_INFO_SUPPORTED + /************************************************************************/ + /* informational public data */ + /************************************************************************/ + // handler_type when present in a media box, is an integer containing one of + // the following values, or a value from a derived specification: + // 'vide' Video track + // 'soun' Audio track + // 'hint' Hint track + unsigned handler_type; + + // Track duration: 64-bit value split into 2 variables + unsigned duration_hi; + unsigned duration_lo; + + // duration scale: duration = timescale*seconds + unsigned timescale; + + // Average bitrate, bits per second + unsigned avg_bitrate_bps; + + // Track language: 3-char ISO 639-2T code: "und", "eng", "rus", "jpn" etc... + unsigned char language[4]; + + // MP4 stream type + // case 0x00: return "Forbidden"; + // case 0x01: return "ObjectDescriptorStream"; + // case 0x02: return "ClockReferenceStream"; + // case 0x03: return "SceneDescriptionStream"; + // case 0x04: return "VisualStream"; + // case 0x05: return "AudioStream"; + // case 0x06: return "MPEG7Stream"; + // case 0x07: return "IPMPStream"; + // case 0x08: return "ObjectContentInfoStream"; + // case 0x09: return "MPEGJStream"; + unsigned stream_type; + + union + { + // for handler_type == 'soun' tracks + struct + { + unsigned channelcount; + unsigned samplerate_hz; + } audio; + + // for handler_type == 'vide' tracks + struct + { + unsigned width; + unsigned height; + } video; + } SampleDescription; +#endif + + /************************************************************************/ + /* private data: MP4 indexes */ + /************************************************************************/ + unsigned *entry_size; + + unsigned sample_to_chunk_count; + struct MP4D_sample_to_chunk_t_tag *sample_to_chunk; + + unsigned chunk_count; + MP4D_file_offset_t *chunk_offset; + +#if MP4D_TIMESTAMPS_SUPPORTED + unsigned *timestamp; + unsigned *duration; +#endif + +} MP4D_track_t; + +typedef struct MP4D_demux_tag +{ + /************************************************************************/ + /* mandatory public data */ + /************************************************************************/ + int64_t read_pos; + int64_t read_size; + MP4D_track_t *track; + int (*read_callback)(int64_t offset, void *buffer, size_t size, void *token); + void *token; + + unsigned track_count; // number of tracks in the movie + +#if MP4D_INFO_SUPPORTED + /************************************************************************/ + /* informational public data */ + /************************************************************************/ + // Movie duration: 64-bit value split into 2 variables + unsigned duration_hi; + unsigned duration_lo; + + // duration scale: duration = timescale*seconds + unsigned timescale; + + // Metadata tag (optional) + // Tags provided 'as-is', without any re-encoding + struct + { + unsigned char *title; + unsigned char *artist; + unsigned char *album; + unsigned char *year; + unsigned char *comment; + unsigned char *genre; + } tag; +#endif + +} MP4D_demux_t; + +struct MP4D_sample_to_chunk_t_tag +{ + unsigned first_chunk; + unsigned samples_per_chunk; +}; + +typedef struct +{ + void *sps_cache[MINIMP4_MAX_SPS]; + void *pps_cache[MINIMP4_MAX_PPS]; + int sps_bytes[MINIMP4_MAX_SPS]; + int pps_bytes[MINIMP4_MAX_PPS]; + + int map_sps[MINIMP4_MAX_SPS]; + int map_pps[MINIMP4_MAX_PPS]; + +} h264_sps_id_patcher_t; + +typedef struct mp4_h26x_writer_tag +{ +#if MINIMP4_TRANSCODE_SPS_ID + h264_sps_id_patcher_t sps_patcher; +#endif + MP4E_mux_t *mux; + int mux_track_id, is_hevc, need_vps, need_sps, need_pps, need_idr; +} mp4_h26x_writer_t; + +int mp4_h26x_write_init(mp4_h26x_writer_t *h, MP4E_mux_t *mux, int width, int height, int is_hevc); +void mp4_h26x_write_close(mp4_h26x_writer_t *h); +int mp4_h26x_write_nal(mp4_h26x_writer_t *h, const unsigned char *nal, int length, unsigned timeStamp90kHz_next); + +/************************************************************************/ +/* API */ +/************************************************************************/ + +/** +* Parse given input stream as MP4 file. Allocate and store data indexes. +* return 1 on success, 0 on failure +* The MP4 indexes may be stored at the end of stream, so this +* function may parse all stream. +* It is guaranteed that function will read/seek sequentially, +* and will never jump back. +*/ +int MP4D_open(MP4D_demux_t *mp4, int (*read_callback)(int64_t offset, void *buffer, size_t size, void *token), void *token, int64_t file_size); + +/** +* Return position and size for given sample from given track. The 'sample' is a +* MP4 term for 'frame' +* +* frame_bytes [OUT] - return coded frame size in bytes +* timestamp [OUT] - return frame timestamp (in mp4->timescale units) +* duration [OUT] - return frame duration (in mp4->timescale units) +* +* function return offset for the frame +*/ +MP4D_file_offset_t MP4D_frame_offset(const MP4D_demux_t *mp4, unsigned int ntrack, unsigned int nsample, unsigned int *frame_bytes, unsigned *timestamp, unsigned *duration); + +/** +* De-allocated memory +*/ +void MP4D_close(MP4D_demux_t *mp4); + +/** +* Helper functions to parse mp4.track[ntrack].dsi for H.264 SPS/PPS +* Return pointer to internal mp4 memory, it must not be free()-ed +* +* Example: process all SPS in MP4 file: +* while (sps = MP4D_read_sps(mp4, num_of_avc_track, sps_count, &sps_bytes)) +* { +* process(sps, sps_bytes); +* sps_count++; +* } +*/ +const void *MP4D_read_sps(const MP4D_demux_t *mp4, unsigned int ntrack, int nsps, int *sps_bytes); +const void *MP4D_read_pps(const MP4D_demux_t *mp4, unsigned int ntrack, int npps, int *pps_bytes); + +#if MP4D_PRINT_INFO_SUPPORTED +/** +* Print MP4 information to stdout. +* Uses printf() as well as floating-point functions +* Given as implementation example and for test purposes +*/ +void MP4D_printf_info(const MP4D_demux_t *mp4); +#endif + +/** +* Allocates and initialize mp4 multiplexor +* Given file handler is transparent to the MP4 library, and used only as +* argument for given fwrite_callback() function. By appropriate definition +* of callback function application may use any other file output API (for +* example C++ streams, or Win32 file functions) +* +* return multiplexor handle on success; NULL on failure +*/ +MP4E_mux_t *MP4E_open(int sequential_mode_flag, int enable_fragmentation, void *token, + int (*write_callback)(int64_t offset, const void *buffer, size_t size, void *token)); + +/** +* Add new track +* The track_data parameter does not referred by the multiplexer after function +* return, and may be allocated in short-time memory. The dsi member of +* track_data parameter is mandatory. +* +* return ID of added track, or error code MP4E_STATUS_* +*/ +int MP4E_add_track(MP4E_mux_t *mux, const MP4E_track_t *track_data); + +/** +* Add new sample to specified track +* The tracks numbered starting with 0, according to order of MP4E_add_track() calls +* 'kind' is one of MP4E_SAMPLE_... defines +* +* return error code MP4E_STATUS_* +* +* Example: +* MP4E_put_sample(mux, 0, data, data_bytes, duration, MP4E_SAMPLE_DEFAULT); +*/ +int MP4E_put_sample(MP4E_mux_t *mux, int track_num, const void *data, int data_bytes, int duration, int kind); + +/** +* Finalize MP4 file, de-allocated memory, and closes MP4 multiplexer. +* The close operation takes a time and disk space, since it writes MP4 file +* indexes. Please note that this function does not closes file handle, +* which was passed to open function. +* +* return error code MP4E_STATUS_* +*/ +int MP4E_close(MP4E_mux_t *mux); + +/** +* Set Decoder Specific Info (DSI) +* Can be used for audio and private tracks. +* MUST be used for AAC track. +* Only one DSI can be set. It is an error to set DSI again +* +* return error code MP4E_STATUS_* +*/ +int MP4E_set_dsi(MP4E_mux_t *mux, int track_id, const void *dsi, int bytes); + +/** +* Set VPS data. MUST be used for HEVC (H.265) track. +* +* return error code MP4E_STATUS_* +*/ +int MP4E_set_vps(MP4E_mux_t *mux, int track_id, const void *vps, int bytes); + +/** +* Set SPS data. MUST be used for AVC (H.264) track. Up to 32 different SPS can be used in one track. +* +* return error code MP4E_STATUS_* +*/ +int MP4E_set_sps(MP4E_mux_t *mux, int track_id, const void *sps, int bytes); + +/** +* Set PPS data. MUST be used for AVC (H.264) track. Up to 256 different PPS can be used in one track. +* +* return error code MP4E_STATUS_* +*/ +int MP4E_set_pps(MP4E_mux_t *mux, int track_id, const void *pps, int bytes); + +/** +* Set or replace ASCII test comment for the file. Set comment to NULL to remove comment. +* +* return error code MP4E_STATUS_* +*/ +int MP4E_set_text_comment(MP4E_mux_t *mux, const char *comment); + +#ifdef __cplusplus +} +#endif +#endif //MINIMP4_H + +#if defined(MINIMP4_IMPLEMENTATION) && !defined(MINIMP4_IMPLEMENTATION_GUARD) +#define MINIMP4_IMPLEMENTATION_GUARD + +#define FOUR_CHAR_INT(a, b, c, d) (((uint32_t)(a) << 24) | ((b) << 16) | ((c) << 8) | (d)) +enum +{ + BOX_co64 = FOUR_CHAR_INT( 'c', 'o', '6', '4' ),//ChunkLargeOffsetAtomType + BOX_stco = FOUR_CHAR_INT( 's', 't', 'c', 'o' ),//ChunkOffsetAtomType + BOX_crhd = FOUR_CHAR_INT( 'c', 'r', 'h', 'd' ),//ClockReferenceMediaHeaderAtomType + BOX_ctts = FOUR_CHAR_INT( 'c', 't', 't', 's' ),//CompositionOffsetAtomType + BOX_cprt = FOUR_CHAR_INT( 'c', 'p', 'r', 't' ),//CopyrightAtomType + BOX_url_ = FOUR_CHAR_INT( 'u', 'r', 'l', ' ' ),//DataEntryURLAtomType + BOX_urn_ = FOUR_CHAR_INT( 'u', 'r', 'n', ' ' ),//DataEntryURNAtomType + BOX_dinf = FOUR_CHAR_INT( 'd', 'i', 'n', 'f' ),//DataInformationAtomType + BOX_dref = FOUR_CHAR_INT( 'd', 'r', 'e', 'f' ),//DataReferenceAtomType + BOX_stdp = FOUR_CHAR_INT( 's', 't', 'd', 'p' ),//DegradationPriorityAtomType + BOX_edts = FOUR_CHAR_INT( 'e', 'd', 't', 's' ),//EditAtomType + BOX_elst = FOUR_CHAR_INT( 'e', 'l', 's', 't' ),//EditListAtomType + BOX_uuid = FOUR_CHAR_INT( 'u', 'u', 'i', 'd' ),//ExtendedAtomType + BOX_free = FOUR_CHAR_INT( 'f', 'r', 'e', 'e' ),//FreeSpaceAtomType + BOX_hdlr = FOUR_CHAR_INT( 'h', 'd', 'l', 'r' ),//HandlerAtomType + BOX_hmhd = FOUR_CHAR_INT( 'h', 'm', 'h', 'd' ),//HintMediaHeaderAtomType + BOX_hint = FOUR_CHAR_INT( 'h', 'i', 'n', 't' ),//HintTrackReferenceAtomType + BOX_mdia = FOUR_CHAR_INT( 'm', 'd', 'i', 'a' ),//MediaAtomType + BOX_mdat = FOUR_CHAR_INT( 'm', 'd', 'a', 't' ),//MediaDataAtomType + BOX_mdhd = FOUR_CHAR_INT( 'm', 'd', 'h', 'd' ),//MediaHeaderAtomType + BOX_minf = FOUR_CHAR_INT( 'm', 'i', 'n', 'f' ),//MediaInformationAtomType + BOX_moov = FOUR_CHAR_INT( 'm', 'o', 'o', 'v' ),//MovieAtomType + BOX_mvhd = FOUR_CHAR_INT( 'm', 'v', 'h', 'd' ),//MovieHeaderAtomType + BOX_stsd = FOUR_CHAR_INT( 's', 't', 's', 'd' ),//SampleDescriptionAtomType + BOX_stsz = FOUR_CHAR_INT( 's', 't', 's', 'z' ),//SampleSizeAtomType + BOX_stz2 = FOUR_CHAR_INT( 's', 't', 'z', '2' ),//CompactSampleSizeAtomType + BOX_stbl = FOUR_CHAR_INT( 's', 't', 'b', 'l' ),//SampleTableAtomType + BOX_stsc = FOUR_CHAR_INT( 's', 't', 's', 'c' ),//SampleToChunkAtomType + BOX_stsh = FOUR_CHAR_INT( 's', 't', 's', 'h' ),//ShadowSyncAtomType + BOX_skip = FOUR_CHAR_INT( 's', 'k', 'i', 'p' ),//SkipAtomType + BOX_smhd = FOUR_CHAR_INT( 's', 'm', 'h', 'd' ),//SoundMediaHeaderAtomType + BOX_stss = FOUR_CHAR_INT( 's', 't', 's', 's' ),//SyncSampleAtomType + BOX_stts = FOUR_CHAR_INT( 's', 't', 't', 's' ),//TimeToSampleAtomType + BOX_trak = FOUR_CHAR_INT( 't', 'r', 'a', 'k' ),//TrackAtomType + BOX_tkhd = FOUR_CHAR_INT( 't', 'k', 'h', 'd' ),//TrackHeaderAtomType + BOX_tref = FOUR_CHAR_INT( 't', 'r', 'e', 'f' ),//TrackReferenceAtomType + BOX_udta = FOUR_CHAR_INT( 'u', 'd', 't', 'a' ),//UserDataAtomType + BOX_vmhd = FOUR_CHAR_INT( 'v', 'm', 'h', 'd' ),//VideoMediaHeaderAtomType + BOX_url = FOUR_CHAR_INT( 'u', 'r', 'l', ' ' ), + BOX_urn = FOUR_CHAR_INT( 'u', 'r', 'n', ' ' ), + + BOX_gnrv = FOUR_CHAR_INT( 'g', 'n', 'r', 'v' ),//GenericVisualSampleEntryAtomType + BOX_gnra = FOUR_CHAR_INT( 'g', 'n', 'r', 'a' ),//GenericAudioSampleEntryAtomType + + //V2 atoms + BOX_ftyp = FOUR_CHAR_INT( 'f', 't', 'y', 'p' ),//FileTypeAtomType + BOX_padb = FOUR_CHAR_INT( 'p', 'a', 'd', 'b' ),//PaddingBitsAtomType + + //MP4 Atoms + BOX_sdhd = FOUR_CHAR_INT( 's', 'd', 'h', 'd' ),//SceneDescriptionMediaHeaderAtomType + BOX_dpnd = FOUR_CHAR_INT( 'd', 'p', 'n', 'd' ),//StreamDependenceAtomType + BOX_iods = FOUR_CHAR_INT( 'i', 'o', 'd', 's' ),//ObjectDescriptorAtomType + BOX_odhd = FOUR_CHAR_INT( 'o', 'd', 'h', 'd' ),//ObjectDescriptorMediaHeaderAtomType + BOX_mpod = FOUR_CHAR_INT( 'm', 'p', 'o', 'd' ),//ODTrackReferenceAtomType + BOX_nmhd = FOUR_CHAR_INT( 'n', 'm', 'h', 'd' ),//MPEGMediaHeaderAtomType + BOX_esds = FOUR_CHAR_INT( 'e', 's', 'd', 's' ),//ESDAtomType + BOX_sync = FOUR_CHAR_INT( 's', 'y', 'n', 'c' ),//OCRReferenceAtomType + BOX_ipir = FOUR_CHAR_INT( 'i', 'p', 'i', 'r' ),//IPIReferenceAtomType + BOX_mp4s = FOUR_CHAR_INT( 'm', 'p', '4', 's' ),//MPEGSampleEntryAtomType + BOX_mp4a = FOUR_CHAR_INT( 'm', 'p', '4', 'a' ),//MPEGAudioSampleEntryAtomType + BOX_mp4v = FOUR_CHAR_INT( 'm', 'p', '4', 'v' ),//MPEGVisualSampleEntryAtomType + + // http://www.itscj.ipsj.or.jp/sc29/open/29view/29n7644t.doc + BOX_avc1 = FOUR_CHAR_INT( 'a', 'v', 'c', '1' ), + BOX_avc2 = FOUR_CHAR_INT( 'a', 'v', 'c', '2' ), + BOX_svc1 = FOUR_CHAR_INT( 's', 'v', 'c', '1' ), + BOX_avcC = FOUR_CHAR_INT( 'a', 'v', 'c', 'C' ), + BOX_svcC = FOUR_CHAR_INT( 's', 'v', 'c', 'C' ), + BOX_btrt = FOUR_CHAR_INT( 'b', 't', 'r', 't' ), + BOX_m4ds = FOUR_CHAR_INT( 'm', '4', 'd', 's' ), + BOX_seib = FOUR_CHAR_INT( 's', 'e', 'i', 'b' ), + + // H264/HEVC + BOX_hev1 = FOUR_CHAR_INT( 'h', 'e', 'v', '1' ), + BOX_hvc1 = FOUR_CHAR_INT( 'h', 'v', 'c', '1' ), + BOX_hvcC = FOUR_CHAR_INT( 'h', 'v', 'c', 'C' ), + + //3GPP atoms + BOX_samr = FOUR_CHAR_INT( 's', 'a', 'm', 'r' ),//AMRSampleEntryAtomType + BOX_sawb = FOUR_CHAR_INT( 's', 'a', 'w', 'b' ),//WB_AMRSampleEntryAtomType + BOX_damr = FOUR_CHAR_INT( 'd', 'a', 'm', 'r' ),//AMRConfigAtomType + BOX_s263 = FOUR_CHAR_INT( 's', '2', '6', '3' ),//H263SampleEntryAtomType + BOX_d263 = FOUR_CHAR_INT( 'd', '2', '6', '3' ),//H263ConfigAtomType + + //V2 atoms - Movie Fragments + BOX_mvex = FOUR_CHAR_INT( 'm', 'v', 'e', 'x' ),//MovieExtendsAtomType + BOX_trex = FOUR_CHAR_INT( 't', 'r', 'e', 'x' ),//TrackExtendsAtomType + BOX_moof = FOUR_CHAR_INT( 'm', 'o', 'o', 'f' ),//MovieFragmentAtomType + BOX_mfhd = FOUR_CHAR_INT( 'm', 'f', 'h', 'd' ),//MovieFragmentHeaderAtomType + BOX_traf = FOUR_CHAR_INT( 't', 'r', 'a', 'f' ),//TrackFragmentAtomType + BOX_tfhd = FOUR_CHAR_INT( 't', 'f', 'h', 'd' ),//TrackFragmentHeaderAtomType + BOX_tfdt = FOUR_CHAR_INT( 't', 'f', 'd', 't' ),//TrackFragmentBaseMediaDecodeTimeBox + BOX_trun = FOUR_CHAR_INT( 't', 'r', 'u', 'n' ),//TrackFragmentRunAtomType + BOX_mehd = FOUR_CHAR_INT( 'm', 'e', 'h', 'd' ),//MovieExtendsHeaderBox + + // Object Descriptors (OD) data coding + // These takes only 1 byte; this implementation translate to + // + OD_BASE to keep API uniform and safe for string functions + OD_BASE = FOUR_CHAR_INT( '$', '$', '$', '0' ),// + OD_ESD = FOUR_CHAR_INT( '$', '$', '$', '3' ),//SDescriptor_Tag + OD_DCD = FOUR_CHAR_INT( '$', '$', '$', '4' ),//DecoderConfigDescriptor_Tag + OD_DSI = FOUR_CHAR_INT( '$', '$', '$', '5' ),//DecoderSpecificInfo_Tag + OD_SLC = FOUR_CHAR_INT( '$', '$', '$', '6' ),//SLConfigDescriptor_Tag + + BOX_meta = FOUR_CHAR_INT( 'm', 'e', 't', 'a' ), + BOX_ilst = FOUR_CHAR_INT( 'i', 'l', 's', 't' ), + + // Metagata tags, see http://atomicparsley.sourceforge.net/mpeg-4files.html + BOX_calb = FOUR_CHAR_INT( '\xa9', 'a', 'l', 'b'), // album + BOX_cart = FOUR_CHAR_INT( '\xa9', 'a', 'r', 't'), // artist + BOX_aART = FOUR_CHAR_INT( 'a', 'A', 'R', 'T' ), // album artist + BOX_ccmt = FOUR_CHAR_INT( '\xa9', 'c', 'm', 't'), // comment + BOX_cday = FOUR_CHAR_INT( '\xa9', 'd', 'a', 'y'), // year (as string) + BOX_cnam = FOUR_CHAR_INT( '\xa9', 'n', 'a', 'm'), // title + BOX_cgen = FOUR_CHAR_INT( '\xa9', 'g', 'e', 'n'), // custom genre (as string or as byte!) + BOX_trkn = FOUR_CHAR_INT( 't', 'r', 'k', 'n'), // track number (byte) + BOX_disk = FOUR_CHAR_INT( 'd', 'i', 's', 'k'), // disk number (byte) + BOX_cwrt = FOUR_CHAR_INT( '\xa9', 'w', 'r', 't'), // composer + BOX_ctoo = FOUR_CHAR_INT( '\xa9', 't', 'o', 'o'), // encoder + BOX_tmpo = FOUR_CHAR_INT( 't', 'm', 'p', 'o'), // bpm (byte) + BOX_cpil = FOUR_CHAR_INT( 'c', 'p', 'i', 'l'), // compilation (byte) + BOX_covr = FOUR_CHAR_INT( 'c', 'o', 'v', 'r'), // cover art (JPEG/PNG) + BOX_rtng = FOUR_CHAR_INT( 'r', 't', 'n', 'g'), // rating/advisory (byte) + BOX_cgrp = FOUR_CHAR_INT( '\xa9', 'g', 'r', 'p'), // grouping + BOX_stik = FOUR_CHAR_INT( 's', 't', 'i', 'k'), // stik (byte) 0 = Movie 1 = Normal 2 = Audiobook 5 = Whacked Bookmark 6 = Music Video 9 = Short Film 10 = TV Show 11 = Booklet 14 = Ringtone + BOX_pcst = FOUR_CHAR_INT( 'p', 'c', 's', 't'), // podcast (byte) + BOX_catg = FOUR_CHAR_INT( 'c', 'a', 't', 'g'), // category + BOX_keyw = FOUR_CHAR_INT( 'k', 'e', 'y', 'w'), // keyword + BOX_purl = FOUR_CHAR_INT( 'p', 'u', 'r', 'l'), // podcast URL (byte) + BOX_egid = FOUR_CHAR_INT( 'e', 'g', 'i', 'd'), // episode global unique ID (byte) + BOX_desc = FOUR_CHAR_INT( 'd', 'e', 's', 'c'), // description + BOX_clyr = FOUR_CHAR_INT( '\xa9', 'l', 'y', 'r'), // lyrics (may be > 255 bytes) + BOX_tven = FOUR_CHAR_INT( 't', 'v', 'e', 'n'), // tv episode number + BOX_tves = FOUR_CHAR_INT( 't', 'v', 'e', 's'), // tv episode (byte) + BOX_tvnn = FOUR_CHAR_INT( 't', 'v', 'n', 'n'), // tv network name + BOX_tvsh = FOUR_CHAR_INT( 't', 'v', 's', 'h'), // tv show name + BOX_tvsn = FOUR_CHAR_INT( 't', 'v', 's', 'n'), // tv season (byte) + BOX_purd = FOUR_CHAR_INT( 'p', 'u', 'r', 'd'), // purchase date + BOX_pgap = FOUR_CHAR_INT( 'p', 'g', 'a', 'p'), // Gapless Playback (byte) + + //BOX_aart = FOUR_CHAR_INT( 'a', 'a', 'r', 't' ), // Album artist + BOX_cART = FOUR_CHAR_INT( '\xa9', 'A', 'R', 'T'), // artist + BOX_gnre = FOUR_CHAR_INT( 'g', 'n', 'r', 'e'), + + // 3GPP metatags (http://cpansearch.perl.org/src/JHAR/MP4-Info-1.12/Info.pm) + BOX_auth = FOUR_CHAR_INT( 'a', 'u', 't', 'h'), // author + BOX_titl = FOUR_CHAR_INT( 't', 'i', 't', 'l'), // title + BOX_dscp = FOUR_CHAR_INT( 'd', 's', 'c', 'p'), // description + BOX_perf = FOUR_CHAR_INT( 'p', 'e', 'r', 'f'), // performer + BOX_mean = FOUR_CHAR_INT( 'm', 'e', 'a', 'n'), // + BOX_name = FOUR_CHAR_INT( 'n', 'a', 'm', 'e'), // + BOX_data = FOUR_CHAR_INT( 'd', 'a', 't', 'a'), // + + // these from http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/2008-September/053151.html + BOX_albm = FOUR_CHAR_INT( 'a', 'l', 'b', 'm'), // album + BOX_yrrc = FOUR_CHAR_INT( 'y', 'r', 'r', 'c') // album +}; + +// Video track : 'vide' +#define MP4E_HANDLER_TYPE_VIDE 0x76696465 +// Audio track : 'soun' +#define MP4E_HANDLER_TYPE_SOUN 0x736F756E +// General MPEG-4 systems streams (without specific handler). +// Used for private stream, as suggested in http://www.mp4ra.org/handler.html +#define MP4E_HANDLER_TYPE_GESM 0x6765736D + +typedef struct +{ + boxsize_t size; + boxsize_t offset; + unsigned duration; + unsigned flag_random_access; +} sample_t; + +typedef struct { + unsigned char *data; + int bytes; + int capacity; +} minimp4_vector_t; + +typedef struct +{ + MP4E_track_t info; + minimp4_vector_t smpl; // sample descriptor + minimp4_vector_t pending_sample; + + minimp4_vector_t vsps; // or dsi for audio + minimp4_vector_t vpps; // not used for audio + minimp4_vector_t vvps; // used for HEVC + +} track_t; + +typedef struct MP4E_mux_tag +{ + minimp4_vector_t tracks; + + int64_t write_pos; + int (*write_callback)(int64_t offset, const void *buffer, size_t size, void *token); + void *token; + char *text_comment; + + int sequential_mode_flag; + int enable_fragmentation; // flag, indicating streaming-friendly 'fragmentation' mode + int fragments_count; // # of fragments in 'fragmentation' mode + +} MP4E_mux_t; + +static const unsigned char box_ftyp[] = { +#if 1 + 0,0,0,0x18,'f','t','y','p', + 'm','p','4','2',0,0,0,0, + 'm','p','4','2','i','s','o','m', +#else + // as in ffmpeg + 0,0,0,0x20,'f','t','y','p', + 'i','s','o','m',0,0,2,0, + 'm','p','4','1','i','s','o','m', + 'i','s','o','2','a','v','c','1', +#endif +}; + +/** +* Endian-independent byte-write macros +*/ +#define WR(x, n) *p++ = (unsigned char)((x) >> 8*n) +#define WRITE_1(x) WR(x, 0); +#define WRITE_2(x) WR(x, 1); WR(x, 0); +#define WRITE_3(x) WR(x, 2); WR(x, 1); WR(x, 0); +#define WRITE_4(x) WR(x, 3); WR(x, 2); WR(x, 1); WR(x, 0); +#define WR4(p, x) (p)[0] = (char)((x) >> 8*3); (p)[1] = (char)((x) >> 8*2); (p)[2] = (char)((x) >> 8*1); (p)[3] = (char)((x)); + +// Finish atom: update atom size field +#define END_ATOM --stack; WR4((unsigned char*)*stack, p - *stack); + +// Initiate atom: save position of size field on stack +#define ATOM(x) *stack++ = p; p += 4; WRITE_4(x); + +// Atom with 'FullAtomVersionFlags' field +#define ATOM_FULL(x, flag) ATOM(x); WRITE_4(flag); + +#define ERR(func) { int err = func; if (err) return err; } + +/** + Allocate vector with given size, return 1 on success, 0 on fail +*/ +static int minimp4_vector_init(minimp4_vector_t *h, int capacity) +{ + h->bytes = 0; + h->capacity = capacity; + h->data = capacity ? (unsigned char *)malloc(capacity) : NULL; + return !capacity || !!h->data; +} + +/** + Deallocates vector memory +*/ +static void minimp4_vector_reset(minimp4_vector_t *h) +{ + if (h->data) + free(h->data); + memset(h, 0, sizeof(minimp4_vector_t)); +} + +/** + Reallocate vector memory to the given size +*/ +static int minimp4_vector_grow(minimp4_vector_t *h, int bytes) +{ + void *p; + int new_size = h->capacity*2 + 1024; + if (new_size < h->capacity + bytes) + new_size = h->capacity + bytes + 1024; + p = realloc(h->data, new_size); + if (!p) + return 0; + h->data = (unsigned char*)p; + h->capacity = new_size; + return 1; +} + +/** + Allocates given number of bytes at the end of vector data, increasing + vector memory if necessary. + Return allocated memory. +*/ +static unsigned char *minimp4_vector_alloc_tail(minimp4_vector_t *h, int bytes) +{ + unsigned char *p; + if (!h->data && !minimp4_vector_init(h, 2*bytes + 1024)) + return NULL; + if ((h->capacity - h->bytes) < bytes && !minimp4_vector_grow(h, bytes)) + return NULL; + assert(h->data); + assert((h->capacity - h->bytes) >= bytes); + p = h->data + h->bytes; + h->bytes += bytes; + return p; +} + +/** + Append data to the end of the vector (accumulate ot enqueue) +*/ +static unsigned char *minimp4_vector_put(minimp4_vector_t *h, const void *buf, int bytes) +{ + unsigned char *tail = minimp4_vector_alloc_tail(h, bytes); + if (tail) + memcpy(tail, buf, bytes); + return tail; +} + +/** +* Allocates and initialize mp4 multiplexer +* return multiplexor handle on success; NULL on failure +*/ +MP4E_mux_t *MP4E_open(int sequential_mode_flag, int enable_fragmentation, void *token, + int (*write_callback)(int64_t offset, const void *buffer, size_t size, void *token)) +{ + if (write_callback(0, box_ftyp, sizeof(box_ftyp), token)) // Write fixed header: 'ftyp' box + return 0; + MP4E_mux_t *mux = (MP4E_mux_t*)malloc(sizeof(MP4E_mux_t)); + if (!mux) + return mux; + mux->sequential_mode_flag = sequential_mode_flag || enable_fragmentation; + mux->enable_fragmentation = enable_fragmentation; + mux->fragments_count = 0; + mux->write_callback = write_callback; + mux->token = token; + mux->text_comment = NULL; + mux->write_pos = sizeof(box_ftyp); + + if (!mux->sequential_mode_flag) + { // Write filler, which would be updated later + if (mux->write_callback(mux->write_pos, box_ftyp, 8, mux->token)) + { + free(mux); + return 0; + } + mux->write_pos += 16; // box_ftyp + box_free for 32bit or 64bit size encoding + } + minimp4_vector_init(&mux->tracks, 2*sizeof(track_t)); + return mux; +} + +/** +* Add new track +*/ +int MP4E_add_track(MP4E_mux_t *mux, const MP4E_track_t *track_data) +{ + track_t *tr; + int ntr = mux->tracks.bytes / sizeof(track_t); + + if (!mux || !track_data) + return MP4E_STATUS_BAD_ARGUMENTS; + + tr = (track_t*)minimp4_vector_alloc_tail(&mux->tracks, sizeof(track_t)); + if (!tr) + return MP4E_STATUS_NO_MEMORY; + memset(tr, 0, sizeof(track_t)); + memcpy(&tr->info, track_data, sizeof(*track_data)); + if (!minimp4_vector_init(&tr->smpl, 256)) + return MP4E_STATUS_NO_MEMORY; + minimp4_vector_init(&tr->vsps, 0); + minimp4_vector_init(&tr->vpps, 0); + minimp4_vector_init(&tr->pending_sample, 0); + return ntr; +} + +static const unsigned char *next_dsi(const unsigned char *p, const unsigned char *end, int *bytes) +{ + if (p < end + 2) + { + *bytes = p[0]*256 + p[1]; + return p + 2; + } else + return NULL; +} + +static int append_mem(minimp4_vector_t *v, const void *mem, int bytes) +{ + int i; + unsigned char size[2]; + const unsigned char *p = v->data; + for (i = 0; i + 2 < v->bytes;) + { + int cb = p[i]*256 + p[i + 1]; + if (cb == bytes && !memcmp(p + i + 2, mem, cb)) + return 1; + i += 2 + cb; + } + size[0] = bytes >> 8; + size[1] = bytes; + return minimp4_vector_put(v, size, 2) && minimp4_vector_put(v, mem, bytes); +} + +static int items_count(minimp4_vector_t *v) +{ + int i, count = 0; + const unsigned char *p = v->data; + for (i = 0; i + 2 < v->bytes;) + { + int cb = p[i]*256 + p[i + 1]; + count++; + i += 2 + cb; + } + return count; +} + +int MP4E_set_dsi(MP4E_mux_t *mux, int track_id, const void *dsi, int bytes) +{ + track_t* tr = ((track_t*)mux->tracks.data) + track_id; + assert(tr->info.track_media_kind == e_audio || + tr->info.track_media_kind == e_private); + if (tr->vsps.bytes) + return MP4E_STATUS_ONLY_ONE_DSI_ALLOWED; // only one DSI allowed + return append_mem(&tr->vsps, dsi, bytes) ? MP4E_STATUS_OK : MP4E_STATUS_NO_MEMORY; +} + +int MP4E_set_vps(MP4E_mux_t *mux, int track_id, const void *vps, int bytes) +{ + track_t* tr = ((track_t*)mux->tracks.data) + track_id; + assert(tr->info.track_media_kind == e_video); + return append_mem(&tr->vvps, vps, bytes) ? MP4E_STATUS_OK : MP4E_STATUS_NO_MEMORY; +} + +int MP4E_set_sps(MP4E_mux_t *mux, int track_id, const void *sps, int bytes) +{ + track_t* tr = ((track_t*)mux->tracks.data) + track_id; + assert(tr->info.track_media_kind == e_video); + return append_mem(&tr->vsps, sps, bytes) ? MP4E_STATUS_OK : MP4E_STATUS_NO_MEMORY; +} + +int MP4E_set_pps(MP4E_mux_t *mux, int track_id, const void *pps, int bytes) +{ + track_t* tr = ((track_t*)mux->tracks.data) + track_id; + assert(tr->info.track_media_kind == e_video); + return append_mem(&tr->vpps, pps, bytes) ? MP4E_STATUS_OK : MP4E_STATUS_NO_MEMORY; +} + +static unsigned get_duration(const track_t *tr) +{ + unsigned i, sum_duration = 0; + const sample_t *s = (const sample_t *)tr->smpl.data; + for (i = 0; i < tr->smpl.bytes/sizeof(sample_t); i++) + { + sum_duration += s[i].duration; + } + return sum_duration; +} + +static int write_pending_data(MP4E_mux_t *mux, track_t *tr) +{ + // if have pending sample && have at least one sample in the index + if (tr->pending_sample.bytes > 0 && tr->smpl.bytes >= sizeof(sample_t)) + { + // Complete pending sample + sample_t *smpl_desc; + unsigned char base[8], *p = base; + + assert(mux->sequential_mode_flag); + + // Write each sample to a separate atom + assert(mux->sequential_mode_flag); // Separate atom needed for sequential_mode only + WRITE_4(tr->pending_sample.bytes + 8); + WRITE_4(BOX_mdat); + ERR(mux->write_callback(mux->write_pos, base, p - base, mux->token)); + mux->write_pos += p - base; + + // Update sample descriptor with size and offset + smpl_desc = ((sample_t*)minimp4_vector_alloc_tail(&tr->smpl, 0)) - 1; + smpl_desc->size = tr->pending_sample.bytes; + smpl_desc->offset = (boxsize_t)mux->write_pos; + + // Write data + ERR(mux->write_callback(mux->write_pos, tr->pending_sample.data, tr->pending_sample.bytes, mux->token)); + mux->write_pos += tr->pending_sample.bytes; + + // reset buffer + tr->pending_sample.bytes = 0; + } + return MP4E_STATUS_OK; +} + +static int add_sample_descriptor(MP4E_mux_t *mux, track_t *tr, int data_bytes, int duration, int kind) +{ + sample_t smp; + smp.size = data_bytes; + smp.offset = (boxsize_t)mux->write_pos; + smp.duration = (duration ? duration : tr->info.default_duration); + smp.flag_random_access = (kind == MP4E_SAMPLE_RANDOM_ACCESS); + return NULL != minimp4_vector_put(&tr->smpl, &smp, sizeof(sample_t)); +} + +static int mp4e_flush_index(MP4E_mux_t *mux); + +/** +* Write Movie Fragment: 'moof' box +*/ +static int mp4e_write_fragment_header(MP4E_mux_t *mux, int track_num, int data_bytes, int duration, int kind +#if MP4D_TFDT_SUPPORT +, uint64_t timestamp +#endif +) +{ + unsigned char base[888], *p = base; + unsigned char *stack_base[20]; // atoms nesting stack + unsigned char **stack = stack_base; + unsigned char *pdata_offset; + unsigned flags; + enum + { + default_sample_duration_present = 0x000008, + default_sample_flags_present = 0x000020, + } e; + + track_t *tr = ((track_t*)mux->tracks.data) + track_num; + + ATOM(BOX_moof) + ATOM_FULL(BOX_mfhd, 0) + WRITE_4(mux->fragments_count); // start from 1 + END_ATOM + ATOM(BOX_traf) + flags = 0; + if (tr->info.track_media_kind == e_video) + flags |= 0x20; // default-sample-flags-present + else + flags |= 0x08; // default-sample-duration-present + flags = (tr->info.track_media_kind == e_video) ? 0x20020 : 0x20008; + + ATOM_FULL(BOX_tfhd, flags) + WRITE_4(track_num + 1); // track_ID + if (tr->info.track_media_kind == e_video) + { + WRITE_4(0x1010000); // default_sample_flags + } else + { + WRITE_4(duration); + } + END_ATOM + #if MP4D_TFDT_SUPPORT + ATOM_FULL(BOX_tfdt, 0x01000000) // version 1 + WRITE_4(timestamp >> 32); // upper timestamp + WRITE_4(timestamp & 0xffffffff); // lower timestamp + END_ATOM + #endif + if (tr->info.track_media_kind == e_audio) + { + flags = 0; + flags |= 0x001; // data-offset-present + flags |= 0x200; // sample-size-present + ATOM_FULL(BOX_trun, flags) + WRITE_4(1); // sample_count + pdata_offset = p; p += 4; // save ptr to data_offset + WRITE_4(data_bytes);// sample_size + END_ATOM + } else if (kind == MP4E_SAMPLE_RANDOM_ACCESS) + { + flags = 0; + flags |= 0x001; // data-offset-present + flags |= 0x004; // first-sample-flags-present + flags |= 0x100; // sample-duration-present + flags |= 0x200; // sample-size-present + ATOM_FULL(BOX_trun, flags) + WRITE_4(1); // sample_count + pdata_offset = p; p += 4; // save ptr to data_offset + WRITE_4(0x2000000); // first_sample_flags + WRITE_4(duration); // sample_duration + WRITE_4(data_bytes);// sample_size + END_ATOM + } else + { + flags = 0; + flags |= 0x001; // data-offset-present + flags |= 0x100; // sample-duration-present + flags |= 0x200; // sample-size-present + ATOM_FULL(BOX_trun, flags) + WRITE_4(1); // sample_count + pdata_offset = p; p += 4; // save ptr to data_offset + WRITE_4(duration); // sample_duration + WRITE_4(data_bytes);// sample_size + END_ATOM + } + END_ATOM + END_ATOM + WR4(pdata_offset, (p - base) + 8); + + ERR(mux->write_callback(mux->write_pos, base, p - base, mux->token)); + mux->write_pos += p - base; + return MP4E_STATUS_OK; +} + +static int mp4e_write_mdat_box(MP4E_mux_t *mux, uint32_t size) +{ + unsigned char base[8], *p = base; + WRITE_4(size); + WRITE_4(BOX_mdat); + ERR(mux->write_callback(mux->write_pos, base, p - base, mux->token)); + mux->write_pos += p - base; + return MP4E_STATUS_OK; +} + +/** +* Add new sample to specified track +*/ +int MP4E_put_sample(MP4E_mux_t *mux, int track_num, const void *data, int data_bytes, int duration, int kind) +{ + track_t *tr; + if (!mux || !data) + return MP4E_STATUS_BAD_ARGUMENTS; + tr = ((track_t*)mux->tracks.data) + track_num; + + if (mux->enable_fragmentation) + { + #if MP4D_TFDT_SUPPORT + // NOTE: assume a constant `duration` to calculate current timestamp + uint64_t timestamp = (uint64_t)mux->fragments_count * duration; + #endif + if (!mux->fragments_count++) + ERR(mp4e_flush_index(mux)); // write file headers before 1st sample + // write MOOF + MDAT + sample data + #if MP4D_TFDT_SUPPORT + ERR(mp4e_write_fragment_header(mux, track_num, data_bytes, duration, kind, timestamp)); + #else + ERR(mp4e_write_fragment_header(mux, track_num, data_bytes, duration, kind)); + #endif + // write MDAT box for each sample + ERR(mp4e_write_mdat_box(mux, data_bytes + 8)); + ERR(mux->write_callback(mux->write_pos, data, data_bytes, mux->token)); + mux->write_pos += data_bytes; + return MP4E_STATUS_OK; + } + + if (kind != MP4E_SAMPLE_CONTINUATION) + { + if (mux->sequential_mode_flag) + ERR(write_pending_data(mux, tr)); + if (!add_sample_descriptor(mux, tr, data_bytes, duration, kind)) + return MP4E_STATUS_NO_MEMORY; + } else + { + if (!mux->sequential_mode_flag) + { + sample_t *smpl_desc; + if (tr->smpl.bytes < sizeof(sample_t)) + return MP4E_STATUS_NO_MEMORY; // write continuation, but there are no samples in the index + // Accumulate size of the continuation in the sample descriptor + smpl_desc = (sample_t*)(tr->smpl.data + tr->smpl.bytes) - 1; + smpl_desc->size += data_bytes; + } + } + + if (mux->sequential_mode_flag) + { + if (!minimp4_vector_put(&tr->pending_sample, data, data_bytes)) + return MP4E_STATUS_NO_MEMORY; + } else + { + ERR(mux->write_callback(mux->write_pos, data, data_bytes, mux->token)); + mux->write_pos += data_bytes; + } + return MP4E_STATUS_OK; +} + +/** +* calculate size of length field of OD box +*/ +static int od_size_of_size(int size) +{ + int i, size_of_size = 1; + for (i = size; i > 0x7F; i -= 0x7F) + size_of_size++; + return size_of_size; +} + +/** +* Add or remove MP4 file text comment according to Apple specs: +* https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW1 +* http://atomicparsley.sourceforge.net/mpeg-4files.html +* note that ISO did not specify comment format. +*/ +int MP4E_set_text_comment(MP4E_mux_t *mux, const char *comment) +{ + if (!mux || !comment) + return MP4E_STATUS_BAD_ARGUMENTS; + if (mux->text_comment) + free(mux->text_comment); + mux->text_comment = strdup(comment); + if (!mux->text_comment) + return MP4E_STATUS_NO_MEMORY; + return MP4E_STATUS_OK; +} + +/** +* Write file index 'moov' box with all its boxes and indexes +*/ +static int mp4e_flush_index(MP4E_mux_t *mux) +{ + unsigned char *stack_base[20]; // atoms nesting stack + unsigned char **stack = stack_base; + unsigned char *base, *p; + unsigned int ntr, index_bytes, ntracks = mux->tracks.bytes / sizeof(track_t); + int i, err; + + // How much memory needed for indexes + // Experimental data: + // file with 1 track = 560 bytes + // file with 2 tracks = 972 bytes + // track size = 412 bytes; + // file header size = 148 bytes +#define FILE_HEADER_BYTES 256 +#define TRACK_HEADER_BYTES 512 + index_bytes = FILE_HEADER_BYTES; + if (mux->text_comment) + index_bytes += 128 + strlen(mux->text_comment); + for (ntr = 0; ntr < ntracks; ntr++) + { + track_t *tr = ((track_t*)mux->tracks.data) + ntr; + index_bytes += TRACK_HEADER_BYTES; // fixed amount (implementation-dependent) + // may need extra 4 bytes for duration field + 4 bytes for worst-case random access box + index_bytes += tr->smpl.bytes * (sizeof(sample_t) + 4 + 4) / sizeof(sample_t); + index_bytes += tr->vsps.bytes; + index_bytes += tr->vpps.bytes; + + ERR(write_pending_data(mux, tr)); + } + + base = (unsigned char*)malloc(index_bytes); + if (!base) + return MP4E_STATUS_NO_MEMORY; + p = base; + + if (!mux->sequential_mode_flag) + { + // update size of mdat box. + // One of 2 points, which requires random file access. + // Second is optional duration update at beginning of file in fragmentation mode. + // This can be avoided using "till eof" size code, but in this case indexes must be + // written before the mdat.... + int64_t size = mux->write_pos - sizeof(box_ftyp); + const int64_t size_limit = (int64_t)(uint64_t)0xfffffffe; + if (size > size_limit) + { + WRITE_4(1); + WRITE_4(BOX_mdat); + WRITE_4((size >> 32) & 0xffffffff); + WRITE_4(size & 0xffffffff); + } else + { + WRITE_4(8); + WRITE_4(BOX_free); + WRITE_4(size - 8); + WRITE_4(BOX_mdat); + } + ERR(mux->write_callback(sizeof(box_ftyp), base, p - base, mux->token)); + p = base; + } + + // Write index atoms; order taken from Table 1 of [1] +#define MOOV_TIMESCALE 1000 + ATOM(BOX_moov); + ATOM_FULL(BOX_mvhd, 0); + WRITE_4(0); // creation_time + WRITE_4(0); // modification_time + + if (ntracks) + { + track_t *tr = ((track_t*)mux->tracks.data) + 0; // take 1st track + unsigned duration = get_duration(tr); + duration = (unsigned)(duration * 1LL * MOOV_TIMESCALE / tr->info.time_scale); + WRITE_4(MOOV_TIMESCALE); // duration + WRITE_4(duration); // duration + } + + WRITE_4(0x00010000); // rate + WRITE_2(0x0100); // volume + WRITE_2(0); // reserved + WRITE_4(0); // reserved + WRITE_4(0); // reserved + + // matrix[9] + WRITE_4(0x00010000); WRITE_4(0); WRITE_4(0); + WRITE_4(0); WRITE_4(0x00010000); WRITE_4(0); + WRITE_4(0); WRITE_4(0); WRITE_4(0x40000000); + + // pre_defined[6] + WRITE_4(0); WRITE_4(0); WRITE_4(0); + WRITE_4(0); WRITE_4(0); WRITE_4(0); + + //next_track_ID is a non-zero integer that indicates a value to use for the track ID of the next track to be + //added to this presentation. Zero is not a valid track ID value. The value of next_track_ID shall be + //larger than the largest track-ID in use. + WRITE_4(ntracks + 1); + END_ATOM; + + for (ntr = 0; ntr < ntracks; ntr++) + { + track_t *tr = ((track_t*)mux->tracks.data) + ntr; + unsigned duration = get_duration(tr); + int samples_count = tr->smpl.bytes / sizeof(sample_t); + const sample_t *sample = (const sample_t *)tr->smpl.data; + unsigned handler_type; + const char *handler_ascii = NULL; + + if (mux->enable_fragmentation) + samples_count = 0; + else if (samples_count <= 0) + continue; // skip empty track + + switch (tr->info.track_media_kind) + { + case e_audio: + handler_type = MP4E_HANDLER_TYPE_SOUN; + handler_ascii = "SoundHandler"; + break; + case e_video: + handler_type = MP4E_HANDLER_TYPE_VIDE; + handler_ascii = "VideoHandler"; + break; + case e_private: + handler_type = MP4E_HANDLER_TYPE_GESM; + break; + default: + return MP4E_STATUS_BAD_ARGUMENTS; + } + + ATOM(BOX_trak); + ATOM_FULL(BOX_tkhd, 7); // flag: 1=trak enabled; 2=track in movie; 4=track in preview + WRITE_4(0); // creation_time + WRITE_4(0); // modification_time + WRITE_4(ntr + 1); // track_ID + WRITE_4(0); // reserved + WRITE_4((unsigned)(duration * 1LL * MOOV_TIMESCALE / tr->info.time_scale)); + WRITE_4(0); WRITE_4(0); // reserved[2] + WRITE_2(0); // layer + WRITE_2(0); // alternate_group + WRITE_2(0x0100); // volume {if track_is_audio 0x0100 else 0}; + WRITE_2(0); // reserved + + // matrix[9] + WRITE_4(0x00010000); WRITE_4(0); WRITE_4(0); + WRITE_4(0); WRITE_4(0x00010000); WRITE_4(0); + WRITE_4(0); WRITE_4(0); WRITE_4(0x40000000); + + if (tr->info.track_media_kind == e_audio || tr->info.track_media_kind == e_private) + { + WRITE_4(0); // width + WRITE_4(0); // height + } else + { + WRITE_4(tr->info.u.v.width*0x10000); // width + WRITE_4(tr->info.u.v.height*0x10000); // height + } + END_ATOM; + + ATOM(BOX_mdia); + ATOM_FULL(BOX_mdhd, 0); + WRITE_4(0); // creation_time + WRITE_4(0); // modification_time + WRITE_4(tr->info.time_scale); + WRITE_4(duration); // duration + { + int lang_code = ((tr->info.language[0] & 31) << 10) | ((tr->info.language[1] & 31) << 5) | (tr->info.language[2] & 31); + WRITE_2(lang_code); // language + } + WRITE_2(0); // pre_defined + END_ATOM; + + ATOM_FULL(BOX_hdlr, 0); + WRITE_4(0); // pre_defined + WRITE_4(handler_type); // handler_type + WRITE_4(0); WRITE_4(0); WRITE_4(0); // reserved[3] + // name is a null-terminated string in UTF-8 characters which gives a human-readable name for the track type (for debugging and inspection purposes). + // set mdia hdlr name field to what quicktime uses. + // Sony smartphone may fail to decode short files w/o handler name + if (handler_ascii) + { + for (i = 0; i < (int)strlen(handler_ascii) + 1; i++) + { + WRITE_1(handler_ascii[i]); + } + } else + { + WRITE_4(0); + } + END_ATOM; + + ATOM(BOX_minf); + + if (tr->info.track_media_kind == e_audio) + { + // Sound Media Header Box + ATOM_FULL(BOX_smhd, 0); + WRITE_2(0); // balance + WRITE_2(0); // reserved + END_ATOM; + } + if (tr->info.track_media_kind == e_video) + { + // mandatory Video Media Header Box + ATOM_FULL(BOX_vmhd, 1); + WRITE_2(0); // graphicsmode + WRITE_2(0); WRITE_2(0); WRITE_2(0); // opcolor[3] + END_ATOM; + } + + ATOM(BOX_dinf); + ATOM_FULL(BOX_dref, 0); + WRITE_4(1); // entry_count + // If the flag is set indicating that the data is in the same file as this box, then no string (not even an empty one) + // shall be supplied in the entry field. + + // ASP the correct way to avoid supply the string, is to use flag 1 + // otherwise ISO reference demux crashes + ATOM_FULL(BOX_url, 1); + END_ATOM; + END_ATOM; + END_ATOM; + + ATOM(BOX_stbl); + ATOM_FULL(BOX_stsd, 0); + WRITE_4(1); // entry_count; + + if (tr->info.track_media_kind == e_audio || tr->info.track_media_kind == e_private) + { + // AudioSampleEntry() assume MP4E_HANDLER_TYPE_SOUN + if (tr->info.track_media_kind == e_audio) + { + ATOM(BOX_mp4a); + } else + { + ATOM(BOX_mp4s); + } + + // SampleEntry + WRITE_4(0); WRITE_2(0); // reserved[6] + WRITE_2(1); // data_reference_index; - this is a tag for descriptor below + + if (tr->info.track_media_kind == e_audio) + { + // AudioSampleEntry + WRITE_4(0); WRITE_4(0); // reserved[2] + WRITE_2(tr->info.u.a.channelcount); // channelcount + WRITE_2(16); // samplesize + WRITE_4(0); // pre_defined+reserved + WRITE_4((tr->info.time_scale << 16)); // samplerate == = {timescale of media}<<16; + } + + ATOM_FULL(BOX_esds, 0); + if (tr->vsps.bytes > 0) + { + int dsi_bytes = tr->vsps.bytes - 2; // - two bytes size field + int dsi_size_size = od_size_of_size(dsi_bytes); + int dcd_bytes = dsi_bytes + dsi_size_size + 1 + (1 + 1 + 3 + 4 + 4); + int dcd_size_size = od_size_of_size(dcd_bytes); + int esd_bytes = dcd_bytes + dcd_size_size + 1 + 3; + +#define WRITE_OD_LEN(size) if (size > 0x7F) do { size -= 0x7F; WRITE_1(0x00ff); } while (size > 0x7F); WRITE_1(size) + WRITE_1(3); // OD_ESD + WRITE_OD_LEN(esd_bytes); + WRITE_2(0); // ES_ID(2) // TODO - what is this? + WRITE_1(0); // flags(1) + + WRITE_1(4); // OD_DCD + WRITE_OD_LEN(dcd_bytes); + if (tr->info.track_media_kind == e_audio) + { + WRITE_1(MP4_OBJECT_TYPE_AUDIO_ISO_IEC_14496_3); // OD_DCD + WRITE_1(5 << 2); // stream_type == AudioStream + } else + { + // http://xhelmboyx.tripod.com/formats/mp4-layout.txt + WRITE_1(208); // 208 = private video + WRITE_1(32 << 2); // stream_type == user private + } + WRITE_3(tr->info.u.a.channelcount * 6144/8); // bufferSizeDB in bytes, constant as in reference decoder + WRITE_4(0); // maxBitrate TODO + WRITE_4(0); // avg_bitrate_bps TODO + + WRITE_1(5); // OD_DSI + WRITE_OD_LEN(dsi_bytes); + for (i = 0; i < dsi_bytes; i++) + { + WRITE_1(tr->vsps.data[2 + i]); + } + } + END_ATOM; + END_ATOM; + } + + if (tr->info.track_media_kind == e_video && (MP4_OBJECT_TYPE_AVC == tr->info.object_type_indication || MP4_OBJECT_TYPE_HEVC == tr->info.object_type_indication)) + { + int numOfSequenceParameterSets = items_count(&tr->vsps); + int numOfPictureParameterSets = items_count(&tr->vpps); + if (MP4_OBJECT_TYPE_AVC == tr->info.object_type_indication) + { + ATOM(BOX_avc1); + } else + { + ATOM(BOX_hvc1); + } + // VisualSampleEntry 8.16.2 + // extends SampleEntry + WRITE_2(0); // reserved + WRITE_2(0); // reserved + WRITE_2(0); // reserved + WRITE_2(1); // data_reference_index + + WRITE_2(0); // pre_defined + WRITE_2(0); // reserved + WRITE_4(0); // pre_defined + WRITE_4(0); // pre_defined + WRITE_4(0); // pre_defined + WRITE_2(tr->info.u.v.width); + WRITE_2(tr->info.u.v.height); + WRITE_4(0x00480000); // horizresolution = 72 dpi + WRITE_4(0x00480000); // vertresolution = 72 dpi + WRITE_4(0); // reserved + WRITE_2(1); // frame_count + for (i = 0; i < 32; i++) + { + WRITE_1(0); // compressorname + } + WRITE_2(24); // depth + WRITE_2(-1); // pre_defined + + if (MP4_OBJECT_TYPE_AVC == tr->info.object_type_indication) + { + ATOM(BOX_avcC); + // AVCDecoderConfigurationRecord 5.2.4.1.1 + WRITE_1(1); // configurationVersion + WRITE_1(tr->vsps.data[2 + 1]); + WRITE_1(tr->vsps.data[2 + 2]); + WRITE_1(tr->vsps.data[2 + 3]); + WRITE_1(255); // 0xfc + NALU_len - 1 + WRITE_1(0xe0 | numOfSequenceParameterSets); + for (i = 0; i < tr->vsps.bytes; i++) + { + WRITE_1(tr->vsps.data[i]); + } + WRITE_1(numOfPictureParameterSets); + for (i = 0; i < tr->vpps.bytes; i++) + { + WRITE_1(tr->vpps.data[i]); + } + } else + { + int numOfVPS = items_count(&tr->vpps); + ATOM(BOX_hvcC); + // TODO: read actual params from stream + WRITE_1(1); // configurationVersion + WRITE_1(1); // Profile Space (2), Tier (1), Profile (5) + WRITE_4(0x60000000); // Profile Compatibility + WRITE_2(0); // progressive, interlaced, non packed constraint, frame only constraint flags + WRITE_4(0); // constraint indicator flags + WRITE_1(0); // level_idc + WRITE_2(0xf000); // Min Spatial Segmentation + WRITE_1(0xfc); // Parallelism Type + WRITE_1(0xfc); // Chroma Format + WRITE_1(0xf8); // Luma Depth + WRITE_1(0xf8); // Chroma Depth + WRITE_2(0); // Avg Frame Rate + WRITE_1(3); // ConstantFrameRate (2), NumTemporalLayers (3), TemporalIdNested (1), LengthSizeMinusOne (2) + + WRITE_1(3); // Num Of Arrays + WRITE_1((1 << 7) | (HEVC_NAL_VPS & 0x3f)); // Array Completeness + NAL Unit Type + WRITE_2(numOfVPS); + for (i = 0; i < tr->vvps.bytes; i++) + { + WRITE_1(tr->vvps.data[i]); + } + WRITE_1((1 << 7) | (HEVC_NAL_SPS & 0x3f)); + WRITE_2(numOfSequenceParameterSets); + for (i = 0; i < tr->vsps.bytes; i++) + { + WRITE_1(tr->vsps.data[i]); + } + WRITE_1((1 << 7) | (HEVC_NAL_PPS & 0x3f)); + WRITE_2(numOfPictureParameterSets); + for (i = 0; i < tr->vpps.bytes; i++) + { + WRITE_1(tr->vpps.data[i]); + } + } + + END_ATOM; + END_ATOM; + } + END_ATOM; + + /************************************************************************/ + /* indexes */ + /************************************************************************/ + + // Time to Sample Box + ATOM_FULL(BOX_stts, 0); + { + unsigned char *pentry_count = p; + int cnt = 1, entry_count = 0; + WRITE_4(0); + for (i = 0; i < samples_count; i++, cnt++) + { + if (i == (samples_count - 1) || sample[i].duration != sample[i + 1].duration) + { + WRITE_4(cnt); + WRITE_4(sample[i].duration); + cnt = 0; + entry_count++; + } + } + WR4(pentry_count, entry_count); + } + END_ATOM; + + // Sample To Chunk Box + ATOM_FULL(BOX_stsc, 0); + if (mux->enable_fragmentation) + { + WRITE_4(0); // entry_count + } else + { + WRITE_4(1); // entry_count + WRITE_4(1); // first_chunk; + WRITE_4(1); // samples_per_chunk; + WRITE_4(1); // sample_description_index; + } + END_ATOM; + + // Sample Size Box + ATOM_FULL(BOX_stsz, 0); + WRITE_4(0); // sample_size If this field is set to 0, then the samples have different sizes, and those sizes + // are stored in the sample size table. + WRITE_4(samples_count); // sample_count; + for (i = 0; i < samples_count; i++) + { + WRITE_4(sample[i].size); + } + END_ATOM; + + // Chunk Offset Box + int is_64_bit = 0; + if (samples_count && sample[samples_count - 1].offset > 0xffffffff) + is_64_bit = 1; + if (!is_64_bit) + { + ATOM_FULL(BOX_stco, 0); + WRITE_4(samples_count); + for (i = 0; i < samples_count; i++) + { + WRITE_4(sample[i].offset); + } + } else + { + ATOM_FULL(BOX_co64, 0); + WRITE_4(samples_count); + for (i = 0; i < samples_count; i++) + { + WRITE_4((sample[i].offset >> 32) & 0xffffffff); + WRITE_4(sample[i].offset & 0xffffffff); + } + } + END_ATOM; + + // Sync Sample Box + { + int ra_count = 0; + for (i = 0; i < samples_count; i++) + { + ra_count += !!sample[i].flag_random_access; + } + if (ra_count != samples_count) + { + // If the sync sample box is not present, every sample is a random access point. + ATOM_FULL(BOX_stss, 0); + WRITE_4(ra_count); + for (i = 0; i < samples_count; i++) + { + if (sample[i].flag_random_access) + { + WRITE_4(i + 1); + } + } + END_ATOM; + } + } + END_ATOM; + END_ATOM; + END_ATOM; + END_ATOM; + } // tracks loop + + if (mux->text_comment) + { + ATOM(BOX_udta); + ATOM_FULL(BOX_meta, 0); + ATOM_FULL(BOX_hdlr, 0); + WRITE_4(0); // pre_defined +#define MP4E_HANDLER_TYPE_MDIR 0x6d646972 + WRITE_4(MP4E_HANDLER_TYPE_MDIR); // handler_type + WRITE_4(0); WRITE_4(0); WRITE_4(0); // reserved[3] + WRITE_4(0); // name is a null-terminated string in UTF-8 characters which gives a human-readable name for the track type (for debugging and inspection purposes). + END_ATOM; + ATOM(BOX_ilst); + ATOM(BOX_ccmt); + ATOM(BOX_data); + WRITE_4(1); // type + WRITE_4(0); // lang + for (i = 0; i < (int)strlen(mux->text_comment) + 1; i++) + { + WRITE_1(mux->text_comment[i]); + } + END_ATOM; + END_ATOM; + END_ATOM; + END_ATOM; + END_ATOM; + } + + if (mux->enable_fragmentation) + { + track_t *tr = ((track_t*)mux->tracks.data) + 0; + uint32_t movie_duration = get_duration(tr); + + ATOM(BOX_mvex); + ATOM_FULL(BOX_mehd, 0); + WRITE_4(movie_duration); // duration + END_ATOM; + for (ntr = 0; ntr < ntracks; ntr++) + { + ATOM_FULL(BOX_trex, 0); + WRITE_4(ntr + 1); // track_ID + WRITE_4(1); // default_sample_description_index + WRITE_4(0); // default_sample_duration + WRITE_4(0); // default_sample_size + WRITE_4(0); // default_sample_flags + END_ATOM; + } + END_ATOM; + } + END_ATOM; // moov atom + + assert((unsigned)(p - base) <= index_bytes); + + err = mux->write_callback(mux->write_pos, base, p - base, mux->token); + mux->write_pos += p - base; + free(base); + return err; +} + +int MP4E_close(MP4E_mux_t *mux) +{ + int err = MP4E_STATUS_OK; + unsigned ntr, ntracks; + if (!mux) + return MP4E_STATUS_BAD_ARGUMENTS; + if (!mux->enable_fragmentation) + err = mp4e_flush_index(mux); + if (mux->text_comment) + free(mux->text_comment); + ntracks = mux->tracks.bytes / sizeof(track_t); + for (ntr = 0; ntr < ntracks; ntr++) + { + track_t *tr = ((track_t*)mux->tracks.data) + ntr; + minimp4_vector_reset(&tr->vsps); + minimp4_vector_reset(&tr->vpps); + minimp4_vector_reset(&tr->smpl); + minimp4_vector_reset(&tr->pending_sample); + } + minimp4_vector_reset(&mux->tracks); + free(mux); + return err; +} + +typedef uint32_t bs_item_t; +#define BS_BITS 32 + +typedef struct +{ + // Look-ahead bit cache: MSB aligned, 17 bits guaranteed, zero stuffing + unsigned int cache; + + // Bit counter = 16 - (number of bits in wCache) + // cache refilled when cache_free_bits >= 0 + int cache_free_bits; + + // Current read position + const uint16_t *buf; + + // original data buffer + const uint16_t *origin; + + // original data buffer length, bytes + unsigned origin_bytes; +} bit_reader_t; + + +#define LOAD_SHORT(x) ((uint16_t)(x << 8) | (x >> 8)) + +static unsigned int show_bits(bit_reader_t *bs, int n) +{ + unsigned int retval; + assert(n > 0 && n <= 16); + retval = (unsigned int)(bs->cache >> (32 - n)); + return retval; +} + +static void flush_bits(bit_reader_t *bs, int n) +{ + assert(n >= 0 && n <= 16); + bs->cache <<= n; + bs->cache_free_bits += n; + if (bs->cache_free_bits >= 0) + { + bs->cache |= ((uint32_t)LOAD_SHORT(*bs->buf)) << bs->cache_free_bits; + bs->buf++; + bs->cache_free_bits -= 16; + } +} + +static unsigned int get_bits(bit_reader_t *bs, int n) +{ + unsigned int retval = show_bits(bs, n); + flush_bits(bs, n); + return retval; +} + +static void set_pos_bits(bit_reader_t *bs, unsigned pos_bits) +{ + assert((int)pos_bits >= 0); + + bs->buf = bs->origin + pos_bits/16; + bs->cache = 0; + bs->cache_free_bits = 16; + flush_bits(bs, 0); + flush_bits(bs, pos_bits & 15); +} + +static unsigned get_pos_bits(const bit_reader_t *bs) +{ + // Current bitbuffer position = + // position of next wobits in the internal buffer + // minus bs, available in bit cache wobits + unsigned pos_bits = (unsigned)(bs->buf - bs->origin)*16; + pos_bits -= 16 - bs->cache_free_bits; + assert((int)pos_bits >= 0); + return pos_bits; +} + +static int remaining_bits(const bit_reader_t *bs) +{ + return bs->origin_bytes * 8 - get_pos_bits(bs); +} + +static void init_bits(bit_reader_t *bs, const void *data, unsigned data_bytes) +{ + bs->origin = (const uint16_t *)data; + bs->origin_bytes = data_bytes; + set_pos_bits(bs, 0); +} + +#define GetBits(n) get_bits(bs, n) + +/** +* Unsigned Golomb code +*/ +static int ue_bits(bit_reader_t *bs) +{ + int clz; + int val; + for (clz = 0; !get_bits(bs, 1); clz++) {} + //get_bits(bs, clz + 1); + val = (1 << clz) - 1 + (clz ? get_bits(bs, clz) : 0); + return val; +} + +#if MINIMP4_TRANSCODE_SPS_ID + +/** +* Output bitstream +*/ +typedef struct +{ + int shift; // bit position in the cache + uint32_t cache; // bit cache + bs_item_t *buf; // current position + bs_item_t *origin; // initial position +} bs_t; + +#define SWAP32(x) (uint32_t)((((x) >> 24) & 0xFF) | (((x) >> 8) & 0xFF00) | (((x) << 8) & 0xFF0000) | ((x & 0xFF) << 24)) + +static void h264e_bs_put_bits(bs_t *bs, unsigned n, unsigned val) +{ + assert(!(val >> n)); + bs->shift -= n; + assert((unsigned)n <= 32); + if (bs->shift < 0) + { + assert(-bs->shift < 32); + bs->cache |= val >> -bs->shift; + *bs->buf++ = SWAP32(bs->cache); + bs->shift = 32 + bs->shift; + bs->cache = 0; + } + bs->cache |= val << bs->shift; +} + +static void h264e_bs_flush(bs_t *bs) +{ + *bs->buf = SWAP32(bs->cache); +} + +static unsigned h264e_bs_get_pos_bits(const bs_t *bs) +{ + unsigned pos_bits = (unsigned)((bs->buf - bs->origin)*BS_BITS); + pos_bits += BS_BITS - bs->shift; + assert((int)pos_bits >= 0); + return pos_bits; +} + +static unsigned h264e_bs_byte_align(bs_t *bs) +{ + int pos = h264e_bs_get_pos_bits(bs); + h264e_bs_put_bits(bs, -pos & 7, 0); + return pos + (-pos & 7); +} + +/** +* Golomb code +* 0 => 1 +* 1 => 01 0 +* 2 => 01 1 +* 3 => 001 00 +* 4 => 001 01 +* +* [0] => 1 +* [1..2] => 01x +* [3..6] => 001xx +* [7..14] => 0001xxx +* +*/ +static void h264e_bs_put_golomb(bs_t *bs, unsigned val) +{ + int size = 0; + unsigned t = val + 1; + do + { + size++; + } while (t >>= 1); + + h264e_bs_put_bits(bs, 2*size - 1, val + 1); +} + +static void h264e_bs_init_bits(bs_t *bs, void *data) +{ + bs->origin = (bs_item_t*)data; + bs->buf = bs->origin; + bs->shift = BS_BITS; + bs->cache = 0; +} + +static int find_mem_cache(void *cache[], int cache_bytes[], int cache_size, void *mem, int bytes) +{ + int i; + if (!bytes) + return -1; + for (i = 0; i < cache_size; i++) + { + if (cache_bytes[i] == bytes && !memcmp(mem, cache[i], bytes)) + return i; // found + } + for (i = 0; i < cache_size; i++) + { + if (!cache_bytes[i]) + { + cache[i] = malloc(bytes); + if (cache[i]) + { + memcpy(cache[i], mem, bytes); + cache_bytes[i] = bytes; + } + return i; // put in + } + } + return -1; // no room +} + +/** +* 7.4.1.1. "Encapsulation of an SODB within an RBSP" +*/ +static int remove_nal_escapes(unsigned char *dst, const unsigned char *src, int h264_data_bytes) +{ + int i = 0, j = 0, zero_cnt = 0; + for (j = 0; j < h264_data_bytes; j++) + { + if (zero_cnt == 2 && src[j] <= 3) + { + if (src[j] == 3) + { + if (j == h264_data_bytes - 1) + { + // cabac_zero_word: no action + } else if (src[j + 1] <= 3) + { + j++; + zero_cnt = 0; + } else + { + // TODO: assume end-of-nal + //return 0; + } + } else + return 0; + } + dst[i++] = src[j]; + if (src[j]) + zero_cnt = 0; + else + zero_cnt++; + } + //while (--j > i) src[j] = 0; + return i; +} + +/** +* Put NAL escape codes to the output bitstream +*/ +static int nal_put_esc(uint8_t *d, const uint8_t *s, int n) +{ + int i, j = 4, cntz = 0; + d[0] = d[1] = d[2] = 0; d[3] = 1; // start code + for (i = 0; i < n; i++) + { + uint8_t byte = *s++; + if (cntz == 2 && byte <= 3) + { + d[j++] = 3; + cntz = 0; + } + if (byte) + cntz = 0; + else + cntz++; + d[j++] = byte; + } + return j; +} + +static void copy_bits(bit_reader_t *bs, bs_t *bd) +{ + unsigned cb, bits; + int bit_count = remaining_bits(bs); + while (bit_count > 7) + { + cb = MINIMP4_MIN(bit_count - 7, 8); + bits = GetBits(cb); + h264e_bs_put_bits(bd, cb, bits); + bit_count -= cb; + } + + // cut extra zeros after stop-bit + bits = GetBits(bit_count); + for (; bit_count && ~bits & 1; bit_count--) + { + bits >>= 1; + } + if (bit_count) + { + h264e_bs_put_bits(bd, bit_count, bits); + } +} + +static int change_sps_id(bit_reader_t *bs, bs_t *bd, int new_id, int *old_id) +{ + unsigned bits, sps_id, i, bytes; + for (i = 0; i < 3; i++) + { + bits = GetBits(8); + h264e_bs_put_bits(bd, 8, bits); + } + sps_id = ue_bits(bs); // max = 31 + + *old_id = sps_id; + sps_id = new_id; + assert(sps_id <= 31); + + h264e_bs_put_golomb(bd, sps_id); + copy_bits(bs, bd); + + bytes = h264e_bs_byte_align(bd) / 8; + h264e_bs_flush(bd); + return bytes; +} + +static int patch_pps(h264_sps_id_patcher_t *h, bit_reader_t *bs, bs_t *bd, int new_pps_id, int *old_id) +{ + int bytes; + unsigned pps_id = ue_bits(bs); // max = 255 + unsigned sps_id = ue_bits(bs); // max = 31 + + *old_id = pps_id; + sps_id = h->map_sps[sps_id]; + pps_id = new_pps_id; + + assert(sps_id <= 31); + assert(pps_id <= 255); + + h264e_bs_put_golomb(bd, pps_id); + h264e_bs_put_golomb(bd, sps_id); + copy_bits(bs, bd); + + bytes = h264e_bs_byte_align(bd) / 8; + h264e_bs_flush(bd); + return bytes; +} + +static void patch_slice_header(h264_sps_id_patcher_t *h, bit_reader_t *bs, bs_t *bd) +{ + unsigned first_mb_in_slice = ue_bits(bs); + unsigned slice_type = ue_bits(bs); + unsigned pps_id = ue_bits(bs); + + pps_id = h->map_pps[pps_id]; + + assert(pps_id <= 255); + + h264e_bs_put_golomb(bd, first_mb_in_slice); + h264e_bs_put_golomb(bd, slice_type); + h264e_bs_put_golomb(bd, pps_id); + copy_bits(bs, bd); +} + +static int transcode_nalu(h264_sps_id_patcher_t *h, const unsigned char *src, int nalu_bytes, unsigned char *dst) +{ + int old_id; + + bit_reader_t bst[1]; + bs_t bdt[1]; + + bit_reader_t bs[1]; + bs_t bd[1]; + int payload_type = src[0] & 31; + + *dst = *src; + h264e_bs_init_bits(bd, dst + 1); + init_bits(bs, src + 1, nalu_bytes - 1); + h264e_bs_init_bits(bdt, dst + 1); + init_bits(bst, src + 1, nalu_bytes - 1); + + switch(payload_type) + { + case 7: + { + int cb = change_sps_id(bst, bdt, 0, &old_id); + int id = find_mem_cache(h->sps_cache, h->sps_bytes, MINIMP4_MAX_SPS, dst + 1, cb); + if (id == -1) + return 0; + h->map_sps[old_id] = id; + change_sps_id(bs, bd, id, &old_id); + } + break; + case 8: + { + int cb = patch_pps(h, bst, bdt, 0, &old_id); + int id = find_mem_cache(h->pps_cache, h->pps_bytes, MINIMP4_MAX_PPS, dst + 1, cb); + if (id == -1) + return 0; + h->map_pps[old_id] = id; + patch_pps(h, bs, bd, id, &old_id); + } + break; + case 1: + case 2: + case 5: + patch_slice_header(h, bs, bd); + break; + default: + memcpy(dst, src, nalu_bytes); + return nalu_bytes; + } + + nalu_bytes = 1 + h264e_bs_byte_align(bd) / 8; + h264e_bs_flush(bd); + + return nalu_bytes; +} + +#endif + +/** +* Set pointer just after start code (00 .. 00 01), or to EOF if not found: +* +* NZ NZ ... NZ 00 00 00 00 01 xx xx ... xx (EOF) +* ^ ^ +* non-zero head.............. here ....... or here if no start code found +* +*/ +static const uint8_t *find_start_code(const uint8_t *h264_data, int h264_data_bytes, int *zcount) +{ + const uint8_t *eof = h264_data + h264_data_bytes; + const uint8_t *p = h264_data; + do + { + int zero_cnt = 1; + const uint8_t* found = (uint8_t*)memchr(p, 0, eof - p); + p = found ? found : eof; + while (p + zero_cnt < eof && !p[zero_cnt]) zero_cnt++; + if (zero_cnt >= 2 && p[zero_cnt] == 1) + { + *zcount = zero_cnt + 1; + return p + zero_cnt + 1; + } + p += zero_cnt; + } while (p < eof); + *zcount = 0; + return eof; +} + +/** +* Locate NAL unit in given buffer, and calculate it's length +*/ +static const uint8_t *find_nal_unit(const uint8_t *h264_data, int h264_data_bytes, int *pnal_unit_bytes) +{ + const uint8_t *eof = h264_data + h264_data_bytes; + int zcount; + const uint8_t *start = find_start_code(h264_data, h264_data_bytes, &zcount); + const uint8_t *stop = start; + if (start) + { + stop = find_start_code(start, (int)(eof - start), &zcount); + while (stop > start && !stop[-1]) + { + stop--; + } + } + + *pnal_unit_bytes = (int)(stop - start - zcount); + return start; +} + +int mp4_h26x_write_init(mp4_h26x_writer_t *h, MP4E_mux_t *mux, int width, int height, int is_hevc) +{ + MP4E_track_t tr; + tr.track_media_kind = e_video; + tr.language[0] = 'u'; + tr.language[1] = 'n'; + tr.language[2] = 'd'; + tr.language[3] = 0; + tr.object_type_indication = is_hevc ? MP4_OBJECT_TYPE_HEVC : MP4_OBJECT_TYPE_AVC; + tr.time_scale = 90000; + tr.default_duration = 0; + tr.u.v.width = width; + tr.u.v.height = height; + h->mux_track_id = MP4E_add_track(mux, &tr); + h->mux = mux; + + h->is_hevc = is_hevc; + h->need_vps = is_hevc; + h->need_sps = 1; + h->need_pps = 1; + h->need_idr = 1; +#if MINIMP4_TRANSCODE_SPS_ID + memset(&h->sps_patcher, 0, sizeof(h264_sps_id_patcher_t)); +#endif + return MP4E_STATUS_OK; +} + +void mp4_h26x_write_close(mp4_h26x_writer_t *h) +{ +#if MINIMP4_TRANSCODE_SPS_ID + h264_sps_id_patcher_t *p = &h->sps_patcher; + int i; + for (i = 0; i < MINIMP4_MAX_SPS; i++) + { + if (p->sps_cache[i]) + free(p->sps_cache[i]); + } + for (i = 0; i < MINIMP4_MAX_PPS; i++) + { + if (p->pps_cache[i]) + free(p->pps_cache[i]); + } +#endif + memset(h, 0, sizeof(*h)); +} + +static int mp4_h265_write_nal(mp4_h26x_writer_t *h, const unsigned char *nal, int sizeof_nal, unsigned timeStamp90kHz_next) +{ + int payload_type = (nal[0] >> 1) & 0x3f; + int is_intra = payload_type >= HEVC_NAL_BLA_W_LP && payload_type <= HEVC_NAL_CRA_NUT; + int err = MP4E_STATUS_OK; + //printf("payload_type=%d, intra=%d\n", payload_type, is_intra); + + if (is_intra && !h->need_sps && !h->need_pps && !h->need_vps) + h->need_idr = 0; + switch (payload_type) + { + case HEVC_NAL_VPS: + MP4E_set_vps(h->mux, h->mux_track_id, nal, sizeof_nal); + h->need_vps = 0; + break; + case HEVC_NAL_SPS: + MP4E_set_sps(h->mux, h->mux_track_id, nal, sizeof_nal); + h->need_sps = 0; + break; + case HEVC_NAL_PPS: + MP4E_set_pps(h->mux, h->mux_track_id, nal, sizeof_nal); + h->need_pps = 0; + break; + default: + if (h->need_vps || h->need_sps || h->need_pps || h->need_idr) + return MP4E_STATUS_BAD_ARGUMENTS; + { + unsigned char *tmp = (unsigned char *)malloc(4 + sizeof_nal); + if (!tmp) + return MP4E_STATUS_NO_MEMORY; + int sample_kind = MP4E_SAMPLE_DEFAULT; + tmp[0] = (unsigned char)(sizeof_nal >> 24); + tmp[1] = (unsigned char)(sizeof_nal >> 16); + tmp[2] = (unsigned char)(sizeof_nal >> 8); + tmp[3] = (unsigned char)(sizeof_nal); + memcpy(tmp + 4, nal, sizeof_nal); + if (is_intra) + sample_kind = MP4E_SAMPLE_RANDOM_ACCESS; + err = MP4E_put_sample(h->mux, h->mux_track_id, tmp, 4 + sizeof_nal, timeStamp90kHz_next, sample_kind); + free(tmp); + } + break; + } + return err; +} + +int mp4_h26x_write_nal(mp4_h26x_writer_t *h, const unsigned char *nal, int length, unsigned timeStamp90kHz_next) +{ + const unsigned char *eof = nal + length; + int payload_type, sizeof_nal, err = MP4E_STATUS_OK; + for (;;nal++) + { +#if MINIMP4_TRANSCODE_SPS_ID + unsigned char *nal1, *nal2; +#endif + nal = find_nal_unit(nal, (int)(eof - nal), &sizeof_nal); + if (!sizeof_nal) + break; + if (h->is_hevc) + { + ERR(mp4_h265_write_nal(h, nal, sizeof_nal, timeStamp90kHz_next)); + continue; + } + payload_type = nal[0] & 31; + if (9 == payload_type) + continue; // access unit delimiter, nothing to be done +#if MINIMP4_TRANSCODE_SPS_ID + // Transcode SPS, PPS and slice headers, reassigning ID's for SPS and PPS: + // - assign unique ID's to different SPS and PPS + // - assign same ID's to equal (except ID) SPS and PPS + // - save all different SPS and PPS + nal1 = (unsigned char *)malloc(sizeof_nal*17/16 + 32); + if (!nal1) + return MP4E_STATUS_NO_MEMORY; + nal2 = (unsigned char *)malloc(sizeof_nal*17/16 + 32); + if (!nal2) + { + free(nal1); + return MP4E_STATUS_NO_MEMORY; + } + sizeof_nal = remove_nal_escapes(nal2, nal, sizeof_nal); + if (!sizeof_nal) + { +exit_with_free: + free(nal1); + free(nal2); + return MP4E_STATUS_BAD_ARGUMENTS; + } + + sizeof_nal = transcode_nalu(&h->sps_patcher, nal2, sizeof_nal, nal1); + sizeof_nal = nal_put_esc(nal2, nal1, sizeof_nal); + + switch (payload_type) { + case 7: + MP4E_set_sps(h->mux, h->mux_track_id, nal2 + 4, sizeof_nal - 4); + h->need_sps = 0; + break; + case 8: + if (h->need_sps) + goto exit_with_free; + MP4E_set_pps(h->mux, h->mux_track_id, nal2 + 4, sizeof_nal - 4); + h->need_pps = 0; + break; + case 5: + if (h->need_sps) + goto exit_with_free; + h->need_idr = 0; + // flow through + default: + if (h->need_sps) + goto exit_with_free; + if (!h->need_pps && !h->need_idr) + { + bit_reader_t bs[1]; + init_bits(bs, nal + 1, sizeof_nal - 4 - 1); + unsigned first_mb_in_slice = ue_bits(bs); + //unsigned slice_type = ue_bits(bs); + int sample_kind = MP4E_SAMPLE_DEFAULT; + nal2[0] = (unsigned char)((sizeof_nal - 4) >> 24); + nal2[1] = (unsigned char)((sizeof_nal - 4) >> 16); + nal2[2] = (unsigned char)((sizeof_nal - 4) >> 8); + nal2[3] = (unsigned char)((sizeof_nal - 4)); + if (first_mb_in_slice) + sample_kind = MP4E_SAMPLE_CONTINUATION; + else if (payload_type == 5) + sample_kind = MP4E_SAMPLE_RANDOM_ACCESS; + err = MP4E_put_sample(h->mux, h->mux_track_id, nal2, sizeof_nal, timeStamp90kHz_next, sample_kind); + } + break; + } + free(nal1); + free(nal2); +#else + // No SPS/PPS transcoding + // This branch assumes that encoder use correct SPS/PPS ID's + switch (payload_type) { + case 7: + MP4E_set_sps(h->mux, h->mux_track_id, nal, sizeof_nal); + h->need_sps = 0; + break; + case 8: + MP4E_set_pps(h->mux, h->mux_track_id, nal, sizeof_nal); + h->need_pps = 0; + break; + case 5: + if (h->need_sps) + return MP4E_STATUS_BAD_ARGUMENTS; + h->need_idr = 0; + // flow through + default: + if (h->need_sps) + return MP4E_STATUS_BAD_ARGUMENTS; + if (!h->need_pps && !h->need_idr) + { + bit_reader_t bs[1]; + unsigned char *tmp = (unsigned char *)malloc(4 + sizeof_nal); + if (!tmp) + return MP4E_STATUS_NO_MEMORY; + init_bits(bs, nal + 1, sizeof_nal - 1); + unsigned first_mb_in_slice = ue_bits(bs); + int sample_kind = MP4E_SAMPLE_DEFAULT; + tmp[0] = (unsigned char)(sizeof_nal >> 24); + tmp[1] = (unsigned char)(sizeof_nal >> 16); + tmp[2] = (unsigned char)(sizeof_nal >> 8); + tmp[3] = (unsigned char)(sizeof_nal); + memcpy(tmp + 4, nal, sizeof_nal); + if (first_mb_in_slice) + sample_kind = MP4E_SAMPLE_CONTINUATION; + else if (payload_type == 5) + sample_kind = MP4E_SAMPLE_RANDOM_ACCESS; + err = MP4E_put_sample(h->mux, h->mux_track_id, tmp, 4 + sizeof_nal, timeStamp90kHz_next, sample_kind); + free(tmp); + } + break; + } +#endif + if (err) + break; + } + return err; +} + +#if MP4D_TRACE_SUPPORTED +# define TRACE(x) printf x +#else +# define TRACE(x) +#endif + +#define NELEM(x) (sizeof(x) / sizeof((x)[0])) + +static int minimp4_fgets(MP4D_demux_t *mp4) +{ + uint8_t c; + if (mp4->read_callback(mp4->read_pos, &c, 1, mp4->token)) + return -1; + mp4->read_pos++; + return c; +} + +/** +* Read given number of bytes from input stream +* Used to read box headers +*/ +static unsigned minimp4_read(MP4D_demux_t *mp4, int nb, int *eof_flag) +{ + uint32_t v = 0; int last_byte; + switch (nb) + { + case 4: v = (v << 8) | minimp4_fgets(mp4); + case 3: v = (v << 8) | minimp4_fgets(mp4); + case 2: v = (v << 8) | minimp4_fgets(mp4); + default: + case 1: v = (v << 8) | (last_byte = minimp4_fgets(mp4)); + } + if (last_byte < 0) + { + *eof_flag = 1; + } + return v; +} + +/** +* Read given number of bytes, but no more than *payload_bytes specifies... +* Used to read box payload +*/ +static uint32_t read_payload(MP4D_demux_t *mp4, unsigned nb, boxsize_t *payload_bytes, int *eof_flag) +{ + if (*payload_bytes < nb) + { + *eof_flag = 1; + nb = (int)*payload_bytes; + } + *payload_bytes -= nb; + + return minimp4_read(mp4, nb, eof_flag); +} + +/** +* Skips given number of bytes. +* Avoid math operations with fpos_t +*/ +static void my_fseek(MP4D_demux_t *mp4, boxsize_t pos, int *eof_flag) +{ + mp4->read_pos += pos; + if (mp4->read_pos >= mp4->read_size) + *eof_flag = 1; +} + +#define READ(n) read_payload(mp4, n, &payload_bytes, &eof_flag) +#define SKIP(n) { boxsize_t t = MINIMP4_MIN(payload_bytes, n); my_fseek(mp4, t, &eof_flag); payload_bytes -= t; } +#define MALLOC(t, p, size) p = (t)malloc(size); if (!(p)) { ERROR("out of memory"); } + +/* +* On error: release resources. +*/ +#define RETURN_ERROR(mess) { \ + TRACE(("\nMP4 ERROR: " mess)); \ + MP4D_close(mp4); \ + return 0; \ +} + +/* +* Any errors, occurred on top-level hierarchy is passed to exit check: 'if (!mp4->track_count) ... ' +*/ +#define ERROR(mess) \ + if (!depth) \ + break; \ + else \ + RETURN_ERROR(mess); + +typedef enum { BOX_ATOM, BOX_OD } boxtype_t; + +int MP4D_open(MP4D_demux_t *mp4, int (*read_callback)(int64_t offset, void *buffer, size_t size, void *token), void *token, int64_t file_size) +{ + // box stack size + int depth = 0; + + struct + { + // remaining bytes for box in the stack + boxsize_t bytes; + + // kind of box children's: OD chunks handled in the same manner as name chunks + boxtype_t format; + + } stack[MAX_CHUNKS_DEPTH]; + +#if MP4D_TRACE_SUPPORTED + // path of current element: List0/List1/... etc + uint32_t box_path[MAX_CHUNKS_DEPTH]; +#endif + + int eof_flag = 0; + unsigned i; + MP4D_track_t *tr = NULL; + + if (!mp4 || !read_callback) + { + TRACE(("\nERROR: invlaid arguments!")); + return 0; + } + + memset(mp4, 0, sizeof(MP4D_demux_t)); + mp4->read_callback = read_callback; + mp4->token = token; + mp4->read_size = file_size; + + stack[0].format = BOX_ATOM; // start with atom box + stack[0].bytes = 0; // never accessed + + do + { + // List of boxes, derived from 'FullBox' + // ~~~~~~~~~~~~~~~~~~~~~ + // need read version field and check version for these boxes + static const struct + { + uint32_t name; + unsigned max_version; + unsigned use_track_flag; + } g_fullbox[] = + { +#if MP4D_INFO_SUPPORTED + {BOX_mdhd, 1, 1}, + {BOX_mvhd, 1, 0}, + {BOX_hdlr, 0, 0}, + {BOX_meta, 0, 0}, // Android can produce meta box without 'FullBox' field, comment this line to simulate the bug +#endif +#if MP4D_TRACE_TIMESTAMPS + {BOX_stts, 0, 0}, + {BOX_ctts, 0, 0}, +#endif + {BOX_stz2, 0, 1}, + {BOX_stsz, 0, 1}, + {BOX_stsc, 0, 1}, + {BOX_stco, 0, 1}, + {BOX_co64, 0, 1}, + {BOX_stsd, 0, 0}, + {BOX_esds, 0, 1} // esds does not use track, but switches to OD mode. Check here, to avoid OD check + }; + + // List of boxes, which contains other boxes ('envelopes') + // Parser will descend down for boxes in this list, otherwise parsing will proceed to + // the next sibling box + // OD boxes handled in the same way as atom boxes... + static const struct + { + uint32_t name; + boxtype_t type; + } g_envelope_box[] = + { + {BOX_esds, BOX_OD}, // TODO: BOX_esds can be used for both audio and video, but this code supports audio only! + {OD_ESD, BOX_OD}, + {OD_DCD, BOX_OD}, + {OD_DSI, BOX_OD}, + {BOX_trak, BOX_ATOM}, + {BOX_moov, BOX_ATOM}, + //{BOX_moof, BOX_ATOM}, + {BOX_mdia, BOX_ATOM}, + {BOX_tref, BOX_ATOM}, + {BOX_minf, BOX_ATOM}, + {BOX_dinf, BOX_ATOM}, + {BOX_stbl, BOX_ATOM}, + {BOX_stsd, BOX_ATOM}, + {BOX_mp4a, BOX_ATOM}, + {BOX_mp4s, BOX_ATOM}, +#if MP4D_AVC_SUPPORTED + {BOX_mp4v, BOX_ATOM}, + {BOX_avc1, BOX_ATOM}, + //{BOX_avc2, BOX_ATOM}, + //{BOX_svc1, BOX_ATOM}, +#endif +#if MP4D_HEVC_SUPPORTED + {BOX_hvc1, BOX_ATOM}, +#endif + {BOX_udta, BOX_ATOM}, + {BOX_meta, BOX_ATOM}, + {BOX_ilst, BOX_ATOM} + }; + + uint32_t FullAtomVersionAndFlags = 0; + boxsize_t payload_bytes; + boxsize_t box_bytes; + uint32_t box_name; +#if MP4D_INFO_SUPPORTED + unsigned char **ptag = NULL; +#endif + int read_bytes = 0; + + // Read header box type and it's length + if (stack[depth].format == BOX_ATOM) + { + box_bytes = minimp4_read(mp4, 4, &eof_flag); +#if FIX_BAD_ANDROID_META_BOX +broken_android_meta_hack: +#endif + if (eof_flag) + break; // normal exit + + if (box_bytes >= 2 && box_bytes < 8) + { + ERROR("invalid box size (broken file?)"); + } + + box_name = minimp4_read(mp4, 4, &eof_flag); + read_bytes = 8; + + // Decode box size + if (box_bytes == 0 || // standard indication of 'till eof' size + box_bytes == (boxsize_t)0xFFFFFFFFU // some files uses non-standard 'till eof' signaling + ) + { + box_bytes = ~(boxsize_t)0; + } + + payload_bytes = box_bytes - 8; + + if (box_bytes == 1) // 64-bit sizes + { + TRACE(("\n64-bit chunk encountered")); + + box_bytes = minimp4_read(mp4, 4, &eof_flag); +#if MP4D_64BIT_SUPPORTED + box_bytes <<= 32; + box_bytes |= minimp4_read(mp4, 4, &eof_flag); +#else + if (box_bytes) + { + ERROR("UNSUPPORTED FEATURE: MP4BoxHeader(): 64-bit boxes not supported!"); + } + box_bytes = minimp4_read(mp4, 4, &eof_flag); +#endif + if (box_bytes < 16) + { + ERROR("invalid box size (broken file?)"); + } + payload_bytes = box_bytes - 16; + } + + // Read and check box version for some boxes + for (i = 0; i < NELEM(g_fullbox); i++) + { + if (box_name == g_fullbox[i].name) + { + FullAtomVersionAndFlags = READ(4); + read_bytes += 4; + +#if FIX_BAD_ANDROID_META_BOX + // Fix invalid BOX_meta, found in some Android-produced MP4 + // This branch is optional: bad box would be skipped + if (box_name == BOX_meta) + { + if (FullAtomVersionAndFlags >= 8 && FullAtomVersionAndFlags < payload_bytes) + { + if (box_bytes > stack[depth].bytes) + { + ERROR("broken file structure!"); + } + stack[depth].bytes -= box_bytes;; + depth++; + stack[depth].bytes = payload_bytes + 4; // +4 need for missing header + stack[depth].format = BOX_ATOM; + box_bytes = FullAtomVersionAndFlags; + TRACE(("Bad metadata box detected (Android bug?)!\n")); + goto broken_android_meta_hack; + } + } +#endif // FIX_BAD_ANDROID_META_BOX + + if ((FullAtomVersionAndFlags >> 24) > g_fullbox[i].max_version) + { + ERROR("unsupported box version!"); + } + if (g_fullbox[i].use_track_flag && !tr) + { + ERROR("broken file structure!"); + } + } + } + } else // stack[depth].format == BOX_OD + { + int val; + box_name = OD_BASE + minimp4_read(mp4, 1, &eof_flag); // 1-byte box type + read_bytes += 1; + if (eof_flag) + break; + + payload_bytes = 0; + box_bytes = 1; + do + { + val = minimp4_read(mp4, 1, &eof_flag); + read_bytes += 1; + if (eof_flag) + { + ERROR("premature EOF!"); + } + payload_bytes = (payload_bytes << 7) | (val & 0x7F); + box_bytes++; + } while (val & 0x80); + box_bytes += payload_bytes; + } + +#if MP4D_TRACE_SUPPORTED + box_path[depth] = (box_name >> 24) | (box_name << 24) | ((box_name >> 8) & 0x0000FF00) | ((box_name << 8) & 0x00FF0000); + TRACE(("%2d %8d %.*s (%d bytes remains for sibilings) \n", depth, (int)box_bytes, depth*4, (char*)box_path, (int)stack[depth].bytes)); +#endif + + // Check that box size <= parent size + if (depth) + { + // Skip box with bad size + assert(box_bytes > 0); + if (box_bytes > stack[depth].bytes) + { + TRACE(("Wrong %c%c%c%c box size: broken file?\n", (box_name >> 24)&255, (box_name >> 16)&255, (box_name >> 8)&255, box_name&255)); + box_bytes = stack[depth].bytes; + box_name = 0; + payload_bytes = box_bytes - read_bytes; + } + stack[depth].bytes -= box_bytes; + } + + // Read box header + switch(box_name) + { + case BOX_stz2: //ISO/IEC 14496-1 Page 38. Section 8.17.2 - Sample Size Box. + case BOX_stsz: + { + int size = 0; + uint32_t sample_size = READ(4); + tr->sample_count = READ(4); + MALLOC(unsigned int*, tr->entry_size, tr->sample_count*4); + for (i = 0; i < tr->sample_count; i++) + { + if (box_name == BOX_stsz) + { + tr->entry_size[i] = (sample_size?sample_size:READ(4)); + } else + { + switch (sample_size & 0xFF) + { + case 16: + tr->entry_size[i] = READ(2); + break; + case 8: + tr->entry_size[i] = READ(1); + break; + case 4: + if (i & 1) + { + tr->entry_size[i] = size & 15; + } else + { + size = READ(1); + tr->entry_size[i] = (size >> 4); + } + break; + } + } + } + } + break; + + case BOX_stsc: //ISO/IEC 14496-12 Page 38. Section 8.18 - Sample To Chunk Box. + tr->sample_to_chunk_count = READ(4); + MALLOC(MP4D_sample_to_chunk_t*, tr->sample_to_chunk, tr->sample_to_chunk_count*sizeof(tr->sample_to_chunk[0])); + for (i = 0; i < tr->sample_to_chunk_count; i++) + { + tr->sample_to_chunk[i].first_chunk = READ(4); + tr->sample_to_chunk[i].samples_per_chunk = READ(4); + SKIP(4); // sample_description_index + } + break; +#if MP4D_TRACE_TIMESTAMPS || MP4D_TIMESTAMPS_SUPPORTED + case BOX_stts: + { + unsigned count = READ(4); + unsigned j, k = 0, ts = 0, ts_count = count; +#if MP4D_TIMESTAMPS_SUPPORTED + MALLOC(unsigned int*, tr->timestamp, ts_count*4); + MALLOC(unsigned int*, tr->duration, ts_count*4); +#endif + + for (i = 0; i < count; i++) + { + unsigned sc = READ(4); + int d = READ(4); + TRACE(("sample %8d count %8d duration %8d\n", i, sc, d)); +#if MP4D_TIMESTAMPS_SUPPORTED + if (k + sc > ts_count) + { + ts_count = k + sc; + tr->timestamp = (unsigned int*)realloc(tr->timestamp, ts_count * sizeof(unsigned)); + tr->duration = (unsigned int*)realloc(tr->duration, ts_count * sizeof(unsigned)); + } + for (j = 0; j < sc; j++) + { + tr->duration[k] = d; + tr->timestamp[k++] = ts; + ts += d; + } +#endif + } + } + break; + case BOX_ctts: + { + unsigned count = READ(4); + for (i = 0; i < count; i++) + { + int sc = READ(4); + int d = READ(4); + (void)sc; + (void)d; + TRACE(("sample %8d count %8d decoding to composition offset %8d\n", i, sc, d)); + } + } + break; +#endif + case BOX_stco: //ISO/IEC 14496-12 Page 39. Section 8.19 - Chunk Offset Box. + case BOX_co64: + tr->chunk_count = READ(4); + MALLOC(MP4D_file_offset_t*, tr->chunk_offset, tr->chunk_count*sizeof(MP4D_file_offset_t)); + for (i = 0; i < tr->chunk_count; i++) + { + tr->chunk_offset[i] = READ(4); + if (box_name == BOX_co64) + { +#if !MP4D_64BIT_SUPPORTED + if (tr->chunk_offset[i]) + { + ERROR("UNSUPPORTED FEATURE: 64-bit chunk_offset not supported!"); + } +#endif + tr->chunk_offset[i] <<= 32; + tr->chunk_offset[i] |= READ(4); + } + } + break; + +#if MP4D_INFO_SUPPORTED + case BOX_mvhd: + SKIP(((FullAtomVersionAndFlags >> 24) == 1) ? 8 + 8 : 4 + 4); + mp4->timescale = READ(4); + mp4->duration_hi = ((FullAtomVersionAndFlags >> 24) == 1) ? READ(4) : 0; + mp4->duration_lo = READ(4); + SKIP(4 + 2 + 2 + 4*2 + 4*9 + 4*6 + 4); + break; + + case BOX_mdhd: + SKIP(((FullAtomVersionAndFlags >> 24) == 1) ? 8 + 8 : 4 + 4); + tr->timescale = READ(4); + tr->duration_hi = ((FullAtomVersionAndFlags >> 24) == 1) ? READ(4) : 0; + tr->duration_lo = READ(4); + + { + int ISO_639_2_T = READ(2); + tr->language[2] = (ISO_639_2_T & 31) + 0x60; ISO_639_2_T >>= 5; + tr->language[1] = (ISO_639_2_T & 31) + 0x60; ISO_639_2_T >>= 5; + tr->language[0] = (ISO_639_2_T & 31) + 0x60; + } + // the rest of this box is skipped by default ... + break; + + case BOX_hdlr: + if (tr) // When this box is within 'meta' box, the track may not be avaialable + { + SKIP(4); // pre_defined + tr->handler_type = READ(4); + } + // typically hdlr box does not contain any useful info. + // the rest of this box is skipped by default ... + break; + + case BOX_btrt: + if (!tr) + { + ERROR("broken file structure!"); + } + + SKIP(4 + 4); + tr->avg_bitrate_bps = READ(4); + break; + + // Set pointer to tag to be read... + case BOX_calb: ptag = &mp4->tag.album; break; + case BOX_cART: ptag = &mp4->tag.artist; break; + case BOX_cnam: ptag = &mp4->tag.title; break; + case BOX_cday: ptag = &mp4->tag.year; break; + case BOX_ccmt: ptag = &mp4->tag.comment; break; + case BOX_cgen: ptag = &mp4->tag.genre; break; + +#endif + + case BOX_stsd: + SKIP(4); // entry_count, BOX_mp4a & BOX_mp4v boxes follows immediately + break; + + case BOX_mp4s: // private stream + if (!tr) + { + ERROR("broken file structure!"); + } + SKIP(6*1 + 2/*Base SampleEntry*/); + break; + + case BOX_mp4a: + if (!tr) + { + ERROR("broken file structure!"); + } +#if MP4D_INFO_SUPPORTED + SKIP(6*1+2/*Base SampleEntry*/ + 4*2); + tr->SampleDescription.audio.channelcount = READ(2); + SKIP(2/*samplesize*/ + 2 + 2); + tr->SampleDescription.audio.samplerate_hz = READ(4) >> 16; +#else + SKIP(28); +#endif + break; + +#if MP4D_AVC_SUPPORTED + case BOX_avc1: // AVCSampleEntry extends VisualSampleEntry +// case BOX_avc2: - no test +// case BOX_svc1: - no test + case BOX_mp4v: + if (!tr) + { + ERROR("broken file structure!"); + } +#if MP4D_INFO_SUPPORTED + SKIP(6*1 + 2/*Base SampleEntry*/ + 2 + 2 + 4*3); + tr->SampleDescription.video.width = READ(2); + tr->SampleDescription.video.height = READ(2); + // frame_count is always 1 + // compressorname is rarely set.. + SKIP(4 + 4 + 4 + 2/*frame_count*/ + 32/*compressorname*/ + 2 + 2); +#else + SKIP(78); +#endif + // ^^^ end of VisualSampleEntry + // now follows for BOX_avc1: + // BOX_avcC + // BOX_btrt (optional) + // BOX_m4ds (optional) + // for BOX_mp4v: + // BOX_esds + break; + + case BOX_avcC: // AVCDecoderConfigurationRecord() + // hack: AAC-specific DSI field reused (for it have same purpoose as sps/pps) + // TODO: check this hack if BOX_esds co-exist with BOX_avcC + tr->object_type_indication = MP4_OBJECT_TYPE_AVC; + tr->dsi = (unsigned char*)malloc((size_t)box_bytes); + tr->dsi_bytes = (unsigned)box_bytes; + { + int spspps; + unsigned char *p = tr->dsi; + unsigned int configurationVersion = READ(1); + unsigned int AVCProfileIndication = READ(1); + unsigned int profile_compatibility = READ(1); + unsigned int AVCLevelIndication = READ(1); + //bit(6) reserved = + unsigned int lengthSizeMinusOne = READ(1) & 3; + + (void)configurationVersion; + (void)AVCProfileIndication; + (void)profile_compatibility; + (void)AVCLevelIndication; + (void)lengthSizeMinusOne; + + for (spspps = 0; spspps < 2; spspps++) + { + unsigned int numOfSequenceParameterSets= READ(1); + if (!spspps) + { + numOfSequenceParameterSets &= 31; // clears 3 msb for SPS + } + *p++ = numOfSequenceParameterSets; + for (i = 0; i < numOfSequenceParameterSets; i++) + { + unsigned k, sequenceParameterSetLength = READ(2); + *p++ = sequenceParameterSetLength >> 8; + *p++ = sequenceParameterSetLength ; + for (k = 0; k < sequenceParameterSetLength; k++) + { + *p++ = READ(1); + } + } + } + } + break; +#endif // MP4D_AVC_SUPPORTED + + case OD_ESD: + { + unsigned flags = READ(3); // ES_ID(2) + flags(1) + + if (flags & 0x80) // steamdependflag + { + SKIP(2); // dependsOnESID + } + if (flags & 0x40) // urlflag + { + unsigned bytecount = READ(1); + SKIP(bytecount); // skip URL + } + if (flags & 0x20) // ocrflag (was reserved in MPEG-4 v.1) + { + SKIP(2); // OCRESID + } + break; + } + + case OD_DCD: //ISO/IEC 14496-1 Page 28. Section 8.6.5 - DecoderConfigDescriptor. + assert(tr); // ensured by g_fullbox[] check + tr->object_type_indication = READ(1); +#if MP4D_INFO_SUPPORTED + tr->stream_type = READ(1) >> 2; + SKIP(3/*bufferSizeDB*/ + 4/*maxBitrate*/); + tr->avg_bitrate_bps = READ(4); +#else + SKIP(1+3+4+4); +#endif + break; + + case OD_DSI: //ISO/IEC 14496-1 Page 28. Section 8.6.5 - DecoderConfigDescriptor. + assert(tr); // ensured by g_fullbox[] check + if (!tr->dsi && payload_bytes) + { + MALLOC(unsigned char*, tr->dsi, (int)payload_bytes); + for (i = 0; i < payload_bytes; i++) + { + tr->dsi[i] = minimp4_read(mp4, 1, &eof_flag); // These bytes available due to check above + } + tr->dsi_bytes = i; + payload_bytes -= i; + break; + } + + default: + TRACE(("[%c%c%c%c] %d\n", box_name >> 24, box_name >> 16, box_name >> 8, box_name, (int)payload_bytes)); + } + +#if MP4D_INFO_SUPPORTED + // Read tag is tag pointer is set + if (ptag && !*ptag && payload_bytes > 16) + { +#if 0 + uint32_t size = READ(4); + uint32_t data = READ(4); + uint32_t class = READ(4); + uint32_t x1 = READ(4); + TRACE(("%2d %2d %2d ", size, class, x1)); +#else + SKIP(4 + 4 + 4 + 4); +#endif + MALLOC(unsigned char*, *ptag, (unsigned)payload_bytes + 1); + for (i = 0; payload_bytes != 0; i++) + { + (*ptag)[i] = READ(1); + } + (*ptag)[i] = 0; // zero-terminated string + } +#endif + + if (box_name == BOX_trak) + { + // New track found: allocate memory using realloc() + // Typically there are 1 audio track for AAC audio file, + // 4 tracks for movie file, + // 3-5 tracks for scalable audio (CELP+AAC) + // and up to 50 tracks for BSAC scalable audio + void *mem = realloc(mp4->track, (mp4->track_count + 1)*sizeof(MP4D_track_t)); + if (!mem) + { + // if realloc fails, it does not deallocate old pointer! + ERROR("out of memory"); + } + mp4->track = (MP4D_track_t*)mem; + tr = mp4->track + mp4->track_count++; + memset(tr, 0, sizeof(MP4D_track_t)); + } else if (box_name == BOX_meta) + { + tr = NULL; // Avoid update of 'hdlr' box, which may contains in the 'meta' box + } + + // If this box is envelope, save it's size in box stack + for (i = 0; i < NELEM(g_envelope_box); i++) + { + if (box_name == g_envelope_box[i].name) + { + if (++depth >= MAX_CHUNKS_DEPTH) + { + ERROR("too deep atoms nesting!"); + } + stack[depth].bytes = payload_bytes; + stack[depth].format = g_envelope_box[i].type; + break; + } + } + + // if box is not envelope, just skip it + if (i == NELEM(g_envelope_box)) + { + if (payload_bytes > file_size) + { + eof_flag = 1; + } else + { + SKIP(payload_bytes); + } + } + + // remove empty boxes from stack + // don't touch box with index 0 (which indicates whole file) + while (depth > 0 && !stack[depth].bytes) + { + depth--; + } + + } while(!eof_flag); + + if (!mp4->track_count) + { + RETURN_ERROR("no tracks found"); + } + return 1; +} + +/** +* Find chunk, containing given sample. +* Returns chunk number, and first sample in this chunk. +*/ +static int sample_to_chunk(MP4D_track_t *tr, unsigned nsample, unsigned *nfirst_sample_in_chunk) +{ + unsigned chunk_group = 0, nc; + unsigned sum = 0; + *nfirst_sample_in_chunk = 0; + if (tr->chunk_count <= 1) + { + return 0; + } + for (nc = 0; nc < tr->chunk_count; nc++) + { + if (chunk_group + 1 < tr->sample_to_chunk_count // stuck at last entry till EOF + && nc + 1 == // Chunks counted starting with '1' + tr->sample_to_chunk[chunk_group + 1].first_chunk) // next group? + { + chunk_group++; + } + + sum += tr->sample_to_chunk[chunk_group].samples_per_chunk; + if (nsample < sum) + return nc; + + // TODO: this can be calculated once per file + *nfirst_sample_in_chunk = sum; + } + return -1; +} + +// Exported API function +MP4D_file_offset_t MP4D_frame_offset(const MP4D_demux_t *mp4, unsigned ntrack, unsigned nsample, unsigned *frame_bytes, unsigned *timestamp, unsigned *duration) +{ + MP4D_track_t *tr = mp4->track + ntrack; + unsigned ns; + int nchunk = sample_to_chunk(tr, nsample, &ns); + MP4D_file_offset_t offset; + + if (nchunk < 0) + { + *frame_bytes = 0; + return 0; + } + + offset = tr->chunk_offset[nchunk]; + for (; ns < nsample; ns++) + { + offset += tr->entry_size[ns]; + } + + *frame_bytes = tr->entry_size[ns]; + + if (timestamp) + { +#if MP4D_TIMESTAMPS_SUPPORTED + *timestamp = tr->timestamp[ns]; +#else + *timestamp = 0; +#endif + } + if (duration) + { +#if MP4D_TIMESTAMPS_SUPPORTED + *duration = tr->duration[ns]; +#else + *duration = 0; +#endif + } + + return offset; +} + +#define FREE(x) if (x) {free(x); x = NULL;} + +// Exported API function +void MP4D_close(MP4D_demux_t *mp4) +{ + while (mp4->track_count) + { + MP4D_track_t *tr = mp4->track + --mp4->track_count; + FREE(tr->entry_size); +#if MP4D_TIMESTAMPS_SUPPORTED + FREE(tr->timestamp); + FREE(tr->duration); +#endif + FREE(tr->sample_to_chunk); + FREE(tr->chunk_offset); + FREE(tr->dsi); + } + FREE(mp4->track); +#if MP4D_INFO_SUPPORTED + FREE(mp4->tag.title); + FREE(mp4->tag.artist); + FREE(mp4->tag.album); + FREE(mp4->tag.year); + FREE(mp4->tag.comment); + FREE(mp4->tag.genre); +#endif +} + +static int skip_spspps(const unsigned char *p, int nbytes, int nskip) +{ + int i, k = 0; + for (i = 0; i < nskip; i++) + { + unsigned segmbytes; + if (k > nbytes - 2) + return -1; + segmbytes = p[k]*256 + p[k+1]; + k += 2 + segmbytes; + } + return k; +} + +static const void *MP4D_read_spspps(const MP4D_demux_t *mp4, unsigned int ntrack, int pps_flag, int nsps, int *sps_bytes) +{ + int sps_count, skip_bytes; + int bytepos = 0; + unsigned char *p = mp4->track[ntrack].dsi; + if (ntrack >= mp4->track_count) + return NULL; + if (mp4->track[ntrack].object_type_indication != MP4_OBJECT_TYPE_AVC) + return NULL; // SPS/PPS are specific for AVC format only + + if (pps_flag) + { + // Skip all SPS + sps_count = p[bytepos++]; + skip_bytes = skip_spspps(p+bytepos, mp4->track[ntrack].dsi_bytes - bytepos, sps_count); + if (skip_bytes < 0) + return NULL; + bytepos += skip_bytes; + } + + // Skip sps/pps before the given target + sps_count = p[bytepos++]; + if (nsps >= sps_count) + return NULL; + skip_bytes = skip_spspps(p+bytepos, mp4->track[ntrack].dsi_bytes - bytepos, nsps); + if (skip_bytes < 0) + return NULL; + bytepos += skip_bytes; + *sps_bytes = p[bytepos]*256 + p[bytepos+1]; + return p + bytepos + 2; +} + + +const void *MP4D_read_sps(const MP4D_demux_t *mp4, unsigned int ntrack, int nsps, int *sps_bytes) +{ + return MP4D_read_spspps(mp4, ntrack, 0, nsps, sps_bytes); +} + +const void *MP4D_read_pps(const MP4D_demux_t *mp4, unsigned int ntrack, int npps, int *pps_bytes) +{ + return MP4D_read_spspps(mp4, ntrack, 1, npps, pps_bytes); +} + +#if MP4D_PRINT_INFO_SUPPORTED +/************************************************************************/ +/* Purely informational part, may be removed for embedded applications */ +/************************************************************************/ + +// +// Decodes ISO/IEC 14496 MP4 stream type to ASCII string +// +static const char *GetMP4StreamTypeName(int streamType) +{ + switch (streamType) + { + case 0x00: return "Forbidden"; + case 0x01: return "ObjectDescriptorStream"; + case 0x02: return "ClockReferenceStream"; + case 0x03: return "SceneDescriptionStream"; + case 0x04: return "VisualStream"; + case 0x05: return "AudioStream"; + case 0x06: return "MPEG7Stream"; + case 0x07: return "IPMPStream"; + case 0x08: return "ObjectContentInfoStream"; + case 0x09: return "MPEGJStream"; + default: + if (streamType >= 0x20 && streamType <= 0x3F) + { + return "User private"; + } else + { + return "Reserved for ISO use"; + } + } +} + +// +// Decodes ISO/IEC 14496 MP4 object type to ASCII string +// +static const char *GetMP4ObjectTypeName(int objectTypeIndication) +{ + switch (objectTypeIndication) + { + case 0x00: return "Forbidden"; + case 0x01: return "Systems ISO/IEC 14496-1"; + case 0x02: return "Systems ISO/IEC 14496-1"; + case 0x20: return "Visual ISO/IEC 14496-2"; + case 0x40: return "Audio ISO/IEC 14496-3"; + case 0x60: return "Visual ISO/IEC 13818-2 Simple Profile"; + case 0x61: return "Visual ISO/IEC 13818-2 Main Profile"; + case 0x62: return "Visual ISO/IEC 13818-2 SNR Profile"; + case 0x63: return "Visual ISO/IEC 13818-2 Spatial Profile"; + case 0x64: return "Visual ISO/IEC 13818-2 High Profile"; + case 0x65: return "Visual ISO/IEC 13818-2 422 Profile"; + case 0x66: return "Audio ISO/IEC 13818-7 Main Profile"; + case 0x67: return "Audio ISO/IEC 13818-7 LC Profile"; + case 0x68: return "Audio ISO/IEC 13818-7 SSR Profile"; + case 0x69: return "Audio ISO/IEC 13818-3"; + case 0x6A: return "Visual ISO/IEC 11172-2"; + case 0x6B: return "Audio ISO/IEC 11172-3"; + case 0x6C: return "Visual ISO/IEC 10918-1"; + case 0xFF: return "no object type specified"; + default: + if (objectTypeIndication >= 0xC0 && objectTypeIndication <= 0xFE) + return "User private"; + else + return "Reserved for ISO use"; + } +} + +/** +* Print MP4 information to stdout. +* Subject for customization to particular application + +Output Example #1: movie file + +MP4 FILE: 7 tracks found. Movie time 104.12 sec + +No|type|lng| duration | bitrate| Stream type | Object type + 0|odsm|fre| 0.00 s 1 frm| 0| Forbidden | Forbidden + 1|sdsm|fre| 0.00 s 1 frm| 0| Forbidden | Forbidden + 2|vide|```| 104.12 s 2603 frm| 1960559| VisualStream | Visual ISO/IEC 14496-2 - 720x304 + 3|soun|ger| 104.06 s 2439 frm| 191242| AudioStream | Audio ISO/IEC 14496-3 - 6 ch 24000 hz + 4|soun|eng| 104.06 s 2439 frm| 194171| AudioStream | Audio ISO/IEC 14496-3 - 6 ch 24000 hz + 5|subp|ger| 71.08 s 25 frm| 0| Forbidden | Forbidden + 6|subp|eng| 71.08 s 25 frm| 0| Forbidden | Forbidden + +Output Example #2: audio file with tags + +MP4 FILE: 1 tracks found. Movie time 92.42 sec +title = 86-Second Blowout +artist = Yo La Tengo +album = May I Sing With Me +year = 1992 + +No|type|lng| duration | bitrate| Stream type | Object type + 0|mdir|und| 92.42 s 3980 frm| 128000| AudioStream | Audio ISO/IEC 14496-3MP4 FILE: 1 tracks found. Movie time 92.42 sec + +*/ +void MP4D_printf_info(const MP4D_demux_t *mp4) +{ + unsigned i; + printf("\nMP4 FILE: %d tracks found. Movie time %.2f sec\n", mp4->track_count, (4294967296.0*mp4->duration_hi + mp4->duration_lo) / mp4->timescale); +#define STR_TAG(name) if (mp4->tag.name) printf("%10s = %s\n", #name, mp4->tag.name) + STR_TAG(title); + STR_TAG(artist); + STR_TAG(album); + STR_TAG(year); + STR_TAG(comment); + STR_TAG(genre); + printf("\nNo|type|lng| duration | bitrate| %-23s| Object type", "Stream type"); + for (i = 0; i < mp4->track_count; i++) + { + MP4D_track_t *tr = mp4->track + i; + + printf("\n%2d|%c%c%c%c|%c%c%c|%7.2f s %6d frm| %7d|", i, + (tr->handler_type >> 24), (tr->handler_type >> 16), (tr->handler_type >> 8), (tr->handler_type >> 0), + tr->language[0], tr->language[1], tr->language[2], + (65536.0*65536.0*tr->duration_hi + tr->duration_lo) / tr->timescale, + tr->sample_count, + tr->avg_bitrate_bps); + + printf(" %-23s|", GetMP4StreamTypeName(tr->stream_type)); + printf(" %-23s", GetMP4ObjectTypeName(tr->object_type_indication)); + + if (tr->handler_type == MP4D_HANDLER_TYPE_SOUN) + { + printf(" - %d ch %d hz", tr->SampleDescription.audio.channelcount, tr->SampleDescription.audio.samplerate_hz); + } else if (tr->handler_type == MP4D_HANDLER_TYPE_VIDE) + { + printf(" - %dx%d", tr->SampleDescription.video.width, tr->SampleDescription.video.height); + } + } + printf("\n"); +} + +#endif // MP4D_PRINT_INFO_SUPPORTED +#endif diff --git a/WickedEngine/Utility/utility_common.cpp b/WickedEngine/Utility/utility_common.cpp index 6afbc1bb0..bd97fa7e8 100644 --- a/WickedEngine/Utility/utility_common.cpp +++ b/WickedEngine/Utility/utility_common.cpp @@ -21,6 +21,12 @@ #define QOI_IMPLEMENTATION #include "qoi.h" +#define MINIMP4_IMPLEMENTATION +#include "minimp4.h" + +#define H264_IMPLEMENTATION +#include "h264.h" + // Basis Universal library sources are compiled below for simplicity: diff --git a/WickedEngine/Utility/vk_mem_alloc.h b/WickedEngine/Utility/vk_mem_alloc.h index b787c36d8..823cef8ad 100644 --- a/WickedEngine/Utility/vk_mem_alloc.h +++ b/WickedEngine/Utility/vk_mem_alloc.h @@ -2614,6 +2614,10 @@ VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString( #include // For std::popcount #endif +#if VMA_STATS_STRING_ENABLED + #include // For snprintf +#endif + /******************************************************************************* CONFIGURATION SECTION @@ -2647,8 +2651,7 @@ VmaAllocatorCreateInfo::pVulkanFunctions. Other members can be null. #endif #ifndef VMA_USE_STL_SHARED_MUTEX - // Compiler conforms to C++17. - #if __cplusplus >= 201703L + #if __cplusplus >= 201703L || _MSVC_LANG >= 201703L // C++17 #define VMA_USE_STL_SHARED_MUTEX 1 // Visual studio defines __cplusplus properly only when passed additional parameter: /Zc:__cplusplus // Otherwise it is always 199711L, despite shared_mutex works since Visual Studio 2015 Update 2. @@ -2693,6 +2696,14 @@ remove them if not needed. #define VMA_NULL nullptr #endif +#ifndef VMA_FALLTHROUGH + #if __cplusplus >= 201703L || _MSVC_LANG >= 201703L // C++17 + #define VMA_FALLTHROUGH [[fallthrough]] + #else + #define VMA_FALLTHROUGH + #endif +#endif + // Normal assert to check for programmer's errors, especially in Debug configuration. #ifndef VMA_ASSERT #ifdef NDEBUG @@ -2769,7 +2780,7 @@ static void* vma_aligned_alloc(size_t alignment, size_t size) { return _aligned_malloc(size, alignment); } -#elif __cplusplus >= 201703L // Compiler conforms to C++17. +#elif __cplusplus >= 201703L || _MSVC_LANG >= 201703L // C++17 static void* vma_aligned_alloc(size_t alignment, size_t size) { return aligned_alloc(alignment, size); @@ -2795,7 +2806,7 @@ static void vma_aligned_free(void* VMA_NULLABLE ptr) #endif #ifndef VMA_ALIGN_OF - #define VMA_ALIGN_OF(type) (__alignof(type)) + #define VMA_ALIGN_OF(type) (alignof(type)) #endif #ifndef VMA_SYSTEM_ALIGNED_MALLOC @@ -2856,6 +2867,21 @@ static void vma_aligned_free(void* VMA_NULLABLE ptr) #define VMA_DEBUG_LOG(str) VMA_DEBUG_LOG_FORMAT("%s", (str)) #endif +#ifndef VMA_CLASS_NO_COPY + #define VMA_CLASS_NO_COPY(className) \ + private: \ + className(const className&) = delete; \ + className& operator=(const className&) = delete; +#endif +#ifndef VMA_CLASS_NO_COPY_NO_MOVE + #define VMA_CLASS_NO_COPY_NO_MOVE(className) \ + private: \ + className(const className&) = delete; \ + className(className&&) = delete; \ + className& operator=(const className&) = delete; \ + className& operator=(className&&) = delete; +#endif + // Define this macro to 1 to enable functions: vmaBuildStatsString, vmaFreeStatsString. #if VMA_STATS_STRING_ENABLED static inline void VmaUint32ToStr(char* VMA_NOT_NULL outStr, size_t strLen, uint32_t num) @@ -2875,7 +2901,9 @@ static void vma_aligned_free(void* VMA_NULLABLE ptr) #ifndef VMA_MUTEX class VmaMutex { + VMA_CLASS_NO_COPY_NO_MOVE(VmaMutex) public: + VmaMutex() { } void Lock() { m_Mutex.lock(); } void Unlock() { m_Mutex.unlock(); } bool TryLock() { return m_Mutex.try_lock(); } @@ -3041,13 +3069,6 @@ tools like RenderDoc. #define VMA_MAPPING_HYSTERESIS_ENABLED 1 #endif -#ifndef VMA_CLASS_NO_COPY - #define VMA_CLASS_NO_COPY(className) \ - private: \ - className(const className&) = delete; \ - className& operator=(const className&) = delete; -#endif - #define VMA_VALIDATE(cond) do { if(!(cond)) { \ VMA_ASSERT(0 && "Validation failed: " #cond); \ return false; \ @@ -3540,7 +3561,7 @@ new element with value (key) should be inserted. template static IterT VmaBinaryFindFirstNotLess(IterT beg, IterT end, const KeyT& key, const CmpLess& cmp) { - size_t down = 0, up = (end - beg); + size_t down = 0, up = size_t(end - beg); while (down < up) { const size_t mid = down + (up - down) / 2; // Overflow-safe midpoint calculation @@ -3947,7 +3968,7 @@ static void VmaAddDetailedStatistics(VmaDetailedStatistics& inoutStats, const Vm // Helper RAII class to lock a mutex in constructor and unlock it in destructor (at the end of scope). struct VmaMutexLock { - VMA_CLASS_NO_COPY(VmaMutexLock) + VMA_CLASS_NO_COPY_NO_MOVE(VmaMutexLock) public: VmaMutexLock(VMA_MUTEX& mutex, bool useMutex = true) : m_pMutex(useMutex ? &mutex : VMA_NULL) @@ -3963,7 +3984,7 @@ private: // Helper RAII class to lock a RW mutex in constructor and unlock it in destructor (at the end of scope), for reading. struct VmaMutexLockRead { - VMA_CLASS_NO_COPY(VmaMutexLockRead) + VMA_CLASS_NO_COPY_NO_MOVE(VmaMutexLockRead) public: VmaMutexLockRead(VMA_RW_MUTEX& mutex, bool useMutex) : m_pMutex(useMutex ? &mutex : VMA_NULL) @@ -3979,7 +4000,7 @@ private: // Helper RAII class to lock a RW mutex in constructor and unlock it in destructor (at the end of scope), for writing. struct VmaMutexLockWrite { - VMA_CLASS_NO_COPY(VmaMutexLockWrite) + VMA_CLASS_NO_COPY_NO_MOVE(VmaMutexLockWrite) public: VmaMutexLockWrite(VMA_RW_MUTEX& mutex, bool useMutex) : m_pMutex(useMutex ? &mutex : VMA_NULL) @@ -4434,7 +4455,7 @@ allocator can create multiple blocks. template class VmaPoolAllocator { - VMA_CLASS_NO_COPY(VmaPoolAllocator) + VMA_CLASS_NO_COPY_NO_MOVE(VmaPoolAllocator) public: VmaPoolAllocator(const VkAllocationCallbacks* pAllocationCallbacks, uint32_t firstBlockCapacity); ~VmaPoolAllocator(); @@ -4567,7 +4588,7 @@ struct VmaListItem template class VmaRawList { - VMA_CLASS_NO_COPY(VmaRawList) + VMA_CLASS_NO_COPY_NO_MOVE(VmaRawList) public: typedef VmaListItem ItemType; @@ -4830,7 +4851,7 @@ VmaListItem* VmaRawList::InsertAfter(ItemType* pItem, const T& value) template class VmaList { - VMA_CLASS_NO_COPY(VmaList) + VMA_CLASS_NO_COPY_NO_MOVE(VmaList) public: class reverse_iterator; class const_iterator; @@ -5422,7 +5443,7 @@ void VmaStringBuilder::AddNumber(uint32_t num) char* p = &buf[10]; do { - *--p = '0' + (num % 10); + *--p = '0' + (char)(num % 10); num /= 10; } while (num); Add(p); @@ -5435,7 +5456,7 @@ void VmaStringBuilder::AddNumber(uint64_t num) char* p = &buf[20]; do { - *--p = '0' + (num % 10); + *--p = '0' + (char)(num % 10); num /= 10; } while (num); Add(p); @@ -5457,7 +5478,7 @@ VmaStringBuilder passed to the constructor. */ class VmaJsonWriter { - VMA_CLASS_NO_COPY(VmaJsonWriter) + VMA_CLASS_NO_COPY_NO_MOVE(VmaJsonWriter) public: // sb - string builder to write the document to. Must remain alive for the whole lifetime of this object. VmaJsonWriter(const VkAllocationCallbacks* pAllocationCallbacks, VmaStringBuilder& sb); @@ -5649,7 +5670,6 @@ void VmaJsonWriter::ContinueString(const char* pStr) break; default: VMA_ASSERT(0 && "Character not currently supported."); - break; } } } @@ -5796,7 +5816,7 @@ static void VmaPrintDetailedStatistics(VmaJsonWriter& json, const VmaDetailedSta class VmaMappingHysteresis { - VMA_CLASS_NO_COPY(VmaMappingHysteresis) + VMA_CLASS_NO_COPY_NO_MOVE(VmaMappingHysteresis) public: VmaMappingHysteresis() = default; @@ -5903,7 +5923,7 @@ Thread-safety: */ class VmaDeviceMemoryBlock { - VMA_CLASS_NO_COPY(VmaDeviceMemoryBlock) + VMA_CLASS_NO_COPY_NO_MOVE(VmaDeviceMemoryBlock) public: VmaBlockMetadata* m_pMetadata; @@ -6126,6 +6146,7 @@ Thread-safe, synchronized internally. */ class VmaDedicatedAllocationList { + VMA_CLASS_NO_COPY_NO_MOVE(VmaDedicatedAllocationList) public: VmaDedicatedAllocationList() {} ~VmaDedicatedAllocationList(); @@ -6311,6 +6332,7 @@ in a single VkDeviceMemory block. */ class VmaBlockMetadata { + VMA_CLASS_NO_COPY_NO_MOVE(VmaBlockMetadata) public: // pAllocationCallbacks, if not null, must be owned externally - alive and unchanged for the whole lifetime of this object. VmaBlockMetadata(const VkAllocationCallbacks* pAllocationCallbacks, @@ -6377,7 +6399,7 @@ public: protected: const VkAllocationCallbacks* GetAllocationCallbacks() const { return m_pAllocationCallbacks; } VkDeviceSize GetBufferImageGranularity() const { return m_BufferImageGranularity; } - VkDeviceSize GetDebugMargin() const { return IsVirtual() ? 0 : VMA_DEBUG_MARGIN; } + VkDeviceSize GetDebugMargin() const { return VkDeviceSize(IsVirtual() ? 0 : VMA_DEBUG_MARGIN); } void DebugLogAllocation(VkDeviceSize offset, VkDeviceSize size, void* userData) const; #if VMA_STATS_STRING_ENABLED @@ -6751,7 +6773,7 @@ class VmaBlockMetadata_Generic : public VmaBlockMetadata { friend class VmaDefragmentationAlgorithm_Generic; friend class VmaDefragmentationAlgorithm_Fast; - VMA_CLASS_NO_COPY(VmaBlockMetadata_Generic) + VMA_CLASS_NO_COPY_NO_MOVE(VmaBlockMetadata_Generic) public: VmaBlockMetadata_Generic(const VkAllocationCallbacks* pAllocationCallbacks, VkDeviceSize bufferImageGranularity, bool isVirtual); @@ -7590,7 +7612,7 @@ GetSize() +-------+ */ class VmaBlockMetadata_Linear : public VmaBlockMetadata { - VMA_CLASS_NO_COPY(VmaBlockMetadata_Linear) + VMA_CLASS_NO_COPY_NO_MOVE(VmaBlockMetadata_Linear) public: VmaBlockMetadata_Linear(const VkAllocationCallbacks* pAllocationCallbacks, VkDeviceSize bufferImageGranularity, bool isVirtual); @@ -9209,7 +9231,7 @@ m_LevelCount is the maximum number of levels to use in the current object. */ class VmaBlockMetadata_Buddy : public VmaBlockMetadata { - VMA_CLASS_NO_COPY(VmaBlockMetadata_Buddy) + VMA_CLASS_NO_COPY_NO_MOVE(VmaBlockMetadata_Buddy) public: VmaBlockMetadata_Buddy(const VkAllocationCallbacks* pAllocationCallbacks, VkDeviceSize bufferImageGranularity, bool isVirtual); @@ -9908,7 +9930,7 @@ void VmaBlockMetadata_Buddy::PrintDetailedMapNode(class VmaJsonWriter& json, con // VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT for fastest alloc time possible. class VmaBlockMetadata_TLSF : public VmaBlockMetadata { - VMA_CLASS_NO_COPY(VmaBlockMetadata_TLSF) + VMA_CLASS_NO_COPY_NO_MOVE(VmaBlockMetadata_TLSF) public: VmaBlockMetadata_TLSF(const VkAllocationCallbacks* pAllocationCallbacks, VkDeviceSize bufferImageGranularity, bool isVirtual); @@ -10070,7 +10092,7 @@ void VmaBlockMetadata_TLSF::Init(VkDeviceSize size) else m_ListsCount += 4; - m_MemoryClasses = memoryClass + 2; + m_MemoryClasses = memoryClass + uint8_t(2); memset(m_InnerIsFreeBitmap, 0, MAX_MEMORY_CLASSES * sizeof(uint32_t)); m_FreeList = vma_new_array(GetAllocationCallbacks(), Block*, m_ListsCount); @@ -10263,7 +10285,7 @@ bool VmaBlockMetadata_TLSF::CreateAllocationRequest( // Round up to the next block VkDeviceSize sizeForNextList = allocSize; - VkDeviceSize smallSizeStep = SMALL_BUFFER_SIZE / (IsVirtual() ? 1 << SECOND_LEVEL_INDEX : 4); + VkDeviceSize smallSizeStep = VkDeviceSize(SMALL_BUFFER_SIZE / (IsVirtual() ? 1 << SECOND_LEVEL_INDEX : 4)); if (allocSize > SMALL_BUFFER_SIZE) { sizeForNextList += (1ULL << (VMA_BITSCAN_MSB(allocSize) - SECOND_LEVEL_INDEX)); @@ -10672,7 +10694,7 @@ void VmaBlockMetadata_TLSF::DebugLogAllAllocations() const uint8_t VmaBlockMetadata_TLSF::SizeToMemoryClass(VkDeviceSize size) const { if (size > SMALL_BUFFER_SIZE) - return VMA_BITSCAN_MSB(size) - MEMORY_CLASS_SHIFT; + return uint8_t(VMA_BITSCAN_MSB(size) - MEMORY_CLASS_SHIFT); return 0; } @@ -10847,7 +10869,7 @@ Synchronized internally with a mutex. class VmaBlockVector { friend struct VmaDefragmentationContext_T; - VMA_CLASS_NO_COPY(VmaBlockVector) + VMA_CLASS_NO_COPY_NO_MOVE(VmaBlockVector) public: VmaBlockVector( VmaAllocator hAllocator, @@ -10966,7 +10988,7 @@ private: #ifndef _VMA_DEFRAGMENTATION_CONTEXT struct VmaDefragmentationContext_T { - VMA_CLASS_NO_COPY(VmaDefragmentationContext_T) + VMA_CLASS_NO_COPY_NO_MOVE(VmaDefragmentationContext_T) public: VmaDefragmentationContext_T( VmaAllocator hAllocator, @@ -11053,7 +11075,7 @@ private: struct VmaPool_T { friend struct VmaPoolListItemTraits; - VMA_CLASS_NO_COPY(VmaPool_T) + VMA_CLASS_NO_COPY_NO_MOVE(VmaPool_T) public: VmaBlockVector m_BlockVector; VmaDedicatedAllocationList m_DedicatedAllocations; @@ -11095,6 +11117,9 @@ struct VmaPoolListItemTraits #ifndef _VMA_CURRENT_BUDGET_DATA struct VmaCurrentBudgetData { + VMA_CLASS_NO_COPY_NO_MOVE(VmaCurrentBudgetData) +public: + VMA_ATOMIC_UINT32 m_BlockCount[VK_MAX_MEMORY_HEAPS]; VMA_ATOMIC_UINT32 m_AllocationCount[VK_MAX_MEMORY_HEAPS]; VMA_ATOMIC_UINT64 m_BlockBytes[VK_MAX_MEMORY_HEAPS]; @@ -11163,7 +11188,7 @@ Thread-safe wrapper over VmaPoolAllocator free list, for allocation of VmaAlloca */ class VmaAllocationObjectAllocator { - VMA_CLASS_NO_COPY(VmaAllocationObjectAllocator) + VMA_CLASS_NO_COPY_NO_MOVE(VmaAllocationObjectAllocator) public: VmaAllocationObjectAllocator(const VkAllocationCallbacks* pAllocationCallbacks) : m_Allocator(pAllocationCallbacks, 1024) {} @@ -11193,7 +11218,7 @@ void VmaAllocationObjectAllocator::Free(VmaAllocation hAlloc) #ifndef _VMA_VIRTUAL_BLOCK_T struct VmaVirtualBlock_T { - VMA_CLASS_NO_COPY(VmaVirtualBlock_T) + VMA_CLASS_NO_COPY_NO_MOVE(VmaVirtualBlock_T) public: const bool m_AllocationCallbacksSpecified; const VkAllocationCallbacks m_AllocationCallbacks; @@ -11333,7 +11358,7 @@ void VmaVirtualBlock_T::BuildStatsString(bool detailedMap, VmaStringBuilder& sb) // Main allocator object. struct VmaAllocator_T { - VMA_CLASS_NO_COPY(VmaAllocator_T) + VMA_CLASS_NO_COPY_NO_MOVE(VmaAllocator_T) public: bool m_UseMutex; uint32_t m_VulkanApiVersion; @@ -13197,29 +13222,24 @@ VkResult VmaDefragmentationContext_T::DefragmentPassEnd(VmaDefragmentationPassMo m_PassStats.bytesFreed += freedBlockSize; } - switch (m_Algorithm) + if(m_Algorithm == VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT && + m_AlgorithmState != VMA_NULL) { - case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT: - { - if (m_AlgorithmState != VMA_NULL) + // Avoid unnecessary tries to allocate when new free block is available + StateExtensive& state = reinterpret_cast(m_AlgorithmState)[vectorIndex]; + if (state.firstFreeBlock != SIZE_MAX) { - // Avoid unnecessary tries to allocate when new free block is available - StateExtensive& state = reinterpret_cast(m_AlgorithmState)[vectorIndex]; - if (state.firstFreeBlock != SIZE_MAX) + const size_t diff = prevCount - currentCount; + if (state.firstFreeBlock >= diff) { - const size_t diff = prevCount - currentCount; - if (state.firstFreeBlock >= diff) - { - state.firstFreeBlock -= diff; - if (state.firstFreeBlock != 0) - state.firstFreeBlock -= vector->GetBlock(state.firstFreeBlock - 1)->m_pMetadata->IsEmpty(); - } - else - state.firstFreeBlock = 0; + state.firstFreeBlock -= diff; + if (state.firstFreeBlock != 0) + state.firstFreeBlock -= vector->GetBlock(state.firstFreeBlock - 1)->m_pMetadata->IsEmpty(); } + else + state.firstFreeBlock = 0; } } - } } moveInfo.moveCount = 0; moveInfo.pMoves = VMA_NULL; @@ -13351,6 +13371,8 @@ VmaDefragmentationContext_T::CounterStatus VmaDefragmentationContext_T::CheckCou else return CounterStatus::End; } + else + m_IgnoredAllocs = 0; return CounterStatus::Pass; } @@ -13360,8 +13382,8 @@ bool VmaDefragmentationContext_T::IncrementCounters(VkDeviceSize bytes) // Early return when max found if (++m_PassStats.allocationsMoved >= m_MaxPassAllocations || m_PassStats.bytesMoved >= m_MaxPassBytes) { - VMA_ASSERT(m_PassStats.allocationsMoved == m_MaxPassAllocations || - m_PassStats.bytesMoved == m_MaxPassBytes && "Exceeded maximal pass threshold!"); + VMA_ASSERT((m_PassStats.allocationsMoved == m_MaxPassAllocations || + m_PassStats.bytesMoved == m_MaxPassBytes) && "Exceeded maximal pass threshold!"); return true; } return false; @@ -13710,7 +13732,7 @@ bool VmaDefragmentationContext_T::ComputeDefragmentation_Extensive(VmaBlockVecto { // Full clear performed already if (prevMoveCount != m_Moves.size() && freeMetadata->GetNextAllocation(handle) == VK_NULL_HANDLE) - reinterpret_cast(m_AlgorithmState)[index] = last; + vectorState.firstFreeBlock = last; return true; } } @@ -13780,6 +13802,7 @@ bool VmaDefragmentationContext_T::ComputeDefragmentation_Extensive(VmaBlockVecto } else break; + VMA_FALLTHROUGH; // Fallthrough } case StateExtensive::Operation::MoveBuffers: { @@ -13804,6 +13827,7 @@ bool VmaDefragmentationContext_T::ComputeDefragmentation_Extensive(VmaBlockVecto } else break; + VMA_FALLTHROUGH; // Fallthrough } case StateExtensive::Operation::MoveAll: { @@ -14201,6 +14225,12 @@ void VmaAllocator_T::ImportVulkanFunctions_Static() m_VulkanFunctions.vkGetImageMemoryRequirements2KHR = (PFN_vkGetImageMemoryRequirements2)vkGetImageMemoryRequirements2; m_VulkanFunctions.vkBindBufferMemory2KHR = (PFN_vkBindBufferMemory2)vkBindBufferMemory2; m_VulkanFunctions.vkBindImageMemory2KHR = (PFN_vkBindImageMemory2)vkBindImageMemory2; + } +#endif + +#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000 + if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + { m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR = (PFN_vkGetPhysicalDeviceMemoryProperties2)vkGetPhysicalDeviceMemoryProperties2; } #endif @@ -14253,7 +14283,7 @@ void VmaAllocator_T::ImportVulkanFunctions_Custom(const VmaVulkanFunctions* pVul VMA_COPY_IF_NOT_NULL(vkBindImageMemory2KHR); #endif -#if VMA_MEMORY_BUDGET +#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000 VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceMemoryProperties2KHR); #endif @@ -14308,8 +14338,18 @@ void VmaAllocator_T::ImportVulkanFunctions_Dynamic() VMA_FETCH_DEVICE_FUNC(vkGetImageMemoryRequirements2KHR, PFN_vkGetImageMemoryRequirements2, "vkGetImageMemoryRequirements2"); VMA_FETCH_DEVICE_FUNC(vkBindBufferMemory2KHR, PFN_vkBindBufferMemory2, "vkBindBufferMemory2"); VMA_FETCH_DEVICE_FUNC(vkBindImageMemory2KHR, PFN_vkBindImageMemory2, "vkBindImageMemory2"); + } +#endif + +#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000 + if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + { VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2, "vkGetPhysicalDeviceMemoryProperties2"); } + else if(m_UseExtMemoryBudget) + { + VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2, "vkGetPhysicalDeviceMemoryProperties2KHR"); + } #endif #if VMA_DEDICATED_ALLOCATION @@ -14328,8 +14368,12 @@ void VmaAllocator_T::ImportVulkanFunctions_Dynamic() } #endif // #if VMA_BIND_MEMORY2 -#if VMA_MEMORY_BUDGET - if(m_UseExtMemoryBudget) +#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000 + if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + { + VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2"); + } + else if(m_UseExtMemoryBudget) { VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2KHR"); } @@ -15531,6 +15575,7 @@ VkResult VmaAllocator_T::Map(VmaAllocation hAllocation, void** ppData) } return res; } + VMA_FALLTHROUGH; // Fallthrough case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED: return hAllocation->DedicatedAllocMap(this, ppData); default: @@ -18165,6 +18210,12 @@ vkDestroyImage(allocator, img2, nullptr); vkDestroyImage(allocator, img1, nullptr); \endcode +VMA also provides convenience functions that create a buffer or image and bind it to memory +represented by an existing #VmaAllocation: +vmaCreateAliasingBuffer(), vmaCreateAliasingBuffer2(), +vmaCreateAliasingImage(), vmaCreateAliasingImage2(). +Versions with "2" offer additional parameter `allocationLocalOffset`. + Remember that using resources that alias in memory requires proper synchronization. You need to issue a memory barrier to make sure commands that use `img1` and `img2` don't overlap on GPU timeline. @@ -19162,6 +19213,7 @@ else // [Executed in runtime]: memcpy(stagingAllocInfo.pMappedData, myData, myDataSize); + vmaFlushAllocation(allocator, stagingAlloc, 0, VK_WHOLE_SIZE); //vkCmdPipelineBarrier: VK_ACCESS_HOST_WRITE_BIT --> VK_ACCESS_TRANSFER_READ_BIT VkBufferCopy bufCopy = { 0, // srcOffset diff --git a/WickedEngine/Utility/volk.c b/WickedEngine/Utility/volk.c index d72e38c3a..d02e3afa3 100644 --- a/WickedEngine/Utility/volk.c +++ b/WickedEngine/Utility/volk.c @@ -596,75 +596,25 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkGetImageViewOpaqueCaptureDescriptorDataEXT = (PFN_vkGetImageViewOpaqueCaptureDescriptorDataEXT)load(context, "vkGetImageViewOpaqueCaptureDescriptorDataEXT"); vkGetSamplerOpaqueCaptureDescriptorDataEXT = (PFN_vkGetSamplerOpaqueCaptureDescriptorDataEXT)load(context, "vkGetSamplerOpaqueCaptureDescriptorDataEXT"); #endif /* defined(VK_EXT_descriptor_buffer) */ -#if defined(VK_EXT_descriptor_buffer) && defined(VK_KHR_acceleration_structure) && defined(VK_NV_ray_tracing) +#if defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT = (PFN_vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT)load(context, "vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT"); -#endif /* defined(VK_EXT_descriptor_buffer) && defined(VK_KHR_acceleration_structure) && defined(VK_NV_ray_tracing) */ +#endif /* defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) */ #if defined(VK_EXT_device_fault) vkGetDeviceFaultInfoEXT = (PFN_vkGetDeviceFaultInfoEXT)load(context, "vkGetDeviceFaultInfoEXT"); #endif /* defined(VK_EXT_device_fault) */ #if defined(VK_EXT_discard_rectangles) vkCmdSetDiscardRectangleEXT = (PFN_vkCmdSetDiscardRectangleEXT)load(context, "vkCmdSetDiscardRectangleEXT"); #endif /* defined(VK_EXT_discard_rectangles) */ +#if defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 + vkCmdSetDiscardRectangleEnableEXT = (PFN_vkCmdSetDiscardRectangleEnableEXT)load(context, "vkCmdSetDiscardRectangleEnableEXT"); + vkCmdSetDiscardRectangleModeEXT = (PFN_vkCmdSetDiscardRectangleModeEXT)load(context, "vkCmdSetDiscardRectangleModeEXT"); +#endif /* defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 */ #if defined(VK_EXT_display_control) vkDisplayPowerControlEXT = (PFN_vkDisplayPowerControlEXT)load(context, "vkDisplayPowerControlEXT"); vkGetSwapchainCounterEXT = (PFN_vkGetSwapchainCounterEXT)load(context, "vkGetSwapchainCounterEXT"); vkRegisterDeviceEventEXT = (PFN_vkRegisterDeviceEventEXT)load(context, "vkRegisterDeviceEventEXT"); vkRegisterDisplayEventEXT = (PFN_vkRegisterDisplayEventEXT)load(context, "vkRegisterDisplayEventEXT"); #endif /* defined(VK_EXT_display_control) */ -#if defined(VK_EXT_extended_dynamic_state) - vkCmdBindVertexBuffers2EXT = (PFN_vkCmdBindVertexBuffers2EXT)load(context, "vkCmdBindVertexBuffers2EXT"); - vkCmdSetCullModeEXT = (PFN_vkCmdSetCullModeEXT)load(context, "vkCmdSetCullModeEXT"); - vkCmdSetDepthBoundsTestEnableEXT = (PFN_vkCmdSetDepthBoundsTestEnableEXT)load(context, "vkCmdSetDepthBoundsTestEnableEXT"); - vkCmdSetDepthCompareOpEXT = (PFN_vkCmdSetDepthCompareOpEXT)load(context, "vkCmdSetDepthCompareOpEXT"); - vkCmdSetDepthTestEnableEXT = (PFN_vkCmdSetDepthTestEnableEXT)load(context, "vkCmdSetDepthTestEnableEXT"); - vkCmdSetDepthWriteEnableEXT = (PFN_vkCmdSetDepthWriteEnableEXT)load(context, "vkCmdSetDepthWriteEnableEXT"); - vkCmdSetFrontFaceEXT = (PFN_vkCmdSetFrontFaceEXT)load(context, "vkCmdSetFrontFaceEXT"); - vkCmdSetPrimitiveTopologyEXT = (PFN_vkCmdSetPrimitiveTopologyEXT)load(context, "vkCmdSetPrimitiveTopologyEXT"); - vkCmdSetScissorWithCountEXT = (PFN_vkCmdSetScissorWithCountEXT)load(context, "vkCmdSetScissorWithCountEXT"); - vkCmdSetStencilOpEXT = (PFN_vkCmdSetStencilOpEXT)load(context, "vkCmdSetStencilOpEXT"); - vkCmdSetStencilTestEnableEXT = (PFN_vkCmdSetStencilTestEnableEXT)load(context, "vkCmdSetStencilTestEnableEXT"); - vkCmdSetViewportWithCountEXT = (PFN_vkCmdSetViewportWithCountEXT)load(context, "vkCmdSetViewportWithCountEXT"); -#endif /* defined(VK_EXT_extended_dynamic_state) */ -#if defined(VK_EXT_extended_dynamic_state2) - vkCmdSetDepthBiasEnableEXT = (PFN_vkCmdSetDepthBiasEnableEXT)load(context, "vkCmdSetDepthBiasEnableEXT"); - vkCmdSetLogicOpEXT = (PFN_vkCmdSetLogicOpEXT)load(context, "vkCmdSetLogicOpEXT"); - vkCmdSetPatchControlPointsEXT = (PFN_vkCmdSetPatchControlPointsEXT)load(context, "vkCmdSetPatchControlPointsEXT"); - vkCmdSetPrimitiveRestartEnableEXT = (PFN_vkCmdSetPrimitiveRestartEnableEXT)load(context, "vkCmdSetPrimitiveRestartEnableEXT"); - vkCmdSetRasterizerDiscardEnableEXT = (PFN_vkCmdSetRasterizerDiscardEnableEXT)load(context, "vkCmdSetRasterizerDiscardEnableEXT"); -#endif /* defined(VK_EXT_extended_dynamic_state2) */ -#if defined(VK_EXT_extended_dynamic_state3) - vkCmdSetAlphaToCoverageEnableEXT = (PFN_vkCmdSetAlphaToCoverageEnableEXT)load(context, "vkCmdSetAlphaToCoverageEnableEXT"); - vkCmdSetAlphaToOneEnableEXT = (PFN_vkCmdSetAlphaToOneEnableEXT)load(context, "vkCmdSetAlphaToOneEnableEXT"); - vkCmdSetColorBlendAdvancedEXT = (PFN_vkCmdSetColorBlendAdvancedEXT)load(context, "vkCmdSetColorBlendAdvancedEXT"); - vkCmdSetColorBlendEnableEXT = (PFN_vkCmdSetColorBlendEnableEXT)load(context, "vkCmdSetColorBlendEnableEXT"); - vkCmdSetColorBlendEquationEXT = (PFN_vkCmdSetColorBlendEquationEXT)load(context, "vkCmdSetColorBlendEquationEXT"); - vkCmdSetColorWriteMaskEXT = (PFN_vkCmdSetColorWriteMaskEXT)load(context, "vkCmdSetColorWriteMaskEXT"); - vkCmdSetConservativeRasterizationModeEXT = (PFN_vkCmdSetConservativeRasterizationModeEXT)load(context, "vkCmdSetConservativeRasterizationModeEXT"); - vkCmdSetCoverageModulationModeNV = (PFN_vkCmdSetCoverageModulationModeNV)load(context, "vkCmdSetCoverageModulationModeNV"); - vkCmdSetCoverageModulationTableEnableNV = (PFN_vkCmdSetCoverageModulationTableEnableNV)load(context, "vkCmdSetCoverageModulationTableEnableNV"); - vkCmdSetCoverageModulationTableNV = (PFN_vkCmdSetCoverageModulationTableNV)load(context, "vkCmdSetCoverageModulationTableNV"); - vkCmdSetCoverageReductionModeNV = (PFN_vkCmdSetCoverageReductionModeNV)load(context, "vkCmdSetCoverageReductionModeNV"); - vkCmdSetCoverageToColorEnableNV = (PFN_vkCmdSetCoverageToColorEnableNV)load(context, "vkCmdSetCoverageToColorEnableNV"); - vkCmdSetCoverageToColorLocationNV = (PFN_vkCmdSetCoverageToColorLocationNV)load(context, "vkCmdSetCoverageToColorLocationNV"); - vkCmdSetDepthClampEnableEXT = (PFN_vkCmdSetDepthClampEnableEXT)load(context, "vkCmdSetDepthClampEnableEXT"); - vkCmdSetDepthClipEnableEXT = (PFN_vkCmdSetDepthClipEnableEXT)load(context, "vkCmdSetDepthClipEnableEXT"); - vkCmdSetDepthClipNegativeOneToOneEXT = (PFN_vkCmdSetDepthClipNegativeOneToOneEXT)load(context, "vkCmdSetDepthClipNegativeOneToOneEXT"); - vkCmdSetExtraPrimitiveOverestimationSizeEXT = (PFN_vkCmdSetExtraPrimitiveOverestimationSizeEXT)load(context, "vkCmdSetExtraPrimitiveOverestimationSizeEXT"); - vkCmdSetLineRasterizationModeEXT = (PFN_vkCmdSetLineRasterizationModeEXT)load(context, "vkCmdSetLineRasterizationModeEXT"); - vkCmdSetLineStippleEnableEXT = (PFN_vkCmdSetLineStippleEnableEXT)load(context, "vkCmdSetLineStippleEnableEXT"); - vkCmdSetLogicOpEnableEXT = (PFN_vkCmdSetLogicOpEnableEXT)load(context, "vkCmdSetLogicOpEnableEXT"); - vkCmdSetPolygonModeEXT = (PFN_vkCmdSetPolygonModeEXT)load(context, "vkCmdSetPolygonModeEXT"); - vkCmdSetProvokingVertexModeEXT = (PFN_vkCmdSetProvokingVertexModeEXT)load(context, "vkCmdSetProvokingVertexModeEXT"); - vkCmdSetRasterizationSamplesEXT = (PFN_vkCmdSetRasterizationSamplesEXT)load(context, "vkCmdSetRasterizationSamplesEXT"); - vkCmdSetRasterizationStreamEXT = (PFN_vkCmdSetRasterizationStreamEXT)load(context, "vkCmdSetRasterizationStreamEXT"); - vkCmdSetRepresentativeFragmentTestEnableNV = (PFN_vkCmdSetRepresentativeFragmentTestEnableNV)load(context, "vkCmdSetRepresentativeFragmentTestEnableNV"); - vkCmdSetSampleLocationsEnableEXT = (PFN_vkCmdSetSampleLocationsEnableEXT)load(context, "vkCmdSetSampleLocationsEnableEXT"); - vkCmdSetSampleMaskEXT = (PFN_vkCmdSetSampleMaskEXT)load(context, "vkCmdSetSampleMaskEXT"); - vkCmdSetShadingRateImageEnableNV = (PFN_vkCmdSetShadingRateImageEnableNV)load(context, "vkCmdSetShadingRateImageEnableNV"); - vkCmdSetTessellationDomainOriginEXT = (PFN_vkCmdSetTessellationDomainOriginEXT)load(context, "vkCmdSetTessellationDomainOriginEXT"); - vkCmdSetViewportSwizzleNV = (PFN_vkCmdSetViewportSwizzleNV)load(context, "vkCmdSetViewportSwizzleNV"); - vkCmdSetViewportWScalingEnableNV = (PFN_vkCmdSetViewportWScalingEnableNV)load(context, "vkCmdSetViewportWScalingEnableNV"); -#endif /* defined(VK_EXT_extended_dynamic_state3) */ #if defined(VK_EXT_external_memory_host) vkGetMemoryHostPointerPropertiesEXT = (PFN_vkGetMemoryHostPointerPropertiesEXT)load(context, "vkGetMemoryHostPointerPropertiesEXT"); #endif /* defined(VK_EXT_external_memory_host) */ @@ -734,6 +684,12 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkGetShaderModuleCreateInfoIdentifierEXT = (PFN_vkGetShaderModuleCreateInfoIdentifierEXT)load(context, "vkGetShaderModuleCreateInfoIdentifierEXT"); vkGetShaderModuleIdentifierEXT = (PFN_vkGetShaderModuleIdentifierEXT)load(context, "vkGetShaderModuleIdentifierEXT"); #endif /* defined(VK_EXT_shader_module_identifier) */ +#if defined(VK_EXT_shader_object) + vkCmdBindShadersEXT = (PFN_vkCmdBindShadersEXT)load(context, "vkCmdBindShadersEXT"); + vkCreateShadersEXT = (PFN_vkCreateShadersEXT)load(context, "vkCreateShadersEXT"); + vkDestroyShaderEXT = (PFN_vkDestroyShaderEXT)load(context, "vkDestroyShaderEXT"); + vkGetShaderBinaryDataEXT = (PFN_vkGetShaderBinaryDataEXT)load(context, "vkGetShaderBinaryDataEXT"); +#endif /* defined(VK_EXT_shader_object) */ #if defined(VK_EXT_swapchain_maintenance1) vkReleaseSwapchainImagesEXT = (PFN_vkReleaseSwapchainImagesEXT)load(context, "vkReleaseSwapchainImagesEXT"); #endif /* defined(VK_EXT_swapchain_maintenance1) */ @@ -751,9 +707,6 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkGetValidationCacheDataEXT = (PFN_vkGetValidationCacheDataEXT)load(context, "vkGetValidationCacheDataEXT"); vkMergeValidationCachesEXT = (PFN_vkMergeValidationCachesEXT)load(context, "vkMergeValidationCachesEXT"); #endif /* defined(VK_EXT_validation_cache) */ -#if defined(VK_EXT_vertex_input_dynamic_state) - vkCmdSetVertexInputEXT = (PFN_vkCmdSetVertexInputEXT)load(context, "vkCmdSetVertexInputEXT"); -#endif /* defined(VK_EXT_vertex_input_dynamic_state) */ #if defined(VK_FUCHSIA_buffer_collection) vkCreateBufferCollectionFUCHSIA = (PFN_vkCreateBufferCollectionFUCHSIA)load(context, "vkCreateBufferCollectionFUCHSIA"); vkDestroyBufferCollectionFUCHSIA = (PFN_vkDestroyBufferCollectionFUCHSIA)load(context, "vkDestroyBufferCollectionFUCHSIA"); @@ -773,6 +726,10 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkGetPastPresentationTimingGOOGLE = (PFN_vkGetPastPresentationTimingGOOGLE)load(context, "vkGetPastPresentationTimingGOOGLE"); vkGetRefreshCycleDurationGOOGLE = (PFN_vkGetRefreshCycleDurationGOOGLE)load(context, "vkGetRefreshCycleDurationGOOGLE"); #endif /* defined(VK_GOOGLE_display_timing) */ +#if defined(VK_HUAWEI_cluster_culling_shader) + vkCmdDrawClusterHUAWEI = (PFN_vkCmdDrawClusterHUAWEI)load(context, "vkCmdDrawClusterHUAWEI"); + vkCmdDrawClusterIndirectHUAWEI = (PFN_vkCmdDrawClusterIndirectHUAWEI)load(context, "vkCmdDrawClusterIndirectHUAWEI"); +#endif /* defined(VK_HUAWEI_cluster_culling_shader) */ #if defined(VK_HUAWEI_invocation_mask) vkCmdBindInvocationMaskHUAWEI = (PFN_vkCmdBindInvocationMaskHUAWEI)load(context, "vkCmdBindInvocationMaskHUAWEI"); #endif /* defined(VK_HUAWEI_invocation_mask) */ @@ -903,6 +860,10 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkGetDeviceImageMemoryRequirementsKHR = (PFN_vkGetDeviceImageMemoryRequirementsKHR)load(context, "vkGetDeviceImageMemoryRequirementsKHR"); vkGetDeviceImageSparseMemoryRequirementsKHR = (PFN_vkGetDeviceImageSparseMemoryRequirementsKHR)load(context, "vkGetDeviceImageSparseMemoryRequirementsKHR"); #endif /* defined(VK_KHR_maintenance4) */ +#if defined(VK_KHR_map_memory2) + vkMapMemory2KHR = (PFN_vkMapMemory2KHR)load(context, "vkMapMemory2KHR"); + vkUnmapMemory2KHR = (PFN_vkUnmapMemory2KHR)load(context, "vkUnmapMemory2KHR"); +#endif /* defined(VK_KHR_map_memory2) */ #if defined(VK_KHR_performance_query) vkAcquireProfilingLockKHR = (PFN_vkAcquireProfilingLockKHR)load(context, "vkAcquireProfilingLockKHR"); vkReleaseProfilingLockKHR = (PFN_vkReleaseProfilingLockKHR)load(context, "vkReleaseProfilingLockKHR"); @@ -1049,6 +1010,9 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkGetAccelerationStructureMemoryRequirementsNV = (PFN_vkGetAccelerationStructureMemoryRequirementsNV)load(context, "vkGetAccelerationStructureMemoryRequirementsNV"); vkGetRayTracingShaderGroupHandlesNV = (PFN_vkGetRayTracingShaderGroupHandlesNV)load(context, "vkGetRayTracingShaderGroupHandlesNV"); #endif /* defined(VK_NV_ray_tracing) */ +#if defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 + vkCmdSetExclusiveScissorEnableNV = (PFN_vkCmdSetExclusiveScissorEnableNV)load(context, "vkCmdSetExclusiveScissorEnableNV"); +#endif /* defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 */ #if defined(VK_NV_scissor_exclusive) vkCmdSetExclusiveScissorNV = (PFN_vkCmdSetExclusiveScissorNV)load(context, "vkCmdSetExclusiveScissorNV"); #endif /* defined(VK_NV_scissor_exclusive) */ @@ -1065,9 +1029,66 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkGetDescriptorSetHostMappingVALVE = (PFN_vkGetDescriptorSetHostMappingVALVE)load(context, "vkGetDescriptorSetHostMappingVALVE"); vkGetDescriptorSetLayoutHostMappingInfoVALVE = (PFN_vkGetDescriptorSetLayoutHostMappingInfoVALVE)load(context, "vkGetDescriptorSetLayoutHostMappingInfoVALVE"); #endif /* defined(VK_VALVE_descriptor_set_host_mapping) */ +#if (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) + vkCmdBindVertexBuffers2EXT = (PFN_vkCmdBindVertexBuffers2EXT)load(context, "vkCmdBindVertexBuffers2EXT"); + vkCmdSetCullModeEXT = (PFN_vkCmdSetCullModeEXT)load(context, "vkCmdSetCullModeEXT"); + vkCmdSetDepthBoundsTestEnableEXT = (PFN_vkCmdSetDepthBoundsTestEnableEXT)load(context, "vkCmdSetDepthBoundsTestEnableEXT"); + vkCmdSetDepthCompareOpEXT = (PFN_vkCmdSetDepthCompareOpEXT)load(context, "vkCmdSetDepthCompareOpEXT"); + vkCmdSetDepthTestEnableEXT = (PFN_vkCmdSetDepthTestEnableEXT)load(context, "vkCmdSetDepthTestEnableEXT"); + vkCmdSetDepthWriteEnableEXT = (PFN_vkCmdSetDepthWriteEnableEXT)load(context, "vkCmdSetDepthWriteEnableEXT"); + vkCmdSetFrontFaceEXT = (PFN_vkCmdSetFrontFaceEXT)load(context, "vkCmdSetFrontFaceEXT"); + vkCmdSetPrimitiveTopologyEXT = (PFN_vkCmdSetPrimitiveTopologyEXT)load(context, "vkCmdSetPrimitiveTopologyEXT"); + vkCmdSetScissorWithCountEXT = (PFN_vkCmdSetScissorWithCountEXT)load(context, "vkCmdSetScissorWithCountEXT"); + vkCmdSetStencilOpEXT = (PFN_vkCmdSetStencilOpEXT)load(context, "vkCmdSetStencilOpEXT"); + vkCmdSetStencilTestEnableEXT = (PFN_vkCmdSetStencilTestEnableEXT)load(context, "vkCmdSetStencilTestEnableEXT"); + vkCmdSetViewportWithCountEXT = (PFN_vkCmdSetViewportWithCountEXT)load(context, "vkCmdSetViewportWithCountEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) + vkCmdSetDepthBiasEnableEXT = (PFN_vkCmdSetDepthBiasEnableEXT)load(context, "vkCmdSetDepthBiasEnableEXT"); + vkCmdSetLogicOpEXT = (PFN_vkCmdSetLogicOpEXT)load(context, "vkCmdSetLogicOpEXT"); + vkCmdSetPatchControlPointsEXT = (PFN_vkCmdSetPatchControlPointsEXT)load(context, "vkCmdSetPatchControlPointsEXT"); + vkCmdSetPrimitiveRestartEnableEXT = (PFN_vkCmdSetPrimitiveRestartEnableEXT)load(context, "vkCmdSetPrimitiveRestartEnableEXT"); + vkCmdSetRasterizerDiscardEnableEXT = (PFN_vkCmdSetRasterizerDiscardEnableEXT)load(context, "vkCmdSetRasterizerDiscardEnableEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) + vkCmdSetAlphaToCoverageEnableEXT = (PFN_vkCmdSetAlphaToCoverageEnableEXT)load(context, "vkCmdSetAlphaToCoverageEnableEXT"); + vkCmdSetAlphaToOneEnableEXT = (PFN_vkCmdSetAlphaToOneEnableEXT)load(context, "vkCmdSetAlphaToOneEnableEXT"); + vkCmdSetColorBlendAdvancedEXT = (PFN_vkCmdSetColorBlendAdvancedEXT)load(context, "vkCmdSetColorBlendAdvancedEXT"); + vkCmdSetColorBlendEnableEXT = (PFN_vkCmdSetColorBlendEnableEXT)load(context, "vkCmdSetColorBlendEnableEXT"); + vkCmdSetColorBlendEquationEXT = (PFN_vkCmdSetColorBlendEquationEXT)load(context, "vkCmdSetColorBlendEquationEXT"); + vkCmdSetColorWriteMaskEXT = (PFN_vkCmdSetColorWriteMaskEXT)load(context, "vkCmdSetColorWriteMaskEXT"); + vkCmdSetConservativeRasterizationModeEXT = (PFN_vkCmdSetConservativeRasterizationModeEXT)load(context, "vkCmdSetConservativeRasterizationModeEXT"); + vkCmdSetCoverageModulationModeNV = (PFN_vkCmdSetCoverageModulationModeNV)load(context, "vkCmdSetCoverageModulationModeNV"); + vkCmdSetCoverageModulationTableEnableNV = (PFN_vkCmdSetCoverageModulationTableEnableNV)load(context, "vkCmdSetCoverageModulationTableEnableNV"); + vkCmdSetCoverageModulationTableNV = (PFN_vkCmdSetCoverageModulationTableNV)load(context, "vkCmdSetCoverageModulationTableNV"); + vkCmdSetCoverageReductionModeNV = (PFN_vkCmdSetCoverageReductionModeNV)load(context, "vkCmdSetCoverageReductionModeNV"); + vkCmdSetCoverageToColorEnableNV = (PFN_vkCmdSetCoverageToColorEnableNV)load(context, "vkCmdSetCoverageToColorEnableNV"); + vkCmdSetCoverageToColorLocationNV = (PFN_vkCmdSetCoverageToColorLocationNV)load(context, "vkCmdSetCoverageToColorLocationNV"); + vkCmdSetDepthClampEnableEXT = (PFN_vkCmdSetDepthClampEnableEXT)load(context, "vkCmdSetDepthClampEnableEXT"); + vkCmdSetDepthClipEnableEXT = (PFN_vkCmdSetDepthClipEnableEXT)load(context, "vkCmdSetDepthClipEnableEXT"); + vkCmdSetDepthClipNegativeOneToOneEXT = (PFN_vkCmdSetDepthClipNegativeOneToOneEXT)load(context, "vkCmdSetDepthClipNegativeOneToOneEXT"); + vkCmdSetExtraPrimitiveOverestimationSizeEXT = (PFN_vkCmdSetExtraPrimitiveOverestimationSizeEXT)load(context, "vkCmdSetExtraPrimitiveOverestimationSizeEXT"); + vkCmdSetLineRasterizationModeEXT = (PFN_vkCmdSetLineRasterizationModeEXT)load(context, "vkCmdSetLineRasterizationModeEXT"); + vkCmdSetLineStippleEnableEXT = (PFN_vkCmdSetLineStippleEnableEXT)load(context, "vkCmdSetLineStippleEnableEXT"); + vkCmdSetLogicOpEnableEXT = (PFN_vkCmdSetLogicOpEnableEXT)load(context, "vkCmdSetLogicOpEnableEXT"); + vkCmdSetPolygonModeEXT = (PFN_vkCmdSetPolygonModeEXT)load(context, "vkCmdSetPolygonModeEXT"); + vkCmdSetProvokingVertexModeEXT = (PFN_vkCmdSetProvokingVertexModeEXT)load(context, "vkCmdSetProvokingVertexModeEXT"); + vkCmdSetRasterizationSamplesEXT = (PFN_vkCmdSetRasterizationSamplesEXT)load(context, "vkCmdSetRasterizationSamplesEXT"); + vkCmdSetRasterizationStreamEXT = (PFN_vkCmdSetRasterizationStreamEXT)load(context, "vkCmdSetRasterizationStreamEXT"); + vkCmdSetRepresentativeFragmentTestEnableNV = (PFN_vkCmdSetRepresentativeFragmentTestEnableNV)load(context, "vkCmdSetRepresentativeFragmentTestEnableNV"); + vkCmdSetSampleLocationsEnableEXT = (PFN_vkCmdSetSampleLocationsEnableEXT)load(context, "vkCmdSetSampleLocationsEnableEXT"); + vkCmdSetSampleMaskEXT = (PFN_vkCmdSetSampleMaskEXT)load(context, "vkCmdSetSampleMaskEXT"); + vkCmdSetShadingRateImageEnableNV = (PFN_vkCmdSetShadingRateImageEnableNV)load(context, "vkCmdSetShadingRateImageEnableNV"); + vkCmdSetTessellationDomainOriginEXT = (PFN_vkCmdSetTessellationDomainOriginEXT)load(context, "vkCmdSetTessellationDomainOriginEXT"); + vkCmdSetViewportSwizzleNV = (PFN_vkCmdSetViewportSwizzleNV)load(context, "vkCmdSetViewportSwizzleNV"); + vkCmdSetViewportWScalingEnableNV = (PFN_vkCmdSetViewportWScalingEnableNV)load(context, "vkCmdSetViewportWScalingEnableNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) */ #if (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) vkGetDeviceGroupSurfacePresentModes2EXT = (PFN_vkGetDeviceGroupSurfacePresentModes2EXT)load(context, "vkGetDeviceGroupSurfacePresentModes2EXT"); #endif /* (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) */ +#if (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) + vkCmdSetVertexInputEXT = (PFN_vkCmdSetVertexInputEXT)load(context, "vkCmdSetVertexInputEXT"); +#endif /* (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) */ #if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) vkCmdPushDescriptorSetWithTemplateKHR = (PFN_vkCmdPushDescriptorSetWithTemplateKHR)load(context, "vkCmdPushDescriptorSetWithTemplateKHR"); #endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) */ @@ -1326,75 +1347,25 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkGetImageViewOpaqueCaptureDescriptorDataEXT = (PFN_vkGetImageViewOpaqueCaptureDescriptorDataEXT)load(context, "vkGetImageViewOpaqueCaptureDescriptorDataEXT"); table->vkGetSamplerOpaqueCaptureDescriptorDataEXT = (PFN_vkGetSamplerOpaqueCaptureDescriptorDataEXT)load(context, "vkGetSamplerOpaqueCaptureDescriptorDataEXT"); #endif /* defined(VK_EXT_descriptor_buffer) */ -#if defined(VK_EXT_descriptor_buffer) && defined(VK_KHR_acceleration_structure) && defined(VK_NV_ray_tracing) +#if defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) table->vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT = (PFN_vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT)load(context, "vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT"); -#endif /* defined(VK_EXT_descriptor_buffer) && defined(VK_KHR_acceleration_structure) && defined(VK_NV_ray_tracing) */ +#endif /* defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) */ #if defined(VK_EXT_device_fault) table->vkGetDeviceFaultInfoEXT = (PFN_vkGetDeviceFaultInfoEXT)load(context, "vkGetDeviceFaultInfoEXT"); #endif /* defined(VK_EXT_device_fault) */ #if defined(VK_EXT_discard_rectangles) table->vkCmdSetDiscardRectangleEXT = (PFN_vkCmdSetDiscardRectangleEXT)load(context, "vkCmdSetDiscardRectangleEXT"); #endif /* defined(VK_EXT_discard_rectangles) */ +#if defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 + table->vkCmdSetDiscardRectangleEnableEXT = (PFN_vkCmdSetDiscardRectangleEnableEXT)load(context, "vkCmdSetDiscardRectangleEnableEXT"); + table->vkCmdSetDiscardRectangleModeEXT = (PFN_vkCmdSetDiscardRectangleModeEXT)load(context, "vkCmdSetDiscardRectangleModeEXT"); +#endif /* defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 */ #if defined(VK_EXT_display_control) table->vkDisplayPowerControlEXT = (PFN_vkDisplayPowerControlEXT)load(context, "vkDisplayPowerControlEXT"); table->vkGetSwapchainCounterEXT = (PFN_vkGetSwapchainCounterEXT)load(context, "vkGetSwapchainCounterEXT"); table->vkRegisterDeviceEventEXT = (PFN_vkRegisterDeviceEventEXT)load(context, "vkRegisterDeviceEventEXT"); table->vkRegisterDisplayEventEXT = (PFN_vkRegisterDisplayEventEXT)load(context, "vkRegisterDisplayEventEXT"); #endif /* defined(VK_EXT_display_control) */ -#if defined(VK_EXT_extended_dynamic_state) - table->vkCmdBindVertexBuffers2EXT = (PFN_vkCmdBindVertexBuffers2EXT)load(context, "vkCmdBindVertexBuffers2EXT"); - table->vkCmdSetCullModeEXT = (PFN_vkCmdSetCullModeEXT)load(context, "vkCmdSetCullModeEXT"); - table->vkCmdSetDepthBoundsTestEnableEXT = (PFN_vkCmdSetDepthBoundsTestEnableEXT)load(context, "vkCmdSetDepthBoundsTestEnableEXT"); - table->vkCmdSetDepthCompareOpEXT = (PFN_vkCmdSetDepthCompareOpEXT)load(context, "vkCmdSetDepthCompareOpEXT"); - table->vkCmdSetDepthTestEnableEXT = (PFN_vkCmdSetDepthTestEnableEXT)load(context, "vkCmdSetDepthTestEnableEXT"); - table->vkCmdSetDepthWriteEnableEXT = (PFN_vkCmdSetDepthWriteEnableEXT)load(context, "vkCmdSetDepthWriteEnableEXT"); - table->vkCmdSetFrontFaceEXT = (PFN_vkCmdSetFrontFaceEXT)load(context, "vkCmdSetFrontFaceEXT"); - table->vkCmdSetPrimitiveTopologyEXT = (PFN_vkCmdSetPrimitiveTopologyEXT)load(context, "vkCmdSetPrimitiveTopologyEXT"); - table->vkCmdSetScissorWithCountEXT = (PFN_vkCmdSetScissorWithCountEXT)load(context, "vkCmdSetScissorWithCountEXT"); - table->vkCmdSetStencilOpEXT = (PFN_vkCmdSetStencilOpEXT)load(context, "vkCmdSetStencilOpEXT"); - table->vkCmdSetStencilTestEnableEXT = (PFN_vkCmdSetStencilTestEnableEXT)load(context, "vkCmdSetStencilTestEnableEXT"); - table->vkCmdSetViewportWithCountEXT = (PFN_vkCmdSetViewportWithCountEXT)load(context, "vkCmdSetViewportWithCountEXT"); -#endif /* defined(VK_EXT_extended_dynamic_state) */ -#if defined(VK_EXT_extended_dynamic_state2) - table->vkCmdSetDepthBiasEnableEXT = (PFN_vkCmdSetDepthBiasEnableEXT)load(context, "vkCmdSetDepthBiasEnableEXT"); - table->vkCmdSetLogicOpEXT = (PFN_vkCmdSetLogicOpEXT)load(context, "vkCmdSetLogicOpEXT"); - table->vkCmdSetPatchControlPointsEXT = (PFN_vkCmdSetPatchControlPointsEXT)load(context, "vkCmdSetPatchControlPointsEXT"); - table->vkCmdSetPrimitiveRestartEnableEXT = (PFN_vkCmdSetPrimitiveRestartEnableEXT)load(context, "vkCmdSetPrimitiveRestartEnableEXT"); - table->vkCmdSetRasterizerDiscardEnableEXT = (PFN_vkCmdSetRasterizerDiscardEnableEXT)load(context, "vkCmdSetRasterizerDiscardEnableEXT"); -#endif /* defined(VK_EXT_extended_dynamic_state2) */ -#if defined(VK_EXT_extended_dynamic_state3) - table->vkCmdSetAlphaToCoverageEnableEXT = (PFN_vkCmdSetAlphaToCoverageEnableEXT)load(context, "vkCmdSetAlphaToCoverageEnableEXT"); - table->vkCmdSetAlphaToOneEnableEXT = (PFN_vkCmdSetAlphaToOneEnableEXT)load(context, "vkCmdSetAlphaToOneEnableEXT"); - table->vkCmdSetColorBlendAdvancedEXT = (PFN_vkCmdSetColorBlendAdvancedEXT)load(context, "vkCmdSetColorBlendAdvancedEXT"); - table->vkCmdSetColorBlendEnableEXT = (PFN_vkCmdSetColorBlendEnableEXT)load(context, "vkCmdSetColorBlendEnableEXT"); - table->vkCmdSetColorBlendEquationEXT = (PFN_vkCmdSetColorBlendEquationEXT)load(context, "vkCmdSetColorBlendEquationEXT"); - table->vkCmdSetColorWriteMaskEXT = (PFN_vkCmdSetColorWriteMaskEXT)load(context, "vkCmdSetColorWriteMaskEXT"); - table->vkCmdSetConservativeRasterizationModeEXT = (PFN_vkCmdSetConservativeRasterizationModeEXT)load(context, "vkCmdSetConservativeRasterizationModeEXT"); - table->vkCmdSetCoverageModulationModeNV = (PFN_vkCmdSetCoverageModulationModeNV)load(context, "vkCmdSetCoverageModulationModeNV"); - table->vkCmdSetCoverageModulationTableEnableNV = (PFN_vkCmdSetCoverageModulationTableEnableNV)load(context, "vkCmdSetCoverageModulationTableEnableNV"); - table->vkCmdSetCoverageModulationTableNV = (PFN_vkCmdSetCoverageModulationTableNV)load(context, "vkCmdSetCoverageModulationTableNV"); - table->vkCmdSetCoverageReductionModeNV = (PFN_vkCmdSetCoverageReductionModeNV)load(context, "vkCmdSetCoverageReductionModeNV"); - table->vkCmdSetCoverageToColorEnableNV = (PFN_vkCmdSetCoverageToColorEnableNV)load(context, "vkCmdSetCoverageToColorEnableNV"); - table->vkCmdSetCoverageToColorLocationNV = (PFN_vkCmdSetCoverageToColorLocationNV)load(context, "vkCmdSetCoverageToColorLocationNV"); - table->vkCmdSetDepthClampEnableEXT = (PFN_vkCmdSetDepthClampEnableEXT)load(context, "vkCmdSetDepthClampEnableEXT"); - table->vkCmdSetDepthClipEnableEXT = (PFN_vkCmdSetDepthClipEnableEXT)load(context, "vkCmdSetDepthClipEnableEXT"); - table->vkCmdSetDepthClipNegativeOneToOneEXT = (PFN_vkCmdSetDepthClipNegativeOneToOneEXT)load(context, "vkCmdSetDepthClipNegativeOneToOneEXT"); - table->vkCmdSetExtraPrimitiveOverestimationSizeEXT = (PFN_vkCmdSetExtraPrimitiveOverestimationSizeEXT)load(context, "vkCmdSetExtraPrimitiveOverestimationSizeEXT"); - table->vkCmdSetLineRasterizationModeEXT = (PFN_vkCmdSetLineRasterizationModeEXT)load(context, "vkCmdSetLineRasterizationModeEXT"); - table->vkCmdSetLineStippleEnableEXT = (PFN_vkCmdSetLineStippleEnableEXT)load(context, "vkCmdSetLineStippleEnableEXT"); - table->vkCmdSetLogicOpEnableEXT = (PFN_vkCmdSetLogicOpEnableEXT)load(context, "vkCmdSetLogicOpEnableEXT"); - table->vkCmdSetPolygonModeEXT = (PFN_vkCmdSetPolygonModeEXT)load(context, "vkCmdSetPolygonModeEXT"); - table->vkCmdSetProvokingVertexModeEXT = (PFN_vkCmdSetProvokingVertexModeEXT)load(context, "vkCmdSetProvokingVertexModeEXT"); - table->vkCmdSetRasterizationSamplesEXT = (PFN_vkCmdSetRasterizationSamplesEXT)load(context, "vkCmdSetRasterizationSamplesEXT"); - table->vkCmdSetRasterizationStreamEXT = (PFN_vkCmdSetRasterizationStreamEXT)load(context, "vkCmdSetRasterizationStreamEXT"); - table->vkCmdSetRepresentativeFragmentTestEnableNV = (PFN_vkCmdSetRepresentativeFragmentTestEnableNV)load(context, "vkCmdSetRepresentativeFragmentTestEnableNV"); - table->vkCmdSetSampleLocationsEnableEXT = (PFN_vkCmdSetSampleLocationsEnableEXT)load(context, "vkCmdSetSampleLocationsEnableEXT"); - table->vkCmdSetSampleMaskEXT = (PFN_vkCmdSetSampleMaskEXT)load(context, "vkCmdSetSampleMaskEXT"); - table->vkCmdSetShadingRateImageEnableNV = (PFN_vkCmdSetShadingRateImageEnableNV)load(context, "vkCmdSetShadingRateImageEnableNV"); - table->vkCmdSetTessellationDomainOriginEXT = (PFN_vkCmdSetTessellationDomainOriginEXT)load(context, "vkCmdSetTessellationDomainOriginEXT"); - table->vkCmdSetViewportSwizzleNV = (PFN_vkCmdSetViewportSwizzleNV)load(context, "vkCmdSetViewportSwizzleNV"); - table->vkCmdSetViewportWScalingEnableNV = (PFN_vkCmdSetViewportWScalingEnableNV)load(context, "vkCmdSetViewportWScalingEnableNV"); -#endif /* defined(VK_EXT_extended_dynamic_state3) */ #if defined(VK_EXT_external_memory_host) table->vkGetMemoryHostPointerPropertiesEXT = (PFN_vkGetMemoryHostPointerPropertiesEXT)load(context, "vkGetMemoryHostPointerPropertiesEXT"); #endif /* defined(VK_EXT_external_memory_host) */ @@ -1464,6 +1435,12 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkGetShaderModuleCreateInfoIdentifierEXT = (PFN_vkGetShaderModuleCreateInfoIdentifierEXT)load(context, "vkGetShaderModuleCreateInfoIdentifierEXT"); table->vkGetShaderModuleIdentifierEXT = (PFN_vkGetShaderModuleIdentifierEXT)load(context, "vkGetShaderModuleIdentifierEXT"); #endif /* defined(VK_EXT_shader_module_identifier) */ +#if defined(VK_EXT_shader_object) + table->vkCmdBindShadersEXT = (PFN_vkCmdBindShadersEXT)load(context, "vkCmdBindShadersEXT"); + table->vkCreateShadersEXT = (PFN_vkCreateShadersEXT)load(context, "vkCreateShadersEXT"); + table->vkDestroyShaderEXT = (PFN_vkDestroyShaderEXT)load(context, "vkDestroyShaderEXT"); + table->vkGetShaderBinaryDataEXT = (PFN_vkGetShaderBinaryDataEXT)load(context, "vkGetShaderBinaryDataEXT"); +#endif /* defined(VK_EXT_shader_object) */ #if defined(VK_EXT_swapchain_maintenance1) table->vkReleaseSwapchainImagesEXT = (PFN_vkReleaseSwapchainImagesEXT)load(context, "vkReleaseSwapchainImagesEXT"); #endif /* defined(VK_EXT_swapchain_maintenance1) */ @@ -1481,9 +1458,6 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkGetValidationCacheDataEXT = (PFN_vkGetValidationCacheDataEXT)load(context, "vkGetValidationCacheDataEXT"); table->vkMergeValidationCachesEXT = (PFN_vkMergeValidationCachesEXT)load(context, "vkMergeValidationCachesEXT"); #endif /* defined(VK_EXT_validation_cache) */ -#if defined(VK_EXT_vertex_input_dynamic_state) - table->vkCmdSetVertexInputEXT = (PFN_vkCmdSetVertexInputEXT)load(context, "vkCmdSetVertexInputEXT"); -#endif /* defined(VK_EXT_vertex_input_dynamic_state) */ #if defined(VK_FUCHSIA_buffer_collection) table->vkCreateBufferCollectionFUCHSIA = (PFN_vkCreateBufferCollectionFUCHSIA)load(context, "vkCreateBufferCollectionFUCHSIA"); table->vkDestroyBufferCollectionFUCHSIA = (PFN_vkDestroyBufferCollectionFUCHSIA)load(context, "vkDestroyBufferCollectionFUCHSIA"); @@ -1503,6 +1477,10 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkGetPastPresentationTimingGOOGLE = (PFN_vkGetPastPresentationTimingGOOGLE)load(context, "vkGetPastPresentationTimingGOOGLE"); table->vkGetRefreshCycleDurationGOOGLE = (PFN_vkGetRefreshCycleDurationGOOGLE)load(context, "vkGetRefreshCycleDurationGOOGLE"); #endif /* defined(VK_GOOGLE_display_timing) */ +#if defined(VK_HUAWEI_cluster_culling_shader) + table->vkCmdDrawClusterHUAWEI = (PFN_vkCmdDrawClusterHUAWEI)load(context, "vkCmdDrawClusterHUAWEI"); + table->vkCmdDrawClusterIndirectHUAWEI = (PFN_vkCmdDrawClusterIndirectHUAWEI)load(context, "vkCmdDrawClusterIndirectHUAWEI"); +#endif /* defined(VK_HUAWEI_cluster_culling_shader) */ #if defined(VK_HUAWEI_invocation_mask) table->vkCmdBindInvocationMaskHUAWEI = (PFN_vkCmdBindInvocationMaskHUAWEI)load(context, "vkCmdBindInvocationMaskHUAWEI"); #endif /* defined(VK_HUAWEI_invocation_mask) */ @@ -1633,6 +1611,10 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkGetDeviceImageMemoryRequirementsKHR = (PFN_vkGetDeviceImageMemoryRequirementsKHR)load(context, "vkGetDeviceImageMemoryRequirementsKHR"); table->vkGetDeviceImageSparseMemoryRequirementsKHR = (PFN_vkGetDeviceImageSparseMemoryRequirementsKHR)load(context, "vkGetDeviceImageSparseMemoryRequirementsKHR"); #endif /* defined(VK_KHR_maintenance4) */ +#if defined(VK_KHR_map_memory2) + table->vkMapMemory2KHR = (PFN_vkMapMemory2KHR)load(context, "vkMapMemory2KHR"); + table->vkUnmapMemory2KHR = (PFN_vkUnmapMemory2KHR)load(context, "vkUnmapMemory2KHR"); +#endif /* defined(VK_KHR_map_memory2) */ #if defined(VK_KHR_performance_query) table->vkAcquireProfilingLockKHR = (PFN_vkAcquireProfilingLockKHR)load(context, "vkAcquireProfilingLockKHR"); table->vkReleaseProfilingLockKHR = (PFN_vkReleaseProfilingLockKHR)load(context, "vkReleaseProfilingLockKHR"); @@ -1779,6 +1761,9 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkGetAccelerationStructureMemoryRequirementsNV = (PFN_vkGetAccelerationStructureMemoryRequirementsNV)load(context, "vkGetAccelerationStructureMemoryRequirementsNV"); table->vkGetRayTracingShaderGroupHandlesNV = (PFN_vkGetRayTracingShaderGroupHandlesNV)load(context, "vkGetRayTracingShaderGroupHandlesNV"); #endif /* defined(VK_NV_ray_tracing) */ +#if defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 + table->vkCmdSetExclusiveScissorEnableNV = (PFN_vkCmdSetExclusiveScissorEnableNV)load(context, "vkCmdSetExclusiveScissorEnableNV"); +#endif /* defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 */ #if defined(VK_NV_scissor_exclusive) table->vkCmdSetExclusiveScissorNV = (PFN_vkCmdSetExclusiveScissorNV)load(context, "vkCmdSetExclusiveScissorNV"); #endif /* defined(VK_NV_scissor_exclusive) */ @@ -1795,9 +1780,66 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkGetDescriptorSetHostMappingVALVE = (PFN_vkGetDescriptorSetHostMappingVALVE)load(context, "vkGetDescriptorSetHostMappingVALVE"); table->vkGetDescriptorSetLayoutHostMappingInfoVALVE = (PFN_vkGetDescriptorSetLayoutHostMappingInfoVALVE)load(context, "vkGetDescriptorSetLayoutHostMappingInfoVALVE"); #endif /* defined(VK_VALVE_descriptor_set_host_mapping) */ +#if (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) + table->vkCmdBindVertexBuffers2EXT = (PFN_vkCmdBindVertexBuffers2EXT)load(context, "vkCmdBindVertexBuffers2EXT"); + table->vkCmdSetCullModeEXT = (PFN_vkCmdSetCullModeEXT)load(context, "vkCmdSetCullModeEXT"); + table->vkCmdSetDepthBoundsTestEnableEXT = (PFN_vkCmdSetDepthBoundsTestEnableEXT)load(context, "vkCmdSetDepthBoundsTestEnableEXT"); + table->vkCmdSetDepthCompareOpEXT = (PFN_vkCmdSetDepthCompareOpEXT)load(context, "vkCmdSetDepthCompareOpEXT"); + table->vkCmdSetDepthTestEnableEXT = (PFN_vkCmdSetDepthTestEnableEXT)load(context, "vkCmdSetDepthTestEnableEXT"); + table->vkCmdSetDepthWriteEnableEXT = (PFN_vkCmdSetDepthWriteEnableEXT)load(context, "vkCmdSetDepthWriteEnableEXT"); + table->vkCmdSetFrontFaceEXT = (PFN_vkCmdSetFrontFaceEXT)load(context, "vkCmdSetFrontFaceEXT"); + table->vkCmdSetPrimitiveTopologyEXT = (PFN_vkCmdSetPrimitiveTopologyEXT)load(context, "vkCmdSetPrimitiveTopologyEXT"); + table->vkCmdSetScissorWithCountEXT = (PFN_vkCmdSetScissorWithCountEXT)load(context, "vkCmdSetScissorWithCountEXT"); + table->vkCmdSetStencilOpEXT = (PFN_vkCmdSetStencilOpEXT)load(context, "vkCmdSetStencilOpEXT"); + table->vkCmdSetStencilTestEnableEXT = (PFN_vkCmdSetStencilTestEnableEXT)load(context, "vkCmdSetStencilTestEnableEXT"); + table->vkCmdSetViewportWithCountEXT = (PFN_vkCmdSetViewportWithCountEXT)load(context, "vkCmdSetViewportWithCountEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) + table->vkCmdSetDepthBiasEnableEXT = (PFN_vkCmdSetDepthBiasEnableEXT)load(context, "vkCmdSetDepthBiasEnableEXT"); + table->vkCmdSetLogicOpEXT = (PFN_vkCmdSetLogicOpEXT)load(context, "vkCmdSetLogicOpEXT"); + table->vkCmdSetPatchControlPointsEXT = (PFN_vkCmdSetPatchControlPointsEXT)load(context, "vkCmdSetPatchControlPointsEXT"); + table->vkCmdSetPrimitiveRestartEnableEXT = (PFN_vkCmdSetPrimitiveRestartEnableEXT)load(context, "vkCmdSetPrimitiveRestartEnableEXT"); + table->vkCmdSetRasterizerDiscardEnableEXT = (PFN_vkCmdSetRasterizerDiscardEnableEXT)load(context, "vkCmdSetRasterizerDiscardEnableEXT"); +#endif /* (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) + table->vkCmdSetAlphaToCoverageEnableEXT = (PFN_vkCmdSetAlphaToCoverageEnableEXT)load(context, "vkCmdSetAlphaToCoverageEnableEXT"); + table->vkCmdSetAlphaToOneEnableEXT = (PFN_vkCmdSetAlphaToOneEnableEXT)load(context, "vkCmdSetAlphaToOneEnableEXT"); + table->vkCmdSetColorBlendAdvancedEXT = (PFN_vkCmdSetColorBlendAdvancedEXT)load(context, "vkCmdSetColorBlendAdvancedEXT"); + table->vkCmdSetColorBlendEnableEXT = (PFN_vkCmdSetColorBlendEnableEXT)load(context, "vkCmdSetColorBlendEnableEXT"); + table->vkCmdSetColorBlendEquationEXT = (PFN_vkCmdSetColorBlendEquationEXT)load(context, "vkCmdSetColorBlendEquationEXT"); + table->vkCmdSetColorWriteMaskEXT = (PFN_vkCmdSetColorWriteMaskEXT)load(context, "vkCmdSetColorWriteMaskEXT"); + table->vkCmdSetConservativeRasterizationModeEXT = (PFN_vkCmdSetConservativeRasterizationModeEXT)load(context, "vkCmdSetConservativeRasterizationModeEXT"); + table->vkCmdSetCoverageModulationModeNV = (PFN_vkCmdSetCoverageModulationModeNV)load(context, "vkCmdSetCoverageModulationModeNV"); + table->vkCmdSetCoverageModulationTableEnableNV = (PFN_vkCmdSetCoverageModulationTableEnableNV)load(context, "vkCmdSetCoverageModulationTableEnableNV"); + table->vkCmdSetCoverageModulationTableNV = (PFN_vkCmdSetCoverageModulationTableNV)load(context, "vkCmdSetCoverageModulationTableNV"); + table->vkCmdSetCoverageReductionModeNV = (PFN_vkCmdSetCoverageReductionModeNV)load(context, "vkCmdSetCoverageReductionModeNV"); + table->vkCmdSetCoverageToColorEnableNV = (PFN_vkCmdSetCoverageToColorEnableNV)load(context, "vkCmdSetCoverageToColorEnableNV"); + table->vkCmdSetCoverageToColorLocationNV = (PFN_vkCmdSetCoverageToColorLocationNV)load(context, "vkCmdSetCoverageToColorLocationNV"); + table->vkCmdSetDepthClampEnableEXT = (PFN_vkCmdSetDepthClampEnableEXT)load(context, "vkCmdSetDepthClampEnableEXT"); + table->vkCmdSetDepthClipEnableEXT = (PFN_vkCmdSetDepthClipEnableEXT)load(context, "vkCmdSetDepthClipEnableEXT"); + table->vkCmdSetDepthClipNegativeOneToOneEXT = (PFN_vkCmdSetDepthClipNegativeOneToOneEXT)load(context, "vkCmdSetDepthClipNegativeOneToOneEXT"); + table->vkCmdSetExtraPrimitiveOverestimationSizeEXT = (PFN_vkCmdSetExtraPrimitiveOverestimationSizeEXT)load(context, "vkCmdSetExtraPrimitiveOverestimationSizeEXT"); + table->vkCmdSetLineRasterizationModeEXT = (PFN_vkCmdSetLineRasterizationModeEXT)load(context, "vkCmdSetLineRasterizationModeEXT"); + table->vkCmdSetLineStippleEnableEXT = (PFN_vkCmdSetLineStippleEnableEXT)load(context, "vkCmdSetLineStippleEnableEXT"); + table->vkCmdSetLogicOpEnableEXT = (PFN_vkCmdSetLogicOpEnableEXT)load(context, "vkCmdSetLogicOpEnableEXT"); + table->vkCmdSetPolygonModeEXT = (PFN_vkCmdSetPolygonModeEXT)load(context, "vkCmdSetPolygonModeEXT"); + table->vkCmdSetProvokingVertexModeEXT = (PFN_vkCmdSetProvokingVertexModeEXT)load(context, "vkCmdSetProvokingVertexModeEXT"); + table->vkCmdSetRasterizationSamplesEXT = (PFN_vkCmdSetRasterizationSamplesEXT)load(context, "vkCmdSetRasterizationSamplesEXT"); + table->vkCmdSetRasterizationStreamEXT = (PFN_vkCmdSetRasterizationStreamEXT)load(context, "vkCmdSetRasterizationStreamEXT"); + table->vkCmdSetRepresentativeFragmentTestEnableNV = (PFN_vkCmdSetRepresentativeFragmentTestEnableNV)load(context, "vkCmdSetRepresentativeFragmentTestEnableNV"); + table->vkCmdSetSampleLocationsEnableEXT = (PFN_vkCmdSetSampleLocationsEnableEXT)load(context, "vkCmdSetSampleLocationsEnableEXT"); + table->vkCmdSetSampleMaskEXT = (PFN_vkCmdSetSampleMaskEXT)load(context, "vkCmdSetSampleMaskEXT"); + table->vkCmdSetShadingRateImageEnableNV = (PFN_vkCmdSetShadingRateImageEnableNV)load(context, "vkCmdSetShadingRateImageEnableNV"); + table->vkCmdSetTessellationDomainOriginEXT = (PFN_vkCmdSetTessellationDomainOriginEXT)load(context, "vkCmdSetTessellationDomainOriginEXT"); + table->vkCmdSetViewportSwizzleNV = (PFN_vkCmdSetViewportSwizzleNV)load(context, "vkCmdSetViewportSwizzleNV"); + table->vkCmdSetViewportWScalingEnableNV = (PFN_vkCmdSetViewportWScalingEnableNV)load(context, "vkCmdSetViewportWScalingEnableNV"); +#endif /* (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) */ #if (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) table->vkGetDeviceGroupSurfacePresentModes2EXT = (PFN_vkGetDeviceGroupSurfacePresentModes2EXT)load(context, "vkGetDeviceGroupSurfacePresentModes2EXT"); #endif /* (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) */ +#if (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) + table->vkCmdSetVertexInputEXT = (PFN_vkCmdSetVertexInputEXT)load(context, "vkCmdSetVertexInputEXT"); +#endif /* (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) */ #if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) table->vkCmdPushDescriptorSetWithTemplateKHR = (PFN_vkCmdPushDescriptorSetWithTemplateKHR)load(context, "vkCmdPushDescriptorSetWithTemplateKHR"); #endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) */ @@ -2119,9 +2161,9 @@ PFN_vkGetImageOpaqueCaptureDescriptorDataEXT vkGetImageOpaqueCaptureDescriptorDa PFN_vkGetImageViewOpaqueCaptureDescriptorDataEXT vkGetImageViewOpaqueCaptureDescriptorDataEXT; PFN_vkGetSamplerOpaqueCaptureDescriptorDataEXT vkGetSamplerOpaqueCaptureDescriptorDataEXT; #endif /* defined(VK_EXT_descriptor_buffer) */ -#if defined(VK_EXT_descriptor_buffer) && defined(VK_KHR_acceleration_structure) && defined(VK_NV_ray_tracing) +#if defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) PFN_vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT; -#endif /* defined(VK_EXT_descriptor_buffer) && defined(VK_KHR_acceleration_structure) && defined(VK_NV_ray_tracing) */ +#endif /* defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) */ #if defined(VK_EXT_device_fault) PFN_vkGetDeviceFaultInfoEXT vkGetDeviceFaultInfoEXT; #endif /* defined(VK_EXT_device_fault) */ @@ -2135,6 +2177,10 @@ PFN_vkGetPhysicalDeviceDirectFBPresentationSupportEXT vkGetPhysicalDeviceDirectF #if defined(VK_EXT_discard_rectangles) PFN_vkCmdSetDiscardRectangleEXT vkCmdSetDiscardRectangleEXT; #endif /* defined(VK_EXT_discard_rectangles) */ +#if defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 +PFN_vkCmdSetDiscardRectangleEnableEXT vkCmdSetDiscardRectangleEnableEXT; +PFN_vkCmdSetDiscardRectangleModeEXT vkCmdSetDiscardRectangleModeEXT; +#endif /* defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 */ #if defined(VK_EXT_display_control) PFN_vkDisplayPowerControlEXT vkDisplayPowerControlEXT; PFN_vkGetSwapchainCounterEXT vkGetSwapchainCounterEXT; @@ -2144,60 +2190,6 @@ PFN_vkRegisterDisplayEventEXT vkRegisterDisplayEventEXT; #if defined(VK_EXT_display_surface_counter) PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT vkGetPhysicalDeviceSurfaceCapabilities2EXT; #endif /* defined(VK_EXT_display_surface_counter) */ -#if defined(VK_EXT_extended_dynamic_state) -PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT; -PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT; -PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT; -PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT; -PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT; -PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT; -PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT; -PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT; -PFN_vkCmdSetScissorWithCountEXT vkCmdSetScissorWithCountEXT; -PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT; -PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT; -PFN_vkCmdSetViewportWithCountEXT vkCmdSetViewportWithCountEXT; -#endif /* defined(VK_EXT_extended_dynamic_state) */ -#if defined(VK_EXT_extended_dynamic_state2) -PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT; -PFN_vkCmdSetLogicOpEXT vkCmdSetLogicOpEXT; -PFN_vkCmdSetPatchControlPointsEXT vkCmdSetPatchControlPointsEXT; -PFN_vkCmdSetPrimitiveRestartEnableEXT vkCmdSetPrimitiveRestartEnableEXT; -PFN_vkCmdSetRasterizerDiscardEnableEXT vkCmdSetRasterizerDiscardEnableEXT; -#endif /* defined(VK_EXT_extended_dynamic_state2) */ -#if defined(VK_EXT_extended_dynamic_state3) -PFN_vkCmdSetAlphaToCoverageEnableEXT vkCmdSetAlphaToCoverageEnableEXT; -PFN_vkCmdSetAlphaToOneEnableEXT vkCmdSetAlphaToOneEnableEXT; -PFN_vkCmdSetColorBlendAdvancedEXT vkCmdSetColorBlendAdvancedEXT; -PFN_vkCmdSetColorBlendEnableEXT vkCmdSetColorBlendEnableEXT; -PFN_vkCmdSetColorBlendEquationEXT vkCmdSetColorBlendEquationEXT; -PFN_vkCmdSetColorWriteMaskEXT vkCmdSetColorWriteMaskEXT; -PFN_vkCmdSetConservativeRasterizationModeEXT vkCmdSetConservativeRasterizationModeEXT; -PFN_vkCmdSetCoverageModulationModeNV vkCmdSetCoverageModulationModeNV; -PFN_vkCmdSetCoverageModulationTableEnableNV vkCmdSetCoverageModulationTableEnableNV; -PFN_vkCmdSetCoverageModulationTableNV vkCmdSetCoverageModulationTableNV; -PFN_vkCmdSetCoverageReductionModeNV vkCmdSetCoverageReductionModeNV; -PFN_vkCmdSetCoverageToColorEnableNV vkCmdSetCoverageToColorEnableNV; -PFN_vkCmdSetCoverageToColorLocationNV vkCmdSetCoverageToColorLocationNV; -PFN_vkCmdSetDepthClampEnableEXT vkCmdSetDepthClampEnableEXT; -PFN_vkCmdSetDepthClipEnableEXT vkCmdSetDepthClipEnableEXT; -PFN_vkCmdSetDepthClipNegativeOneToOneEXT vkCmdSetDepthClipNegativeOneToOneEXT; -PFN_vkCmdSetExtraPrimitiveOverestimationSizeEXT vkCmdSetExtraPrimitiveOverestimationSizeEXT; -PFN_vkCmdSetLineRasterizationModeEXT vkCmdSetLineRasterizationModeEXT; -PFN_vkCmdSetLineStippleEnableEXT vkCmdSetLineStippleEnableEXT; -PFN_vkCmdSetLogicOpEnableEXT vkCmdSetLogicOpEnableEXT; -PFN_vkCmdSetPolygonModeEXT vkCmdSetPolygonModeEXT; -PFN_vkCmdSetProvokingVertexModeEXT vkCmdSetProvokingVertexModeEXT; -PFN_vkCmdSetRasterizationSamplesEXT vkCmdSetRasterizationSamplesEXT; -PFN_vkCmdSetRasterizationStreamEXT vkCmdSetRasterizationStreamEXT; -PFN_vkCmdSetRepresentativeFragmentTestEnableNV vkCmdSetRepresentativeFragmentTestEnableNV; -PFN_vkCmdSetSampleLocationsEnableEXT vkCmdSetSampleLocationsEnableEXT; -PFN_vkCmdSetSampleMaskEXT vkCmdSetSampleMaskEXT; -PFN_vkCmdSetShadingRateImageEnableNV vkCmdSetShadingRateImageEnableNV; -PFN_vkCmdSetTessellationDomainOriginEXT vkCmdSetTessellationDomainOriginEXT; -PFN_vkCmdSetViewportSwizzleNV vkCmdSetViewportSwizzleNV; -PFN_vkCmdSetViewportWScalingEnableNV vkCmdSetViewportWScalingEnableNV; -#endif /* defined(VK_EXT_extended_dynamic_state3) */ #if defined(VK_EXT_external_memory_host) PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesEXT; #endif /* defined(VK_EXT_external_memory_host) */ @@ -2275,6 +2267,12 @@ PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT vkGetPhysicalDeviceMultisamplePr PFN_vkGetShaderModuleCreateInfoIdentifierEXT vkGetShaderModuleCreateInfoIdentifierEXT; PFN_vkGetShaderModuleIdentifierEXT vkGetShaderModuleIdentifierEXT; #endif /* defined(VK_EXT_shader_module_identifier) */ +#if defined(VK_EXT_shader_object) +PFN_vkCmdBindShadersEXT vkCmdBindShadersEXT; +PFN_vkCreateShadersEXT vkCreateShadersEXT; +PFN_vkDestroyShaderEXT vkDestroyShaderEXT; +PFN_vkGetShaderBinaryDataEXT vkGetShaderBinaryDataEXT; +#endif /* defined(VK_EXT_shader_object) */ #if defined(VK_EXT_swapchain_maintenance1) PFN_vkReleaseSwapchainImagesEXT vkReleaseSwapchainImagesEXT; #endif /* defined(VK_EXT_swapchain_maintenance1) */ @@ -2295,9 +2293,6 @@ PFN_vkDestroyValidationCacheEXT vkDestroyValidationCacheEXT; PFN_vkGetValidationCacheDataEXT vkGetValidationCacheDataEXT; PFN_vkMergeValidationCachesEXT vkMergeValidationCachesEXT; #endif /* defined(VK_EXT_validation_cache) */ -#if defined(VK_EXT_vertex_input_dynamic_state) -PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT; -#endif /* defined(VK_EXT_vertex_input_dynamic_state) */ #if defined(VK_FUCHSIA_buffer_collection) PFN_vkCreateBufferCollectionFUCHSIA vkCreateBufferCollectionFUCHSIA; PFN_vkDestroyBufferCollectionFUCHSIA vkDestroyBufferCollectionFUCHSIA; @@ -2323,6 +2318,10 @@ PFN_vkCreateStreamDescriptorSurfaceGGP vkCreateStreamDescriptorSurfaceGGP; PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE; PFN_vkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLE; #endif /* defined(VK_GOOGLE_display_timing) */ +#if defined(VK_HUAWEI_cluster_culling_shader) +PFN_vkCmdDrawClusterHUAWEI vkCmdDrawClusterHUAWEI; +PFN_vkCmdDrawClusterIndirectHUAWEI vkCmdDrawClusterIndirectHUAWEI; +#endif /* defined(VK_HUAWEI_cluster_culling_shader) */ #if defined(VK_HUAWEI_invocation_mask) PFN_vkCmdBindInvocationMaskHUAWEI vkCmdBindInvocationMaskHUAWEI; #endif /* defined(VK_HUAWEI_invocation_mask) */ @@ -2497,6 +2496,10 @@ PFN_vkGetDeviceBufferMemoryRequirementsKHR vkGetDeviceBufferMemoryRequirementsKH PFN_vkGetDeviceImageMemoryRequirementsKHR vkGetDeviceImageMemoryRequirementsKHR; PFN_vkGetDeviceImageSparseMemoryRequirementsKHR vkGetDeviceImageSparseMemoryRequirementsKHR; #endif /* defined(VK_KHR_maintenance4) */ +#if defined(VK_KHR_map_memory2) +PFN_vkMapMemory2KHR vkMapMemory2KHR; +PFN_vkUnmapMemory2KHR vkUnmapMemory2KHR; +#endif /* defined(VK_KHR_map_memory2) */ #if defined(VK_KHR_performance_query) PFN_vkAcquireProfilingLockKHR vkAcquireProfilingLockKHR; PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR; @@ -2693,6 +2696,9 @@ PFN_vkGetAccelerationStructureHandleNV vkGetAccelerationStructureHandleNV; PFN_vkGetAccelerationStructureMemoryRequirementsNV vkGetAccelerationStructureMemoryRequirementsNV; PFN_vkGetRayTracingShaderGroupHandlesNV vkGetRayTracingShaderGroupHandlesNV; #endif /* defined(VK_NV_ray_tracing) */ +#if defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 +PFN_vkCmdSetExclusiveScissorEnableNV vkCmdSetExclusiveScissorEnableNV; +#endif /* defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 */ #if defined(VK_NV_scissor_exclusive) PFN_vkCmdSetExclusiveScissorNV vkCmdSetExclusiveScissorNV; #endif /* defined(VK_NV_scissor_exclusive) */ @@ -2713,9 +2719,66 @@ PFN_vkGetPhysicalDeviceScreenPresentationSupportQNX vkGetPhysicalDeviceScreenPre PFN_vkGetDescriptorSetHostMappingVALVE vkGetDescriptorSetHostMappingVALVE; PFN_vkGetDescriptorSetLayoutHostMappingInfoVALVE vkGetDescriptorSetLayoutHostMappingInfoVALVE; #endif /* defined(VK_VALVE_descriptor_set_host_mapping) */ +#if (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) +PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT; +PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT; +PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT; +PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT; +PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT; +PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT; +PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT; +PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT; +PFN_vkCmdSetScissorWithCountEXT vkCmdSetScissorWithCountEXT; +PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT; +PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT; +PFN_vkCmdSetViewportWithCountEXT vkCmdSetViewportWithCountEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) +PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT; +PFN_vkCmdSetLogicOpEXT vkCmdSetLogicOpEXT; +PFN_vkCmdSetPatchControlPointsEXT vkCmdSetPatchControlPointsEXT; +PFN_vkCmdSetPrimitiveRestartEnableEXT vkCmdSetPrimitiveRestartEnableEXT; +PFN_vkCmdSetRasterizerDiscardEnableEXT vkCmdSetRasterizerDiscardEnableEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) +PFN_vkCmdSetAlphaToCoverageEnableEXT vkCmdSetAlphaToCoverageEnableEXT; +PFN_vkCmdSetAlphaToOneEnableEXT vkCmdSetAlphaToOneEnableEXT; +PFN_vkCmdSetColorBlendAdvancedEXT vkCmdSetColorBlendAdvancedEXT; +PFN_vkCmdSetColorBlendEnableEXT vkCmdSetColorBlendEnableEXT; +PFN_vkCmdSetColorBlendEquationEXT vkCmdSetColorBlendEquationEXT; +PFN_vkCmdSetColorWriteMaskEXT vkCmdSetColorWriteMaskEXT; +PFN_vkCmdSetConservativeRasterizationModeEXT vkCmdSetConservativeRasterizationModeEXT; +PFN_vkCmdSetCoverageModulationModeNV vkCmdSetCoverageModulationModeNV; +PFN_vkCmdSetCoverageModulationTableEnableNV vkCmdSetCoverageModulationTableEnableNV; +PFN_vkCmdSetCoverageModulationTableNV vkCmdSetCoverageModulationTableNV; +PFN_vkCmdSetCoverageReductionModeNV vkCmdSetCoverageReductionModeNV; +PFN_vkCmdSetCoverageToColorEnableNV vkCmdSetCoverageToColorEnableNV; +PFN_vkCmdSetCoverageToColorLocationNV vkCmdSetCoverageToColorLocationNV; +PFN_vkCmdSetDepthClampEnableEXT vkCmdSetDepthClampEnableEXT; +PFN_vkCmdSetDepthClipEnableEXT vkCmdSetDepthClipEnableEXT; +PFN_vkCmdSetDepthClipNegativeOneToOneEXT vkCmdSetDepthClipNegativeOneToOneEXT; +PFN_vkCmdSetExtraPrimitiveOverestimationSizeEXT vkCmdSetExtraPrimitiveOverestimationSizeEXT; +PFN_vkCmdSetLineRasterizationModeEXT vkCmdSetLineRasterizationModeEXT; +PFN_vkCmdSetLineStippleEnableEXT vkCmdSetLineStippleEnableEXT; +PFN_vkCmdSetLogicOpEnableEXT vkCmdSetLogicOpEnableEXT; +PFN_vkCmdSetPolygonModeEXT vkCmdSetPolygonModeEXT; +PFN_vkCmdSetProvokingVertexModeEXT vkCmdSetProvokingVertexModeEXT; +PFN_vkCmdSetRasterizationSamplesEXT vkCmdSetRasterizationSamplesEXT; +PFN_vkCmdSetRasterizationStreamEXT vkCmdSetRasterizationStreamEXT; +PFN_vkCmdSetRepresentativeFragmentTestEnableNV vkCmdSetRepresentativeFragmentTestEnableNV; +PFN_vkCmdSetSampleLocationsEnableEXT vkCmdSetSampleLocationsEnableEXT; +PFN_vkCmdSetSampleMaskEXT vkCmdSetSampleMaskEXT; +PFN_vkCmdSetShadingRateImageEnableNV vkCmdSetShadingRateImageEnableNV; +PFN_vkCmdSetTessellationDomainOriginEXT vkCmdSetTessellationDomainOriginEXT; +PFN_vkCmdSetViewportSwizzleNV vkCmdSetViewportSwizzleNV; +PFN_vkCmdSetViewportWScalingEnableNV vkCmdSetViewportWScalingEnableNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) */ #if (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) PFN_vkGetDeviceGroupSurfacePresentModes2EXT vkGetDeviceGroupSurfacePresentModes2EXT; #endif /* (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) */ +#if (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) +PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT; +#endif /* (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) */ #if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR; #endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) */ diff --git a/WickedEngine/Utility/volk.h b/WickedEngine/Utility/volk.h index 960efd8a3..62a36937d 100644 --- a/WickedEngine/Utility/volk.h +++ b/WickedEngine/Utility/volk.h @@ -15,7 +15,7 @@ #endif /* VOLK_GENERATE_VERSION_DEFINE */ -#define VOLK_HEADER_VERSION 238 +#define VOLK_HEADER_VERSION 249 /* VOLK_GENERATE_VERSION_DEFINE */ #ifndef VK_NO_PROTOTYPES @@ -23,8 +23,8 @@ #endif #ifndef VULKAN_H_ -# ifdef VOLK_VULKAN_H_PATH -# include VOLK_VULKAN_H_PATH +# ifdef VOLK_VULKAN_H_PATH +# include VOLK_VULKAN_H_PATH # elif defined(VK_USE_PLATFORM_WIN32_KHR) # include # include @@ -372,75 +372,25 @@ struct VolkDeviceTable PFN_vkGetImageViewOpaqueCaptureDescriptorDataEXT vkGetImageViewOpaqueCaptureDescriptorDataEXT; PFN_vkGetSamplerOpaqueCaptureDescriptorDataEXT vkGetSamplerOpaqueCaptureDescriptorDataEXT; #endif /* defined(VK_EXT_descriptor_buffer) */ -#if defined(VK_EXT_descriptor_buffer) && defined(VK_KHR_acceleration_structure) && defined(VK_NV_ray_tracing) +#if defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) PFN_vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT; -#endif /* defined(VK_EXT_descriptor_buffer) && defined(VK_KHR_acceleration_structure) && defined(VK_NV_ray_tracing) */ +#endif /* defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) */ #if defined(VK_EXT_device_fault) PFN_vkGetDeviceFaultInfoEXT vkGetDeviceFaultInfoEXT; #endif /* defined(VK_EXT_device_fault) */ #if defined(VK_EXT_discard_rectangles) PFN_vkCmdSetDiscardRectangleEXT vkCmdSetDiscardRectangleEXT; #endif /* defined(VK_EXT_discard_rectangles) */ +#if defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 + PFN_vkCmdSetDiscardRectangleEnableEXT vkCmdSetDiscardRectangleEnableEXT; + PFN_vkCmdSetDiscardRectangleModeEXT vkCmdSetDiscardRectangleModeEXT; +#endif /* defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 */ #if defined(VK_EXT_display_control) PFN_vkDisplayPowerControlEXT vkDisplayPowerControlEXT; PFN_vkGetSwapchainCounterEXT vkGetSwapchainCounterEXT; PFN_vkRegisterDeviceEventEXT vkRegisterDeviceEventEXT; PFN_vkRegisterDisplayEventEXT vkRegisterDisplayEventEXT; #endif /* defined(VK_EXT_display_control) */ -#if defined(VK_EXT_extended_dynamic_state) - PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT; - PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT; - PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT; - PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT; - PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT; - PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT; - PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT; - PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT; - PFN_vkCmdSetScissorWithCountEXT vkCmdSetScissorWithCountEXT; - PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT; - PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT; - PFN_vkCmdSetViewportWithCountEXT vkCmdSetViewportWithCountEXT; -#endif /* defined(VK_EXT_extended_dynamic_state) */ -#if defined(VK_EXT_extended_dynamic_state2) - PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT; - PFN_vkCmdSetLogicOpEXT vkCmdSetLogicOpEXT; - PFN_vkCmdSetPatchControlPointsEXT vkCmdSetPatchControlPointsEXT; - PFN_vkCmdSetPrimitiveRestartEnableEXT vkCmdSetPrimitiveRestartEnableEXT; - PFN_vkCmdSetRasterizerDiscardEnableEXT vkCmdSetRasterizerDiscardEnableEXT; -#endif /* defined(VK_EXT_extended_dynamic_state2) */ -#if defined(VK_EXT_extended_dynamic_state3) - PFN_vkCmdSetAlphaToCoverageEnableEXT vkCmdSetAlphaToCoverageEnableEXT; - PFN_vkCmdSetAlphaToOneEnableEXT vkCmdSetAlphaToOneEnableEXT; - PFN_vkCmdSetColorBlendAdvancedEXT vkCmdSetColorBlendAdvancedEXT; - PFN_vkCmdSetColorBlendEnableEXT vkCmdSetColorBlendEnableEXT; - PFN_vkCmdSetColorBlendEquationEXT vkCmdSetColorBlendEquationEXT; - PFN_vkCmdSetColorWriteMaskEXT vkCmdSetColorWriteMaskEXT; - PFN_vkCmdSetConservativeRasterizationModeEXT vkCmdSetConservativeRasterizationModeEXT; - PFN_vkCmdSetCoverageModulationModeNV vkCmdSetCoverageModulationModeNV; - PFN_vkCmdSetCoverageModulationTableEnableNV vkCmdSetCoverageModulationTableEnableNV; - PFN_vkCmdSetCoverageModulationTableNV vkCmdSetCoverageModulationTableNV; - PFN_vkCmdSetCoverageReductionModeNV vkCmdSetCoverageReductionModeNV; - PFN_vkCmdSetCoverageToColorEnableNV vkCmdSetCoverageToColorEnableNV; - PFN_vkCmdSetCoverageToColorLocationNV vkCmdSetCoverageToColorLocationNV; - PFN_vkCmdSetDepthClampEnableEXT vkCmdSetDepthClampEnableEXT; - PFN_vkCmdSetDepthClipEnableEXT vkCmdSetDepthClipEnableEXT; - PFN_vkCmdSetDepthClipNegativeOneToOneEXT vkCmdSetDepthClipNegativeOneToOneEXT; - PFN_vkCmdSetExtraPrimitiveOverestimationSizeEXT vkCmdSetExtraPrimitiveOverestimationSizeEXT; - PFN_vkCmdSetLineRasterizationModeEXT vkCmdSetLineRasterizationModeEXT; - PFN_vkCmdSetLineStippleEnableEXT vkCmdSetLineStippleEnableEXT; - PFN_vkCmdSetLogicOpEnableEXT vkCmdSetLogicOpEnableEXT; - PFN_vkCmdSetPolygonModeEXT vkCmdSetPolygonModeEXT; - PFN_vkCmdSetProvokingVertexModeEXT vkCmdSetProvokingVertexModeEXT; - PFN_vkCmdSetRasterizationSamplesEXT vkCmdSetRasterizationSamplesEXT; - PFN_vkCmdSetRasterizationStreamEXT vkCmdSetRasterizationStreamEXT; - PFN_vkCmdSetRepresentativeFragmentTestEnableNV vkCmdSetRepresentativeFragmentTestEnableNV; - PFN_vkCmdSetSampleLocationsEnableEXT vkCmdSetSampleLocationsEnableEXT; - PFN_vkCmdSetSampleMaskEXT vkCmdSetSampleMaskEXT; - PFN_vkCmdSetShadingRateImageEnableNV vkCmdSetShadingRateImageEnableNV; - PFN_vkCmdSetTessellationDomainOriginEXT vkCmdSetTessellationDomainOriginEXT; - PFN_vkCmdSetViewportSwizzleNV vkCmdSetViewportSwizzleNV; - PFN_vkCmdSetViewportWScalingEnableNV vkCmdSetViewportWScalingEnableNV; -#endif /* defined(VK_EXT_extended_dynamic_state3) */ #if defined(VK_EXT_external_memory_host) PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesEXT; #endif /* defined(VK_EXT_external_memory_host) */ @@ -510,6 +460,12 @@ struct VolkDeviceTable PFN_vkGetShaderModuleCreateInfoIdentifierEXT vkGetShaderModuleCreateInfoIdentifierEXT; PFN_vkGetShaderModuleIdentifierEXT vkGetShaderModuleIdentifierEXT; #endif /* defined(VK_EXT_shader_module_identifier) */ +#if defined(VK_EXT_shader_object) + PFN_vkCmdBindShadersEXT vkCmdBindShadersEXT; + PFN_vkCreateShadersEXT vkCreateShadersEXT; + PFN_vkDestroyShaderEXT vkDestroyShaderEXT; + PFN_vkGetShaderBinaryDataEXT vkGetShaderBinaryDataEXT; +#endif /* defined(VK_EXT_shader_object) */ #if defined(VK_EXT_swapchain_maintenance1) PFN_vkReleaseSwapchainImagesEXT vkReleaseSwapchainImagesEXT; #endif /* defined(VK_EXT_swapchain_maintenance1) */ @@ -527,9 +483,6 @@ struct VolkDeviceTable PFN_vkGetValidationCacheDataEXT vkGetValidationCacheDataEXT; PFN_vkMergeValidationCachesEXT vkMergeValidationCachesEXT; #endif /* defined(VK_EXT_validation_cache) */ -#if defined(VK_EXT_vertex_input_dynamic_state) - PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT; -#endif /* defined(VK_EXT_vertex_input_dynamic_state) */ #if defined(VK_FUCHSIA_buffer_collection) PFN_vkCreateBufferCollectionFUCHSIA vkCreateBufferCollectionFUCHSIA; PFN_vkDestroyBufferCollectionFUCHSIA vkDestroyBufferCollectionFUCHSIA; @@ -549,6 +502,10 @@ struct VolkDeviceTable PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE; PFN_vkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLE; #endif /* defined(VK_GOOGLE_display_timing) */ +#if defined(VK_HUAWEI_cluster_culling_shader) + PFN_vkCmdDrawClusterHUAWEI vkCmdDrawClusterHUAWEI; + PFN_vkCmdDrawClusterIndirectHUAWEI vkCmdDrawClusterIndirectHUAWEI; +#endif /* defined(VK_HUAWEI_cluster_culling_shader) */ #if defined(VK_HUAWEI_invocation_mask) PFN_vkCmdBindInvocationMaskHUAWEI vkCmdBindInvocationMaskHUAWEI; #endif /* defined(VK_HUAWEI_invocation_mask) */ @@ -679,6 +636,10 @@ struct VolkDeviceTable PFN_vkGetDeviceImageMemoryRequirementsKHR vkGetDeviceImageMemoryRequirementsKHR; PFN_vkGetDeviceImageSparseMemoryRequirementsKHR vkGetDeviceImageSparseMemoryRequirementsKHR; #endif /* defined(VK_KHR_maintenance4) */ +#if defined(VK_KHR_map_memory2) + PFN_vkMapMemory2KHR vkMapMemory2KHR; + PFN_vkUnmapMemory2KHR vkUnmapMemory2KHR; +#endif /* defined(VK_KHR_map_memory2) */ #if defined(VK_KHR_performance_query) PFN_vkAcquireProfilingLockKHR vkAcquireProfilingLockKHR; PFN_vkReleaseProfilingLockKHR vkReleaseProfilingLockKHR; @@ -825,6 +786,9 @@ struct VolkDeviceTable PFN_vkGetAccelerationStructureMemoryRequirementsNV vkGetAccelerationStructureMemoryRequirementsNV; PFN_vkGetRayTracingShaderGroupHandlesNV vkGetRayTracingShaderGroupHandlesNV; #endif /* defined(VK_NV_ray_tracing) */ +#if defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 + PFN_vkCmdSetExclusiveScissorEnableNV vkCmdSetExclusiveScissorEnableNV; +#endif /* defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 */ #if defined(VK_NV_scissor_exclusive) PFN_vkCmdSetExclusiveScissorNV vkCmdSetExclusiveScissorNV; #endif /* defined(VK_NV_scissor_exclusive) */ @@ -841,9 +805,66 @@ struct VolkDeviceTable PFN_vkGetDescriptorSetHostMappingVALVE vkGetDescriptorSetHostMappingVALVE; PFN_vkGetDescriptorSetLayoutHostMappingInfoVALVE vkGetDescriptorSetLayoutHostMappingInfoVALVE; #endif /* defined(VK_VALVE_descriptor_set_host_mapping) */ +#if (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) + PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT; + PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT; + PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT; + PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT; + PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT; + PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT; + PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT; + PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT; + PFN_vkCmdSetScissorWithCountEXT vkCmdSetScissorWithCountEXT; + PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT; + PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT; + PFN_vkCmdSetViewportWithCountEXT vkCmdSetViewportWithCountEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) + PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT; + PFN_vkCmdSetLogicOpEXT vkCmdSetLogicOpEXT; + PFN_vkCmdSetPatchControlPointsEXT vkCmdSetPatchControlPointsEXT; + PFN_vkCmdSetPrimitiveRestartEnableEXT vkCmdSetPrimitiveRestartEnableEXT; + PFN_vkCmdSetRasterizerDiscardEnableEXT vkCmdSetRasterizerDiscardEnableEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) + PFN_vkCmdSetAlphaToCoverageEnableEXT vkCmdSetAlphaToCoverageEnableEXT; + PFN_vkCmdSetAlphaToOneEnableEXT vkCmdSetAlphaToOneEnableEXT; + PFN_vkCmdSetColorBlendAdvancedEXT vkCmdSetColorBlendAdvancedEXT; + PFN_vkCmdSetColorBlendEnableEXT vkCmdSetColorBlendEnableEXT; + PFN_vkCmdSetColorBlendEquationEXT vkCmdSetColorBlendEquationEXT; + PFN_vkCmdSetColorWriteMaskEXT vkCmdSetColorWriteMaskEXT; + PFN_vkCmdSetConservativeRasterizationModeEXT vkCmdSetConservativeRasterizationModeEXT; + PFN_vkCmdSetCoverageModulationModeNV vkCmdSetCoverageModulationModeNV; + PFN_vkCmdSetCoverageModulationTableEnableNV vkCmdSetCoverageModulationTableEnableNV; + PFN_vkCmdSetCoverageModulationTableNV vkCmdSetCoverageModulationTableNV; + PFN_vkCmdSetCoverageReductionModeNV vkCmdSetCoverageReductionModeNV; + PFN_vkCmdSetCoverageToColorEnableNV vkCmdSetCoverageToColorEnableNV; + PFN_vkCmdSetCoverageToColorLocationNV vkCmdSetCoverageToColorLocationNV; + PFN_vkCmdSetDepthClampEnableEXT vkCmdSetDepthClampEnableEXT; + PFN_vkCmdSetDepthClipEnableEXT vkCmdSetDepthClipEnableEXT; + PFN_vkCmdSetDepthClipNegativeOneToOneEXT vkCmdSetDepthClipNegativeOneToOneEXT; + PFN_vkCmdSetExtraPrimitiveOverestimationSizeEXT vkCmdSetExtraPrimitiveOverestimationSizeEXT; + PFN_vkCmdSetLineRasterizationModeEXT vkCmdSetLineRasterizationModeEXT; + PFN_vkCmdSetLineStippleEnableEXT vkCmdSetLineStippleEnableEXT; + PFN_vkCmdSetLogicOpEnableEXT vkCmdSetLogicOpEnableEXT; + PFN_vkCmdSetPolygonModeEXT vkCmdSetPolygonModeEXT; + PFN_vkCmdSetProvokingVertexModeEXT vkCmdSetProvokingVertexModeEXT; + PFN_vkCmdSetRasterizationSamplesEXT vkCmdSetRasterizationSamplesEXT; + PFN_vkCmdSetRasterizationStreamEXT vkCmdSetRasterizationStreamEXT; + PFN_vkCmdSetRepresentativeFragmentTestEnableNV vkCmdSetRepresentativeFragmentTestEnableNV; + PFN_vkCmdSetSampleLocationsEnableEXT vkCmdSetSampleLocationsEnableEXT; + PFN_vkCmdSetSampleMaskEXT vkCmdSetSampleMaskEXT; + PFN_vkCmdSetShadingRateImageEnableNV vkCmdSetShadingRateImageEnableNV; + PFN_vkCmdSetTessellationDomainOriginEXT vkCmdSetTessellationDomainOriginEXT; + PFN_vkCmdSetViewportSwizzleNV vkCmdSetViewportSwizzleNV; + PFN_vkCmdSetViewportWScalingEnableNV vkCmdSetViewportWScalingEnableNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) */ #if (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) PFN_vkGetDeviceGroupSurfacePresentModes2EXT vkGetDeviceGroupSurfacePresentModes2EXT; #endif /* (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) */ +#if (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) + PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT; +#endif /* (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) */ #if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR; #endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) */ @@ -1157,9 +1178,9 @@ extern PFN_vkGetImageOpaqueCaptureDescriptorDataEXT vkGetImageOpaqueCaptureDescr extern PFN_vkGetImageViewOpaqueCaptureDescriptorDataEXT vkGetImageViewOpaqueCaptureDescriptorDataEXT; extern PFN_vkGetSamplerOpaqueCaptureDescriptorDataEXT vkGetSamplerOpaqueCaptureDescriptorDataEXT; #endif /* defined(VK_EXT_descriptor_buffer) */ -#if defined(VK_EXT_descriptor_buffer) && defined(VK_KHR_acceleration_structure) && defined(VK_NV_ray_tracing) +#if defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) extern PFN_vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT; -#endif /* defined(VK_EXT_descriptor_buffer) && defined(VK_KHR_acceleration_structure) && defined(VK_NV_ray_tracing) */ +#endif /* defined(VK_EXT_descriptor_buffer) && (defined(VK_KHR_acceleration_structure) || defined(VK_NV_ray_tracing)) */ #if defined(VK_EXT_device_fault) extern PFN_vkGetDeviceFaultInfoEXT vkGetDeviceFaultInfoEXT; #endif /* defined(VK_EXT_device_fault) */ @@ -1173,6 +1194,10 @@ extern PFN_vkGetPhysicalDeviceDirectFBPresentationSupportEXT vkGetPhysicalDevice #if defined(VK_EXT_discard_rectangles) extern PFN_vkCmdSetDiscardRectangleEXT vkCmdSetDiscardRectangleEXT; #endif /* defined(VK_EXT_discard_rectangles) */ +#if defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 +extern PFN_vkCmdSetDiscardRectangleEnableEXT vkCmdSetDiscardRectangleEnableEXT; +extern PFN_vkCmdSetDiscardRectangleModeEXT vkCmdSetDiscardRectangleModeEXT; +#endif /* defined(VK_EXT_discard_rectangles) && VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION >= 2 */ #if defined(VK_EXT_display_control) extern PFN_vkDisplayPowerControlEXT vkDisplayPowerControlEXT; extern PFN_vkGetSwapchainCounterEXT vkGetSwapchainCounterEXT; @@ -1182,60 +1207,6 @@ extern PFN_vkRegisterDisplayEventEXT vkRegisterDisplayEventEXT; #if defined(VK_EXT_display_surface_counter) extern PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT vkGetPhysicalDeviceSurfaceCapabilities2EXT; #endif /* defined(VK_EXT_display_surface_counter) */ -#if defined(VK_EXT_extended_dynamic_state) -extern PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT; -extern PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT; -extern PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT; -extern PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT; -extern PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT; -extern PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT; -extern PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT; -extern PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT; -extern PFN_vkCmdSetScissorWithCountEXT vkCmdSetScissorWithCountEXT; -extern PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT; -extern PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT; -extern PFN_vkCmdSetViewportWithCountEXT vkCmdSetViewportWithCountEXT; -#endif /* defined(VK_EXT_extended_dynamic_state) */ -#if defined(VK_EXT_extended_dynamic_state2) -extern PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT; -extern PFN_vkCmdSetLogicOpEXT vkCmdSetLogicOpEXT; -extern PFN_vkCmdSetPatchControlPointsEXT vkCmdSetPatchControlPointsEXT; -extern PFN_vkCmdSetPrimitiveRestartEnableEXT vkCmdSetPrimitiveRestartEnableEXT; -extern PFN_vkCmdSetRasterizerDiscardEnableEXT vkCmdSetRasterizerDiscardEnableEXT; -#endif /* defined(VK_EXT_extended_dynamic_state2) */ -#if defined(VK_EXT_extended_dynamic_state3) -extern PFN_vkCmdSetAlphaToCoverageEnableEXT vkCmdSetAlphaToCoverageEnableEXT; -extern PFN_vkCmdSetAlphaToOneEnableEXT vkCmdSetAlphaToOneEnableEXT; -extern PFN_vkCmdSetColorBlendAdvancedEXT vkCmdSetColorBlendAdvancedEXT; -extern PFN_vkCmdSetColorBlendEnableEXT vkCmdSetColorBlendEnableEXT; -extern PFN_vkCmdSetColorBlendEquationEXT vkCmdSetColorBlendEquationEXT; -extern PFN_vkCmdSetColorWriteMaskEXT vkCmdSetColorWriteMaskEXT; -extern PFN_vkCmdSetConservativeRasterizationModeEXT vkCmdSetConservativeRasterizationModeEXT; -extern PFN_vkCmdSetCoverageModulationModeNV vkCmdSetCoverageModulationModeNV; -extern PFN_vkCmdSetCoverageModulationTableEnableNV vkCmdSetCoverageModulationTableEnableNV; -extern PFN_vkCmdSetCoverageModulationTableNV vkCmdSetCoverageModulationTableNV; -extern PFN_vkCmdSetCoverageReductionModeNV vkCmdSetCoverageReductionModeNV; -extern PFN_vkCmdSetCoverageToColorEnableNV vkCmdSetCoverageToColorEnableNV; -extern PFN_vkCmdSetCoverageToColorLocationNV vkCmdSetCoverageToColorLocationNV; -extern PFN_vkCmdSetDepthClampEnableEXT vkCmdSetDepthClampEnableEXT; -extern PFN_vkCmdSetDepthClipEnableEXT vkCmdSetDepthClipEnableEXT; -extern PFN_vkCmdSetDepthClipNegativeOneToOneEXT vkCmdSetDepthClipNegativeOneToOneEXT; -extern PFN_vkCmdSetExtraPrimitiveOverestimationSizeEXT vkCmdSetExtraPrimitiveOverestimationSizeEXT; -extern PFN_vkCmdSetLineRasterizationModeEXT vkCmdSetLineRasterizationModeEXT; -extern PFN_vkCmdSetLineStippleEnableEXT vkCmdSetLineStippleEnableEXT; -extern PFN_vkCmdSetLogicOpEnableEXT vkCmdSetLogicOpEnableEXT; -extern PFN_vkCmdSetPolygonModeEXT vkCmdSetPolygonModeEXT; -extern PFN_vkCmdSetProvokingVertexModeEXT vkCmdSetProvokingVertexModeEXT; -extern PFN_vkCmdSetRasterizationSamplesEXT vkCmdSetRasterizationSamplesEXT; -extern PFN_vkCmdSetRasterizationStreamEXT vkCmdSetRasterizationStreamEXT; -extern PFN_vkCmdSetRepresentativeFragmentTestEnableNV vkCmdSetRepresentativeFragmentTestEnableNV; -extern PFN_vkCmdSetSampleLocationsEnableEXT vkCmdSetSampleLocationsEnableEXT; -extern PFN_vkCmdSetSampleMaskEXT vkCmdSetSampleMaskEXT; -extern PFN_vkCmdSetShadingRateImageEnableNV vkCmdSetShadingRateImageEnableNV; -extern PFN_vkCmdSetTessellationDomainOriginEXT vkCmdSetTessellationDomainOriginEXT; -extern PFN_vkCmdSetViewportSwizzleNV vkCmdSetViewportSwizzleNV; -extern PFN_vkCmdSetViewportWScalingEnableNV vkCmdSetViewportWScalingEnableNV; -#endif /* defined(VK_EXT_extended_dynamic_state3) */ #if defined(VK_EXT_external_memory_host) extern PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesEXT; #endif /* defined(VK_EXT_external_memory_host) */ @@ -1313,6 +1284,12 @@ extern PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT vkGetPhysicalDeviceMultis extern PFN_vkGetShaderModuleCreateInfoIdentifierEXT vkGetShaderModuleCreateInfoIdentifierEXT; extern PFN_vkGetShaderModuleIdentifierEXT vkGetShaderModuleIdentifierEXT; #endif /* defined(VK_EXT_shader_module_identifier) */ +#if defined(VK_EXT_shader_object) +extern PFN_vkCmdBindShadersEXT vkCmdBindShadersEXT; +extern PFN_vkCreateShadersEXT vkCreateShadersEXT; +extern PFN_vkDestroyShaderEXT vkDestroyShaderEXT; +extern PFN_vkGetShaderBinaryDataEXT vkGetShaderBinaryDataEXT; +#endif /* defined(VK_EXT_shader_object) */ #if defined(VK_EXT_swapchain_maintenance1) extern PFN_vkReleaseSwapchainImagesEXT vkReleaseSwapchainImagesEXT; #endif /* defined(VK_EXT_swapchain_maintenance1) */ @@ -1333,9 +1310,6 @@ extern PFN_vkDestroyValidationCacheEXT vkDestroyValidationCacheEXT; extern PFN_vkGetValidationCacheDataEXT vkGetValidationCacheDataEXT; extern PFN_vkMergeValidationCachesEXT vkMergeValidationCachesEXT; #endif /* defined(VK_EXT_validation_cache) */ -#if defined(VK_EXT_vertex_input_dynamic_state) -extern PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT; -#endif /* defined(VK_EXT_vertex_input_dynamic_state) */ #if defined(VK_FUCHSIA_buffer_collection) extern PFN_vkCreateBufferCollectionFUCHSIA vkCreateBufferCollectionFUCHSIA; extern PFN_vkDestroyBufferCollectionFUCHSIA vkDestroyBufferCollectionFUCHSIA; @@ -1361,6 +1335,10 @@ extern PFN_vkCreateStreamDescriptorSurfaceGGP vkCreateStreamDescriptorSurfaceGGP extern PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE; extern PFN_vkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLE; #endif /* defined(VK_GOOGLE_display_timing) */ +#if defined(VK_HUAWEI_cluster_culling_shader) +extern PFN_vkCmdDrawClusterHUAWEI vkCmdDrawClusterHUAWEI; +extern PFN_vkCmdDrawClusterIndirectHUAWEI vkCmdDrawClusterIndirectHUAWEI; +#endif /* defined(VK_HUAWEI_cluster_culling_shader) */ #if defined(VK_HUAWEI_invocation_mask) extern PFN_vkCmdBindInvocationMaskHUAWEI vkCmdBindInvocationMaskHUAWEI; #endif /* defined(VK_HUAWEI_invocation_mask) */ @@ -1535,6 +1513,10 @@ extern PFN_vkGetDeviceBufferMemoryRequirementsKHR vkGetDeviceBufferMemoryRequire extern PFN_vkGetDeviceImageMemoryRequirementsKHR vkGetDeviceImageMemoryRequirementsKHR; extern PFN_vkGetDeviceImageSparseMemoryRequirementsKHR vkGetDeviceImageSparseMemoryRequirementsKHR; #endif /* defined(VK_KHR_maintenance4) */ +#if defined(VK_KHR_map_memory2) +extern PFN_vkMapMemory2KHR vkMapMemory2KHR; +extern PFN_vkUnmapMemory2KHR vkUnmapMemory2KHR; +#endif /* defined(VK_KHR_map_memory2) */ #if defined(VK_KHR_performance_query) extern PFN_vkAcquireProfilingLockKHR vkAcquireProfilingLockKHR; extern PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR; @@ -1731,6 +1713,9 @@ extern PFN_vkGetAccelerationStructureHandleNV vkGetAccelerationStructureHandleNV extern PFN_vkGetAccelerationStructureMemoryRequirementsNV vkGetAccelerationStructureMemoryRequirementsNV; extern PFN_vkGetRayTracingShaderGroupHandlesNV vkGetRayTracingShaderGroupHandlesNV; #endif /* defined(VK_NV_ray_tracing) */ +#if defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 +extern PFN_vkCmdSetExclusiveScissorEnableNV vkCmdSetExclusiveScissorEnableNV; +#endif /* defined(VK_NV_scissor_exclusive) && VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION >= 2 */ #if defined(VK_NV_scissor_exclusive) extern PFN_vkCmdSetExclusiveScissorNV vkCmdSetExclusiveScissorNV; #endif /* defined(VK_NV_scissor_exclusive) */ @@ -1751,9 +1736,66 @@ extern PFN_vkGetPhysicalDeviceScreenPresentationSupportQNX vkGetPhysicalDeviceSc extern PFN_vkGetDescriptorSetHostMappingVALVE vkGetDescriptorSetHostMappingVALVE; extern PFN_vkGetDescriptorSetLayoutHostMappingInfoVALVE vkGetDescriptorSetLayoutHostMappingInfoVALVE; #endif /* defined(VK_VALVE_descriptor_set_host_mapping) */ +#if (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) +extern PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT; +extern PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT; +extern PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT; +extern PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT; +extern PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT; +extern PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT; +extern PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT; +extern PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT; +extern PFN_vkCmdSetScissorWithCountEXT vkCmdSetScissorWithCountEXT; +extern PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT; +extern PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT; +extern PFN_vkCmdSetViewportWithCountEXT vkCmdSetViewportWithCountEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) +extern PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT; +extern PFN_vkCmdSetLogicOpEXT vkCmdSetLogicOpEXT; +extern PFN_vkCmdSetPatchControlPointsEXT vkCmdSetPatchControlPointsEXT; +extern PFN_vkCmdSetPrimitiveRestartEnableEXT vkCmdSetPrimitiveRestartEnableEXT; +extern PFN_vkCmdSetRasterizerDiscardEnableEXT vkCmdSetRasterizerDiscardEnableEXT; +#endif /* (defined(VK_EXT_extended_dynamic_state2)) || (defined(VK_EXT_shader_object)) */ +#if (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) +extern PFN_vkCmdSetAlphaToCoverageEnableEXT vkCmdSetAlphaToCoverageEnableEXT; +extern PFN_vkCmdSetAlphaToOneEnableEXT vkCmdSetAlphaToOneEnableEXT; +extern PFN_vkCmdSetColorBlendAdvancedEXT vkCmdSetColorBlendAdvancedEXT; +extern PFN_vkCmdSetColorBlendEnableEXT vkCmdSetColorBlendEnableEXT; +extern PFN_vkCmdSetColorBlendEquationEXT vkCmdSetColorBlendEquationEXT; +extern PFN_vkCmdSetColorWriteMaskEXT vkCmdSetColorWriteMaskEXT; +extern PFN_vkCmdSetConservativeRasterizationModeEXT vkCmdSetConservativeRasterizationModeEXT; +extern PFN_vkCmdSetCoverageModulationModeNV vkCmdSetCoverageModulationModeNV; +extern PFN_vkCmdSetCoverageModulationTableEnableNV vkCmdSetCoverageModulationTableEnableNV; +extern PFN_vkCmdSetCoverageModulationTableNV vkCmdSetCoverageModulationTableNV; +extern PFN_vkCmdSetCoverageReductionModeNV vkCmdSetCoverageReductionModeNV; +extern PFN_vkCmdSetCoverageToColorEnableNV vkCmdSetCoverageToColorEnableNV; +extern PFN_vkCmdSetCoverageToColorLocationNV vkCmdSetCoverageToColorLocationNV; +extern PFN_vkCmdSetDepthClampEnableEXT vkCmdSetDepthClampEnableEXT; +extern PFN_vkCmdSetDepthClipEnableEXT vkCmdSetDepthClipEnableEXT; +extern PFN_vkCmdSetDepthClipNegativeOneToOneEXT vkCmdSetDepthClipNegativeOneToOneEXT; +extern PFN_vkCmdSetExtraPrimitiveOverestimationSizeEXT vkCmdSetExtraPrimitiveOverestimationSizeEXT; +extern PFN_vkCmdSetLineRasterizationModeEXT vkCmdSetLineRasterizationModeEXT; +extern PFN_vkCmdSetLineStippleEnableEXT vkCmdSetLineStippleEnableEXT; +extern PFN_vkCmdSetLogicOpEnableEXT vkCmdSetLogicOpEnableEXT; +extern PFN_vkCmdSetPolygonModeEXT vkCmdSetPolygonModeEXT; +extern PFN_vkCmdSetProvokingVertexModeEXT vkCmdSetProvokingVertexModeEXT; +extern PFN_vkCmdSetRasterizationSamplesEXT vkCmdSetRasterizationSamplesEXT; +extern PFN_vkCmdSetRasterizationStreamEXT vkCmdSetRasterizationStreamEXT; +extern PFN_vkCmdSetRepresentativeFragmentTestEnableNV vkCmdSetRepresentativeFragmentTestEnableNV; +extern PFN_vkCmdSetSampleLocationsEnableEXT vkCmdSetSampleLocationsEnableEXT; +extern PFN_vkCmdSetSampleMaskEXT vkCmdSetSampleMaskEXT; +extern PFN_vkCmdSetShadingRateImageEnableNV vkCmdSetShadingRateImageEnableNV; +extern PFN_vkCmdSetTessellationDomainOriginEXT vkCmdSetTessellationDomainOriginEXT; +extern PFN_vkCmdSetViewportSwizzleNV vkCmdSetViewportSwizzleNV; +extern PFN_vkCmdSetViewportWScalingEnableNV vkCmdSetViewportWScalingEnableNV; +#endif /* (defined(VK_EXT_extended_dynamic_state3)) || (defined(VK_EXT_shader_object)) */ #if (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) extern PFN_vkGetDeviceGroupSurfacePresentModes2EXT vkGetDeviceGroupSurfacePresentModes2EXT; #endif /* (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) */ +#if (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) +extern PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT; +#endif /* (defined(VK_EXT_shader_object)) || (defined(VK_EXT_vertex_input_dynamic_state)) */ #if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) extern PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR; #endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) */ diff --git a/WickedEngine/Utility/vulkan/vk_icd.h b/WickedEngine/Utility/vulkan/vk_icd.h index 1133fa367..2cd6c3d33 100644 --- a/WickedEngine/Utility/vulkan/vk_icd.h +++ b/WickedEngine/Utility/vulkan/vk_icd.h @@ -78,7 +78,7 @@ extern "C" { #endif VKAPI_ATTR VkResult VKAPI_CALL vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pVersion); VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr(VkInstance instance, const char* pName); - VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetPhysicalDeviceProcAddr(VkInstance isntance, const char* pName); + VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetPhysicalDeviceProcAddr(VkInstance instance, const char* pName); #if defined(VK_USE_PLATFORM_WIN32_KHR) VKAPI_ATTR VkResult VKAPI_CALL vk_icdEnumerateAdapterPhysicalDevices(VkInstance instance, LUID adapterLUID, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices); diff --git a/WickedEngine/Utility/vulkan/vk_layer.h b/WickedEngine/Utility/vulkan/vk_layer.h index 6bd1c9a03..7954f71d8 100644 --- a/WickedEngine/Utility/vulkan/vk_layer.h +++ b/WickedEngine/Utility/vulkan/vk_layer.h @@ -28,14 +28,6 @@ #include "vulkan_core.h" -#if defined(__GNUC__) && __GNUC__ >= 4 -#define VK_LAYER_EXPORT __attribute__((visibility("default"))) -#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590) -#define VK_LAYER_EXPORT __attribute__((visibility("default"))) -#else -#define VK_LAYER_EXPORT -#endif - #define MAX_NUM_UNKNOWN_EXTS 250 // Loader-Layer version negotiation API. Versions add the following features: diff --git a/WickedEngine/Utility/vulkan/vk_platform.h b/WickedEngine/Utility/vulkan/vk_platform.h index 3ff8c5d14..ed67a6004 100644 --- a/WickedEngine/Utility/vulkan/vk_platform.h +++ b/WickedEngine/Utility/vulkan/vk_platform.h @@ -2,7 +2,7 @@ // File: vk_platform.h // /* -** Copyright 2014-2022 The Khronos Group Inc. +** Copyright 2014-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/WickedEngine/Utility/vk_video/vulkan_video_codec_h264std.h b/WickedEngine/Utility/vulkan/vk_video/vulkan_video_codec_h264std.h similarity index 99% rename from WickedEngine/Utility/vk_video/vulkan_video_codec_h264std.h rename to WickedEngine/Utility/vulkan/vk_video/vulkan_video_codec_h264std.h index d3ebec6a1..21c7b667f 100644 --- a/WickedEngine/Utility/vk_video/vulkan_video_codec_h264std.h +++ b/WickedEngine/Utility/vulkan/vk_video/vulkan_video_codec_h264std.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_H264STD_H_ 1 /* -** Copyright 2015-2022 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/WickedEngine/Utility/vk_video/vulkan_video_codec_h264std_decode.h b/WickedEngine/Utility/vulkan/vk_video/vulkan_video_codec_h264std_decode.h similarity index 98% rename from WickedEngine/Utility/vk_video/vulkan_video_codec_h264std_decode.h rename to WickedEngine/Utility/vulkan/vk_video/vulkan_video_codec_h264std_decode.h index b1e79429d..f7eb8edbd 100644 --- a/WickedEngine/Utility/vk_video/vulkan_video_codec_h264std_decode.h +++ b/WickedEngine/Utility/vulkan/vk_video/vulkan_video_codec_h264std_decode.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_H264STD_DECODE_H_ 1 /* -** Copyright 2015-2022 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/WickedEngine/Utility/vk_video/vulkan_video_codec_h264std_encode.h b/WickedEngine/Utility/vulkan/vk_video/vulkan_video_codec_h264std_encode.h similarity index 82% rename from WickedEngine/Utility/vk_video/vulkan_video_codec_h264std_encode.h rename to WickedEngine/Utility/vulkan/vk_video/vulkan_video_codec_h264std_encode.h index 7bd96aa7b..d4edb40ee 100644 --- a/WickedEngine/Utility/vk_video/vulkan_video_codec_h264std_encode.h +++ b/WickedEngine/Utility/vulkan/vk_video/vulkan_video_codec_h264std_encode.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_H264STD_ENCODE_H_ 1 /* -** Copyright 2015-2022 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -21,9 +21,9 @@ extern "C" { #define vulkan_video_codec_h264std_encode 1 // Vulkan 0.9 provisional Vulkan video H.264 encode std specification version number -#define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_API_VERSION_0_9_8 VK_MAKE_VIDEO_STD_VERSION(0, 9, 8) +#define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_API_VERSION_0_9_9 VK_MAKE_VIDEO_STD_VERSION(0, 9, 9) -#define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_API_VERSION_0_9_8 +#define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_API_VERSION_0_9_9 #define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h264_encode" typedef struct StdVideoEncodeH264WeightTableFlags { uint32_t luma_weight_l0_flag; @@ -64,10 +64,10 @@ typedef struct StdVideoEncodeH264ReferenceInfoFlags { uint32_t used_for_long_term_reference : 1; } StdVideoEncodeH264ReferenceInfoFlags; -typedef struct StdVideoEncodeH264RefMgmtFlags { - uint32_t ref_pic_list_modification_l0_flag : 1; - uint32_t ref_pic_list_modification_l1_flag : 1; -} StdVideoEncodeH264RefMgmtFlags; +typedef struct StdVideoEncodeH264ReferenceListsInfoFlags { + uint32_t ref_pic_list_modification_flag_l0 : 1; + uint32_t ref_pic_list_modification_flag_l1 : 1; +} StdVideoEncodeH264ReferenceListsInfoFlags; typedef struct StdVideoEncodeH264RefListModEntry { StdVideoH264ModificationOfPicNumsIdc modification_of_pic_nums_idc; @@ -83,20 +83,26 @@ typedef struct StdVideoEncodeH264RefPicMarkingEntry { uint16_t max_long_term_frame_idx_plus1; } StdVideoEncodeH264RefPicMarkingEntry; -typedef struct StdVideoEncodeH264RefMemMgmtCtrlOperations { - StdVideoEncodeH264RefMgmtFlags flags; +typedef struct StdVideoEncodeH264ReferenceListsInfo { + StdVideoEncodeH264ReferenceListsInfoFlags flags; + uint8_t refPicList0EntryCount; + uint8_t refPicList1EntryCount; uint8_t refList0ModOpCount; - const StdVideoEncodeH264RefListModEntry* pRefList0ModOperations; uint8_t refList1ModOpCount; - const StdVideoEncodeH264RefListModEntry* pRefList1ModOperations; uint8_t refPicMarkingOpCount; + uint8_t reserved1[7]; + const uint8_t* pRefPicList0Entries; + const uint8_t* pRefPicList1Entries; + const StdVideoEncodeH264RefListModEntry* pRefList0ModOperations; + const StdVideoEncodeH264RefListModEntry* pRefList1ModOperations; const StdVideoEncodeH264RefPicMarkingEntry* pRefPicMarkingOperations; -} StdVideoEncodeH264RefMemMgmtCtrlOperations; +} StdVideoEncodeH264ReferenceListsInfo; typedef struct StdVideoEncodeH264PictureInfo { StdVideoEncodeH264PictureInfoFlags flags; uint8_t seq_parameter_set_id; uint8_t pic_parameter_set_id; + uint16_t reserved1; StdVideoH264PictureType pictureType; uint32_t frame_num; int32_t PicOrderCnt; @@ -104,6 +110,7 @@ typedef struct StdVideoEncodeH264PictureInfo { typedef struct StdVideoEncodeH264ReferenceInfo { StdVideoEncodeH264ReferenceInfoFlags flags; + StdVideoH264PictureType pictureType; uint32_t FrameNum; int32_t PicOrderCnt; uint16_t long_term_pic_num; @@ -121,6 +128,8 @@ typedef struct StdVideoEncodeH264SliceHeader { StdVideoH264DisableDeblockingFilterIdc disable_deblocking_filter_idc; int8_t slice_alpha_c0_offset_div2; int8_t slice_beta_offset_div2; + uint16_t reserved1; + uint32_t reserved2; const StdVideoEncodeH264WeightTable* pWeightTable; } StdVideoEncodeH264SliceHeader; diff --git a/WickedEngine/Utility/vk_video/vulkan_video_codec_h265std.h b/WickedEngine/Utility/vulkan/vk_video/vulkan_video_codec_h265std.h similarity index 99% rename from WickedEngine/Utility/vk_video/vulkan_video_codec_h265std.h rename to WickedEngine/Utility/vulkan/vk_video/vulkan_video_codec_h265std.h index 862f8817f..4233bdc89 100644 --- a/WickedEngine/Utility/vk_video/vulkan_video_codec_h265std.h +++ b/WickedEngine/Utility/vulkan/vk_video/vulkan_video_codec_h265std.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_H265STD_H_ 1 /* -** Copyright 2015-2022 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/WickedEngine/Utility/vk_video/vulkan_video_codec_h265std_decode.h b/WickedEngine/Utility/vulkan/vk_video/vulkan_video_codec_h265std_decode.h similarity index 97% rename from WickedEngine/Utility/vk_video/vulkan_video_codec_h265std_decode.h rename to WickedEngine/Utility/vulkan/vk_video/vulkan_video_codec_h265std_decode.h index d8660d12e..7eee9b389 100644 --- a/WickedEngine/Utility/vk_video/vulkan_video_codec_h265std_decode.h +++ b/WickedEngine/Utility/vulkan/vk_video/vulkan_video_codec_h265std_decode.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_H265STD_DECODE_H_ 1 /* -** Copyright 2015-2022 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/WickedEngine/Utility/vk_video/vulkan_video_codec_h265std_encode.h b/WickedEngine/Utility/vulkan/vk_video/vulkan_video_codec_h265std_encode.h similarity index 86% rename from WickedEngine/Utility/vk_video/vulkan_video_codec_h265std_encode.h rename to WickedEngine/Utility/vulkan/vk_video/vulkan_video_codec_h265std_encode.h index 5a419b14b..1a42b95e0 100644 --- a/WickedEngine/Utility/vk_video/vulkan_video_codec_h265std_encode.h +++ b/WickedEngine/Utility/vulkan/vk_video/vulkan_video_codec_h265std_encode.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_H265STD_ENCODE_H_ 1 /* -** Copyright 2015-2022 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -21,9 +21,9 @@ extern "C" { #define vulkan_video_codec_h265std_encode 1 // Vulkan 0.9 provisional Vulkan video H.265 encode std specification version number -#define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_API_VERSION_0_9_9 VK_MAKE_VIDEO_STD_VERSION(0, 9, 9) +#define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_API_VERSION_0_9_10 VK_MAKE_VIDEO_STD_VERSION(0, 9, 10) -#define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_API_VERSION_0_9_9 +#define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_API_VERSION_0_9_10 #define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h265_encode" typedef struct StdVideoEncodeH265WeightTableFlags { uint16_t luma_weight_l0_flag; @@ -96,18 +96,21 @@ typedef struct StdVideoEncodeH265SliceSegmentHeader { const StdVideoEncodeH265WeightTable* pWeightTable; } StdVideoEncodeH265SliceSegmentHeader; -typedef struct StdVideoEncodeH265ReferenceModificationFlags { +typedef struct StdVideoEncodeH265ReferenceListsInfoFlags { uint32_t ref_pic_list_modification_flag_l0 : 1; uint32_t ref_pic_list_modification_flag_l1 : 1; -} StdVideoEncodeH265ReferenceModificationFlags; +} StdVideoEncodeH265ReferenceListsInfoFlags; -typedef struct StdVideoEncodeH265ReferenceModifications { - StdVideoEncodeH265ReferenceModificationFlags flags; - uint8_t referenceList0ModificationsCount; - const uint8_t* pReferenceList0Modifications; - uint8_t referenceList1ModificationsCount; - const uint8_t* pReferenceList1Modifications; -} StdVideoEncodeH265ReferenceModifications; +typedef struct StdVideoEncodeH265ReferenceListsInfo { + StdVideoEncodeH265ReferenceListsInfoFlags flags; + uint8_t num_ref_idx_l0_active_minus1; + uint8_t num_ref_idx_l1_active_minus1; + uint16_t reserved1; + const uint8_t* pRefPicList0Entries; + const uint8_t* pRefPicList1Entries; + const uint8_t* pRefList0Modifications; + const uint8_t* pRefList1Modifications; +} StdVideoEncodeH265ReferenceListsInfo; typedef struct StdVideoEncodeH265PictureInfoFlags { uint32_t is_reference_flag : 1; @@ -123,8 +126,8 @@ typedef struct StdVideoEncodeH265PictureInfo { uint8_t sps_video_parameter_set_id; uint8_t pps_seq_parameter_set_id; uint8_t pps_pic_parameter_set_id; - int32_t PicOrderCntVal; uint8_t TemporalId; + int32_t PicOrderCntVal; } StdVideoEncodeH265PictureInfo; typedef struct StdVideoEncodeH265ReferenceInfoFlags { @@ -134,6 +137,7 @@ typedef struct StdVideoEncodeH265ReferenceInfoFlags { typedef struct StdVideoEncodeH265ReferenceInfo { StdVideoEncodeH265ReferenceInfoFlags flags; + StdVideoH265PictureType PictureType; int32_t PicOrderCntVal; uint8_t TemporalId; } StdVideoEncodeH265ReferenceInfo; diff --git a/WickedEngine/Utility/vk_video/vulkan_video_codecs_common.h b/WickedEngine/Utility/vulkan/vk_video/vulkan_video_codecs_common.h similarity index 91% rename from WickedEngine/Utility/vk_video/vulkan_video_codecs_common.h rename to WickedEngine/Utility/vulkan/vk_video/vulkan_video_codecs_common.h index 1e498265e..f486d3ca3 100644 --- a/WickedEngine/Utility/vk_video/vulkan_video_codecs_common.h +++ b/WickedEngine/Utility/vulkan/vk_video/vulkan_video_codecs_common.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODECS_COMMON_H_ 1 /* -** Copyright 2015-2022 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/WickedEngine/Utility/vulkan/vulkan.h b/WickedEngine/Utility/vulkan/vulkan.h index 3510ac912..426cff58d 100644 --- a/WickedEngine/Utility/vulkan/vulkan.h +++ b/WickedEngine/Utility/vulkan/vulkan.h @@ -2,7 +2,7 @@ #define VULKAN_H_ 1 /* -** Copyright 2015-2022 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -84,6 +84,14 @@ #include "vulkan_screen.h" #endif + +#ifdef VK_USE_PLATFORM_SCI +#include +#include +#include "vulkan_sci.h" +#endif + + #ifdef VK_ENABLE_BETA_EXTENSIONS #include "vulkan_beta.h" #endif diff --git a/WickedEngine/Utility/vulkan/vulkan_android.h b/WickedEngine/Utility/vulkan/vulkan_android.h index 11f539796..2e1dfa9ba 100644 --- a/WickedEngine/Utility/vulkan/vulkan_android.h +++ b/WickedEngine/Utility/vulkan/vulkan_android.h @@ -2,7 +2,7 @@ #define VULKAN_ANDROID_H_ 1 /* -** Copyright 2015-2022 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/WickedEngine/Utility/vulkan/vulkan_beta.h b/WickedEngine/Utility/vulkan/vulkan_beta.h index cfeda0eb3..b0729cc37 100644 --- a/WickedEngine/Utility/vulkan/vulkan_beta.h +++ b/WickedEngine/Utility/vulkan/vulkan_beta.h @@ -2,7 +2,7 @@ #define VULKAN_BETA_H_ 1 /* -** Copyright 2015-2022 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -51,7 +51,7 @@ typedef struct VkPhysicalDevicePortabilitySubsetPropertiesKHR { #define VK_KHR_video_encode_queue 1 -#define VK_KHR_VIDEO_ENCODE_QUEUE_SPEC_VERSION 7 +#define VK_KHR_VIDEO_ENCODE_QUEUE_SPEC_VERSION 8 #define VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME "VK_KHR_video_encode_queue" typedef enum VkVideoEncodeTuningModeKHR { @@ -71,13 +71,21 @@ typedef enum VkVideoEncodeCapabilityFlagBitsKHR { typedef VkFlags VkVideoEncodeCapabilityFlagsKHR; typedef enum VkVideoEncodeRateControlModeFlagBitsKHR { - VK_VIDEO_ENCODE_RATE_CONTROL_MODE_NONE_BIT_KHR = 0, - VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR = 1, - VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR = 2, + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DEFAULT_KHR = 0, + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR = 0x00000004, VK_VIDEO_ENCODE_RATE_CONTROL_MODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkVideoEncodeRateControlModeFlagBitsKHR; typedef VkFlags VkVideoEncodeRateControlModeFlagsKHR; +typedef enum VkVideoEncodeFeedbackFlagBitsKHR { + VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_FEEDBACK_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeFeedbackFlagBitsKHR; +typedef VkFlags VkVideoEncodeFeedbackFlagsKHR; + typedef enum VkVideoEncodeUsageFlagBitsKHR { VK_VIDEO_ENCODE_USAGE_DEFAULT_KHR = 0, VK_VIDEO_ENCODE_USAGE_TRANSCODING_BIT_KHR = 0x00000001, @@ -102,9 +110,9 @@ typedef struct VkVideoEncodeInfoKHR { const void* pNext; VkVideoEncodeFlagsKHR flags; uint32_t qualityLevel; - VkBuffer dstBitstreamBuffer; - VkDeviceSize dstBitstreamBufferOffset; - VkDeviceSize dstBitstreamBufferMaxRange; + VkBuffer dstBuffer; + VkDeviceSize dstBufferOffset; + VkDeviceSize dstBufferRange; VkVideoPictureResourceInfoKHR srcPictureResource; const VkVideoReferenceSlotInfoKHR* pSetupReferenceSlot; uint32_t referenceSlotCount; @@ -117,11 +125,18 @@ typedef struct VkVideoEncodeCapabilitiesKHR { void* pNext; VkVideoEncodeCapabilityFlagsKHR flags; VkVideoEncodeRateControlModeFlagsKHR rateControlModes; - uint8_t rateControlLayerCount; - uint8_t qualityLevelCount; + uint32_t maxRateControlLayers; + uint32_t maxQualityLevels; VkExtent2D inputImageDataFillAlignment; + VkVideoEncodeFeedbackFlagsKHR supportedEncodeFeedbackFlags; } VkVideoEncodeCapabilitiesKHR; +typedef struct VkQueryPoolVideoEncodeFeedbackCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoEncodeFeedbackFlagsKHR encodeFeedbackFlags; +} VkQueryPoolVideoEncodeFeedbackCreateInfoKHR; + typedef struct VkVideoEncodeUsageInfoKHR { VkStructureType sType; const void* pNext; @@ -133,8 +148,8 @@ typedef struct VkVideoEncodeUsageInfoKHR { typedef struct VkVideoEncodeRateControlLayerInfoKHR { VkStructureType sType; const void* pNext; - uint32_t averageBitrate; - uint32_t maxBitrate; + uint64_t averageBitrate; + uint64_t maxBitrate; uint32_t frameRateNumerator; uint32_t frameRateDenominator; uint32_t virtualBufferSizeInMs; @@ -146,8 +161,8 @@ typedef struct VkVideoEncodeRateControlInfoKHR { const void* pNext; VkVideoEncodeRateControlFlagsKHR flags; VkVideoEncodeRateControlModeFlagBitsKHR rateControlMode; - uint8_t layerCount; - const VkVideoEncodeRateControlLayerInfoKHR* pLayerConfigs; + uint32_t layerCount; + const VkVideoEncodeRateControlLayerInfoKHR* pLayers; } VkVideoEncodeRateControlInfoKHR; typedef void (VKAPI_PTR *PFN_vkCmdEncodeVideoKHR)(VkCommandBuffer commandBuffer, const VkVideoEncodeInfoKHR* pEncodeInfo); @@ -162,7 +177,7 @@ VKAPI_ATTR void VKAPI_CALL vkCmdEncodeVideoKHR( #define VK_EXT_video_encode_h264 1 #include "vk_video/vulkan_video_codec_h264std.h" #include "vk_video/vulkan_video_codec_h264std_encode.h" -#define VK_EXT_VIDEO_ENCODE_H264_SPEC_VERSION 9 +#define VK_EXT_VIDEO_ENCODE_H264_SPEC_VERSION 10 #define VK_EXT_VIDEO_ENCODE_H264_EXTENSION_NAME "VK_EXT_video_encode_h264" typedef enum VkVideoEncodeH264RateControlStructureEXT { @@ -198,34 +213,17 @@ typedef enum VkVideoEncodeH264CapabilityFlagBitsEXT { VK_VIDEO_ENCODE_H264_CAPABILITY_ROW_UNALIGNED_SLICE_BIT_EXT = 0x00400000, VK_VIDEO_ENCODE_H264_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_EXT = 0x00800000, VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_EXT = 0x01000000, + VK_VIDEO_ENCODE_H264_CAPABILITY_DIFFERENT_REFERENCE_FINAL_LISTS_BIT_EXT = 0x02000000, VK_VIDEO_ENCODE_H264_CAPABILITY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF } VkVideoEncodeH264CapabilityFlagBitsEXT; typedef VkFlags VkVideoEncodeH264CapabilityFlagsEXT; - -typedef enum VkVideoEncodeH264InputModeFlagBitsEXT { - VK_VIDEO_ENCODE_H264_INPUT_MODE_FRAME_BIT_EXT = 0x00000001, - VK_VIDEO_ENCODE_H264_INPUT_MODE_SLICE_BIT_EXT = 0x00000002, - VK_VIDEO_ENCODE_H264_INPUT_MODE_NON_VCL_BIT_EXT = 0x00000004, - VK_VIDEO_ENCODE_H264_INPUT_MODE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkVideoEncodeH264InputModeFlagBitsEXT; -typedef VkFlags VkVideoEncodeH264InputModeFlagsEXT; - -typedef enum VkVideoEncodeH264OutputModeFlagBitsEXT { - VK_VIDEO_ENCODE_H264_OUTPUT_MODE_FRAME_BIT_EXT = 0x00000001, - VK_VIDEO_ENCODE_H264_OUTPUT_MODE_SLICE_BIT_EXT = 0x00000002, - VK_VIDEO_ENCODE_H264_OUTPUT_MODE_NON_VCL_BIT_EXT = 0x00000004, - VK_VIDEO_ENCODE_H264_OUTPUT_MODE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkVideoEncodeH264OutputModeFlagBitsEXT; -typedef VkFlags VkVideoEncodeH264OutputModeFlagsEXT; typedef struct VkVideoEncodeH264CapabilitiesEXT { VkStructureType sType; void* pNext; VkVideoEncodeH264CapabilityFlagsEXT flags; - VkVideoEncodeH264InputModeFlagsEXT inputModeFlags; - VkVideoEncodeH264OutputModeFlagsEXT outputModeFlags; - uint8_t maxPPictureL0ReferenceCount; - uint8_t maxBPictureL0ReferenceCount; - uint8_t maxL1ReferenceCount; + uint32_t maxPPictureL0ReferenceCount; + uint32_t maxBPictureL0ReferenceCount; + uint32_t maxL1ReferenceCount; VkBool32 motionVectorsOverPicBoundariesFlag; uint32_t maxBytesPerPicDenom; uint32_t maxBitsPerMbDenom; @@ -250,48 +248,28 @@ typedef struct VkVideoEncodeH264SessionParametersCreateInfoEXT { const VkVideoEncodeH264SessionParametersAddInfoEXT* pParametersAddInfo; } VkVideoEncodeH264SessionParametersCreateInfoEXT; -typedef struct VkVideoEncodeH264DpbSlotInfoEXT { - VkStructureType sType; - const void* pNext; - int8_t slotIndex; - const StdVideoEncodeH264ReferenceInfo* pStdReferenceInfo; -} VkVideoEncodeH264DpbSlotInfoEXT; - -typedef struct VkVideoEncodeH264ReferenceListsInfoEXT { - VkStructureType sType; - const void* pNext; - uint8_t referenceList0EntryCount; - const VkVideoEncodeH264DpbSlotInfoEXT* pReferenceList0Entries; - uint8_t referenceList1EntryCount; - const VkVideoEncodeH264DpbSlotInfoEXT* pReferenceList1Entries; - const StdVideoEncodeH264RefMemMgmtCtrlOperations* pMemMgmtCtrlOperations; -} VkVideoEncodeH264ReferenceListsInfoEXT; - typedef struct VkVideoEncodeH264NaluSliceInfoEXT { - VkStructureType sType; - const void* pNext; - uint32_t mbCount; - const VkVideoEncodeH264ReferenceListsInfoEXT* pReferenceFinalLists; - const StdVideoEncodeH264SliceHeader* pSliceHeaderStd; + VkStructureType sType; + const void* pNext; + uint32_t mbCount; + const StdVideoEncodeH264ReferenceListsInfo* pStdReferenceFinalLists; + const StdVideoEncodeH264SliceHeader* pStdSliceHeader; } VkVideoEncodeH264NaluSliceInfoEXT; typedef struct VkVideoEncodeH264VclFrameInfoEXT { - VkStructureType sType; - const void* pNext; - const VkVideoEncodeH264ReferenceListsInfoEXT* pReferenceFinalLists; - uint32_t naluSliceEntryCount; - const VkVideoEncodeH264NaluSliceInfoEXT* pNaluSliceEntries; - const StdVideoEncodeH264PictureInfo* pCurrentPictureInfo; + VkStructureType sType; + const void* pNext; + const StdVideoEncodeH264ReferenceListsInfo* pStdReferenceFinalLists; + uint32_t naluSliceEntryCount; + const VkVideoEncodeH264NaluSliceInfoEXT* pNaluSliceEntries; + const StdVideoEncodeH264PictureInfo* pStdPictureInfo; } VkVideoEncodeH264VclFrameInfoEXT; -typedef struct VkVideoEncodeH264EmitPictureParametersInfoEXT { - VkStructureType sType; - const void* pNext; - uint8_t spsId; - VkBool32 emitSpsEnable; - uint32_t ppsIdEntryCount; - const uint8_t* ppsIdEntries; -} VkVideoEncodeH264EmitPictureParametersInfoEXT; +typedef struct VkVideoEncodeH264DpbSlotInfoEXT { + VkStructureType sType; + const void* pNext; + const StdVideoEncodeH264ReferenceInfo* pStdReferenceInfo; +} VkVideoEncodeH264DpbSlotInfoEXT; typedef struct VkVideoEncodeH264ProfileInfoEXT { VkStructureType sType; @@ -306,7 +284,7 @@ typedef struct VkVideoEncodeH264RateControlInfoEXT { uint32_t idrPeriod; uint32_t consecutiveBFrameCount; VkVideoEncodeH264RateControlStructureEXT rateControlStructure; - uint8_t temporalLayerCount; + uint32_t temporalLayerCount; } VkVideoEncodeH264RateControlInfoEXT; typedef struct VkVideoEncodeH264QpEXT { @@ -324,7 +302,7 @@ typedef struct VkVideoEncodeH264FrameSizeEXT { typedef struct VkVideoEncodeH264RateControlLayerInfoEXT { VkStructureType sType; const void* pNext; - uint8_t temporalLayerId; + uint32_t temporalLayerId; VkBool32 useInitialRcQp; VkVideoEncodeH264QpEXT initialRcQp; VkBool32 useMinQp; @@ -340,7 +318,7 @@ typedef struct VkVideoEncodeH264RateControlLayerInfoEXT { #define VK_EXT_video_encode_h265 1 #include "vk_video/vulkan_video_codec_h265std.h" #include "vk_video/vulkan_video_codec_h265std_encode.h" -#define VK_EXT_VIDEO_ENCODE_H265_SPEC_VERSION 9 +#define VK_EXT_VIDEO_ENCODE_H265_SPEC_VERSION 10 #define VK_EXT_VIDEO_ENCODE_H265_EXTENSION_NAME "VK_EXT_video_encode_h265" typedef enum VkVideoEncodeH265RateControlStructureEXT { @@ -377,26 +355,11 @@ typedef enum VkVideoEncodeH265CapabilityFlagBitsEXT { VK_VIDEO_ENCODE_H265_CAPABILITY_DEPENDENT_SLICE_SEGMENT_BIT_EXT = 0x00800000, VK_VIDEO_ENCODE_H265_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_EXT = 0x01000000, VK_VIDEO_ENCODE_H265_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_EXT = 0x02000000, + VK_VIDEO_ENCODE_H265_CAPABILITY_DIFFERENT_REFERENCE_FINAL_LISTS_BIT_EXT = 0x04000000, VK_VIDEO_ENCODE_H265_CAPABILITY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF } VkVideoEncodeH265CapabilityFlagBitsEXT; typedef VkFlags VkVideoEncodeH265CapabilityFlagsEXT; -typedef enum VkVideoEncodeH265InputModeFlagBitsEXT { - VK_VIDEO_ENCODE_H265_INPUT_MODE_FRAME_BIT_EXT = 0x00000001, - VK_VIDEO_ENCODE_H265_INPUT_MODE_SLICE_SEGMENT_BIT_EXT = 0x00000002, - VK_VIDEO_ENCODE_H265_INPUT_MODE_NON_VCL_BIT_EXT = 0x00000004, - VK_VIDEO_ENCODE_H265_INPUT_MODE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkVideoEncodeH265InputModeFlagBitsEXT; -typedef VkFlags VkVideoEncodeH265InputModeFlagsEXT; - -typedef enum VkVideoEncodeH265OutputModeFlagBitsEXT { - VK_VIDEO_ENCODE_H265_OUTPUT_MODE_FRAME_BIT_EXT = 0x00000001, - VK_VIDEO_ENCODE_H265_OUTPUT_MODE_SLICE_SEGMENT_BIT_EXT = 0x00000002, - VK_VIDEO_ENCODE_H265_OUTPUT_MODE_NON_VCL_BIT_EXT = 0x00000004, - VK_VIDEO_ENCODE_H265_OUTPUT_MODE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkVideoEncodeH265OutputModeFlagBitsEXT; -typedef VkFlags VkVideoEncodeH265OutputModeFlagsEXT; - typedef enum VkVideoEncodeH265CtbSizeFlagBitsEXT { VK_VIDEO_ENCODE_H265_CTB_SIZE_16_BIT_EXT = 0x00000001, VK_VIDEO_ENCODE_H265_CTB_SIZE_32_BIT_EXT = 0x00000002, @@ -417,25 +380,23 @@ typedef struct VkVideoEncodeH265CapabilitiesEXT { VkStructureType sType; void* pNext; VkVideoEncodeH265CapabilityFlagsEXT flags; - VkVideoEncodeH265InputModeFlagsEXT inputModeFlags; - VkVideoEncodeH265OutputModeFlagsEXT outputModeFlags; VkVideoEncodeH265CtbSizeFlagsEXT ctbSizes; VkVideoEncodeH265TransformBlockSizeFlagsEXT transformBlockSizes; - uint8_t maxPPictureL0ReferenceCount; - uint8_t maxBPictureL0ReferenceCount; - uint8_t maxL1ReferenceCount; - uint8_t maxSubLayersCount; - uint8_t minLog2MinLumaCodingBlockSizeMinus3; - uint8_t maxLog2MinLumaCodingBlockSizeMinus3; - uint8_t minLog2MinLumaTransformBlockSizeMinus2; - uint8_t maxLog2MinLumaTransformBlockSizeMinus2; - uint8_t minMaxTransformHierarchyDepthInter; - uint8_t maxMaxTransformHierarchyDepthInter; - uint8_t minMaxTransformHierarchyDepthIntra; - uint8_t maxMaxTransformHierarchyDepthIntra; - uint8_t maxDiffCuQpDeltaDepth; - uint8_t minMaxNumMergeCand; - uint8_t maxMaxNumMergeCand; + uint32_t maxPPictureL0ReferenceCount; + uint32_t maxBPictureL0ReferenceCount; + uint32_t maxL1ReferenceCount; + uint32_t maxSubLayersCount; + uint32_t minLog2MinLumaCodingBlockSizeMinus3; + uint32_t maxLog2MinLumaCodingBlockSizeMinus3; + uint32_t minLog2MinLumaTransformBlockSizeMinus2; + uint32_t maxLog2MinLumaTransformBlockSizeMinus2; + uint32_t minMaxTransformHierarchyDepthInter; + uint32_t maxMaxTransformHierarchyDepthInter; + uint32_t minMaxTransformHierarchyDepthIntra; + uint32_t maxMaxTransformHierarchyDepthIntra; + uint32_t maxDiffCuQpDeltaDepth; + uint32_t minMaxNumMergeCand; + uint32_t maxMaxNumMergeCand; } VkVideoEncodeH265CapabilitiesEXT; typedef struct VkVideoEncodeH265SessionParametersAddInfoEXT { @@ -458,50 +419,28 @@ typedef struct VkVideoEncodeH265SessionParametersCreateInfoEXT { const VkVideoEncodeH265SessionParametersAddInfoEXT* pParametersAddInfo; } VkVideoEncodeH265SessionParametersCreateInfoEXT; -typedef struct VkVideoEncodeH265DpbSlotInfoEXT { - VkStructureType sType; - const void* pNext; - int8_t slotIndex; - const StdVideoEncodeH265ReferenceInfo* pStdReferenceInfo; -} VkVideoEncodeH265DpbSlotInfoEXT; - -typedef struct VkVideoEncodeH265ReferenceListsInfoEXT { - VkStructureType sType; - const void* pNext; - uint8_t referenceList0EntryCount; - const VkVideoEncodeH265DpbSlotInfoEXT* pReferenceList0Entries; - uint8_t referenceList1EntryCount; - const VkVideoEncodeH265DpbSlotInfoEXT* pReferenceList1Entries; - const StdVideoEncodeH265ReferenceModifications* pReferenceModifications; -} VkVideoEncodeH265ReferenceListsInfoEXT; - typedef struct VkVideoEncodeH265NaluSliceSegmentInfoEXT { - VkStructureType sType; - const void* pNext; - uint32_t ctbCount; - const VkVideoEncodeH265ReferenceListsInfoEXT* pReferenceFinalLists; - const StdVideoEncodeH265SliceSegmentHeader* pSliceSegmentHeaderStd; + VkStructureType sType; + const void* pNext; + uint32_t ctbCount; + const StdVideoEncodeH265ReferenceListsInfo* pStdReferenceFinalLists; + const StdVideoEncodeH265SliceSegmentHeader* pStdSliceSegmentHeader; } VkVideoEncodeH265NaluSliceSegmentInfoEXT; typedef struct VkVideoEncodeH265VclFrameInfoEXT { VkStructureType sType; const void* pNext; - const VkVideoEncodeH265ReferenceListsInfoEXT* pReferenceFinalLists; + const StdVideoEncodeH265ReferenceListsInfo* pStdReferenceFinalLists; uint32_t naluSliceSegmentEntryCount; const VkVideoEncodeH265NaluSliceSegmentInfoEXT* pNaluSliceSegmentEntries; - const StdVideoEncodeH265PictureInfo* pCurrentPictureInfo; + const StdVideoEncodeH265PictureInfo* pStdPictureInfo; } VkVideoEncodeH265VclFrameInfoEXT; -typedef struct VkVideoEncodeH265EmitPictureParametersInfoEXT { - VkStructureType sType; - const void* pNext; - uint8_t vpsId; - uint8_t spsId; - VkBool32 emitVpsEnable; - VkBool32 emitSpsEnable; - uint32_t ppsIdEntryCount; - const uint8_t* ppsIdEntries; -} VkVideoEncodeH265EmitPictureParametersInfoEXT; +typedef struct VkVideoEncodeH265DpbSlotInfoEXT { + VkStructureType sType; + const void* pNext; + const StdVideoEncodeH265ReferenceInfo* pStdReferenceInfo; +} VkVideoEncodeH265DpbSlotInfoEXT; typedef struct VkVideoEncodeH265ProfileInfoEXT { VkStructureType sType; @@ -516,7 +455,7 @@ typedef struct VkVideoEncodeH265RateControlInfoEXT { uint32_t idrPeriod; uint32_t consecutiveBFrameCount; VkVideoEncodeH265RateControlStructureEXT rateControlStructure; - uint8_t subLayerCount; + uint32_t subLayerCount; } VkVideoEncodeH265RateControlInfoEXT; typedef struct VkVideoEncodeH265QpEXT { @@ -534,7 +473,7 @@ typedef struct VkVideoEncodeH265FrameSizeEXT { typedef struct VkVideoEncodeH265RateControlLayerInfoEXT { VkStructureType sType; const void* pNext; - uint8_t temporalId; + uint32_t temporalId; VkBool32 useInitialRcQp; VkVideoEncodeH265QpEXT initialRcQp; VkBool32 useMinQp; @@ -546,6 +485,51 @@ typedef struct VkVideoEncodeH265RateControlLayerInfoEXT { } VkVideoEncodeH265RateControlLayerInfoEXT; + +#define VK_NV_displacement_micromap 1 +#define VK_NV_DISPLACEMENT_MICROMAP_SPEC_VERSION 1 +#define VK_NV_DISPLACEMENT_MICROMAP_EXTENSION_NAME "VK_NV_displacement_micromap" + +typedef enum VkDisplacementMicromapFormatNV { + VK_DISPLACEMENT_MICROMAP_FORMAT_64_TRIANGLES_64_BYTES_NV = 1, + VK_DISPLACEMENT_MICROMAP_FORMAT_256_TRIANGLES_128_BYTES_NV = 2, + VK_DISPLACEMENT_MICROMAP_FORMAT_1024_TRIANGLES_128_BYTES_NV = 3, + VK_DISPLACEMENT_MICROMAP_FORMAT_MAX_ENUM_NV = 0x7FFFFFFF +} VkDisplacementMicromapFormatNV; +typedef struct VkPhysicalDeviceDisplacementMicromapFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 displacementMicromap; +} VkPhysicalDeviceDisplacementMicromapFeaturesNV; + +typedef struct VkPhysicalDeviceDisplacementMicromapPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t maxDisplacementMicromapSubdivisionLevel; +} VkPhysicalDeviceDisplacementMicromapPropertiesNV; + +typedef struct VkAccelerationStructureTrianglesDisplacementMicromapNV { + VkStructureType sType; + void* pNext; + VkFormat displacementBiasAndScaleFormat; + VkFormat displacementVectorFormat; + VkDeviceOrHostAddressConstKHR displacementBiasAndScaleBuffer; + VkDeviceSize displacementBiasAndScaleStride; + VkDeviceOrHostAddressConstKHR displacementVectorBuffer; + VkDeviceSize displacementVectorStride; + VkDeviceOrHostAddressConstKHR displacedMicromapPrimitiveFlags; + VkDeviceSize displacedMicromapPrimitiveFlagsStride; + VkIndexType indexType; + VkDeviceOrHostAddressConstKHR indexBuffer; + VkDeviceSize indexStride; + uint32_t baseTriangle; + uint32_t usageCountsCount; + const VkMicromapUsageEXT* pUsageCounts; + const VkMicromapUsageEXT* const* ppUsageCounts; + VkMicromapEXT micromap; +} VkAccelerationStructureTrianglesDisplacementMicromapNV; + + #ifdef __cplusplus } #endif diff --git a/WickedEngine/Utility/vulkan/vulkan_core.h b/WickedEngine/Utility/vulkan/vulkan_core.h index bed57387b..22cb0911a 100644 --- a/WickedEngine/Utility/vulkan/vulkan_core.h +++ b/WickedEngine/Utility/vulkan/vulkan_core.h @@ -2,7 +2,7 @@ #define VULKAN_CORE_H_ 1 /* -** Copyright 2015-2022 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -58,37 +58,37 @@ extern "C" { #endif #endif -// DEPRECATED: This define is deprecated. VK_MAKE_API_VERSION should be used instead. -#define VK_MAKE_VERSION(major, minor, patch) \ - ((((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch))) +#define VK_MAKE_API_VERSION(variant, major, minor, patch) \ + ((((uint32_t)(variant)) << 29U) | (((uint32_t)(major)) << 22U) | (((uint32_t)(minor)) << 12U) | ((uint32_t)(patch))) // DEPRECATED: This define has been removed. Specific version defines (e.g. VK_API_VERSION_1_0), or the VK_MAKE_VERSION macro, should be used instead. -//#define VK_API_VERSION VK_MAKE_VERSION(1, 0, 0) // Patch version should always be set to 0 - -#define VK_MAKE_API_VERSION(variant, major, minor, patch) \ - ((((uint32_t)(variant)) << 29) | (((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch))) +//#define VK_API_VERSION VK_MAKE_API_VERSION(0, 1, 0, 0) // Patch version should always be set to 0 // Vulkan 1.0 version number #define VK_API_VERSION_1_0 VK_MAKE_API_VERSION(0, 1, 0, 0)// Patch version should always be set to 0 // Version of this file -#define VK_HEADER_VERSION 238 +#define VK_HEADER_VERSION 249 // Complete version of this file #define VK_HEADER_VERSION_COMPLETE VK_MAKE_API_VERSION(0, 1, 3, VK_HEADER_VERSION) +// DEPRECATED: This define is deprecated. VK_MAKE_API_VERSION should be used instead. +#define VK_MAKE_VERSION(major, minor, patch) \ + ((((uint32_t)(major)) << 22U) | (((uint32_t)(minor)) << 12U) | ((uint32_t)(patch))) + // DEPRECATED: This define is deprecated. VK_API_VERSION_MAJOR should be used instead. -#define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22) +#define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22U) // DEPRECATED: This define is deprecated. VK_API_VERSION_MINOR should be used instead. -#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3FFU) +#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12U) & 0x3FFU) // DEPRECATED: This define is deprecated. VK_API_VERSION_PATCH should be used instead. #define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU) -#define VK_API_VERSION_VARIANT(version) ((uint32_t)(version) >> 29) -#define VK_API_VERSION_MAJOR(version) (((uint32_t)(version) >> 22) & 0x7FU) -#define VK_API_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3FFU) +#define VK_API_VERSION_VARIANT(version) ((uint32_t)(version) >> 29U) +#define VK_API_VERSION_MAJOR(version) (((uint32_t)(version) >> 22U) & 0x7FU) +#define VK_API_VERSION_MINOR(version) (((uint32_t)(version) >> 12U) & 0x3FFU) #define VK_API_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU) typedef uint32_t VkBool32; typedef uint64_t VkDeviceAddress; @@ -181,7 +181,11 @@ typedef enum VkResult { VK_THREAD_DONE_KHR = 1000268001, VK_OPERATION_DEFERRED_KHR = 1000268002, VK_OPERATION_NOT_DEFERRED_KHR = 1000268003, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR = -1000299000, +#endif VK_ERROR_COMPRESSION_EXHAUSTED_EXT = -1000338000, + VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT = 1000482000, VK_ERROR_OUT_OF_POOL_MEMORY_KHR = VK_ERROR_OUT_OF_POOL_MEMORY, VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR = VK_ERROR_INVALID_EXTERNAL_HANDLE, VK_ERROR_FRAGMENTATION_EXT = VK_ERROR_FRAGMENTATION, @@ -480,9 +484,6 @@ typedef enum VkStructureType { #ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_NALU_SLICE_INFO_EXT = 1000038005, #endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_EMIT_PICTURE_PARAMETERS_INFO_EXT = 1000038006, -#endif #ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_INFO_EXT = 1000038007, #endif @@ -492,9 +493,6 @@ typedef enum VkStructureType { #ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_LAYER_INFO_EXT = 1000038009, #endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_REFERENCE_LISTS_INFO_EXT = 1000038010, -#endif #ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_CAPABILITIES_EXT = 1000039000, #endif @@ -513,15 +511,9 @@ typedef enum VkStructureType { #ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_NALU_SLICE_SEGMENT_INFO_EXT = 1000039005, #endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_EMIT_PICTURE_PARAMETERS_INFO_EXT = 1000039006, -#endif #ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_INFO_EXT = 1000039007, #endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_REFERENCE_LISTS_INFO_EXT = 1000039008, -#endif #ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_INFO_EXT = 1000039009, #endif @@ -777,6 +769,8 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR = 1000269003, VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR = 1000269004, VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR = 1000269005, + VK_STRUCTURE_TYPE_MEMORY_MAP_INFO_KHR = 1000271000, + VK_STRUCTURE_TYPE_MEMORY_UNMAP_INFO_KHR = 1000271001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT = 1000273000, VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT = 1000274000, VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT = 1000274001, @@ -828,9 +822,13 @@ typedef enum VkStructureType { #endif #ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_VIDEO_ENCODE_USAGE_INFO_KHR = 1000299004, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_QUERY_POOL_VIDEO_ENCODE_FEEDBACK_CREATE_INFO_KHR = 1000299005, #endif VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV = 1000300000, VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV = 1000300001, + VK_STRUCTURE_TYPE_QUERY_LOW_LATENCY_SUPPORT_NV = 1000310000, VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECT_CREATE_INFO_EXT = 1000311000, VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECTS_INFO_EXT = 1000311001, VK_STRUCTURE_TYPE_EXPORT_METAL_DEVICE_INFO_EXT = 1000311002, @@ -936,6 +934,8 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT = 1000392000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT = 1000392001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT = 1000393000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TILE_IMAGE_FEATURES_EXT = 1000395000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TILE_IMAGE_PROPERTIES_EXT = 1000395001, VK_STRUCTURE_TYPE_MICROMAP_BUILD_INFO_EXT = 1000396000, VK_STRUCTURE_TYPE_MICROMAP_VERSION_INFO_EXT = 1000396001, VK_STRUCTURE_TYPE_COPY_MICROMAP_INFO_EXT = 1000396002, @@ -946,9 +946,23 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_MICROMAP_CREATE_INFO_EXT = 1000396007, VK_STRUCTURE_TYPE_MICROMAP_BUILD_SIZES_INFO_EXT = 1000396008, VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_TRIANGLES_OPACITY_MICROMAP_EXT = 1000396009, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_FEATURES_NV = 1000397000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_PROPERTIES_NV = 1000397001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_TRIANGLES_DISPLACEMENT_MICROMAP_NV = 1000397002, +#endif + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_FEATURES_HUAWEI = 1000404000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_PROPERTIES_HUAWEI = 1000404001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT = 1000411000, VK_STRUCTURE_TYPE_SAMPLER_BORDER_COLOR_COMPONENT_MAPPING_CREATE_INFO_EXT = 1000411001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT = 1000412000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_ARM = 1000415000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_SLICED_VIEW_OF_3D_FEATURES_EXT = 1000418000, + VK_STRUCTURE_TYPE_IMAGE_VIEW_SLICED_CREATE_INFO_EXT = 1000418001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_SET_HOST_MAPPING_FEATURES_VALVE = 1000420000, VK_STRUCTURE_TYPE_DESCRIPTOR_SET_BINDING_REFERENCE_VALVE = 1000420001, VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_HOST_MAPPING_INFO_VALVE = 1000420002, @@ -988,6 +1002,10 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_OPTICAL_FLOW_SESSION_CREATE_PRIVATE_DATA_INFO_NV = 1000464010, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LEGACY_DITHERING_FEATURES_EXT = 1000465000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT = 1000466000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_POSITION_FETCH_FEATURES_KHR = 1000481000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT = 1000482000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_PROPERTIES_EXT = 1000482001, + VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT = 1000482002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TILE_PROPERTIES_FEATURES_QCOM = 1000484000, VK_STRUCTURE_TYPE_TILE_PROPERTIES_QCOM = 1000484001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_AMIGO_PROFILING_FEATURES_SEC = 1000485000, @@ -999,6 +1017,9 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT = 1000351002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_FEATURES_ARM = 1000497000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_PROPERTIES_ARM = 1000497001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_LIBRARY_GROUP_HANDLES_FEATURES_EXT = 1000498000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_RENDER_AREAS_FEATURES_QCOM = 1000510000, + VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_RENDER_AREAS_RENDER_PASS_BEGIN_INFO_QCOM = 1000510001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES, VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT, @@ -1172,6 +1193,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES, VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS_KHR = VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS, VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS_KHR = VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS, + VK_STRUCTURE_TYPE_SHADER_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO, VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF } VkStructureType; @@ -1276,6 +1298,7 @@ typedef enum VkObjectType { VK_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA = 1000366000, VK_OBJECT_TYPE_MICROMAP_EXT = 1000396000, VK_OBJECT_TYPE_OPTICAL_FLOW_SESSION_NV = 1000464000, + VK_OBJECT_TYPE_SHADER_EXT = 1000482000, VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE, VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION, VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT = VK_OBJECT_TYPE_PRIVATE_DATA_SLOT, @@ -1289,6 +1312,7 @@ typedef enum VkVendorId { VK_VENDOR_ID_CODEPLAY = 0x10004, VK_VENDOR_ID_MESA = 0x10005, VK_VENDOR_ID_POCL = 0x10006, + VK_VENDOR_ID_MOBILEYE = 0x10007, VK_VENDOR_ID_MAX_ENUM = 0x7FFFFFFF } VkVendorId; @@ -1647,7 +1671,7 @@ typedef enum VkQueryType { VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV = 1000165000, VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL = 1000210000, #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_QUERY_TYPE_VIDEO_ENCODE_BITSTREAM_BUFFER_RANGE_KHR = 1000299000, + VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR = 1000299000, #endif VK_QUERY_TYPE_MESH_PRIMITIVES_GENERATED_EXT = 1000328000, VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT = 1000382000, @@ -1803,10 +1827,13 @@ typedef enum VkDynamicState { VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE = 1000377004, VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV = 1000087000, VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT = 1000099000, + VK_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT = 1000099001, + VK_DYNAMIC_STATE_DISCARD_RECTANGLE_MODE_EXT = 1000099002, VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT = 1000143000, VK_DYNAMIC_STATE_RAY_TRACING_PIPELINE_STACK_SIZE_KHR = 1000347000, VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV = 1000164004, VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV = 1000164006, + VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_ENABLE_NV = 1000205000, VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV = 1000205001, VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR = 1000226000, VK_DYNAMIC_STATE_LINE_STIPPLE_EXT = 1000259000, @@ -2352,6 +2379,7 @@ typedef enum VkQueryPipelineStatisticFlagBits { VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT = 0x00000400, VK_QUERY_PIPELINE_STATISTIC_TASK_SHADER_INVOCATIONS_BIT_EXT = 0x00000800, VK_QUERY_PIPELINE_STATISTIC_MESH_SHADER_INVOCATIONS_BIT_EXT = 0x00001000, + VK_QUERY_PIPELINE_STATISTIC_CLUSTER_CULLING_SHADER_INVOCATIONS_BIT_HUAWEI = 0x00002000, VK_QUERY_PIPELINE_STATISTIC_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkQueryPipelineStatisticFlagBits; typedef VkFlags VkQueryPipelineStatisticFlags; @@ -2472,6 +2500,9 @@ typedef enum VkPipelineCreateFlagBits { VK_PIPELINE_CREATE_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0x02000000, VK_PIPELINE_CREATE_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0x04000000, VK_PIPELINE_CREATE_RAY_TRACING_OPACITY_MICROMAP_BIT_EXT = 0x01000000, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_PIPELINE_CREATE_RAY_TRACING_DISPLACEMENT_MICROMAP_BIT_NV = 0x10000000, +#endif VK_PIPELINE_CREATE_NO_PROTECTED_ACCESS_BIT_EXT = 0x08000000, VK_PIPELINE_CREATE_PROTECTED_ACCESS_ONLY_BIT_EXT = 0x40000000, VK_PIPELINE_CREATE_DISPATCH_BASE = VK_PIPELINE_CREATE_DISPATCH_BASE_BIT, @@ -2512,6 +2543,7 @@ typedef enum VkShaderStageFlagBits { VK_SHADER_STAGE_TASK_BIT_EXT = 0x00000040, VK_SHADER_STAGE_MESH_BIT_EXT = 0x00000080, VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI = 0x00004000, + VK_SHADER_STAGE_CLUSTER_CULLING_BIT_HUAWEI = 0x00080000, VK_SHADER_STAGE_RAYGEN_BIT_NV = VK_SHADER_STAGE_RAYGEN_BIT_KHR, VK_SHADER_STAGE_ANY_HIT_BIT_NV = VK_SHADER_STAGE_ANY_HIT_BIT_KHR, VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, @@ -5641,6 +5673,7 @@ typedef enum VkDriverId { VK_DRIVER_ID_MESA_VENUS = 22, VK_DRIVER_ID_MESA_DOZEN = 23, VK_DRIVER_ID_MESA_NVK = 24, + VK_DRIVER_ID_IMAGINATION_OPEN_SOURCE_MESA = 25, VK_DRIVER_ID_AMD_PROPRIETARY_KHR = VK_DRIVER_ID_AMD_PROPRIETARY, VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR = VK_DRIVER_ID_AMD_OPEN_SOURCE, VK_DRIVER_ID_MESA_RADV_KHR = VK_DRIVER_ID_MESA_RADV, @@ -6475,6 +6508,7 @@ static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HU static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI = 0x10000000000ULL; static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR = 0x10000000ULL; static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT = 0x40000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CLUSTER_CULLING_SHADER_BIT_HUAWEI = 0x20000000000ULL; static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_OPTICAL_FLOW_BIT_NV = 0x20000000ULL; typedef VkFlags64 VkAccessFlags2; @@ -8176,8 +8210,8 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDecodeVideoKHR( #define VK_KHR_video_decode_h264 1 -#include "Utility/vk_video/vulkan_video_codec_h264std.h" -#include "Utility/vk_video/vulkan_video_codec_h264std_decode.h" +#include "vk_video/vulkan_video_codec_h264std.h" +#include "vk_video/vulkan_video_codec_h264std_decode.h" #define VK_KHR_VIDEO_DECODE_H264_SPEC_VERSION 8 #define VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME "VK_KHR_video_decode_h264" @@ -9349,8 +9383,8 @@ typedef struct VkPhysicalDeviceShaderClockFeaturesKHR { #define VK_KHR_video_decode_h265 1 -#include "Utility/vk_video/vulkan_video_codec_h265std.h" -#include "Utility/vk_video/vulkan_video_codec_h265std_decode.h" +#include "vk_video/vulkan_video_codec_h265std.h" +#include "vk_video/vulkan_video_codec_h265std_decode.h" #define VK_KHR_VIDEO_DECODE_H265_SPEC_VERSION 7 #define VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME "VK_KHR_video_decode_h265" typedef struct VkVideoDecodeH265ProfileInfoKHR { @@ -9386,11 +9420,11 @@ typedef struct VkVideoDecodeH265SessionParametersCreateInfoKHR { } VkVideoDecodeH265SessionParametersCreateInfoKHR; typedef struct VkVideoDecodeH265PictureInfoKHR { - VkStructureType sType; - const void* pNext; - StdVideoDecodeH265PictureInfo* pStdPictureInfo; - uint32_t sliceSegmentCount; - const uint32_t* pSliceSegmentOffsets; + VkStructureType sType; + const void* pNext; + const StdVideoDecodeH265PictureInfo* pStdPictureInfo; + uint32_t sliceSegmentCount; + const uint32_t* pSliceSegmentOffsets; } VkVideoDecodeH265PictureInfoKHR; typedef struct VkVideoDecodeH265DpbSlotInfoKHR { @@ -9824,6 +9858,41 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutableInternalRepresentationsKHR #endif +#define VK_KHR_map_memory2 1 +#define VK_KHR_MAP_MEMORY_2_SPEC_VERSION 1 +#define VK_KHR_MAP_MEMORY_2_EXTENSION_NAME "VK_KHR_map_memory2" +typedef VkFlags VkMemoryUnmapFlagsKHR; +typedef struct VkMemoryMapInfoKHR { + VkStructureType sType; + const void* pNext; + VkMemoryMapFlags flags; + VkDeviceMemory memory; + VkDeviceSize offset; + VkDeviceSize size; +} VkMemoryMapInfoKHR; + +typedef struct VkMemoryUnmapInfoKHR { + VkStructureType sType; + const void* pNext; + VkMemoryUnmapFlagsKHR flags; + VkDeviceMemory memory; +} VkMemoryUnmapInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkMapMemory2KHR)(VkDevice device, const VkMemoryMapInfoKHR* pMemoryMapInfo, void** ppData); +typedef VkResult (VKAPI_PTR *PFN_vkUnmapMemory2KHR)(VkDevice device, const VkMemoryUnmapInfoKHR* pMemoryUnmapInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkMapMemory2KHR( + VkDevice device, + const VkMemoryMapInfoKHR* pMemoryMapInfo, + void** ppData); + +VKAPI_ATTR VkResult VKAPI_CALL vkUnmapMemory2KHR( + VkDevice device, + const VkMemoryUnmapInfoKHR* pMemoryUnmapInfo); +#endif + + #define VK_KHR_shader_integer_dot_product 1 #define VK_KHR_SHADER_INTEGER_DOT_PRODUCT_SPEC_VERSION 1 #define VK_KHR_SHADER_INTEGER_DOT_PRODUCT_EXTENSION_NAME "VK_KHR_shader_integer_dot_product" @@ -10162,6 +10231,17 @@ VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageSparseMemoryRequirementsKHR( #endif +#define VK_KHR_ray_tracing_position_fetch 1 +#define VK_KHR_RAY_TRACING_POSITION_FETCH_SPEC_VERSION 1 +#define VK_KHR_RAY_TRACING_POSITION_FETCH_EXTENSION_NAME "VK_KHR_ray_tracing_position_fetch" +typedef struct VkPhysicalDeviceRayTracingPositionFetchFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 rayTracingPositionFetch; +} VkPhysicalDeviceRayTracingPositionFetchFeaturesKHR; + + + #define VK_EXT_debug_report 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT) #define VK_EXT_DEBUG_REPORT_SPEC_VERSION 10 @@ -11158,7 +11238,7 @@ typedef struct VkPipelineViewportSwizzleStateCreateInfoNV { #define VK_EXT_discard_rectangles 1 -#define VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION 1 +#define VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION 2 #define VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME "VK_EXT_discard_rectangles" typedef enum VkDiscardRectangleModeEXT { @@ -11183,6 +11263,8 @@ typedef struct VkPipelineDiscardRectangleStateCreateInfoEXT { } VkPipelineDiscardRectangleStateCreateInfoEXT; typedef void (VKAPI_PTR *PFN_vkCmdSetDiscardRectangleEXT)(VkCommandBuffer commandBuffer, uint32_t firstDiscardRectangle, uint32_t discardRectangleCount, const VkRect2D* pDiscardRectangles); +typedef void (VKAPI_PTR *PFN_vkCmdSetDiscardRectangleEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 discardRectangleEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDiscardRectangleModeEXT)(VkCommandBuffer commandBuffer, VkDiscardRectangleModeEXT discardRectangleMode); #ifndef VK_NO_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetDiscardRectangleEXT( @@ -11190,6 +11272,14 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetDiscardRectangleEXT( uint32_t firstDiscardRectangle, uint32_t discardRectangleCount, const VkRect2D* pDiscardRectangles); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDiscardRectangleEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 discardRectangleEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDiscardRectangleModeEXT( + VkCommandBuffer commandBuffer, + VkDiscardRectangleModeEXT discardRectangleMode); #endif @@ -12009,6 +12099,10 @@ typedef enum VkBuildAccelerationStructureFlagBitsKHR { VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_UPDATE_EXT = 0x00000040, VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISABLE_OPACITY_MICROMAPS_EXT = 0x00000080, VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_DATA_UPDATE_EXT = 0x00000100, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISPLACEMENT_MICROMAP_UPDATE_NV = 0x00000200, +#endif + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DATA_ACCESS_KHR = 0x00000800, VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR, VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR, VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR, @@ -12610,7 +12704,7 @@ typedef struct VkPhysicalDeviceShaderImageFootprintFeaturesNV { #define VK_NV_scissor_exclusive 1 -#define VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION 1 +#define VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION 2 #define VK_NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME "VK_NV_scissor_exclusive" typedef struct VkPipelineViewportExclusiveScissorStateCreateInfoNV { VkStructureType sType; @@ -12625,9 +12719,16 @@ typedef struct VkPhysicalDeviceExclusiveScissorFeaturesNV { VkBool32 exclusiveScissor; } VkPhysicalDeviceExclusiveScissorFeaturesNV; +typedef void (VKAPI_PTR *PFN_vkCmdSetExclusiveScissorEnableNV)(VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor, uint32_t exclusiveScissorCount, const VkBool32* pExclusiveScissorEnables); typedef void (VKAPI_PTR *PFN_vkCmdSetExclusiveScissorNV)(VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor, uint32_t exclusiveScissorCount, const VkRect2D* pExclusiveScissors); #ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetExclusiveScissorEnableNV( + VkCommandBuffer commandBuffer, + uint32_t firstExclusiveScissor, + uint32_t exclusiveScissorCount, + const VkBool32* pExclusiveScissorEnables); + VKAPI_ATTR void VKAPI_CALL vkCmdSetExclusiveScissorNV( VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor, @@ -13520,21 +13621,21 @@ typedef struct VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT { typedef struct VkSwapchainPresentFenceInfoEXT { VkStructureType sType; - void* pNext; + const void* pNext; uint32_t swapchainCount; const VkFence* pFences; } VkSwapchainPresentFenceInfoEXT; typedef struct VkSwapchainPresentModesCreateInfoEXT { VkStructureType sType; - void* pNext; + const void* pNext; uint32_t presentModeCount; const VkPresentModeKHR* pPresentModes; } VkSwapchainPresentModesCreateInfoEXT; typedef struct VkSwapchainPresentModeInfoEXT { VkStructureType sType; - void* pNext; + const void* pNext; uint32_t swapchainCount; const VkPresentModeKHR* pPresentModes; } VkSwapchainPresentModeInfoEXT; @@ -14034,6 +14135,17 @@ typedef struct VkDeviceDiagnosticsConfigCreateInfoNV { #define VK_QCOM_RENDER_PASS_STORE_OPS_EXTENSION_NAME "VK_QCOM_render_pass_store_ops" +#define VK_NV_low_latency 1 +#define VK_NV_LOW_LATENCY_SPEC_VERSION 1 +#define VK_NV_LOW_LATENCY_EXTENSION_NAME "VK_NV_low_latency" +typedef struct VkQueryLowLatencySupportNV { + VkStructureType sType; + const void* pNext; + void* pQueriedLowLatencyData; +} VkQueryLowLatencySupportNV; + + + #define VK_EXT_descriptor_buffer 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureKHR) #define VK_EXT_DESCRIPTOR_BUFFER_SPEC_VERSION 1 @@ -14596,7 +14708,7 @@ typedef struct VkPhysicalDevice4444FormatsFeaturesEXT { #define VK_EXT_device_fault 1 -#define VK_EXT_DEVICE_FAULT_SPEC_VERSION 1 +#define VK_EXT_DEVICE_FAULT_SPEC_VERSION 2 #define VK_EXT_DEVICE_FAULT_EXTENSION_NAME "VK_EXT_device_fault" typedef enum VkDeviceFaultAddressTypeEXT { @@ -14660,6 +14772,8 @@ typedef struct VkDeviceFaultVendorBinaryHeaderVersionOneEXT { uint32_t applicationNameOffset; uint32_t applicationVersion; uint32_t engineNameOffset; + uint32_t engineVersion; + uint32_t apiVersion; } VkDeviceFaultVendorBinaryHeaderVersionOneEXT; typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceFaultInfoEXT)(VkDevice device, VkDeviceFaultCountsEXT* pFaultCounts, VkDeviceFaultInfoEXT* pFaultInfo); @@ -15143,6 +15257,27 @@ typedef struct VkPhysicalDeviceImage2DViewOf3DFeaturesEXT { +#define VK_EXT_shader_tile_image 1 +#define VK_EXT_SHADER_TILE_IMAGE_SPEC_VERSION 1 +#define VK_EXT_SHADER_TILE_IMAGE_EXTENSION_NAME "VK_EXT_shader_tile_image" +typedef struct VkPhysicalDeviceShaderTileImageFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderTileImageColorReadAccess; + VkBool32 shaderTileImageDepthReadAccess; + VkBool32 shaderTileImageStencilReadAccess; +} VkPhysicalDeviceShaderTileImageFeaturesEXT; + +typedef struct VkPhysicalDeviceShaderTileImagePropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderTileImageCoherentReadAccelerated; + VkBool32 shaderTileImageReadSampleFromPixelRateInvocation; + VkBool32 shaderTileImageReadFromHelperInvocation; +} VkPhysicalDeviceShaderTileImagePropertiesEXT; + + + #define VK_EXT_opacity_micromap 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkMicromapEXT) #define VK_EXT_OPACITY_MICROMAP_SPEC_VERSION 2 @@ -15150,6 +15285,9 @@ VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkMicromapEXT) typedef enum VkMicromapTypeEXT { VK_MICROMAP_TYPE_OPACITY_MICROMAP_EXT = 0, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_MICROMAP_TYPE_DISPLACEMENT_MICROMAP_NV = 1000397000, +#endif VK_MICROMAP_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF } VkMicromapTypeEXT; @@ -15416,6 +15554,42 @@ VKAPI_ATTR void VKAPI_CALL vkGetMicromapBuildSizesEXT( #define VK_EXT_LOAD_STORE_OP_NONE_EXTENSION_NAME "VK_EXT_load_store_op_none" +#define VK_HUAWEI_cluster_culling_shader 1 +#define VK_HUAWEI_CLUSTER_CULLING_SHADER_SPEC_VERSION 2 +#define VK_HUAWEI_CLUSTER_CULLING_SHADER_EXTENSION_NAME "VK_HUAWEI_cluster_culling_shader" +typedef struct VkPhysicalDeviceClusterCullingShaderFeaturesHUAWEI { + VkStructureType sType; + void* pNext; + VkBool32 clustercullingShader; + VkBool32 multiviewClusterCullingShader; +} VkPhysicalDeviceClusterCullingShaderFeaturesHUAWEI; + +typedef struct VkPhysicalDeviceClusterCullingShaderPropertiesHUAWEI { + VkStructureType sType; + void* pNext; + uint32_t maxWorkGroupCount[3]; + uint32_t maxWorkGroupSize[3]; + uint32_t maxOutputClusterCount; + VkDeviceSize indirectBufferOffsetAlignment; +} VkPhysicalDeviceClusterCullingShaderPropertiesHUAWEI; + +typedef void (VKAPI_PTR *PFN_vkCmdDrawClusterHUAWEI)(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); +typedef void (VKAPI_PTR *PFN_vkCmdDrawClusterIndirectHUAWEI)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawClusterHUAWEI( + VkCommandBuffer commandBuffer, + uint32_t groupCountX, + uint32_t groupCountY, + uint32_t groupCountZ); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawClusterIndirectHUAWEI( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset); +#endif + + #define VK_EXT_border_color_swizzle 1 #define VK_EXT_BORDER_COLOR_SWIZZLE_SPEC_VERSION 1 #define VK_EXT_BORDER_COLOR_SWIZZLE_EXTENSION_NAME "VK_EXT_border_color_swizzle" @@ -15454,6 +15628,38 @@ VKAPI_ATTR void VKAPI_CALL vkSetDeviceMemoryPriorityEXT( #endif +#define VK_ARM_shader_core_properties 1 +#define VK_ARM_SHADER_CORE_PROPERTIES_SPEC_VERSION 1 +#define VK_ARM_SHADER_CORE_PROPERTIES_EXTENSION_NAME "VK_ARM_shader_core_properties" +typedef struct VkPhysicalDeviceShaderCorePropertiesARM { + VkStructureType sType; + void* pNext; + uint32_t pixelRate; + uint32_t texelRate; + uint32_t fmaRate; +} VkPhysicalDeviceShaderCorePropertiesARM; + + + +#define VK_EXT_image_sliced_view_of_3d 1 +#define VK_EXT_IMAGE_SLICED_VIEW_OF_3D_SPEC_VERSION 1 +#define VK_EXT_IMAGE_SLICED_VIEW_OF_3D_EXTENSION_NAME "VK_EXT_image_sliced_view_of_3d" +#define VK_REMAINING_3D_SLICES_EXT (~0U) +typedef struct VkPhysicalDeviceImageSlicedViewOf3DFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 imageSlicedViewOf3D; +} VkPhysicalDeviceImageSlicedViewOf3DFeaturesEXT; + +typedef struct VkImageViewSlicedCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t sliceOffset; + uint32_t sliceCount; +} VkImageViewSlicedCreateInfoEXT; + + + #define VK_VALVE_descriptor_set_host_mapping 1 #define VK_VALVE_DESCRIPTOR_SET_HOST_MAPPING_SPEC_VERSION 1 #define VK_VALVE_DESCRIPTOR_SET_HOST_MAPPING_EXTENSION_NAME "VK_VALVE_descriptor_set_host_mapping" @@ -16251,6 +16457,92 @@ typedef struct VkPhysicalDevicePipelineProtectedAccessFeaturesEXT { +#define VK_EXT_shader_object 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkShaderEXT) +#define VK_EXT_SHADER_OBJECT_SPEC_VERSION 1 +#define VK_EXT_SHADER_OBJECT_EXTENSION_NAME "VK_EXT_shader_object" + +typedef enum VkShaderCodeTypeEXT { + VK_SHADER_CODE_TYPE_BINARY_EXT = 0, + VK_SHADER_CODE_TYPE_SPIRV_EXT = 1, + VK_SHADER_CODE_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkShaderCodeTypeEXT; + +typedef enum VkShaderCreateFlagBitsEXT { + VK_SHADER_CREATE_LINK_STAGE_BIT_EXT = 0x00000001, + VK_SHADER_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT = 0x00000002, + VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT = 0x00000004, + VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT = 0x00000008, + VK_SHADER_CREATE_DISPATCH_BASE_BIT_EXT = 0x00000010, + VK_SHADER_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_EXT = 0x00000020, + VK_SHADER_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT = 0x00000040, + VK_SHADER_CREATE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkShaderCreateFlagBitsEXT; +typedef VkFlags VkShaderCreateFlagsEXT; +typedef struct VkPhysicalDeviceShaderObjectFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderObject; +} VkPhysicalDeviceShaderObjectFeaturesEXT; + +typedef struct VkPhysicalDeviceShaderObjectPropertiesEXT { + VkStructureType sType; + void* pNext; + uint8_t shaderBinaryUUID[VK_UUID_SIZE]; + uint32_t shaderBinaryVersion; +} VkPhysicalDeviceShaderObjectPropertiesEXT; + +typedef struct VkShaderCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkShaderCreateFlagsEXT flags; + VkShaderStageFlagBits stage; + VkShaderStageFlags nextStage; + VkShaderCodeTypeEXT codeType; + size_t codeSize; + const void* pCode; + const char* pName; + uint32_t setLayoutCount; + const VkDescriptorSetLayout* pSetLayouts; + uint32_t pushConstantRangeCount; + const VkPushConstantRange* pPushConstantRanges; + const VkSpecializationInfo* pSpecializationInfo; +} VkShaderCreateInfoEXT; + +typedef VkPipelineShaderStageRequiredSubgroupSizeCreateInfo VkShaderRequiredSubgroupSizeCreateInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateShadersEXT)(VkDevice device, uint32_t createInfoCount, const VkShaderCreateInfoEXT* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkShaderEXT* pShaders); +typedef void (VKAPI_PTR *PFN_vkDestroyShaderEXT)(VkDevice device, VkShaderEXT shader, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetShaderBinaryDataEXT)(VkDevice device, VkShaderEXT shader, size_t* pDataSize, void* pData); +typedef void (VKAPI_PTR *PFN_vkCmdBindShadersEXT)(VkCommandBuffer commandBuffer, uint32_t stageCount, const VkShaderStageFlagBits* pStages, const VkShaderEXT* pShaders); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateShadersEXT( + VkDevice device, + uint32_t createInfoCount, + const VkShaderCreateInfoEXT* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkShaderEXT* pShaders); + +VKAPI_ATTR void VKAPI_CALL vkDestroyShaderEXT( + VkDevice device, + VkShaderEXT shader, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetShaderBinaryDataEXT( + VkDevice device, + VkShaderEXT shader, + size_t* pDataSize, + void* pData); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindShadersEXT( + VkCommandBuffer commandBuffer, + uint32_t stageCount, + const VkShaderStageFlagBits* pStages, + const VkShaderEXT* pShaders); +#endif + + #define VK_QCOM_tile_properties 1 #define VK_QCOM_TILE_PROPERTIES_SPEC_VERSION 1 #define VK_QCOM_TILE_PROPERTIES_EXTENSION_NAME "VK_QCOM_tile_properties" @@ -16361,6 +16653,35 @@ typedef struct VkPhysicalDeviceShaderCoreBuiltinsPropertiesARM { +#define VK_EXT_pipeline_library_group_handles 1 +#define VK_EXT_PIPELINE_LIBRARY_GROUP_HANDLES_SPEC_VERSION 1 +#define VK_EXT_PIPELINE_LIBRARY_GROUP_HANDLES_EXTENSION_NAME "VK_EXT_pipeline_library_group_handles" +typedef struct VkPhysicalDevicePipelineLibraryGroupHandlesFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 pipelineLibraryGroupHandles; +} VkPhysicalDevicePipelineLibraryGroupHandlesFeaturesEXT; + + + +#define VK_QCOM_multiview_per_view_render_areas 1 +#define VK_QCOM_MULTIVIEW_PER_VIEW_RENDER_AREAS_SPEC_VERSION 1 +#define VK_QCOM_MULTIVIEW_PER_VIEW_RENDER_AREAS_EXTENSION_NAME "VK_QCOM_multiview_per_view_render_areas" +typedef struct VkPhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 multiviewPerViewRenderAreas; +} VkPhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM; + +typedef struct VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM { + VkStructureType sType; + const void* pNext; + uint32_t perViewRenderAreaCount; + const VkRect2D* pPerViewRenderAreas; +} VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM; + + + #define VK_KHR_acceleration_structure 1 #define VK_KHR_ACCELERATION_STRUCTURE_SPEC_VERSION 13 #define VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME "VK_KHR_acceleration_structure" diff --git a/WickedEngine/Utility/vulkan/vulkan_directfb.h b/WickedEngine/Utility/vulkan/vulkan_directfb.h index ab3504efa..81d22fa7a 100644 --- a/WickedEngine/Utility/vulkan/vulkan_directfb.h +++ b/WickedEngine/Utility/vulkan/vulkan_directfb.h @@ -2,7 +2,7 @@ #define VULKAN_DIRECTFB_H_ 1 /* -** Copyright 2015-2022 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/WickedEngine/Utility/vulkan/vulkan_fuchsia.h b/WickedEngine/Utility/vulkan/vulkan_fuchsia.h index 61774ff9c..c11d9e65b 100644 --- a/WickedEngine/Utility/vulkan/vulkan_fuchsia.h +++ b/WickedEngine/Utility/vulkan/vulkan_fuchsia.h @@ -2,7 +2,7 @@ #define VULKAN_FUCHSIA_H_ 1 /* -** Copyright 2015-2022 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/WickedEngine/Utility/vulkan/vulkan_ggp.h b/WickedEngine/Utility/vulkan/vulkan_ggp.h index 19dfd2261..2c0d5edf1 100644 --- a/WickedEngine/Utility/vulkan/vulkan_ggp.h +++ b/WickedEngine/Utility/vulkan/vulkan_ggp.h @@ -2,7 +2,7 @@ #define VULKAN_GGP_H_ 1 /* -** Copyright 2015-2022 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/WickedEngine/Utility/vulkan/vulkan_ios.h b/WickedEngine/Utility/vulkan/vulkan_ios.h index 579220543..8c6d9e72a 100644 --- a/WickedEngine/Utility/vulkan/vulkan_ios.h +++ b/WickedEngine/Utility/vulkan/vulkan_ios.h @@ -2,7 +2,7 @@ #define VULKAN_IOS_H_ 1 /* -** Copyright 2015-2022 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/WickedEngine/Utility/vulkan/vulkan_macos.h b/WickedEngine/Utility/vulkan/vulkan_macos.h index 8e197c7cf..3310e11ab 100644 --- a/WickedEngine/Utility/vulkan/vulkan_macos.h +++ b/WickedEngine/Utility/vulkan/vulkan_macos.h @@ -2,7 +2,7 @@ #define VULKAN_MACOS_H_ 1 /* -** Copyright 2015-2022 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/WickedEngine/Utility/vulkan/vulkan_metal.h b/WickedEngine/Utility/vulkan/vulkan_metal.h index 11b964091..7127651c1 100644 --- a/WickedEngine/Utility/vulkan/vulkan_metal.h +++ b/WickedEngine/Utility/vulkan/vulkan_metal.h @@ -2,7 +2,7 @@ #define VULKAN_METAL_H_ 1 /* -** Copyright 2015-2022 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/WickedEngine/Utility/vulkan/vulkan_screen.h b/WickedEngine/Utility/vulkan/vulkan_screen.h index f0ef40a6c..1067c0463 100644 --- a/WickedEngine/Utility/vulkan/vulkan_screen.h +++ b/WickedEngine/Utility/vulkan/vulkan_screen.h @@ -2,7 +2,7 @@ #define VULKAN_SCREEN_H_ 1 /* -** Copyright 2015-2022 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/WickedEngine/Utility/vulkan/vulkan_vi.h b/WickedEngine/Utility/vulkan/vulkan_vi.h index 0355e7a16..672647053 100644 --- a/WickedEngine/Utility/vulkan/vulkan_vi.h +++ b/WickedEngine/Utility/vulkan/vulkan_vi.h @@ -2,7 +2,7 @@ #define VULKAN_VI_H_ 1 /* -** Copyright 2015-2022 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/WickedEngine/Utility/vulkan/vulkan_wayland.h b/WickedEngine/Utility/vulkan/vulkan_wayland.h index 9afd0b76d..42b280184 100644 --- a/WickedEngine/Utility/vulkan/vulkan_wayland.h +++ b/WickedEngine/Utility/vulkan/vulkan_wayland.h @@ -2,7 +2,7 @@ #define VULKAN_WAYLAND_H_ 1 /* -** Copyright 2015-2022 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/WickedEngine/Utility/vulkan/vulkan_win32.h b/WickedEngine/Utility/vulkan/vulkan_win32.h index a8e46c89b..5b65a36a6 100644 --- a/WickedEngine/Utility/vulkan/vulkan_win32.h +++ b/WickedEngine/Utility/vulkan/vulkan_win32.h @@ -2,7 +2,7 @@ #define VULKAN_WIN32_H_ 1 /* -** Copyright 2015-2022 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/WickedEngine/Utility/vulkan/vulkan_xcb.h b/WickedEngine/Utility/vulkan/vulkan_xcb.h index 68e61b88f..b49aa4e2c 100644 --- a/WickedEngine/Utility/vulkan/vulkan_xcb.h +++ b/WickedEngine/Utility/vulkan/vulkan_xcb.h @@ -2,7 +2,7 @@ #define VULKAN_XCB_H_ 1 /* -** Copyright 2015-2022 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/WickedEngine/Utility/vulkan/vulkan_xlib.h b/WickedEngine/Utility/vulkan/vulkan_xlib.h index ea5360ab6..186cdd5ef 100644 --- a/WickedEngine/Utility/vulkan/vulkan_xlib.h +++ b/WickedEngine/Utility/vulkan/vulkan_xlib.h @@ -2,7 +2,7 @@ #define VULKAN_XLIB_H_ 1 /* -** Copyright 2015-2022 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/WickedEngine/Utility/vulkan/vulkan_xlib_xrandr.h b/WickedEngine/Utility/vulkan/vulkan_xlib_xrandr.h index 8fc35cfc5..9a3b62991 100644 --- a/WickedEngine/Utility/vulkan/vulkan_xlib_xrandr.h +++ b/WickedEngine/Utility/vulkan/vulkan_xlib_xrandr.h @@ -2,7 +2,7 @@ #define VULKAN_XLIB_XRANDR_H_ 1 /* -** Copyright 2015-2022 The Khronos Group Inc. +** Copyright 2015-2023 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/WickedEngine/WickedEngine.h b/WickedEngine/WickedEngine.h index 7fee01811..45e2da16e 100644 --- a/WickedEngine/WickedEngine.h +++ b/WickedEngine/WickedEngine.h @@ -72,6 +72,7 @@ #include "wiConfig.h" #include "wiTerrain.h" #include "wiLocalization.h" +#include "wiVideo.h" #ifdef _WIN32 #ifdef PLATFORM_UWP diff --git a/WickedEngine/WickedEngine_SOURCE.vcxitems b/WickedEngine/WickedEngine_SOURCE.vcxitems index 4fa2d6cca..f616a7dd1 100644 --- a/WickedEngine/WickedEngine_SOURCE.vcxitems +++ b/WickedEngine/WickedEngine_SOURCE.vcxitems @@ -229,6 +229,9 @@ + + + @@ -364,6 +367,7 @@ + @@ -702,6 +706,7 @@ + diff --git a/WickedEngine/WickedEngine_SOURCE.vcxitems.filters b/WickedEngine/WickedEngine_SOURCE.vcxitems.filters index 34b1b3125..6ee57c628 100644 --- a/WickedEngine/WickedEngine_SOURCE.vcxitems.filters +++ b/WickedEngine/WickedEngine_SOURCE.vcxitems.filters @@ -52,6 +52,9 @@ {a25b4076-72bb-4c78-8bc1-84c59a8984fd} + + {7cb35feb-169d-4eb9-b90c-61418a8e99df} + @@ -1104,6 +1107,18 @@ UTILITY + + UTILITY + + + ENGINE\Video + + + UTILITY + + + UTILITY + @@ -1856,6 +1871,9 @@ UTILITY + + ENGINE\Video + diff --git a/WickedEngine/offlineshadercompiler.cpp b/WickedEngine/offlineshadercompiler.cpp index 918e6081d..a5176772a 100644 --- a/WickedEngine/offlineshadercompiler.cpp +++ b/WickedEngine/offlineshadercompiler.cpp @@ -220,6 +220,7 @@ wi::vector shaders = { {"virtualTextureTileAllocateCS", wi::graphics::ShaderStage::CS }, {"virtualTextureResidencyUpdateCS", wi::graphics::ShaderStage::CS }, {"windCS", wi::graphics::ShaderStage::CS }, + {"yuv_to_rgbCS", wi::graphics::ShaderStage::CS }, {"emittedparticlePS_soft", wi::graphics::ShaderStage::PS }, @@ -617,5 +618,7 @@ int main(int argc, char* argv[]) std::cout << "[Wicked Engine Offline Shader Compiler] ShaderDump written to wiShaderDump.h in " << std::setprecision(4) << timer.elapsed_seconds() << " seconds\n"; } + wi::jobsystem::ShutDown(); + return 0; } diff --git a/WickedEngine/shaders/Shaders_SOURCE.vcxitems b/WickedEngine/shaders/Shaders_SOURCE.vcxitems index 821190064..b4aadc4b3 100644 --- a/WickedEngine/shaders/Shaders_SOURCE.vcxitems +++ b/WickedEngine/shaders/Shaders_SOURCE.vcxitems @@ -1118,6 +1118,10 @@ 4.0 + + Compute + 4.0 + Compute 4.0 diff --git a/WickedEngine/shaders/Shaders_SOURCE.vcxitems.filters b/WickedEngine/shaders/Shaders_SOURCE.vcxitems.filters index 690c02e10..a0f3682e1 100644 --- a/WickedEngine/shaders/Shaders_SOURCE.vcxitems.filters +++ b/WickedEngine/shaders/Shaders_SOURCE.vcxitems.filters @@ -1091,6 +1091,9 @@ PS + + CS + diff --git a/WickedEngine/shaders/yuv_to_rgbCS.hlsl b/WickedEngine/shaders/yuv_to_rgbCS.hlsl new file mode 100644 index 000000000..fbbd2a526 --- /dev/null +++ b/WickedEngine/shaders/yuv_to_rgbCS.hlsl @@ -0,0 +1,29 @@ +#include "globals.hlsli" +#include "ShaderInterop_Postprocess.h" + +PUSHCONSTANT(postprocess, PostProcess); + +Texture2DArray input_luminance : register(t0); +Texture2DArray input_chrominance : register(t1); + +RWTexture2D output : register(u0); + +[numthreads(POSTPROCESS_BLOCKSIZE, POSTPROCESS_BLOCKSIZE, 1)] +void main(uint3 DTid : SV_DispatchThreadID) +{ + const float3 uv = float3((DTid.xy + 0.5f) * postprocess.resolution_rcp, 0); + + float luminance = input_luminance.SampleLevel(sampler_linear_clamp, uv, 0); + float2 chrominance = input_chrominance.SampleLevel(sampler_linear_clamp, uv, 0); + + // https://learn.microsoft.com/en-us/windows/win32/medfound/recommended-8-bit-yuv-formats-for-video-rendering#converting-8-bit-yuv-to-rgb888 + float C = luminance - 16.0 / 255.0; + float D = chrominance.x - 0.5; + float E = chrominance.y - 0.5; + + float r = saturate(1.164383 * C + 1.596027 * E); + float g = saturate(1.164383 * C - (0.391762 * D) - (0.812968 * E)); + float b = saturate(1.164383 * C + 2.017232 * D); + + output[DTid.xy] = float4(r, g, b, 1); +} diff --git a/WickedEngine/wiApplication.cpp b/WickedEngine/wiApplication.cpp index dfc5156d8..965821dff 100644 --- a/WickedEngine/wiApplication.cpp +++ b/WickedEngine/wiApplication.cpp @@ -105,7 +105,8 @@ namespace wi return; } - #ifdef WICKEDENGINE_BUILD_DX12 +#if 0 +#ifdef WICKEDENGINE_BUILD_DX12 static bool startup_workaround = false; if (!startup_workaround) { @@ -117,7 +118,8 @@ namespace wi graphicsDevice->SubmitCommandLists(); } } - #endif // WICKEDENGINE_BUILD_DX12 +#endif // WICKEDENGINE_BUILD_DX12 +#endif static bool startup_script = false; if (!startup_script) @@ -519,6 +521,12 @@ namespace wi validationMode = ValidationMode::Verbose; } + GPUPreference preference = GPUPreference::Discrete; + if (wi::arguments::HasArgument("igpu")) + { + preference = GPUPreference::Integrated; + } + bool use_dx12 = wi::arguments::HasArgument("dx12"); bool use_vulkan = wi::arguments::HasArgument("vulkan"); @@ -552,14 +560,14 @@ namespace wi { #ifdef WICKEDENGINE_BUILD_VULKAN wi::renderer::SetShaderPath(wi::renderer::GetShaderPath() + "spirv/"); - graphicsDevice = std::make_unique(window, validationMode); + graphicsDevice = std::make_unique(window, validationMode, preference); #endif } else if (use_dx12) { #ifdef WICKEDENGINE_BUILD_DX12 wi::renderer::SetShaderPath(wi::renderer::GetShaderPath() + "hlsl6/"); - graphicsDevice = std::make_unique(validationMode); + graphicsDevice = std::make_unique(validationMode, preference); #endif } } diff --git a/WickedEngine/wiEnums.h b/WickedEngine/wiEnums.h index 990975ed6..c4ae990bd 100644 --- a/WickedEngine/wiEnums.h +++ b/WickedEngine/wiEnums.h @@ -397,6 +397,7 @@ namespace wi::enums CSTYPE_VIRTUALTEXTURE_TILEALLOCATE, CSTYPE_VIRTUALTEXTURE_RESIDENCYUPDATE, CSTYPE_WIND, + CSTYPE_YUV_TO_RGB, // raytracing pipelines: diff --git a/WickedEngine/wiGraphics.h b/WickedEngine/wiGraphics.h index 71157a37c..a5d93ed0c 100644 --- a/WickedEngine/wiGraphics.h +++ b/WickedEngine/wiGraphics.h @@ -31,6 +31,12 @@ namespace wi::graphics Cpu, }; + enum class GPUPreference + { + Discrete, + Integrated, + }; + enum class ShaderStage { MS, // Mesh Shader @@ -224,7 +230,7 @@ namespace wi::graphics R32G32_FLOAT, R32G32_UINT, R32G32_SINT, - D32_FLOAT_S8X24_UINT, // depth (32-bit) + stencil (8-bit) | SRV: R32_FLOAT + D32_FLOAT_S8X24_UINT, // depth (32-bit) + stencil (8-bit) | SRV: R32_FLOAT (default or depth aspect), R8_UINT (stencil aspect) R10G10B10A2_UNORM, R10G10B10A2_UINT, @@ -245,7 +251,7 @@ namespace wi::graphics R32_FLOAT, R32_UINT, R32_SINT, - D24_UNORM_S8_UINT, // depth (24-bit) + stencil (8-bit) | SRV: R24_INTERNAL + D24_UNORM_S8_UINT, // depth (24-bit) + stencil (8-bit) | SRV: R24_INTERNAL (default or depth aspect), R8_UINT (stencil aspect) R9G9B9E5_SHAREDEXP, R8G8_UNORM, @@ -264,6 +270,8 @@ namespace wi::graphics R8_SNORM, R8_SINT, + // Formats that are not usable in render pass must be below because formats in render pass must be encodable as 6 bits: + BC1_UNORM, BC1_UNORM_SRGB, BC2_UNORM, @@ -277,7 +285,9 @@ namespace wi::graphics BC6H_UF16, BC6H_SF16, BC7_UNORM, - BC7_UNORM_SRGB + BC7_UNORM_SRGB, + + NV12, // video YUV420; SRV Luminance aspect: R8_UNORM, SRV Chrominance aspect: R8G8_UNORM }; enum class GpuQueryType { @@ -322,6 +332,14 @@ namespace wi::graphics COLOR, DEPTH, STENCIL, + LUMINANCE, + CHROMINANCE, + }; + + enum class VideoFrameType + { + Intra, + Predictive, }; // Flags //////////////////////////////////////////// @@ -366,6 +384,7 @@ namespace wi::graphics SPARSE_TILE_POOL = SPARSE_TILE_POOL_BUFFER | SPARSE_TILE_POOL_TEXTURE_NON_RT_DS | SPARSE_TILE_POOL_TEXTURE_RT_DS, // buffer only, makes it suitable for containing tile memory for all kinds of sparse resources. Requires GraphicsDeviceCapability::GENERIC_SPARSE_TILE_POOL to be supported TYPED_FORMAT_CASTING = 1 << 11, // enable casting formats between same type and different modifiers: eg. UNORM -> SRGB TYPELESS_FORMAT_CASTING = 1 << 12, // enable casting formats to other formats that have the same bit-width and channel layout: eg. R32_FLOAT -> R32_UINT + VIDEO_DECODE = 1 << 15, // resource is usabe in video decoding operations }; enum class GraphicsDeviceCapability @@ -388,10 +407,11 @@ namespace wi::graphics SPARSE_TEXTURE2D = 1 << 14, SPARSE_TEXTURE3D = 1 << 15, SPARSE_NULL_MAPPING = 1 << 16, - GENERIC_SPARSE_TILE_POOL = 1 << 17, // alows using ResourceMiscFlag::SPARSE_TILE_POOL (non resource type specific version) + GENERIC_SPARSE_TILE_POOL = 1 << 17, // allows using ResourceMiscFlag::SPARSE_TILE_POOL (non resource type specific version) DEPTH_RESOLVE_MIN_MAX = 1 << 18, STENCIL_RESOLVE_MIN_MAX = 1 << 19, CACHE_COHERENT_UMA = 1 << 20, // https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_feature_data_architecture + VIDEO_DECODE_H264, }; enum class ResourceState @@ -414,9 +434,13 @@ namespace wi::graphics VERTEX_BUFFER = 1 << 9, // vertex buffer, read only INDEX_BUFFER = 1 << 10, // index buffer, read only CONSTANT_BUFFER = 1 << 11, // constant buffer, read only - INDIRECT_ARGUMENT = 1 << 12, // argument buffer to DrawIndirect() or DispatchIndirect() + INDIRECT_ARGUMENT = 1 << 12, // argument buffer to DrawIndirect() or DispatchIndirect() RAYTRACING_ACCELERATION_STRUCTURE = 1 << 13, // acceleration structure storage or scratch - PREDICATION = 1 << 14 // storage for predication comparison value + PREDICATION = 1 << 14, // storage for predication comparison value + + // Other: + VIDEO_DECODE_SRC = 1 << 15, // video decode operation source (bitstream buffer or DPB texture) + VIDEO_DECODE_DST = 1 << 16, // video decode operation destination DPB texture }; enum class ColorSpace @@ -434,6 +458,11 @@ namespace wi::graphics RESUMING = 1 << 2, }; + enum class VideoProfile + { + H264, // AVC + }; + // Descriptor structs: @@ -619,6 +648,7 @@ namespace wi::graphics ResourceState layout_after; int mip; int slice; + const ImageAspect* aspect; }; struct Buffer { @@ -641,7 +671,7 @@ namespace wi::graphics return barrier; } static GPUBarrier Image(const Texture* texture, ResourceState before, ResourceState after, - int mip = -1, int slice = -1) + int mip = -1, int slice = -1, const ImageAspect* aspect = nullptr) { GPUBarrier barrier; barrier.type = Type::IMAGE; @@ -650,6 +680,7 @@ namespace wi::graphics barrier.image.layout_after = after; barrier.image.mip = mip; barrier.image.slice = slice; + barrier.image.aspect = aspect; return barrier; } static GPUBarrier Buffer(const GPUBuffer* buffer, ResourceState before, ResourceState after) @@ -736,6 +767,20 @@ namespace wi::graphics uint32_t packed_mip_tile_count = 0; // how many tiles are required for the packed mipmaps }; + struct VideoDesc + { + uint32_t width = 0; // must meet the codec specific alignment requirements + uint32_t height = 0; // must meet the codec specific alignment requirements + uint32_t bit_rate = 0; // can be 0, it means that decoding will be prepared for worst case + Format format = Format::NV12; + VideoProfile profile = VideoProfile::H264; + const void* pps_datas = nullptr; // array of picture parameter set structures. The structure type depends on video codec + size_t pps_count = 0; // number of picture parameter set structures in the pps_datas array + const void* sps_datas = nullptr; // array of sequence parameter set structures. The structure type depends on video codec + size_t sps_count = 0; // number of sequence parameter set structures in the sps_datas array + uint32_t num_dpb_slots = 0; // The number of decode picture buffer slots. Usually it is required to be at least number_of_reference_frames + 1 + }; + // Resources: @@ -800,6 +845,38 @@ namespace wi::graphics constexpr const TextureDesc& GetDesc() const { return desc; } }; + struct VideoDecoder : public GraphicsDeviceChild + { + VideoDesc desc; + constexpr const VideoDesc& GetDesc() const { return desc; } + }; + + struct VideoDecodeOperation + { + enum Flags + { + FLAG_EMPTY = 0, + FLAG_SESSION_RESET = 1 << 0, // first usage of decoder needs reset + }; + uint32_t flags = FLAG_EMPTY; + const GPUBuffer* stream = nullptr; + uint64_t stream_offset = 0; // must be aligned with GraphicsDevice::GetVideoDecodeBitstreamAlignment() + uint64_t stream_size = 0; + VideoFrameType frame_type = VideoFrameType::Intra; + uint32_t reference_priority = 0; // nal_ref_idc from nal unit header + int decoded_frame_index = 0; // frame index in order of decoding + const void* slice_header = nullptr; // slice header for current frame + const void* pps = nullptr; // picture parameter set for current slice header + const void* sps = nullptr; // sequence parameter set for current picture parameter set + int poc[2] = {}; // PictureOrderCount Top and Bottom fields + uint32_t current_dpb = 0; // DPB slot for current output picture + uint8_t dpb_reference_count = 0; // number of references in dpb_reference_slots array + const uint8_t* dpb_reference_slots = nullptr; // dpb slot indices that are used as reference pictures + const int* dpb_poc = nullptr; // for each DPB reference slot, indicate the PictureOrderCount + const int* dpb_framenum = nullptr; // for each DPB reference slot, indicate the framenum value + const Texture* DPB = nullptr; // DPB texture with arraysize = num_references + 1 + }; + struct RenderPassImage { enum class Type diff --git a/WickedEngine/wiGraphicsDevice.h b/WickedEngine/wiGraphicsDevice.h index 41b05b42a..e3badd257 100644 --- a/WickedEngine/wiGraphicsDevice.h +++ b/WickedEngine/wiGraphicsDevice.h @@ -43,6 +43,7 @@ namespace wi::graphics QUEUE_GRAPHICS, QUEUE_COMPUTE, QUEUE_COPY, + QUEUE_VIDEO_DECODE, QUEUE_COUNT, }; @@ -58,6 +59,7 @@ namespace wi::graphics size_t TOPLEVEL_ACCELERATION_STRUCTURE_INSTANCE_SIZE = 0; uint32_t VARIABLE_RATE_SHADING_TILE_SIZE = 0; uint64_t TIMESTAMP_FREQUENCY = 0; + uint64_t VIDEO_DECODE_BITSTREAM_ALIGNMENT = 1u; uint32_t vendorId = 0; uint32_t deviceId = 0; std::string adapterName; @@ -79,8 +81,9 @@ namespace wi::graphics virtual bool CreatePipelineState(const PipelineStateDesc* desc, PipelineState* pso, const RenderPassInfo* renderpass_info = nullptr) const = 0; virtual bool CreateRaytracingAccelerationStructure(const RaytracingAccelerationStructureDesc* desc, RaytracingAccelerationStructure* bvh) const { return false; } virtual bool CreateRaytracingPipelineState(const RaytracingPipelineStateDesc* desc, RaytracingPipelineState* rtpso) const { return false; } - - virtual int CreateSubresource(Texture* texture, SubresourceType type, uint32_t firstSlice, uint32_t sliceCount, uint32_t firstMip, uint32_t mipCount, const Format* format_change = nullptr) const = 0; + virtual bool CreateVideoDecoder(const VideoDesc* desc, VideoDecoder* video_decoder) const { return false; }; + + virtual int CreateSubresource(Texture* texture, SubresourceType type, uint32_t firstSlice, uint32_t sliceCount, uint32_t firstMip, uint32_t mipCount, const Format* format_change = nullptr, const ImageAspect* aspect = nullptr) const = 0; virtual int CreateSubresource(GPUBuffer* buffer, SubresourceType type, uint64_t offset, uint64_t size = ~0, const Format* format_change = nullptr) const = 0; virtual int GetDescriptorIndex(const GPUResource* resource, SubresourceType type, int subresource = -1) const = 0; @@ -91,8 +94,8 @@ namespace wi::graphics virtual void WriteShaderIdentifier(const RaytracingPipelineState* rtpso, uint32_t group_index, void* dest) const {} // Set a debug name which will be visible in graphics debuggers - virtual void SetName(GPUResource* pResource, const char* name) {} - virtual void SetName(Shader* shader, const char* name) {} + virtual void SetName(GPUResource* pResource, const char* name) const {} + virtual void SetName(Shader* shader, const char* name) const {} // Begin a new command list for GPU command recording. // This will be valid until SubmitCommandLists() is called. @@ -130,6 +133,7 @@ namespace wi::graphics constexpr size_t GetTopLevelAccelerationStructureInstanceSize() const { return TOPLEVEL_ACCELERATION_STRUCTURE_INSTANCE_SIZE; } constexpr uint32_t GetVariableRateShadingTileSize() const { return VARIABLE_RATE_SHADING_TILE_SIZE; } constexpr uint64_t GetTimestampFrequency() const { return TIMESTAMP_FREQUENCY; } + constexpr uint64_t GetVideoDecodeBitstreamAlignment() const { return VIDEO_DECODE_BITSTREAM_ALIGNMENT; } constexpr uint32_t GetVendorId() const { return vendorId; } constexpr uint32_t GetDeviceId() const { return deviceId; } @@ -220,6 +224,7 @@ namespace wi::graphics virtual void PredicationBegin(const GPUBuffer* buffer, uint64_t offset, PredicationOp op, CommandList cmd) {} virtual void PredicationEnd(CommandList cmd) {} virtual void ClearUAV(const GPUResource* resource, uint32_t value, CommandList cmd) = 0; + virtual void VideoDecode(const VideoDecoder* video_decoder, const VideoDecodeOperation* op, CommandList cmd) {} virtual void EventBegin(const char* name, CommandList cmd) = 0; virtual void EventEnd(CommandList cmd) = 0; diff --git a/WickedEngine/wiGraphicsDevice_DX12.cpp b/WickedEngine/wiGraphicsDevice_DX12.cpp index d5bde5cd9..c4e0a9fa0 100644 --- a/WickedEngine/wiGraphicsDevice_DX12.cpp +++ b/WickedEngine/wiGraphicsDevice_DX12.cpp @@ -7,21 +7,24 @@ #include "wiUnorderedSet.h" #include "Utility/dx12/dxgiformat.h" -#include "Utility/dx12/d3d12.h" #include "Utility/dx12/d3dx12_default.h" #include "Utility/dx12/d3dx12_resource_helpers.h" #include "Utility/dx12/d3dx12_pipeline_state_stream.h" #include "Utility/dx12/d3dx12_check_feature_support.h" #include "Utility/D3D12MemAlloc.h" -#include +#include "Utility/h264.h" +#include "Utility/dxva.h" +#include +#include #include #ifdef _DEBUG #include -#pragma comment(lib,"dxguid.lib") #endif +#pragma comment(lib,"dxguid.lib") + #include #include #include // _BitScanReverse64 @@ -121,6 +124,11 @@ namespace dx12_internal if (has_flag(value, ResourceState::PREDICATION)) ret |= D3D12_RESOURCE_STATE_PREDICATION; + if (has_flag(value, ResourceState::VIDEO_DECODE_SRC)) + ret |= D3D12_RESOURCE_STATE_VIDEO_DECODE_READ; + if (has_flag(value, ResourceState::VIDEO_DECODE_DST)) + ret |= D3D12_RESOURCE_STATE_VIDEO_DECODE_WRITE; + return ret; } constexpr D3D12_FILTER _ConvertFilter(Filter value) @@ -636,6 +644,8 @@ namespace dx12_internal return DXGI_FORMAT_BC7_UNORM; case Format::BC7_UNORM_SRGB: return DXGI_FORMAT_BC7_UNORM_SRGB; + case Format::NV12: + return DXGI_FORMAT_NV12; } return DXGI_FORMAT_UNKNOWN; } @@ -814,6 +824,23 @@ namespace dx12_internal } return D3D12_SHADING_RATE_1X1; } + constexpr UINT _ImageAspectToPlane(ImageAspect value) + { + switch (value) + { + default: + case wi::graphics::ImageAspect::COLOR: + return 0; + case wi::graphics::ImageAspect::DEPTH: + return 0; + case wi::graphics::ImageAspect::STENCIL: + return 1; + case wi::graphics::ImageAspect::LUMINANCE: + return 0; + case wi::graphics::ImageAspect::CHROMINANCE: + return 1; + } + } // Native -> Engine converters constexpr Format _ConvertFormat_Inv(DXGI_FORMAT value) @@ -1363,7 +1390,7 @@ namespace dx12_internal struct QueryHeap_DX12 { std::shared_ptr allocationhandler; - Microsoft::WRL::ComPtr heap; + ComPtr heap; ~QueryHeap_DX12() { @@ -1456,8 +1483,8 @@ namespace dx12_internal struct SwapChain_DX12 { std::shared_ptr allocationhandler; - Microsoft::WRL::ComPtr swapChain; - wi::vector> backBuffers; + ComPtr swapChain; + wi::vector> backBuffers; wi::vector backbufferRTV; Texture dummyTexture; @@ -1478,6 +1505,21 @@ namespace dx12_internal } } }; + struct VideoDecoder_DX12 + { + std::shared_ptr allocationhandler; + ComPtr decoder_heap; + ComPtr decoder; + + ~VideoDecoder_DX12() + { + allocationhandler->destroylocker.lock(); + uint64_t framecount = allocationhandler->framecount; + allocationhandler->destroyer_video_decoder_heaps.push_back(std::make_pair(decoder_heap, framecount)); + allocationhandler->destroyer_video_decoders.push_back(std::make_pair(decoder, framecount)); + allocationhandler->destroylocker.unlock(); + } + }; Resource_DX12* to_internal(const GPUResource* param) { @@ -1519,6 +1561,10 @@ namespace dx12_internal { return static_cast(param->internal_state.get()); } + VideoDecoder_DX12* to_internal(const VideoDecoder* param) + { + return static_cast(param->internal_state.get()); + } inline const std::string GetCachePath() { @@ -1553,7 +1599,7 @@ namespace dx12_internal } using namespace dx12_internal; - // Allocators: + void GraphicsDevice_DX12::CopyAllocator::init(GraphicsDevice_DX12* device) { @@ -1627,6 +1673,11 @@ using namespace dx12_internal; assert(SUCCEEDED(hr)); hr = device->queues[QUEUE_COMPUTE].queue->Wait(cmd.fence.Get(), 1); assert(SUCCEEDED(hr)); + if (device->queues[QUEUE_VIDEO_DECODE].queue) + { + hr = device->queues[QUEUE_VIDEO_DECODE].queue->Wait(cmd.fence.Get(), 1); + assert(SUCCEEDED(hr)); + } locker.lock(); freelist.push_back(cmd); @@ -2098,12 +2149,13 @@ using namespace dx12_internal; // Engine functions - GraphicsDevice_DX12::GraphicsDevice_DX12(ValidationMode validationMode_) + GraphicsDevice_DX12::GraphicsDevice_DX12(ValidationMode validationMode_, GPUPreference preference) { wi::Timer timer; SHADER_IDENTIFIER_SIZE = D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES; TOPLEVEL_ACCELERATION_STRUCTURE_INSTANCE_SIZE = sizeof(D3D12_RAYTRACING_INSTANCE_DESC); + VIDEO_DECODE_BITSTREAM_ALIGNMENT = D3D12_VIDEO_DECODE_MIN_BITSTREAM_OFFSET_ALIGNMENT; validationMode = validationMode_; @@ -2261,9 +2313,10 @@ using namespace dx12_internal; auto NextAdapter = [&](uint32_t index, IDXGIAdapter1** ppAdapter) { if (queryByPreference) - return dxgiFactory6->EnumAdapterByGpuPreference(index, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, IID_PPV_ARGS(ppAdapter)); - else - return dxgiFactory->EnumAdapters1(index, ppAdapter); + { + return dxgiFactory6->EnumAdapterByGpuPreference(index, preference == GPUPreference::Integrated ? DXGI_GPU_PREFERENCE_MINIMUM_POWER : DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, IID_PPV_ARGS(ppAdapter)); + } + return dxgiFactory->EnumAdapters1(index, ppAdapter); }; for (uint32_t i = 0; NextAdapter(i, dxgiAdapter.ReleaseAndGetAddressOf()) != DXGI_ERROR_NOT_FOUND; ++i) @@ -2390,7 +2443,7 @@ using namespace dx12_internal; wi::helper::messageBox(ss.str(), "Error!"); wi::platform::Exit(); } - hr = device->CreateFence(0, D3D12_FENCE_FLAG_SHARED, IID_PPV_ARGS(&queues[QUEUE_GRAPHICS].fence)); + hr = device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&queues[QUEUE_GRAPHICS].fence)); assert(SUCCEEDED(hr)); if (FAILED(hr)) { @@ -2415,7 +2468,7 @@ using namespace dx12_internal; wi::helper::messageBox(ss.str(), "Error!"); wi::platform::Exit(); } - hr = device->CreateFence(0, D3D12_FENCE_FLAG_SHARED, IID_PPV_ARGS(&queues[QUEUE_COMPUTE].fence)); + hr = device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&queues[QUEUE_COMPUTE].fence)); assert(SUCCEEDED(hr)); if (FAILED(hr)) { @@ -2440,7 +2493,7 @@ using namespace dx12_internal; wi::helper::messageBox(ss.str(), "Error!"); wi::platform::Exit(); } - hr = device->CreateFence(0, D3D12_FENCE_FLAG_SHARED, IID_PPV_ARGS(&queues[QUEUE_COPY].fence)); + hr = device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&queues[QUEUE_COPY].fence)); assert(SUCCEEDED(hr)); if (FAILED(hr)) { @@ -2451,6 +2504,34 @@ using namespace dx12_internal; } } + + if (SUCCEEDED(device.As(&video_device))) + { + capabilities |= GraphicsDeviceCapability::VIDEO_DECODE_H264; + queues[QUEUE_VIDEO_DECODE].desc.Type = D3D12_COMMAND_LIST_TYPE_VIDEO_DECODE; + queues[QUEUE_VIDEO_DECODE].desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL; + queues[QUEUE_VIDEO_DECODE].desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queues[QUEUE_VIDEO_DECODE].desc.NodeMask = 0; + hr = device->CreateCommandQueue(&queues[QUEUE_VIDEO_DECODE].desc, IID_PPV_ARGS(&queues[QUEUE_VIDEO_DECODE].queue)); + assert(SUCCEEDED(hr)); + if (FAILED(hr)) + { + std::stringstream ss(""); + ss << "ID3D12Device::CreateCommandQueue[QUEUE_VIDEO_DECODE] failed! ERROR: 0x" << std::hex << hr; + wi::helper::messageBox(ss.str(), "Error!"); + wi::platform::Exit(); + } + hr = device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&queues[QUEUE_VIDEO_DECODE].fence)); + assert(SUCCEEDED(hr)); + if (FAILED(hr)) + { + std::stringstream ss(""); + ss << "ID3D12Device::CreateFence[QUEUE_VIDEO_DECODE] failed! ERROR: 0x" << std::hex << hr; + wi::helper::messageBox(ss.str(), "Error!"); + wi::platform::Exit(); + } + } + rtv_descriptor_size = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); dsv_descriptor_size = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV); resource_descriptor_size = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); @@ -2475,7 +2556,7 @@ using namespace dx12_internal; descriptorheap_res.start_cpu = descriptorheap_res.heap_GPU->GetCPUDescriptorHandleForHeapStart(); descriptorheap_res.start_gpu = descriptorheap_res.heap_GPU->GetGPUDescriptorHandleForHeapStart(); - hr = device->CreateFence(0, D3D12_FENCE_FLAG_SHARED, IID_PPV_ARGS(&descriptorheap_res.fence)); + hr = device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&descriptorheap_res.fence)); assert(SUCCEEDED(hr)); if (FAILED(hr)) { @@ -2511,7 +2592,7 @@ using namespace dx12_internal; descriptorheap_sam.start_cpu = descriptorheap_sam.heap_GPU->GetCPUDescriptorHandleForHeapStart(); descriptorheap_sam.start_gpu = descriptorheap_sam.heap_GPU->GetGPUDescriptorHandleForHeapStart(); - hr = device->CreateFence(0, D3D12_FENCE_FLAG_SHARED, IID_PPV_ARGS(&descriptorheap_sam.fence)); + hr = device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&descriptorheap_sam.fence)); assert(SUCCEEDED(hr)); if (FAILED(hr)) { @@ -3208,6 +3289,8 @@ using namespace dx12_internal; ); } assert(SUCCEEDED(hr)); + if (!SUCCEEDED(hr)) + return false; internal_state->gpu_address = internal_state->resource->GetGPUVirtualAddress(); @@ -3332,6 +3415,12 @@ using namespace dx12_internal; { resourcedesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; } + if (has_flag(desc->misc_flags, ResourceMiscFlag::VIDEO_DECODE)) + { + // Because video queue can only transition from/to VIDEO_ and COMMON states, we will use COMMON internally and rely on implicit transition for DPB textures + // (See how the resource barrier on video queue overrides any user specified state into COMMON) + resourcedesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS; + } switch (texture->desc.type) { @@ -4339,8 +4428,126 @@ using namespace dx12_internal; return SUCCEEDED(hr); } + bool GraphicsDevice_DX12::CreateVideoDecoder(const VideoDesc* desc, VideoDecoder* video_decoder) const + { + if (video_device == nullptr) + return false; - int GraphicsDevice_DX12::CreateSubresource(Texture* texture, SubresourceType type, uint32_t firstSlice, uint32_t sliceCount, uint32_t firstMip, uint32_t mipCount, const Format* format_change) const + HRESULT hr = E_FAIL; + + D3D12_FEATURE_DATA_VIDEO_DECODE_PROFILE_COUNT video_decode_profile_count = {}; + hr = video_device->CheckFeatureSupport(D3D12_FEATURE_VIDEO_DECODE_PROFILE_COUNT, &video_decode_profile_count, sizeof(video_decode_profile_count)); + assert(SUCCEEDED(hr)); + + wi::vector profiles(video_decode_profile_count.ProfileCount); + D3D12_FEATURE_DATA_VIDEO_DECODE_PROFILES video_decode_profiles = {}; + video_decode_profiles.ProfileCount = video_decode_profile_count.ProfileCount; + video_decode_profiles.pProfiles = profiles.data(); + hr = video_device->CheckFeatureSupport(D3D12_FEATURE_VIDEO_DECODE_PROFILES, &video_decode_profiles, sizeof(video_decode_profiles)); + assert(SUCCEEDED(hr)); + + D3D12_VIDEO_DECODER_DESC decoder_desc = {}; + switch (desc->profile) + { + case VideoProfile::H264: + decoder_desc.Configuration.DecodeProfile = D3D12_VIDEO_DECODE_PROFILE_H264; + decoder_desc.Configuration.InterlaceType = D3D12_VIDEO_FRAME_CODED_INTERLACE_TYPE_NONE; + break; + //case VideoProfile::H265: + // decoder_desc.Configuration.DecodeProfile = D3D12_VIDEO_DECODE_PROFILE_HEVC_MAIN; + // break; + default: + assert(0); // not implemented + break; + } + bool profile_valid = false; + for (auto& x : profiles) + { + if (x == decoder_desc.Configuration.DecodeProfile) + { + profile_valid = true; + break; + } + } + if (!profile_valid) + return false; + + D3D12_FEATURE_DATA_VIDEO_DECODE_FORMAT_COUNT video_decode_format_count = {}; + video_decode_format_count.Configuration = decoder_desc.Configuration; + hr = video_device->CheckFeatureSupport(D3D12_FEATURE_VIDEO_DECODE_FORMAT_COUNT, &video_decode_format_count, sizeof(video_decode_format_count)); + assert(SUCCEEDED(hr)); + + wi::vector formats(video_decode_format_count.FormatCount); + D3D12_FEATURE_DATA_VIDEO_DECODE_FORMATS video_decode_formats = {}; + video_decode_formats.Configuration = decoder_desc.Configuration; + video_decode_formats.FormatCount = video_decode_format_count.FormatCount; + video_decode_formats.pOutputFormats = formats.data(); + hr = video_device->CheckFeatureSupport(D3D12_FEATURE_VIDEO_DECODE_FORMATS, &video_decode_formats, sizeof(video_decode_formats)); + assert(SUCCEEDED(hr)); + + D3D12_FEATURE_DATA_VIDEO_DECODE_SUPPORT video_decode_support = {}; + video_decode_support.Configuration = decoder_desc.Configuration; + video_decode_support.DecodeFormat = _ConvertFormat(desc->format); + bool format_valid = false; + for (auto& x : formats) + { + if (x == video_decode_support.DecodeFormat) + { + format_valid = true; + break; + } + } + if (!format_valid) + return false; + video_decode_support.Width = desc->width; + video_decode_support.Height = desc->height; + video_decode_support.BitRate = desc->bit_rate; + video_decode_support.FrameRate = { 0, 1 }; + hr = video_device->CheckFeatureSupport(D3D12_FEATURE_VIDEO_DECODE_SUPPORT, &video_decode_support, sizeof(video_decode_support)); + assert(SUCCEEDED(hr)); + + bool reference_only = video_decode_support.ConfigurationFlags & D3D12_VIDEO_DECODE_CONFIGURATION_FLAG_REFERENCE_ONLY_ALLOCATIONS_REQUIRED; + assert(!reference_only); // Not supported currently, will need to use resource flags: D3D12_RESOURCE_FLAG_VIDEO_DECODE_REFERENCE_ONLY | D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE, and do output decode conversion + + if (video_decode_support.DecodeTier < D3D12_VIDEO_DECODE_TIER_1) + return false; + + auto internal_state = std::make_shared(); + internal_state->allocationhandler = allocationhandler; + video_decoder->internal_state = internal_state; + video_decoder->desc = *desc; + + D3D12_VIDEO_DECODER_HEAP_DESC heap_desc = {}; + heap_desc.Configuration = decoder_desc.Configuration; + heap_desc.DecodeWidth = video_decode_support.Width; + heap_desc.DecodeHeight = video_decode_support.Height; + heap_desc.Format = video_decode_support.DecodeFormat; + heap_desc.FrameRate = { 0,1 }; + heap_desc.BitRate = 0; + heap_desc.MaxDecodePictureBufferCount = desc->num_dpb_slots; + + if (video_decode_support.ConfigurationFlags & D3D12_VIDEO_DECODE_CONFIGURATION_FLAG_HEIGHT_ALIGNMENT_MULTIPLE_32_REQUIRED) + { + heap_desc.DecodeWidth = AlignTo(video_decode_support.Width, 32u); + heap_desc.DecodeHeight = AlignTo(video_decode_support.Height, 32u); + } + +#if 0 + D3D12_FEATURE_DATA_VIDEO_DECODER_HEAP_SIZE video_decoder_heap_size = {}; + video_decoder_heap_size.VideoDecoderHeapDesc = heap_desc; + hr = video_device->CheckFeatureSupport(D3D12_FEATURE_VIDEO_DECODER_HEAP_SIZE, &video_decoder_heap_size, sizeof(video_decoder_heap_size)); + assert(SUCCEEDED(hr)); +#endif + + hr = video_device->CreateVideoDecoderHeap(&heap_desc, IID_PPV_ARGS(&internal_state->decoder_heap)); + assert(SUCCEEDED(hr)); + hr = video_device->CreateVideoDecoder(&decoder_desc, IID_PPV_ARGS(&internal_state->decoder)); + assert(SUCCEEDED(hr)); + + return SUCCEEDED(hr); + } + + int GraphicsDevice_DX12::CreateSubresource(Texture* texture, SubresourceType type, uint32_t firstSlice, uint32_t sliceCount, uint32_t firstMip, uint32_t mipCount, const Format* format_change, const ImageAspect* aspect) const { auto internal_state = to_internal(texture); @@ -4349,6 +4556,11 @@ using namespace dx12_internal; { format = *format_change; } + UINT plane = 0; + if (aspect != nullptr) + { + plane = _ImageAspectToPlane(*aspect); + } switch (type) { @@ -4372,6 +4584,9 @@ using namespace dx12_internal; case Format::D32_FLOAT_S8X24_UINT: srv_desc.Format = DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS; break; + case Format::NV12: + srv_desc.Format = DXGI_FORMAT_R8_UNORM; + break; default: srv_desc.Format = _ConvertFormat(format); break; @@ -4400,7 +4615,7 @@ using namespace dx12_internal; { if (has_flag(texture->desc.misc_flags, ResourceMiscFlag::TEXTURECUBE)) { - if (texture->desc.array_size > 6) + if (texture->desc.array_size > 6 && sliceCount > 6) { srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY; srv_desc.TextureCubeArray.First2DArrayFace = firstSlice; @@ -4430,6 +4645,7 @@ using namespace dx12_internal; srv_desc.Texture2DArray.ArraySize = sliceCount; srv_desc.Texture2DArray.MostDetailedMip = firstMip; srv_desc.Texture2DArray.MipLevels = mipCount; + srv_desc.Texture2DArray.PlaneSlice = plane; } } } @@ -4444,6 +4660,7 @@ using namespace dx12_internal; srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; srv_desc.Texture2D.MostDetailedMip = firstMip; srv_desc.Texture2D.MipLevels = mipCount; + srv_desc.Texture2D.PlaneSlice = plane; } } } @@ -4870,7 +5087,7 @@ using namespace dx12_internal; std::memcpy(dest, identifier, D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES); } - void GraphicsDevice_DX12::SetName(GPUResource* pResource, const char* name) + void GraphicsDevice_DX12::SetName(GPUResource* pResource, const char* name) const { wchar_t text[256]; if (wi::helper::StringConvert(name, text) > 0) @@ -4903,7 +5120,7 @@ using namespace dx12_internal; commandlist.id = cmd_current; commandlist.waited_on.store(false); - if (commandlist.GetGraphicsCommandList() == nullptr) + if (commandlist.GetCommandList() == nullptr) { // need to create one more command list: @@ -4913,11 +5130,22 @@ using namespace dx12_internal; assert(SUCCEEDED(hr)); } - hr = device->CreateCommandList1(0, queues[queue].desc.Type, D3D12_COMMAND_LIST_FLAG_NONE, IID_PPV_ARGS(&commandlist.commandLists[queue])); + if (queue == QUEUE_VIDEO_DECODE) + { + ComPtr videoCommandList; + hr = device->CreateCommandList1(0, queues[queue].desc.Type, D3D12_COMMAND_LIST_FLAG_NONE, IID_PPV_ARGS(&videoCommandList)); + commandlist.commandLists[queue] = videoCommandList; + } + else + { + ComPtr graphicsCommandList; + hr = device->CreateCommandList1(0, queues[queue].desc.Type, D3D12_COMMAND_LIST_FLAG_NONE, IID_PPV_ARGS(&graphicsCommandList)); + commandlist.commandLists[queue] = graphicsCommandList; + } assert(SUCCEEDED(hr)); std::wstring ws = L"cmd" + std::to_wstring(commandlist.id); - commandlist.commandLists[queue]->SetName(ws.c_str()); + commandlist.GetCommandList()->SetName(ws.c_str()); commandlist.binder.init(this); } @@ -4925,12 +5153,21 @@ using namespace dx12_internal; // Start the command list in a default state: hr = commandlist.GetCommandAllocator()->Reset(); assert(SUCCEEDED(hr)); - hr = commandlist.GetGraphicsCommandList()->Reset(commandlist.GetCommandAllocator(), nullptr); - assert(SUCCEEDED(hr)); - if (queue != QUEUE_COPY) + if (queue == QUEUE_VIDEO_DECODE) { - ID3D12DescriptorHeap* heaps[2] = { + hr = commandlist.GetVideoDecodeCommandList()->Reset(commandlist.GetCommandAllocator()); + assert(SUCCEEDED(hr)); + } + else + { + hr = commandlist.GetGraphicsCommandList()->Reset(commandlist.GetCommandAllocator(), nullptr); + assert(SUCCEEDED(hr)); + } + + if (queue == QUEUE_GRAPHICS || queue == QUEUE_COMPUTE) + { + ID3D12DescriptorHeap* heaps[] = { descriptorheap_res.heap_GPU.Get(), descriptorheap_sam.heap_GPU.Get() }; @@ -4963,11 +5200,18 @@ using namespace dx12_internal; for (uint32_t cmd = 0; cmd < cmd_last; ++cmd) { CommandList_DX12& commandlist = *commandlists[cmd].get(); - hr = commandlist.GetGraphicsCommandList()->Close(); + if (commandlist.queue == QUEUE_VIDEO_DECODE) + { + hr = commandlist.GetVideoDecodeCommandList()->Close(); + } + else + { + hr = commandlist.GetGraphicsCommandList()->Close(); + } assert(SUCCEEDED(hr)); CommandQueue& queue = queues[commandlist.queue]; - queue.submit_cmds.push_back(commandlist.GetGraphicsCommandList()); + queue.submit_cmds.push_back(commandlist.GetCommandList()); if (commandlist.waited_on.load() || !commandlist.waits.empty()) { @@ -5126,15 +5370,186 @@ using namespace dx12_internal; break; } + + // Based on: https://github.com/simco50/D3D12_Research/blob/869373829444f029eb3a6ce95dd3aa541c665bb2/D3D12/Graphics/RHI/Graphics.cpp + + //D3D12_AUTO_BREADCRUMB_OP + constexpr const char* OpNames[] = + { + "SetMarker", + "BeginEvent", + "EndEvent", + "DrawInstanced", + "DrawIndexedInstanced", + "ExecuteIndirect", + "Dispatch", + "CopyBufferRegion", + "CopyTextureRegion", + "CopyResource", + "CopyTiles", + "ResolveSubresource", + "ClearRenderTargetView", + "ClearUnorderedAccessView", + "ClearDepthStencilView", + "ResourceBarrier", + "ExecuteBundle", + "Present", + "ResolveQueryData", + "BeginSubmission", + "EndSubmission", + "DecodeFrame", + "ProcessFrames", + "AtomicCopyBufferUint", + "AtomicCopyBufferUint64", + "ResolveSubresourceRegion", + "WriteBufferImmediate", + "DecodeFrame1", + "SetProtectedResourceSession", + "DecodeFrame2", + "ProcessFrames1", + "BuildRaytracingAccelerationStructure", + "EmitRaytracingAccelerationStructurePostBuildInfo", + "CopyRaytracingAccelerationStructure", + "DispatchRays", + "InitializeMetaCommand", + "ExecuteMetaCommand", + "EstimateMotion", + "ResolveMotionVectorHeap", + "SetPipelineState1", + "InitializeExtensionCommand", + "ExecuteExtensionCommand", + "DispatchMesh", + "EncodeFrame", + "ResolveEncoderOutputMetadata", + }; + static_assert(ARRAYSIZE(OpNames) == D3D12_AUTO_BREADCRUMB_OP_RESOLVEENCODEROUTPUTMETADATA + 1, "OpNames array length mismatch"); + + //D3D12_DRED_ALLOCATION_TYPE + constexpr const char* AllocTypesNames[] = + { + "CommandQueue", + "CommandAllocator", + "PipelineState", + "CommandList", + "Fence", + "DescriptorHeap", + "Heap", + "Unknown", + "QueryHeap", + "CommandSignature", + "PipelineLibrary", + "VideoDecoder", + "Unknown", + "VideoProcessor", + "Unknown", + "Resource", + "Pass", + "CryptoSession", + "CryptoSessionPolicy", + "ProtectedResourceSession", + "VideoDecoderHeap", + "CommandPool", + "CommandRecorder", + "StateObjectr", + "MetaCommand", + "SchedulingGroup", + "VideoMotionEstimator", + "VideoMotionVectorHeap", + "VideoExtensionCommand", + "VideoEncoder", + "VideoEncoderHeap", + }; + static_assert(ARRAYSIZE(AllocTypesNames) == D3D12_DRED_ALLOCATION_TYPE_VIDEO_ENCODER_HEAP - D3D12_DRED_ALLOCATION_TYPE_COMMAND_QUEUE + 1, "AllocTypes array length mismatch"); + + std::string log; + ComPtr pDred; if (SUCCEEDED(device->QueryInterface(IID_PPV_ARGS(&pDred)))) { - D3D12_DRED_AUTO_BREADCRUMBS_OUTPUT1 dredAutoBreadcrumbsOutput; - HRESULT hr = pDred->GetAutoBreadcrumbsOutput1(&dredAutoBreadcrumbsOutput); - if (SUCCEEDED(hr)) + D3D12_DRED_AUTO_BREADCRUMBS_OUTPUT1 pDredAutoBreadcrumbsOutput = {}; + if (SUCCEEDED(pDred->GetAutoBreadcrumbsOutput1(&pDredAutoBreadcrumbsOutput))) { - // TODO: Log DRED info -> to file? + log += "[DRED] Last tracked GPU operations:\n"; + + std::map contextStrings; + + const D3D12_AUTO_BREADCRUMB_NODE1* pNode = pDredAutoBreadcrumbsOutput.pHeadAutoBreadcrumbNode; + while (pNode && pNode->pLastBreadcrumbValue) + { + int lastCompletedOp = *pNode->pLastBreadcrumbValue; + + log += std::string("[DRED] Commandlist = [") + (pNode->pCommandListDebugNameA == nullptr ? "-" : pNode->pCommandListDebugNameA) + std::string("], CommandQueue = [") + (pNode->pCommandQueueDebugNameA == nullptr ? "-" : pNode->pCommandQueueDebugNameA) + std::string("], lastCompletedOp = [") + std::to_string(lastCompletedOp) + "], BreadCrumbCount = [" + std::to_string(pNode->BreadcrumbCount) + "]\n"; + + int firstOp = std::max(lastCompletedOp - 100, 0); + int lastOp = std::min(lastCompletedOp + 20, int(pNode->BreadcrumbCount) - 1); + + contextStrings.clear(); + for (uint32_t breadcrumbContext = firstOp; breadcrumbContext < pNode->BreadcrumbContextsCount; ++breadcrumbContext) + { + const D3D12_DRED_BREADCRUMB_CONTEXT& context = pNode->pBreadcrumbContexts[breadcrumbContext]; + contextStrings[context.BreadcrumbIndex] = context.pContextString; + } + + for (int op = firstOp; op <= lastOp; ++op) + { + D3D12_AUTO_BREADCRUMB_OP breadcrumbOp = pNode->pCommandHistory[op]; + + std::string contextString; + auto it = contextStrings.find(op); + if (it != contextStrings.end()) + { + wi::helper::StringConvert(it->second, contextString); + } + + const char* opName = (breadcrumbOp < arraysize(OpNames)) ? OpNames[breadcrumbOp] : "Unknown Op"; + log += "\tOp: " + std::to_string(op) + " " + opName + " " + contextString + "\n"; + } + + if (lastCompletedOp != (int)pNode->BreadcrumbCount) + { + log += "ERROR: lastCompletedOp = " + std::to_string(lastCompletedOp) + ", BreadcrumbCount = " + std::to_string((int)pNode->BreadcrumbCount) + "\n"; + } + + pNode = pNode->pNext; + } } + + D3D12_DRED_PAGE_FAULT_OUTPUT1 DredPageFaultOutput = {}; + if (SUCCEEDED(pDred->GetPageFaultAllocationOutput1(&DredPageFaultOutput)) && DredPageFaultOutput.PageFaultVA != 0) + { + log += "[DRED] PageFault at VA GPUAddress " + std::to_string(DredPageFaultOutput.PageFaultVA) + "\n"; + + const D3D12_DRED_ALLOCATION_NODE1* pNode = DredPageFaultOutput.pHeadExistingAllocationNode; + if (pNode) + { + log += "[DRED] Active objects with VA ranges that match the faulting VA:\n"; + while (pNode) + { + uint32_t alloc_type_index = pNode->AllocationType - D3D12_DRED_ALLOCATION_TYPE_COMMAND_QUEUE; + const char* AllocTypeName = (alloc_type_index < arraysize(AllocTypesNames)) ? AllocTypesNames[alloc_type_index] : "Unknown Alloc"; + log += std::string("\tName: ") + pNode->ObjectNameA + std::string(" ") + AllocTypeName + std::string("\n"); + pNode = pNode->pNext; + } + } + + pNode = DredPageFaultOutput.pHeadRecentFreedAllocationNode; + if (pNode) + { + log += "[DRED] Recent freed objects with VA ranges that match the faulting VA:\n"; + while (pNode) + { + uint32_t allocTypeIndex = pNode->AllocationType - D3D12_DRED_ALLOCATION_TYPE_COMMAND_QUEUE; + const char* AllocTypeName = (allocTypeIndex < arraysize(AllocTypesNames)) ? AllocTypesNames[allocTypeIndex] : "Unknown Alloc"; + log += std::string("\tName: ") + pNode->ObjectNameA + std::string(" (Type: ") + AllocTypeName + std::string(")\n"); + pNode = pNode->pNext; + } + } + } + } + + if (!log.empty()) + { + wi::backlog::post(log, wi::backlog::LogLevel::Error); } std::string message = "D3D12: device removed, cause: "; @@ -6331,12 +6746,13 @@ using namespace dx12_internal; barrierdesc.Transition.pResource = internal_state->resource.Get(); barrierdesc.Transition.StateBefore = _ParseResourceState(barrier.image.layout_before); barrierdesc.Transition.StateAfter = _ParseResourceState(barrier.image.layout_after); - if (barrier.image.mip >= 0 || barrier.image.slice >= 0) + if (barrier.image.mip >= 0 || barrier.image.slice >= 0 || barrier.image.aspect != nullptr) { + const UINT PlaneSlice = barrier.image.aspect != nullptr ? _ImageAspectToPlane(*barrier.image.aspect) : 0; barrierdesc.Transition.Subresource = D3D12CalcSubresource( (UINT)std::max(0, barrier.image.mip), (UINT)std::max(0, barrier.image.slice), - 0, + PlaneSlice, barrier.image.texture->desc.mip_levels, barrier.image.texture->desc.array_size ); @@ -6400,14 +6816,40 @@ using namespace dx12_internal; if (!barrierdescs.empty()) { - commandlist.GetGraphicsCommandList()->ResourceBarrier( - (UINT)barrierdescs.size(), - barrierdescs.data() - ); + if (commandlist.queue == QUEUE_VIDEO_DECODE) + { + // Video queue can only transition from/to VIDEO_ and COMMON states, so we will overwrite anything else to COMMON, + // but the video textures will be using D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS so that implicit transition can happen from COMMON in a different queue + for (auto& barrier : barrierdescs) + { + if (barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_TRANSITION) + { + if (barrier.Transition.StateBefore != D3D12_RESOURCE_STATE_VIDEO_DECODE_READ && barrier.Transition.StateBefore != D3D12_RESOURCE_STATE_VIDEO_DECODE_WRITE) + { + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COMMON; + } + if (barrier.Transition.StateAfter != D3D12_RESOURCE_STATE_VIDEO_DECODE_READ && barrier.Transition.StateAfter != D3D12_RESOURCE_STATE_VIDEO_DECODE_WRITE) + { + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; + } + } + } + commandlist.GetVideoDecodeCommandList()->ResourceBarrier( + (UINT)barrierdescs.size(), + barrierdescs.data() + ); + } + else + { + commandlist.GetGraphicsCommandList()->ResourceBarrier( + (UINT)barrierdescs.size(), + barrierdescs.data() + ); + } barrierdescs.clear(); } - if (!commandlist.discards.empty()) + if (!commandlist.discards.empty() && commandlist.queue != QUEUE_VIDEO_DECODE) { for (auto& discard : commandlist.discards) { @@ -6634,27 +7076,412 @@ using namespace dx12_internal; nullptr ); } + void GraphicsDevice_DX12::VideoDecode(const VideoDecoder* video_decoder, const VideoDecodeOperation* op, CommandList cmd) + { + auto decoder_internal = to_internal(video_decoder); + auto stream_internal = to_internal(op->stream); + auto dpb_internal = to_internal(op->DPB); + D3D12_VIDEO_DECODE_OUTPUT_STREAM_ARGUMENTS output = {}; + D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS input = {}; + + output.pOutputTexture2D = dpb_internal->resource.Get(); + output.OutputSubresource = D3D12CalcSubresource(0, op->current_dpb, 0, 1, op->DPB->desc.array_size); + + const h264::SliceHeader* slice_header = (const h264::SliceHeader*)op->slice_header; + const h264::PPS* pps = (const h264::PPS*)op->pps; + const h264::SPS* sps = (const h264::SPS*)op->sps; + + ID3D12Resource* reference_frames[16] = {}; + UINT reference_subresources[16] = {}; + for (size_t i = 0; i < op->dpb_reference_count; ++i) + { + reference_frames[i] = dpb_internal->resource.Get(); + reference_subresources[i] = D3D12CalcSubresource(0, op->dpb_reference_slots[i], 0, 1, op->DPB->desc.array_size); + } + input.ReferenceFrames.NumTexture2Ds = (UINT)op->dpb_reference_count; + input.ReferenceFrames.ppTexture2Ds = input.ReferenceFrames.NumTexture2Ds > 0 ? reference_frames : nullptr; + input.ReferenceFrames.pSubresources = input.ReferenceFrames.NumTexture2Ds > 0 ? reference_subresources : nullptr; + + input.CompressedBitstream.pBuffer = stream_internal->resource.Get(); + input.CompressedBitstream.Offset = op->stream_offset; + input.CompressedBitstream.Size = op->stream_size; + input.pHeap = decoder_internal->decoder_heap.Get(); + + // DirectX Video Acceleration for H.264/MPEG-4 AVC Decoding, Microsoft, Updated 2010, Page 21 + // https://www.microsoft.com/en-us/download/details.aspx?id=11323 + // Also: https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/src/gallium/drivers/d3d12/d3d12_video_dec_h264.cpp + DXVA_PicParams_H264 pic_params = {}; + pic_params.wFrameWidthInMbsMinus1 = sps->pic_width_in_mbs_minus1; + pic_params.wFrameHeightInMbsMinus1 = sps->pic_height_in_map_units_minus1; + pic_params.IntraPicFlag = op->frame_type == VideoFrameType::Intra ? 1 : 0; + pic_params.MbaffFrameFlag = sps->mb_adaptive_frame_field_flag && !slice_header->field_pic_flag; + pic_params.field_pic_flag = slice_header->field_pic_flag; // 0 = full frame (top and bottom field) + //pic_params.bottom_field_flag = 0; // missing?? + pic_params.chroma_format_idc = 1; // sps->chroma_format_idc; // only 1 is supported (YUV420) + pic_params.bit_depth_chroma_minus8 = sps->bit_depth_chroma_minus8; + assert(pic_params.bit_depth_chroma_minus8 == 0); // Only support for NV12 now + pic_params.bit_depth_luma_minus8 = sps->bit_depth_luma_minus8; + assert(pic_params.bit_depth_luma_minus8 == 0); // Only support for NV12 now + pic_params.residual_colour_transform_flag = sps->separate_colour_plane_flag; // https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/src/gallium/drivers/d3d12/d3d12_video_dec_h264.cpp#L328 + if (pic_params.field_pic_flag) + { + pic_params.CurrPic.AssociatedFlag = slice_header->bottom_field_flag ? 1 : 0; // if pic_params.field_pic_flag == 1, then this is 0 = top field, 1 = bottom_field + } + else + { + pic_params.CurrPic.AssociatedFlag = 0; + } + pic_params.CurrPic.Index7Bits = (UCHAR)op->current_dpb; + pic_params.CurrFieldOrderCnt[0] = op->poc[0]; + pic_params.CurrFieldOrderCnt[1] = op->poc[1]; + for (uint32_t i = 0; i < 16; ++i) + { + pic_params.RefFrameList[i].bPicEntry = 0xFF; + pic_params.FieldOrderCntList[i][0] = 0; + pic_params.FieldOrderCntList[i][1] = 0; + pic_params.FrameNumList[i] = 0; + } + for (size_t i = 0; i < op->dpb_reference_count; ++i) + { + uint32_t ref_slot = op->dpb_reference_slots[i]; + pic_params.RefFrameList[i].AssociatedFlag = 0; // 0 = short term, 1 = long term reference + pic_params.RefFrameList[i].Index7Bits = (UCHAR)ref_slot; + pic_params.FieldOrderCntList[i][0] = op->dpb_poc[ref_slot]; + pic_params.FieldOrderCntList[i][1] = op->dpb_poc[ref_slot]; + pic_params.UsedForReferenceFlags |= 1 << (i * 2 + 0); + pic_params.UsedForReferenceFlags |= 1 << (i * 2 + 1); + pic_params.FrameNumList[i] = op->dpb_framenum[ref_slot]; + } + pic_params.weighted_pred_flag = pps->weighted_pred_flag; + pic_params.weighted_bipred_idc = pps->weighted_bipred_idc; + pic_params.sp_for_switch_flag = 0; + + pic_params.transform_8x8_mode_flag = pps->transform_8x8_mode_flag; + pic_params.constrained_intra_pred_flag = pps->constrained_intra_pred_flag; + pic_params.num_ref_frames = sps->num_ref_frames; + pic_params.MbsConsecutiveFlag = 1; // The value shall be 1 unless the restricted-mode profile in use explicitly supports the value 0. + pic_params.frame_mbs_only_flag = sps->frame_mbs_only_flag; + pic_params.MinLumaBipredSize8x8Flag = 1; + pic_params.RefPicFlag = op->reference_priority > 0 ? 1 : 0; + pic_params.frame_num = slice_header->frame_num; + pic_params.pic_init_qp_minus26 = pps->pic_init_qp_minus26; + pic_params.pic_init_qs_minus26 = pps->pic_init_qs_minus26; + pic_params.chroma_qp_index_offset = pps->chroma_qp_index_offset; + pic_params.second_chroma_qp_index_offset = pps->second_chroma_qp_index_offset; + pic_params.log2_max_frame_num_minus4 = sps->log2_max_frame_num_minus4; + pic_params.pic_order_cnt_type = sps->pic_order_cnt_type; + pic_params.log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_pic_order_cnt_lsb_minus4; + pic_params.delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag; + pic_params.direct_8x8_inference_flag = sps->direct_8x8_inference_flag; + pic_params.entropy_coding_mode_flag = pps->entropy_coding_mode_flag; + pic_params.pic_order_present_flag = pps->pic_order_present_flag; + pic_params.num_slice_groups_minus1 = pps->num_slice_groups_minus1; + assert(pic_params.num_slice_groups_minus1 == 0); // FMO Not supported by VA + pic_params.slice_group_map_type = pps->slice_group_map_type; + pic_params.deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag; + pic_params.redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present_flag; + pic_params.slice_group_change_rate_minus1 = pps->slice_group_change_rate_minus1; + pic_params.Reserved16Bits = 3; // DXVA spec + pic_params.StatusReportFeedbackNumber = (UINT)op->decoded_frame_index + 1; // shall not be 0 + assert(pic_params.StatusReportFeedbackNumber > 0); + pic_params.ContinuationFlag = 1; + input.FrameArguments[input.NumFrameArguments].Type = D3D12_VIDEO_DECODE_ARGUMENT_TYPE_PICTURE_PARAMETERS; + input.FrameArguments[input.NumFrameArguments].Size = sizeof(pic_params); + input.FrameArguments[input.NumFrameArguments].pData = &pic_params; + input.NumFrameArguments++; + + // DirectX Video Acceleration for H.264/MPEG-4 AVC Decoding, Microsoft, Updated 2010, Page 29 + // Also: https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/src/gallium/drivers/d3d12/d3d12_video_dec_h264.cpp#L548 + static constexpr int vl_zscan_normal_16[] = + { + /* Zig-Zag scan pattern */ + 0, 1, 4, 8, 5, 2, 3, 6, + 9, 12, 13, 10, 7, 11, 14, 15 + }; + static constexpr int vl_zscan_normal[] = + { + /* Zig-Zag scan pattern */ + 0, 1, 8,16, 9, 2, 3,10, + 17,24,32,25,18,11, 4, 5, + 12,19,26,33,40,48,41,34, + 27,20,13, 6, 7,14,21,28, + 35,42,49,56,57,50,43,36, + 29,22,15,23,30,37,44,51, + 58,59,52,45,38,31,39,46, + 53,60,61,54,47,55,62,63 + }; + DXVA_Qmatrix_H264 qmatrix = {}; + for (int i = 0; i < 6; ++i) + { + for (int j = 0; j < 16; ++j) + { + qmatrix.bScalingLists4x4[i][j] = pps->ScalingList4x4[i][vl_zscan_normal_16[j]]; + } + } + for (int i = 0; i < 64; ++i) + { + qmatrix.bScalingLists8x8[0][i] = pps->ScalingList8x8[0][vl_zscan_normal[i]]; + qmatrix.bScalingLists8x8[1][i] = pps->ScalingList8x8[1][vl_zscan_normal[i]]; + } + input.FrameArguments[input.NumFrameArguments].Type = D3D12_VIDEO_DECODE_ARGUMENT_TYPE_INVERSE_QUANTIZATION_MATRIX; + input.FrameArguments[input.NumFrameArguments].Size = sizeof(qmatrix); + input.FrameArguments[input.NumFrameArguments].pData = &qmatrix; + input.NumFrameArguments++; + + // DirectX Video Acceleration for H.264/MPEG-4 AVC Decoding, Microsoft, Updated 2010, Page 31 +#if 1 + DXVA_Slice_H264_Short sliceinfo = {}; + sliceinfo.BSNALunitDataLocation = 0; + sliceinfo.SliceBytesInBuffer = (UINT)op->stream_size; + sliceinfo.wBadSliceChopping = 0; // whole slice is in the buffer + input.FrameArguments[input.NumFrameArguments].Type = D3D12_VIDEO_DECODE_ARGUMENT_TYPE_SLICE_CONTROL; + input.FrameArguments[input.NumFrameArguments].Size = sizeof(sliceinfo); + input.FrameArguments[input.NumFrameArguments].pData = &sliceinfo; + input.NumFrameArguments++; +#else + DXVA_Slice_H264_Long sliceinfo = {}; + //sliceinfo.BSNALunitDataLocation = (UINT)op->stream_offset; + sliceinfo.BSNALunitDataLocation = 0; + sliceinfo.SliceBytesInBuffer = (UINT)op->stream_size; + sliceinfo.wBadSliceChopping = 0; + sliceinfo.first_mb_in_slice = slice_header->first_mb_in_slice; + sliceinfo.NumMbsForSlice = 0; + sliceinfo.BitOffsetToSliceData = 0; + sliceinfo.slice_type = slice_header->slice_type; + sliceinfo.luma_log2_weight_denom = slice_header->pwt.luma_log2_weight_denom; + sliceinfo.chroma_log2_weight_denom = slice_header->pwt.chroma_log2_weight_denom; + sliceinfo.num_ref_idx_l0_active_minus1 = slice_header->num_ref_idx_l0_active_minus1; + sliceinfo.num_ref_idx_l1_active_minus1 = slice_header->num_ref_idx_l1_active_minus1; + sliceinfo.slice_alpha_c0_offset_div2 = slice_header->slice_alpha_c0_offset_div2; + sliceinfo.slice_beta_offset_div2 = slice_header->slice_beta_offset_div2; + sliceinfo.slice_qs_delta = slice_header->slice_qs_delta; + sliceinfo.slice_qp_delta = slice_header->slice_qp_delta; + sliceinfo.redundant_pic_cnt = slice_header->redundant_pic_cnt; + sliceinfo.direct_spatial_mv_pred_flag = slice_header->direct_spatial_mv_pred_flag; + sliceinfo.cabac_init_idc = slice_header->cabac_init_idc; + sliceinfo.disable_deblocking_filter_idc = slice_header->disable_deblocking_filter_idc; + sliceinfo.slice_id = 0; // if picture has multiple slices, this identifies the slice id (not supported currently) + std::memset(sliceinfo.RefPicList, 0xFF, sizeof(sliceinfo.RefPicList)); + // L0: + switch (sliceinfo.slice_type) + { + case 2: + case 4: + case 7: + case 9: + // keep 0xFF + break; + default: + for (int j = 0; j < sliceinfo.num_ref_idx_l0_active_minus1; ++j) + { + sliceinfo.RefPicList[0][j] = {}; + sliceinfo.RefPicList[0][j].Index7Bits = op->dpb_reference_slots[j]; + } + break; + } + // L1: + switch (sliceinfo.slice_type) + { + case 0: + case 2: + case 3: + case 4: + case 5: + case 7: + case 8: + case 9: + // keep 0xFF + break; + default: + for (int j = 0; j < sliceinfo.num_ref_idx_l1_active_minus1; ++j) + { + sliceinfo.RefPicList[1][j] = {}; + sliceinfo.RefPicList[1][j].Index7Bits = op->dpb_reference_slots[j]; + } + break; + } + // L0: + for (int j = 0; j < 32; ++j) // weights/offsets + { + for (int k = 0; k < 3; ++k) // y, cb, cr + { + switch (k) + { + default: + case 0: + sliceinfo.Weights[0][j][k][0] = slice_header->pwt.luma_weight_l0[j]; + sliceinfo.Weights[0][j][k][1] = slice_header->pwt.luma_offset_l0[j]; + break; + case 1: + sliceinfo.Weights[0][j][k][0] = slice_header->pwt.chroma_weight_l0[j][0]; + sliceinfo.Weights[0][j][k][1] = slice_header->pwt.chroma_offset_l0[j][0]; + break; + case 2: + sliceinfo.Weights[0][j][k][0] = slice_header->pwt.chroma_weight_l0[j][1]; + sliceinfo.Weights[0][j][k][1] = slice_header->pwt.chroma_offset_l0[j][1]; + break; + } + } + } + // L1: + for (int j = 0; j < 32; ++j) // weights/offsets + { + for (int k = 0; k < 3; ++k) // y, cb, cr + { + switch (k) + { + default: + case 0: + sliceinfo.Weights[1][j][k][0] = slice_header->pwt.luma_weight_l1[j]; + sliceinfo.Weights[1][j][k][1] = slice_header->pwt.luma_offset_l1[j]; + break; + case 1: + sliceinfo.Weights[1][j][k][0] = slice_header->pwt.chroma_weight_l1[j][0]; + sliceinfo.Weights[1][j][k][1] = slice_header->pwt.chroma_offset_l1[j][0]; + break; + case 2: + sliceinfo.Weights[1][j][k][0] = slice_header->pwt.chroma_weight_l1[j][1]; + sliceinfo.Weights[1][j][k][1] = slice_header->pwt.chroma_offset_l1[j][1]; + break; + } + } + } + + input.FrameArguments[input.NumFrameArguments].Type = D3D12_VIDEO_DECODE_ARGUMENT_TYPE_SLICE_CONTROL; + input.FrameArguments[input.NumFrameArguments].Size = sizeof(sliceinfo); + input.FrameArguments[input.NumFrameArguments].pData = &sliceinfo; + input.NumFrameArguments++; +#endif + + CommandList_DX12& commandlist = GetCommandList(cmd); + commandlist.GetVideoDecodeCommandList()->DecodeFrame( + decoder_internal->decoder.Get(), + &output, + &input + ); + + // Debug printout for pic params: +#if 0 + AllocConsole(); + AttachConsole(GetCurrentProcessId()); + HWND Handle = GetConsoleWindow(); + freopen("CON", "w", stdout); + const DXVA_PicParams_H264* pPicParams = &pic_params; + printf("\n=============================================\n"); + printf("wFrameWidthInMbsMinus1 = %d\n", pPicParams->wFrameWidthInMbsMinus1); + printf("wFrameHeightInMbsMinus1 = %d\n", pPicParams->wFrameHeightInMbsMinus1); + printf("CurrPic.Index7Bits = %d\n", pPicParams->CurrPic.Index7Bits); + printf("CurrPic.AssociatedFlag = %d\n", pPicParams->CurrPic.AssociatedFlag); + printf("num_ref_frames = %d\n", pPicParams->num_ref_frames); + printf("sp_for_switch_flag = %d\n", pPicParams->sp_for_switch_flag); + printf("field_pic_flag = %d\n", pPicParams->field_pic_flag); + printf("MbaffFrameFlag = %d\n", pPicParams->MbaffFrameFlag); + printf("residual_colour_transform_flag = %d\n", pPicParams->residual_colour_transform_flag); + printf("chroma_format_idc = %d\n", pPicParams->chroma_format_idc); + printf("RefPicFlag = %d\n", pPicParams->RefPicFlag); + printf("IntraPicFlag = %d\n", pPicParams->IntraPicFlag); + printf("constrained_intra_pred_flag = %d\n", pPicParams->constrained_intra_pred_flag); + printf("MinLumaBipredSize8x8Flag = %d\n", pPicParams->MinLumaBipredSize8x8Flag); + printf("weighted_pred_flag = %d\n", pPicParams->weighted_pred_flag); + printf("weighted_bipred_idc = %d\n", pPicParams->weighted_bipred_idc); + printf("MbsConsecutiveFlag = %d\n", pPicParams->MbsConsecutiveFlag); + printf("frame_mbs_only_flag = %d\n", pPicParams->frame_mbs_only_flag); + printf("transform_8x8_mode_flag = %d\n", pPicParams->transform_8x8_mode_flag); + printf("StatusReportFeedbackNumber = %d\n", pPicParams->StatusReportFeedbackNumber); + printf("CurrFieldOrderCnt[0] = %d\n", pPicParams->CurrFieldOrderCnt[0]); + printf("CurrFieldOrderCnt[1] = %d\n", pPicParams->CurrFieldOrderCnt[1]); + printf("chroma_qp_index_offset = %d\n", pPicParams->chroma_qp_index_offset); + printf("second_chroma_qp_index_offset = %d\n", pPicParams->second_chroma_qp_index_offset); + printf("ContinuationFlag = %d\n", pPicParams->ContinuationFlag); + printf("pic_init_qp_minus26 = %d\n", pPicParams->pic_init_qp_minus26); + printf("pic_init_qs_minus26 = %d\n", pPicParams->pic_init_qs_minus26); + printf("num_ref_idx_l0_active_minus1 = %d\n", pPicParams->num_ref_idx_l0_active_minus1); + printf("num_ref_idx_l1_active_minus1 = %d\n", pPicParams->num_ref_idx_l1_active_minus1); + printf("frame_num = %d\n", pPicParams->frame_num); + printf("log2_max_frame_num_minus4 = %d\n", pPicParams->log2_max_frame_num_minus4); + printf("pic_order_cnt_type = %d\n", pPicParams->pic_order_cnt_type); + printf("log2_max_pic_order_cnt_lsb_minus4 = %d\n", pPicParams->log2_max_pic_order_cnt_lsb_minus4); + printf("delta_pic_order_always_zero_flag = %d\n", pPicParams->delta_pic_order_always_zero_flag); + printf("direct_8x8_inference_flag = %d\n", pPicParams->direct_8x8_inference_flag); + printf("entropy_coding_mode_flag = %d\n", pPicParams->entropy_coding_mode_flag); + printf("pic_order_present_flag = %d\n", pPicParams->pic_order_present_flag); + printf("deblocking_filter_control_present_flag = %d\n", pPicParams->deblocking_filter_control_present_flag); + printf("redundant_pic_cnt_present_flag = %d\n", pPicParams->redundant_pic_cnt_present_flag); + printf("num_slice_groups_minus1 = %d\n", pPicParams->num_slice_groups_minus1); + printf("slice_group_map_type = %d\n", pPicParams->slice_group_map_type); + printf("slice_group_change_rate_minus1 = %d\n", pPicParams->slice_group_change_rate_minus1); + printf("Reserved8BitsB = %d\n", pPicParams->Reserved8BitsB); + printf("UsedForReferenceFlags 0x%08x\n", pPicParams->UsedForReferenceFlags); + printf("NonExistingFrameFlags 0x%08x\n", pPicParams->NonExistingFrameFlags); +#endif + + // Debug immediate submit-wait: +#if 0 + ComPtr fence; + HRESULT hr = device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence)); + assert(SUCCEEDED(hr)); + + //D3D12_RESOURCE_BARRIER bar = {}; + //bar.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + //bar.Transition.pResource = dpb_internal->resource.Get(); + //bar.Transition.StateBefore = D3D12_RESOURCE_STATE_VIDEO_DECODE_WRITE; + //bar.Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; + //bar.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + //commandlist.GetVideoDecodeCommandList()->ResourceBarrier(1, &bar); + + hr = commandlist.GetVideoDecodeCommandList()->Close(); + assert(SUCCEEDED(hr)); + + CommandQueue& queue = queues[commandlist.queue]; + queue.submit_cmds.push_back(commandlist.GetCommandList()); + queue.queue->ExecuteCommandLists( + (UINT)queue.submit_cmds.size(), + queue.submit_cmds.data() + ); + queue.submit_cmds.clear(); + + hr = queue.queue->Signal(fence.Get(), 1); + assert(SUCCEEDED(hr)); + if (fence->GetCompletedValue() < 1) + { + hr = fence->SetEventOnCompletion(1, NULL); + assert(SUCCEEDED(hr)); + } + fence->Signal(0); + + hr = commandlist.GetCommandAllocator()->Reset(); + assert(SUCCEEDED(hr)); + hr = commandlist.GetGraphicsCommandList()->Reset(commandlist.GetCommandAllocator(), nullptr); + assert(SUCCEEDED(hr)); +#endif + } void GraphicsDevice_DX12::EventBegin(const char* name, CommandList cmd) { + CommandList_DX12& commandlist = GetCommandList(cmd); + if (commandlist.queue == QUEUE_VIDEO_DECODE) + return; wchar_t text[128]; if (wi::helper::StringConvert(name, text) > 0) { - CommandList_DX12& commandlist = GetCommandList(cmd); PIXBeginEvent(commandlist.GetGraphicsCommandList(), 0xFF000000, text); } } void GraphicsDevice_DX12::EventEnd(CommandList cmd) { CommandList_DX12& commandlist = GetCommandList(cmd); + if (commandlist.queue == QUEUE_VIDEO_DECODE) + return; PIXEndEvent(commandlist.GetGraphicsCommandList()); } void GraphicsDevice_DX12::SetMarker(const char* name, CommandList cmd) { + CommandList_DX12& commandlist = GetCommandList(cmd); + if (commandlist.queue == QUEUE_VIDEO_DECODE) + return; wchar_t text[128]; if (wi::helper::StringConvert(name, text) > 0) { - CommandList_DX12& commandlist = GetCommandList(cmd); PIXSetMarker(commandlist.GetGraphicsCommandList(), 0xFFFF0000, text); } } diff --git a/WickedEngine/wiGraphicsDevice_DX12.h b/WickedEngine/wiGraphicsDevice_DX12.h index a6c21c414..a4051e021 100644 --- a/WickedEngine/wiGraphicsDevice_DX12.h +++ b/WickedEngine/wiGraphicsDevice_DX12.h @@ -16,6 +16,7 @@ #include // ComPtr #include "Utility/dx12/d3d12.h" +#include "Utility/dx12/d3d12video.h" #define D3D12MA_D3D12_HEADERS_ALREADY_INCLUDED #include "Utility/D3D12MemAlloc.h" @@ -31,6 +32,7 @@ namespace wi::graphics Microsoft::WRL::ComPtr dxgiFactory; Microsoft::WRL::ComPtr dxgiAdapter; Microsoft::WRL::ComPtr device; + Microsoft::WRL::ComPtr video_device; Microsoft::WRL::ComPtr pipelineLibrary; wi::vector pipelineLibraryData; // must be alive while pipelineLibrary object is alive! mutable std::mutex pipelineLibraryLocker; @@ -113,7 +115,9 @@ namespace wi::graphics struct CommandList_DX12 { Microsoft::WRL::ComPtr commandAllocators[BUFFERCOUNT][QUEUE_COUNT]; - Microsoft::WRL::ComPtr commandLists[QUEUE_COUNT]; + Microsoft::WRL::ComPtr commandLists[QUEUE_COUNT]; + using graphics_command_list_version = ID3D12GraphicsCommandList6; + using video_decode_command_list_version = ID3D12VideoDecodeCommandList; uint32_t buffer_index = 0; QUEUE_TYPE queue = {}; @@ -183,9 +187,19 @@ namespace wi::graphics { return commandAllocators[buffer_index][queue].Get(); } - inline ID3D12GraphicsCommandList6* GetGraphicsCommandList() + inline ID3D12CommandList* GetCommandList() { - return (ID3D12GraphicsCommandList6*)commandLists[queue].Get(); + return commandLists[queue].Get(); + } + inline graphics_command_list_version* GetGraphicsCommandList() + { + assert(queue != QUEUE_VIDEO_DECODE); + return (graphics_command_list_version*)commandLists[queue].Get(); + } + inline video_decode_command_list_version* GetVideoDecodeCommandList() + { + assert(queue == QUEUE_VIDEO_DECODE); + return (video_decode_command_list_version*)commandLists[queue].Get(); } }; wi::vector> commandlists; @@ -210,7 +224,7 @@ namespace wi::graphics void predispatch(CommandList cmd); public: - GraphicsDevice_DX12(ValidationMode validationMode = ValidationMode::Disabled); + GraphicsDevice_DX12(ValidationMode validationMode = ValidationMode::Disabled, GPUPreference preference = GPUPreference::Discrete); ~GraphicsDevice_DX12() override; bool CreateSwapChain(const SwapChainDesc* desc, wi::platform::window_type window, SwapChain* swapchain) const override; @@ -222,8 +236,9 @@ namespace wi::graphics bool CreatePipelineState(const PipelineStateDesc* desc, PipelineState* pso, const RenderPassInfo* renderpass_info = nullptr) const override; bool CreateRaytracingAccelerationStructure(const RaytracingAccelerationStructureDesc* desc, RaytracingAccelerationStructure* bvh) const override; bool CreateRaytracingPipelineState(const RaytracingPipelineStateDesc* desc, RaytracingPipelineState* rtpso) const override; - - int CreateSubresource(Texture* texture, SubresourceType type, uint32_t firstSlice, uint32_t sliceCount, uint32_t firstMip, uint32_t mipCount, const Format* format_change = nullptr) const override; + bool CreateVideoDecoder(const VideoDesc* desc, VideoDecoder* video_decoder) const override; + + int CreateSubresource(Texture* texture, SubresourceType type, uint32_t firstSlice, uint32_t sliceCount, uint32_t firstMip, uint32_t mipCount, const Format* format_change = nullptr, const ImageAspect* aspect = nullptr) const override; int CreateSubresource(GPUBuffer* buffer, SubresourceType type, uint64_t offset, uint64_t size = ~0, const Format* format_change = nullptr) const override; int GetDescriptorIndex(const GPUResource* resource, SubresourceType type, int subresource = -1) const override; @@ -233,7 +248,7 @@ namespace wi::graphics void WriteTopLevelAccelerationStructureInstance(const RaytracingAccelerationStructureDesc::TopLevel::Instance* instance, void* dest) const override; void WriteShaderIdentifier(const RaytracingPipelineState* rtpso, uint32_t group_index, void* dest) const override; - void SetName(GPUResource* pResource, const char* name) override; + void SetName(GPUResource* pResource, const char* name) const override; CommandList BeginCommandList(QUEUE_TYPE queue = QUEUE_GRAPHICS) override; void SubmitCommandLists() override; @@ -332,6 +347,7 @@ namespace wi::graphics void PredicationBegin(const GPUBuffer* buffer, uint64_t offset, PredicationOp op, CommandList cmd) override; void PredicationEnd(CommandList cmd) override; void ClearUAV(const GPUResource* resource, uint32_t value, CommandList cmd) override; + void VideoDecode(const VideoDecoder* video_decoder, const VideoDecodeOperation* op, CommandList cmd) override; void EventBegin(const char* name, CommandList cmd) override; void EventEnd(CommandList cmd) override; @@ -444,6 +460,8 @@ namespace wi::graphics std::deque, uint64_t>> destroyer_pipelines; std::deque, uint64_t>> destroyer_rootSignatures; std::deque, uint64_t>> destroyer_stateobjects; + std::deque, uint64_t>> destroyer_video_decoder_heaps; + std::deque, uint64_t>> destroyer_video_decoders; std::deque> destroyer_bindless_res; std::deque> destroyer_bindless_sam; @@ -529,6 +547,30 @@ namespace wi::graphics break; } } + while (!destroyer_video_decoder_heaps.empty()) + { + if (destroyer_video_decoder_heaps.front().second + BUFFERCOUNT < FRAMECOUNT) + { + destroyer_video_decoder_heaps.pop_front(); + // comptr auto delete + } + else + { + break; + } + } + while (!destroyer_video_decoders.empty()) + { + if (destroyer_video_decoders.front().second + BUFFERCOUNT < FRAMECOUNT) + { + destroyer_video_decoders.pop_front(); + // comptr auto delete + } + else + { + break; + } + } while (!destroyer_bindless_res.empty()) { if (destroyer_bindless_res.front().second + BUFFERCOUNT < FRAMECOUNT) diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.cpp b/WickedEngine/wiGraphicsDevice_Vulkan.cpp index ed56210e8..a3d4cb8eb 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.cpp +++ b/WickedEngine/wiGraphicsDevice_Vulkan.cpp @@ -7,6 +7,9 @@ #include "wiTimer.h" #include "wiUnorderedSet.h" +#include "Utility/vulkan/vk_video/vulkan_video_codec_h264std_decode.h" +#include "Utility/h264.h" + #define VOLK_IMPLEMENTATION #include "Utility/volk.h" @@ -25,18 +28,21 @@ #include #include -// These shifts are made so that Vulkan resource bindings slots don't interfere with each other across shader stages: -// These are also defined in wi::shadercompiler.cpp as hard coded compiler arguments for SPIRV, so they need to be the same -#define VULKAN_BINDING_SHIFT_B 0 -#define VULKAN_BINDING_SHIFT_T 1000 -#define VULKAN_BINDING_SHIFT_U 2000 -#define VULKAN_BINDING_SHIFT_S 3000 - namespace wi::graphics { namespace vulkan_internal { + // These shifts are made so that Vulkan resource bindings slots don't interfere with each other across shader stages: + // These are also defined in wi::shadercompiler.cpp as hard coded compiler arguments for SPIRV, so they need to be the same + enum + { + VULKAN_BINDING_SHIFT_B = 0, + VULKAN_BINDING_SHIFT_T = 1000, + VULKAN_BINDING_SHIFT_U = 2000, + VULKAN_BINDING_SHIFT_S = 3000, + }; + // Converters: constexpr VkFormat _ConvertFormat(Format value) { @@ -172,6 +178,8 @@ namespace vulkan_internal return VK_FORMAT_BC7_UNORM_BLOCK; case Format::BC7_UNORM_SRGB: return VK_FORMAT_BC7_SRGB_BLOCK; + case Format::NV12: + return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; } return VK_FORMAT_UNDEFINED; } @@ -343,6 +351,9 @@ namespace vulkan_internal return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; case ResourceState::SHADING_RATE_SOURCE: return VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR; + case ResourceState::VIDEO_DECODE_SRC: + case ResourceState::VIDEO_DECODE_DST: + return VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR; default: return VK_IMAGE_LAYOUT_UNDEFINED; } @@ -382,6 +393,10 @@ namespace vulkan_internal return VK_IMAGE_ASPECT_DEPTH_BIT; case wi::graphics::ImageAspect::STENCIL: return VK_IMAGE_ASPECT_STENCIL_BIT; + case wi::graphics::ImageAspect::LUMINANCE: + return VK_IMAGE_ASPECT_PLANE_0_BIT; + case wi::graphics::ImageAspect::CHROMINANCE: + return VK_IMAGE_ASPECT_PLANE_1_BIT; } } constexpr VkPipelineStageFlags2 _ConvertPipelineStage(ResourceState value) @@ -394,29 +409,24 @@ namespace vulkan_internal { flags |= VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT; } - if (has_flag(value, ResourceState::COPY_SRC) || has_flag(value, ResourceState::COPY_DST)) { flags |= VK_PIPELINE_STAGE_2_TRANSFER_BIT; } - if (has_flag(value, ResourceState::RENDERTARGET)) { flags |= VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT; } - if (has_flag(value, ResourceState::DEPTHSTENCIL) || has_flag(value, ResourceState::DEPTHSTENCIL_READONLY)) { flags |= VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT; } - if (has_flag(value, ResourceState::SHADING_RATE_SOURCE)) { flags |= VK_ACCESS_2_SHADING_RATE_IMAGE_READ_BIT_NV; } - if (has_flag(value, ResourceState::VERTEX_BUFFER)) { flags |= VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT; @@ -441,6 +451,11 @@ namespace vulkan_internal { flags |= VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT; } + if (has_flag(value, ResourceState::VIDEO_DECODE_DST) || + has_flag(value, ResourceState::VIDEO_DECODE_SRC)) + { + flags |= VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR; + } return flags; } @@ -469,7 +484,6 @@ namespace vulkan_internal { flags |= VK_ACCESS_2_TRANSFER_WRITE_BIT; } - if (has_flag(value, ResourceState::RENDERTARGET)) { flags |= VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT; @@ -484,7 +498,6 @@ namespace vulkan_internal { flags |= VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT; } - if (has_flag(value, ResourceState::VERTEX_BUFFER)) { flags |= VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT; @@ -501,11 +514,18 @@ namespace vulkan_internal { flags |= VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT; } - if (has_flag(value, ResourceState::PREDICATION)) { flags |= VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT; } + if (has_flag(value, ResourceState::VIDEO_DECODE_DST)) + { + flags |= VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR; + } + if (has_flag(value, ResourceState::VIDEO_DECODE_SRC)) + { + flags |= VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR; + } return flags; } @@ -707,6 +727,8 @@ namespace vulkan_internal wi::vector mapped_subresources; SparseTextureProperties sparse_texture_properties; + VkImageView video_decode_view = VK_NULL_HANDLE; + ~Texture_Vulkan() { if (allocationhandler == nullptr) @@ -761,6 +783,10 @@ namespace vulkan_internal { allocationhandler->destroyer_imageviews.push_back(std::make_pair(x.image_view, framecount)); } + if (video_decode_view != VK_NULL_HANDLE) + { + allocationhandler->destroyer_imageviews.push_back(std::make_pair(video_decode_view, framecount)); + } allocationhandler->destroylocker.unlock(); } }; @@ -964,6 +990,28 @@ namespace vulkan_internal } }; + struct VideoDecoder_Vulkan + { + std::shared_ptr allocationhandler; + VkVideoSessionKHR video_session = VK_NULL_HANDLE; + VkVideoSessionParametersKHR session_parameters = VK_NULL_HANDLE; + wi::vector allocations; + + ~VideoDecoder_Vulkan() + { + if (allocationhandler == nullptr) + return; + allocationhandler->destroylocker.lock(); + uint64_t framecount = allocationhandler->framecount; + allocationhandler->destroyer_video_sessions.push_back(std::make_pair(video_session, framecount)); + allocationhandler->destroyer_video_session_parameters.push_back(std::make_pair(session_parameters, framecount)); + for (auto& x : allocations) + { + allocationhandler->destroyer_allocations.push_back(std::make_pair(x, framecount)); + } + allocationhandler->destroylocker.unlock(); + } + }; Buffer_Vulkan* to_internal(const GPUBuffer* param) { @@ -1001,10 +1049,14 @@ namespace vulkan_internal { return static_cast(param->internal_state.get()); } + VideoDecoder_Vulkan* to_internal(const VideoDecoder* param) + { + return static_cast(param->internal_state.get()); + } inline const std::string GetCachePath() { - return wi::helper::GetTempDirectoryPath() + "wiPipelineCache_Vulkan"; + return wi::helper::GetTempDirectoryPath() + "/wiPipelineCache_Vulkan"; } bool CreateSwapChainInternal( @@ -1059,6 +1111,7 @@ namespace vulkan_internal } if (!valid) { + internal_state->desc.format = Format::B8G8R8A8_UNORM; surfaceFormat.format = VK_FORMAT_B8G8R8A8_UNORM; surfaceFormat.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; } @@ -1211,7 +1264,10 @@ using namespace vulkan_internal; void GraphicsDevice_Vulkan::CommandQueue::submit(GraphicsDevice_Vulkan* device, VkFence fence) { - locker.lock(); + if (queue == VK_NULL_HANDLE) + return; + std::scoped_lock lock(locker); + VkSubmitInfo2 submitInfo = {}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2; submitInfo.commandBufferInfoCount = (uint32_t)submit_cmds.size(); @@ -1262,7 +1318,6 @@ using namespace vulkan_internal; submit_signalSemaphores.clear(); submit_signalSemaphoreInfos.clear(); submit_cmds.clear(); - locker.unlock(); } void GraphicsDevice_Vulkan::CopyAllocator::init(GraphicsDevice_Vulkan* device) @@ -1276,8 +1331,10 @@ using namespace vulkan_internal; { vkDestroyCommandPool(device->device, x.transferCommandPool, nullptr); vkDestroyCommandPool(device->device, x.transitionCommandPool, nullptr); - vkDestroySemaphore(device->device, x.semaphores[0], nullptr); - vkDestroySemaphore(device->device, x.semaphores[1], nullptr); + for (auto& sema : x.semaphores) + { + vkDestroySemaphore(device->device, sema, nullptr); + } vkDestroyFence(device->device, x.fence, nullptr); } } @@ -1337,6 +1394,8 @@ using namespace vulkan_internal; assert(res == VK_SUCCESS); res = vkCreateSemaphore(device->device, &semaphoreInfo, nullptr, &cmd.semaphores[1]); assert(res == VK_SUCCESS); + res = vkCreateSemaphore(device->device, &semaphoreInfo, nullptr, &cmd.semaphores[2]); + assert(res == VK_SUCCESS); GPUBufferDesc uploaddesc; uploaddesc.size = wi::math::GetNextPowerOfTwo(staging_size); @@ -1374,61 +1433,96 @@ using namespace vulkan_internal; res = vkEndCommandBuffer(cmd.transitionCommandBuffer); assert(res == VK_SUCCESS); - VkCommandBufferSubmitInfo cbSubmitInfo{}; - cbSubmitInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO; - cbSubmitInfo.commandBuffer = cmd.transferCommandBuffer; - - VkSemaphoreSubmitInfo signalSemaphoreInfo{}; - signalSemaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO; - signalSemaphoreInfo.semaphore = cmd.semaphores[0]; - VkSubmitInfo2 submitInfo = {}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2; - submitInfo.commandBufferInfoCount = 1; - submitInfo.pCommandBufferInfos = &cbSubmitInfo; - submitInfo.signalSemaphoreInfoCount = 1; - submitInfo.pSignalSemaphoreInfos = &signalSemaphoreInfo; - device->queues[QUEUE_COPY].locker.lock(); - res = vkQueueSubmit2(device->queues[QUEUE_COPY].queue, 1, &submitInfo, VK_NULL_HANDLE); - assert(res == VK_SUCCESS); - device->queues[QUEUE_COPY].locker.unlock(); - VkSemaphoreSubmitInfo waitSemaphoreInfo{}; + VkCommandBufferSubmitInfo cbSubmitInfo = {}; + cbSubmitInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO; + + VkSemaphoreSubmitInfo signalSemaphoreInfos[2] = {}; + signalSemaphoreInfos[0].sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO; + signalSemaphoreInfos[1].sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO; + + VkSemaphoreSubmitInfo waitSemaphoreInfo = {}; waitSemaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO; - waitSemaphoreInfo.semaphore = cmd.semaphores[0]; - waitSemaphoreInfo.stageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT; - cbSubmitInfo.commandBuffer = cmd.transitionCommandBuffer; - signalSemaphoreInfo.semaphore = cmd.semaphores[1]; - - submitInfo.waitSemaphoreInfoCount = 1; - submitInfo.pWaitSemaphoreInfos = &waitSemaphoreInfo; - submitInfo.commandBufferInfoCount = 1; - submitInfo.pCommandBufferInfos = &cbSubmitInfo; - submitInfo.signalSemaphoreInfoCount = 1; - submitInfo.pSignalSemaphoreInfos = &signalSemaphoreInfo; + { + cbSubmitInfo.commandBuffer = cmd.transferCommandBuffer; + signalSemaphoreInfos[0].semaphore = cmd.semaphores[0]; // signal for graphics queue - device->queues[QUEUE_GRAPHICS].locker.lock(); - res = vkQueueSubmit2(device->queues[QUEUE_GRAPHICS].queue, 1, &submitInfo, VK_NULL_HANDLE); - assert(res == VK_SUCCESS); - device->queues[QUEUE_GRAPHICS].locker.unlock(); + submitInfo.commandBufferInfoCount = 1; + submitInfo.pCommandBufferInfos = &cbSubmitInfo; + submitInfo.signalSemaphoreInfoCount = 1; + submitInfo.pSignalSemaphoreInfos = signalSemaphoreInfos; - waitSemaphoreInfo.semaphore = cmd.semaphores[1]; - submitInfo.waitSemaphoreInfoCount = 1; - submitInfo.pWaitSemaphoreInfos = &waitSemaphoreInfo; - submitInfo.commandBufferInfoCount = 0; - submitInfo.pCommandBufferInfos = nullptr; - submitInfo.signalSemaphoreInfoCount = 0; - submitInfo.pSignalSemaphoreInfos = nullptr; + std::scoped_lock lock(device->queues[QUEUE_COPY].locker); + res = vkQueueSubmit2(device->queues[QUEUE_COPY].queue, 1, &submitInfo, VK_NULL_HANDLE); + assert(res == VK_SUCCESS); + } - device->queues[QUEUE_COMPUTE].locker.lock(); - res = vkQueueSubmit2(device->queues[QUEUE_COMPUTE].queue, 1, &submitInfo, cmd.fence); // final submit also signals fence! - assert(res == VK_SUCCESS); - device->queues[QUEUE_COMPUTE].locker.unlock(); + { + waitSemaphoreInfo.semaphore = cmd.semaphores[0]; // wait for copy queue + waitSemaphoreInfo.stageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT; - locker.lock(); + cbSubmitInfo.commandBuffer = cmd.transitionCommandBuffer; + signalSemaphoreInfos[0].semaphore = cmd.semaphores[1]; // signal for compute queue + signalSemaphoreInfos[1].semaphore = cmd.semaphores[2]; // signal for video decode queue + + submitInfo.waitSemaphoreInfoCount = 1; + submitInfo.pWaitSemaphoreInfos = &waitSemaphoreInfo; + submitInfo.commandBufferInfoCount = 1; + submitInfo.pCommandBufferInfos = &cbSubmitInfo; + if (device->queues[QUEUE_VIDEO_DECODE].queue != VK_NULL_HANDLE) + { + submitInfo.signalSemaphoreInfoCount = 2; + } + else + { + submitInfo.signalSemaphoreInfoCount = 1; + } + submitInfo.pSignalSemaphoreInfos = signalSemaphoreInfos; + + std::scoped_lock lock(device->queues[QUEUE_GRAPHICS].locker); + res = vkQueueSubmit2(device->queues[QUEUE_GRAPHICS].queue, 1, &submitInfo, VK_NULL_HANDLE); + assert(res == VK_SUCCESS); + } + + if (device->queues[QUEUE_VIDEO_DECODE].queue != VK_NULL_HANDLE) + { + waitSemaphoreInfo.semaphore = cmd.semaphores[2]; // wait for graphics queue + waitSemaphoreInfo.stageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT; + + submitInfo.waitSemaphoreInfoCount = 1; + submitInfo.pWaitSemaphoreInfos = &waitSemaphoreInfo; + submitInfo.commandBufferInfoCount = 0; + submitInfo.pCommandBufferInfos = nullptr; + submitInfo.signalSemaphoreInfoCount = 0; + submitInfo.pSignalSemaphoreInfos = nullptr; + + std::scoped_lock lock(device->queues[QUEUE_VIDEO_DECODE].locker); + res = vkQueueSubmit2(device->queues[QUEUE_VIDEO_DECODE].queue, 1, &submitInfo, VK_NULL_HANDLE); + assert(res == VK_SUCCESS); + } + + // This must be final submit in this function because it will also signal a fence for state tracking by CPU! + { + waitSemaphoreInfo.semaphore = cmd.semaphores[1]; // wait for graphics queue + waitSemaphoreInfo.stageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT; + + submitInfo.waitSemaphoreInfoCount = 1; + submitInfo.pWaitSemaphoreInfos = &waitSemaphoreInfo; + submitInfo.commandBufferInfoCount = 0; + submitInfo.pCommandBufferInfos = nullptr; + submitInfo.signalSemaphoreInfoCount = 0; + submitInfo.pSignalSemaphoreInfos = nullptr; + + std::scoped_lock lock(device->queues[QUEUE_COMPUTE].locker); + res = vkQueueSubmit2(device->queues[QUEUE_COMPUTE].queue, 1, &submitInfo, cmd.fence); // final submit also signals fence! + assert(res == VK_SUCCESS); + } + + std::scoped_lock lock(locker); freelist.push_back(cmd); - locker.unlock(); } void GraphicsDevice_Vulkan::DescriptorBinderPool::init(GraphicsDevice_Vulkan* device) @@ -2192,7 +2286,7 @@ using namespace vulkan_internal; } // Engine functions - GraphicsDevice_Vulkan::GraphicsDevice_Vulkan(wi::platform::window_type window, ValidationMode validationMode_) + GraphicsDevice_Vulkan::GraphicsDevice_Vulkan(wi::platform::window_type window, ValidationMode validationMode_, GPUPreference preference) { wi::Timer timer; @@ -2374,6 +2468,8 @@ using namespace vulkan_internal; }; wi::vector enabled_deviceExtensions; + bool h264_decode_extension = false; + for (const auto& dev : devices) { bool suitable = true; @@ -2395,6 +2491,8 @@ using namespace vulkan_internal; if (!suitable) continue; + h264_decode_extension = false; + features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; features_1_1.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES; features_1_2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; @@ -2505,15 +2603,29 @@ using namespace vulkan_internal; features_chain = &conditional_rendering_features.pNext; } + if (checkExtensionSupport(VK_KHR_VIDEO_QUEUE_EXTENSION_NAME, available_deviceExtensions) && + checkExtensionSupport(VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME, available_deviceExtensions) && + checkExtensionSupport(VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME, available_deviceExtensions)) + { + enabled_deviceExtensions.push_back(VK_KHR_VIDEO_QUEUE_EXTENSION_NAME); + enabled_deviceExtensions.push_back(VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME); + enabled_deviceExtensions.push_back(VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME); + h264_decode_extension = true; + } + vkGetPhysicalDeviceProperties2(dev, &properties2); - bool discrete = properties2.properties.deviceType == VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU; - if (discrete || physicalDevice == VK_NULL_HANDLE) + bool priority = properties2.properties.deviceType == VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU; + if (preference == GPUPreference::Integrated) + { + priority = properties2.properties.deviceType == VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU; + } + if (priority || physicalDevice == VK_NULL_HANDLE) { physicalDevice = dev; - if (discrete) + if (priority) { - break; // if this is discrete GPU, look no further (prioritize discrete GPU) + break; // if this is prioritized GPU type, look no further } } } @@ -2663,94 +2775,138 @@ using namespace vulkan_internal; capabilities |= GraphicsDeviceCapability::STENCIL_RESOLVE_MIN_MAX; } + if(h264_decode_extension) + { + decode_h264_profile.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR; + decode_h264_profile.stdProfileIdc = STD_VIDEO_H264_PROFILE_IDC_HIGH; + decode_h264_profile.pictureLayout = VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_KHR; + + decode_h264_capabilities.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_KHR; + + video_capability_h264.profile.sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR; + video_capability_h264.profile.pNext = &decode_h264_profile; + video_capability_h264.profile.videoCodecOperation = VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR; + video_capability_h264.profile.lumaBitDepth = VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR; + video_capability_h264.profile.chromaBitDepth = VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR; + video_capability_h264.profile.chromaSubsampling = VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR; + + video_capability_h264.decode_capabilities.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_CAPABILITIES_KHR; + + video_capability_h264.video_capabilities.sType = VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR; + video_capability_h264.video_capabilities.pNext = &video_capability_h264.decode_capabilities; + video_capability_h264.decode_capabilities.pNext = &decode_h264_capabilities; + res = vkGetPhysicalDeviceVideoCapabilitiesKHR(physicalDevice, &video_capability_h264.profile, &video_capability_h264.video_capabilities); + assert(res == VK_SUCCESS); + + if (video_capability_h264.decode_capabilities.flags) + { + capabilities |= GraphicsDeviceCapability::VIDEO_DECODE_H264; + VIDEO_DECODE_BITSTREAM_ALIGNMENT = std::max(VIDEO_DECODE_BITSTREAM_ALIGNMENT, video_capability_h264.video_capabilities.minBitstreamBufferOffsetAlignment); + VIDEO_DECODE_BITSTREAM_ALIGNMENT = std::max(VIDEO_DECODE_BITSTREAM_ALIGNMENT, video_capability_h264.video_capabilities.minBitstreamBufferSizeAlignment); + } + } + // Find queue families: uint32_t queueFamilyCount = 0; - vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, nullptr); + vkGetPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueFamilyCount, nullptr); queueFamilies.resize(queueFamilyCount); - vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, queueFamilies.data()); - - // Query base queue families: - uint32_t familyIndex = 0; - for (const auto& queueFamily : queueFamilies) + queueFamiliesVideo.resize(queueFamilyCount); + for (uint32_t i = 0; i < queueFamilyCount; ++i) { - if (graphicsFamily == VK_QUEUE_FAMILY_IGNORED && queueFamily.queueCount > 0 && queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) + queueFamilies[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2; + queueFamilies[i].pNext = &queueFamiliesVideo[i]; + queueFamiliesVideo[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR; + } + vkGetPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueFamilyCount, queueFamilies.data()); + + // Query base queue families: + for (uint32_t i = 0; i < queueFamilyCount; ++i) + { + auto& queueFamily = queueFamilies[i]; + auto& queueFamilyVideo = queueFamiliesVideo[i]; + + if (graphicsFamily == VK_QUEUE_FAMILY_IGNORED && queueFamily.queueFamilyProperties.queueCount > 0 && queueFamily.queueFamilyProperties.queueFlags & VK_QUEUE_GRAPHICS_BIT) { - graphicsFamily = familyIndex; - if (queueFamily.queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) + graphicsFamily = i; + if (queueFamily.queueFamilyProperties.queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) { queues[QUEUE_GRAPHICS].sparse_binding_supported = true; } } - if (copyFamily == VK_QUEUE_FAMILY_IGNORED && queueFamily.queueCount > 0 && queueFamily.queueFlags & VK_QUEUE_TRANSFER_BIT) + if (copyFamily == VK_QUEUE_FAMILY_IGNORED && queueFamily.queueFamilyProperties.queueCount > 0 && queueFamily.queueFamilyProperties.queueFlags & VK_QUEUE_TRANSFER_BIT) { - copyFamily = familyIndex; + copyFamily = i; } - if (computeFamily == VK_QUEUE_FAMILY_IGNORED && queueFamily.queueCount > 0 && queueFamily.queueFlags & VK_QUEUE_COMPUTE_BIT) + if (computeFamily == VK_QUEUE_FAMILY_IGNORED && queueFamily.queueFamilyProperties.queueCount > 0 && queueFamily.queueFamilyProperties.queueFlags & VK_QUEUE_COMPUTE_BIT) { - computeFamily = familyIndex; + computeFamily = i; } - familyIndex++; + if (videoFamily == VK_QUEUE_FAMILY_IGNORED && + queueFamily.queueFamilyProperties.queueCount > 0 && + (queueFamily.queueFamilyProperties.queueFlags & VK_QUEUE_VIDEO_DECODE_BIT_KHR) && + (queueFamilyVideo.videoCodecOperations & VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) + ) + { + videoFamily = i; + } } // Now try to find dedicated compute and transfer queues: - familyIndex = 0; - for (const auto& queueFamily : queueFamilies) + for (uint32_t i = 0; i < queueFamilyCount; ++i) { - if (queueFamily.queueCount > 0 && (queueFamily.queueFlags == VK_QUEUE_TRANSFER_BIT)) - { - copyFamily = familyIndex; - } - else if (queueFamily.queueCount > 0 && queueFamily.queueFlags == (VK_QUEUE_TRANSFER_BIT | VK_QUEUE_SPARSE_BINDING_BIT)) - { - copyFamily = familyIndex; - queues[QUEUE_COPY].sparse_binding_supported = true; - } + auto& queueFamily = queueFamilies[i]; - if (queueFamily.queueCount > 0 && - queueFamily.queueFlags & VK_QUEUE_COMPUTE_BIT && - !(queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) + if (queueFamily.queueFamilyProperties.queueCount > 0 && + queueFamily.queueFamilyProperties.queueFlags & VK_QUEUE_TRANSFER_BIT && + !(queueFamily.queueFamilyProperties.queueFlags & VK_QUEUE_GRAPHICS_BIT) && + !(queueFamily.queueFamilyProperties.queueFlags & VK_QUEUE_COMPUTE_BIT) ) { - computeFamily = familyIndex; + copyFamily = i; - if (queueFamily.queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) + if (queueFamily.queueFamilyProperties.queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) + { + queues[QUEUE_COPY].sparse_binding_supported = true; + } + } + + if (queueFamily.queueFamilyProperties.queueCount > 0 && + queueFamily.queueFamilyProperties.queueFlags & VK_QUEUE_COMPUTE_BIT && + !(queueFamily.queueFamilyProperties.queueFlags & VK_QUEUE_GRAPHICS_BIT) + ) + { + computeFamily = i; + + if (queueFamily.queueFamilyProperties.queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) { queues[QUEUE_COMPUTE].sparse_binding_supported = true; } } - - familyIndex++; } - // If the above search found no transfer family, fall back to the less strict exclusivity criteria - if (copyFamily == VK_QUEUE_FAMILY_IGNORED) + // Now try to find dedicated transfer queue with only transfer and sparse flags: + // (This is a workaround for a driver bug with sparse updating from transfer queue) + for (uint32_t i = 0; i < queueFamilyCount; ++i) { - familyIndex = 0; - for (const auto& queueFamily : queueFamilies) - { - if (queueFamily.queueCount > 0 && - queueFamily.queueFlags & VK_QUEUE_TRANSFER_BIT && - !(queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) && - !(queueFamily.queueFlags & VK_QUEUE_COMPUTE_BIT) - ) - { - copyFamily = familyIndex; + auto& queueFamily = queueFamilies[i]; - if (queueFamily.queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) - { - queues[QUEUE_COPY].sparse_binding_supported = true; - } - } - familyIndex++; + if (queueFamily.queueFamilyProperties.queueCount > 0 && queueFamily.queueFamilyProperties.queueFlags == (VK_QUEUE_TRANSFER_BIT | VK_QUEUE_SPARSE_BINDING_BIT)) + { + copyFamily = i; + queues[QUEUE_COPY].sparse_binding_supported = true; } } wi::vector queueCreateInfos; wi::unordered_set uniqueQueueFamilies = { graphicsFamily,copyFamily,computeFamily }; + if (videoFamily != VK_QUEUE_FAMILY_IGNORED) + { + uniqueQueueFamilies.insert(videoFamily); + } float queuePriority = 1.0f; for (uint32_t queueFamily : uniqueQueueFamilies) @@ -2789,10 +2945,15 @@ using namespace vulkan_internal; vkGetDeviceQueue(device, graphicsFamily, 0, &graphicsQueue); vkGetDeviceQueue(device, computeFamily, 0, &computeQueue); vkGetDeviceQueue(device, copyFamily, 0, ©Queue); + if (videoFamily != VK_QUEUE_FAMILY_IGNORED) + { + vkGetDeviceQueue(device, videoFamily, 0, &videoQueue); + } queues[QUEUE_GRAPHICS].queue = graphicsQueue; queues[QUEUE_COMPUTE].queue = computeQueue; queues[QUEUE_COPY].queue = copyQueue; + queues[QUEUE_VIDEO_DECODE].queue = videoQueue; VkSemaphoreTypeCreateInfo timelineCreateInfo = {}; timelineCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO; @@ -2826,6 +2987,16 @@ using namespace vulkan_internal; wi::helper::messageBox("vkCreateSemaphore[QUEUE_COPY] failed! ERROR: " + std::to_string(res), "Error!"); wi::platform::Exit(); } + if (videoQueue != VK_NULL_HANDLE) + { + res = vkCreateSemaphore(device, &createInfo, nullptr, &queues[QUEUE_VIDEO_DECODE].semaphore); + assert(res == VK_SUCCESS); + if (res != VK_SUCCESS) + { + wi::helper::messageBox("vkCreateSemaphore[QUEUE_VIDEO_DECODE] failed! ERROR: " + std::to_string(res), "Error!"); + wi::platform::Exit(); + } + } } memory_properties_2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2; @@ -2901,6 +3072,9 @@ using namespace vulkan_internal; { for (int queue = 0; queue < QUEUE_COUNT; ++queue) { + if (queues[queue].queue == VK_NULL_HANDLE) + continue; + VkFenceCreateInfo fenceInfo = {}; fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; //fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; @@ -3383,6 +3557,11 @@ using namespace vulkan_internal; vkDestroyImageView(device, nullImageView3D, nullptr); vkDestroySampler(device, nullSampler, nullptr); + for (VkSampler sam : immutable_samplers) + { + vkDestroySampler(device, sam, nullptr); + } + if (pipelineCache != VK_NULL_HANDLE) { // Get size of pipeline cache @@ -3453,7 +3632,7 @@ using namespace vulkan_internal; res = vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, (uint32_t)familyIndex, internal_state->surface, &presentSupport); assert(res == VK_SUCCESS); - if (presentFamily == VK_QUEUE_FAMILY_IGNORED && queueFamily.queueCount > 0 && presentSupport) + if (presentFamily == VK_QUEUE_FAMILY_IGNORED && queueFamily.queueFamilyProperties.queueCount > 0 && presentSupport) { presentFamily = familyIndex; break; @@ -3468,7 +3647,13 @@ using namespace vulkan_internal; return false; } - return CreateSwapChainInternal(internal_state.get(), physicalDevice, device, allocationhandler); + bool success = CreateSwapChainInternal(internal_state.get(), physicalDevice, device, allocationhandler); + assert(success); + + // The requested swapchain format is overridden if it wasn't supported: + swapchain->desc.format = internal_state->desc.format; + + return success; } bool GraphicsDevice_Vulkan::CreateBuffer2(const GPUBufferDesc* desc, const std::function& init_callback, GPUBuffer* buffer) const { @@ -3531,9 +3716,24 @@ using namespace vulkan_internal; { bufferInfo.usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; } + if (has_flag(buffer->desc.misc_flags, ResourceMiscFlag::VIDEO_DECODE)) + { + bufferInfo.usage |= VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR; + } bufferInfo.usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT; bufferInfo.usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; + VkVideoProfileListInfoKHR profile_list_info = {}; + profile_list_info.sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR; + profile_list_info.pProfiles = &video_capability_h264.profile; + profile_list_info.profileCount = 1; + if ((bufferInfo.usage & VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR) || + (bufferInfo.usage & VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR) + ) + { + bufferInfo.pNext = &profile_list_info; + } + bufferInfo.flags = 0; if (families.size() > 1) @@ -3798,6 +3998,48 @@ using namespace vulkan_internal; { imageInfo.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; } + if (has_flag(texture->desc.misc_flags, ResourceMiscFlag::VIDEO_DECODE)) + { + imageInfo.usage |= VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR; + imageInfo.usage |= VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR; + imageInfo.usage |= VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR; + } + + if (desc->format == Format::NV12 && has_flag(texture->desc.bind_flags, BindFlag::SHADER_RESOURCE)) + { + imageInfo.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; + } + + VkVideoProfileListInfoKHR profile_list_info = {}; + profile_list_info.sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR; + profile_list_info.pProfiles = &video_capability_h264.profile; + profile_list_info.profileCount = 1; + if ((imageInfo.usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR) || + (imageInfo.usage & VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR) || + (imageInfo.usage & VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR) + ) + { + imageInfo.pNext = &profile_list_info; + + VkPhysicalDeviceVideoFormatInfoKHR video_format_info = {}; + video_format_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR; + video_format_info.imageUsage = imageInfo.usage; + video_format_info.pNext = &profile_list_info; + uint32_t format_property_count = 0; + VkResult res = vkGetPhysicalDeviceVideoFormatPropertiesKHR(physicalDevice, &video_format_info, &format_property_count, nullptr); + assert(res == VK_SUCCESS); + + wi::vector video_format_properties(format_property_count); + for (auto& x : video_format_properties) + { + x.sType = VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR; + } + res = vkGetPhysicalDeviceVideoFormatPropertiesKHR(physicalDevice, &video_format_info, &format_property_count, video_format_properties.data()); + assert(res == VK_SUCCESS); + + //assert(imageInfo.flags == 0 || (!video_format_properties.empty() && video_format_properties[0].imageCreateFlags & imageInfo.flags)); + //assert(!video_format_properties.empty() && video_format_properties[0].imageUsageFlags & imageInfo.usage); + } if (families.size() > 1) { @@ -4114,7 +4356,7 @@ using namespace vulkan_internal; copyAllocator.submit(cmd); } } - else + else if(texture->desc.layout != ResourceState::UNDEFINED) { VkImageMemoryBarrier2 barrier = {}; barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2; @@ -4172,6 +4414,29 @@ using namespace vulkan_internal; CreateSubresource(texture, SubresourceType::UAV, 0, -1, 0, -1); } + if (has_flag(texture->desc.misc_flags, ResourceMiscFlag::VIDEO_DECODE)) + { + VkImageViewCreateInfo view_desc = {}; + view_desc.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + view_desc.flags = 0; + view_desc.image = internal_state->resource; + view_desc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + view_desc.subresourceRange.baseArrayLayer = 0; + view_desc.subresourceRange.layerCount = imageInfo.arrayLayers; + view_desc.subresourceRange.baseMipLevel = 0; + view_desc.subresourceRange.levelCount = imageInfo.mipLevels; + view_desc.format = imageInfo.format; + view_desc.viewType = imageInfo.arrayLayers > 1 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D; + + VkImageViewUsageCreateInfo viewUsageInfo = {}; + viewUsageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO; + viewUsageInfo.usage = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR | VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR | VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR; + view_desc.pNext = &viewUsageInfo; + + res = vkCreateImageView(device, &view_desc, nullptr, &internal_state->video_decode_view); + assert(res == VK_SUCCESS); + } + return res == VK_SUCCESS; } bool GraphicsDevice_Vulkan::CreateShader(ShaderStage stage, const void* shadercode, size_t shadercode_size, Shader* shader) const @@ -5228,10 +5493,6 @@ using namespace vulkan_internal; pipelineInfo.pDynamicState = &dynamicStateInfo; - if (desc->il == nullptr) - { - } - if (renderpass_info != nullptr) { // MSAA: @@ -5684,8 +5945,313 @@ using namespace vulkan_internal; return res == VK_SUCCESS; } - - int GraphicsDevice_Vulkan::CreateSubresource(Texture* texture, SubresourceType type, uint32_t firstSlice, uint32_t sliceCount, uint32_t firstMip, uint32_t mipCount, const Format* format_change) const + bool GraphicsDevice_Vulkan::CreateVideoDecoder(const VideoDesc* desc, VideoDecoder* video_decoder) const + { + VkResult res = VK_SUCCESS; + + auto internal_state = std::make_shared(); + internal_state->allocationhandler = allocationhandler; + video_decoder->internal_state = internal_state; + video_decoder->desc = *desc; + + wi::vector pps_array_h264(desc->pps_count); + wi::vector scalinglist_array_h264(desc->pps_count); + for (uint32_t i = 0; i < desc->pps_count; ++i) + { + const h264::PPS* pps = (const h264::PPS*)desc->pps_datas + i; + StdVideoH264PictureParameterSet& vk_pps = pps_array_h264[i]; + StdVideoH264ScalingLists& vk_scalinglist = scalinglist_array_h264[i]; + + vk_pps.flags.transform_8x8_mode_flag = pps->transform_8x8_mode_flag; + vk_pps.flags.redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present_flag; + vk_pps.flags.constrained_intra_pred_flag = pps->constrained_intra_pred_flag; + vk_pps.flags.deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag; + vk_pps.flags.weighted_pred_flag = pps->weighted_pred_flag; + vk_pps.flags.bottom_field_pic_order_in_frame_present_flag = pps->pic_order_present_flag; + vk_pps.flags.entropy_coding_mode_flag = pps->entropy_coding_mode_flag; + vk_pps.flags.pic_scaling_matrix_present_flag = pps->pic_scaling_matrix_present_flag; + + vk_pps.seq_parameter_set_id = pps->seq_parameter_set_id; + vk_pps.pic_parameter_set_id = pps->pic_parameter_set_id; + vk_pps.num_ref_idx_l0_default_active_minus1 = pps->num_ref_idx_l0_active_minus1; + vk_pps.num_ref_idx_l1_default_active_minus1 = pps->num_ref_idx_l1_active_minus1; + vk_pps.weighted_bipred_idc = (StdVideoH264WeightedBipredIdc)pps->weighted_bipred_idc; + vk_pps.pic_init_qp_minus26 = pps->pic_init_qp_minus26; + vk_pps.pic_init_qs_minus26 = pps->pic_init_qs_minus26; + vk_pps.chroma_qp_index_offset = pps->chroma_qp_index_offset; + vk_pps.second_chroma_qp_index_offset = pps->second_chroma_qp_index_offset; + + vk_pps.pScalingLists = &vk_scalinglist; + for (int j = 0; j < arraysize(pps->pic_scaling_list_present_flag); ++j) + { + vk_scalinglist.scaling_list_present_mask |= pps->pic_scaling_list_present_flag[j] << j; + } + for (int j = 0; j < arraysize(pps->UseDefaultScalingMatrix4x4Flag); ++j) + { + vk_scalinglist.use_default_scaling_matrix_mask |= pps->UseDefaultScalingMatrix4x4Flag[j] << j; + } + for (int j = 0; j < arraysize(pps->ScalingList4x4); ++j) + { + for (int k = 0; k < arraysize(pps->ScalingList4x4[j]); ++k) + { + vk_scalinglist.ScalingList4x4[j][k] = (uint8_t)pps->ScalingList4x4[j][k]; + } + } + for (int j = 0; j < arraysize(pps->ScalingList8x8); ++j) + { + for (int k = 0; k < arraysize(pps->ScalingList8x8[j]); ++k) + { + vk_scalinglist.ScalingList8x8[j][k] = (uint8_t)pps->ScalingList8x8[j][k]; + } + } + } + + uint32_t num_reference_frames = 0; + wi::vector sps_array_h264(desc->sps_count); + wi::vector vui_array_h264(desc->sps_count); + wi::vector hrd_array_h264(desc->sps_count); + for (uint32_t i = 0; i < desc->sps_count; ++i) + { + const h264::SPS* sps = (const h264::SPS*)desc->sps_datas + i; + StdVideoH264SequenceParameterSet& vk_sps = sps_array_h264[i]; + + vk_sps.flags.constraint_set0_flag = sps->constraint_set0_flag; + vk_sps.flags.constraint_set1_flag = sps->constraint_set1_flag; + vk_sps.flags.constraint_set2_flag = sps->constraint_set2_flag; + vk_sps.flags.constraint_set3_flag = sps->constraint_set3_flag; + vk_sps.flags.constraint_set4_flag = sps->constraint_set4_flag; + vk_sps.flags.constraint_set5_flag = sps->constraint_set5_flag; + vk_sps.flags.direct_8x8_inference_flag = sps->direct_8x8_inference_flag; + vk_sps.flags.mb_adaptive_frame_field_flag = sps->mb_adaptive_frame_field_flag; + vk_sps.flags.frame_mbs_only_flag = sps->frame_mbs_only_flag; + vk_sps.flags.delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag; + vk_sps.flags.separate_colour_plane_flag = sps->separate_colour_plane_flag; + vk_sps.flags.gaps_in_frame_num_value_allowed_flag = sps->gaps_in_frame_num_value_allowed_flag; + vk_sps.flags.qpprime_y_zero_transform_bypass_flag = sps->qpprime_y_zero_transform_bypass_flag; + vk_sps.flags.frame_cropping_flag = sps->frame_cropping_flag; + vk_sps.flags.seq_scaling_matrix_present_flag = sps->seq_scaling_matrix_present_flag; + vk_sps.flags.vui_parameters_present_flag = sps->vui_parameters_present_flag; + + if (vk_sps.flags.vui_parameters_present_flag) + { + StdVideoH264SequenceParameterSetVui& vk_vui = vui_array_h264[i]; + vk_sps.pSequenceParameterSetVui = &vk_vui; + vk_vui.flags.aspect_ratio_info_present_flag = sps->vui.aspect_ratio_info_present_flag; + vk_vui.flags.overscan_info_present_flag = sps->vui.overscan_info_present_flag; + vk_vui.flags.overscan_appropriate_flag = sps->vui.overscan_appropriate_flag; + vk_vui.flags.video_signal_type_present_flag = sps->vui.video_signal_type_present_flag; + vk_vui.flags.video_full_range_flag = sps->vui.video_full_range_flag; + vk_vui.flags.color_description_present_flag = sps->vui.colour_description_present_flag; + vk_vui.flags.chroma_loc_info_present_flag = sps->vui.chroma_loc_info_present_flag; + vk_vui.flags.timing_info_present_flag = sps->vui.timing_info_present_flag; + vk_vui.flags.fixed_frame_rate_flag = sps->vui.fixed_frame_rate_flag; + vk_vui.flags.bitstream_restriction_flag = sps->vui.bitstream_restriction_flag; + vk_vui.flags.nal_hrd_parameters_present_flag = sps->vui.nal_hrd_parameters_present_flag; + vk_vui.flags.vcl_hrd_parameters_present_flag = sps->vui.vcl_hrd_parameters_present_flag; + + vk_vui.aspect_ratio_idc = (StdVideoH264AspectRatioIdc)sps->vui.aspect_ratio_idc; + vk_vui.sar_width = sps->vui.sar_width; + vk_vui.sar_height = sps->vui.sar_height; + vk_vui.video_format = sps->vui.video_format; + vk_vui.colour_primaries = sps->vui.colour_primaries; + vk_vui.transfer_characteristics = sps->vui.transfer_characteristics; + vk_vui.matrix_coefficients = sps->vui.matrix_coefficients; + vk_vui.num_units_in_tick = sps->vui.num_units_in_tick; + vk_vui.time_scale = sps->vui.time_scale; + vk_vui.max_num_reorder_frames = sps->vui.num_reorder_frames; + vk_vui.max_dec_frame_buffering = sps->vui.max_dec_frame_buffering; + vk_vui.chroma_sample_loc_type_top_field = sps->vui.chroma_sample_loc_type_top_field; + vk_vui.chroma_sample_loc_type_bottom_field = sps->vui.chroma_sample_loc_type_bottom_field; + + StdVideoH264HrdParameters& vk_hrd = hrd_array_h264[i]; + vk_vui.pHrdParameters = &vk_hrd; + vk_hrd.cpb_cnt_minus1 = sps->hrd.cpb_cnt_minus1; + vk_hrd.bit_rate_scale = sps->hrd.bit_rate_scale; + vk_hrd.cpb_size_scale = sps->hrd.cpb_size_scale; + for (int j = 0; j < arraysize(sps->hrd.bit_rate_value_minus1); ++j) + { + vk_hrd.bit_rate_value_minus1[j] = sps->hrd.bit_rate_value_minus1[j]; + vk_hrd.cpb_size_value_minus1[j] = sps->hrd.cpb_size_value_minus1[j]; + vk_hrd.cbr_flag[j] = sps->hrd.cbr_flag[j]; + } + vk_hrd.initial_cpb_removal_delay_length_minus1 = sps->hrd.initial_cpb_removal_delay_length_minus1; + vk_hrd.cpb_removal_delay_length_minus1 = sps->hrd.cpb_removal_delay_length_minus1; + vk_hrd.dpb_output_delay_length_minus1 = sps->hrd.dpb_output_delay_length_minus1; + vk_hrd.time_offset_length = sps->hrd.time_offset_length; + } + + vk_sps.profile_idc = (StdVideoH264ProfileIdc)sps->profile_idc; + switch (sps->level_idc) + { + case 0: + vk_sps.level_idc = STD_VIDEO_H264_LEVEL_IDC_1_0; + break; + case 11: + vk_sps.level_idc = STD_VIDEO_H264_LEVEL_IDC_1_1; + break; + case 12: + vk_sps.level_idc = STD_VIDEO_H264_LEVEL_IDC_1_2; + break; + case 13: + vk_sps.level_idc = STD_VIDEO_H264_LEVEL_IDC_1_3; + break; + case 20: + vk_sps.level_idc = STD_VIDEO_H264_LEVEL_IDC_2_0; + break; + case 21: + vk_sps.level_idc = STD_VIDEO_H264_LEVEL_IDC_2_1; + break; + case 22: + vk_sps.level_idc = STD_VIDEO_H264_LEVEL_IDC_2_2; + break; + case 30: + vk_sps.level_idc = STD_VIDEO_H264_LEVEL_IDC_3_0; + break; + case 31: + vk_sps.level_idc = STD_VIDEO_H264_LEVEL_IDC_3_1; + break; + case 32: + vk_sps.level_idc = STD_VIDEO_H264_LEVEL_IDC_3_2; + break; + case 40: + vk_sps.level_idc = STD_VIDEO_H264_LEVEL_IDC_4_0; + break; + case 41: + vk_sps.level_idc = STD_VIDEO_H264_LEVEL_IDC_4_1; + break; + case 42: + vk_sps.level_idc = STD_VIDEO_H264_LEVEL_IDC_4_2; + break; + case 50: + vk_sps.level_idc = STD_VIDEO_H264_LEVEL_IDC_5_0; + break; + case 51: + vk_sps.level_idc = STD_VIDEO_H264_LEVEL_IDC_5_1; + break; + case 52: + vk_sps.level_idc = STD_VIDEO_H264_LEVEL_IDC_5_2; + break; + case 60: + vk_sps.level_idc = STD_VIDEO_H264_LEVEL_IDC_6_0; + break; + case 61: + vk_sps.level_idc = STD_VIDEO_H264_LEVEL_IDC_6_1; + break; + case 62: + vk_sps.level_idc = STD_VIDEO_H264_LEVEL_IDC_6_2; + break; + default: + assert(0); + break; + } + assert(vk_sps.level_idc <= decode_h264_capabilities.maxLevelIdc); + //vk_sps.chroma_format_idc = (StdVideoH264ChromaFormatIdc)sps->chroma_format_idc; + vk_sps.chroma_format_idc = STD_VIDEO_H264_CHROMA_FORMAT_IDC_420; // only one we support currently + vk_sps.seq_parameter_set_id = sps->seq_parameter_set_id; + vk_sps.bit_depth_luma_minus8 = sps->bit_depth_luma_minus8; + vk_sps.bit_depth_chroma_minus8 = sps->bit_depth_chroma_minus8; + vk_sps.log2_max_frame_num_minus4 = sps->log2_max_frame_num_minus4; + vk_sps.pic_order_cnt_type = (StdVideoH264PocType)sps->pic_order_cnt_type; + vk_sps.offset_for_non_ref_pic = sps->offset_for_non_ref_pic; + vk_sps.offset_for_top_to_bottom_field = sps->offset_for_top_to_bottom_field; + vk_sps.log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_pic_order_cnt_lsb_minus4; + vk_sps.num_ref_frames_in_pic_order_cnt_cycle = sps->num_ref_frames_in_pic_order_cnt_cycle; + vk_sps.max_num_ref_frames = sps->num_ref_frames; + vk_sps.pic_width_in_mbs_minus1 = sps->pic_width_in_mbs_minus1; + vk_sps.pic_height_in_map_units_minus1 = sps->pic_height_in_map_units_minus1; + vk_sps.frame_crop_left_offset = sps->frame_crop_left_offset; + vk_sps.frame_crop_right_offset = sps->frame_crop_right_offset; + vk_sps.frame_crop_top_offset = sps->frame_crop_top_offset; + vk_sps.frame_crop_bottom_offset = sps->frame_crop_bottom_offset; + vk_sps.pOffsetForRefFrame = sps->offset_for_ref_frame; + + num_reference_frames = std::max(num_reference_frames, (uint32_t)sps->num_ref_frames); + } + + num_reference_frames = std::min(num_reference_frames, video_capability_h264.video_capabilities.maxActiveReferencePictures); + + VkVideoDecodeH264SessionParametersAddInfoKHR session_parameters_add_info_h264 = {}; + session_parameters_add_info_h264.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_KHR; + session_parameters_add_info_h264.stdPPSCount = (uint32_t)desc->pps_count; + session_parameters_add_info_h264.pStdPPSs = pps_array_h264.data(); + session_parameters_add_info_h264.stdSPSCount = (uint32_t)desc->sps_count; + session_parameters_add_info_h264.pStdSPSs = sps_array_h264.data(); + + VkVideoSessionCreateInfoKHR info = {}; + info.sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_CREATE_INFO_KHR; + info.queueFamilyIndex = videoFamily; + info.maxActiveReferencePictures = num_reference_frames * 2; // *2: top and bottom field counts as two I think: https://vulkan.lunarg.com/doc/view/1.3.239.0/windows/1.3-extensions/vkspec.html#_video_decode_commands + info.maxDpbSlots = std::min(desc->num_dpb_slots, video_capability_h264.video_capabilities.maxDpbSlots); + info.maxCodedExtent.width = std::min(desc->width, video_capability_h264.video_capabilities.maxCodedExtent.width); + info.maxCodedExtent.height = std::min(desc->height, video_capability_h264.video_capabilities.maxCodedExtent.height); + info.pictureFormat = _ConvertFormat(desc->format); + info.referencePictureFormat = info.pictureFormat; + info.pVideoProfile = &video_capability_h264.profile; + info.pStdHeaderVersion = &video_capability_h264.video_capabilities.stdHeaderVersion; + + res = vkCreateVideoSessionKHR(device, &info, nullptr, &internal_state->video_session); + assert(res == VK_SUCCESS); + + uint32_t requirement_count = 0; + res = vkGetVideoSessionMemoryRequirementsKHR(device, internal_state->video_session, &requirement_count, nullptr); + assert(res == VK_SUCCESS); + + wi::vector requirements(requirement_count); + for (auto& x : requirements) + { + x.sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_MEMORY_REQUIREMENTS_KHR; + } + res = vkGetVideoSessionMemoryRequirementsKHR(device, internal_state->video_session, &requirement_count, requirements.data()); + assert(res == VK_SUCCESS); + + internal_state->allocations.resize(requirement_count); + wi::vector bind_session_memory_infos(requirement_count); + for (uint32_t i = 0; i < requirement_count; ++i) + { + const VkVideoSessionMemoryRequirementsKHR& video_req = requirements[i]; + VmaAllocationCreateInfo alloc_create_info = {}; + alloc_create_info.memoryTypeBits = video_req.memoryRequirements.memoryTypeBits; + VmaAllocationInfo alloc_info = {}; + + res = vmaAllocateMemory( + allocationhandler->allocator, + &video_req.memoryRequirements, + &alloc_create_info, + &internal_state->allocations[i], + &alloc_info + ); + assert(res == VK_SUCCESS); + + VkBindVideoSessionMemoryInfoKHR& bind_info = bind_session_memory_infos[i]; + bind_info.sType = VK_STRUCTURE_TYPE_BIND_VIDEO_SESSION_MEMORY_INFO_KHR; + bind_info.memory = alloc_info.deviceMemory; + bind_info.memoryBindIndex = video_req.memoryBindIndex; + bind_info.memoryOffset = alloc_info.offset; + bind_info.memorySize = alloc_info.size; + } + res = vkBindVideoSessionMemoryKHR(device, internal_state->video_session, requirement_count, bind_session_memory_infos.data()); + assert(res == VK_SUCCESS); + + VkVideoDecodeH264SessionParametersCreateInfoKHR session_parameters_info_h264 = {}; + session_parameters_info_h264.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR; + session_parameters_info_h264.maxStdPPSCount = (uint32_t)desc->pps_count; + session_parameters_info_h264.maxStdSPSCount = (uint32_t)desc->sps_count; + session_parameters_info_h264.pParametersAddInfo = &session_parameters_add_info_h264; + + VkVideoSessionParametersCreateInfoKHR session_parameters_info = {}; + session_parameters_info.sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR; + session_parameters_info.videoSession = internal_state->video_session; + session_parameters_info.videoSessionParametersTemplate = VK_NULL_HANDLE; + session_parameters_info.pNext = &session_parameters_info_h264; + res = vkCreateVideoSessionParametersKHR(device, &session_parameters_info, nullptr, &internal_state->session_parameters); + assert(res == VK_SUCCESS); + + assert(video_capability_h264.decode_capabilities.flags & VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR); // Currently the only method supported + + return true; + } + + int GraphicsDevice_Vulkan::CreateSubresource(Texture* texture, SubresourceType type, uint32_t firstSlice, uint32_t sliceCount, uint32_t firstMip, uint32_t mipCount, const Format* format_change, const ImageAspect* aspect) const { auto internal_state = to_internal(texture); @@ -5706,11 +6272,35 @@ using namespace vulkan_internal; view_desc.flags = 0; view_desc.image = internal_state->resource; view_desc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + if (aspect != nullptr) + { + view_desc.subresourceRange.aspectMask = _ConvertImageAspect(*aspect); + } view_desc.subresourceRange.baseArrayLayer = firstSlice; view_desc.subresourceRange.layerCount = sliceCount; view_desc.subresourceRange.baseMipLevel = firstMip; view_desc.subresourceRange.levelCount = mipCount; - view_desc.format = _ConvertFormat(format); + switch (format) + { + case Format::NV12: + if (view_desc.subresourceRange.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) + { + view_desc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT; + view_desc.format = VK_FORMAT_R8_UNORM; + } + else if (view_desc.subresourceRange.aspectMask == VK_IMAGE_ASPECT_PLANE_0_BIT) + { + view_desc.format = VK_FORMAT_R8_UNORM; + } + else if (view_desc.subresourceRange.aspectMask == VK_IMAGE_ASPECT_PLANE_0_BIT) + { + view_desc.format = VK_FORMAT_R8G8_UNORM; + } + break; + default: + view_desc.format = _ConvertFormat(format); + break; + } if (texture->desc.type == TextureDesc::Type::TEXTURE_1D) { @@ -6176,7 +6766,7 @@ using namespace vulkan_internal; assert(res == VK_SUCCESS); } - void GraphicsDevice_Vulkan::SetName(GPUResource* pResource, const char* name) + void GraphicsDevice_Vulkan::SetName(GPUResource* pResource, const char* name) const { if (!debugUtils || pResource == nullptr || !pResource->IsValid()) return; @@ -6205,7 +6795,7 @@ using namespace vulkan_internal; VkResult res = vkSetDebugUtilsObjectNameEXT(device, &info); assert(res == VK_SUCCESS); } - void GraphicsDevice_Vulkan::SetName(Shader* shader, const char* name) + void GraphicsDevice_Vulkan::SetName(Shader* shader, const char* name) const { if (!debugUtils || shader == nullptr || !shader->IsValid()) return; @@ -6261,6 +6851,9 @@ using namespace vulkan_internal; case wi::graphics::QUEUE_COPY: poolInfo.queueFamilyIndex = copyFamily; break; + case wi::graphics::QUEUE_VIDEO_DECODE: + poolInfo.queueFamilyIndex = videoFamily; + break; default: assert(0); // queue type not handled break; @@ -6419,12 +7012,15 @@ using namespace vulkan_internal; FRAMECOUNT++; // Initiate stalling CPU when GPU is not yet finished with next frame: - const uint32_t bufferindex = GetBufferIndex(); if (FRAMECOUNT >= BUFFERCOUNT) { + const uint32_t bufferindex = GetBufferIndex(); for (int queue = 0; queue < QUEUE_COUNT; ++queue) { - res = vkWaitForFences(device, 1, &frame_fence[bufferindex][queue], true, 0xFFFFFFFFFFFFFFFF); + if (frame_fence[bufferindex][queue] == VK_NULL_HANDLE) + continue; + + res = vkWaitForFences(device, 1, &frame_fence[bufferindex][queue], VK_TRUE, 0xFFFFFFFFFFFFFFFF); assert(res == VK_SUCCESS); res = vkResetFences(device, 1, &frame_fence[bufferindex][queue]); @@ -6498,7 +7094,6 @@ using namespace vulkan_internal; result.desc.format = swapchain->desc.format; return result; } - ColorSpace GraphicsDevice_Vulkan::GetSwapChainColorSpace(const SwapChain* swapchain) const { auto internal_state = to_internal(swapchain); @@ -7758,8 +8353,16 @@ using namespace vulkan_internal; copy.srcOffset.x = 0; copy.srcOffset.y = 0; copy.srcOffset.z = 0; - copy.extent.width = std::min(dst->desc.width, src->desc.width); - copy.extent.height = std::min(dst->desc.height, src->desc.height); + if (src->desc.format == Format::NV12 && src_aspect == ImageAspect::CHROMINANCE) + { + copy.extent.width = std::min(dst->desc.width, src->desc.width / 2); + copy.extent.height = std::min(dst->desc.height, src->desc.height / 2); + } + else + { + copy.extent.width = std::min(dst->desc.width, src->desc.width); + copy.extent.height = std::min(dst->desc.height, src->desc.height); + } copy.extent.depth = std::min(dst->desc.depth, src->desc.depth); } else @@ -7936,6 +8539,10 @@ using namespace vulkan_internal; { barrierdesc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; } + if (barrier.image.aspect != nullptr) + { + barrierdesc.subresourceRange.aspectMask = _ConvertImageAspect(*barrier.image.aspect); + } if (barrier.image.mip >= 0 || barrier.image.slice >= 0) { barrierdesc.subresourceRange.baseMipLevel = (uint32_t)std::max(0, barrier.image.mip); @@ -8274,6 +8881,119 @@ using namespace vulkan_internal; } } + void GraphicsDevice_Vulkan::VideoDecode(const VideoDecoder* video_decoder, const VideoDecodeOperation* op, CommandList cmd) + { + CommandList_Vulkan& commandlist = GetCommandList(cmd); + auto decoder_internal = to_internal(video_decoder); + auto stream_internal = to_internal(op->stream); + auto dpb_internal = to_internal(op->DPB); + + const h264::SliceHeader* slice_header = (const h264::SliceHeader*)op->slice_header; + const h264::PPS* pps = (const h264::PPS*)op->pps; + const h264::SPS* sps = (const h264::SPS*)op->sps; + + StdVideoDecodeH264PictureInfo std_picture_info_h264 = {}; + std_picture_info_h264.pic_parameter_set_id = slice_header->pic_parameter_set_id; + std_picture_info_h264.seq_parameter_set_id = pps->seq_parameter_set_id; + std_picture_info_h264.frame_num = slice_header->frame_num; + std_picture_info_h264.PicOrderCnt[0] = op->poc[0]; + std_picture_info_h264.PicOrderCnt[1] = op->poc[1]; + std_picture_info_h264.idr_pic_id = slice_header->idr_pic_id; + std_picture_info_h264.flags.is_intra = op->frame_type == VideoFrameType::Intra ? 1 : 0; + std_picture_info_h264.flags.is_reference = op->reference_priority > 0 ? 1 : 0; + std_picture_info_h264.flags.IdrPicFlag = (std_picture_info_h264.flags.is_intra && std_picture_info_h264.flags.is_reference) ? 1 : 0; + std_picture_info_h264.flags.field_pic_flag = slice_header->field_pic_flag; + std_picture_info_h264.flags.bottom_field_flag = slice_header->bottom_field_flag; + std_picture_info_h264.flags.complementary_field_pair = 0; + + VkVideoReferenceSlotInfoKHR reference_slot_infos[17] = {}; + VkVideoPictureResourceInfoKHR reference_slot_pictures[17] = {}; + VkVideoDecodeH264DpbSlotInfoKHR dpb_slots_h264[17] = {}; + StdVideoDecodeH264ReferenceInfo reference_infos_h264[17] = {}; + for (uint32_t i = 0; i < op->DPB->desc.array_size; ++i) + { + VkVideoReferenceSlotInfoKHR& slot = reference_slot_infos[i]; + VkVideoPictureResourceInfoKHR& pic = reference_slot_pictures[i]; + VkVideoDecodeH264DpbSlotInfoKHR& dpb = dpb_slots_h264[i]; + StdVideoDecodeH264ReferenceInfo& ref = reference_infos_h264[i]; + + slot.sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR; + slot.pPictureResource = &pic; + slot.slotIndex = i; + slot.pNext = &dpb; + + pic.sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR; + pic.codedOffset.x = 0; + pic.codedOffset.y = 0; + pic.codedExtent.width = op->DPB->desc.width; + pic.codedExtent.height = op->DPB->desc.height; + pic.baseArrayLayer = i; + pic.imageViewBinding = dpb_internal->video_decode_view; + + dpb.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_KHR; + dpb.pStdReferenceInfo = &ref; + + ref.flags.bottom_field_flag = 1; + ref.flags.top_field_flag = 1; + ref.flags.is_non_existing = 0; + ref.flags.used_for_long_term_reference = 0; + ref.FrameNum = op->dpb_framenum[i]; + ref.PicOrderCnt[0] = op->dpb_poc[i]; + ref.PicOrderCnt[1] = op->dpb_poc[i]; + } + + VkVideoReferenceSlotInfoKHR reference_slots[17] = {}; + for (size_t i = 0; i < op->dpb_reference_count; ++i) + { + uint32_t ref_slot = op->dpb_reference_slots[i]; + assert(ref_slot != op->current_dpb); + reference_slots[i] = reference_slot_infos[ref_slot]; + } + reference_slots[op->dpb_reference_count] = reference_slot_infos[op->current_dpb]; + reference_slots[op->dpb_reference_count].slotIndex = -1; + + VkVideoBeginCodingInfoKHR begin_info = {}; + begin_info.sType = VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR; + begin_info.videoSession = decoder_internal->video_session; + begin_info.videoSessionParameters = decoder_internal->session_parameters; + begin_info.referenceSlotCount = op->dpb_reference_count + 1; // add in the current reconstructed DPB image + begin_info.pReferenceSlots = begin_info.referenceSlotCount == 0 ? nullptr : reference_slots; + vkCmdBeginVideoCodingKHR(commandlist.GetCommandBuffer(), &begin_info); + + if (op->flags & VideoDecodeOperation::FLAG_SESSION_RESET) + { + VkVideoCodingControlInfoKHR control_info = {}; + control_info.sType = VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR; + control_info.flags = VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR; + vkCmdControlVideoCodingKHR(commandlist.GetCommandBuffer(), &control_info); + } + + VkVideoDecodeInfoKHR decode_info = {}; + decode_info.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR; + decode_info.srcBuffer = stream_internal->resource; + decode_info.srcBufferOffset = (VkDeviceSize)op->stream_offset; + decode_info.srcBufferRange = (VkDeviceSize)AlignTo(op->stream_size, VIDEO_DECODE_BITSTREAM_ALIGNMENT); + decode_info.dstPictureResource = *reference_slot_infos[op->current_dpb].pPictureResource; + decode_info.referenceSlotCount = op->dpb_reference_count; + decode_info.pReferenceSlots = decode_info.referenceSlotCount == 0 ? nullptr : reference_slots; + decode_info.pSetupReferenceSlot = &reference_slot_infos[op->current_dpb]; + + uint32_t slice_offset = 0; + + // https://vulkan.lunarg.com/doc/view/1.3.239.0/windows/1.3-extensions/vkspec.html#_h_264_decoding_parameters + VkVideoDecodeH264PictureInfoKHR picture_info_h264 = {}; + picture_info_h264.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_KHR; + picture_info_h264.pStdPictureInfo = &std_picture_info_h264; + picture_info_h264.sliceCount = 1; + picture_info_h264.pSliceOffsets = &slice_offset; + decode_info.pNext = &picture_info_h264; + + vkCmdDecodeVideoKHR(commandlist.GetCommandBuffer(), &decode_info); + + VkVideoEndCodingInfoKHR end_info = {}; + end_info.sType = VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR; + vkCmdEndVideoCodingKHR(commandlist.GetCommandBuffer(), &end_info); + } void GraphicsDevice_Vulkan::EventBegin(const char* name, CommandList cmd) { diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.h b/WickedEngine/wiGraphicsDevice_Vulkan.h index 11dc67455..dcaaa5ed1 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.h +++ b/WickedEngine/wiGraphicsDevice_Vulkan.h @@ -37,14 +37,17 @@ namespace wi::graphics VkDebugUtilsMessengerEXT debugUtilsMessenger = VK_NULL_HANDLE; VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; VkDevice device = VK_NULL_HANDLE; - wi::vector queueFamilies; + wi::vector queueFamilies; + wi::vector queueFamiliesVideo; uint32_t graphicsFamily = VK_QUEUE_FAMILY_IGNORED; uint32_t computeFamily = VK_QUEUE_FAMILY_IGNORED; uint32_t copyFamily = VK_QUEUE_FAMILY_IGNORED; + uint32_t videoFamily = VK_QUEUE_FAMILY_IGNORED; wi::vector families; VkQueue graphicsQueue = VK_NULL_HANDLE; VkQueue computeQueue = VK_NULL_HANDLE; VkQueue copyQueue = VK_NULL_HANDLE; + VkQueue videoQueue = VK_NULL_HANDLE; VkPhysicalDeviceProperties2 properties2 = {}; VkPhysicalDeviceVulkan11Properties properties_1_1 = {}; @@ -70,6 +73,16 @@ namespace wi::graphics VkPhysicalDeviceDepthClipEnableFeaturesEXT depth_clip_enable_features = {}; VkPhysicalDeviceMeshShaderFeaturesEXT mesh_shader_features = {}; + VkVideoDecodeH264ProfileInfoKHR decode_h264_profile = {}; + VkVideoDecodeH264CapabilitiesKHR decode_h264_capabilities = {}; + struct VideoCapability + { + VkVideoProfileInfoKHR profile = {}; + VkVideoDecodeCapabilitiesKHR decode_capabilities = {}; + VkVideoCapabilitiesKHR video_capabilities = {}; + }; + VideoCapability video_capability_h264 = {}; + wi::vector pso_dynamicStates; VkPipelineDynamicStateCreateInfo dynamicStateInfo = {}; @@ -122,7 +135,7 @@ namespace wi::graphics VkCommandPool transitionCommandPool = VK_NULL_HANDLE; VkCommandBuffer transitionCommandBuffer = VK_NULL_HANDLE; VkFence fence = VK_NULL_HANDLE; - VkSemaphore semaphores[2] = { VK_NULL_HANDLE, VK_NULL_HANDLE }; // graphics, compute + VkSemaphore semaphores[3] = { VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE }; // graphics, compute, video GPUBuffer uploadbuffer; inline bool IsValid() const { return transferCommandBuffer != VK_NULL_HANDLE; } }; @@ -271,7 +284,7 @@ namespace wi::graphics wi::vector immutable_samplers; public: - GraphicsDevice_Vulkan(wi::platform::window_type window, ValidationMode validationMode = ValidationMode::Disabled); + GraphicsDevice_Vulkan(wi::platform::window_type window, ValidationMode validationMode = ValidationMode::Disabled, GPUPreference preference = GPUPreference::Discrete); ~GraphicsDevice_Vulkan() override; bool CreateSwapChain(const SwapChainDesc* desc, wi::platform::window_type window, SwapChain* swapchain) const override; @@ -283,8 +296,9 @@ namespace wi::graphics bool CreatePipelineState(const PipelineStateDesc* desc, PipelineState* pso, const RenderPassInfo* renderpass_info = nullptr) const override; bool CreateRaytracingAccelerationStructure(const RaytracingAccelerationStructureDesc* desc, RaytracingAccelerationStructure* bvh) const override; bool CreateRaytracingPipelineState(const RaytracingPipelineStateDesc* desc, RaytracingPipelineState* rtpso) const override; - - int CreateSubresource(Texture* texture, SubresourceType type, uint32_t firstSlice, uint32_t sliceCount, uint32_t firstMip, uint32_t mipCount, const Format* format_change = nullptr) const override; + bool CreateVideoDecoder(const VideoDesc* desc, VideoDecoder* video_decoder) const override; + + int CreateSubresource(Texture* texture, SubresourceType type, uint32_t firstSlice, uint32_t sliceCount, uint32_t firstMip, uint32_t mipCount, const Format* format_change = nullptr, const ImageAspect* aspect = nullptr) const override; int CreateSubresource(GPUBuffer* buffer, SubresourceType type, uint64_t offset, uint64_t size = ~0, const Format* format_change = nullptr) const override; int GetDescriptorIndex(const GPUResource* resource, SubresourceType type, int subresource = -1) const override; @@ -294,8 +308,8 @@ namespace wi::graphics void WriteTopLevelAccelerationStructureInstance(const RaytracingAccelerationStructureDesc::TopLevel::Instance* instance, void* dest) const override; void WriteShaderIdentifier(const RaytracingPipelineState* rtpso, uint32_t group_index, void* dest) const override; - void SetName(GPUResource* pResource, const char* name) override; - void SetName(Shader* shader, const char* name) override; + void SetName(GPUResource* pResource, const char* name) const override; + void SetName(Shader* shader, const char* name) const override; CommandList BeginCommandList(QUEUE_TYPE queue = QUEUE_GRAPHICS) override; void SubmitCommandLists() override; @@ -399,6 +413,7 @@ namespace wi::graphics void PredicationBegin(const GPUBuffer* buffer, uint64_t offset, PredicationOp op, CommandList cmd) override; void PredicationEnd(CommandList cmd) override; void ClearUAV(const GPUResource* resource, uint32_t value, CommandList cmd) override; + void VideoDecode(const VideoDecoder* video_decoder, const VideoDecodeOperation* op, CommandList cmd) override; void EventBegin(const char* name, CommandList cmd) override; void EventEnd(CommandList cmd) override; @@ -551,6 +566,8 @@ namespace wi::graphics std::deque> destroyer_swapchains; std::deque> destroyer_surfaces; std::deque> destroyer_semaphores; + std::deque> destroyer_video_sessions; + std::deque> destroyer_video_session_parameters; std::deque> destroyer_bindlessSampledImages; std::deque> destroyer_bindlessUniformTexelBuffers; std::deque> destroyer_bindlessStorageBuffers; @@ -800,6 +817,32 @@ namespace wi::graphics break; } } + while (!destroyer_video_sessions.empty()) + { + if (destroyer_video_sessions.front().second + BUFFERCOUNT < FRAMECOUNT) + { + auto item = destroyer_video_sessions.front(); + destroyer_video_sessions.pop_front(); + vkDestroyVideoSessionKHR(device, item.first, nullptr); + } + else + { + break; + } + } + while (!destroyer_video_session_parameters.empty()) + { + if (destroyer_video_session_parameters.front().second + BUFFERCOUNT < FRAMECOUNT) + { + auto item = destroyer_video_session_parameters.front(); + destroyer_video_session_parameters.pop_front(); + vkDestroyVideoSessionParametersKHR(device, item.first, nullptr); + } + else + { + break; + } + } while (!destroyer_bindlessSampledImages.empty()) { if (destroyer_bindlessSampledImages.front().second + BUFFERCOUNT < FRAMECOUNT) diff --git a/WickedEngine/wiHelper.cpp b/WickedEngine/wiHelper.cpp index edd48de10..162da6b6c 100644 --- a/WickedEngine/wiHelper.cpp +++ b/WickedEngine/wiHelper.cpp @@ -961,9 +961,9 @@ namespace wi::helper std::thread([=] { - char szFile[256]; + wchar_t szFile[256]; - OPENFILENAMEA ofn; + OPENFILENAME ofn; ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = nullptr; @@ -982,7 +982,7 @@ namespace wi::helper // Second string is extensions, each separated by ';' and at the end of all, a '\0' // Then the whole container string is closed with an other '\0' // For example: "model files\0*.model;*.obj;\0" <-- this string literal has "model files" as description and two accepted extensions "model" and "obj" - wi::vector filter; + wi::vector filter; filter.reserve(256); { for (auto& x : params.description) @@ -1013,18 +1013,20 @@ namespace wi::helper case FileDialogParams::OPEN: ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; ofn.Flags |= OFN_NOCHANGEDIR; - ok = GetOpenFileNameA(&ofn) == TRUE; + ok = GetOpenFileName(&ofn) == TRUE; break; case FileDialogParams::SAVE: ofn.Flags = OFN_OVERWRITEPROMPT; ofn.Flags |= OFN_NOCHANGEDIR; - ok = GetSaveFileNameA(&ofn) == TRUE; + ok = GetSaveFileName(&ofn) == TRUE; break; } if (ok) { - onSuccess(ofn.lpstrFile); + std::string result_filename; + StringConvert(ofn.lpstrFile, result_filename); + onSuccess(result_filename); } }).detach(); diff --git a/WickedEngine/wiImage.cpp b/WickedEngine/wiImage.cpp index a80a81855..f7af03971 100644 --- a/WickedEngine/wiImage.cpp +++ b/WickedEngine/wiImage.cpp @@ -75,8 +75,8 @@ namespace wi::image ImageConstants image = {}; image.buffer_index = -1; image.buffer_offset = 0; - image.texture_base_index = device->GetDescriptorIndex(texture, SubresourceType::SRV); - image.texture_mask_index = device->GetDescriptorIndex(params.maskMap, SubresourceType::SRV); + image.texture_base_index = device->GetDescriptorIndex(texture, SubresourceType::SRV, params.image_subresource); + image.texture_mask_index = device->GetDescriptorIndex(params.maskMap, SubresourceType::SRV, params.mask_subresource); if (params.isBackgroundEnabled()) { image.texture_background_index = device->GetDescriptorIndex(&backgroundTexture, SubresourceType::SRV); diff --git a/WickedEngine/wiImage.h b/WickedEngine/wiImage.h index 157eaf8e2..99a70b8ae 100644 --- a/WickedEngine/wiImage.h +++ b/WickedEngine/wiImage.h @@ -97,6 +97,8 @@ namespace wi::image QUALITY quality = QUALITY_LINEAR; const wi::graphics::Texture* maskMap = nullptr; + int image_subresource = -1; + int mask_subresource = -1; // Set a mask map that will be used to multiply the base image constexpr void setMaskMap(const wi::graphics::Texture* tex) { maskMap = tex; } diff --git a/WickedEngine/wiJobSystem.cpp b/WickedEngine/wiJobSystem.cpp index 193c2521e..c5e4c83fa 100644 --- a/WickedEngine/wiJobSystem.cpp +++ b/WickedEngine/wiJobSystem.cpp @@ -64,7 +64,7 @@ namespace wi::jobsystem std::mutex wakeMutex; std::atomic nextQueue{ 0 }; wi::vector threads; - ~InternalState() + void ShutDown() { alive.store(false); // indicate that new jobs cannot be started from this point bool wake_loop = true; @@ -73,13 +73,21 @@ namespace wi::jobsystem { wakeCondition.notify_all(); // wakes up sleeping worker threads } - }); + }); for (auto& thread : threads) { thread.join(); } wake_loop = false; waker.join(); + jobQueuePerThread.reset(); + threads.clear(); + numCores = 0; + numThreads = 0; + } + ~InternalState() + { + ShutDown(); } } static internal_state; @@ -196,6 +204,11 @@ namespace wi::jobsystem wi::backlog::post("wi::jobsystem Initialized with [" + std::to_string(internal_state.numCores) + " cores] [" + std::to_string(internal_state.numThreads) + " threads] (" + std::to_string((int)std::round(timer.elapsed())) + " ms)"); } + void ShutDown() + { + internal_state.ShutDown(); + } + uint32_t GetThreadCount() { return internal_state.numThreads; diff --git a/WickedEngine/wiJobSystem.h b/WickedEngine/wiJobSystem.h index 81a8ced67..291df5b69 100644 --- a/WickedEngine/wiJobSystem.h +++ b/WickedEngine/wiJobSystem.h @@ -6,6 +6,7 @@ namespace wi::jobsystem { void Initialize(uint32_t maxThreadCount = ~0u); + void ShutDown(); struct JobArgs { diff --git a/WickedEngine/wiRenderPath3D.cpp b/WickedEngine/wiRenderPath3D.cpp index 70536277f..bc4521a42 100644 --- a/WickedEngine/wiRenderPath3D.cpp +++ b/WickedEngine/wiRenderPath3D.cpp @@ -662,6 +662,25 @@ namespace wi camera_reflection.texture_surfelgi_index = -1; camera_reflection.texture_vxgi_diffuse_index = -1; camera_reflection.texture_vxgi_specular_index = -1; + + video_cmd = {}; + if (scene->videos.GetCount() > 0) + { + for (size_t i = 0; i < scene->videos.GetCount(); ++i) + { + const wi::scene::VideoComponent& video = scene->videos[i]; + if (wi::video::IsDecodingRequired(&video.videoinstance, dt)) + { + video_cmd = device->BeginCommandList(QUEUE_VIDEO_DECODE); + break; + } + } + for (size_t i = 0; i < scene->videos.GetCount(); ++i) + { + wi::scene::VideoComponent& video = scene->videos[i]; + wi::video::UpdateVideo(&video.videoinstance, dt, video_cmd); + } + } } void RenderPath3D::Render() const @@ -829,11 +848,21 @@ namespace wi // must finish before "main scene opaque color pass") cmd = device->BeginCommandList(QUEUE_COMPUTE); device->WaitCommandList(cmd, cmd_maincamera_prepass); + if (video_cmd.IsValid()) + { + device->WaitCommandList(cmd, video_cmd); + } CommandList cmd_maincamera_compute_effects = cmd; wi::jobsystem::Execute(ctx, [this, cmd](wi::jobsystem::JobArgs args) { GraphicsDevice* device = wi::graphics::GetDevice(); + for (size_t i = 0; i < scene->videos.GetCount(); ++i) + { + wi::scene::VideoComponent& video = scene->videos[i]; + wi::video::ResolveVideoToRGB(&video.videoinstance, cmd); + } + wi::renderer::BindCameraCB( *camera, camera_previous, diff --git a/WickedEngine/wiRenderPath3D.h b/WickedEngine/wiRenderPath3D.h index 023683707..64cc0af8b 100644 --- a/WickedEngine/wiRenderPath3D.h +++ b/WickedEngine/wiRenderPath3D.h @@ -142,6 +142,9 @@ namespace wi wi::renderer::FSR2Resources fsr2Resources; wi::renderer::VXGIResources vxgiResources; + wi::graphics::CommandList video_cmd; + wi::vector video_instances_tmp; + mutable const wi::graphics::Texture* lastPostprocessRT = &rtPostprocess; // Post-processes are ping-ponged, this function helps to obtain the last postprocess render target that was written const wi::graphics::Texture* GetLastPostprocessRT() const diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 904545864..d172a5e98 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -1088,6 +1088,7 @@ void LoadShaders() wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::CS, shaders[CSTYPE_VIRTUALTEXTURE_TILEALLOCATE], "virtualTextureTileAllocateCS.cso"); }); wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::CS, shaders[CSTYPE_VIRTUALTEXTURE_RESIDENCYUPDATE], "virtualTextureResidencyUpdateCS.cso"); }); wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::CS, shaders[CSTYPE_WIND], "windCS.cso"); }); + wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::CS, shaders[CSTYPE_YUV_TO_RGB], "yuv_to_rgbCS.cso"); }); wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::HS, shaders[HSTYPE_OBJECT], "objectHS.cso"); }); wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::HS, shaders[HSTYPE_OBJECT_PREPASS], "objectHS_prepass.cso"); }); @@ -2683,10 +2684,8 @@ void RenderMeshes( for (uint32_t subsetIndex = first_subset; subsetIndex < last_subset; ++subsetIndex) { const MeshComponent::MeshSubset& subset = mesh.subsets[subsetIndex]; - if (subset.indexCount == 0) - { + if (subset.indexCount == 0 || subset.materialIndex >= vis.scene->materials.GetCount()) continue; - } const MaterialComponent& material = vis.scene->materials[subset.materialIndex]; if (skip_planareflection_objects && material.HasPlanarReflection()) @@ -15339,6 +15338,61 @@ void Postprocess_Underwater( } +void YUV_to_RGB( + const Texture& input, + int input_subresource_luminance, + int input_subresource_chrominance, + const Texture& output, + CommandList cmd +) +{ + device->EventBegin("YUV_to_RGB", cmd); + + device->BindComputeShader(&shaders[CSTYPE_YUV_TO_RGB], cmd); + + const TextureDesc& input_desc = input.GetDesc(); + const TextureDesc& output_desc = output.GetDesc(); + + PostProcess postprocess; + postprocess.resolution.x = input_desc.width; // taking input desc resolution to avoid sampling padding texels + postprocess.resolution.y = input_desc.height; // taking input desc resolution to avoid sampling padding texels + postprocess.resolution_rcp.x = 1.0f / postprocess.resolution.x; + postprocess.resolution_rcp.y = 1.0f / postprocess.resolution.y; + device->PushConstants(&postprocess, sizeof(postprocess), cmd); + + device->BindResource(&input, 0, cmd, input_subresource_luminance); + device->BindResource(&input, 1, cmd, input_subresource_chrominance); + + const GPUResource* uavs[] = { + &output, + }; + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); + + { + GPUBarrier barriers[] = { + GPUBarrier::Image(&output, output.desc.layout, ResourceState::UNORDERED_ACCESS), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + + device->Dispatch( + (output_desc.width + POSTPROCESS_BLOCKSIZE - 1) / POSTPROCESS_BLOCKSIZE, + (output_desc.height + POSTPROCESS_BLOCKSIZE - 1) / POSTPROCESS_BLOCKSIZE, + 1, + cmd + ); + + { + GPUBarrier barriers[] = { + GPUBarrier::Image(&output, ResourceState::UNORDERED_ACCESS, output.desc.layout), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + + device->EventEnd(cmd); +} + + Ray GetPickRay(long cursorX, long cursorY, const wi::Canvas& canvas, const CameraComponent& camera) { float screenW = canvas.GetLogicalWidth(); diff --git a/WickedEngine/wiRenderer.h b/WickedEngine/wiRenderer.h index 1578cf645..dbd870fe1 100644 --- a/WickedEngine/wiRenderer.h +++ b/WickedEngine/wiRenderer.h @@ -855,6 +855,14 @@ namespace wi::renderer wi::graphics::CommandList cmd ); + void YUV_to_RGB( + const wi::graphics::Texture& input, + int input_subresource_luminance, + int input_subresource_chrominance, + const wi::graphics::Texture& output, + wi::graphics::CommandList cmd + ); + // Render the scene with ray tracing void RayTraceScene( const wi::scene::Scene& scene, diff --git a/WickedEngine/wiResourceManager.cpp b/WickedEngine/wiResourceManager.cpp index 56b24e848..ad8037753 100644 --- a/WickedEngine/wiResourceManager.cpp +++ b/WickedEngine/wiResourceManager.cpp @@ -25,6 +25,7 @@ namespace wi int srgb_subresource = -1; wi::audio::Sound sound; std::string script; + wi::video::Video video; wi::vector filedata; }; @@ -48,6 +49,11 @@ namespace wi const ResourceInternal* resourceinternal = (ResourceInternal*)internal_state.get(); return resourceinternal->script; } + const wi::video::Video& Resource::GetVideo() const + { + const ResourceInternal* resourceinternal = (ResourceInternal*)internal_state.get(); + return resourceinternal->video; + } int Resource::GetTextureSRGBSubresource() const { const ResourceInternal* resourceinternal = (ResourceInternal*)internal_state.get(); @@ -100,6 +106,15 @@ namespace wi ResourceInternal* resourceinternal = (ResourceInternal*)internal_state.get(); resourceinternal->script = script; } + void Resource::SetVideo(const wi::video::Video& video) + { + if (internal_state == nullptr) + { + internal_state = std::make_shared(); + } + ResourceInternal* resourceinternal = (ResourceInternal*)internal_state.get(); + resourceinternal->video = video; + } namespace resourcemanager { @@ -121,6 +136,7 @@ namespace wi IMAGE, SOUND, SCRIPT, + VIDEO, }; static const wi::unordered_map types = { {"BASIS", DataType::IMAGE}, @@ -136,6 +152,7 @@ namespace wi {"WAV", DataType::SOUND}, {"OGG", DataType::SOUND}, {"LUA", DataType::SCRIPT}, + {"MP4", DataType::VIDEO}, }; wi::vector GetSupportedImageExtensions() { @@ -161,6 +178,18 @@ namespace wi } return ret; } + wi::vector GetSupportedVideoExtensions() + { + wi::vector ret; + for (auto& x : types) + { + if (x.second == DataType::VIDEO) + { + ret.push_back(x.first); + } + } + return ret; + } wi::vector GetSupportedScriptExtensions() { wi::vector ret; @@ -800,6 +829,12 @@ namespace wi } break; + case DataType::VIDEO: + { + success = wi::video::CreateVideo(filedata, filesize, &resource->video); + } + break; + }; if (success) diff --git a/WickedEngine/wiResourceManager.h b/WickedEngine/wiResourceManager.h index 92175be33..f1cc1e101 100644 --- a/WickedEngine/wiResourceManager.h +++ b/WickedEngine/wiResourceManager.h @@ -5,6 +5,7 @@ #include "wiArchive.h" #include "wiJobSystem.h" #include "wiVector.h" +#include "wiVideo.h" #include @@ -21,6 +22,7 @@ namespace wi const wi::graphics::Texture& GetTexture() const; const wi::audio::Sound& GetSound() const; const std::string& GetScript() const; + const wi::video::Video& GetVideo() const; int GetTextureSRGBSubresource() const; void SetFileData(const wi::vector& data); @@ -30,6 +32,7 @@ namespace wi void SetTexture(const wi::graphics::Texture& texture, int srgb_subresource = -1); void SetSound(const wi::audio::Sound& sound); void SetScript(const std::string& script); + void SetVideo(const wi::video::Video& script); }; namespace resourcemanager @@ -44,6 +47,7 @@ namespace wi Mode GetMode(); wi::vector GetSupportedImageExtensions(); wi::vector GetSupportedSoundExtensions(); + wi::vector GetSupportedVideoExtensions(); wi::vector GetSupportedScriptExtensions(); // Order of these must not change as the flags can be serialized! diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index 68bc5ed13..7cc017209 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -300,6 +300,8 @@ namespace wi::scene RunSoundUpdateSystem(ctx); + RunVideoUpdateSystem(ctx); + RunImpostorUpdateSystem(ctx); wi::jobsystem::Wait(ctx); // dependencies @@ -1094,6 +1096,25 @@ namespace wi::scene return entity; } + Entity Scene::Entity_CreateVideo( + const std::string& name, + const std::string& filename + ) + { + Entity entity = CreateEntity(); + + names.Create(entity) = name; + + if (!filename.empty()) + { + VideoComponent& video = videos.Create(entity); + video.filename = filename; + video.videoResource = wi::resourcemanager::Load(filename, wi::resourcemanager::Flags::IMPORT_RETAIN_FILEDATA); + wi::video::CreateVideoInstance(&video.videoResource.GetVideo(), &video.videoinstance); + } + + return entity; + } Entity Scene::Entity_CreateCube( const std::string& name ) @@ -3326,6 +3347,15 @@ namespace wi::scene material.WriteShaderMaterial(materialArrayMapped + args.jobIndex); + VideoComponent* video = videos.GetComponent(entity); + if (video != nullptr) + { + // Video attachment will overwrite texture slots on shader side: + int descriptor = GetDevice()->GetDescriptorIndex(&video->videoinstance.output.texture, SubresourceType::SRV, video->videoinstance.output.subresource_srgb); + material.WriteShaderTextureSlot(materialArrayMapped + args.jobIndex, BASECOLORMAP, descriptor); + material.WriteShaderTextureSlot(materialArrayMapped + args.jobIndex, EMISSIVEMAP, descriptor); + } + }); } void Scene::RunImpostorUpdateSystem(wi::jobsystem::context& ctx) @@ -4297,6 +4327,34 @@ namespace wi::scene wi::audio::SetVolume(sound.volume, &sound.soundinstance); } } + void Scene::RunVideoUpdateSystem(wi::jobsystem::context& ctx) + { + for (size_t i = 0; i < videos.GetCount(); ++i) + { + VideoComponent& video = videos[i]; + + if (video.IsPlaying()) + { + video.videoinstance.flags |= wi::video::VideoInstance::Flags::Playing; + } + else + { + video.videoinstance.flags &= ~wi::video::VideoInstance::Flags::Playing; + } + + if (video.IsLooped()) + { + video.videoinstance.flags |= wi::video::VideoInstance::Flags::Looped; + } + else + { + video.videoinstance.flags &= ~wi::video::VideoInstance::Flags::Looped; + } + + video.videoinstance.flags |= wi::video::VideoInstance::Flags::Mipmapped; + + } + } void Scene::RunScriptUpdateSystem(wi::jobsystem::context& ctx) { for (size_t i = 0; i < scripts.GetCount(); ++i) diff --git a/WickedEngine/wiScene.h b/WickedEngine/wiScene.h index 92b4e8e8f..e5cad807f 100644 --- a/WickedEngine/wiScene.h +++ b/WickedEngine/wiScene.h @@ -47,6 +47,7 @@ namespace wi::scene wi::ecs::ComponentManager& hairs = componentLibrary.Register("wi::scene::Scene::hairs"); wi::ecs::ComponentManager& weathers = componentLibrary.Register("wi::scene::Scene::weathers", 4); // version = 4 wi::ecs::ComponentManager& sounds = componentLibrary.Register("wi::scene::Scene::sounds"); + wi::ecs::ComponentManager& videos = componentLibrary.Register("wi::scene::Scene::videos"); wi::ecs::ComponentManager& inverse_kinematics = componentLibrary.Register("wi::scene::Scene::inverse_kinematics"); wi::ecs::ComponentManager& springs = componentLibrary.Register("wi::scene::Scene::springs", 1); // version = 1 wi::ecs::ComponentManager& colliders = componentLibrary.Register("wi::scene::Scene::colliders", 2); // version = 2 @@ -354,6 +355,10 @@ namespace wi::scene const std::string& filename, const XMFLOAT3& position = XMFLOAT3(0, 0, 0) ); + wi::ecs::Entity Entity_CreateVideo( + const std::string& name, + const std::string& filename + ); wi::ecs::Entity Entity_CreateCube( const std::string& name ); @@ -389,6 +394,7 @@ namespace wi::scene void RunParticleUpdateSystem(wi::jobsystem::context& ctx); void RunWeatherUpdateSystem(wi::jobsystem::context& ctx); void RunSoundUpdateSystem(wi::jobsystem::context& ctx); + void RunVideoUpdateSystem(wi::jobsystem::context& ctx); void RunScriptUpdateSystem(wi::jobsystem::context& ctx); diff --git a/WickedEngine/wiScene_Components.cpp b/WickedEngine/wiScene_Components.cpp index afe6d3d07..74d7015d0 100644 --- a/WickedEngine/wiScene_Components.cpp +++ b/WickedEngine/wiScene_Components.cpp @@ -367,6 +367,10 @@ namespace wi::scene std::memcpy(dest, &material, sizeof(ShaderMaterial)); // memcpy whole structure into mapped pointer to avoid read from uncached memory } + void MaterialComponent::WriteShaderTextureSlot(ShaderMaterial* dest, int slot, int descriptor) + { + std::memcpy(&dest->textures[slot].texture_descriptor, &descriptor, sizeof(descriptor)); // memcpy into mapped pointer to avoid read from uncached memory + } void MaterialComponent::WriteTextures(const wi::graphics::GPUResource** dest, int count) const { count = std::min(count, (int)TEXTURESLOT_COUNT); diff --git a/WickedEngine/wiScene_Components.h b/WickedEngine/wiScene_Components.h index 000939f09..9e486a6be 100644 --- a/WickedEngine/wiScene_Components.h +++ b/WickedEngine/wiScene_Components.h @@ -3,6 +3,7 @@ #include "wiArchive.h" #include "wiCanvas.h" #include "wiAudio.h" +#include "wiVideo.h" #include "wiEnums.h" #include "wiOcean.h" #include "wiPrimitive.h" @@ -304,6 +305,7 @@ namespace wi::scene // The MaterialComponent will be written to ShaderMaterial (a struct that is optimized for GPU use) void WriteShaderMaterial(ShaderMaterial* dest) const; + void WriteShaderTextureSlot(ShaderMaterial* dest, int slot, int descriptor); // Retrieve the array of textures from the material void WriteTextures(const wi::graphics::GPUResource** dest, int count) const; @@ -1341,6 +1343,30 @@ namespace wi::scene void Serialize(wi::Archive& archive, wi::ecs::EntitySerializer& seri); }; + struct VideoComponent + { + enum FLAGS + { + EMPTY = 0, + PLAYING = 1 << 0, + LOOPED = 1 << 1, + }; + uint32_t _flags = LOOPED; + + std::string filename; + wi::Resource videoResource; + wi::video::VideoInstance videoinstance; + + inline bool IsPlaying() const { return _flags & PLAYING; } + inline bool IsLooped() const { return _flags & LOOPED; } + + inline void Play() { _flags |= PLAYING; } + inline void Stop() { _flags &= ~PLAYING; } + inline void SetLooped(bool value = true) { if (value) { _flags |= LOOPED; } else { _flags &= ~LOOPED; } } + + void Serialize(wi::Archive& archive, wi::ecs::EntitySerializer& seri); + }; + struct InverseKinematicsComponent { enum FLAGS diff --git a/WickedEngine/wiScene_Serializers.cpp b/WickedEngine/wiScene_Serializers.cpp index 7e723f9f1..7ffa98aef 100644 --- a/WickedEngine/wiScene_Serializers.cpp +++ b/WickedEngine/wiScene_Serializers.cpp @@ -1665,6 +1665,32 @@ namespace wi::scene archive << soundinstance.type; } } + void VideoComponent::Serialize(wi::Archive& archive, EntitySerializer& seri) + { + const std::string& dir = archive.GetSourceDirectory(); + + if (archive.IsReadMode()) + { + archive >> _flags; + archive >> filename; + + wi::jobsystem::Execute(seri.ctx, [&](wi::jobsystem::JobArgs args) { + if (!filename.empty()) + { + filename = dir + filename; + videoResource = wi::resourcemanager::Load(filename, wi::resourcemanager::Flags::IMPORT_RETAIN_FILEDATA); + wi::video::CreateVideoInstance(&videoResource.GetVideo(), &videoinstance); + } + }); + } + else + { + wi::helper::MakePathRelative(dir, filename); + + archive << _flags; + archive << filename; + } + } void InverseKinematicsComponent::Serialize(wi::Archive& archive, EntitySerializer& seri) { SerializeEntity(archive, target, seri); diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 7d4f3ad0e..bba47f5bf 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 71; // minor bug fixes, alterations, refactors, updates - const int revision = 194; + const int revision = 195; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision); @@ -127,6 +127,7 @@ Patreon supporters - nathants - Fahd Ahmed - Gabriel Jadderson +- SAS_Controller )"; return credits; diff --git a/WickedEngine/wiVideo.cpp b/WickedEngine/wiVideo.cpp new file mode 100644 index 000000000..3aa3f3a8a --- /dev/null +++ b/WickedEngine/wiVideo.cpp @@ -0,0 +1,679 @@ +#include "wiVideo.h" +#include "wiHelper.h" +#include "wiRenderer.h" +#include "wiBacklog.h" + +#include "Utility/minimp4.h" +#include "Utility/h264.h" + +//#define DEBUG_DUMP_H264 + +using namespace wi::graphics; + +namespace wi::video +{ + bool CreateVideo(const std::string& filename, Video* video) + { + wi::vector filedata; + if (!wi::helper::FileRead(filename, filedata)) + return false; + return CreateVideo(filedata.data(), filedata.size(), video); + } + bool CreateVideo(const uint8_t* filedata, size_t filesize, Video* video) + { + bool success = false; + const uint8_t* input_buf = filedata; + struct INPUT_BUFFER + { + const uint8_t* buffer; + size_t size; + } input_buffer = { input_buf,filesize }; + MP4D_demux_t mp4 = {}; + int token = 0; + auto read_callback = [](int64_t offset, void* buffer, size_t size, void* token) -> int + { + INPUT_BUFFER* buf = (INPUT_BUFFER*)token; + size_t to_copy = MINIMP4_MIN(size, buf->size - offset - size); + std::memcpy(buffer, buf->buffer + offset, to_copy); + return to_copy != size; + }; + int result = MP4D_open(&mp4, read_callback, &input_buffer, (int64_t)filesize); + if (result == 1) + { + video->title = {}; + video->album = {}; + video->artist = {}; + video->year = {}; + video->comment = {}; + video->genre = {}; + if (mp4.tag.title != nullptr) + { + video->title = (char*)mp4.tag.title; + } + if (mp4.tag.album != nullptr) + { + video->album = (char*)mp4.tag.album; + } + if (mp4.tag.artist != nullptr) + { + video->artist = (char*)mp4.tag.artist; + } + if (mp4.tag.year != nullptr) + { + video->year = (char*)mp4.tag.year; + } + if (mp4.tag.comment != nullptr) + { + video->comment = (char*)mp4.tag.comment; + } + if (mp4.tag.genre != nullptr) + { + video->genre = (char*)mp4.tag.genre; + } + + for (uint32_t ntrack = 0; ntrack < mp4.track_count; ntrack++) + { + MP4D_track_t& track = mp4.track[ntrack]; + +#ifdef DEBUG_DUMP_H264 + wi::vector dump; + size_t dump_offset = 0; +#endif // DEBUG_DUMP_H264 + + if (track.handler_type == MP4D_HANDLER_TYPE_VIDE) + { + switch (track.object_type_indication) + { + case MP4_OBJECT_TYPE_AVC: + video->profile = VideoProfile::H264; + break; + case MP4_OBJECT_TYPE_HEVC: + wi::helper::messageBox("H265 (HEVC) video format is not supported yet!", "Error!"); + return false; + default: + wi::helper::messageBox("Unknown video format!", "Error!"); + return false; + } + + // SPS: + video->sps_datas.clear(); + video->sps_count = 0; + video->num_dpb_slots = 0; + { + int size = 0; + int index = 0; + const void* data = nullptr; + while (data = MP4D_read_sps(&mp4, ntrack, index, &size)) + { + const uint8_t* sps_data = (const uint8_t*)data; +#ifdef DEBUG_DUMP_H264 + size_t additional_dump_size = sizeof(h264::start_code) + size; + dump.resize(dump.size() + additional_dump_size); + std::memcpy(dump.data() + dump_offset, h264::start_code, sizeof(h264::start_code)); + std::memcpy(dump.data() + dump_offset + sizeof(h264::start_code), sps_data, size); + dump_offset += additional_dump_size; +#endif // DEBUG_DUMP_H264 + + h264::Bitstream bs = {}; + bs.init(sps_data, size); + h264::NALHeader nal = {}; + h264::read_nal_header(&nal, &bs); + assert(nal.type = h264::NAL_UNIT_TYPE_SPS); + + h264::SPS sps = {}; + h264::read_sps(&sps, &bs); + + // Some validation checks that data parsing returned expected values: + // https://stackoverflow.com/questions/6394874/fetching-the-dimensions-of-a-h264video-stream + uint32_t width = ((sps.pic_width_in_mbs_minus1 + 1) * 16) - sps.frame_crop_left_offset * 2 - sps.frame_crop_right_offset * 2; + uint32_t height = ((2 - sps.frame_mbs_only_flag) * (sps.pic_height_in_map_units_minus1 + 1) * 16) - (sps.frame_crop_top_offset * 2) - (sps.frame_crop_bottom_offset * 2); + assert(track.SampleDescription.video.width == width); + assert(track.SampleDescription.video.height == height); + video->padded_width = (sps.pic_width_in_mbs_minus1 + 1) * 16; + video->padded_height = (sps.pic_height_in_map_units_minus1 + 1) * 16; + video->num_dpb_slots = std::max(video->num_dpb_slots, uint32_t(sps.num_ref_frames + 1)); + + video->sps_datas.resize(video->sps_datas.size() + sizeof(sps)); + std::memcpy((h264::SPS*)video->sps_datas.data() + video->sps_count, &sps, sizeof(sps)); + video->sps_count++; + index++; + } + } + + // PPS: + video->pps_datas.clear(); + video->pps_count = 0; + { + int size = 0; + int index = 0; + const void* data = nullptr; + while (data = MP4D_read_pps(&mp4, ntrack, index, &size)) + { + const uint8_t* pps_data = (const uint8_t*)data; +#ifdef DEBUG_DUMP_H264 + size_t additional_dump_size = sizeof(h264::start_code) + size; + dump.resize(dump.size() + additional_dump_size); + std::memcpy(dump.data() + dump_offset, h264::start_code, sizeof(h264::start_code)); + std::memcpy(dump.data() + dump_offset + sizeof(h264::start_code), pps_data, size); + dump_offset += additional_dump_size; +#endif // DEBUG_DUMP_H264 + + h264::Bitstream bs = {}; + bs.init(pps_data, size); + h264::NALHeader nal = {}; + h264::read_nal_header(&nal, &bs); + assert(nal.type = h264::NAL_UNIT_TYPE_PPS); + + h264::PPS pps = {}; + h264::read_pps(&pps, &bs); + video->pps_datas.resize(video->pps_datas.size() + sizeof(pps)); + std::memcpy((h264::PPS*)video->pps_datas.data() + video->pps_count, &pps, sizeof(pps)); + video->pps_count++; + index++; + } + } + + video->width = track.SampleDescription.video.width; + video->height = track.SampleDescription.video.height; + video->bit_rate = track.avg_bitrate_bps; + + double timescale_rcp = 1.0 / double(track.timescale); + + GraphicsDevice* device = GetDevice(); + const uint64_t alignment = device->GetVideoDecodeBitstreamAlignment(); + + const h264::PPS* pps_array = (const h264::PPS*)video->pps_datas.data(); + const h264::SPS* sps_array = (const h264::SPS*)video->sps_datas.data(); + int prev_pic_order_cnt_lsb = 0; + int prev_pic_order_cnt_msb = 0; + int poc_cycle = 0; + + video->frames_infos.reserve(track.sample_count); + video->slice_header_datas.reserve(track.sample_count * sizeof(h264::SliceHeader)); + video->slice_header_count = track.sample_count; + uint32_t track_duration = 0; + uint64_t aligned_size = 0; + for (uint32_t i = 0; i < track.sample_count; i++) + { + unsigned frame_bytes, timestamp, duration; + MP4D_file_offset_t ofs = MP4D_frame_offset(&mp4, ntrack, i, &frame_bytes, ×tamp, &duration); + track_duration += duration; + + Video::FrameInfo& info = video->frames_infos.emplace_back(); + info.offset = aligned_size; + + const uint8_t* src_buffer = input_buf + ofs; + while (frame_bytes > 0) + { + uint32_t size = ((uint32_t)src_buffer[0] << 24) | ((uint32_t)src_buffer[1] << 16) | ((uint32_t)src_buffer[2] << 8) | src_buffer[3]; + size += 4; + assert(frame_bytes >= size); + +#ifdef DEBUG_DUMP_H264 + size_t additional_dump_size = sizeof(h264::start_code) + size - 4; + dump.resize(dump.size() + additional_dump_size); + std::memcpy(dump.data() + dump_offset, h264::start_code, sizeof(h264::start_code)); + std::memcpy(dump.data() + dump_offset + sizeof(h264::start_code), src_buffer + 4, size - 4); + dump_offset += additional_dump_size; +#endif // DEBUG_DUMP_H264 + + h264::Bitstream bs = {}; + bs.init(&src_buffer[4], frame_bytes); + h264::NALHeader nal = {}; + h264::read_nal_header(&nal, &bs); + + if (nal.type == h264::NAL_UNIT_TYPE_CODED_SLICE_IDR) + { + info.type = VideoFrameType::Intra; + } + else if (nal.type == h264::NAL_UNIT_TYPE_CODED_SLICE_NON_IDR) + { + info.type = VideoFrameType::Predictive; + } + else + { + // Continue search for frame beginning NAL unit: + frame_bytes -= size; + src_buffer += size; + continue; + } + + h264::SliceHeader* slice_header = (h264::SliceHeader*)video->slice_header_datas.data() + i; + *slice_header = {}; + h264::read_slice_header(slice_header, &nal, pps_array, sps_array, &bs); + + const h264::PPS& pps = pps_array[slice_header->pic_parameter_set_id]; + const h264::SPS& sps = sps_array[pps.seq_parameter_set_id]; + + // Rec. ITU-T H.264 (08/2021) page 77 + int max_pic_order_cnt_lsb = 1 << (sps.log2_max_pic_order_cnt_lsb_minus4 + 4); + int pic_order_cnt_lsb = slice_header->pic_order_cnt_lsb; + + if (pic_order_cnt_lsb == 0) + { + poc_cycle++; + } + + // Rec. ITU-T H.264 (08/2021) page 115 + // Also: https://www.ramugedia.com/negative-pocs + int pic_order_cnt_msb = 0; + if (pic_order_cnt_lsb < prev_pic_order_cnt_lsb && (prev_pic_order_cnt_lsb - pic_order_cnt_lsb) >= max_pic_order_cnt_lsb / 2) + { + pic_order_cnt_msb = prev_pic_order_cnt_msb + max_pic_order_cnt_lsb; // pic_order_cnt_lsb wrapped around + } + else if (pic_order_cnt_lsb > prev_pic_order_cnt_lsb && (pic_order_cnt_lsb - prev_pic_order_cnt_lsb) > max_pic_order_cnt_lsb / 2) + { + pic_order_cnt_msb = prev_pic_order_cnt_msb - max_pic_order_cnt_lsb; // here negative POC might occur + } + else + { + pic_order_cnt_msb = prev_pic_order_cnt_msb; + } + //pic_order_cnt_msb = pic_order_cnt_msb % 256; + prev_pic_order_cnt_lsb = pic_order_cnt_lsb; + prev_pic_order_cnt_msb = pic_order_cnt_msb; + + // https://www.vcodex.com/h264avc-picture-management/ + info.poc = pic_order_cnt_msb + pic_order_cnt_lsb; // poc = TopFieldOrderCount + info.gop = poc_cycle - 1; + + // Accept frame beginning NAL unit: + info.reference_priority = nal.idc; + info.size = sizeof(h264::nal_start_code) + size - 4; + break; + } + + aligned_size += AlignTo(info.size, alignment); + info.timestamp_seconds = float(double(timestamp) * timescale_rcp); + info.duration_seconds = float(double(duration) * timescale_rcp); + } + +#ifdef DEBUG_DUMP_H264 + wi::helper::FileWrite("dump.h264", dump.data(), dump.size()); +#endif // DEBUG_DUMP_H264 + + video->frame_display_order.resize(video->frames_infos.size()); + for (size_t i = 0; i < video->frames_infos.size(); ++i) + { + video->frame_display_order[i] = i; + } + std::sort(video->frame_display_order.begin(), video->frame_display_order.end(), [&](size_t a, size_t b) { + const Video::FrameInfo& frameA = video->frames_infos[a]; + const Video::FrameInfo& frameB = video->frames_infos[b]; + int64_t prioA = (int64_t(frameA.gop) << 32ll) | int64_t(frameA.poc); + int64_t prioB = (int64_t(frameB.gop) << 32ll) | int64_t(frameB.poc); + return prioA < prioB; + }); + for (size_t i = 0; i < video->frame_display_order.size(); ++i) + { + video->frames_infos[video->frame_display_order[i]].display_order = (int)i; + } + + video->average_frames_per_second = float(double(track.timescale) / double(track_duration) * track.sample_count); + video->duration_seconds = float(double(track_duration) * timescale_rcp); + + auto copy_video_track = [&](void* dest) { + for (uint32_t i = 0; i < track.sample_count; i++) + { + unsigned frame_bytes, timestamp, duration; + MP4D_file_offset_t ofs = MP4D_frame_offset(&mp4, ntrack, i, &frame_bytes, ×tamp, &duration); + uint8_t* dst_buffer = (uint8_t*)dest + video->frames_infos[i].offset; + const uint8_t* src_buffer = input_buf + ofs; + while (frame_bytes > 0) + { + uint32_t size = ((uint32_t)src_buffer[0] << 24) | ((uint32_t)src_buffer[1] << 16) | ((uint32_t)src_buffer[2] << 8) | src_buffer[3]; + size += 4; + assert(frame_bytes >= size); + + h264::Bitstream bs = {}; + bs.init(&src_buffer[4], sizeof(uint8_t)); + h264::NALHeader nal = {}; + h264::read_nal_header(&nal, &bs); + + if ( + nal.type != h264::NAL_UNIT_TYPE_CODED_SLICE_IDR && + nal.type != h264::NAL_UNIT_TYPE_CODED_SLICE_NON_IDR + ) + { + frame_bytes -= size; + src_buffer += size; + continue; + } + + std::memcpy(dst_buffer, h264::nal_start_code, sizeof(h264::nal_start_code)); + std::memcpy(dst_buffer + sizeof(h264::nal_start_code), src_buffer + 4, size - 4); + break; + } + } + }; + + GPUBufferDesc bd; + bd.size = aligned_size; + bd.usage = Usage::UPLOAD; + bd.misc_flags = ResourceMiscFlag::VIDEO_DECODE; + success = device->CreateBuffer2(&bd, copy_video_track, &video->data_stream); + assert(success); + device->SetName(&video->data_stream, "wi::Video::data_stream"); + } + else if (track.handler_type == MP4D_HANDLER_TYPE_SOUN) + { + wi::backlog::post("Audio from video file is not implemented yet!"); + } + } + } + else + { + wi::helper::messageBox("MP4 parsing failure!", "Error!"); + return false; + } + MP4D_close(&mp4); + return success; + } + bool CreateVideoInstance(const Video* video, VideoInstance* instance) + { + instance->video = video; + instance->current_frame = 0; + instance->flags &= ~VideoInstance::Flags::InitialFirstFrameDecoded; + + GraphicsDevice* device = GetDevice(); + if (!device->CheckCapability(GraphicsDeviceCapability::VIDEO_DECODE_H264)) + { + wi::helper::messageBox("Video decoding is not supported by your GPU!\nYou can attempt to update graphics driver.\nThere is no CPU decoding implemented yet, video will be disabled!", "Warning!"); + return false; + } + + VideoDesc vd; + vd.width = video->padded_width; + vd.height = video->padded_height; + vd.bit_rate = video->bit_rate; + vd.format = Format::NV12; + vd.profile = video->profile; + vd.pps_datas = instance->video->pps_datas.data(); + vd.pps_count = instance->video->pps_count; + vd.sps_datas = instance->video->sps_datas.data(); + vd.sps_count = instance->video->sps_count; + vd.num_dpb_slots = video->num_dpb_slots; + bool success = device->CreateVideoDecoder(&vd, &instance->decoder); + assert(success); + + TextureDesc td; + td.width = vd.width; + td.height = vd.height; + td.format = vd.format; + td.array_size = video->num_dpb_slots; + td.bind_flags = BindFlag::SHADER_RESOURCE; + td.misc_flags = ResourceMiscFlag::VIDEO_DECODE; + td.layout = ResourceState::VIDEO_DECODE_DST; + success = device->CreateTexture(&td, nullptr, &instance->dpb.texture); + assert(success); + device->SetName(&instance->dpb.texture, "VideoInstance::DPB"); + + for (uint32_t i = 0; i < td.array_size; ++i) + { + instance->dpb.resource_states[i] = td.layout; + Format luminance_format = Format::R8_UNORM; + ImageAspect luminance_aspect = ImageAspect::LUMINANCE; + instance->dpb.subresources_luminance[i] = device->CreateSubresource( + &instance->dpb.texture, + SubresourceType::SRV, + i, 1, 0, 1, + &luminance_format, &luminance_aspect + ); + + Format chrominance_format = Format::R8G8_UNORM; + ImageAspect chrominance_aspect = ImageAspect::CHROMINANCE; + instance->dpb.subresources_chrominance[i] = device->CreateSubresource( + &instance->dpb.texture, + SubresourceType::SRV, + i, 1, 0, 1, + &chrominance_format, &chrominance_aspect + ); + } + + return success; + } + + bool IsDecodingRequired(const VideoInstance* instance, float dt) + { + if (!GetDevice()->CheckCapability(GraphicsDeviceCapability::VIDEO_DECODE_H264)) + return false; + if (instance == nullptr || instance->video == nullptr) + return false; + if (!has_flag(instance->flags, VideoInstance::Flags::InitialFirstFrameDecoded)) + return true; + if (has_flag(instance->flags, VideoInstance::Flags::Playing) && instance->time_until_next_frame - dt <= 0) + return true; + return false; + } + void UpdateVideo(VideoInstance* instance, float dt, CommandList cmd) + { + if (!GetDevice()->CheckCapability(GraphicsDeviceCapability::VIDEO_DECODE_H264)) + return; + if (instance == nullptr || instance->video == nullptr) + return; + + if (has_flag(instance->flags, VideoInstance::Flags::InitialFirstFrameDecoded)) + { + if (!has_flag(instance->flags, VideoInstance::Flags::Playing)) + return; + instance->time_until_next_frame -= dt; + if (instance->time_until_next_frame > 0) + return; + if (instance->current_frame >= (int)instance->video->frames_infos.size() - 1) + { + if (has_flag(instance->flags, VideoInstance::Flags::Looped)) + { + instance->current_frame = 0; + } + else + { + instance->flags &= ~VideoInstance::Flags::Playing; + instance->current_frame = (int)instance->video->frames_infos.size() - 1; + } + } + } + + if (!cmd.IsValid()) + return; + + GraphicsDevice* device = GetDevice(); + + const Video* video = instance->video; + instance->current_frame = std::min(instance->current_frame, std::max(0, (int)video->frames_infos.size() - 1)); + const Video::FrameInfo& frame_info = video->frames_infos[instance->current_frame]; + instance->time_until_next_frame = frame_info.duration_seconds; + + const h264::SliceHeader* slice_header = (const h264::SliceHeader*)video->slice_header_datas.data() + instance->current_frame; + const h264::PPS* pps = (const h264::PPS*)video->pps_datas.data() + slice_header->pic_parameter_set_id; + const h264::SPS* sps = (const h264::SPS*)video->sps_datas.data() + pps->seq_parameter_set_id; + + VideoDecodeOperation decode_operation; + if (instance->current_frame == 0 || has_flag(instance->flags, VideoInstance::Flags::DecoderReset)) + { + decode_operation.flags = VideoDecodeOperation::FLAG_SESSION_RESET; + instance->flags &= ~VideoInstance::Flags::DecoderReset; + instance->output = {}; + instance->output_textures_free.clear(); + instance->output_textures_used.clear(); + instance->target_display_order = instance->current_frame; + } + if (frame_info.type == VideoFrameType::Intra) + { + instance->dpb.reference_usage.clear(); + instance->dpb.next_ref = 0; + instance->dpb.next_slot = 0; + } + instance->dpb.current_slot = instance->dpb.next_slot; + instance->dpb.poc_status[instance->dpb.current_slot] = frame_info.poc; + instance->dpb.framenum_status[instance->dpb.current_slot] = slice_header->frame_num; + decode_operation.stream = &video->data_stream; + decode_operation.stream_offset = frame_info.offset; + decode_operation.stream_size = frame_info.size; + decode_operation.poc[0] = frame_info.poc; + decode_operation.poc[1] = frame_info.poc; + decode_operation.frame_type = frame_info.type; + decode_operation.reference_priority = frame_info.reference_priority; + decode_operation.decoded_frame_index = instance->current_frame; + decode_operation.slice_header = slice_header; + decode_operation.pps = pps; + decode_operation.sps = sps; + decode_operation.current_dpb = instance->dpb.current_slot; + decode_operation.dpb_reference_count = (uint32_t)instance->dpb.reference_usage.size(); + decode_operation.dpb_reference_slots = instance->dpb.reference_usage.data(); + decode_operation.dpb_poc = instance->dpb.poc_status; + decode_operation.dpb_framenum = instance->dpb.framenum_status; + decode_operation.DPB = &instance->dpb.texture; + + ImageAspect aspect_luma = ImageAspect::LUMINANCE; + ImageAspect aspect_chroma = ImageAspect::CHROMINANCE; + // Ensure that current DPB slot is in DST state: + if (instance->dpb.resource_states[instance->dpb.current_slot] != ResourceState::VIDEO_DECODE_DST) + { + instance->barriers.push_back(GPUBarrier::Image(&instance->dpb.texture, instance->dpb.resource_states[instance->dpb.current_slot], ResourceState::VIDEO_DECODE_DST, 0, instance->dpb.current_slot, &aspect_luma)); + instance->barriers.push_back(GPUBarrier::Image(&instance->dpb.texture, instance->dpb.resource_states[instance->dpb.current_slot], ResourceState::VIDEO_DECODE_DST, 0, instance->dpb.current_slot, &aspect_chroma)); + instance->dpb.resource_states[instance->dpb.current_slot] = ResourceState::VIDEO_DECODE_DST; + } + // Ensure that reference frame DPB slots are in SRC state: + for (size_t i = 0; i < instance->dpb.reference_usage.size(); ++i) + { + uint8_t ref = instance->dpb.reference_usage[i]; + if (instance->dpb.resource_states[ref] != ResourceState::VIDEO_DECODE_SRC) + { + instance->barriers.push_back(GPUBarrier::Image(&instance->dpb.texture, instance->dpb.resource_states[ref], ResourceState::VIDEO_DECODE_SRC, 0, ref, &aspect_luma)); + instance->barriers.push_back(GPUBarrier::Image(&instance->dpb.texture, instance->dpb.resource_states[ref], ResourceState::VIDEO_DECODE_SRC, 0, ref, &aspect_chroma)); + instance->dpb.resource_states[ref] = ResourceState::VIDEO_DECODE_SRC; + } + } + if (!instance->barriers.empty()) + { + device->Barrier(instance->barriers.data(), (uint32_t)instance->barriers.size(), cmd); + instance->barriers.clear(); + } + + device->VideoDecode(&instance->decoder, &decode_operation, cmd); + + // The current DPB slot is transitioned into a shader readable state because it will need to be resolved into RGB on a different GPU queue: + // The video queue must be used to transition from video states + if (instance->dpb.resource_states[instance->dpb.current_slot] != ResourceState::SHADER_RESOURCE_COMPUTE) + { + GPUBarrier barriers[] = { + GPUBarrier::Image(&instance->dpb.texture, instance->dpb.resource_states[instance->dpb.current_slot], ResourceState::SHADER_RESOURCE_COMPUTE, 0, instance->dpb.current_slot, &aspect_luma), + GPUBarrier::Image(&instance->dpb.texture, instance->dpb.resource_states[instance->dpb.current_slot], ResourceState::SHADER_RESOURCE_COMPUTE, 0, instance->dpb.current_slot, &aspect_chroma), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + instance->dpb.resource_states[instance->dpb.current_slot] = ResourceState::SHADER_RESOURCE_COMPUTE; + } + + // DPB slot management: + // When current frame was a reference, then the next frame can not overwrite its DPB slot, so increment next_slot as a ring buffer + // However, the ring buffer will wrap around so older reference frames can be overwritten by this + if (frame_info.reference_priority > 0) + { + if (instance->dpb.next_ref >= instance->dpb.reference_usage.size()) + { + instance->dpb.reference_usage.resize(instance->dpb.next_ref + 1); + } + instance->dpb.reference_usage[instance->dpb.next_ref] = instance->dpb.current_slot; + instance->dpb.next_ref = (instance->dpb.next_ref + 1) % (instance->dpb.texture.desc.array_size - 1); + instance->dpb.next_slot = (instance->dpb.next_slot + 1) % instance->dpb.texture.desc.array_size; + } + + instance->flags |= VideoInstance::Flags::NeedsResolve; + instance->flags |= VideoInstance::Flags::InitialFirstFrameDecoded; + instance->current_frame++; + } + void ResolveVideoToRGB(VideoInstance* instance, CommandList cmd) + { + if (instance == nullptr || instance->video == nullptr) + return; + if (!has_flag(instance->flags, VideoInstance::Flags::NeedsResolve)) + return; + instance->flags &= ~VideoInstance::Flags::NeedsResolve; + + const Video* video = instance->video; + GraphicsDevice* device = GetDevice(); + + if (instance->output_textures_free.empty()) + { + VideoInstance::OutputTexture& output = instance->output_textures_free.emplace_back(); + TextureDesc td; + td.width = video->width; + td.height = video->height; + td.format = Format::R8G8B8A8_UNORM; + if (has_flag(instance->flags, VideoInstance::Flags::Mipmapped)) + { + td.mip_levels = 0; // max mipcount + } + td.bind_flags = BindFlag::UNORDERED_ACCESS | BindFlag::SHADER_RESOURCE; + td.misc_flags = ResourceMiscFlag::TYPED_FORMAT_CASTING; + td.layout = ResourceState::SHADER_RESOURCE_COMPUTE; + bool success = device->CreateTexture(&td, nullptr, &output.texture); + device->SetName(&output.texture, "VideoInstance::OutputTexture"); + assert(success); + + if (has_flag(instance->flags, VideoInstance::Flags::Mipmapped)) + { + for (uint32_t i = 0; i < output.texture.GetDesc().mip_levels; ++i) + { + int subresource_index; + subresource_index = device->CreateSubresource(&output.texture, SubresourceType::SRV, 0, 1, i, 1); + assert(subresource_index == i); + subresource_index = device->CreateSubresource(&output.texture, SubresourceType::UAV, 0, 1, i, 1); + assert(subresource_index == i); + } + } + + // This part must be AFTER mip level subresource creation: + Format srgb_format = GetFormatSRGB(td.format); + output.subresource_srgb = device->CreateSubresource( + &output.texture, + SubresourceType::SRV, + 0, -1, + 0, -1, + &srgb_format + ); + } + + VideoInstance::OutputTexture output = std::move(instance->output_textures_free.back()); + instance->output_textures_free.pop_back(); + output.display_order = video->frames_infos[std::max(instance->current_frame - 1, 0)].display_order; + + wi::renderer::YUV_to_RGB( + instance->dpb.texture, + instance->dpb.subresources_luminance[instance->dpb.current_slot], + instance->dpb.subresources_chrominance[instance->dpb.current_slot], + output.texture, + cmd + ); + + if (has_flag(instance->flags, VideoInstance::Flags::Mipmapped)) + { + wi::renderer::GenerateMipChain(output.texture, wi::renderer::MIPGENFILTER_LINEAR, cmd); + } + + instance->output_textures_used.push_back(std::move(output)); + + for (size_t i = 0; i < instance->output_textures_used.size(); ++i) + { + if (instance->output_textures_used[i].display_order == instance->target_display_order) + { + if (instance->output.texture.IsValid()) + { + // Free current output texture: + instance->output_textures_free.push_back(std::move(instance->output)); + } + + // Take this used texture as current oputput: + instance->output = std::move(instance->output_textures_used[i]); + + // Remove this used texture: + std::swap(instance->output_textures_used[i], instance->output_textures_used.back()); + instance->output_textures_used.pop_back(); + + // request next displayable picture in order: + instance->target_display_order++; + break; + } + } + } +} diff --git a/WickedEngine/wiVideo.h b/WickedEngine/wiVideo.h new file mode 100644 index 000000000..475caca2b --- /dev/null +++ b/WickedEngine/wiVideo.h @@ -0,0 +1,109 @@ +#pragma once +#include "CommonInclude.h" +#include "wiGraphicsDevice.h" +#include "wiVector.h" +#include "wiUnorderedSet.h" + +#include +#include + +namespace wi::video +{ + struct Video + { + std::string title; + std::string album; + std::string artist; + std::string year; + std::string comment; + std::string genre; + uint32_t padded_width = 0; + uint32_t padded_height = 0; + uint32_t width = 0; + uint32_t height = 0; + uint32_t bit_rate = 0; + wi::graphics::VideoProfile profile = wi::graphics::VideoProfile::H264; + wi::vector sps_datas; + wi::vector pps_datas; + wi::vector slice_header_datas; + uint32_t sps_count = 0; + uint32_t pps_count = 0; + uint32_t slice_header_count = 0; + wi::graphics::GPUBuffer data_stream; + float average_frames_per_second = 0; + float duration_seconds = 0; + struct FrameInfo + { + uint64_t offset = 0; + uint64_t size = 0; + float timestamp_seconds = 0; + float duration_seconds = 0; + wi::graphics::VideoFrameType type = wi::graphics::VideoFrameType::Intra; + uint32_t reference_priority = 0; + int poc = 0; + int gop = 0; + int display_order = 0; + }; + wi::vector frames_infos; + wi::vector frame_display_order; + uint32_t num_dpb_slots = 0; + inline bool IsValid() const { return data_stream.IsValid(); } + }; + + struct VideoInstance + { + const Video* video = nullptr; + wi::graphics::VideoDecoder decoder; + struct DPB + { + wi::graphics::Texture texture; + int subresources_luminance[17] = {}; + int subresources_chrominance[17] = {}; + int poc_status[17] = {}; + int framenum_status[17] = {}; + wi::graphics::ResourceState resource_states[17] = {}; + wi::vector reference_usage; + uint8_t next_ref = 0; + uint8_t next_slot = 0; + uint8_t current_slot = 0; + } dpb; + struct OutputTexture + { + wi::graphics::Texture texture; + int subresource_srgb = -1; + int display_order = -1; + }; + wi::vector output_textures_free; + wi::vector output_textures_used; + OutputTexture output; + int target_display_order = 0; + int current_frame = 0; + float time_until_next_frame = 0; + wi::vector barriers; + enum class Flags + { + Empty = 0, + Playing = 1 << 0, + Looped = 1 << 1, + Mipmapped = 1 << 2, + NeedsResolve = 1 << 3, + InitialFirstFrameDecoded = 1 << 4, + DecoderReset = 1 << 5, + }; + Flags flags = Flags::Empty; + inline bool IsValid() const { return decoder.IsValid(); } + }; + + bool CreateVideo(const std::string& filename, Video* video); + bool CreateVideo(const uint8_t* filedata, size_t filesize, Video* video); + bool CreateVideoInstance(const Video* video, VideoInstance* instance); + + bool IsDecodingRequired(const VideoInstance* instance, float dt); + void UpdateVideo(VideoInstance* instance, float dt, wi::graphics::CommandList cmd); + void ResolveVideoToRGB(VideoInstance* instance, wi::graphics::CommandList cmd); +} + +template<> +struct enable_bitmask_operators { + static const bool enable = true; +}; diff --git a/third_party_software.txt b/third_party_software.txt index 95a366b12..1b5dcd8ff 100644 --- a/third_party_software.txt +++ b/third_party_software.txt @@ -566,6 +566,17 @@ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +############################################################################################################################### + +MiniMP4: https://github.com/lieff/minimp4 + +https://github.com/aspt/mp4 +https://github.com/lieff/minimp4 +To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. +This software is distributed without any warranty. +See . + + ############################################################################################################################### ###############################################################################################################################