Forráskód Böngészése

feat: 添加编译着色器

nicetry12138 1 éve
szülő
commit
c6b48990d8
1 módosított fájl, 65 hozzáadás és 9 törlés
  1. 65 9
      图形学/DirectX学习/README.md

+ 65 - 9
图形学/DirectX学习/README.md

@@ -1716,15 +1716,71 @@ Direct3D 中,着色器程序必须先被**编译为**一种可移植的**字
 
 ```cpp
 HRESULT D3DCompileFromFile(
-  [in]            LPCWSTR                pFileName,
-  [in, optional]  const D3D_SHADER_MACRO *pDefines,
-  [in, optional]  ID3DInclude            *pInclude,
-  [in]            LPCSTR                 pEntrypoint,
-  [in]            LPCSTR                 pTarget,
-  [in]            UINT                   Flags1,
-  [in]            UINT                   Flags2,
-  [out]           ID3DBlob               **ppCode,
-  [out, optional] ID3DBlob               **ppErrorMsgs
+  [in]            LPCWSTR                pFileName,		// 希望编译的以 .hlsl 作为扩展名的 HLSL 源码文件
+  [in, optional]  const D3D_SHADER_MACRO *pDefines,		// 高级选项,不使用时填写 nullptr
+  [in, optional]  ID3DInclude            *pInclude,		// 高级选项,不使用时填写 nullptr
+  [in]            LPCSTR                 pEntrypoint,	// 着色器函数的入口点函数名
+  [in]            LPCSTR                 pTarget,		// 指定着色器类型和版本
+  [in]            UINT                   Flags1,		// 如何编译的标志
+  [in]            UINT                   Flags2,		// 高级编译选项
+  [out]           ID3DBlob               **ppCode,		// 指向 ID3DBlob 数据结构的指针,存储编译好的字节码
+  [out, optional] ID3DBlob               **ppErrorMsgs	// 指向 ID3DBlob 数据结构的指针,如果发生错误会存储报错的字符串
 );
 ```
 
+`ID3DBlob` 就是一段普通的字符串,通过 `GetBufferPointer` 可以获得 `void*` 类型的指针,需要自己手动转换;通过 `GetBufferSize` 可以获得缓冲区的字节大小
+
+```cpp
+ComPtr<ID3DBlob> d3dUtil::CompileShader(const std::wstring& filename, const D3D_SHADER_MACRO* defines, const std::string& entrypoint, const std::string& target)
+{
+	UINT compileFlags = 0;
+#if defined(DEBUG) || defined(_DEBUG)  
+	compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
+#endif
+
+	HRESULT hr = S_OK;
+
+	ComPtr<ID3DBlob> byteCode = nullptr;
+	ComPtr<ID3DBlob> errors;
+	hr = D3DCompileFromFile(filename.c_str(), defines, D3D_COMPILE_STANDARD_FILE_INCLUDE, entrypoint.c_str(), target.c_str(), compileFlags, 0, &byteCode, &errors);
+
+	if(errors != nullptr) {
+		OutputDebugStringA((char*)errors->GetBufferPointer());
+	}
+
+	ThrowIfFailed(hr);
+
+	return byteCode;
+}
+```
+
+除了运行时编译着色器,还能够以单独的步骤离线的编译着色器
+
+1. 复杂的着色器编译时间长,离线编译可以缩短程序加载时间
+2. 提前编译可以提前发现错误
+
+通常用 `.cso` (`compiled shader object`) 作为以编译着色器的扩展名
+
+可以使用 `DirectX` 自带的 `FXC` 命令行编译工具来离线的编译着色器
+
+在程序运行时,可以通过标准文件输入机制来将 `cso` 中编译好的字节码加载到应用程序中
+
+```cpp
+ComPtr<ID3DBlob> d3dUtil::LoadBinary(const std::wstring& filename)
+{
+    std::ifstream fin(filename, std::ios::binary);
+
+    fin.seekg(0, std::ios_base::end);
+    std::ifstream::pos_type size = (int)fin.tellg();
+    fin.seekg(0, std::ios_base::beg);
+
+    ComPtr<ID3DBlob> blob;
+    ThrowIfFailed(D3DCreateBlob(size, blob.GetAddressOf()));
+
+    fin.read((char*)blob->GetBufferPointer(), size);
+    fin.close();
+
+    return blob;
+}
+```
+