Diligent Core عبارة عن واجهة برمجة تطبيقات حديثة للرسومات منخفضة المستوى ومتعددة المنصات تشكل الأساس لمحرك Diligent. تطبق الوحدة الواجهات الخلفية للعرض Direct3D11 وDirect3D12 وOpenGL وOpenGLES وVulkan (يتوفر تطبيق Metal للعملاء التجاريين)، بالإضافة إلى الأدوات المساعدة الأساسية الخاصة بالمنصة. إنها قائمة بذاتها ويمكن بناؤها بمفردها. يرجى الرجوع إلى المستودع الرئيسي للحصول على معلومات حول الأنظمة الأساسية والميزات المدعومة وتعليمات البناء وما إلى ذلك.
منصة | حالة البناء |
---|---|
Win32 | |
ويندوز العالمي | |
لينكس | |
أندرويد | |
ماك | |
دائرة الرقابة الداخلية | |
tvOS | |
إمسكريتن |
استنساخ المستودع
أساسيات واجهة برمجة التطبيقات
تخطيط موارد خطوط الأنابيب
Win32
منصة ويندوز العالمية
لينكس
ماك
أندرويد
دائرة الرقابة الداخلية
إمسكريتن
تدمير المحرك
تهيئة المحرك
إنشاء الموارد
إنشاء تظليل
تهيئة حالة خط الأنابيب
ملزمة الموارد شادر
ضبط حالة خط الأنابيب واستدعاء أمر الرسم
إمكانية التشغيل التفاعلي لواجهة برمجة التطبيقات (API) ذات المستوى المنخفض
تعليمات بناء حزمة NuGet
رخصة
المساهمة
تاريخ الإصدار
للحصول على المستودع وجميع الوحدات الفرعية، استخدم الأمر التالي:
git clone --recursive https://github.com/DiligentGraphics/DiligentCore.git
لبناء الوحدة، راجع تعليمات البناء في المستودع الرئيسي.
قبل أن تتمكن من استخدام أي وظيفة يوفرها المحرك، تحتاج إلى إنشاء جهاز عرض وسياق فوري وسلسلة مبادلة.
على منصة Win32، يمكنك إنشاء جهاز OpenGL أو Direct3D11 أو Direct3D12 أو Vulkan كما هو موضح أدناه:
باطلة تهيئة ديليجنت إنجين (HWND NativeWindowHandle) { SwapChainDesc SCDesc;// RefCntAutoPtr<IRenderDevice> m_pDevice;// RefCntAutoPtr<IDeviceContext> m_pImmediateContext;// RefCntAutoPtr<ISwapChain> m_pSwapChain;switch (m_DeviceType) {الحالة RENDER_DEVICE_TYPE_D3D11: { EngineD3D11CreateInfo EngineCI; # if ENGINE_DLL// قم بتحميل ملف dll واستيراد GetEngineFactoryD3D11() functionauto* GetEngineFactoryD3D11 = LoadGraphicsEngineD3D11(); # endifauto* pFactoryD3D11 = GetEngineFactoryD3D11(); pFactoryD3D11->CreateDeviceAndContextsD3D11(EngineCI, &m_pDevice, &m_pImmediateContext); Win32NativeWindow Window{hWnd}; pFactoryD3D11->إنشاء SwapChainD3D11(m_pDevice، m_pImmediateContext، SCDesc، FullScreenModeDesc{}, Window, &m_pSwapChain); }فاصل؛حالة RENDER_DEVICE_TYPE_D3D12: { # if ENGINE_DLL// قم بتحميل ملف dll واستيراد GetEngineFactoryD3D12() functionauto GetEngineFactoryD3D12 = LoadGraphicsEngineD3D12(); # endifEngineD3D12CreateInfo EngineCI;auto* pFactoryD3D12 = GetEngineFactoryD3D12(); pFactoryD3D12->CreateDeviceAndContextsD3D12(EngineCI, &m_pDevice, &m_pImmediateContext); Win32NativeWindow Window{hWnd}; pFactoryD3D12->إنشاء SwapChainD3D12(m_pDevice، m_pImmediateContext، SCDesc، FullScreenModeDesc{}, Window, &m_pSwapChain); }فاصل؛حالة RENDER_DEVICE_TYPE_GL: { # if EXPLICITLY_LOAD_ENGINE_GL_DLL// قم بتحميل ملف dll واستيراد GetEngineFactoryOpenGL() functionauto GetEngineFactoryOpenGL = LoadGraphicsEngineOpenGL(); # endifauto* pFactoryOpenGL = GetEngineFactoryOpenGL(); EngineGLCreateInfo EngineCI; EngineCI.Window.hWnd = hWnd; pFactoryOpenGL->CreateDeviceAndSwapChainGL(EngineCI, &m_pDevice, &m_pImmediateContext, SCDesc, &m_pSwapChain); }فاصل؛الحالة RENDER_DEVICE_TYPE_VULKAN: { # if EXPLICITLY_LOAD_ENGINE_VK_DLL// قم بتحميل ملف dll واستيراد GetEngineFactoryVk() functionauto GetEngineFactoryVk = LoadGraphicsEngineVk(); # endifEngineVkCreateInfo EngineCI;auto* pFactoryVk = GetEngineFactoryVk(); pFactoryVk->CreateDeviceAndContextsVk(EngineCI, &m_pDevice, &m_pImmediateContext); Win32NativeWindow Window{hWnd}; pFactoryVk->CreateSwapChainVk(m_pDevice, m_pImmediateContext, SCDesc, Window, &m_pSwapChain); }كسر؛افتراضي: std::cerr << "نوع الجهاز غير معروف"; } }
في نظام التشغيل Windows، يمكن ربط المحرك بشكل ثابت بالتطبيق أو إنشاءه كملف DLL منفصل. في الحالة الأولى، يمكن استدعاء وظائف المصنع GetEngineFactoryOpenGL()
و GetEngineFactoryD3D11()
و GetEngineFactoryD3D12()
و GetEngineFactoryVk()
مباشرة. في الحالة الثانية، تحتاج إلى تحميل ملف DLL في مساحة عنوان العملية باستخدام وظيفة LoadGraphicsEngineOpenGL()
أو LoadGraphicsEngineD3D11()
أو LoadGraphicsEngineD3D12()
أو LoadGraphicsEngineVk()
. تقوم كل وظيفة بتحميل المكتبة الديناميكية المناسبة وتستورد الوظائف المطلوبة لتهيئة المحرك. يجب عليك تضمين الرؤوس التالية:
#include "EngineFactoryD3D11.h" #include "EngineFactoryD3D12.h" #include "EngineFactoryOpenGL.h" #include "EngineFactoryVk.h"
تحتاج أيضًا إلى إضافة الدلائل التالية إلى مسارات البحث المضمنة:
DiligentCore/Graphics/GraphicsEngineD3D11/interface
DiligentCore/Graphics/GraphicsEngineD3D12/interface
DiligentCore/Graphics/GraphicsEngineOpenGL/interface
DiligentCore/Graphics/GraphicsEngineVulkan/interface
وكبديل، يمكنك فقط إضافة المسار إلى المجلد الجذر ثم استخدام المسارات المرتبطة به.
تمكين مساحة الاسم Diligent
:
باستخدام مساحة الاسم الدؤوب؛
يمكن لوظائف IEngineFactoryD3D11::CreateDeviceAndContextsD3D11()
و IEngineFactoryD3D12::CreateDeviceAndContextsD3D12()
و IEngineFactoryVk::CreateDeviceAndContextsVk()
أيضًا إنشاء عدد محدد من السياقات المباشرة والمؤجلة، والتي يمكن استخدامها للعرض غير المتزامن و تسجيل الأوامر متعدد الخيوط. لا يجوز إنشاء السياقات إلا أثناء تهيئة المحرك. تقوم الدالة بملء مجموعة من المؤشرات إلى السياقات، حيث تنتقل السياقات الفورية أولاً، تليها جميع السياقات المؤجلة.
لمزيد من التفاصيل، قم بإلقاء نظرة على ملف Tutorial00_HelloWin32.cpp.
على النظام الأساسي العالمي Windows، يمكنك إنشاء جهاز Direct3D11 أو Direct3D12. يتم تنفيذ التهيئة بنفس الطريقة كما هو الحال في نظام Win32 الأساسي. الفرق هو أنك تقوم أولاً بإنشاء سياقات جهاز العرض والجهاز عن طريق استدعاء IEngineFactoryD3D11::CreateDeviceAndContextsD3D11()
أو IEngineFactoryD3D12::CreateDeviceAndContextsD3D12()
. يتم إنشاء سلسلة المبادلة لاحقًا عن طريق استدعاء IEngineFactoryD3D11::CreateSwapChainD3D11()
أو IEngineFactoryD3D12::CreateSwapChainD3D12()
. يرجى الاطلاع على ملف SampleAppUWP.cpp لمزيد من التفاصيل.
على نظام التشغيل Linux، يدعم المحرك واجهات OpenGL وVulkan الخلفية. تقترن تهيئة سياق GL على Linux بإحكام بإنشاء النافذة. ونتيجة لذلك، لا يقوم Diligent Engine بتهيئة السياق، ولكنه يرتبط بالسياق الذي تمت تهيئته بواسطة التطبيق. يمكن العثور على مثال لتهيئة المحرك على Linux في Tutorial00_HelloLinux.cpp.
في نظام التشغيل MacOS، يدعم Diligent Engine الواجهات الخلفية لـ OpenGL وVulkan وMetal. يتم تنفيذ تهيئة سياق GL على نظام MacOS بواسطة التطبيق، ويرتبط المحرك بالسياق الذي أنشأه التطبيق؛ راجع GLView.mm للحصول على التفاصيل. تتم تهيئة الواجهة الخلفية لـ Vulkan بشكل مشابه للمنصات الأخرى. انظر MetalView.mm.
على Android، يمكنك إنشاء جهاز OpenGLES أو Vulkan. يعرض مقتطف الكود التالي مثالاً:
auto* pFactoryOpenGL = GetEngineFactoryOpenGL(); EngineGLCreateInfo EngineCI; EngineCI.Window.pAWindow = NativeWindowHandle; pFactoryOpenGL->CreateDeviceAndSwapChainGL( EngineCI، &m_pDevice، &m_pContext، SCDesc، &m_pSwapChain)؛
إذا تم إنشاء المحرك كمكتبة ديناميكية، فيجب تحميل المكتبة بواسطة النشاط الأصلي. يوضح الكود التالي إحدى الطرق الممكنة:
static{try{System.loadLibrary("GraphicsEngineOpenGL"); } Catch (UnsatisfiedLinkError e) {Log.e("native-activity"، "فشل تحميل مكتبة GraphicsEngineOpenGL.n" + e); } }
يدعم تطبيق iOS الواجهة الخلفية OpenGLES وVulkan وMetal. يتم تنفيذ تهيئة سياق GL على نظام التشغيل iOS بواسطة التطبيق، ويرتبط المحرك بالسياق الذي تمت تهيئته بواسطة التطبيق؛ راجع EAGLView.mm للحصول على التفاصيل.
في Emscripten، يمكنك إنشاء جهاز OpenGLES. يعرض مقتطف الكود التالي مثالاً:
// تحتاج إلى تمرير معرف اللوحة القماشية إلى NativeWindowauto* pFactoryOpenGL = GetEngineFactoryOpenGL(); EngineGLCreateInfo EngineCI = {}; EngineCI.Window = NativeWindow{"#canvas"}; pFactoryOpenGL->CreateDeviceAndSwapChainGL(EngineCI, &m_pDevice, &m_pContext, SCDesc, &m_pSwapChain);
إذا كنت تستخدم SDL أو GLFW مع سياق موجود، فيمكنك توفير null كمقبض النافذة الأصلي: EngineCI.Window = NativeWindow{nullptr}
يقوم المحرك بإجراء العد المرجعي تلقائيًا ويتم إيقاف تشغيله عند تحرير المرجع الأخير لكائن المحرك.
يتم إنشاء موارد الجهاز بواسطة جهاز العرض. النوعان الرئيسيان من الموارد هما المخازن المؤقتة، التي تمثل الذاكرة الخطية، والأنسجة، التي تستخدم تخطيطات الذاكرة المحسنة للتصفية السريعة. لإنشاء مخزن مؤقت، تحتاج إلى ملء بنية BufferDesc
واستدعاء IRenderDevice::CreateBuffer()
. يقوم التعليمة البرمجية التالية بإنشاء مخزن مؤقت موحد (ثابت):
BufferDesc BuffDesc; BuffDesc.Name = "المخزن المؤقت الموحد"; BuffDesc.BindFlags = BIND_UNIFORM_BUFFER; BuffDesc.Usage = USAGE_DYNAMIC; BuffDesc.uiSizeInBytes = sizeof(ShaderConstants); BuffDesc.CPUAccessFlags = CPU_ACCESS_WRITE; m_pDevice->CreateBuffer(BuffDesc, nullptr, &m_pConstantBuffer);
وبالمثل، لإنشاء نسيج، قم بملء بنية TextureDesc
واستدعاء IRenderDevice::CreateTexture()
كما في المثال التالي:
TextureDesc TexDesc; TexDesc.Name = "نسيجي ثنائي الأبعاد"; TexDesc.Type = TEXTURE_TYPE_2D; TexDesc.Width = 1024; TexDesc.Height = 1024; TexDesc.Format = TEX_FORMAT_RGBA8_UNORM; TexDesc.Usage = USAGE_DEFAULT; TexDesc.BindFlags = BIND_SHADER_RESOURCE | BIND_RENDER_TARGET | BIND_UNORDERED_ACCESS; TexDesc.Name = "نموذج نسيج ثنائي الأبعاد"؛ m_pRenderDevice->CreateTexture(TexDesc, nullptr, &m_pTestTex);
توجد وظيفة واحدة فقط CreateTexture()
قادرة على إنشاء جميع أنواع الأنسجة. يتم تحديد النوع والتنسيق وحجم الصفيف وجميع المعلمات الأخرى بواسطة أعضاء بنية TextureDesc
.
لكل علامة ربط محددة أثناء وقت إنشاء النسيج، يقوم كائن النسيج بإنشاء عرض افتراضي. يعالج عرض مورد التظليل الافتراضي النسيج بأكمله، وتشير طرق عرض استنسل الهدف والعمق الافتراضية إلى جميع شرائح المصفوفة في مستوى mip الأكثر تفصيلاً، وتشير طريقة عرض الوصول غير المرتبة إلى النسيج بأكمله. للحصول على عرض افتراضي من المادة، استخدم الدالة ITexture::GetDefaultView()
. لاحظ أن هذه الوظيفة لا تزيد العداد المرجعي للواجهة التي تم إرجاعها. يمكنك إنشاء عروض نسيج إضافية باستخدام ITexture::CreateView()
. استخدم IBuffer::CreateView()
لإنشاء طرق عرض إضافية للمخزن المؤقت.
لإنشاء تظليل، قم بملء بنية ShaderCreateInfo
:
ShaderCreateInfo ShaderCI;
هناك ثلاث طرق لإنشاء تظليل. الطريقة الأولى هي توفير مؤشر للكود المصدري للتظليل من خلال عضو ShaderCreateInfo::Source
. الطريقة الثانية هي توفير اسم الملف. الطريقة الثالثة هي توفير مؤشر لرمز البايت المترجم من خلال عضو ShaderCreateInfo::ByteCode
. تم فصل محرك الرسومات تمامًا عن النظام الأساسي. نظرًا لأن نظام الملفات المضيف يعتمد على النظام الأساسي، فإن البنية تكشف عن عضو ShaderCreateInfo::pShaderSourceStreamFactory
الذي يهدف إلى منح المحرك حق الوصول إلى نظام الملفات. إذا قمت بتوفير اسم الملف المصدر، فيجب عليك أيضًا توفير مؤشر غير فارغ لمصنع دفق مصدر التظليل. إذا كان مصدر التظليل يحتوي على أي توجيهات #include
، فسيتم استخدام مصنع التدفق المصدر أيضًا لتحميل هذه الملفات. يوفر المحرك التنفيذ الافتراضي لكل منصة مدعومة والتي يجب أن تكون كافية في معظم الحالات. ومع ذلك، يمكنك تحديد التنفيذ الخاص بك.
عضو مهم هو ShaderCreateInfo::SourceLanguage
. فيما يلي القيم الصالحة لهذا العضو:
SHADER_SOURCE_LANGUAGE_DEFAULT
- يتطابق تنسيق مصدر التظليل مع واجهة برمجة تطبيقات الرسومات الأساسية: HLSL لوضع D3D11 أو D3D12، وGLSL لأوضاع OpenGL وOpenGLES وVulkan.
SHADER_SOURCE_LANGUAGE_HLSL
- مصدر التظليل موجود في HLSL. بالنسبة لأوضاع OpenGL وOpenGLES، سيتم تحويل كود المصدر إلى GLSL. في الواجهة الخلفية لـ Vulkan، سيتم تجميع التعليمات البرمجية إلى SPIRV مباشرة.
SHADER_SOURCE_LANGUAGE_GLSL
- مصدر التظليل موجود في GLSL.
SHADER_SOURCE_LANGUAGE_GLSL_VERBATIM
- لغة مصدر التظليل هي GLSL ويجب تجميعها حرفيًا.
SHADER_SOURCE_LANGUAGE_MSL
- اللغة المصدر هي لغة تظليل المعادن.
يحدد الأعضاء الآخرون في بنية ShaderCreateInfo
التظليل بما في ذلك أدلة البحث وتعريفات ماكرو التظليل ونقطة دخول التظليل والمعلمات الأخرى.
ShaderMacroHelper وحدات الماكرو؛ Macros.AddShaderMacro("USE_SHADOWS", 1); Macros.AddShaderMacro("NUM_SHADOW_SAMPLES"، 4); Macros.Finalize(); ShaderCI.Macros = وحدات الماكرو؛
عندما يصبح كل شيء جاهزًا، اتصل بـ IRenderDevice::CreateShader()
لإنشاء كائن التظليل:
ShaderCreateInfo ShaderCI; ShaderCI.Desc.Name = "MyPixelShader"; ShaderCI.FilePath = "MyShaderFile.fx"; ShaderCI.EntryPoint = "MyPixelShader"; ShaderCI.Desc.ShaderType = SHADER_TYPE_PIXEL; ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;const auto* SearchDirectories = "shaders;shadersinc;"; RefCntAutoPtr<IShaderSourceInputStreamFactory> pShaderSourceFactory; m_pEngineFactory->CreateDefaultShaderSourceStreamFactory(SearchDirectories, &pShaderSourceFactory); ShaderCI.pShaderSourceStreamFactory = pShaderSourceFactory; RefCntAutoPtr<IShader> pShader; m_pDevice->CreateShader(ShaderCI, &pShader);
يتبع محرك Diligent أسلوب Direct3D12/Vulkan لتكوين مسار الرسومات/الحوسبة. يشتمل كائن حالة خطوط الأنابيب المتجانسة (PSO) على جميع الحالات المطلوبة (جميع مراحل التظليل ووصف تخطيط الإدخال واستنسل العمق وأوصاف حالة التنقيط والمزج وما إلى ذلك). لإنشاء كائن حالة خط أنابيب الرسومات، حدد مثيلًا لبنية GraphicsPipelineStateCreateInfo
:
GraphicsPipelineStateCreateInfo PSOCreateInfo؛ PipelineStateDesc& PSODesc = PSOCreateInfo.PSODesc; PSODesc.Name = "حالة خط الأنابيب الخاص بي"؛
قم بوصف تفاصيل خط الأنابيب مثل عدد وتنسيق أهداف العرض بالإضافة إلى تنسيق استنسل العمق:
// هذا هو خط أنابيب الرسوماتPSODesc.PipelineType = PIPELINE_TYPE_GRAPHICS; PSOCreateInfo.GraphicsPipeline.NumRenderTargets = 1; PSOCreateInfo.GraphicsPipeline.RTVFormats[0] = TEX_FORMAT_RGBA8_UNORM_SRGB; PSOCreateInfo.GraphicsPipeline.DSVFormat = TEX_FORMAT_D32_FLOAT;
تهيئة وصف حالة استنسل العمق DepthStencilStateDesc
. لاحظ أن المنشئ يقوم بتهيئة الأعضاء بقيم افتراضية ويمكنك فقط تعيين تلك التي تختلف عن القيمة الافتراضية.
// Init Deep-stencilstateDepthStencilStateDesc& DepthStencilDesc = PSOCreateInfo.GraphicsPipeline.DepthStencilDesc; DepthStencilDesc.DepthEnable = true; DepthStencilDesc.DepthWriteEnable = true;
تهيئة وصف حالة المزج BlendStateDesc
:
// مزيج Init StateBlendStateDesc& BSDesc = PSOCreateInfo.GraphicsPipeline.BlendDesc; BSDesc.IndependentBlendEnable = False;auto &RT0 = BSDesc.RenderTargets[0]; RT0.BlendEnable = صحيح؛ RT0.RenderTargetWriteMask = COLOR_MASK_ALL; RT0.SrcBlend = BLEND_FACTOR_SRC_ALPHA; RT0.DestBlend = BLEND_FACTOR_INV_SRC_ALPHA; RT0.BlendOp = BLEND_OPERATION_ADD; RT0.SrcBlendAlpha = BLEND_FACTOR_SRC_ALPHA; RT0.DestBlendAlpha = BLEND_FACTOR_INV_SRC_ALPHA; RT0.BlendOpAlpha = BLEND_OPERATION_ADD;
تهيئة وصف حالة أداة المسح RasterizerStateDesc
:
// Init rasterizerstateRasterizerStateDesc& RasterizerDesc = PSOCreateInfo.GraphicsPipeline.RasterizerDesc; RasterizerDesc.FillMode = FILL_MODE_SOLID; RasterizerDesc.CullMode = CULL_MODE_NONE; RasterizerDesc.FrontCounterClockwise = True; RasterizerDesc.ScissorEnable = True; RasterizerDesc.AntialiasedLineEnable = False;
تهيئة وصف تخطيط الإدخال InputLayoutDesc
:
// تحديد تخطيط الإدخالInputLayoutDesc& Layout = PSOCreateInfo.GraphicsPipeline.InputLayout; LayoutElement LayoutElems[] = {LayoutElement( 0, 0, 3, VT_FLOAT32, False ),LayoutElement( 1, 0, 4, VT_UINT8, True ),LayoutElement( 2, 0, 2, VT_FLOAT32, False ), }; Layout.LayoutElements = LayoutElems; Layout.NumElements = _countof(LayoutElems);
تحديد الهيكل البدائي وتعيين مؤشرات التظليل:
// تحديد التظليل والطوبولوجيا البدائيةPSOCreateInfo.GraphicsPipeline.PrimitiveTopology = PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; PSOCreateInfo.pVS = m_pVS; PSOCreateInfo.pPS = m_pPS;
يقوم تخطيط موارد خط الأنابيب بإعلام المحرك بكيفية استخدام التطبيق لمتغيرات موارد التظليل المختلفة. للسماح بتجميع الموارد بناءً على التكرار المتوقع لتغييرات روابط الموارد، يقدم Diligent Engine تصنيفًا لمتغيرات التظليل:
المتغيرات الثابتة ( SHADER_RESOURCE_VARIABLE_TYPE_STATIC
) هي متغيرات من المتوقع تعيينها مرة واحدة فقط. ولا يجوز تغييرها بمجرد ربط المورد بالمتغير. تهدف هذه المتغيرات إلى الاحتفاظ بالثوابت العالمية مثل سمات الكاميرا أو المخازن المؤقتة الثابتة لسمات الضوء العالمية. لاحظ أن ربط المورد هو الذي لا يجوز تغييره، في حين يُسمح بتغيير محتويات المورد وفقًا لاستخدامه.
تحدد المتغيرات القابلة للتغيير ( SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE
) الموارد التي من المتوقع أن تتغير على تردد كل مادة. قد تتضمن الأمثلة مواد منتشرة وخرائط عادية وما إلى ذلك. مرة أخرى، تكون تحديثات محتويات المورد متعامدة مع تغييرات الربط.
من المتوقع أن تتغير المتغيرات الديناميكية ( SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC
) بشكل متكرر وعشوائي.
لتحديد أنواع المتغيرات، قم بإعداد مصفوفة من بنيات ShaderResourceVariableDesc
وتهيئة أعضاء PSODesc.ResourceLayout.Variables
و PSODesc.ResourceLayout.NumVariables
. كما يمكن استخدام PSODesc.ResourceLayout.DefaultVariableType
لتعيين النوع الذي سيتم استخدامه إذا لم يتم توفير اسم متغير.
ShaderResourceVariableDesc ShaderVars[] = { {SHADER_TYPE_PIXEL، "g_StaticTexture"، SHADER_RESOURCE_VARIABLE_TYPE_STATIC}، {SHADER_TYPE_PIXEL، "g_MutableTexture"، SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE}، {SHADER_TYPE_PIXEL، "g_DynamicTexture"، SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC} }; PSODesc.ResourceLayout.Variables = ShaderVars; PSODesc.ResourceLayout.NumVariables = _countof(ShaderVars); PSODesc.ResourceLayout.DefaultVariableType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC;
عند إنشاء حالة خط الأنابيب، يمكن تعيين الأنسجة بشكل دائم لعينات غير قابلة للتغيير. إذا تم تعيين أداة أخذ عينات غير قابلة للتغيير إلى مادة ما، فسيتم استخدامها دائمًا بدلاً من تلك التي تمت تهيئتها في عرض مورد تظليل النسيج. لتعريف أجهزة أخذ العينات غير القابلة للتغيير، قم بإعداد مصفوفة من بنيات ImmutableSamplerDesc
وتهيئة أعضاء PSODesc.ResourceLayout.ImmutableSamplers
و PSODesc.ResourceLayout.NumImmutableSamplers
. لاحظ أنه يمكن تعيين أجهزة أخذ العينات غير القابلة للتغيير إلى متغير نسيج من أي نوع، وليس بالضرورة ثابتًا، بحيث يمكن تغيير ربط النسيج في وقت التشغيل، بينما يظل جهاز أخذ العينات غير قابل للتغيير. يوصى بشدة باستخدام أجهزة أخذ العينات غير القابلة للتغيير كلما أمكن ذلك.
ImmutableSamplerDesc ImtblSampler; ImtblSampler.ShaderStages = SHADER_TYPE_PIXEL; ImtblSampler.Desc.MinFilter = FILTER_TYPE_LINEAR; ImtblSampler.Desc.MagFilter = FILTER_TYPE_LINEAR; ImtblSampler.Desc.MipFilter = FILTER_TYPE_LINEAR; ImtblSampler.TextureName = "g_MutableTexture"; PSODesc.ResourceLayout.NumImmutableSamplers = 1; PSODesc.ResourceLayout.ImmutableSamplers = &ImtblSampler;
يوفر هذا المستند معلومات مفصلة حول العمل مع عينات النسيج.
عندما يتم تعيين كافة الحقول المطلوبة لبنية وصف PSO، اتصل بـ IRenderDevice::CreateGraphicsPipelineState()
لإنشاء كائن PSO:
m_pDevice->CreateGraphicsPipelineState(PSOCreateInfo, &m_pPSO);
كما ذكرنا سابقًا، يعتمد ربط موارد التظليل في Diligent Engine على تجميع المتغيرات في 3 مجموعات مختلفة (ثابتة وقابلة للتغيير وديناميكية). المتغيرات الثابتة هي متغيرات من المتوقع تعيينها مرة واحدة فقط. ولا يجوز تغييرها بمجرد ربط المورد بالمتغير. تهدف هذه المتغيرات إلى الاحتفاظ بالثوابت العالمية مثل سمات الكاميرا أو المخازن المؤقتة الثابتة لسمات الضوء العالمية. وهي مرتبطة مباشرة بكائن حالة خط الأنابيب:
m_pPSO->GetStaticShaderVariable(SHADER_TYPE_PIXEL, "g_tex2DShadowMap")->Set(pShadowMapSRV);
يتم ربط المتغيرات القابلة للتغيير والديناميكية عبر كائن جديد يسمى Shader Resource Binding (SRB)، والذي يتم إنشاؤه بواسطة حالة خط الأنابيب ( IPipelineState::CreateShaderResourceBinding()
)، أو توقيع مورد خط الأنابيب في حالات الاستخدام المتقدمة:
m_pPSO->CreateShaderResourceBinding(&m_pSRB, true);
تخبر المعلمة الثانية النظام بتهيئة الهياكل الداخلية في كائن SRB الذي يشير إلى المتغيرات الثابتة في PSO.
يتم بعد ذلك ربط الموارد الديناميكية والقابلة للتغيير من خلال كائن SRB:
m_pSRB->GetVariable(SHADER_TYPE_PIXEL, "tex2DDiffuse")->Set(pDiffuseTexSRV); m_pSRB->GetVariable(SHADER_TYPE_VERTEX, "cbRandomAttribs")->Set(pRandomAttrsCB);
الفرق بين الموارد القابلة للتغيير والديناميكية هو أنه لا يمكن تعيين الموارد القابلة للتغيير إلا مرة واحدة لكل مثيل لربط مورد التظليل. يمكن تعيين الموارد الديناميكية عدة مرات. من المهم ضبط نوع المتغير بشكل صحيح لأن ذلك يؤثر على الأداء. تعد المتغيرات الثابتة والمتغيرة أكثر كفاءة. تعد المتغيرات الديناميكية أكثر تكلفة وتتسبب في بعض النفقات العامة في وقت التشغيل.
هناك طريقة بديلة لربط موارد التظليل وهي إنشاء واجهة IResourceMapping
التي تقوم بتعيين الأسماء الحرفية للموارد إلى الموارد الفعلية:
إدخالات ResourceMappingEntry[] = { {"g_Texture"، pTexture->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE)} }; ResourceMappingCreateInfo ResMappingCI; ResMappingCI.pEntries = Entries; ResMappingCI.NumEntries = _countof(Entries); RefCntAutoPtr<IResourceMapping> pResMapping; pRenderDevice->CreateResourceMapping(ResMappingCI, &pResMapping);
يمكن بعد ذلك استخدام تعيين الموارد لربط جميع الموارد الثابتة في حالة خط الأنابيب ( IPipelineState::BindStaticResources()
):
m_pPSO->BindStaticResources(SHADER_TYPE_VERTEX | SHADER_TYPE_PIXEL, pResMapping, BIND_SHADER_RESOURCES_VERIFY_ALL_RESOLVED)؛
أو جميع الموارد القابلة للتغيير والديناميكية في رابط مورد التظليل ( IShaderResourceBinding::BindResources()
):
m_pSRB->BindResources(SHADER_TYPE_VERTEX | SHADER_TYPE_PIXEL, pResMapping, BIND_SHADER_RESOURCES_VERIFY_ALL_RESOLVED)؛
تحدد المعلمة الأخيرة لجميع وظائف BindResources()
كيفية حل الموارد:
BIND_SHADER_RESOURCES_UPDATE_STATIC
- يشير إلى أنه سيتم تحديث روابط المتغيرات الثابتة.
BIND_SHADER_RESOURCES_UPDATE_MUTABLE
- يشير إلى أنه سيتم تحديث الارتباطات المتغيرة القابلة للتغيير.
BIND_SHADER_RESOURCES_UPDATE_DYNAMIC
- يشير إلى أنه سيتم تحديث الارتباطات المتغيرة الديناميكية.
BIND_SHADER_RESOURCES_UPDATE_ALL
- يشير إلى أنه سيتم تحديث جميع أنواع المتغيرات (الثابتة والقابلة للتغيير والديناميكية). لاحظ أنه إذا لم يتم تعيين أي من علامات BIND_SHADER_RESOURCES_UPDATE_STATIC
و BIND_SHADER_RESOURCES_UPDATE_MUTABLE
و BIND_SHADER_RESOURCES_UPDATE_DYNAMIC
، فسيتم تحديث جميع أنواع المتغيرات كما لو تم تحديد BIND_SHADER_RESOURCES_UPDATE_ALL
.
BIND_SHADER_RESOURCES_KEEP_EXISTING
- إذا تم تحديد هذه العلامة، فسيتم تحديث الارتباطات التي لم يتم حلها فقط. ستحتفظ جميع الارتباطات الموجودة بقيمها الأصلية. إذا لم يتم تحديد هذه العلامة، فسيتم تحديث كل متغير تظليل إذا كان التعيين يحتوي على المورد المقابل.
BIND_SHADER_RESOURCES_VERIFY_ALL_RESOLVED
- إذا تم تحديد هذه العلامة، فمن المتوقع أن يتم حل جميع روابط التظليل بعد الاستدعاء. إذا لم يكن الأمر كذلك، سيتم الإبلاغ عن خطأ.
قد يتم استدعاء BindResources()
عدة مرات باستخدام تعيينات موارد مختلفة لربط الموارد. ومع ذلك، يوصى باستخدام تعيين مورد واحد كبير لأن حجم التعيين لا يؤثر على وقت البحث عن العنصر.
يقوم المحرك بإجراء فحوصات وقت التشغيل للتحقق من ربط الموارد الصحيحة. على سبيل المثال، إذا حاولت ربط مخزن مؤقت ثابت بمتغير عرض مورد التظليل، فسيتم إخراج خطأ إلى وحدة تحكم التصحيح.
قبل أن يتم استدعاء أي أمر رسم، يجب أن تكون جميع مخازن الرأس والفهرس المؤقتة المطلوبة بالإضافة إلى حالة خط الأنابيب مرتبطة بسياق الجهاز:
// تعيين أهداف العرض قبل إصدار أي رسم Command.auto* pRTV = m_pSwapChain->GetCurrentBackBufferRTV();auto* pDSV = m_pSwapChain->GetDepthBufferDSV(); m_pContext->SetRenderTargets(1, &pRTV, pDSV, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);// مسح هدف العرض وعمق الاستنسلconst float Zero[4] = {0, 0, 0, 0}; m_pContext->ClearRenderTarget(pRTV, ClearColor, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); m_pContext->ClearDepthStencil(pDSV, CLEAR_DEPTH_FLAG, 1.f, 0, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);// تعيين المخازن المؤقتة للقمة والفهرسIBuffer* buffer[] = {m_pVertexBuffer}; إزاحة Uint32[] = {0}; m_pContext->SetVertexBuffers(0, 1, المخزن المؤقت, الإزاحات, SET_VERTEX_BUFFERS_FLAG_RESET, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); m_pContext->SetIndexBuffer(m_pIndexBuffer, 0, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); m_pContext->SetPipelineState(m_pPSO);
كافة الأساليب التي قد تحتاج إلى تنفيذ انتقالات حالة المورد تستخدم تعداد RESOURCE_STATE_TRANSITION_MODE
كمعلمة. يحدد التعداد الأوضاع التالية:
RESOURCE_STATE_TRANSITION_MODE_NONE
- عدم إجراء أي انتقالات لحالة المورد.
RESOURCE_STATE_TRANSITION_MODE_TRANSITION
- نقل الموارد إلى الحالات المطلوبة بواسطة الأمر.
RESOURCE_STATE_TRANSITION_MODE_VERIFY
- لا تقم بالانتقال، ولكن تأكد من صحة الحالات.
الخطوة الأخيرة هي تخصيص موارد التظليل لسياق الجهاز. يتم تحقيق ذلك عن طريق الأسلوب IDeviceContext::CommitShaderResources()
:
m_pContext->CommitShaderResources(m_pSRB, COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES);
إذا لم يتم استدعاء الطريقة، فسيكتشف المحرك أن الموارد غير ملتزم بها ويخرج رسالة تصحيح. لاحظ أن المعلمة الأخيرة تخبر النظام بنقل الموارد إلى الحالات الصحيحة. إذا لم يتم تحديد هذه العلامة، فيجب نقل الموارد بشكل صريح إلى الحالات المطلوبة عن طريق استدعاء IDeviceContext::TransitionShaderResources()
:
m_pContext->TransitionShaderResources(m_pPSO, m_pSRB);
لاحظ أن الطريقة تتطلب مؤشرًا لحالة خط الأنابيب التي أنشأت ربط مورد التظليل.
عندما تكون كافة الحالات والموارد المطلوبة مرتبطة، يمكن استخدام IDeviceContext::DrawIndexed()
لتنفيذ أمر رسم أو يمكن استخدام IDeviceContext::DispatchCompute()
لتنفيذ أمر حساب. لاحظ أنه بالنسبة لأمر الرسم، يجب أن يكون خط أنابيب الرسومات مرتبطًا، وبالنسبة لأمر الإرسال، يجب أن يكون خط أنابيب الحساب مرتبطًا. يأخذ DrawIndexed()
بنية DrawIndexedAttribs
كوسيطة، على سبيل المثال:
DrawIndexedAttribs attrs; attrs.IndexType = VT_UINT16; attrs.NumIndices = 36; attrs.Flags = DRAW_FLAG_VERIFY_STATES; pContext->DrawIndexed(attrs);
تقوم علامة DRAW_FLAG_VERIFY_STATES
بتوجيه المحرك للتحقق من أن مخازن الرأس والفهرس المؤقتة المستخدمة بواسطة أمر الرسم قد تم نقلها إلى الحالات المناسبة.
يستخدم DispatchCompute()
بنية DispatchComputeAttribs
التي تحدد أبعاد شبكة الحساب:
m_pContext->SetPipelineState(m_pComputePSO); m_pContext->CommitShaderResources(m_pComputeSRB, COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES); DispatchComputeAttribs DispatchAttrs{64, 64, 8}; m_pContext->DispatchCompute(DispatchAttr);
يمكنك معرفة المزيد حول واجهة برمجة تطبيقات المحرك من خلال دراسة العينات والبرامج التعليمية.
يدعم Diligent Engine على نطاق واسع إمكانية التشغيل التفاعلي مع واجهات برمجة التطبيقات الأساسية ذات المستوى المنخفض. يمكن تهيئة المحرك من خلال ربطه بجهاز D3D11/D3D12 أو سياق OpenGL/GLES الموجود ويوفر الوصول إلى كائنات API الأصلية الأساسية. راجع الصفحات التالية لمزيد من المعلومات:
إمكانية التشغيل البيني Direct3D11
إمكانية التشغيل البيني Direct3D12
إمكانية التشغيل البيني لبرنامج OpenGL/GLES
قابلية التشغيل البيني فولكان
اتبع الخطوات التالية لإنشاء حزمة NuGet:
قم بتثبيت حزم بايثون المطلوبة
python -m pip install -r ./BuildTools/.NET/requirements.txt
قم بتشغيل البرنامج النصي لبناء حزمة NuGet، على سبيل المثال:
python ./BuildTools/.NET/dotnet-build-package.py -c Debug -d ./
دعوى | وصف | مطلوب |
---|---|---|
-c ( configuration ) | تقوم المكتبات الديناميكية الأصلية بإنشاء التكوين (مثل التصحيح والإصدار وما إلى ذلك) | نعم |
-d ( root-dir ) | المسار إلى الدليل الجذر لـ DiligentCore | نعم |
-s ( settings ) | المسار إلى ملف الإعدادات | لا |
dotnet-tests | علامة تشير إلى ما إذا كان سيتم تشغيل اختبارات .NET أم لا | لا |
dotnet-publish | علامة تشير إلى ما إذا كان سيتم نشر الحزمة إلى NuGet Gallery أم لا | لا |
free-memory | استخدم هذه الوسيطة إذا واجهت ذاكرة غير كافية أثناء عملية الإنشاء | لا |
يمكنك تجاوز الإعدادات الافتراضية باستخدام ملف الإعدادات (راجع قاموس default_settings
في dotnet-build-package.py
)
راجع ترخيص أباتشي 2.0.
يحتوي هذا المشروع على بعض تبعيات الطرف الثالث، والتي قد يكون لكل منها ترخيص مستقل:
Vulkan-Headers: ملفات Vulkan Header وسجل API (ترخيص Apache 2.0).
SPIRV-Cross: أدوات تحليل SPIRV والتجميع المتبادل (ترخيص Apache 2.0).
رؤوس SPIRV: ملفات رأس SPIRV (ترخيص يشبه Khronos MIT).
أدوات SPIRV: أدوات تحسين SPIRV والتحقق من صحتها (ترخيص Apache 2.0).
glslang: مترجم ومدقق مرجعي لـ Khronos لـ GLSL وESSL وHLSL (ترخيص BSD ثلاثي البنود، ترخيص BSD ثنائي البند، MIT، ترخيص Apache 2.0).
توهج: مكتبة OpenGL Extension Wrangler (مكتبة رسومات Mesa ثلاثية الأبعاد، ترخيص Khronos MIT).
volk: محمل Meta لـ Vulkan API (ترخيص Arseny Kapoulkine المشابه لمعهد ماساتشوستس للتكنولوجيا).
stb: مكتبات المجال العام ذات الملف الفردي stb لـ C/C++ (ترخيص MIT أو المجال العام).
googletest: Google Testing and Mocking Framework (رخصة BSD المكونة من 3 فقرات "جديدة" أو "مراجعة").
DirectXShaderCompiler: مترجم DirectX Shader القائم على LLVM/Clang (ترخيص إصدار LLVM).
DXBCChecksum: خوارزمية حساب المجموع الاختباري DXBC بواسطة فريق أدوات مطور AMD (MIT lincesne).
xxHash: خوارزمية تجزئة غير مشفرة سريعة للغاية (ترخيص BSD مكون من فقرتين).
للمساهمة بالكود الخاص بك، أرسل طلب سحب إلى هذا المستودع. يتم توزيع Diligent Engine بموجب ترخيص Apache 2.0 الذي يضمن خلو المحتوى الموجود في مستودع DiligentCore من أعباء الملكية الفكرية. عند تقديم أي محتوى إلى هذا المستودع، فإنك تقوم بترخيص هذا المحتوى بموجب نفس الشروط، وتوافق على أن المحتوى خالٍ من أي مطالبات تتعلق بالملكية الفكرية ولديك الحق في ترخيصه بموجب هذه الشروط.
يستخدم Diligent Engine تنسيق clang لضمان اتساق نمط التعليمات البرمجية المصدر في جميع أنحاء قاعدة التعليمات البرمجية. يتم التحقق من صحة التنسيق بواسطة CI لكل طلب التزام وسحب، وسيفشل الإنشاء في حالة العثور على أي مشكلة في تنسيق التعليمات البرمجية. يرجى الرجوع إلى هذه الصفحة للحصول على إرشادات حول كيفية إعداد تنسيق clang والتنسيق التلقائي للتعليمات البرمجية.
انظر تاريخ الإصدار
diligentgraphics.com