dxcapi.impl.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // dxcapi.impl.h //
  4. // Copyright (C) Microsoft Corporation. All rights reserved. //
  5. // This file is distributed under the University of Illinois Open Source //
  6. // License. See LICENSE.TXT for details. //
  7. // //
  8. // Provides support for DXC API implementations. //
  9. // //
  10. ///////////////////////////////////////////////////////////////////////////////
  11. #ifndef __DXCAPI_IMPL__
  12. #define __DXCAPI_IMPL__
  13. #include "dxc/dxcapi.h"
  14. #include "dxc/Support/microcom.h"
  15. #include "llvm/Support/raw_ostream.h"
  16. #include "llvm/ADT/ArrayRef.h"
  17. // Simple adaptor for IStream. Can probably do better.
  18. class raw_stream_ostream : public llvm::raw_ostream {
  19. private:
  20. CComPtr<hlsl::AbstractMemoryStream> m_pStream;
  21. void write_impl(const char *Ptr, size_t Size) override {
  22. ULONG cbWritten;
  23. IFT(m_pStream->Write(Ptr, Size, &cbWritten));
  24. }
  25. uint64_t current_pos() const override { return m_pStream->GetPosition(); }
  26. public:
  27. raw_stream_ostream(hlsl::AbstractMemoryStream* pStream) : m_pStream(pStream) { }
  28. ~raw_stream_ostream() override {
  29. flush();
  30. }
  31. };
  32. namespace {
  33. HRESULT TranslateUtf8StringForOutput(
  34. _In_opt_count_(size) LPCSTR pStr, SIZE_T size, UINT32 codePage, IDxcBlobEncoding **ppBlobEncoding) {
  35. CComPtr<IDxcBlobEncoding> pBlobEncoding;
  36. IFR(hlsl::DxcCreateBlobWithEncodingOnHeapCopy(pStr, size, DXC_CP_UTF8, &pBlobEncoding));
  37. if (codePage == DXC_CP_UTF16) {
  38. CComPtr<IDxcBlobUtf16> pBlobUtf16;
  39. IFT(hlsl::DxcGetBlobAsUtf16(pBlobEncoding, nullptr, &pBlobUtf16))
  40. pBlobEncoding = pBlobUtf16;
  41. }
  42. *ppBlobEncoding = pBlobEncoding.Detach();
  43. return S_OK;
  44. }
  45. HRESULT TranslateUtf16StringForOutput(
  46. _In_opt_count_(size) LPCWSTR pStr, SIZE_T size, UINT32 codePage, IDxcBlobEncoding **ppBlobEncoding) {
  47. CComPtr<IDxcBlobEncoding> pBlobEncoding;
  48. IFR(hlsl::DxcCreateBlobWithEncodingOnHeapCopy(pStr, size, DXC_CP_UTF16, &pBlobEncoding));
  49. if (codePage == DXC_CP_UTF8) {
  50. CComPtr<IDxcBlobUtf8> pBlobUtf8;
  51. IFT(hlsl::DxcGetBlobAsUtf8(pBlobEncoding, nullptr, &pBlobUtf8))
  52. pBlobEncoding = pBlobUtf8;
  53. }
  54. *ppBlobEncoding = pBlobEncoding.Detach();
  55. return S_OK;
  56. }
  57. HRESULT TranslateStringBlobForOutput(IDxcBlob *pBlob, UINT32 codePage, IDxcBlobEncoding **ppBlobEncoding) {
  58. CComPtr<IDxcBlobEncoding> pEncoding;
  59. IFR(pBlob->QueryInterface(&pEncoding));
  60. BOOL known;
  61. UINT32 inputCP;
  62. IFR(pEncoding->GetEncoding(&known, &inputCP));
  63. IFRBOOL(known, E_INVALIDARG);
  64. if (inputCP == DXC_CP_UTF8) {
  65. return TranslateUtf8StringForOutput((LPCSTR)pBlob->GetBufferPointer(), pBlob->GetBufferSize(), codePage, ppBlobEncoding);
  66. } else if (inputCP == DXC_CP_UTF16) {
  67. return TranslateUtf16StringForOutput((LPCWSTR)pBlob->GetBufferPointer(), pBlob->GetBufferSize(), codePage, ppBlobEncoding);
  68. }
  69. return E_INVALIDARG;
  70. }
  71. }
  72. typedef enum DxcOutputType {
  73. DxcOutputType_None = 0,
  74. DxcOutputType_Blob = 1,
  75. DxcOutputType_Text = 2,
  76. DxcOutputTypeForceDword = 0xFFFFFFFF
  77. } DxcOutputType;
  78. inline DxcOutputType DxcGetOutputType(DXC_OUT_KIND kind) {
  79. switch (kind) {
  80. case DXC_OUT_OBJECT:
  81. case DXC_OUT_PDB:
  82. case DXC_OUT_SHADER_HASH:
  83. case DXC_OUT_REFLECTION:
  84. case DXC_OUT_ROOT_SIGNATURE:
  85. return DxcOutputType_Blob;
  86. case DXC_OUT_ERRORS:
  87. case DXC_OUT_DISASSEMBLY:
  88. case DXC_OUT_HLSL:
  89. case DXC_OUT_TEXT:
  90. return DxcOutputType_Text;
  91. }
  92. return DxcOutputType_None;
  93. }
  94. // Update when new results are allowed
  95. static const unsigned kNumDxcOutputTypes = DXC_OUT_ROOT_SIGNATURE;
  96. static const SIZE_T kAutoSize = (SIZE_T)-1;
  97. static const LPCWSTR DxcOutNoName = nullptr;
  98. struct DxcOutputObject {
  99. CComPtr<IUnknown> object;
  100. CComPtr<IDxcBlobUtf16> name;
  101. DXC_OUT_KIND kind = DXC_OUT_NONE;
  102. /////////////////////////
  103. // Convenient set methods
  104. /////////////////////////
  105. HRESULT SetObject(IUnknown *pUnknown, UINT32 codePage = DXC_CP_UTF8) {
  106. DXASSERT_NOMSG(!object);
  107. if (!pUnknown)
  108. return S_OK;
  109. if (codePage && DxcGetOutputType(kind) == DxcOutputType_Text) {
  110. CComPtr<IDxcBlob> pBlob;
  111. IFR(pUnknown->QueryInterface(&pBlob));
  112. CComPtr<IDxcBlobEncoding> pEncoding;
  113. // If not blob encoding, assume utf-8 text
  114. if (FAILED(TranslateStringBlobForOutput(pBlob, codePage, &pEncoding)))
  115. IFR(TranslateUtf8StringForOutput(
  116. (LPCSTR)pBlob->GetBufferPointer(), pBlob->GetBufferSize(),
  117. codePage, &pEncoding));
  118. object = pEncoding;
  119. } else {
  120. object = pUnknown;
  121. }
  122. return S_OK;
  123. }
  124. HRESULT SetObjectData(_In_opt_bytecount_(size) LPCVOID pData, SIZE_T size) {
  125. DXASSERT_NOMSG(!object);
  126. if (!pData || !size)
  127. return S_OK;
  128. IDxcBlob *pBlob;
  129. IFR(hlsl::DxcCreateBlobOnHeapCopy(pData, size, &pBlob));
  130. object = pBlob;
  131. return S_OK;
  132. }
  133. HRESULT SetString(_In_ UINT32 codePage, _In_opt_count_(size) LPCWSTR pText, SIZE_T size = kAutoSize) {
  134. DXASSERT_NOMSG(!object);
  135. if (!pText)
  136. return S_OK;
  137. if (size == kAutoSize)
  138. size = wcslen(pText);
  139. CComPtr<IDxcBlobEncoding> pBlobEncoding;
  140. IFR(TranslateUtf16StringForOutput(pText, size, codePage, &pBlobEncoding));
  141. object = pBlobEncoding;
  142. return S_OK;
  143. }
  144. HRESULT SetString(_In_ UINT32 codePage, _In_opt_count_(size) LPCSTR pText, SIZE_T size = kAutoSize) {
  145. DXASSERT_NOMSG(!object);
  146. if (!pText)
  147. return S_OK;
  148. if (size == kAutoSize)
  149. size = strlen(pText);
  150. CComPtr<IDxcBlobEncoding> pBlobEncoding;
  151. IFR(TranslateUtf8StringForOutput(pText, size, codePage, &pBlobEncoding));
  152. object = pBlobEncoding;
  153. return S_OK;
  154. }
  155. HRESULT SetName(_In_opt_z_ IDxcBlobUtf16 *pName) {
  156. DXASSERT_NOMSG(!name);
  157. name = pName;
  158. return S_OK;
  159. }
  160. HRESULT SetName(_In_opt_z_ LPCWSTR pName) {
  161. DXASSERT_NOMSG(!name);
  162. if (!pName)
  163. return S_OK;
  164. CComPtr<IDxcBlobEncoding> pBlobEncoding;
  165. IFR(hlsl::DxcCreateBlobWithEncodingOnHeapCopy(
  166. pName, (wcslen(pName) + 1) * sizeof(wchar_t), DXC_CP_UTF16, &pBlobEncoding));
  167. return pBlobEncoding->QueryInterface(&name);
  168. }
  169. HRESULT SetName(_In_opt_z_ LPCSTR pName) {
  170. DXASSERT_NOMSG(!name);
  171. if (!pName)
  172. return S_OK;
  173. CComPtr<IDxcBlobEncoding> pBlobEncoding;
  174. IFR(TranslateUtf8StringForOutput(pName, strlen(pName) + 1, DXC_CP_UTF16, &pBlobEncoding));
  175. return pBlobEncoding->QueryInterface(&name);
  176. }
  177. HRESULT SetName(_In_opt_z_ llvm::StringRef Name) {
  178. DXASSERT_NOMSG(!name);
  179. if (Name.empty())
  180. return S_OK;
  181. CComPtr<IDxcBlobEncoding> pBlobEncoding;
  182. IFR(TranslateUtf8StringForOutput(Name.data(), Name.size(), DXC_CP_UTF16, &pBlobEncoding));
  183. return pBlobEncoding->QueryInterface(&name);
  184. }
  185. /////////////////////////////
  186. // Static object constructors
  187. /////////////////////////////
  188. template<typename DataTy, typename NameTy>
  189. static DxcOutputObject StringOutput(_In_ DXC_OUT_KIND kind,
  190. _In_ UINT32 codePage,
  191. _In_opt_count_(size) DataTy pText, _In_ SIZE_T size,
  192. _In_opt_z_ NameTy pName) {
  193. DxcOutputObject output;
  194. output.kind = kind;
  195. IFT(output.SetString(codePage, pText, size));
  196. IFT(output.SetName(pName));
  197. return output;
  198. }
  199. template<typename DataTy, typename NameTy>
  200. static DxcOutputObject StringOutput(_In_ DXC_OUT_KIND kind,
  201. _In_ UINT32 codePage,
  202. _In_opt_ DataTy pText,
  203. _In_opt_z_ NameTy pName) {
  204. return StringOutput(kind, codePage, pText, kAutoSize, pName);
  205. }
  206. template<typename NameTy>
  207. static DxcOutputObject DataOutput(_In_ DXC_OUT_KIND kind,
  208. _In_opt_bytecount_(size) LPCVOID pData, _In_ SIZE_T size,
  209. _In_opt_z_ NameTy pName) {
  210. DxcOutputObject output;
  211. output.kind = kind;
  212. IFT(output.SetObjectData(pData, size));
  213. IFT(output.SetName(pName));
  214. return output;
  215. }
  216. template<typename NameTy>
  217. static DxcOutputObject DataOutput(_In_ DXC_OUT_KIND kind,
  218. _In_opt_ IDxcBlob *pBlob,
  219. _In_opt_z_ NameTy pName) {
  220. DxcOutputObject output;
  221. output.kind = kind;
  222. IFT(output.SetObject(pBlob));
  223. IFT(output.SetName(pName));
  224. return output;
  225. }
  226. static DxcOutputObject DataOutput(_In_ DXC_OUT_KIND kind,
  227. _In_opt_ IDxcBlob *pBlob) {
  228. return DataOutput(kind, pBlob, DxcOutNoName);
  229. }
  230. template<typename NameTy>
  231. static DxcOutputObject DataOutput(_In_ DXC_OUT_KIND kind,
  232. _In_ UINT32 codePage,
  233. _In_opt_ IDxcBlob *pBlob,
  234. _In_opt_z_ NameTy pName) {
  235. DxcOutputObject output;
  236. output.kind = kind;
  237. IFT(output.SetObject(pBlob, codePage));
  238. IFT(output.SetName(pName));
  239. return output;
  240. }
  241. static DxcOutputObject DataOutput(_In_ DXC_OUT_KIND kind,
  242. _In_ UINT32 codePage,
  243. _In_opt_ IDxcBlob *pBlob) {
  244. return DataOutput(kind, codePage, pBlob, DxcOutNoName);
  245. }
  246. template<typename DataTy>
  247. static DxcOutputObject ErrorOutput(UINT32 codePage, DataTy pText, SIZE_T size) {
  248. return StringOutput(DXC_OUT_ERRORS, codePage, pText, size, DxcOutNoName);
  249. }
  250. template<typename DataTy>
  251. static DxcOutputObject ErrorOutput(UINT32 codePage, DataTy pText) {
  252. return StringOutput(DXC_OUT_ERRORS, codePage, pText, DxcOutNoName);
  253. }
  254. template<typename NameTy>
  255. static DxcOutputObject ObjectOutput(LPCVOID pData, SIZE_T size, NameTy pName) {
  256. return DataOutput(DXC_OUT_OBJECT, pData, size, pName);
  257. }
  258. static DxcOutputObject ObjectOutput(LPCVOID pData, SIZE_T size) {
  259. return DataOutput(DXC_OUT_OBJECT, pData, size, DxcOutNoName);
  260. }
  261. };
  262. class DxcResult : public IDxcResult {
  263. private:
  264. DXC_MICROCOM_TM_REF_FIELDS()
  265. HRESULT m_status = S_OK;
  266. DxcOutputObject m_outputs[kNumDxcOutputTypes]; // indexed by DXC_OUT_KIND enum - 1
  267. DXC_OUT_KIND m_resultType = DXC_OUT_NONE; // result type for GetResult()
  268. UINT32 m_textEncoding = DXC_CP_UTF8; // encoding for text outputs
  269. public:
  270. DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL()
  271. DXC_MICROCOM_TM_CTOR(DxcResult)
  272. HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) override {
  273. return DoBasicQueryInterface<IDxcResult, IDxcOperationResult>(this, iid, ppvObject);
  274. }
  275. //////////////////////
  276. // IDxcOperationResult
  277. //////////////////////
  278. HRESULT STDMETHODCALLTYPE GetStatus(_Out_ HRESULT *pStatus) override {
  279. if (pStatus == nullptr)
  280. return E_INVALIDARG;
  281. *pStatus = m_status;
  282. return S_OK;
  283. }
  284. HRESULT STDMETHODCALLTYPE
  285. GetResult(_COM_Outptr_result_maybenull_ IDxcBlob **ppResult) override {
  286. *ppResult = nullptr;
  287. if (m_resultType == DXC_OUT_NONE)
  288. return S_OK;
  289. DxcOutputObject *pObject = Output(m_resultType);
  290. if (pObject && pObject->object)
  291. return pObject->object->QueryInterface(ppResult);
  292. return S_OK;
  293. }
  294. HRESULT STDMETHODCALLTYPE
  295. GetErrorBuffer(_COM_Outptr_result_maybenull_ IDxcBlobEncoding **ppErrors) override {
  296. *ppErrors = nullptr;
  297. DxcOutputObject *pObject = Output(DXC_OUT_ERRORS);
  298. if (pObject && pObject->object)
  299. return pObject->object->QueryInterface(ppErrors);
  300. return S_OK;
  301. }
  302. /////////////
  303. // IDxcResult
  304. /////////////
  305. BOOL STDMETHODCALLTYPE HasOutput(_In_ DXC_OUT_KIND dxcOutKind) override {
  306. if (dxcOutKind <= DXC_OUT_NONE || (unsigned)dxcOutKind > kNumDxcOutputTypes)
  307. return FALSE;
  308. return m_outputs[(unsigned)dxcOutKind - 1].kind != DXC_OUT_NONE;
  309. }
  310. HRESULT STDMETHODCALLTYPE GetOutput(_In_ DXC_OUT_KIND dxcOutKind,
  311. _In_ REFIID iid, _COM_Outptr_opt_result_maybenull_ void **ppvObject,
  312. _COM_Outptr_ IDxcBlobUtf16 **ppOutputName) override {
  313. if (ppvObject == nullptr)
  314. return E_INVALIDARG;
  315. if (dxcOutKind <= DXC_OUT_NONE || (unsigned)dxcOutKind > kNumDxcOutputTypes)
  316. return E_INVALIDARG;
  317. DxcOutputObject &object = m_outputs[(unsigned)dxcOutKind - 1];
  318. if (object.kind == DXC_OUT_NONE)
  319. return E_INVALIDARG;
  320. *ppvObject = nullptr;
  321. if (ppOutputName)
  322. *ppOutputName = nullptr;
  323. IFR(object.object->QueryInterface(iid, ppvObject));
  324. if (ppOutputName && object.name) {
  325. object.name.CopyTo(ppOutputName);
  326. }
  327. return S_OK;
  328. }
  329. UINT32 GetNumOutputs() override {
  330. UINT32 numOutputs = 0;
  331. for (unsigned i = 0; i < kNumDxcOutputTypes; ++i) {
  332. if (m_outputs[i].kind != DXC_OUT_NONE)
  333. numOutputs++;
  334. }
  335. return numOutputs;
  336. }
  337. DXC_OUT_KIND GetOutputByIndex(UINT32 Index) override {
  338. if (!(Index < kNumDxcOutputTypes))
  339. return DXC_OUT_NONE;
  340. UINT32 numOutputs = 0;
  341. unsigned i = 0;
  342. for (; i < kNumDxcOutputTypes; ++i) {
  343. if (Index == numOutputs)
  344. return m_outputs[i].kind;
  345. if (m_outputs[i].kind != DXC_OUT_NONE)
  346. numOutputs++;
  347. }
  348. return DXC_OUT_NONE;
  349. }
  350. DXC_OUT_KIND PrimaryOutput() override {
  351. return m_resultType;
  352. }
  353. /////////////////////
  354. // Internal Interface
  355. /////////////////////
  356. HRESULT SetEncoding(UINT32 textEncoding) {
  357. if (textEncoding != DXC_CP_ACP && textEncoding != DXC_CP_UTF8 && textEncoding != DXC_CP_UTF16)
  358. return E_INVALIDARG;
  359. m_textEncoding = textEncoding;
  360. return S_OK;
  361. }
  362. DxcOutputObject *Output(DXC_OUT_KIND kind) {
  363. if (kind <= DXC_OUT_NONE || (unsigned)kind > kNumDxcOutputTypes)
  364. return nullptr;
  365. return &(m_outputs[(unsigned)kind - 1]);
  366. }
  367. HRESULT ClearOutput(DXC_OUT_KIND kind) {
  368. if (kind <= DXC_OUT_NONE || (unsigned)kind > kNumDxcOutputTypes)
  369. return E_INVALIDARG;
  370. DxcOutputObject &output = m_outputs[(unsigned)kind - 1];
  371. output.kind = DXC_OUT_NONE;
  372. output.object.Release();
  373. output.name.Release();
  374. return S_OK;
  375. }
  376. void ClearAllOutputs() {
  377. for (unsigned i = DXC_OUT_NONE + 1; i <= kNumDxcOutputTypes; i++)
  378. ClearOutput((DXC_OUT_KIND)(i));
  379. }
  380. HRESULT SetStatusAndPrimaryResult(HRESULT status, DXC_OUT_KIND resultType = DXC_OUT_NONE) {
  381. if ((unsigned)resultType > kNumDxcOutputTypes)
  382. return E_INVALIDARG;
  383. m_status = status;
  384. m_resultType = resultType;
  385. return S_OK;
  386. }
  387. // Set output object and name for previously uninitialized entry
  388. HRESULT SetOutput(const DxcOutputObject &output) {
  389. if (output.kind <= DXC_OUT_NONE || (unsigned)output.kind > kNumDxcOutputTypes)
  390. return E_INVALIDARG;
  391. if (!output.object)
  392. return E_INVALIDARG;
  393. DxcOutputObject &internalOutput = m_outputs[(unsigned)output.kind - 1];
  394. // Must not be overwriting an existing output
  395. if (internalOutput.kind != DXC_OUT_NONE)
  396. return E_INVALIDARG;
  397. internalOutput = output;
  398. return S_OK;
  399. }
  400. // Set or overwrite output object and set the kind
  401. HRESULT SetOutputObject(DXC_OUT_KIND kind, IUnknown *pObject) {
  402. if (kind <= DXC_OUT_NONE || (unsigned)kind > kNumDxcOutputTypes)
  403. return E_INVALIDARG;
  404. DxcOutputObject &output = m_outputs[(unsigned)kind - 1];
  405. if (!pObject)
  406. kind = DXC_OUT_NONE;
  407. output.kind = kind;
  408. output.SetObject(pObject, m_textEncoding);
  409. return S_OK;
  410. }
  411. // Set or overwrite output string object and set the kind
  412. template<typename StringTy>
  413. HRESULT SetOutputString(DXC_OUT_KIND kind, StringTy pString, size_t size = kAutoSize) {
  414. if (kind <= DXC_OUT_NONE || (unsigned)kind > kNumDxcOutputTypes)
  415. return E_INVALIDARG;
  416. DxcOutputObject &output = m_outputs[(unsigned)kind - 1];
  417. if (!pString)
  418. kind = DXC_OUT_NONE;
  419. output.kind = kind;
  420. output.SetString(m_textEncoding, pString, size);
  421. return S_OK;
  422. }
  423. // Set or overwrite the output name. This does not set kind,
  424. // since that indicates an active output, which must have an object.
  425. template<typename NameTy>
  426. HRESULT SetOutputName(DXC_OUT_KIND kind, NameTy Name) {
  427. if (kind <= DXC_OUT_NONE || (unsigned)kind > kNumDxcOutputTypes)
  428. return E_INVALIDARG;
  429. Output(kind)->SetName(Name);
  430. return S_OK;
  431. }
  432. HRESULT SetOutputs(const llvm::ArrayRef<DxcOutputObject> outputs) {
  433. for (unsigned i = 0; i < outputs.size(); i++) {
  434. const DxcOutputObject &output = outputs.data()[i];
  435. // Skip if DXC_OUT_NONE or no object to store
  436. if (output.kind == DXC_OUT_NONE || !output.object)
  437. continue;
  438. IFR(SetOutput(output));
  439. }
  440. return S_OK;
  441. }
  442. HRESULT CopyOutputsFromResult(IDxcResult *pResult) {
  443. if (!pResult)
  444. return E_INVALIDARG;
  445. for (unsigned i = 0; i < kNumDxcOutputTypes; i++) {
  446. DxcOutputObject &output = m_outputs[i];
  447. DXC_OUT_KIND kind = (DXC_OUT_KIND)(i + 1);
  448. if (pResult->HasOutput(kind)) {
  449. IFR(pResult->GetOutput(kind, IID_PPV_ARGS(&output.object), &output.name));
  450. output.kind = kind;
  451. }
  452. }
  453. return S_OK;
  454. }
  455. // All-in-one initialization
  456. HRESULT Init(_In_ HRESULT status, _In_ DXC_OUT_KIND resultType,
  457. const llvm::ArrayRef<DxcOutputObject> outputs) {
  458. m_status = status;
  459. m_resultType = resultType;
  460. return SetOutputs(outputs);
  461. }
  462. // All-in-one create functions
  463. static HRESULT Create(_In_ HRESULT status, _In_ DXC_OUT_KIND resultType,
  464. _In_opt_count_(numOutputs) const DxcOutputObject *pOutputs,
  465. _In_ unsigned numOutputs,
  466. _COM_Outptr_ IDxcResult **ppResult) {
  467. *ppResult = nullptr;
  468. CComPtr<DxcResult> result =
  469. DxcResult::Alloc(DxcGetThreadMallocNoRef());
  470. IFROOM(result.p);
  471. IFR(result->Init(status, resultType, llvm::ArrayRef<DxcOutputObject>(pOutputs, numOutputs)));
  472. *ppResult = result.Detach();
  473. return S_OK;
  474. }
  475. static HRESULT Create(_In_ HRESULT status, _In_ DXC_OUT_KIND resultType,
  476. const llvm::ArrayRef<DxcOutputObject> outputs,
  477. _COM_Outptr_ IDxcResult **ppResult) {
  478. return Create(status, resultType, outputs.data(), outputs.size(), ppResult);
  479. }
  480. // For convenient use in legacy interface implementations
  481. static HRESULT Create(_In_ HRESULT status, _In_ DXC_OUT_KIND resultType,
  482. const llvm::ArrayRef<DxcOutputObject> outputs,
  483. _COM_Outptr_ IDxcOperationResult **ppResult) {
  484. IDxcResult *pResult;
  485. IFR(Create(status, resultType, outputs.data(), outputs.size(), &pResult));
  486. *ppResult = pResult;
  487. return S_OK;
  488. }
  489. };
  490. #endif