1 //// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
2 //// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
3 //// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
4 //// PARTICULAR PURPOSE.
6 //// Copyright (c) Microsoft Corporation. All rights reserved
9 #include "BasicLoader.h"
10 #include "BasicShapes.h"
11 #include "DDSTextureLoader.h"
12 #include "DirectXSample.h"
15 using namespace Microsoft::WRL;
16 using namespace Windows::Storage;
17 using namespace Windows::Storage::Streams;
18 using namespace Windows::Foundation;
19 using namespace Windows::ApplicationModel;
21 BasicLoader::BasicLoader(
22 _In_ ID3D11Device* d3dDevice,
23 _In_opt_ IWICImagingFactory2* wicFactory
25 m_d3dDevice(d3dDevice),
26 m_wicFactory(wicFactory)
28 // Create a new BasicReaderWriter to do raw file I/O.
29 m_basicReaderWriter = ref new BasicReaderWriter();
32 template<class DeviceChildType>
33 inline void BasicLoader::SetDebugName(
34 _In_ DeviceChildType* object,
35 _In_ Platform::String^ name
39 // Only assign debug names in debug builds.
41 char nameString[1024];
42 int nameStringLength = WideCharToMultiByte(
53 if (nameStringLength == 0 )
55 char defaultNameString[] = "BasicLoaderObject";
57 object->SetPrivateData(
58 WKPDID_D3DDebugObjectName,
59 sizeof(defaultNameString) - 1,
67 object->SetPrivateData(
68 WKPDID_D3DDebugObjectName,
77 Platform::String^ BasicLoader::GetExtension(
78 _In_ Platform::String^ filename
81 int lastDotIndex = -1;
82 for (int i = filename->Length() - 1; i >= 0 && lastDotIndex == -1; i--)
84 if (*(filename->Data() + i) == '.')
89 if (lastDotIndex != -1)
91 std::unique_ptr<wchar_t[]> extension(new wchar_t[filename->Length() - lastDotIndex]);
92 for (unsigned int i = 0; i < filename->Length() - lastDotIndex; i++)
94 extension[i] = tolower(*(filename->Data() + lastDotIndex + 1 + i));
96 return ref new Platform::String(extension.get());
101 void BasicLoader::CreateTexture(
102 _In_ bool decodeAsDDS,
103 _In_reads_bytes_(dataSize) byte* data,
104 _In_ uint32 dataSize,
105 _Out_opt_ ID3D11Texture2D** texture,
106 _Out_opt_ ID3D11ShaderResourceView** textureView,
107 _In_opt_ Platform::String^ debugName
110 ComPtr<ID3D11ShaderResourceView> shaderResourceView;
111 ComPtr<ID3D11Texture2D> texture2D;
115 ComPtr<ID3D11Resource> resource;
117 if (textureView == nullptr)
119 CreateDDSTextureFromMemory(
129 CreateDDSTextureFromMemory(
139 resource.As(&texture2D)
144 if (m_wicFactory.Get() == nullptr)
146 // A WIC factory object is required in order to load texture
147 // assets stored in non-DDS formats. If BasicLoader was not
148 // initialized with one, create one as needed.
151 CLSID_WICImagingFactory,
153 CLSCTX_INPROC_SERVER,
154 IID_PPV_ARGS(&m_wicFactory)
159 ComPtr<IWICStream> stream;
161 m_wicFactory->CreateStream(&stream)
165 stream->InitializeFromMemory(
171 ComPtr<IWICBitmapDecoder> bitmapDecoder;
173 m_wicFactory->CreateDecoderFromStream(
176 WICDecodeMetadataCacheOnDemand,
181 ComPtr<IWICBitmapFrameDecode> bitmapFrame;
183 bitmapDecoder->GetFrame(0, &bitmapFrame)
186 ComPtr<IWICFormatConverter> formatConverter;
188 m_wicFactory->CreateFormatConverter(&formatConverter)
192 formatConverter->Initialize(
194 GUID_WICPixelFormat32bppPBGRA,
195 WICBitmapDitherTypeNone,
198 WICBitmapPaletteTypeCustom
205 bitmapFrame->GetSize(&width, &height)
208 std::unique_ptr<byte[]> bitmapPixels(new byte[width * height * 4]);
210 formatConverter->CopyPixels(
218 D3D11_SUBRESOURCE_DATA initialData;
219 ZeroMemory(&initialData, sizeof(initialData));
220 initialData.pSysMem = bitmapPixels.get();
221 initialData.SysMemPitch = width * 4;
222 initialData.SysMemSlicePitch = 0;
225 m_d3dDevice->CreateTexture2D(
226 &CD3D11_TEXTURE2D_DESC(
227 DXGI_FORMAT_B8G8R8A8_UNORM,
238 if (textureView != nullptr)
241 m_d3dDevice->CreateShaderResourceView(
243 &CD3D11_SHADER_RESOURCE_VIEW_DESC(
245 D3D11_SRV_DIMENSION_TEXTURE2D
253 SetDebugName(texture2D.Get(), debugName);
255 if (texture != nullptr)
257 *texture = texture2D.Detach();
259 if (textureView != nullptr)
261 *textureView = shaderResourceView.Detach();
265 void BasicLoader::CreateInputLayout(
266 _In_reads_bytes_(bytecodeSize) byte* bytecode,
267 _In_ uint32 bytecodeSize,
268 _In_reads_opt_(layoutDescNumElements) D3D11_INPUT_ELEMENT_DESC* layoutDesc,
269 _In_ uint32 layoutDescNumElements,
270 _Out_ ID3D11InputLayout** layout
273 if (layoutDesc == nullptr)
275 // If no input layout is specified, use the BasicVertex layout.
276 const D3D11_INPUT_ELEMENT_DESC basicVertexLayoutDesc[] =
278 { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
279 { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
280 { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 },
284 m_d3dDevice->CreateInputLayout(
285 basicVertexLayoutDesc,
286 ARRAYSIZE(basicVertexLayoutDesc),
296 m_d3dDevice->CreateInputLayout(
298 layoutDescNumElements,
307 void BasicLoader::CreateMesh(
309 _Out_ ID3D11Buffer** vertexBuffer,
310 _Out_ ID3D11Buffer** indexBuffer,
311 _Out_opt_ uint32* vertexCount,
312 _Out_opt_ uint32* indexCount,
313 _In_opt_ Platform::String^ debugName
316 // The first 4 bytes of the BasicMesh format define the number of vertices in the mesh.
317 uint32 numVertices = *reinterpret_cast<uint32*>(meshData);
319 // The following 4 bytes define the number of indices in the mesh.
320 uint32 numIndices = *reinterpret_cast<uint32*>(meshData + sizeof(uint32));
322 // The next segment of the BasicMesh format contains the vertices of the mesh.
323 BasicVertex* vertices = reinterpret_cast<BasicVertex*>(meshData + sizeof(uint32) * 2);
325 // The last segment of the BasicMesh format contains the indices of the mesh.
326 uint16* indices = reinterpret_cast<uint16*>(meshData + sizeof(uint32) * 2 + sizeof(BasicVertex) * numVertices);
328 // Create the vertex and index buffers with the mesh data.
330 D3D11_SUBRESOURCE_DATA vertexBufferData = {0};
331 vertexBufferData.pSysMem = vertices;
332 vertexBufferData.SysMemPitch = 0;
333 vertexBufferData.SysMemSlicePitch = 0;
335 m_d3dDevice->CreateBuffer(
336 &CD3D11_BUFFER_DESC(numVertices * sizeof(BasicVertex), D3D11_BIND_VERTEX_BUFFER),
342 D3D11_SUBRESOURCE_DATA indexBufferData = {0};
343 indexBufferData.pSysMem = indices;
344 indexBufferData.SysMemPitch = 0;
345 indexBufferData.SysMemSlicePitch = 0;
347 m_d3dDevice->CreateBuffer(
348 &CD3D11_BUFFER_DESC(numIndices * sizeof(uint16), D3D11_BIND_INDEX_BUFFER),
354 SetDebugName(*vertexBuffer, Platform::String::Concat(debugName, "_VertexBuffer"));
355 SetDebugName(*indexBuffer, Platform::String::Concat(debugName, "_IndexBuffer"));
357 if (vertexCount != nullptr)
359 *vertexCount = numVertices;
361 if (indexCount != nullptr)
363 *indexCount = numIndices;
367 void BasicLoader::LoadTexture(
368 _In_ Platform::String^ filename,
369 _Out_opt_ ID3D11Texture2D** texture,
370 _Out_opt_ ID3D11ShaderResourceView** textureView
373 Platform::Array<byte>^ textureData = m_basicReaderWriter->ReadData(filename);
376 GetExtension(filename) == "dds",
385 void BasicLoader::LoadTextureAsync(
386 _In_ Platform::String^ filename,
387 _Out_opt_ ID3D11Texture2D** texture,
388 _Out_opt_ ID3D11ShaderResourceView** textureView
391 m_basicReaderWriter->ReadDataAsync(filename, ref new ReadDataAsyncCallback([=](Platform::Array<byte>^ textureData, AsyncStatus /*status*/)
394 GetExtension(filename) == "dds",
404 void BasicLoader::LoadShader(
405 _In_ Platform::String^ filename,
406 _In_reads_opt_(layoutDescNumElements) D3D11_INPUT_ELEMENT_DESC layoutDesc[],
407 _In_ uint32 layoutDescNumElements,
408 _Out_ ID3D11VertexShader** shader,
409 _Out_opt_ ID3D11InputLayout** layout
412 Platform::Array<byte>^ bytecode = m_basicReaderWriter->ReadData(filename);
415 m_d3dDevice->CreateVertexShader(
423 SetDebugName(*shader, filename);
425 if (layout != nullptr)
431 layoutDescNumElements,
435 SetDebugName(*layout, filename);
439 void BasicLoader::LoadShaderAsync(
440 _In_ Platform::String^ filename,
441 _In_reads_opt_(layoutDescNumElements) D3D11_INPUT_ELEMENT_DESC layoutDesc[],
442 _In_ uint32 layoutDescNumElements,
443 _Out_ ID3D11VertexShader** shader,
444 _Out_opt_ ID3D11InputLayout** layout
447 m_basicReaderWriter->ReadDataAsync(filename, ref new ReadDataAsyncCallback([=](Platform::Array<byte>^ bytecode, AsyncStatus /*status*/)
450 m_d3dDevice->CreateVertexShader(
458 SetDebugName(*shader, filename);
460 if (layout != nullptr)
466 layoutDescNumElements,
470 SetDebugName(*layout, filename);
475 void BasicLoader::LoadShader(
476 _In_ Platform::String^ filename,
477 _Out_ ID3D11PixelShader** shader
480 Platform::Array<byte>^ bytecode = m_basicReaderWriter->ReadData(filename);
483 m_d3dDevice->CreatePixelShader(
491 SetDebugName(*shader, filename);
494 void BasicLoader::LoadShaderAsync(
495 _In_ Platform::String^ filename,
496 _Out_ ID3D11PixelShader** shader
499 m_basicReaderWriter->ReadDataAsync(filename, ref new ReadDataAsyncCallback([=](Platform::Array<byte>^ bytecode, AsyncStatus /*status*/)
502 m_d3dDevice->CreatePixelShader(
510 SetDebugName(*shader, filename);
514 void BasicLoader::LoadShader(
515 _In_ Platform::String^ filename,
516 _Out_ ID3D11ComputeShader** shader
519 Platform::Array<byte>^ bytecode = m_basicReaderWriter->ReadData(filename);
522 m_d3dDevice->CreateComputeShader(
530 SetDebugName(*shader, filename);
533 void BasicLoader::LoadShaderAsync(
534 _In_ Platform::String^ filename,
535 _Out_ ID3D11ComputeShader** shader
538 m_basicReaderWriter->ReadDataAsync(filename, ref new ReadDataAsyncCallback([=](Platform::Array<byte>^ bytecode, AsyncStatus /*status*/)
541 m_d3dDevice->CreateComputeShader(
549 SetDebugName(*shader, filename);
553 void BasicLoader::LoadShader(
554 _In_ Platform::String^ filename,
555 _Out_ ID3D11GeometryShader** shader
558 Platform::Array<byte>^ bytecode = m_basicReaderWriter->ReadData(filename);
561 m_d3dDevice->CreateGeometryShader(
569 SetDebugName(*shader, filename);
572 void BasicLoader::LoadShaderAsync(
573 _In_ Platform::String^ filename,
574 _Out_ ID3D11GeometryShader** shader
577 m_basicReaderWriter->ReadDataAsync(filename, ref new ReadDataAsyncCallback([=](Platform::Array<byte>^ bytecode, AsyncStatus /*status*/)
580 m_d3dDevice->CreateGeometryShader(
588 SetDebugName(*shader, filename);
592 void BasicLoader::LoadShader(
593 _In_ Platform::String^ filename,
594 _In_reads_opt_(numEntries) const D3D11_SO_DECLARATION_ENTRY* streamOutDeclaration,
595 _In_ uint32 numEntries,
596 _In_reads_opt_(numStrides) const uint32* bufferStrides,
597 _In_ uint32 numStrides,
598 _In_ uint32 rasterizedStream,
599 _Out_ ID3D11GeometryShader** shader
602 Platform::Array<byte>^ bytecode = m_basicReaderWriter->ReadData(filename);
605 m_d3dDevice->CreateGeometryShaderWithStreamOutput(
608 streamOutDeclaration,
618 SetDebugName(*shader, filename);
621 void BasicLoader::LoadShaderAsync(
622 _In_ Platform::String^ filename,
623 _In_reads_opt_(numEntries) const D3D11_SO_DECLARATION_ENTRY* streamOutDeclaration,
624 _In_ uint32 numEntries,
625 _In_reads_opt_(numStrides) const uint32* bufferStrides,
626 _In_ uint32 numStrides,
627 _In_ uint32 rasterizedStream,
628 _Out_ ID3D11GeometryShader** shader
631 m_basicReaderWriter->ReadDataAsync(filename, ref new ReadDataAsyncCallback([=](Platform::Array<byte>^ bytecode, AsyncStatus /*status*/)
634 m_d3dDevice->CreateGeometryShaderWithStreamOutput(
637 streamOutDeclaration,
647 SetDebugName(*shader, filename);
651 void BasicLoader::LoadShader(
652 _In_ Platform::String^ filename,
653 _Out_ ID3D11HullShader** shader
656 Platform::Array<byte>^ bytecode = m_basicReaderWriter->ReadData(filename);
659 m_d3dDevice->CreateHullShader(
667 SetDebugName(*shader, filename);
670 void BasicLoader::LoadShaderAsync(
671 _In_ Platform::String^ filename,
672 _Out_ ID3D11HullShader** shader
675 m_basicReaderWriter->ReadDataAsync(filename, ref new ReadDataAsyncCallback([=](Platform::Array<byte>^ bytecode, AsyncStatus /*status*/)
678 m_d3dDevice->CreateHullShader(
686 SetDebugName(*shader, filename);
690 void BasicLoader::LoadShader(
691 _In_ Platform::String^ filename,
692 _Out_ ID3D11DomainShader** shader
695 Platform::Array<byte>^ bytecode = m_basicReaderWriter->ReadData(filename);
698 m_d3dDevice->CreateDomainShader(
706 SetDebugName(*shader, filename);
709 void BasicLoader::LoadShaderAsync(
710 _In_ Platform::String^ filename,
711 _Out_ ID3D11DomainShader** shader
714 m_basicReaderWriter->ReadDataAsync(filename, ref new ReadDataAsyncCallback([=](Platform::Array<byte>^ bytecode, AsyncStatus /*status*/)
717 m_d3dDevice->CreateDomainShader(
725 SetDebugName(*shader, filename);
729 void BasicLoader::LoadMesh(
730 _In_ Platform::String^ filename,
731 _Out_ ID3D11Buffer** vertexBuffer,
732 _Out_ ID3D11Buffer** indexBuffer,
733 _Out_opt_ uint32* vertexCount,
734 _Out_opt_ uint32* indexCount
737 Platform::Array<byte>^ meshData = m_basicReaderWriter->ReadData(filename);
749 void BasicLoader::LoadMeshAsync(
750 _In_ Platform::String^ filename,
751 _Out_ ID3D11Buffer** vertexBuffer,
752 _Out_ ID3D11Buffer** indexBuffer,
753 _Out_opt_ uint32* vertexCount,
754 _Out_opt_ uint32* indexCount
757 m_basicReaderWriter->ReadDataAsync(filename, ref new ReadDataAsyncCallback([=](Platform::Array<byte>^ meshData, AsyncStatus /*status*/)