Diligent Core는 Diligent Engine의 기반을 이루는 현대적인 크로스 플랫폼 저수준 그래픽 API입니다. 이 모듈은 Direct3D11, Direct3D12, OpenGL, OpenGLES 및 Vulkan 렌더링 백엔드(Metal 구현은 상용 클라이언트에 사용 가능)와 기본 플랫폼별 유틸리티를 구현합니다. 독립형이므로 자체적으로 구축할 수 있습니다. 지원되는 플랫폼 및 기능, 빌드 지침 등에 대한 정보는 기본 저장소를 참조하세요.
플랫폼 | 빌드 상태 |
---|---|
Win32 | |
유니버설 윈도우 | |
리눅스 | |
기계적 인조 인간 | |
맥OS | |
iOS | |
tvOS | |
엠스크립트 |
저장소 복제
API 기본 사항
파이프라인 리소스 레이아웃
Win32
유니버설 Windows 플랫폼
리눅스
맥OS
기계적 인조 인간
iOS
엠스크립트
엔진 파괴
엔진 초기화
리소스 생성
셰이더 만들기
파이프라인 상태 초기화
셰이더 리소스 바인딩
파이프라인 상태 설정 및 그리기 명령 호출
낮은 수준의 API 상호 운용성
NuGet 패키지 빌드 지침
특허
기여
출시 내역
저장소와 모든 하위 모듈을 얻으려면 다음 명령을 사용하십시오.
git clone --recursive https://github.com/DiligentGraphics/DiligentCore.git
모듈을 빌드하려면 마스터 리포지토리의 빌드 지침을 참조하세요.
엔진에서 제공하는 기능을 사용하려면 먼저 렌더링 장치, 즉각적인 컨텍스트 및 스왑 체인을 만들어야 합니다.
Win32 플랫폼에서는 아래와 같이 OpenGL, Direct3D11, Direct3D12 또는 Vulkan 장치를 생성할 수 있습니다.
void 초기화DiligentEngine(HWND NativeWindowHandle) { SwapChainDesc SCDesc;// RefCntAutoPtr<IRenderDevice> m_pDevice;// RefCntAutoPtr<IDeviceContext> m_pImmediateContext;// RefCntAutoPtr<ISwapChain> m_pSwapChain;스위치(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 창{hWnd}; pFactoryD3D11->CreateSwapChainD3D11(m_pDevice, m_pImmediateContext, SCDesc, FullScreenModeDesc{}, Window, &m_pSwapChain); }break;case 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 창{hWnd}; pFactoryD3D12->CreateSwapChainD3D12(m_pDevice, m_pImmediateContext, SCDesc, FullScreenModeDesc{}, Window, &m_pSwapChain); }break;case 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); }break;case 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 창{hWnd}; pFactoryVk->CreateSwapChainVk(m_pDevice, m_pImmediateContext, SCDesc, Window, &m_pSwapChain); }break;기본값: std::cerr << "알 수 없는 장치 유형"; } }
Windows에서는 엔진을 애플리케이션에 정적으로 연결하거나 별도의 DLL로 빌드할 수 있습니다. 첫 번째 경우에는 팩토리 함수 GetEngineFactoryOpenGL()
, GetEngineFactoryD3D11()
, GetEngineFactoryD3D12()
및 GetEngineFactoryVk()
직접 호출할 수 있습니다. 두 번째 경우에는 LoadGraphicsEngineOpenGL()
, LoadGraphicsEngineD3D11()
, LoadGraphicsEngineD3D12()
또는 LoadGraphicsEngineVk()
함수를 사용하여 프로세스의 주소 공간에 DLL을 로드해야 합니다. 각 함수는 적절한 동적 라이브러리를 로드하고 엔진을 초기화하는 데 필요한 함수를 가져옵니다. 다음 헤더를 포함해야 합니다.
#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
네임스페이스 활성화:
네임스페이스 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 백엔드를 지원합니다. Linux에서 GL 컨텍스트 초기화는 창 생성과 밀접하게 결합되어 있습니다. 결과적으로 Diligent Engine은 컨텍스트를 초기화하지 않고 앱에서 초기화한 컨텍스트에 연결합니다. Linux에서 엔진 초기화의 예는 Tutorial00_HelloLinux.cpp에서 찾을 수 있습니다.
MacOS에서 Diligent Engine은 OpenGL, Vulkan 및 Metal 백엔드를 지원합니다. MacOS에서 GL 컨텍스트의 초기화는 애플리케이션에 의해 수행되며 엔진은 앱에서 생성된 컨텍스트에 연결됩니다. 자세한 내용은 GLView.mm을 참조하세요. Vulkan 백엔드는 다른 플랫폼과 유사하게 초기화됩니다. MetalView.mm을 참조하세요.
Android에서는 OpenGLES 또는 Vulkan 장치를 만들 수 있습니다. 다음 코드 조각은 예를 보여줍니다.
자동* 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 백엔드를 지원합니다. iOS에서 GL 컨텍스트 초기화는 애플리케이션에 의해 수행되며, 엔진은 앱에 의해 초기화된 컨텍스트에 연결됩니다. 자세한 내용은 EAGLView.mm을 참조하세요.
Emscripten에서는 OpenGLES 장치를 생성할 수 있습니다. 다음 코드 조각은 예를 보여줍니다.
//캔버스의 ID를 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 = "내 텍스처 2D"; 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 = "샘플 2D 텍스처"; m_pRenderDevice->CreateTexture(TexDesc, nullptr, &m_pTestTex);
모든 유형의 텍스처를 생성할 수 있는 CreateTexture()
함수는 단 하나뿐입니다. 유형, 형식, 배열 크기 및 기타 모든 매개변수는 TextureDesc
구조의 멤버에 의해 지정됩니다.
텍스처 생성 시간 동안 지정된 모든 바인드 플래그에 대해 텍스처 객체는 기본 뷰를 생성합니다. 기본 셰이더 리소스 보기는 전체 텍스처를 다루고, 기본 렌더링 대상 및 깊이 스텐실 보기는 가장 상세한 밉 수준의 모든 배열 조각을 참조하며, 순서가 지정되지 않은 액세스 보기는 전체 텍스처를 참조합니다. 텍스처에서 기본 보기를 얻으려면 ITexture::GetDefaultView()
함수를 사용하세요. 이 함수는 반환된 인터페이스의 참조 카운터를 증가시키지 않습니다. ITexture::CreateView()
사용하여 추가 텍스처 뷰를 만들 수 있습니다. IBuffer::CreateView()
사용하여 버퍼의 추가 뷰를 만듭니다.
셰이더를 생성하려면 ShaderCreateInfo
구조를 채웁니다.
ShaderCreateInfo ShaderCI;
셰이더를 만드는 방법에는 세 가지가 있습니다. 첫 번째 방법은 ShaderCreateInfo::Source
멤버를 통해 셰이더 소스 코드에 대한 포인터를 제공하는 것입니다. 두 번째 방법은 파일 이름을 제공하는 것입니다. 세 번째 방법은 ShaderCreateInfo::ByteCode
멤버를 통해 컴파일된 바이트 코드에 대한 포인터를 제공하는 것입니다. 그래픽 엔진은 플랫폼에서 완전히 분리됩니다. 호스트 파일 시스템은 플랫폼에 따라 다르므로 구조는 엔진에 파일 시스템에 대한 액세스 권한을 부여하기 위한 ShaderCreateInfo::pShaderSourceStreamFactory
멤버를 노출합니다. 소스 파일 이름을 제공한 경우 셰이더 소스 스트림 팩토리에 대한 null이 아닌 포인터도 제공해야 합니다. 셰이더 소스에 #include
지시문이 포함되어 있으면 소스 스트림 팩토리도 이러한 파일을 로드하는 데 사용됩니다. 엔진은 지원되는 모든 플랫폼에 대해 대부분의 경우 충분할 기본 구현을 제공합니다. 그러나 자신만의 구현을 정의할 수 있습니다.
중요한 멤버는 ShaderCreateInfo::SourceLanguage
입니다. 다음은 이 멤버에 대한 유효한 값입니다.
SHADER_SOURCE_LANGUAGE_DEFAULT
- 셰이더 소스 형식은 기본 그래픽 API(D3D11 또는 D3D12 모드의 경우 HLSL, OpenGL, OpenGLES 및 Vulkan 모드의 경우 GLSL)와 일치합니다.
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
- 소스 언어는 Metal Shading Language입니다.
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 Engine은 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
를 초기화합니다. 생성자는 기본값으로 멤버를 초기화하며 기본값과 다른 멤버만 설정할 수 있습니다.
// 깊이 스텐실 초기화 stateDepthStencilStateDesc& DepthStencilDesc = PSOCreateInfo.GraphicsPipeline.DepthStencilDesc; DepthStencilDesc.DepthEnable = true; DepthStencilDesc.DepthWriteEnable = true;
혼합 상태 설명 초기화 BlendStateDesc
:
// 블렌드 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
:
// 래스터라이저 초기화 stateRasterizerStateDesc& 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);
변경 가능한 동적 변수는 파이프라인 상태( IPipelineState::CreateShaderResourceBinding()
) 또는 고급 사용 사례의 파이프라인 리소스 서명에 의해 생성되는 SRB(셰이더 리소스 바인딩)라는 새 개체를 통해 바인딩됩니다.
m_pPSO->CreateShaderResourceBinding(&m_pSRB, true);
두 번째 매개변수는 PSO의 정적 변수를 참조하는 SRB 개체의 내부 구조를 초기화하도록 시스템에 지시합니다.
그러면 동적 및 변경 가능한 리소스가 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 = 항목; ResMappingCI.NumEntries = _countof(항목); 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()
리소스를 바인딩하기 위해 다양한 리소스 매핑을 사용하여 여러 번 호출될 수 있습니다. 그러나 매핑의 크기는 요소 검색 시간에 영향을 미치지 않으므로 하나의 큰 리소스 매핑을 사용하는 것이 좋습니다.
엔진은 런타임 검사를 수행하여 올바른 리소스가 바인딩되고 있는지 확인합니다. 예를 들어 상수 버퍼를 셰이더 리소스 뷰 변수에 바인딩하려고 하면 디버그 콘솔에 오류가 출력됩니다.
그리기 명령을 호출하기 전에 필요한 모든 정점 및 인덱스 버퍼와 파이프라인 상태를 장치 컨텍스트에 바인딩해야 합니다.
// 그리기 명령을 실행하기 전에 렌더 대상을 설정합니다.auto* pRTV = m_pSwapChain->GetCurrentBackBufferRTV();auto* pDSV = m_pSwapChain->GetDepthBufferDSV(); m_pContext->SetRenderTargets(1, &pRTV, pDSV, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);// 렌더링 대상 및 깊이 스텐실 상수 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.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(DispatchAttrs);
샘플과 튜토리얼을 통해 엔진 API에 대해 자세히 알아볼 수 있습니다.
Diligent Engine은 기본 하위 수준 API와의 상호 운용성을 광범위하게 지원합니다. 엔진은 기존 D3D11/D3D12 장치 또는 OpenGL/GLES 컨텍스트에 연결하여 초기화할 수 있으며 기본 네이티브 API 개체에 대한 액세스를 제공합니다. 자세한 내용은 다음 페이지를 참조하세요.
Direct3D11 상호 운용성
Direct3D12 상호 운용성
OpenGL/GLES 상호 운용성
Vulkan 상호 운용성
NuGet 패키지를 빌드하려면 다음 단계를 따르세요.
필수 Python 패키지 설치
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 갤러리에 패키지를 게시할지 여부를 나타내는 플래그 | 아니요 |
free-memory | 빌드 프로세스 중에 메모리가 부족하면 이 인수를 사용하십시오. | 아니요 |
설정 파일을 사용하여 기본 설정을 재정의할 수 있습니다( dotnet-build-package.py
에서 default_settings
사전 확인).
Apache 2.0 라이센스를 참조하십시오.
이 프로젝트에는 일부 타사 종속성이 있으며 각 종속성은 독립적인 라이선스를 가질 수 있습니다.
Vulkan 헤더: Vulkan 헤더 파일 및 API 레지스트리(Apache License 2.0).
SPIRV-Cross: SPIRV 구문 분석 및 크로스 컴파일 도구(Apache License 2.0).
SPIRV-헤더: SPIRV 헤더 파일(Khronos MIT와 유사한 라이센스).
SPIRV-도구: SPIRV 최적화 및 검증 도구(Apache License 2.0).
glslang: GLSL, ESSL 및 HLSL(3절 BSD 라이센스, 2절 BSD 라이센스, MIT, Apache 라이센스 2.0)에 대한 Khronos 참조 컴파일러 및 유효성 검사기.
glew: OpenGL Extension Wrangler Library(Mesa 3-D 그래픽 라이브러리, Khronos MIT와 유사한 라이센스).
volk: Vulkan API용 메타 로더(Arseny Kapoulkine MIT와 유사한 라이센스).
stb: C/C++용 stb 단일 파일 공개 도메인 라이브러리(MIT 라이센스 또는 공개 도메인).
googletest: Google 테스트 및 모의 프레임워크(BSD 3절 "신규" 또는 "개정" 라이센스).
DirectXShaderCompiler: LLVM/Clang 기반 DirectX 셰이더 컴파일러(LLVM 릴리스 라이선스).
DXBCChecksum: AMD 개발자 도구 팀(MIT lincesne)의 DXBC 체크섬 계산 알고리즘입니다.
xxHash: 매우 빠른 비암호화 해시 알고리즘(2-Clause BSD 라이센스).
코드를 제공하려면 이 저장소에 Pull Request를 제출하세요. Diligent Engine은 DiligentCore 저장소의 콘텐츠에 지적 재산권 침해가 없음을 보장하는 Apache 2.0 라이선스에 따라 배포됩니다. 이 저장소에 콘텐츠를 제출하면 귀하는 동일한 조건에 따라 해당 콘텐츠에 대한 라이선스를 부여받게 되며 해당 콘텐츠에는 지적 재산권 주장이 없으며 해당 조건에 따라 라이선스를 부여할 권리가 있다는 데 동의합니다.
Diligent Engine은 clang-format을 사용하여 코드 베이스 전체에서 일관된 소스 코드 스타일을 보장합니다. 형식은 각 커밋 및 끌어오기 요청에 대해 CI로 검증되며, 코드 형식 문제가 발견되면 빌드가 실패합니다. clang-format 및 자동 코드 형식 지정 방법에 대한 지침은 이 페이지를 참조하세요.
출시 내역 보기
diligentgraphics.com