// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. #if GRAPHICS_API_DIRECTX11 #include "GPUShaderDX11.h" #include "GPUShaderProgramDX11.h" #include "Engine/Serialization/MemoryReadStream.h" #include "../RenderToolsDX.h" GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, byte* cacheBytes, uint32 cacheSize, MemoryReadStream& stream) { GPUShaderProgram* shader = nullptr; HRESULT result; switch (type) { case ShaderStage::Vertex: { D3D11_INPUT_ELEMENT_DESC inputLayoutDesc[VERTEX_SHADER_MAX_INPUT_ELEMENTS]; // Temporary variables byte Type, Format, Index, InputSlot, InputSlotClass; uint32 AlignedByteOffset, InstanceDataStepRate; // Load Input Layout (it may be empty) byte inputLayoutSize; stream.ReadByte(&inputLayoutSize); ASSERT(inputLayoutSize <= VERTEX_SHADER_MAX_INPUT_ELEMENTS); for (int32 a = 0; a < inputLayoutSize; a++) { // Read description // TODO: maybe use struct and load at once? stream.ReadByte(&Type); stream.ReadByte(&Index); stream.ReadByte(&Format); stream.ReadByte(&InputSlot); stream.ReadUint32(&AlignedByteOffset); stream.ReadByte(&InputSlotClass); stream.ReadUint32(&InstanceDataStepRate); // Get semantic name const char* semanticName = nullptr; // TODO: maybe use enum+mapping ? switch (Type) { case 1: semanticName = "POSITION"; break; case 2: semanticName = "COLOR"; break; case 3: semanticName = "TEXCOORD"; break; case 4: semanticName = "NORMAL"; break; case 5: semanticName = "TANGENT"; break; case 6: semanticName = "BITANGENT"; break; case 7: semanticName = "ATTRIBUTE"; break; case 8: semanticName = "BLENDINDICES"; break; case 9: semanticName = "BLENDWEIGHT"; break; default: LOG(Fatal, "Invalid vertex shader element semantic type: {0}", Type); break; } // Set data inputLayoutDesc[a] = { semanticName, static_cast(Index), static_cast(Format), static_cast(InputSlot), static_cast(AlignedByteOffset), static_cast(InputSlotClass), static_cast(InstanceDataStepRate) }; } ID3D11InputLayout* inputLayout = nullptr; if (inputLayoutSize > 0) { // Create input layout VALIDATE_DIRECTX_CALL(_device->GetDevice()->CreateInputLayout(inputLayoutDesc, inputLayoutSize, cacheBytes, cacheSize, &inputLayout)); } // Create shader ID3D11VertexShader* buffer = nullptr; result = _device->GetDevice()->CreateVertexShader(cacheBytes, cacheSize, nullptr, &buffer); LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr); // Create object shader = New(initializer, buffer, inputLayout, inputLayoutSize); break; } case ShaderStage::Hull: { // Read control points int32 controlPointsCount; stream.ReadInt32(&controlPointsCount); // Create shader ID3D11HullShader* buffer = nullptr; result = _device->GetDevice()->CreateHullShader(cacheBytes, cacheSize, nullptr, &buffer); LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr); // Create object shader = New(initializer, buffer, controlPointsCount); break; } case ShaderStage::Domain: { // Create shader ID3D11DomainShader* buffer = nullptr; result = _device->GetDevice()->CreateDomainShader(cacheBytes, cacheSize, nullptr, &buffer); LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr); // Create object shader = New(initializer, buffer); break; } case ShaderStage::Geometry: { // Create shader ID3D11GeometryShader* buffer = nullptr; result = _device->GetDevice()->CreateGeometryShader(cacheBytes, cacheSize, nullptr, &buffer); LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr); // Create object shader = New(initializer, buffer); break; } case ShaderStage::Pixel: { // Create shader ID3D11PixelShader* buffer = nullptr; result = _device->GetDevice()->CreatePixelShader(cacheBytes, cacheSize, nullptr, &buffer); LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr); // Create object shader = New(initializer, buffer); break; } case ShaderStage::Compute: { // Create shader ID3D11ComputeShader* buffer = nullptr; result = _device->GetDevice()->CreateComputeShader(cacheBytes, cacheSize, nullptr, &buffer); LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr); // Create object shader = New(initializer, buffer); break; } } return shader; } void GPUShaderDX11::OnReleaseGPU() { _cbs.Clear(); GPUShader::OnReleaseGPU(); } #endif