dxcapi.impl.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  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_EXTRA_OUTPUTS;
  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. static DxcOutputObject DataOutput(_In_ DXC_OUT_KIND kind,
  247. _In_ UINT32 codePage,
  248. _In_opt_ IUnknown *pBlob) {
  249. DxcOutputObject output;
  250. output.kind = kind;
  251. IFT(output.SetObject(pBlob, codePage));
  252. IFT(output.SetName(DxcOutNoName));
  253. return output;
  254. }
  255. template<typename DataTy>
  256. static DxcOutputObject ErrorOutput(UINT32 codePage, DataTy pText, SIZE_T size) {
  257. return StringOutput(DXC_OUT_ERRORS, codePage, pText, size, DxcOutNoName);
  258. }
  259. template<typename DataTy>
  260. static DxcOutputObject ErrorOutput(UINT32 codePage, DataTy pText) {
  261. return StringOutput(DXC_OUT_ERRORS, codePage, pText, DxcOutNoName);
  262. }
  263. template<typename NameTy>
  264. static DxcOutputObject ObjectOutput(LPCVOID pData, SIZE_T size, NameTy pName) {
  265. return DataOutput(DXC_OUT_OBJECT, pData, size, pName);
  266. }
  267. static DxcOutputObject ObjectOutput(LPCVOID pData, SIZE_T size) {
  268. return DataOutput(DXC_OUT_OBJECT, pData, size, DxcOutNoName);
  269. }
  270. };
  271. struct DxcExtraOutputObject {
  272. CComPtr<IDxcBlobUtf16> pType; // Custom name to identify the object
  273. CComPtr<IDxcBlobUtf16> pName; // The file path for the output
  274. CComPtr<IUnknown> pObject; // The object itself
  275. };
  276. class DxcExtraOutputs : public IDxcExtraOutputs {
  277. DXC_MICROCOM_TM_REF_FIELDS()
  278. DxcExtraOutputObject *m_Objects = nullptr;
  279. UINT32 m_uCount = 0;
  280. public:
  281. DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL()
  282. DXC_MICROCOM_TM_CTOR(DxcExtraOutputs)
  283. ~DxcExtraOutputs() {
  284. Clear();
  285. }
  286. HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) override {
  287. return DoBasicQueryInterface<IDxcExtraOutputs>(this, iid, ppvObject);
  288. }
  289. /////////////////////
  290. // IDxcExtraOutputs
  291. /////////////////////
  292. UINT32 STDMETHODCALLTYPE GetOutputCount() override {
  293. return m_uCount;
  294. }
  295. HRESULT STDMETHODCALLTYPE GetOutput(_In_ UINT32 uIndex,
  296. _In_ REFIID iid, _COM_Outptr_opt_result_maybenull_ void **ppvObject,
  297. _COM_Outptr_opt_result_maybenull_ IDxcBlobUtf16 **ppOutputType,
  298. _COM_Outptr_opt_result_maybenull_ IDxcBlobUtf16 **ppOutputName) override
  299. {
  300. if (uIndex >= m_uCount)
  301. return E_INVALIDARG;
  302. DxcExtraOutputObject *pObject = &m_Objects[uIndex];
  303. if (ppOutputType) {
  304. *ppOutputType = nullptr;
  305. IFR(pObject->pType.CopyTo(ppOutputType));
  306. }
  307. if (ppOutputName) {
  308. *ppOutputName = nullptr;
  309. IFR(pObject->pName.CopyTo(ppOutputName));
  310. }
  311. if (ppvObject) {
  312. *ppvObject = nullptr;
  313. if (pObject->pObject) {
  314. IFR(pObject->pObject->QueryInterface(iid, ppvObject));
  315. }
  316. }
  317. return S_OK;
  318. }
  319. /////////////////////
  320. // Internal Interface
  321. /////////////////////
  322. void Clear() {
  323. m_uCount = 0;
  324. if (m_Objects) {
  325. delete[] m_Objects;
  326. m_Objects = nullptr;
  327. }
  328. }
  329. void SetOutputs(const llvm::ArrayRef<DxcExtraOutputObject> outputs) {
  330. Clear();
  331. m_uCount = outputs.size();
  332. if (m_uCount > 0) {
  333. m_Objects = new DxcExtraOutputObject[m_uCount];
  334. for (UINT32 i = 0; i < outputs.size(); i++)
  335. m_Objects[i] = outputs[i];
  336. }
  337. }
  338. };
  339. class DxcResult : public IDxcResult {
  340. private:
  341. DXC_MICROCOM_TM_REF_FIELDS()
  342. HRESULT m_status = S_OK;
  343. DxcOutputObject m_outputs[kNumDxcOutputTypes]; // indexed by DXC_OUT_KIND enum - 1
  344. DXC_OUT_KIND m_resultType = DXC_OUT_NONE; // result type for GetResult()
  345. UINT32 m_textEncoding = DXC_CP_UTF8; // encoding for text outputs
  346. public:
  347. DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL()
  348. DXC_MICROCOM_TM_CTOR(DxcResult)
  349. HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) override {
  350. return DoBasicQueryInterface<IDxcResult, IDxcOperationResult>(this, iid, ppvObject);
  351. }
  352. //////////////////////
  353. // IDxcOperationResult
  354. //////////////////////
  355. HRESULT STDMETHODCALLTYPE GetStatus(_Out_ HRESULT *pStatus) override {
  356. if (pStatus == nullptr)
  357. return E_INVALIDARG;
  358. *pStatus = m_status;
  359. return S_OK;
  360. }
  361. HRESULT STDMETHODCALLTYPE
  362. GetResult(_COM_Outptr_result_maybenull_ IDxcBlob **ppResult) override {
  363. *ppResult = nullptr;
  364. if (m_resultType == DXC_OUT_NONE)
  365. return S_OK;
  366. DxcOutputObject *pObject = Output(m_resultType);
  367. if (pObject && pObject->object)
  368. return pObject->object->QueryInterface(ppResult);
  369. return S_OK;
  370. }
  371. HRESULT STDMETHODCALLTYPE
  372. GetErrorBuffer(_COM_Outptr_result_maybenull_ IDxcBlobEncoding **ppErrors) override {
  373. *ppErrors = nullptr;
  374. DxcOutputObject *pObject = Output(DXC_OUT_ERRORS);
  375. if (pObject && pObject->object)
  376. return pObject->object->QueryInterface(ppErrors);
  377. return S_OK;
  378. }
  379. /////////////
  380. // IDxcResult
  381. /////////////
  382. BOOL STDMETHODCALLTYPE HasOutput(_In_ DXC_OUT_KIND dxcOutKind) override {
  383. if (dxcOutKind <= DXC_OUT_NONE || (unsigned)dxcOutKind > kNumDxcOutputTypes)
  384. return FALSE;
  385. return m_outputs[(unsigned)dxcOutKind - 1].kind != DXC_OUT_NONE;
  386. }
  387. HRESULT STDMETHODCALLTYPE GetOutput(_In_ DXC_OUT_KIND dxcOutKind,
  388. _In_ REFIID iid, _COM_Outptr_opt_result_maybenull_ void **ppvObject,
  389. _COM_Outptr_ IDxcBlobUtf16 **ppOutputName) override {
  390. if (ppvObject == nullptr)
  391. return E_INVALIDARG;
  392. if (dxcOutKind <= DXC_OUT_NONE || (unsigned)dxcOutKind > kNumDxcOutputTypes)
  393. return E_INVALIDARG;
  394. DxcOutputObject &object = m_outputs[(unsigned)dxcOutKind - 1];
  395. if (object.kind == DXC_OUT_NONE)
  396. return E_INVALIDARG;
  397. *ppvObject = nullptr;
  398. if (ppOutputName)
  399. *ppOutputName = nullptr;
  400. IFR(object.object->QueryInterface(iid, ppvObject));
  401. if (ppOutputName && object.name) {
  402. object.name.CopyTo(ppOutputName);
  403. }
  404. return S_OK;
  405. }
  406. UINT32 GetNumOutputs() override {
  407. UINT32 numOutputs = 0;
  408. for (unsigned i = 0; i < kNumDxcOutputTypes; ++i) {
  409. if (m_outputs[i].kind != DXC_OUT_NONE)
  410. numOutputs++;
  411. }
  412. return numOutputs;
  413. }
  414. DXC_OUT_KIND GetOutputByIndex(UINT32 Index) override {
  415. if (!(Index < kNumDxcOutputTypes))
  416. return DXC_OUT_NONE;
  417. UINT32 numOutputs = 0;
  418. unsigned i = 0;
  419. for (; i < kNumDxcOutputTypes; ++i) {
  420. if (Index == numOutputs)
  421. return m_outputs[i].kind;
  422. if (m_outputs[i].kind != DXC_OUT_NONE)
  423. numOutputs++;
  424. }
  425. return DXC_OUT_NONE;
  426. }
  427. DXC_OUT_KIND PrimaryOutput() override {
  428. return m_resultType;
  429. }
  430. /////////////////////
  431. // Internal Interface
  432. /////////////////////
  433. HRESULT SetEncoding(UINT32 textEncoding) {
  434. if (textEncoding != DXC_CP_ACP && textEncoding != DXC_CP_UTF8 && textEncoding != DXC_CP_UTF16)
  435. return E_INVALIDARG;
  436. m_textEncoding = textEncoding;
  437. return S_OK;
  438. }
  439. DxcOutputObject *Output(DXC_OUT_KIND kind) {
  440. if (kind <= DXC_OUT_NONE || (unsigned)kind > kNumDxcOutputTypes)
  441. return nullptr;
  442. return &(m_outputs[(unsigned)kind - 1]);
  443. }
  444. HRESULT ClearOutput(DXC_OUT_KIND kind) {
  445. if (kind <= DXC_OUT_NONE || (unsigned)kind > kNumDxcOutputTypes)
  446. return E_INVALIDARG;
  447. DxcOutputObject &output = m_outputs[(unsigned)kind - 1];
  448. output.kind = DXC_OUT_NONE;
  449. output.object.Release();
  450. output.name.Release();
  451. return S_OK;
  452. }
  453. void ClearAllOutputs() {
  454. for (unsigned i = DXC_OUT_NONE + 1; i <= kNumDxcOutputTypes; i++)
  455. ClearOutput((DXC_OUT_KIND)(i));
  456. }
  457. HRESULT SetStatusAndPrimaryResult(HRESULT status, DXC_OUT_KIND resultType = DXC_OUT_NONE) {
  458. if ((unsigned)resultType > kNumDxcOutputTypes)
  459. return E_INVALIDARG;
  460. m_status = status;
  461. m_resultType = resultType;
  462. return S_OK;
  463. }
  464. // Set output object and name for previously uninitialized entry
  465. HRESULT SetOutput(const DxcOutputObject &output) {
  466. if (output.kind <= DXC_OUT_NONE || (unsigned)output.kind > kNumDxcOutputTypes)
  467. return E_INVALIDARG;
  468. if (!output.object)
  469. return E_INVALIDARG;
  470. DxcOutputObject &internalOutput = m_outputs[(unsigned)output.kind - 1];
  471. // Must not be overwriting an existing output
  472. if (internalOutput.kind != DXC_OUT_NONE)
  473. return E_INVALIDARG;
  474. internalOutput = output;
  475. return S_OK;
  476. }
  477. // Set or overwrite output object and set the kind
  478. HRESULT SetOutputObject(DXC_OUT_KIND kind, IUnknown *pObject) {
  479. if (kind <= DXC_OUT_NONE || (unsigned)kind > kNumDxcOutputTypes)
  480. return E_INVALIDARG;
  481. DxcOutputObject &output = m_outputs[(unsigned)kind - 1];
  482. if (!pObject)
  483. kind = DXC_OUT_NONE;
  484. output.kind = kind;
  485. output.SetObject(pObject, m_textEncoding);
  486. return S_OK;
  487. }
  488. // Set or overwrite output string object and set the kind
  489. template<typename StringTy>
  490. HRESULT SetOutputString(DXC_OUT_KIND kind, StringTy pString, size_t size = kAutoSize) {
  491. if (kind <= DXC_OUT_NONE || (unsigned)kind > kNumDxcOutputTypes)
  492. return E_INVALIDARG;
  493. DxcOutputObject &output = m_outputs[(unsigned)kind - 1];
  494. if (!pString)
  495. kind = DXC_OUT_NONE;
  496. output.kind = kind;
  497. output.SetString(m_textEncoding, pString, size);
  498. return S_OK;
  499. }
  500. // Set or overwrite the output name. This does not set kind,
  501. // since that indicates an active output, which must have an object.
  502. template<typename NameTy>
  503. HRESULT SetOutputName(DXC_OUT_KIND kind, NameTy Name) {
  504. if (kind <= DXC_OUT_NONE || (unsigned)kind > kNumDxcOutputTypes)
  505. return E_INVALIDARG;
  506. Output(kind)->SetName(Name);
  507. return S_OK;
  508. }
  509. HRESULT SetOutputs(const llvm::ArrayRef<DxcOutputObject> outputs) {
  510. for (unsigned i = 0; i < outputs.size(); i++) {
  511. const DxcOutputObject &output = outputs.data()[i];
  512. // Skip if DXC_OUT_NONE or no object to store
  513. if (output.kind == DXC_OUT_NONE || !output.object)
  514. continue;
  515. IFR(SetOutput(output));
  516. }
  517. return S_OK;
  518. }
  519. HRESULT CopyOutputsFromResult(IDxcResult *pResult) {
  520. if (!pResult)
  521. return E_INVALIDARG;
  522. for (unsigned i = 0; i < kNumDxcOutputTypes; i++) {
  523. DxcOutputObject &output = m_outputs[i];
  524. DXC_OUT_KIND kind = (DXC_OUT_KIND)(i + 1);
  525. if (pResult->HasOutput(kind)) {
  526. IFR(pResult->GetOutput(kind, IID_PPV_ARGS(&output.object), &output.name));
  527. output.kind = kind;
  528. }
  529. }
  530. return S_OK;
  531. }
  532. // All-in-one initialization
  533. HRESULT Init(_In_ HRESULT status, _In_ DXC_OUT_KIND resultType,
  534. const llvm::ArrayRef<DxcOutputObject> outputs) {
  535. m_status = status;
  536. m_resultType = resultType;
  537. return SetOutputs(outputs);
  538. }
  539. // All-in-one create functions
  540. static HRESULT Create(_In_ HRESULT status, _In_ DXC_OUT_KIND resultType,
  541. _In_opt_count_(numOutputs) const DxcOutputObject *pOutputs,
  542. _In_ unsigned numOutputs,
  543. _COM_Outptr_ IDxcResult **ppResult) {
  544. *ppResult = nullptr;
  545. CComPtr<DxcResult> result =
  546. DxcResult::Alloc(DxcGetThreadMallocNoRef());
  547. IFROOM(result.p);
  548. IFR(result->Init(status, resultType, llvm::ArrayRef<DxcOutputObject>(pOutputs, numOutputs)));
  549. *ppResult = result.Detach();
  550. return S_OK;
  551. }
  552. static HRESULT Create(_In_ HRESULT status, _In_ DXC_OUT_KIND resultType,
  553. const llvm::ArrayRef<DxcOutputObject> outputs,
  554. _COM_Outptr_ IDxcResult **ppResult) {
  555. return Create(status, resultType, outputs.data(), outputs.size(), ppResult);
  556. }
  557. // For convenient use in legacy interface implementations
  558. static HRESULT Create(_In_ HRESULT status, _In_ DXC_OUT_KIND resultType,
  559. const llvm::ArrayRef<DxcOutputObject> outputs,
  560. _COM_Outptr_ IDxcOperationResult **ppResult) {
  561. IDxcResult *pResult;
  562. IFR(Create(status, resultType, outputs.data(), outputs.size(), &pResult));
  563. *ppResult = pResult;
  564. return S_OK;
  565. }
  566. };
  567. #endif