From f2e065dee10fb110e9d51175ee6381333319ef56 Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Tue, 20 Oct 2015 21:05:29 -0700 Subject: Release v1.0.0 --- RenderScript/src/BlendStateParser.cpp | 196 +++++++++++++++++ RenderScript/src/BufferParser.cpp | 259 +++++++++++++++++++++++ RenderScript/src/BufferViewParser.cpp | 105 ++++++++++ RenderScript/src/DepthStencilStateParser.cpp | 127 +++++++++++ RenderScript/src/DeviceContextFuncBindings.cpp | 145 +++++++++++++ RenderScript/src/DrawAttribsParser.cpp | 146 +++++++++++++ RenderScript/src/EngineObjectParserBase.cpp | 271 ++++++++++++++++++++++++ RenderScript/src/EnumMappings.cpp | 210 +++++++++++++++++++ RenderScript/src/LayoutDescParser.cpp | 151 ++++++++++++++ RenderScript/src/LuaBindings.cpp | 278 +++++++++++++++++++++++++ RenderScript/src/LuaFunctionBinding.cpp | 110 ++++++++++ RenderScript/src/LuaWrappers.cpp | 83 ++++++++ RenderScript/src/ParsingErrors.cpp | 87 ++++++++ RenderScript/src/RasterizerStateParser.cpp | 89 ++++++++ RenderScript/src/ResourceMappingParser.cpp | 166 +++++++++++++++ RenderScript/src/SamplerParser.cpp | 92 ++++++++ RenderScript/src/ScissorRectParser.cpp | 124 +++++++++++ RenderScript/src/ScriptParser.cpp | 263 +++++++++++++++++++++++ RenderScript/src/ShaderParser.cpp | 197 ++++++++++++++++++ RenderScript/src/ShaderVariableParser.cpp | 140 +++++++++++++ RenderScript/src/TextureParser.cpp | 86 ++++++++ RenderScript/src/TextureViewParser.cpp | 138 ++++++++++++ RenderScript/src/ViewportParser.cpp | 133 ++++++++++++ RenderScript/src/pch.cpp | 25 +++ 24 files changed, 3621 insertions(+) create mode 100644 RenderScript/src/BlendStateParser.cpp create mode 100644 RenderScript/src/BufferParser.cpp create mode 100644 RenderScript/src/BufferViewParser.cpp create mode 100644 RenderScript/src/DepthStencilStateParser.cpp create mode 100644 RenderScript/src/DeviceContextFuncBindings.cpp create mode 100644 RenderScript/src/DrawAttribsParser.cpp create mode 100644 RenderScript/src/EngineObjectParserBase.cpp create mode 100644 RenderScript/src/EnumMappings.cpp create mode 100644 RenderScript/src/LayoutDescParser.cpp create mode 100644 RenderScript/src/LuaBindings.cpp create mode 100644 RenderScript/src/LuaFunctionBinding.cpp create mode 100644 RenderScript/src/LuaWrappers.cpp create mode 100644 RenderScript/src/ParsingErrors.cpp create mode 100644 RenderScript/src/RasterizerStateParser.cpp create mode 100644 RenderScript/src/ResourceMappingParser.cpp create mode 100644 RenderScript/src/SamplerParser.cpp create mode 100644 RenderScript/src/ScissorRectParser.cpp create mode 100644 RenderScript/src/ScriptParser.cpp create mode 100644 RenderScript/src/ShaderParser.cpp create mode 100644 RenderScript/src/ShaderVariableParser.cpp create mode 100644 RenderScript/src/TextureParser.cpp create mode 100644 RenderScript/src/TextureViewParser.cpp create mode 100644 RenderScript/src/ViewportParser.cpp create mode 100644 RenderScript/src/pch.cpp (limited to 'RenderScript/src') diff --git a/RenderScript/src/BlendStateParser.cpp b/RenderScript/src/BlendStateParser.cpp new file mode 100644 index 0000000..adf26ae --- /dev/null +++ b/RenderScript/src/BlendStateParser.cpp @@ -0,0 +1,196 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "BlendStateParser.h" + +namespace std +{ + DEFINE_ENUM_HASH( Diligent::BLEND_FACTOR ) + DEFINE_ENUM_HASH( Diligent::BLEND_OPERATION ) + DEFINE_ENUM_HASH( Diligent::COLOR_MASK ) +} + +namespace Diligent +{ + class RenderTargetBlendStateParser; + + template<> + class MemberBinder : public MemberBinderBase + { + public: + MemberBinder( size_t MemberOffset, size_t Dummy ) : + MemberBinderBase( MemberOffset ) + { + DEFINE_BINDER( m_Bindings, RenderTargetBlendDesc, BlendEnable, Bool, Validator() ) + + DEFINE_ENUM_ELEMENT_MAPPING( m_BlendFactorEnumMapping, BLEND_FACTOR_ZERO); + DEFINE_ENUM_ELEMENT_MAPPING( m_BlendFactorEnumMapping, BLEND_FACTOR_ONE); + DEFINE_ENUM_ELEMENT_MAPPING( m_BlendFactorEnumMapping, BLEND_FACTOR_SRC_COLOR); + DEFINE_ENUM_ELEMENT_MAPPING( m_BlendFactorEnumMapping, BLEND_FACTOR_INV_SRC_COLOR); + DEFINE_ENUM_ELEMENT_MAPPING( m_BlendFactorEnumMapping, BLEND_FACTOR_SRC_ALPHA); + DEFINE_ENUM_ELEMENT_MAPPING( m_BlendFactorEnumMapping, BLEND_FACTOR_INV_SRC_ALPHA); + DEFINE_ENUM_ELEMENT_MAPPING( m_BlendFactorEnumMapping, BLEND_FACTOR_DEST_ALPHA); + DEFINE_ENUM_ELEMENT_MAPPING( m_BlendFactorEnumMapping, BLEND_FACTOR_INV_DEST_ALPHA); + DEFINE_ENUM_ELEMENT_MAPPING( m_BlendFactorEnumMapping, BLEND_FACTOR_DEST_COLOR); + DEFINE_ENUM_ELEMENT_MAPPING( m_BlendFactorEnumMapping, BLEND_FACTOR_INV_DEST_COLOR); + DEFINE_ENUM_ELEMENT_MAPPING( m_BlendFactorEnumMapping, BLEND_FACTOR_SRC_ALPHA_SAT); + DEFINE_ENUM_ELEMENT_MAPPING( m_BlendFactorEnumMapping, BLEND_FACTOR_BLEND_FACTOR); + DEFINE_ENUM_ELEMENT_MAPPING( m_BlendFactorEnumMapping, BLEND_FACTOR_INV_BLEND_FACTOR); + DEFINE_ENUM_ELEMENT_MAPPING( m_BlendFactorEnumMapping, BLEND_FACTOR_SRC1_COLOR); + DEFINE_ENUM_ELEMENT_MAPPING( m_BlendFactorEnumMapping, BLEND_FACTOR_INV_SRC1_COLOR); + DEFINE_ENUM_ELEMENT_MAPPING( m_BlendFactorEnumMapping, BLEND_FACTOR_SRC1_ALPHA); + DEFINE_ENUM_ELEMENT_MAPPING( m_BlendFactorEnumMapping, BLEND_FACTOR_INV_SRC1_ALPHA); + VERIFY( m_BlendFactorEnumMapping.m_Str2ValMap.size() == BLEND_FACTOR_NUM_FACTORS - 1, + "Unexpected map size. Did you update BLEND_FACTOR enum?" ); + VERIFY( m_BlendFactorEnumMapping.m_Val2StrMap.size() == BLEND_FACTOR_NUM_FACTORS - 1, + "Unexpected map size. Did you update BLEND_FACTOR enum?" ); + + DEFINE_ENUM_BINDER( m_Bindings, RenderTargetBlendDesc, SrcBlend, BLEND_FACTOR, m_BlendFactorEnumMapping ); + DEFINE_ENUM_BINDER( m_Bindings, RenderTargetBlendDesc, DestBlend, BLEND_FACTOR, m_BlendFactorEnumMapping ); + DEFINE_ENUM_BINDER( m_Bindings, RenderTargetBlendDesc, SrcBlendAlpha, BLEND_FACTOR, m_BlendFactorEnumMapping ); + DEFINE_ENUM_BINDER( m_Bindings, RenderTargetBlendDesc, DestBlendAlpha, BLEND_FACTOR, m_BlendFactorEnumMapping ); + + + DEFINE_ENUM_ELEMENT_MAPPING( m_BlendOpEnumMapping, BLEND_OPERATION_ADD ); + DEFINE_ENUM_ELEMENT_MAPPING( m_BlendOpEnumMapping, BLEND_OPERATION_SUBTRACT ); + DEFINE_ENUM_ELEMENT_MAPPING( m_BlendOpEnumMapping, BLEND_OPERATION_REV_SUBTRACT ); + DEFINE_ENUM_ELEMENT_MAPPING( m_BlendOpEnumMapping, BLEND_OPERATION_MIN ); + DEFINE_ENUM_ELEMENT_MAPPING( m_BlendOpEnumMapping, BLEND_OPERATION_MAX ); + VERIFY( m_BlendOpEnumMapping.m_Str2ValMap.size() == BLEND_OPERATION_NUM_OPERATIONS - 1, + "Unexpected map size. Did you update BLEND_OPERATION enum?" ); + VERIFY( m_BlendOpEnumMapping.m_Val2StrMap.size() == BLEND_OPERATION_NUM_OPERATIONS - 1, + "Unexpected map size. Did you update BLEND_OPERATION enum?" ); + + DEFINE_ENUM_BINDER( m_Bindings, RenderTargetBlendDesc, BlendOp, BLEND_OPERATION, m_BlendOpEnumMapping ); + DEFINE_ENUM_BINDER( m_Bindings, RenderTargetBlendDesc, BlendOpAlpha, BLEND_OPERATION, m_BlendOpEnumMapping ); + + + DEFINE_ENUM_ELEMENT_MAPPING( m_ColorMaskEnumMapping, COLOR_MASK_RED ); + DEFINE_ENUM_ELEMENT_MAPPING( m_ColorMaskEnumMapping, COLOR_MASK_GREEN ); + DEFINE_ENUM_ELEMENT_MAPPING( m_ColorMaskEnumMapping, COLOR_MASK_BLUE ); + DEFINE_ENUM_ELEMENT_MAPPING( m_ColorMaskEnumMapping, COLOR_MASK_ALPHA ); + DEFINE_ENUM_ELEMENT_MAPPING( m_ColorMaskEnumMapping, COLOR_MASK_ALL ); + DEFINE_FLAGS_BINDER( m_Bindings, RenderTargetBlendDesc, RenderTargetWriteMask, COLOR_MASK, m_ColorMaskEnumMapping ); + } + + virtual void GetValue( lua_State *L, const void* pBasePointer ) + { + const auto &RTs = GetMemberByOffest< const RenderTargetBlendDesc >(pBasePointer, m_MemberOffset); + PushLuaArray( L, &RTs, &RTs+BlendStateDesc::MaxRenderTargets, [&](const RenderTargetBlendDesc &Elem) + { + PushLuaTable( L, &Elem, m_Bindings ); + } + ); + } + + virtual void SetValue( lua_State *L, int Index, void* pBasePointer ) + { + ParseLuaArray( L, Index, pBasePointer, [&]( void* _pBasePointer, int StackIndex, int NewArrayIndex ) + { + VERIFY( pBasePointer == _pBasePointer, "Sanity check" ); + auto &RenderTargets = GetMemberByOffest( pBasePointer, m_MemberOffset ); + + auto MaxRTs = BlendStateDesc::MaxRenderTargets; + if( !(NewArrayIndex >= 1 && NewArrayIndex <= MaxRTs) ) + SCRIPT_PARSING_ERROR( L, "Incorrect render target index ", NewArrayIndex, ". Only 1..", MaxRTs, " are allowed" ); + + ParseLuaTable( L, StackIndex, &RenderTargets + (NewArrayIndex-1), m_Bindings ); + } + ); + } + private: + BindingsMapType m_Bindings; + + EnumMapping < BLEND_FACTOR > m_BlendFactorEnumMapping; + EnumMapping < BLEND_OPERATION > m_BlendOpEnumMapping; + EnumMapping < COLOR_MASK > m_ColorMaskEnumMapping; + }; + + + const Char* BlendStateParser::BlendStateLibName = "BlendState"; + + BlendStateParser::BlendStateParser( IRenderDevice *pRenderDevice, lua_State *L ) : + EngineObjectParserCommon( pRenderDevice, L, BlendStateLibName ), + m_SetBlendBinding( this, L, "Context", "SetBlendState", &BlendStateParser::SetBlendState ) + { + DEFINE_BUFFERED_STRING_BINDER( m_Bindings, SBSDescWrapper, Name, NameBuffer ) + + DEFINE_BINDER( m_Bindings, SBSDescWrapper, AlphaToCoverageEnable, Bool, Validator() ) + DEFINE_BINDER( m_Bindings, SBSDescWrapper, IndependentBlendEnable, Bool, Validator() ) + + DEFINE_BINDER( m_Bindings, SBSDescWrapper, RenderTargets, RenderTargetBlendStateParser, 0 ) + }; + + void BlendStateParser::CreateObj( lua_State *L ) + { + INIT_LUA_STACK_TRACKING( L ); + + SBSDescWrapper BlendDesc; + ParseLuaTable( L, 1, &BlendDesc, m_Bindings ); + + CHECK_LUA_STACK_HEIGHT(); + + auto ppBlendState = reinterpret_cast(lua_newuserdata( L, sizeof( IBlendState* ) )); + *ppBlendState = nullptr; + m_pRenderDevice->CreateBlendState( BlendDesc, ppBlendState ); + if( *ppBlendState == nullptr ) + SCRIPT_PARSING_ERROR( L, "Failed to create blend state object" ) + + CHECK_LUA_STACK_HEIGHT( +1 ); + } + + int BlendStateParser::SetBlendState( lua_State *L ) + { + auto *pBS = *GetUserData( L, 1, m_MetatableRegistryName.c_str() ); + + auto NumArgs = lua_gettop( L ); + float BlendFactors[4] = { 1, 1, 1, 1 }; + if( NumArgs >= 2 ) + { + INIT_LUA_STACK_TRACKING( L ); + + ParseLuaArray( L, 2, BlendFactors, [&]( void* _pBasePointer, int StackIndex, int NewArrayIndex ) + { + VERIFY( BlendFactors == _pBasePointer, "Sanity check" ); + if( !(NewArrayIndex >= 1 && NewArrayIndex <= 4) ) + SCRIPT_PARSING_ERROR( L, "Incorrect blend factor index ", NewArrayIndex, ". Only 1..4 are allowed." ); + + BlendFactors[NewArrayIndex - 1] = ReadValueFromLua( L, StackIndex ); + } + ); + + CHECK_LUA_STACK_HEIGHT(); + } + + Uint32 SampleMask = 0xFFFFFFFF; + if( NumArgs >= 3 ) + { + SampleMask = ReadValueFromLua( L, 3 ); + } + + auto *pContext = LoadDeviceContextFromRegistry( L ); + pContext->SetBlendState( pBS, BlendFactors, SampleMask ); + return 0; + } +} diff --git a/RenderScript/src/BufferParser.cpp b/RenderScript/src/BufferParser.cpp new file mode 100644 index 0000000..efa2d2a --- /dev/null +++ b/RenderScript/src/BufferParser.cpp @@ -0,0 +1,259 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "BufferParser.h" +#include "GraphicsUtilities.h" + +namespace Diligent +{ + const Char* BufferParser::BufferLibName = "Buffer"; + + template<> + class MemberBinder : public MemberBinderBase + { + public: + MemberBinder( size_t MemberOffset, size_t Dummy ) : + MemberBinderBase( MemberOffset ) + { + DEFINE_ENUM_BINDER( m_Bindings, BufferDesc::BufferFormat, ValueType, VALUE_TYPE, m_ValueTypeEnumMapping ) + DEFINE_BINDER( m_Bindings, BufferDesc::BufferFormat, NumComponents, Uint32, Validator( "Num Components", 1, 4 ) ) + DEFINE_BINDER( m_Bindings, BufferDesc::BufferFormat, IsNormalized, Bool, Validator() ) + } + + virtual void GetValue( lua_State *L, const void* pBasePointer ) + { + const auto &BuffFmt = GetMemberByOffest( pBasePointer, m_MemberOffset ); + PushLuaTable( L, &BuffFmt, m_Bindings ); + } + + virtual void SetValue( lua_State *L, int Index, void* pBasePointer ) + { + auto &BuffFmt = GetMemberByOffest( pBasePointer, m_MemberOffset ); + ParseLuaTable( L, Index, &BuffFmt, m_Bindings ); + } + private: + BindingsMapType m_Bindings; + ValueTypeEnumMapping m_ValueTypeEnumMapping; + }; + + BufferParser::BufferParser( IRenderDevice *pRenderDevice, lua_State *L ) : + EngineObjectParserCommon( pRenderDevice, L, BufferLibName ), + m_SetVertexBuffersBinding(this, L, "Context", "SetVertexBuffers", &BufferParser::SetVertexBuffers), + m_SetIndexBufferBinding( this, L, "Context", "SetIndexBuffer", &BufferParser::SetIndexBuffer ) + { + DEFINE_BUFFERED_STRING_BINDER( m_Bindings, SBuffDescWrapper, Name, NameBuffer ); + + DEFINE_BINDER( m_Bindings, SBuffDescWrapper, uiSizeInBytes, Uint32, Validator() ) + + DEFINE_ENUM_ELEMENT_MAPPING( m_BindFlagEnumMapping, BIND_VERTEX_BUFFER ); + DEFINE_ENUM_ELEMENT_MAPPING( m_BindFlagEnumMapping, BIND_INDEX_BUFFER ); + DEFINE_ENUM_ELEMENT_MAPPING( m_BindFlagEnumMapping, BIND_UNIFORM_BUFFER ); + DEFINE_ENUM_ELEMENT_MAPPING( m_BindFlagEnumMapping, BIND_SHADER_RESOURCE ); + DEFINE_ENUM_ELEMENT_MAPPING( m_BindFlagEnumMapping, BIND_STREAM_OUTPUT ); + //DEFINE_ENUM_ELEMENT_MAPPING( m_BindFlagEnumMapping, BIND_RENDER_TARGET ); + //DEFINE_ENUM_ELEMENT_MAPPING( m_BindFlagEnumMapping, BIND_DEPTH_STENCIL ); + DEFINE_ENUM_ELEMENT_MAPPING( m_BindFlagEnumMapping, BIND_UNORDERED_ACCESS ); + DEFINE_ENUM_ELEMENT_MAPPING( m_BindFlagEnumMapping, BIND_INDIRECT_DRAW_ARGS ); + // Explicit namespace declaraion is necesseary to avoid + // name conflicts when building for windows store + DEFINE_FLAGS_BINDER( m_Bindings, SBuffDescWrapper, BindFlags, Diligent::BIND_FLAGS, m_BindFlagEnumMapping ); + + DEFINE_ENUM_BINDER( m_Bindings, SBuffDescWrapper, Usage, USAGE, m_UsageEnumMapping ) + DEFINE_FLAGS_BINDER( m_Bindings, SBuffDescWrapper, CPUAccessFlags, CPU_ACCESS_FLAG, m_CpuAccessFlagEnumMapping ); + + DEFINE_ENUM_ELEMENT_MAPPING( m_BuffModeEnumMapping, BUFFER_MODE_UNDEFINED ); + DEFINE_ENUM_ELEMENT_MAPPING( m_BuffModeEnumMapping, BUFFER_MODE_FORMATED ); + DEFINE_ENUM_ELEMENT_MAPPING( m_BuffModeEnumMapping, BUFFER_MODE_STRUCTURED ); + static_assert(BUFFER_MODE_NUM_MODES == BUFFER_MODE_STRUCTURED + 1, "Not all buffer modes initialized."); + VERIFY( m_BuffModeEnumMapping.m_Str2ValMap.size() == BUFFER_MODE_NUM_MODES, + "Unexpected map size. Did you update BUFFER_MODE enum?" ); + VERIFY( m_BuffModeEnumMapping.m_Val2StrMap.size() == BUFFER_MODE_NUM_MODES, + "Unexpected map size. Did you update BUFFER_MODE enum?" ); + DEFINE_ENUM_BINDER( m_Bindings, SBuffDescWrapper, Mode, BUFFER_MODE, m_BuffModeEnumMapping ); + + DEFINE_BINDER( m_Bindings, SBuffDescWrapper, Format, BufferDesc::BufferFormat, 0 ); + DEFINE_BINDER( m_Bindings, SBuffDescWrapper, ElementByteStride, Uint32, Validator() ); + + DEFINE_ENUM_ELEMENT_MAPPING( m_SetVBFlagEnumMapping, SET_VERTEX_BUFFERS_FLAG_RESET ); + }; + + void BufferParser::CreateObj( lua_State *L ) + { + auto NumArgs = lua_gettop( L ); + INIT_LUA_STACK_TRACKING(L); + SBuffDescWrapper BufferDesc; + ParseLuaTable( L, 1, &BufferDesc, m_Bindings ); + CHECK_LUA_STACK_HEIGHT(); + + if( BufferDesc.Mode == BUFFER_MODE_FORMATED ) + { + auto &BuffFmt = BufferDesc.Format; + if( BuffFmt.ValueType == VT_UNDEFINED || BuffFmt.NumComponents == 0 ) + SCRIPT_PARSING_ERROR( L, "Valid format must be specified for a formated buffer" ); + auto FmtSize = GetValueSize( BuffFmt.ValueType ) * BuffFmt.NumComponents; + if( BufferDesc.ElementByteStride != 0 ) + { + if( BufferDesc.ElementByteStride != FmtSize ) + SCRIPT_PARSING_ERROR( L, "Size of the specified format (", FmtSize, ") does not match UAV element byte stride (", BufferDesc.ElementByteStride, ")." ); + } + else + { + BufferDesc.ElementByteStride = FmtSize; + } + if( BuffFmt.ValueType == VT_FLOAT32 || BuffFmt.ValueType == VT_FLOAT16 ) + BuffFmt.IsNormalized = false; + } + + if( BufferDesc.Mode == BUFFER_MODE_STRUCTURED && BufferDesc.ElementByteStride == 0 ) + SCRIPT_PARSING_ERROR( L, "UAV element byte stride of a structured buffer cannot be zero" ); + + if( (BufferDesc.Mode == BUFFER_MODE_FORMATED || BufferDesc.Mode == BUFFER_MODE_STRUCTURED) && + (BufferDesc.uiSizeInBytes % BufferDesc.ElementByteStride) != 0 ) + SCRIPT_PARSING_ERROR( L, "Buffer size (", BufferDesc.uiSizeInBytes, ") is not multiple of element byte stride (", BufferDesc.ElementByteStride, ")." ); + + std::vector RawData; + if( NumArgs > 1 ) + { + if( NumArgs != 3 ) + { + SCRIPT_PARSING_ERROR( L, "To initialize buffer with initial data, provide value type and array of values as the 2nd and 3rd parameters. ", NumArgs, " arguments is provided." ); + } + + m_ArrayLoader.LoadArray( L, 3, RawData ); + } + BufferData BuffData; + auto DataSize = static_cast(RawData.size()); + if( DataSize ) + { + if( BufferDesc.uiSizeInBytes == 0 ) + BufferDesc.uiSizeInBytes = DataSize; + if( DataSize != BufferDesc.uiSizeInBytes ) + { + SCRIPT_PARSING_ERROR( L, "Initial buffer data size (", DataSize, ") does not match the requested buffer size (", BufferDesc.uiSizeInBytes, "). " + "Do not specify uiSizeInBytes to have the buffer size calculated automatically." ); + } + BuffData.pData = RawData.data(); + BuffData.DataSize = DataSize; + } + + if( (BufferDesc.BindFlags & BIND_UNIFORM_BUFFER) && (BufferDesc.uiSizeInBytes % 16) ) + { + SCRIPT_PARSING_ERROR( L, "Uniform buffer size (", DataSize, ") is not multiple of 16." ); + } + + auto ppBuffer = reinterpret_cast(lua_newuserdata( L, sizeof( IBuffer* ) )); + *ppBuffer = nullptr; + m_pRenderDevice->CreateBuffer( BufferDesc, BuffData, ppBuffer ); + if( *ppBuffer == nullptr ) + SCRIPT_PARSING_ERROR( L, "Failed to create buffer" ) + + CHECK_LUA_STACK_HEIGHT( +1 ); + } + + int BufferParser::SetVertexBuffers( lua_State *L ) + { + auto NumArgs = lua_gettop( L ); + + int CurrArgInd = 1; + + Int32 StartSlot = 0; + if( lua_type( L, CurrArgInd ) == LUA_TNUMBER ) + { + StartSlot = ReadValueFromLua( L, CurrArgInd++ ); + if( StartSlot < 0 ) + { + SCRIPT_PARSING_ERROR( L, "Start slot (", StartSlot, " provided) must be in range 0..", MaxBufferSlots - 1 ); + } + } + + Uint32 Flags = 0; + Uint32 NumBuffers = 0; + IBuffer *pBuffs[MaxBufferSlots] = {}; + Uint32 Offsets[MaxBufferSlots] = {}; + Uint32 Strides[MaxBufferSlots] = {}; + while( CurrArgInd <= NumArgs ) + { + if( StartSlot + (NumBuffers + 1) > MaxBufferSlots ) + { + SCRIPT_PARSING_ERROR( L, "Too many buffer slots (", StartSlot, "..", StartSlot + NumBuffers - 1, ") are being set. Allowed slots are 0..", MaxBufferSlots - 1 ); + break; + } + + if( lua_type( L, CurrArgInd ) != LUA_TNIL ) + pBuffs[NumBuffers] = *GetUserData( L, CurrArgInd++, m_MetatableRegistryName.c_str() ); + else + { + ++CurrArgInd; + pBuffs[NumBuffers] = nullptr; + } + + if( lua_type( L, CurrArgInd ) == LUA_TNUMBER ) + Offsets[NumBuffers] = ReadValueFromLua( L, CurrArgInd++ ); + else + Offsets[NumBuffers] = 0; + + if( lua_type( L, CurrArgInd ) == LUA_TNUMBER ) + Strides[NumBuffers] = ReadValueFromLua( L, CurrArgInd++ ); + else + Strides[NumBuffers] = 0; + + // The last argument may be flags + if( CurrArgInd == NumArgs && + (lua_type( L, CurrArgInd ) == LUA_TSTRING || + lua_type( L, CurrArgInd ) == LUA_TTABLE ) ) + { + VERIFY( Flags == 0, "Flags have already been set!" ); + FlagsLoader SetVBFlagsLoader(0, "SetVBFlags", m_SetVBFlagEnumMapping); + SetVBFlagsLoader.SetValue( L, CurrArgInd, &Flags ); + ++CurrArgInd; + } + + ++NumBuffers; + } + + auto *pContext = LoadDeviceContextFromRegistry( L ); + pContext->SetVertexBuffers( StartSlot, NumBuffers, pBuffs, Strides, Offsets, Flags ); + + // Return no values to Lua + return 0; + } + + int BufferParser::SetIndexBuffer( lua_State *L ) + { + auto *pIndexBuff = *GetUserData( L, 1, m_MetatableRegistryName.c_str() ); + Uint32 Offset = 0; + auto NumArgs = lua_gettop( L ); + if( NumArgs > 2 ) + { + SCRIPT_PARSING_ERROR( L, "SetIndexBuffer() expects offset as optional 2nd parameter. ", NumArgs, " arguments are provided." ); + } + if( lua_isnumber( L, 2 ) ) + Offset = ReadValueFromLua( L, 2 ); + auto *pContext = LoadDeviceContextFromRegistry( L ); + pContext->SetIndexBuffer( pIndexBuff, Offset ); + + // Return no values to Lua + return 0; + } +} diff --git a/RenderScript/src/BufferViewParser.cpp b/RenderScript/src/BufferViewParser.cpp new file mode 100644 index 0000000..c86bace --- /dev/null +++ b/RenderScript/src/BufferViewParser.cpp @@ -0,0 +1,105 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "BufferViewParser.h" +#include "BufferParser.h" +#include "SamplerParser.h" + +namespace Diligent +{ + const Char* BufferViewParser::BufferViewLibName = "BufferView"; + + BufferViewParser::BufferViewParser( BufferParser *pBufParser, + IRenderDevice *pRenderDevice, + lua_State *L ) : + EngineObjectParserCommon( pRenderDevice, L, BufferViewLibName ), + m_BufferLibMetatableName(pBufParser->GetMetatableName()), + m_CreateViewBinding( this, L, m_BufferLibMetatableName.c_str(), "CreateView", &BufferViewParser::CreateView ), + m_GetDefaultViewBinding( this, L, m_BufferLibMetatableName.c_str(), "GetDefaultView", &BufferViewParser::GetDefaultView ), + m_ViewTypeParser( 0, "ViewType", m_ViewTypeEnumMapping ) + { + DEFINE_BUFFERED_STRING_BINDER( m_Bindings, SBuffViewDescWrapper, Name, NameBuffer ); + + DEFINE_ENUM_ELEMENT_MAPPING( m_ViewTypeEnumMapping, BUFFER_VIEW_SHADER_RESOURCE ); + DEFINE_ENUM_ELEMENT_MAPPING( m_ViewTypeEnumMapping, BUFFER_VIEW_UNORDERED_ACCESS ); + VERIFY( m_ViewTypeEnumMapping.m_Str2ValMap.size() == BUFFER_VIEW_NUM_VIEWS - 1, + "Unexpected map size. Did you update BUFFER_VIEW_TYPE enum?" ); + VERIFY( m_ViewTypeEnumMapping.m_Val2StrMap.size() == BUFFER_VIEW_NUM_VIEWS - 1, + "Unexpected map size. Did you update BUFFER_VIEW_TYPE enum?" ); + DEFINE_ENUM_BINDER( m_Bindings, SBuffViewDescWrapper, ViewType, BUFFER_VIEW_TYPE, m_ViewTypeEnumMapping ); + + DEFINE_BINDER( m_Bindings, SBuffViewDescWrapper, ByteOffset, Uint32, Validator() ); + DEFINE_BINDER( m_Bindings, SBuffViewDescWrapper, ByteWidth, Uint32, Validator() ); + }; + + void BufferViewParser::CreateObj( lua_State *L ) + { + INIT_LUA_STACK_TRACKING(L); + + auto *pBuffer = *GetUserData( L, 1, m_BufferLibMetatableName.c_str() ); + + SBuffViewDescWrapper BufferViewDesc; + ParseLuaTable( L, 2, &BufferViewDesc, m_Bindings ); + CHECK_LUA_STACK_HEIGHT(); + + auto ppBufferView = reinterpret_cast(lua_newuserdata( L, sizeof( IBufferView* ) )); + *ppBufferView = nullptr; + pBuffer->CreateView( BufferViewDesc, ppBufferView ); + if( *ppBufferView == nullptr ) + SCRIPT_PARSING_ERROR(L, "Failed to create buffer view") + + CHECK_LUA_STACK_HEIGHT( +1 ); + } + + int BufferViewParser::CreateView( lua_State *L ) + { + // Note that LuaCreate is a static function. + // However, this pointer to the BufferViewParser object + // is stored in the upvalue. So LuaCreate will call + // BufferViewParser::CreateObj() + return LuaCreate(L); + } + + int BufferViewParser::GetDefaultView( lua_State *L ) + { + INIT_LUA_STACK_TRACKING( L ); + + // Buffer should be the first argument + auto *pBuffer = *GetUserData( L, 1, m_BufferLibMetatableName.c_str() ); + + // View type should be the second argument + BUFFER_VIEW_TYPE ViewType; + m_ViewTypeParser.SetValue( L, 2, &ViewType ); + + auto pView = pBuffer->GetDefaultView( ViewType ); + + // Push existing object + PushObject(L, pView); + + CHECK_LUA_STACK_HEIGHT( +1 ); + + // Returning one value to Lua + return 1; + } +} diff --git a/RenderScript/src/DepthStencilStateParser.cpp b/RenderScript/src/DepthStencilStateParser.cpp new file mode 100644 index 0000000..4f95623 --- /dev/null +++ b/RenderScript/src/DepthStencilStateParser.cpp @@ -0,0 +1,127 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "DepthStencilStateParser.h" + +namespace std +{ + DEFINE_ENUM_HASH( Diligent::STENCIL_OP ) +} + +namespace Diligent +{ + const Char* DepthStencilStateParser::DepthStencilStateLibName = "DepthStencilState"; + + template<> + class MemberBinder : public MemberBinderBase + { + public: + MemberBinder( size_t MemberOffset, size_t Dummy ) : + MemberBinderBase( MemberOffset ) + { + DEFINE_ENUM_ELEMENT_MAPPING( m_StencilOpEnumMapping, STENCIL_OP_KEEP ); + DEFINE_ENUM_ELEMENT_MAPPING( m_StencilOpEnumMapping, STENCIL_OP_ZERO ); + DEFINE_ENUM_ELEMENT_MAPPING( m_StencilOpEnumMapping, STENCIL_OP_REPLACE ); + DEFINE_ENUM_ELEMENT_MAPPING( m_StencilOpEnumMapping, STENCIL_OP_INCR_SAT ); + DEFINE_ENUM_ELEMENT_MAPPING( m_StencilOpEnumMapping, STENCIL_OP_DECR_SAT ); + DEFINE_ENUM_ELEMENT_MAPPING( m_StencilOpEnumMapping, STENCIL_OP_INVERT ); + DEFINE_ENUM_ELEMENT_MAPPING( m_StencilOpEnumMapping, STENCIL_OP_INCR_WRAP ); + DEFINE_ENUM_ELEMENT_MAPPING( m_StencilOpEnumMapping, STENCIL_OP_DECR_WRAP ); + VERIFY( m_StencilOpEnumMapping.m_Str2ValMap.size() == STENCIL_OP_NUM_OPS - 1, + "Unexpected map size. Did you update STENCIL_OP enum?" ); + VERIFY( m_StencilOpEnumMapping.m_Val2StrMap.size() == STENCIL_OP_NUM_OPS - 1, + "Unexpected map size. Did you update STENCIL_OP enum?" ); + + DEFINE_ENUM_BINDER( m_Bindings, StencilOpDesc, StencilFailOp, STENCIL_OP, m_StencilOpEnumMapping ) + DEFINE_ENUM_BINDER( m_Bindings, StencilOpDesc, StencilDepthFailOp, STENCIL_OP, m_StencilOpEnumMapping ) + DEFINE_ENUM_BINDER( m_Bindings, StencilOpDesc, StencilPassOp, STENCIL_OP, m_StencilOpEnumMapping ) + DEFINE_ENUM_BINDER( m_Bindings, StencilOpDesc, StencilFunc, COMPARISON_FUNCTION, m_CmpFuncEnumMapping ) + } + + virtual void GetValue( lua_State *L, const void* pBasePointer ) + { + const auto &StOpDesc = GetMemberByOffest< StencilOpDesc >(pBasePointer, m_MemberOffset); + PushLuaTable( L, &StOpDesc, m_Bindings ); + } + + virtual void SetValue( lua_State *L, int Index, void* pBasePointer ) + { + auto &StOpDesc = GetMemberByOffest< StencilOpDesc >( pBasePointer, m_MemberOffset ); + ParseLuaTable( L, Index, &StOpDesc, m_Bindings ); + } + + private: + BindingsMapType m_Bindings; + ComparisonFuncEnumMapping m_CmpFuncEnumMapping; + EnumMapping < STENCIL_OP > m_StencilOpEnumMapping; + }; + + DepthStencilStateParser::DepthStencilStateParser( IRenderDevice *pRenderDevice, lua_State *L ) : + EngineObjectParserCommon( pRenderDevice, L, DepthStencilStateLibName ), + m_SetDepthStencilBinding( this, L, "Context", "SetDepthStencilState", &DepthStencilStateParser::SetDepthStencilState ) + { + DEFINE_BUFFERED_STRING_BINDER( m_Bindings, SDSSDescWrapper, Name, NameBuffer ) + + DEFINE_BINDER( m_Bindings, SDSSDescWrapper, DepthEnable, Bool, Validator() ) + DEFINE_BINDER( m_Bindings, SDSSDescWrapper, DepthWriteEnable, Bool, Validator() ) + DEFINE_ENUM_BINDER( m_Bindings, SDSSDescWrapper, DepthFunc, COMPARISON_FUNCTION, m_CmpFuncEnumMapping ) + + DEFINE_BINDER( m_Bindings, SDSSDescWrapper, StencilEnable, Bool, Validator() ) + DEFINE_BINDER( m_Bindings, SDSSDescWrapper, StencilReadMask, Uint8, Validator() ) + DEFINE_BINDER( m_Bindings, SDSSDescWrapper, StencilWriteMask, Uint8, Validator() ) + DEFINE_BINDER( m_Bindings, SDSSDescWrapper, FrontFace, StencilOpDesc, 0 ) + DEFINE_BINDER( m_Bindings, SDSSDescWrapper, BackFace, StencilOpDesc, 0 ) + }; + + void DepthStencilStateParser::CreateObj( lua_State *L ) + { + INIT_LUA_STACK_TRACKING( L ); + + SDSSDescWrapper DepthStencilDesc; + ParseLuaTable( L, 1, &DepthStencilDesc, m_Bindings ); + + CHECK_LUA_STACK_HEIGHT(); + + auto ppDepthStencilState = reinterpret_cast(lua_newuserdata( L, sizeof( IDepthStencilState* ) )); + *ppDepthStencilState = nullptr; + m_pRenderDevice->CreateDepthStencilState( DepthStencilDesc, ppDepthStencilState ); + if( *ppDepthStencilState == nullptr ) + SCRIPT_PARSING_ERROR(L, "Failed to create depth stencil state") + + CHECK_LUA_STACK_HEIGHT( +1 ); + } + + int DepthStencilStateParser::SetDepthStencilState( lua_State *L ) + { + auto pVertDesc = *GetUserData( L, 1, m_MetatableRegistryName.c_str() ); + Uint8 StencilRef = 0; + if( lua_gettop( L ) > 1 ) + { + StencilRef = ReadValueFromLua( L, 2 ); + } + auto *pContext = LoadDeviceContextFromRegistry( L ); + pContext->SetDepthStencilState( pVertDesc, StencilRef ); + return 0; + } +} diff --git a/RenderScript/src/DeviceContextFuncBindings.cpp b/RenderScript/src/DeviceContextFuncBindings.cpp new file mode 100644 index 0000000..9525cf2 --- /dev/null +++ b/RenderScript/src/DeviceContextFuncBindings.cpp @@ -0,0 +1,145 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "DeviceContextFuncBindings.h" +#include "GraphicsUtilities.h" +#include "TextureViewParser.h" +#include "EngineObjectParserBase.h" + +namespace Diligent +{ + DeviceContextFuncBindings::DeviceContextFuncBindings( IRenderDevice *pRenderDevice, lua_State *L, TextureViewParser *pTexViewPasrser ) : + m_SetRenderTargetsBinding(this, L, "Context", "SetRenderTargets", &DeviceContextFuncBindings::SetRenderTargets), + m_ClearRenderTargetBinding(this, L, "Context", "ClearRenderTarget", &DeviceContextFuncBindings::ClearRenderTarget), + m_ClearDepthStencilBinding(this, L, "Context", "ClearDepthStencil", &DeviceContextFuncBindings::ClearDepthStencil), + m_TexViewMetatableName( pTexViewPasrser->GetMetatableName() ) + { + }; + + int DeviceContextFuncBindings::SetRenderTargets( lua_State *L ) + { + auto NumArgs = lua_gettop( L ); + ITextureView *pRTVs[MaxRenderTargets] = {}; + ITextureView *pDSV = nullptr; + Uint32 NumRTs = 0; + for( int CurrArg = 1; CurrArg <= NumArgs; ++CurrArg ) + { + auto *pView = *GetUserData( L, CurrArg, m_TexViewMetatableName.c_str() ); + auto ViewType = pView->GetDesc().ViewType; + if( ViewType == TEXTURE_VIEW_RENDER_TARGET ) + { + if( NumRTs < MaxRenderTargets ) + { + pRTVs[NumRTs] = pView; + ++NumRTs; + } + else + { + SCRIPT_PARSING_ERROR( L, "Too many render targets are being set. ", MaxRenderTargets, " at most are allowed." ); + } + } + else if( ViewType == TEXTURE_VIEW_DEPTH_STENCIL ) + { + if( pDSV != nullptr ) + SCRIPT_PARSING_ERROR( L, "Respecifying depth stencil view. Only one is allowed" ); + pDSV = pView; + } + else + { + SCRIPT_PARSING_ERROR( L, "Unexpected view type. Only render target and depth stencil are allowed" ); + } + } + + auto *pContext = EngineObjectParserBase::LoadDeviceContextFromRegistry( L ); + pContext->SetRenderTargets( NumRTs, pRTVs, pDSV ); + + // Return no values to Lua + return 0; + } + + int DeviceContextFuncBindings::ClearRenderTarget( lua_State *L ) + { + auto NumArgs = lua_gettop( L ); + + ITextureView *pView = nullptr; + Float32 RGBA[4] = {}; + + int CurrArg = 1; + if( CurrArg <= NumArgs ) + { + if( lua_type( L, CurrArg ) == LUA_TUSERDATA ) + { + pView = *GetUserData( L, CurrArg, m_TexViewMetatableName.c_str() ); + ++CurrArg; + } + } + for( int c = 0; c < 4 && CurrArg <= NumArgs; ++c, ++CurrArg ) + { + RGBA[c] = ReadValueFromLua( L, CurrArg ); + } + auto *pContext = EngineObjectParserBase::LoadDeviceContextFromRegistry( L ); + pContext->ClearRenderTarget( pView, RGBA ); + + return 0; + } + + int DeviceContextFuncBindings::ClearDepthStencil( lua_State *L ) + { + auto NumArgs = lua_gettop( L ); + + ITextureView *pView = nullptr; + Float32 fDepth = 1.f; + Uint8 Stencil = 0; + Uint32 ClearFlags = 0; + + int CurrArg = 1; + if( CurrArg <= NumArgs ) + { + if( lua_type( L, CurrArg ) == LUA_TUSERDATA ) + { + pView = *GetUserData( L, CurrArg, m_TexViewMetatableName.c_str() ); + ++CurrArg; + } + } + + if( CurrArg <= NumArgs ) + { + fDepth = ReadValueFromLua( L, CurrArg ); + ClearFlags |= CLEAR_DEPTH_FLAG; + ++CurrArg; + } + + if( CurrArg <= NumArgs ) + { + Stencil = ReadValueFromLua( L, CurrArg ); + ClearFlags |= CLEAR_STENCIL_FLAG; + ++CurrArg; + } + + auto *pContext = EngineObjectParserBase::LoadDeviceContextFromRegistry( L ); + pContext->ClearDepthStencil( pView, ClearFlags, fDepth, Stencil ); + + return 0; + } +} diff --git a/RenderScript/src/DrawAttribsParser.cpp b/RenderScript/src/DrawAttribsParser.cpp new file mode 100644 index 0000000..a1d9d3e --- /dev/null +++ b/RenderScript/src/DrawAttribsParser.cpp @@ -0,0 +1,146 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "DrawAttribsParser.h" +#include "BufferParser.h" + +namespace Diligent +{ + const Char* DrawAttribsParser::DrawAttribsLibName = "DrawAttribs"; + + DrawAttribsParser::DrawAttribsParser( BufferParser *pBuffParser, IRenderDevice *pRenderDevice, lua_State *L ) : + EngineObjectParserBase( pRenderDevice, L, DrawAttribsLibName ), + m_DrawBinding( this, L, "Context", "Draw", &DrawAttribsParser::Draw ), + m_DispatchComputeBinding( this, L, "Context", "DispatchCompute", &DrawAttribsParser::DispatchCompute ), + m_BufferMetatableName(pBuffParser->GetMetatableName()) + { + DEFINE_ENUM_ELEMENT_MAPPING( m_PrimTopologyEnumMapping, PRIMITIVE_TOPOLOGY_TRIANGLE_LIST ); + DEFINE_ENUM_ELEMENT_MAPPING( m_PrimTopologyEnumMapping, PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP ); + DEFINE_ENUM_ELEMENT_MAPPING( m_PrimTopologyEnumMapping, PRIMITIVE_TOPOLOGY_POINT_LIST ); + DEFINE_ENUM_ELEMENT_MAPPING( m_PrimTopologyEnumMapping, PRIMITIVE_TOPOLOGY_LINE_LIST ); + VERIFY( m_PrimTopologyEnumMapping.m_Str2ValMap.size() == PRIMITIVE_TOPOLOGY_NUM_TOPOLOGIES - 1, + "Unexpected map size. Did you update PRIMITIVE_TOPOLOGY enum?" ); + VERIFY( m_PrimTopologyEnumMapping.m_Val2StrMap.size() == PRIMITIVE_TOPOLOGY_NUM_TOPOLOGIES - 1, + "Unexpected map size. Did you update PRIMITIVE_TOPOLOGY enum?" ); + DEFINE_ENUM_BINDER( m_Bindings, DrawAttribs, Topology, PRIMITIVE_TOPOLOGY, m_PrimTopologyEnumMapping ); + + // NumVertices and NumIndices are in Union + DEFINE_BINDER( m_Bindings, DrawAttribs, NumVertices, Uint32, Validator() ); + DEFINE_BINDER( m_Bindings, DrawAttribs, NumIndices, Uint32, Validator() ); + + DEFINE_ENUM_ELEMENT_MAPPING( m_ValueTypeEnumMapping, VT_UINT16 ); + DEFINE_ENUM_ELEMENT_MAPPING( m_ValueTypeEnumMapping, VT_UINT32 ); + DEFINE_ENUM_BINDER( m_Bindings, DrawAttribs, IndexType, VALUE_TYPE, m_ValueTypeEnumMapping ); + + DEFINE_BINDER( m_Bindings, DrawAttribs, IsIndexed, Bool, Validator() ); + DEFINE_BINDER( m_Bindings, DrawAttribs, NumInstances, Uint32, Validator() ); + DEFINE_BINDER( m_Bindings, DrawAttribs, IsIndirect, Bool, Validator() ); + DEFINE_BINDER( m_Bindings, DrawAttribs, BaseVertex, Uint32, Validator() ); + DEFINE_BINDER( m_Bindings, DrawAttribs, IndirectDrawArgsOffset, Uint32, Validator() ); + + // StartVertexLocation and FirstIndexLocation are in union + DEFINE_BINDER( m_Bindings, DrawAttribs, StartVertexLocation, Uint32, Validator() ); + DEFINE_BINDER( m_Bindings, DrawAttribs, FirstIndexLocation, Uint32, Validator() ); + + DEFINE_BINDER( m_Bindings, DrawAttribs, FirstInstanceLocation, Uint32, Validator() ); + + std::vector AllowedMetatable = { "Metatables.Buffer" }; + DEFINE_BINDER( m_Bindings, DrawAttribs, pIndirectDrawAttribs, EngineObjectPtrLoader, AllowedMetatable ); + }; + + void DrawAttribsParser::CreateObj( lua_State *L ) + { + INIT_LUA_STACK_TRACKING(L); + + DrawAttribs DrawAttrs; + ParseLuaTable( L, 1, &DrawAttrs, m_Bindings ); + + CHECK_LUA_STACK_HEIGHT(); + + auto pDrawAttribs = reinterpret_cast(lua_newuserdata( L, sizeof( DrawAttribs ) )); + memcpy(pDrawAttribs, &DrawAttrs, sizeof(DrawAttribs)); + + CHECK_LUA_STACK_HEIGHT( +1 ); + } + + void DrawAttribsParser::DestroyObj( void *pData ) + { + // We do not need to do anything, because the whole object is + // created as full user data and thus managed by Lua + } + + void DrawAttribsParser::ReadField( lua_State *L, void *pData, const Char *Field ) + { + auto pDrawAttribs = reinterpret_cast(pData); + PushField( L, pDrawAttribs, Field, m_Bindings ); + } + + void DrawAttribsParser::UpdateField( lua_State *L, void *pData, const Char *Field ) + { + auto pDrawAttribs = reinterpret_cast(pData); + Diligent::UpdateField( L, -1, pDrawAttribs, Field, m_Bindings ); + } + + void DrawAttribsParser::PushExistingObject( lua_State *L, const void *pObject ) + { + auto pDrawAttribs = reinterpret_cast(lua_newuserdata( L, sizeof( DrawAttribs ) )); + memcpy( pDrawAttribs, pObject, sizeof( DrawAttribs ) ); + } + + int DrawAttribsParser::Draw( lua_State *L ) + { + auto pDrawAttribs = GetUserData( L, 1, m_MetatableRegistryName.c_str() ); + auto *pContext = LoadDeviceContextFromRegistry( L ); + pContext->Draw( *pDrawAttribs ); + + return 0; + } + + int DrawAttribsParser::DispatchCompute( lua_State *L ) + { + DispatchComputeAttribs DispatchAttrs; + if( lua_type( L, 1 ) == LUA_TUSERDATA ) + { + DispatchAttrs.pIndirectDispatchAttribs = *GetUserData( L, 1, m_BufferMetatableName.c_str() ); + if( lua_gettop( L ) > 1 ) + { + DispatchAttrs.DispatchArgsByteOffset = ReadValueFromLua( L, 2 ); + } + } + else + { + if( lua_gettop( L ) >= 1 ) + DispatchAttrs.ThreadGroupCountX = ReadValueFromLua( L, 1 ); + if( lua_gettop( L ) >= 2 ) + DispatchAttrs.ThreadGroupCountY = ReadValueFromLua( L, 2 ); + if( lua_gettop( L ) >= 3 ) + DispatchAttrs.ThreadGroupCountY = ReadValueFromLua( L, 3 ); + } + + auto *pContext = LoadDeviceContextFromRegistry( L ); + pContext->DispatchCompute( DispatchAttrs ); + + return 0; + } +} diff --git a/RenderScript/src/EngineObjectParserBase.cpp b/RenderScript/src/EngineObjectParserBase.cpp new file mode 100644 index 0000000..5790e60 --- /dev/null +++ b/RenderScript/src/EngineObjectParserBase.cpp @@ -0,0 +1,271 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "EngineObjectParserBase.h" +#include "ScriptParser.h" + +using namespace Diligent; + +namespace Diligent +{ + EngineObjectParserBase::EngineObjectParserBase( IRenderDevice *pRenderDevice, lua_State *L, const Char *LibName ) : + m_pRenderDevice( pRenderDevice ), + m_LibName( LibName ), + m_MetatableRegistryName( String( "Metatables." ) + m_LibName ) + { + // TODO: remove this function, move everything to ctor + RegisterTable( L ); + } + + int EngineObjectParserBase::LuaCreate( lua_State *L ) + { + INIT_LUA_STACK_TRACKING( L ); + + EngineObjectParserBase *This = static_cast(lua_touserdata( L, lua_upvalueindex( 1 ) )); + // This pointer cannot be null because we stored it in an up value when created the library + VERIFY( This, "This pointer is null" ); + if( !This )return 0; + + try + { + This->CreateObj( L ); + } + catch( const std::runtime_error &err ) + { + SCRIPT_PARSING_ERROR( L, "Failed to create ", This->m_LibName, " object: \n", err.what() ); + } + + // Push onto the stack the metatable associated with name given in the registry + luaL_getmetatable( L, This->m_MetatableRegistryName.c_str() ); // -0 | +1 -> +1 + // Pop a table from the top of the stack and set it as the new metatable + // for the value at the given index (which is where the new user datum is) + lua_setmetatable( L, -2 ); // -1 | +0 -> -1 + + CHECK_LUA_STACK_HEIGHT( +1 ); + + // Return number of return arguments + // New userdatum is on the top of the stack + return 1; + } + + int EngineObjectParserBase::LuaGC( lua_State *L ) + { + INIT_LUA_STACK_TRACKING( L ); + + EngineObjectParserBase *This = static_cast(lua_touserdata( L, lua_upvalueindex( 1 ) )); + // This pointer cannot be null because we stored it in an up value when created the library + VERIFY( This, "This pointer is null" ); + if( !This )return 0; + + // Do not throw exception as this function can be called from dtor! + //auto pData = GetUserData( L, 1, This->m_MetatableRegistryName.c_str() ); + auto pData = reinterpret_cast(luaL_testudata( L, 1, This->m_MetatableRegistryName.c_str() )); + if( pData ) + { + This->DestroyObj( pData ); + } + + CHECK_LUA_STACK_HEIGHT(); + + return 0; + } + + int EngineObjectParserBase::LuaIndex( lua_State *L ) + { + INIT_LUA_STACK_TRACKING( L ); + + // Whenever Lua calls C, the called function gets a new stack, which is independent + // of previous stacks and of stacks of C functions that are still active. This stack + // initially contains any arguments to the C function and it is where the C function + // pushes its results to be returned to the calle + + + // Note that the syntax var.Name is just syntactic sugar for var["Name"] + // The first parameter to the __index() function is the object and the second is + // the index + + EngineObjectParserBase *This = static_cast(lua_touserdata( L, lua_upvalueindex( 1 ) )); + // This pointer cannot be null because we stored it in an up value when created the library + VERIFY( This, "This pointer is null" ); + if( !This )return 0; + + auto pData = GetUserData( L, 1, This->m_MetatableRegistryName.c_str() ); + auto Field = ReadValueFromLua( L, 2 ); + + // First try to find the field in the metatable + // Push metatable onto the stack + luaL_getmetatable( L, This->m_MetatableRegistryName.c_str() ); // -0 | +1 -> +1 + // Duplicate key on the top of the stack + lua_pushvalue( L, -2 ); // -0 | +1 -> +1 + // Use rawget to avoid calling __index + lua_rawget( L, -2 ); // -1 | +1 -> +0 + // Remove metatable from the stack + lua_remove( L, -2 ); // -1 | +0 -> -1 + if( lua_type( L, -1 ) == LUA_TNIL ) + { + // Pop nil from the stack + lua_pop( L, 1 ); // -1 | +0 -> -1 + This->ReadField( L, pData, Field ); + } + else + { + // Value is on top of the stack + } + + CHECK_LUA_STACK_HEIGHT( +1 ); + + return 1; + } + + void EngineObjectParserBase::UpdateField( lua_State *L, void *pData, const Char *Field ) + { + SCRIPT_PARSING_ERROR( L, "Attempting to update \"", Field, "\" field of a read-only object \"", m_LibName.c_str(), '\"' ); + } + + int EngineObjectParserBase::LuaNewIndex( lua_State *L ) + { + INIT_LUA_STACK_TRACKING( L ); + + EngineObjectParserBase *This = static_cast(lua_touserdata( L, lua_upvalueindex( 1 ) )); + // This pointer cannot be null because we stored it in an up value when created the library + VERIFY( This, "This pointer is null" ); + if( !This )return 0; + + auto pData = GetUserData( L, 1, This->m_MetatableRegistryName.c_str() ); + auto Field = ReadValueFromLua( L, 2 ); + This->UpdateField( L, pData, Field ); + + CHECK_LUA_STACK_HEIGHT(); + + return 0; + } + + void EngineObjectParserBase::RegisterTable( lua_State *L ) + { + INIT_LUA_STACK_TRACKING( L ); + + // If the registry already has the key with the same name, luaL_newmetatable() returns 0. + // Otherwise, it creates a new table to be used as a metatable for userdata, adds it to the + // registry with key tname, and returns 1. In both cases it pushes onto the stack the final + // value associated with tname in the registry. + auto Created = luaL_newmetatable( L, m_MetatableRegistryName.c_str() ); // -0 | +1 -> +1 + VERIFY( Created, "Metatble with the same name already registered!" ); + + // http://lua-users.org/wiki/MetatableEvents + luaL_Reg MetaMethods[] = { + // An object is marked for finalization when its metatable is set and the metatable + // has a field indexed by the string "__gc". NOTE: if a metatable without a __gc field + // is set and that field is only later added to the metatable, the object will NOT be marked + // for finalization. + { "__gc", LuaGC }, + { "__index", LuaIndex }, + { "__newindex", LuaNewIndex }, + { NULL, NULL } + }; + + lua_pushlightuserdata( L, this ); // -0 | +1 -> +1 + + // Register all functions in the array into the table on the top of the stack + // When nup (last parameter) is not zero, all functions are created sharing nup upvalues, + // which must be previously pushed on the stack on top of the library table. + // These values are popped from the stack after the registration. + luaL_setfuncs( L, MetaMethods, 1 ); // -1 | +0 -> -1 + + // luaL_setfuncs() does the following for every function in the list: + //lua_pushstring( L, FuncName ); + //lua_pushlightuserdata( L, this ); + //lua_pushcclosure( L, Function, 1 ); + //lua_settable( L, -3 ); + + // Protect metatable from tampering in the script + // If __metatable field is set, then getmetatable() function returns + // what is stored in this field instead of the actual metatable + // and setmetatable() is not allowed to access it + lua_pushliteral( L, "__metatable" ); // -0 | +1 -> +1 + lua_pushliteral( L, "Metatable is not accessible!" ); // -0 | +1 -> +1 + // Note that lua_settable() may trigger a metamethod + // for the "newindex" event + lua_settable( L, -3 ); // -2 | +0 -> -2 + + // Pop metatable + lua_pop( L, 1 ); // -1 | +0 -> -1 + + CHECK_LUA_STACK_HEIGHT(); + + luaL_Reg Methods[] = { + { "Create", LuaCreate }, + { NULL, NULL } + }; + + // Create a new table with a size optimized to store all entries in the array Methods + // (but does not actually store them). + luaL_newlibtable( L, Methods ); // -0 | +1 -> +1 + + // Push pointer onto the stack + lua_pushlightuserdata( L, this ); // -0 | +1 -> +1 + + // Register all functions in the array into the table on the top of the stack + // When nup (last parameter) is not zero, all functions are created sharing nup upvalues, + // which must be previously pushed on the stack on top of the library table. + // These values are popped from the stack after the registration. + luaL_setfuncs( L, Methods, 1 ); // -1 | +0 -> -1 + + // Pop a value from the stack and set it as the new value of global name. + lua_setglobal( L, m_LibName.c_str() ); // -1 | +0 -> -1 + + CHECK_LUA_STACK_HEIGHT(); + } + + void EngineObjectParserBase::PushObject( lua_State *L, const void *pData ) + { + INIT_LUA_STACK_TRACKING( L ); + + if( pData ) + PushExistingObject( L, pData ); + else + lua_pushnil( L ); + + luaL_getmetatable( L, m_MetatableRegistryName.c_str() ); // -0 | +1 -> +1 + lua_setmetatable( L, -2 ); // -1 | +0 -> -1 + + CHECK_LUA_STACK_HEIGHT( +1 ); + } + + IDeviceContext* EngineObjectParserBase::LoadDeviceContextFromRegistry( lua_State *L ) + { + INIT_LUA_STACK_TRACKING( L ); + + lua_pushstring( L, ScriptParser::DeviceContextRegistryKey ); // -0 | +1 -> +1 + lua_gettable(L, LUA_REGISTRYINDEX ); // -1 | +1 -> +0 + CheckType( L, -1, LUA_TLIGHTUSERDATA ); + IDeviceContext* pContext = reinterpret_cast( lua_touserdata(L, -1) ); + lua_pop( L, 1 ); // -1 | +0 -> -1 + + VERIFY( pContext != nullptr, "Device context is null" ); + + CHECK_LUA_STACK_HEIGHT(); + + return pContext; + } +} diff --git a/RenderScript/src/EnumMappings.cpp b/RenderScript/src/EnumMappings.cpp new file mode 100644 index 0000000..3bc9349 --- /dev/null +++ b/RenderScript/src/EnumMappings.cpp @@ -0,0 +1,210 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "EnumMappings.h" + +using namespace std; + +namespace Diligent +{ + CpuAccessFlagEnumMapping::CpuAccessFlagEnumMapping() + { + DEFINE_ENUM_ELEMENT_MAPPING( (*this), CPU_ACCESS_READ ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), CPU_ACCESS_WRITE ); + } + + UsageEnumMapping::UsageEnumMapping() + { + DEFINE_ENUM_ELEMENT_MAPPING( (*this), USAGE_STATIC ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), USAGE_DEFAULT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), USAGE_DYNAMIC ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), USAGE_CPU_ACCESSIBLE ); + } + + TextureFormatEnumMapping::TextureFormatEnumMapping() + { + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RGBA32_TYPELESS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RGBA32_FLOAT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RGBA32_UINT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RGBA32_SINT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RGB32_TYPELESS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RGB32_FLOAT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RGB32_UINT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RGB32_SINT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RGBA16_TYPELESS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RGBA16_FLOAT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RGBA16_UNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RGBA16_UINT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RGBA16_SNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RGBA16_SINT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RG32_TYPELESS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RG32_FLOAT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RG32_UINT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RG32_SINT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_R32G8X24_TYPELESS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_D32_FLOAT_S8X24_UINT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_R32_FLOAT_X8X24_TYPELESS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_X32_TYPELESS_G8X24_UINT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RGB10A2_TYPELESS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RGB10A2_UNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RGB10A2_UINT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_R11G11B10_FLOAT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RGBA8_TYPELESS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RGBA8_UNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RGBA8_UNORM_SRGB ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RGBA8_UINT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RGBA8_SNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RGBA8_SINT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RG16_TYPELESS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RG16_FLOAT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RG16_UNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RG16_UINT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RG16_SNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RG16_SINT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_R32_TYPELESS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_D32_FLOAT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_R32_FLOAT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_R32_UINT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_R32_SINT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_R24G8_TYPELESS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_D24_UNORM_S8_UINT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_R24_UNORM_X8_TYPELESS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_X24_TYPELESS_G8_UINT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RG8_TYPELESS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RG8_UNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RG8_UINT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RG8_SNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RG8_SINT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_R16_TYPELESS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_R16_FLOAT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_D16_UNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_R16_UNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_R16_UINT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_R16_SNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_R16_SINT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_R8_TYPELESS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_R8_UNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_R8_UINT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_R8_SNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_R8_SINT ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_A8_UNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_R1_UNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RGB9E5_SHAREDEXP ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_RG8_B8G8_UNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_G8R8_G8B8_UNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BC1_TYPELESS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BC1_UNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BC1_UNORM_SRGB ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BC2_TYPELESS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BC2_UNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BC2_UNORM_SRGB ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BC3_TYPELESS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BC3_UNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BC3_UNORM_SRGB ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BC4_TYPELESS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BC4_UNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BC4_SNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BC5_TYPELESS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BC5_UNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BC5_SNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_B5G6R5_UNORM ); // Deprecated format, unavailable in D3D11+ + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_B5G5R5A1_UNORM ); // Deprecated format, unavailable in D3D11+ + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BGRA8_UNORM ); // Deprecated format, unavailable in D3D11+ + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BGRX8_UNORM ); // Deprecated format, unavailable in D3D11+ + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_R10G10B10_XR_BIAS_A2_UNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BGRA8_TYPELESS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BGRA8_UNORM_SRGB ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BGRX8_TYPELESS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BGRX8_UNORM_SRGB ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BC6H_TYPELESS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BC6H_UF16 ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BC6H_SF16 ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BC7_TYPELESS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BC7_UNORM ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEX_FORMAT_BC7_UNORM_SRGB ); + static_assert(TEX_FORMAT_NUM_FORMATS == TEX_FORMAT_BC7_UNORM_SRGB + 1, "Not all texture formats initialized."); + VERIFY( m_Str2ValMap.size() == TEX_FORMAT_NUM_FORMATS - 1, + "Unexpected map size. Did you update TEXTURE_FORMAT enum?" ); + VERIFY( m_Val2StrMap.size() == TEX_FORMAT_NUM_FORMATS - 1, + "Unexpected map size. Did you update TEXTURE_FORMAT enum?" ); + } + + TextureTypeEnumMapping::TextureTypeEnumMapping() + { + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEXTURE_TYPE_1D ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEXTURE_TYPE_1D_ARRAY ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEXTURE_TYPE_2D ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEXTURE_TYPE_2D_ARRAY ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEXTURE_TYPE_3D ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEXTURE_TYPE_CUBE ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), TEXTURE_TYPE_CUBE_ARRAY ); + static_assert(TEXTURE_TYPE_NUM_TYPES == TEXTURE_TYPE_CUBE_ARRAY + 1, "Not all texture types initialized."); + VERIFY( m_Str2ValMap.size() == TEXTURE_TYPE_NUM_TYPES - 1, + "Unexpected map size. Did you update TEXTURE_TYPE enum?" ); + VERIFY( m_Val2StrMap.size() == TEXTURE_TYPE_NUM_TYPES - 1, + "Unexpected map size. Did you update TEXTURE_TYPE enum?" ); + } + + ValueTypeEnumMapping::ValueTypeEnumMapping() + { + DEFINE_ENUM_ELEMENT_MAPPING( (*this), VT_UNDEFINED ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), VT_INT8 ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), VT_INT16 ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), VT_INT32 ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), VT_UINT8 ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), VT_UINT16 ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), VT_UINT32 ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), VT_FLOAT16 ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), VT_FLOAT32 ); + static_assert(VT_NUM_TYPES == VT_FLOAT32 + 1, "Not all value types initialized."); + VERIFY( m_Str2ValMap.size() == VT_NUM_TYPES, + "Unexpected map size. Did you update VALUE_TYPE enum?" ); + VERIFY( m_Val2StrMap.size() == VT_NUM_TYPES, + "Unexpected map size. Did you update VALUE_TYPE enum?" ); + } + + ComparisonFuncEnumMapping::ComparisonFuncEnumMapping() + { + DEFINE_ENUM_ELEMENT_MAPPING( (*this), COMPARISON_FUNC_NEVER ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), COMPARISON_FUNC_LESS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), COMPARISON_FUNC_EQUAL ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), COMPARISON_FUNC_LESS_EQUAL ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), COMPARISON_FUNC_GREATER ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), COMPARISON_FUNC_NOT_EQUAL ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), COMPARISON_FUNC_GREATER_EQUAL ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), COMPARISON_FUNC_ALWAYS ); + static_assert(COMPARISON_FUNC_NUM_FUNCTIONS == COMPARISON_FUNC_ALWAYS + 1, "Not all comparison functions initialized."); + VERIFY( m_Str2ValMap.size() == COMPARISON_FUNC_NUM_FUNCTIONS - 1, + "Unexpected map size. Did you update COMPARISON_FUNCTION enum?" ); + VERIFY( m_Val2StrMap.size() == COMPARISON_FUNC_NUM_FUNCTIONS - 1, + "Unexpected map size. Did you update COMPARISON_FUNCTION enum?" ); + } + + BindShaderResourcesFlagEnumMapping::BindShaderResourcesFlagEnumMapping() + { + DEFINE_ENUM_ELEMENT_MAPPING( (*this), BIND_SHADER_RESOURCES_RESET_BINDINGS ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), BIND_SHADER_RESOURCES_UPDATE_UNRESOLVED ); + DEFINE_ENUM_ELEMENT_MAPPING( (*this), BIND_SHADER_RESOURCES_ALL_RESOLVED ); + } +} diff --git a/RenderScript/src/LayoutDescParser.cpp b/RenderScript/src/LayoutDescParser.cpp new file mode 100644 index 0000000..a5bbda1 --- /dev/null +++ b/RenderScript/src/LayoutDescParser.cpp @@ -0,0 +1,151 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "LayoutDescParser.h" + +namespace std +{ + DEFINE_ENUM_HASH( Diligent::LayoutElement::FREQUENCY ) +} + +namespace Diligent +{ + const Char* LayoutDescParser::LayoutDescLibName = "LayoutDesc"; + + class LayoutElementLoader; // Used only as a template switch + + template<> + class MemberBinder : public MemberBinderBase + { + public: + MemberBinder( size_t LayoutElementsOffset, size_t ElementsBufferOffset, size_t NumElementsOffset ) : + MemberBinderBase( ElementsBufferOffset ), + m_LayoutElementsOffset(LayoutElementsOffset), + m_NumElementsOffset(NumElementsOffset) + { + DEFINE_BINDER( m_Bindings, LayoutElement, InputIndex, Uint32, Validator( "Input Index", 0, 32 ) ) + DEFINE_BINDER( m_Bindings, LayoutElement, BufferSlot, Uint32, Validator( "Buffer Slot", 0, MaxBufferSlots ) ) + DEFINE_BINDER( m_Bindings, LayoutElement, NumComponents, Uint32, Validator( "Num Components", 1, 4 ) ) + + DEFINE_ENUM_BINDER( m_Bindings, LayoutElement, ValueType, VALUE_TYPE, m_ValueTypeEnumMapping ) + + DEFINE_BINDER( m_Bindings, LayoutElement, IsNormalized, Bool, Validator() ) + DEFINE_BINDER( m_Bindings, LayoutElement, RelativeOffset, Uint32, Validator() ) + + + m_FrequencyEnumMapping.AddMapping( "FREQUENCY_PER_VERTEX", LayoutElement::FREQUENCY_PER_VERTEX ); + m_FrequencyEnumMapping.AddMapping( "FREQUENCY_PER_INSTANCE", LayoutElement::FREQUENCY_PER_INSTANCE ); + VERIFY( m_FrequencyEnumMapping.m_Str2ValMap.size() == LayoutElement::FREQUENCY_NUM_FREQUENCIES - 1, + "Unexpected map size. Did you update LayoutElement::FREQUENCY_PER_VERTEX enum?" ); + VERIFY( m_FrequencyEnumMapping.m_Val2StrMap.size() == LayoutElement::FREQUENCY_NUM_FREQUENCIES - 1, + "Unexpected map size. Did you update LayoutElement::FREQUENCY_PER_VERTEX enum?" ); + DEFINE_ENUM_BINDER( m_Bindings, LayoutElement, Frequency, LayoutElement::FREQUENCY, m_FrequencyEnumMapping ) + + DEFINE_BINDER( m_Bindings, LayoutElement, InstanceDataStepRate, Uint32, Validator() ) + } + + virtual void GetValue( lua_State *L, const void* pBasePointer ) + { + // Use raw pointer to push the value to Lua because the buffer + // most likely does not exist + const auto *Elements = GetMemberByOffest(pBasePointer, m_LayoutElementsOffset); + const auto &NumElements = GetMemberByOffest< Uint32 >( pBasePointer, m_NumElementsOffset ); + PushLuaArray( L, Elements, Elements + NumElements, [&]( const LayoutElement &Elem ) + { + PushLuaTable( L, &Elem, m_Bindings ); + } + ); + } + + virtual void SetValue( lua_State *L, int Index, void* pBasePointer ) + { + ParseLuaArray( L, Index, pBasePointer, [&]( void* _pBasePointer, int StackIndex, int NewArrayIndex ) + { + VERIFY( pBasePointer == _pBasePointer, "Sanity check failed" ); + auto &Elements = GetMemberByOffest >( pBasePointer, m_MemberOffset ); + auto CurrIndex = Elements.size(); + if( CurrIndex != NewArrayIndex - 1 ) + SCRIPT_PARSING_ERROR( L, "Explicit array indices are not allowed in layout description. Provided index ", NewArrayIndex - 1, " conflicts with actual index ", CurrIndex, "." ); + Elements.resize( CurrIndex + 1 ); + ParseLuaTable( L, StackIndex, &(Elements)[CurrIndex], m_Bindings ); + if( Elements[CurrIndex].ValueType == VT_UNDEFINED ) + SCRIPT_PARSING_ERROR( L, "Valid value type must be specified for layout element #", CurrIndex ); + } + ); + + auto &ElementsBuffer = GetMemberByOffest >( pBasePointer, m_MemberOffset ); + auto &LayoutElements = GetMemberByOffest< LayoutElement* >( pBasePointer, m_LayoutElementsOffset ); + auto &NumElements = GetMemberByOffest< Uint32 >( pBasePointer, m_NumElementsOffset ); + LayoutElements = ElementsBuffer.data(); + NumElements = static_cast( ElementsBuffer.size() ); + } + private: + BindingsMapType m_Bindings; + ValueTypeEnumMapping m_ValueTypeEnumMapping; + EnumMapping < LayoutElement::FREQUENCY > m_FrequencyEnumMapping; + size_t m_LayoutElementsOffset; + size_t m_NumElementsOffset; + }; + + LayoutDescParser::LayoutDescParser( IRenderDevice *pRenderDevice, lua_State *L ) : + EngineObjectParserCommon( pRenderDevice, L, LayoutDescLibName ), + m_SetInputLayoutBinding( this, L, "Context", "SetInputLayout", &LayoutDescParser::SetInputLayout ) + { + DEFINE_BUFFERED_STRING_BINDER( m_Bindings, LayoutDescWrapper, Name, NameBuffer ) + + auto *pLayoutElemBinder = + new MemberBinder( + offsetof(LayoutDescWrapper, LayoutElements), + offsetof(LayoutDescWrapper, ElementsBuffer), + offsetof(LayoutDescWrapper, NumElements) + ); + m_Bindings.insert( std::make_pair( "LayoutElements", std::unique_ptr(pLayoutElemBinder) ) ); + }; + + void LayoutDescParser::CreateObj( lua_State *L ) + { + INIT_LUA_STACK_TRACKING( L ); + + LayoutDescWrapper LayoutDesc; + ParseLuaTable( L, -2, &LayoutDesc, m_Bindings ); + CHECK_LUA_STACK_HEIGHT(); + + auto ppVertexShader = GetUserData( L, -1, "Metatables.Shader" ); + auto ppVertDesc = reinterpret_cast(lua_newuserdata( L, sizeof( IVertexDescription* ) )); + *ppVertDesc = nullptr; + m_pRenderDevice->CreateVertexDescription( LayoutDesc, *ppVertexShader, ppVertDesc ); + if( *ppVertDesc == nullptr ) + SCRIPT_PARSING_ERROR(L, "Failed to create vertex description") + + CHECK_LUA_STACK_HEIGHT( +1 ); + } + + int LayoutDescParser::SetInputLayout( lua_State *L ) + { + auto pVertDesc = *GetUserData( L, 1, m_MetatableRegistryName.c_str() ); + auto *pContext = LoadDeviceContextFromRegistry( L ); + pContext->SetVertexDescription( pVertDesc ); + return 0; + } +} diff --git a/RenderScript/src/LuaBindings.cpp b/RenderScript/src/LuaBindings.cpp new file mode 100644 index 0000000..707a33c --- /dev/null +++ b/RenderScript/src/LuaBindings.cpp @@ -0,0 +1,278 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "LuaBindings.h" +#include "GraphicsUtilities.h" + +using namespace std; + +namespace Diligent +{ + template + int ReadIntValueFromLua( lua_State *L, int Index ) + { + CheckType( L, Index, LUA_TNUMBER ); + + int isnum; + auto Val = lua_tonumberx( L, Index, &isnum ); + if( !isnum ) + { + auto Str = lua_tostring( L, Index ); + SCRIPT_PARSING_ERROR( L, "Failed to convert parameter ", Str, " to int" ); + } + if( static_cast(Val) != Val ) + { + SCRIPT_PARSING_ERROR( L, "Parameter value (", Val, ") is not integer. Truncating to int" ); + } + return static_cast(Val); + } + + template + Type ReadFPValueFromLua( lua_State *L, int Index ) + { + CheckType( L, Index, LUA_TNUMBER ); + + int isnum; + auto Val = lua_tonumberx( L, Index, &isnum ); + if( !isnum ) + { + auto Str = lua_tostring( L, Index ); + SCRIPT_PARSING_ERROR( L, "Failed to convert parameter ", Str, " to floating point" ); + } + return static_cast(Val); + } + + template<> + int ReadValueFromLua( lua_State *L, int Index ) + { + return ReadIntValueFromLua( L, Index ); + } + + template<> + double ReadValueFromLua( lua_State *L, int Index ) + { + return ReadFPValueFromLua( L, Index ); + } + + template<> + float ReadValueFromLua( lua_State *L, int Index ) + { + return ReadFPValueFromLua( L, Index ); + } + + + template<> + String ReadValueFromLua( lua_State *L, int Index ) + { + CheckType( L, Index, LUA_TSTRING ); + + auto Str = lua_tostring( L, Index ); + return String( Str ); + } + + template<> + const Char* ReadValueFromLua( lua_State *L, int Index ) + { + CheckType( L, Index, LUA_TSTRING ); + + auto Str = lua_tostring( L, Index ); + return Str; + } + + template<> + Bool ReadValueFromLua( lua_State *L, int Index ) + { + CheckType( L, Index, LUA_TBOOLEAN ); + auto Val = lua_toboolean( L, Index ); + return Val ? True : False; + } + + template<> + Uint32 ReadValueFromLua( lua_State *L, int Index ) + { + return ReadIntValueFromLua( L, Index ); + } + + template<>Uint8 ReadValueFromLua( lua_State *L, int Index ) + { + return ReadIntValueFromLua( L, Index ); + } + + + + template<> + void PushValue( lua_State *L, double Val ) + { + lua_pushnumber( L, Val ); + } + + template<> + void PushValue( lua_State *L, const float& Val ) + { + lua_pushnumber( L, Val ); + } + + template<> + void PushValue( lua_State *L, const Int32& Val ) + { + lua_pushnumber( L, Val ); + } + + template<> + void PushValue( lua_State *L, const Uint8& Val ) + { + lua_pushnumber( L, Val ); + } + + template<> + void PushValue( lua_State *L, const Uint32& Val ) + { + lua_pushnumber( L, Val ); + } + + template<> + void PushValue( lua_State *L, const Char* Val ) + { + lua_pushstring( L, Val ); + } + + template<> void PushValue( lua_State *L, const Char* const& Val ) + { + lua_pushstring( L, Val ); + } + + template<> + void PushValue( lua_State *L, const String& Val ) + { + lua_pushstring( L, Val.c_str() ); + } + + template<> + void PushValue( lua_State *L, bool Val ) + { + lua_pushboolean( L, Val ); + } + + template<> + void PushValue( lua_State *L, const bool &Val ) + { + lua_pushboolean( L, Val ); + } + + + + template + void ParseNumericArray( lua_State *L, int StackIndex, std::vector< Uint8 >& RawData ) + { + typedef typename VALUE_TYPE2CType::CType ElemType; + CheckType( L, StackIndex, LUA_TTABLE ); + auto ArraySize = lua_rawlen( L, StackIndex ); + + auto ElemSize = sizeof( ElemType ); + RawData.reserve( ArraySize * ElemSize ); + + ParseLuaArray( L, StackIndex, &RawData, [ &]( void* pBasePointer, int StackIndex, int NewArrayIndex ) + { + VERIFY( pBasePointer == &RawData, "Sanity check failed" ); + auto CurrIndex = RawData.size() / ElemSize; + if( CurrIndex != NewArrayIndex - 1 ) + SCRIPT_PARSING_ERROR( L, "Explicit array indices are not allowed in array initialization. Provided index ", NewArrayIndex - 1, " conflicts with actual index ", CurrIndex, "." ); + RawData.resize( (CurrIndex + 1) * ElemSize ); + auto CurrValue = ReadValueFromLua( L, StackIndex ); + reinterpret_cast(RawData[CurrIndex * ElemSize]) = static_cast(CurrValue); + } ); + } + + NumericArrayLoader::NumericArrayLoader() : + m_ValueTypeBinder( 0, "VALUE_TYPE", m_ValueTypeEnumMapping ) + { + DEFINE_ENUM_ELEMENT_MAPPING( m_ValueTypeEnumMapping, VT_INT8 ); + DEFINE_ENUM_ELEMENT_MAPPING( m_ValueTypeEnumMapping, VT_INT16 ); + DEFINE_ENUM_ELEMENT_MAPPING( m_ValueTypeEnumMapping, VT_INT32 ); + DEFINE_ENUM_ELEMENT_MAPPING( m_ValueTypeEnumMapping, VT_UINT8 ); + DEFINE_ENUM_ELEMENT_MAPPING( m_ValueTypeEnumMapping, VT_UINT16 ); + DEFINE_ENUM_ELEMENT_MAPPING( m_ValueTypeEnumMapping, VT_UINT32 ); + DEFINE_ENUM_ELEMENT_MAPPING( m_ValueTypeEnumMapping, VT_FLOAT16 ); + DEFINE_ENUM_ELEMENT_MAPPING( m_ValueTypeEnumMapping, VT_FLOAT32 ); + VERIFY( m_ValueTypeEnumMapping.m_Str2ValMap.size() == VT_NUM_TYPES - 1, + "Unexpected map size. Did you update VALUE_TYPE enum?" ); + VERIFY( m_ValueTypeEnumMapping.m_Val2StrMap.size() == VT_NUM_TYPES - 1, + "Unexpected map size. Did you update VALUE_TYPE enum?" ); + + m_ParseFuncJumpTbl.insert( make_pair( VT_INT8, ParseNumericArray ) ); + m_ParseFuncJumpTbl.insert( make_pair( VT_INT16, ParseNumericArray ) ); + m_ParseFuncJumpTbl.insert( make_pair( VT_INT32, ParseNumericArray ) ); + m_ParseFuncJumpTbl.insert( make_pair( VT_UINT8, ParseNumericArray ) ); + m_ParseFuncJumpTbl.insert( make_pair( VT_UINT16, ParseNumericArray ) ); + m_ParseFuncJumpTbl.insert( make_pair( VT_UINT32, ParseNumericArray ) ); + //m_ParseFuncJumpTbl.insert( make_pair( VT_FLOAT16, ParseNumericArray ) ); + m_ParseFuncJumpTbl.insert( make_pair( VT_FLOAT32, ParseNumericArray ) ); + }; + + + void NumericArrayLoader::LoadArray( lua_State *L, int StackIndex, std::vector< Uint8 >& RawData ) + { + VALUE_TYPE ValueType; + m_ValueTypeBinder.SetValue( L, StackIndex-1, &ValueType ); + + auto it = m_ParseFuncJumpTbl.find( ValueType ); + if( it != m_ParseFuncJumpTbl.end() ) + { + it->second( L, StackIndex, RawData ); + } + else + { + SCRIPT_PARSING_ERROR( L, "No method to parse array of value VALUE_TYPE==", ValueType); + } + } + + // Special version of luaL_testudata() which takes an array of allowed metatables + void *luaL_testudata( lua_State *L, int ud, const std::vector &MetatableNames ) + { + void *p = lua_touserdata( L, ud ); + if( p != nullptr ) + { + // value is a userdata? + if( lua_getmetatable( L, ud ) ) // -0 | +(0|1) -> +(0|1) + { + // does it have a metatable? + bool bMatchingMTFound = false; + for( auto mtname = MetatableNames.begin(); mtname != MetatableNames.end() && !bMatchingMTFound; ++mtname ) + { + // get correct metatable + luaL_getmetatable( L, mtname->c_str() ); // -0 | +1 -> +1 + if( lua_rawequal( L, -1, -2 ) ) // are the same? + bMatchingMTFound = true; + + // pop correct metatable + lua_pop( L, 1 ); // -1 | +0 -> -1 + } + // pop user metatable + lua_pop( L, 1 ); // -1 | +0 -> -1 + return bMatchingMTFound ? p : nullptr; + } + } + return nullptr; // value is not a userdata with a metatable + } +} diff --git a/RenderScript/src/LuaFunctionBinding.cpp b/RenderScript/src/LuaFunctionBinding.cpp new file mode 100644 index 0000000..d81634e --- /dev/null +++ b/RenderScript/src/LuaFunctionBinding.cpp @@ -0,0 +1,110 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "LuaFunctionBinding.h" +#include "LuaBindings.h" + +namespace Diligent +{ + void LuaFunctionCallerBase::PushFuncStub( lua_State *L, Bool Arg ) + { + PushValue( L, Arg ); + } + + void LuaFunctionCallerBase::PushFuncStub( lua_State *L, Int32 Arg ) + { + PushValue( L, Arg ); + } + + void LuaFunctionCallerBase::PushFuncStub( lua_State *L, Uint32 Arg ) + { + PushValue( L, Arg ); + } + + void LuaFunctionCallerBase::PushFuncStub( lua_State *L, Int16 Arg ) + { + PushValue( L, Arg ); + } + + void LuaFunctionCallerBase::PushFuncStub( lua_State *L, Uint16 Arg ) + { + PushValue( L, Arg ); + } + + void LuaFunctionCallerBase::PushFuncStub( lua_State *L, Int8 Arg ) + { + PushValue( L, Arg ); + } + + void LuaFunctionCallerBase::PushFuncStub( lua_State *L, Uint8 Arg ) + { + PushValue( L, Arg ); + } + + void LuaFunctionCallerBase::PushFuncStub( lua_State *L, float Arg ) + { + PushValue( L, Arg ); + } + + void LuaFunctionCallerBase::PushFuncStub( lua_State *L, const Char *Arg ) + { + PushValue( L, Arg ); + } + + void LuaFunctionCallerBase::PushFuncStub( lua_State *L, const String &Arg ) + { + PushValue( L, Arg.c_str() ); + } + + void LuaFunctionCallerBase::Run_internal( int NumArgs, const Char *FuncName ) + { + // http://www.lua.org/pil/25.2.html + + if( FuncName ) + { + // Push onto the stack the value of the global name. + lua_getglobal( m_LuaState, FuncName ); + // All arguments are now below the function, while we need to have + // the function below all the arguments: + lua_insert( m_LuaState, -NumArgs - 1 ); + } + else + { + // If FuncName == 0, it is assumed that the chunk was previously loaded into the stack + auto StackTop = lua_gettop( m_LuaState ); + if( StackTop < 1 ) + LOG_ERROR( "Lua stack is empty. Load Lua chunk before calling Run()" ); + } + // do the call (NumArgs arguments, 0 results) + // lua_pcall() pops the function and all its arguments from the stack and + // pushes all the results (if any) + // In case of errors, the error message is pushed onto the top of the stack + if( lua_pcall( m_LuaState, NumArgs, 0, 0 ) != 0 ) + { + auto ErrorMsg = lua_tostring( m_LuaState, -1 ); + LOG_ERROR_AND_THROW( "Failed to call function \"", FuncName ? FuncName : "
", "\"\n" + "The following error occured:\n", ErrorMsg ); + } + } +} diff --git a/RenderScript/src/LuaWrappers.cpp b/RenderScript/src/LuaWrappers.cpp new file mode 100644 index 0000000..939fdac --- /dev/null +++ b/RenderScript/src/LuaWrappers.cpp @@ -0,0 +1,83 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "LuaWrappers.h" + +namespace Diligent +{ + LuaState::LuaState( Uint32 OpenLibFlags ) + { + m_pLuaState = luaL_newstate(); + //luaL_openlibs( m_pLuaState ); + + INIT_LUA_STACK_TRACKING( m_pLuaState ); + struct LuaStdLibInfo + { + const char *name; + lua_CFunction func; + Uint32 Flag; + }LuaStdLibs[] = + { + { "_G", luaopen_base, LUA_LIB_BASE }, + { LUA_LOADLIBNAME, luaopen_package, LUA_LIB_PACKAGE }, + { LUA_COLIBNAME, luaopen_coroutine, LUA_LIB_COROUTINE }, + { LUA_TABLIBNAME, luaopen_table, LUA_LIB_TABLE }, + { LUA_IOLIBNAME, luaopen_io, LUA_LIB_IO }, + { LUA_OSLIBNAME, luaopen_os, LUA_LIB_OS }, + { LUA_STRLIBNAME, luaopen_string, LUA_LIB_STRING }, + { LUA_BITLIBNAME, luaopen_bit32, LUA_LIB_BIT32 }, + { LUA_MATHLIBNAME, luaopen_math, LUA_LIB_MATH }, + { LUA_DBLIBNAME, luaopen_debug, LUA_LIB_DEBUG }, + { nullptr, nullptr, 0 } + }; + + for( auto lib = LuaStdLibs; lib->func; lib++ ) + { + if( OpenLibFlags & lib->Flag ) + { + luaL_requiref( m_pLuaState, lib->name, lib->func, 1 ); // -0 | +1 -> +1 + lua_pop( m_pLuaState, 1 ); // -1 | +0 -> -1 + } + } + + CHECK_LUA_STACK_HEIGHT(); + } + + LuaState::~LuaState() + { + Close(); + } + + void LuaState::Close() + { + if( m_pLuaState ) + lua_close( m_pLuaState ); + m_pLuaState = nullptr; + } + + LuaState::operator lua_State *() + { + return m_pLuaState; + } +} diff --git a/RenderScript/src/ParsingErrors.cpp b/RenderScript/src/ParsingErrors.cpp new file mode 100644 index 0000000..bb78387 --- /dev/null +++ b/RenderScript/src/ParsingErrors.cpp @@ -0,0 +1,87 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "ParsingErrors.h" + +static Diligent::String FindSourceLine( const char *pSource, int LineNumber ) +{ + const char *pLineStart = pSource; + for( int CurrLine = 1; CurrLine < LineNumber; ++CurrLine ) + { + pLineStart = strchr( pLineStart, '\n' ); + if( !pLineStart ) + break; + ++pLineStart; + } + + Diligent::String Line; + if( pLineStart ) + { + for( ; *pLineStart != '\n' && *pLineStart != 0; ++pLineStart ) + Line += *pLineStart; + } + return Line; +} + +void LuaDebugInformation( lua_State *L, std::stringstream &ss ) +{ + // Trace the Lua stack + ss << "Lua stack:\n"; + + Diligent::String FailureLine; + //String ShortSource; + + lua_Debug info; + int level = 0; + //int FailureLineNum = -1; + // lua_getstack() retrieves information about the interpreter runtime stack. + // This function fills parts of a lua_Debug structure that is required to call lua_getinfo() + // Level 0 is the current running function, whereas level n+1 is the function that has called + // level n (except for tail calls, which do not count on the stack). When there are no errors, + // lua_getstack returns 1; when called with a level greater than the stack depth, it returns 0. + while( lua_getstack( L, level, &info ) ) + { + // Get current stack level info + + // 'n': fills in the field name and namewhat; + // 'S': fills in the fields source, short_src, linedefined, lastlinedefined, and what; + // 'l': fills in the field currentline; + // 't': fills in the field istailcall; + // 'u': fills in the fields nups, nparams, and isvararg; + // 'f': pushes onto the stack the function that is running at the given level; + // 'L': pushes onto the stack a table whose indices are the numbers of the lines that are valid + // on the function. (A valid line is a line with some associated code, that is, a line where + // you can put a break point.Non - valid lines include empty lines and comments.) + lua_getinfo( L, "nSl", &info ); + ss << (info.name ? info.name : "") << '<' << (info.what ? info.what : "") << "> Line " << info.currentline << '\n'; + if( info.currentline >= 0 && FailureLine.length() == 0 ) + { + //ShortSource = info.short_src; + FailureLine = FindSourceLine( info.source, info.currentline ); + //FailureLineNum = info.currentline; + } + ++level; + } + ss << "Failure line:\n" << FailureLine;// << "\nLocation:\n" << ShortSource << ':' << FailureLineNum; +} diff --git a/RenderScript/src/RasterizerStateParser.cpp b/RenderScript/src/RasterizerStateParser.cpp new file mode 100644 index 0000000..1cac9ed --- /dev/null +++ b/RenderScript/src/RasterizerStateParser.cpp @@ -0,0 +1,89 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "RasterizerStateParser.h" + + +namespace Diligent +{ + const Char* RasterizerStateParser::RasterizerStateLibName = "RasterizerState"; + + RasterizerStateParser::RasterizerStateParser( IRenderDevice *pRenderDevice, lua_State *L ) : + EngineObjectParserCommon( pRenderDevice, L, RasterizerStateLibName ), + m_SetRasterizerBinding( this, L, "Context", "SetRasterizerState", &RasterizerStateParser::SetRasterizerState ) + { + DEFINE_BUFFERED_STRING_BINDER( m_Bindings, SRSDescWrapper, Name, NameBuffer ) + + DEFINE_ENUM_ELEMENT_MAPPING( m_FillModeEnumMapping, FILL_MODE_WIREFRAME ); + DEFINE_ENUM_ELEMENT_MAPPING( m_FillModeEnumMapping, FILL_MODE_SOLID ); + VERIFY( m_FillModeEnumMapping.m_Str2ValMap.size() == FILL_MODE_NUM_MODES-1, + "Unexpected map size. Did you update FILL_MODE enum?" ); + VERIFY( m_FillModeEnumMapping.m_Val2StrMap.size() == FILL_MODE_NUM_MODES-1, + "Unexpected map size. Did you update FILL_MODE enum?" ); + DEFINE_ENUM_BINDER( m_Bindings, SRSDescWrapper, FillMode, FILL_MODE, m_FillModeEnumMapping ); + + DEFINE_ENUM_ELEMENT_MAPPING( m_CullModeEnumMapping, CULL_MODE_NONE ); + DEFINE_ENUM_ELEMENT_MAPPING( m_CullModeEnumMapping, CULL_MODE_FRONT ); + DEFINE_ENUM_ELEMENT_MAPPING( m_CullModeEnumMapping, CULL_MODE_BACK ); + VERIFY( m_CullModeEnumMapping.m_Str2ValMap.size() == CULL_MODE_NUM_MODES-1, + "Unexpected map size. Did you update CULL_MODE enum?" ); + VERIFY( m_CullModeEnumMapping.m_Val2StrMap.size() == CULL_MODE_NUM_MODES-1, + "Unexpected map size. Did you update CULL_MODE enum?" ); + DEFINE_ENUM_BINDER( m_Bindings, SRSDescWrapper, CullMode, CULL_MODE, m_CullModeEnumMapping ); + + DEFINE_BINDER( m_Bindings, SRSDescWrapper, FrontCounterClockwise, Bool, Validator() ); + DEFINE_BINDER( m_Bindings, SRSDescWrapper, DepthBias, Int32, Validator() ); + DEFINE_BINDER( m_Bindings, SRSDescWrapper, DepthBiasClamp, Float32, Validator() ); + DEFINE_BINDER( m_Bindings, SRSDescWrapper, SlopeScaledDepthBias, Float32, Validator() ); + DEFINE_BINDER( m_Bindings, SRSDescWrapper, DepthClipEnable, Bool, Validator() ); + DEFINE_BINDER( m_Bindings, SRSDescWrapper, ScissorEnable, Bool, Validator() ); + DEFINE_BINDER( m_Bindings, SRSDescWrapper, AntialiasedLineEnable, Bool, Validator() ); + }; + + void RasterizerStateParser::CreateObj( lua_State *L ) + { + INIT_LUA_STACK_TRACKING( L ); + + SRSDescWrapper RasterizerDesc; + ParseLuaTable( L, 1, &RasterizerDesc, m_Bindings ); + + CHECK_LUA_STACK_HEIGHT(); + + auto ppRasterizerState = reinterpret_cast(lua_newuserdata( L, sizeof( IRasterizerState* ) )); + *ppRasterizerState = nullptr; + m_pRenderDevice->CreateRasterizerState( RasterizerDesc, ppRasterizerState ); + if( *ppRasterizerState == nullptr ) + SCRIPT_PARSING_ERROR(L, "Failed to create rasterizer state") + + CHECK_LUA_STACK_HEIGHT( +1 ); + } + + int RasterizerStateParser::SetRasterizerState( lua_State *L ) + { + auto *pRS = *GetUserData( L, 1, m_MetatableRegistryName.c_str() ); + auto *pContext = LoadDeviceContextFromRegistry( L ); + pContext->SetRasterizerState( pRS ); + return 0; + } +} diff --git a/RenderScript/src/ResourceMappingParser.cpp b/RenderScript/src/ResourceMappingParser.cpp new file mode 100644 index 0000000..e3f4918 --- /dev/null +++ b/RenderScript/src/ResourceMappingParser.cpp @@ -0,0 +1,166 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "ResourceMappingParser.h" +#include "TextureViewParser.h" +#include "BufferParser.h" +#include "BufferViewParser.h" + +namespace Diligent +{ + const Char* ResourceMappingParser::ResourceMappingLibName = "ResourceMapping"; + + ResourceMappingParser::ResourceMappingParser( IRenderDevice *pRenderDevice, lua_State *L, + TextureViewParser *pTexViewParser, + BufferParser *pBuffParser, + BufferViewParser *pBuffViewParser ) : + EngineObjectParserBase( pRenderDevice, L, ResourceMappingLibName), + m_BindShaderResourcesBinding( this, L, "Context", "BindShaderResources", &ResourceMappingParser::BindShaderResources ), + m_pTexViewParser( pTexViewParser ), + m_pBuffParser( pBuffParser ), + m_pBuffViewParser( pBuffViewParser ), + m_MappedResourceMetatables( { pTexViewParser->GetMetatableName(), pBuffParser->GetMetatableName(), pBuffViewParser->GetMetatableName() } ) + { + DEFINE_BINDER( m_Bindings, ResourceMappingEntry, Name, const Char*, SkipValidationFunc ) + DEFINE_BINDER( m_Bindings, ResourceMappingEntry, pObject, EngineObjectPtrLoader, m_MappedResourceMetatables ); + }; + + void ResourceMappingParser::CreateObj( lua_State *L ) + { + std::vector Entries; + + ParseLuaArray( L, 1, &Entries, [ &]( void* pBasePointer, int StackIndex, int NewArrayIndex ) + { + VERIFY( pBasePointer == &Entries, "Sanity check failed" ); + auto CurrIndex = Entries.size(); + if( CurrIndex != NewArrayIndex - 1 ) + SCRIPT_PARSING_ERROR( L, "Explicit array indices are not allowed in resource mapping description. Provided index ", NewArrayIndex - 1, " conflicts with actual index ", CurrIndex, "." ); + Entries.resize( CurrIndex + 1 ); + ParseLuaTable( L, StackIndex, &(Entries)[CurrIndex], m_Bindings ); + } + ); + + Entries.push_back( ResourceMappingEntry() ); + + // Note that ResourceMappingEntry.Name is declared as const Char*, not as String. + // This is not a problem as Lua guarantees that all pointers to string values + // remain valid as long as these strings are not popped from the stack + ResourceMappingDesc ResourceMappingDesc; + ResourceMappingDesc.pEntries = Entries.data(); + + IResourceMapping **ppResourceMapping = reinterpret_cast( lua_newuserdata( L, sizeof( IResourceMapping* ) ) ); + *ppResourceMapping = nullptr; + m_pRenderDevice->CreateResourceMapping( ResourceMappingDesc, ppResourceMapping ); + if( *ppResourceMapping == nullptr ) + SCRIPT_PARSING_ERROR(L, "Failed to create resource mapping") + } + + void ResourceMappingParser::DestroyObj( void *pData ) + { + if( pData != nullptr ) + { + auto ppObject = reinterpret_cast(pData); + if( *ppObject != nullptr ) + (*ppObject)->Release(); + } + } + + void ResourceMappingParser::ReadField( lua_State *L, void *pData, const Char *Field ) + { + auto *pResourceMapping = *reinterpret_cast(pData); + Diligent::RefCntAutoPtr pResource; + pResourceMapping->GetResource( Field, &pResource ); + Diligent::RefCntAutoPtr pTextureView; + Diligent::RefCntAutoPtr pBuffer; + if( pResource ) + { + pResource->QueryInterface( IID_TextureView, &pTextureView ); + if( pTextureView ) + { + m_pTexViewParser->PushObject(L, pTextureView); + } + + if( !pTextureView ) + { + pResource->QueryInterface( IID_Buffer, &pBuffer ); + if( pBuffer ) + { + m_pBuffParser->PushObject( L, pBuffer ); + } + } + } + + if( !(pTextureView || pBuffer) ) + { + lua_pushnil( L ); // -0 | +1 -> +1 + } + } + + void ResourceMappingParser::UpdateField( lua_State *L, void *pData, const Char *Field ) + { + auto *pResourceMapping = *reinterpret_cast(pData); + if( lua_type( L, 3 ) == LUA_TNIL ) + { + pResourceMapping->RemoveResourceByName( Field ); + } + else + { + auto pResource = *GetUserData( L, 3, m_MappedResourceMetatables ); + pResourceMapping->AddResource( Field, pResource, false ); + } + } + + int ResourceMappingParser::BindShaderResources( lua_State *L ) + { + auto *pContext = LoadDeviceContextFromRegistry( L ); + auto pResMapping = *GetUserData( L, 1, m_MetatableRegistryName.c_str() ); + Uint32 Flags = 0; + auto NumArgs = lua_gettop( L ); + // The last argument may be flags + const int FlagsArgInd = 2; + if( NumArgs >= FlagsArgInd && + (lua_type( L, FlagsArgInd ) == LUA_TSTRING || lua_type( L, FlagsArgInd ) == LUA_TTABLE ) ) + { + FlagsLoader FlagsLoader(0, "BindShaderResourceFlags", m_BindShaderResFlagEnumMapping); + FlagsLoader.SetValue( L, FlagsArgInd, &Flags ); + } + + pContext->BindShaderResources( pResMapping, Flags ); + return 0; + } + + void ResourceMappingParser::GetObjectByName( lua_State *L, const Char *ShaderName, IResourceMapping** ppObject ) + { + auto pObject = *GetGlobalObject( L, ShaderName, m_MetatableRegistryName.c_str() ); + *ppObject = pObject; + pObject->AddRef(); + } + + void ResourceMappingParser::PushExistingObject( lua_State *L, const void *pObject ) + { + auto ppObject = reinterpret_cast(lua_newuserdata( L, sizeof( IResourceMapping* ) )); + *ppObject = reinterpret_cast(const_cast(pObject)); + (*ppObject)->AddRef(); + } +} diff --git a/RenderScript/src/SamplerParser.cpp b/RenderScript/src/SamplerParser.cpp new file mode 100644 index 0000000..74aa71f --- /dev/null +++ b/RenderScript/src/SamplerParser.cpp @@ -0,0 +1,92 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "SamplerParser.h" + +namespace Diligent +{ + const Char* SamplerParser::SamplerLibName = "Sampler"; + + SamplerParser::SamplerParser( IRenderDevice *pRenderDevice, lua_State *L ) : + EngineObjectParserCommon( pRenderDevice, L, SamplerLibName ) + { + DEFINE_BUFFERED_STRING_BINDER( m_Bindings, SSamDescWrapper, Name, NameBuffer ) + + DEFINE_ENUM_ELEMENT_MAPPING( m_FilterTypeEnumMapping, FILTER_TYPE_POINT ); + DEFINE_ENUM_ELEMENT_MAPPING( m_FilterTypeEnumMapping, FILTER_TYPE_LINEAR ); + DEFINE_ENUM_ELEMENT_MAPPING( m_FilterTypeEnumMapping, FILTER_TYPE_ANISOTROPIC ); + DEFINE_ENUM_ELEMENT_MAPPING( m_FilterTypeEnumMapping, FILTER_TYPE_COMPARISON_POINT ); + DEFINE_ENUM_ELEMENT_MAPPING( m_FilterTypeEnumMapping, FILTER_TYPE_COMPARISON_LINEAR ); + DEFINE_ENUM_ELEMENT_MAPPING( m_FilterTypeEnumMapping, FILTER_TYPE_COMPARISON_ANISOTROPIC ); + VERIFY( m_FilterTypeEnumMapping.m_Str2ValMap.size() == FILTER_TYPE_NUM_FILTERS - 1, "Unexpected map size. Did you update FILTER_TYPE enum?" ); + VERIFY( m_FilterTypeEnumMapping.m_Val2StrMap.size() == FILTER_TYPE_NUM_FILTERS - 1, "Unexpected map size. Did you update FILTER_TYPE enum?" ); + DEFINE_ENUM_BINDER( m_Bindings, SSamDescWrapper, MinFilter, FILTER_TYPE, m_FilterTypeEnumMapping ) + DEFINE_ENUM_BINDER( m_Bindings, SSamDescWrapper, MagFilter, FILTER_TYPE, m_FilterTypeEnumMapping ) + DEFINE_ENUM_BINDER( m_Bindings, SSamDescWrapper, MipFilter, FILTER_TYPE, m_FilterTypeEnumMapping ) + + + DEFINE_ENUM_ELEMENT_MAPPING( m_TexAddrModeEnumMapping, TEXTURE_ADDRESS_WRAP ); + DEFINE_ENUM_ELEMENT_MAPPING( m_TexAddrModeEnumMapping, TEXTURE_ADDRESS_MIRROR ); + DEFINE_ENUM_ELEMENT_MAPPING( m_TexAddrModeEnumMapping, TEXTURE_ADDRESS_CLAMP ); + DEFINE_ENUM_ELEMENT_MAPPING( m_TexAddrModeEnumMapping, TEXTURE_ADDRESS_BORDER ); + DEFINE_ENUM_ELEMENT_MAPPING( m_TexAddrModeEnumMapping, TEXTURE_ADDRESS_MIRROR_ONCE ); + VERIFY( m_TexAddrModeEnumMapping.m_Str2ValMap.size() == TEXTURE_ADDRESS_NUM_MODES - 1, "Unexpected map size. Did you update TEXTURE_ADDRESS_MODE enum?" ); + VERIFY( m_TexAddrModeEnumMapping.m_Val2StrMap.size() == TEXTURE_ADDRESS_NUM_MODES - 1, "Unexpected map size. Did you update TEXTURE_ADDRESS_MODE enum?" ); + DEFINE_ENUM_BINDER( m_Bindings, SSamDescWrapper, AddressU, TEXTURE_ADDRESS_MODE, m_TexAddrModeEnumMapping ) + DEFINE_ENUM_BINDER( m_Bindings, SSamDescWrapper, AddressV, TEXTURE_ADDRESS_MODE, m_TexAddrModeEnumMapping ) + DEFINE_ENUM_BINDER( m_Bindings, SSamDescWrapper, AddressW, TEXTURE_ADDRESS_MODE, m_TexAddrModeEnumMapping ) + + + Validator DummyValidatorF( SkipValidationFunc ); + DEFINE_BINDER( m_Bindings, SSamDescWrapper, MipLODBias, Float32, DummyValidatorF ) + + Validator MaxAnisotropyValidator( "Max Anisotropy", 0, 32 ); + DEFINE_BINDER( m_Bindings, SSamDescWrapper, MaxAnisotropy, Uint32, MaxAnisotropyValidator ) + + DEFINE_ENUM_BINDER( m_Bindings, SSamDescWrapper, ComparisonFunc, COMPARISON_FUNCTION, m_CmpFuncEnumMapping ) + + DEFINE_BINDER( m_Bindings, SSamDescWrapper, BorderColor, RGBALoader, 0 ) + + DEFINE_BINDER( m_Bindings, SSamDescWrapper, MinLOD, Float32, DummyValidatorF ) + DEFINE_BINDER( m_Bindings, SSamDescWrapper, MaxLOD, Float32, DummyValidatorF ) + }; + + void SamplerParser::CreateObj( lua_State *L ) + { + INIT_LUA_STACK_TRACKING( L ); + + SSamDescWrapper SamplerDesc; + ParseLuaTable( L, -1, &SamplerDesc, m_Bindings ); + + CHECK_LUA_STACK_HEIGHT(); + + auto ppSampler = reinterpret_cast(lua_newuserdata( L, sizeof( ISampler* ) )); + *ppSampler = nullptr; + m_pRenderDevice->CreateSampler( SamplerDesc, ppSampler ); + if( *ppSampler == nullptr ) + SCRIPT_PARSING_ERROR(L, "Failed to create a sampler") + + CHECK_LUA_STACK_HEIGHT( +1 ); + } +} diff --git a/RenderScript/src/ScissorRectParser.cpp b/RenderScript/src/ScissorRectParser.cpp new file mode 100644 index 0000000..3f81087 --- /dev/null +++ b/RenderScript/src/ScissorRectParser.cpp @@ -0,0 +1,124 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "ScissorRectParser.h" + +namespace Diligent +{ + const Char* ScissorRectParser::ScissorRectLibName = "ScissorRect"; + + ScissorRectParser::ScissorRectParser( IRenderDevice *pRenderDevice, lua_State *L ) : + EngineObjectParserBase( pRenderDevice, L, ScissorRectLibName ), + m_SetScissorRectsBinding( this, L, "Context", "SetScissorRects", &ScissorRectParser::SetScissorRects ) + { + m_ScissorRects.reserve( 8 ); + + // NumVertices and NumIndices are in Union + DEFINE_BINDER( m_Bindings, Rect, left, Int32, Validator() ) + DEFINE_BINDER( m_Bindings, Rect, top, Int32, Validator() ) + DEFINE_BINDER( m_Bindings, Rect, right, Int32, Validator() ) + DEFINE_BINDER( m_Bindings, Rect, bottom, Int32, Validator() ) + }; + + void ScissorRectParser::CreateObj( lua_State *L ) + { + INIT_LUA_STACK_TRACKING(L); + + Rect ScissorRect; + ParseLuaTable( L, 1, &ScissorRect, m_Bindings ); + if( ScissorRect.left > ScissorRect.right ) + SCRIPT_PARSING_ERROR(L, "Scissor rect left and right boundaries (", ScissorRect.left, ", ", ScissorRect.right, ") are incorrect") + if( ScissorRect.top > ScissorRect.bottom ) + SCRIPT_PARSING_ERROR(L, "Scissor rect top and bottom boundaries (", ScissorRect.top, ", ", ScissorRect.bottom, ") are incorrect") + + CHECK_LUA_STACK_HEIGHT(); + + auto pScissorRect = reinterpret_cast(lua_newuserdata( L, sizeof( Rect ) )); + memcpy(pScissorRect, &ScissorRect, sizeof(ScissorRect)); + + CHECK_LUA_STACK_HEIGHT( +1 ); + } + + void ScissorRectParser::DestroyObj( void *pData ) + { + // We do not need to do anything, because the whole object is + // created as full user data and thus managed by Lua + } + + void ScissorRectParser::ReadField( lua_State *L, void *pData, const Char *Field ) + { + auto pScissorRect = reinterpret_cast(pData); + PushField( L, pScissorRect, Field, m_Bindings ); + } + + void ScissorRectParser::UpdateField( lua_State *L, void *pData, const Char *Field ) + { + auto pScissorRect = reinterpret_cast(pData); + Diligent::UpdateField( L, -1, pScissorRect, Field, m_Bindings ); + } + + void ScissorRectParser::PushExistingObject( lua_State *L, const void *pObject ) + { + auto pScissorRect = reinterpret_cast(lua_newuserdata( L, sizeof( Rect ) )); + memcpy( pScissorRect, pObject, sizeof( Rect ) ); + } + + int ScissorRectParser::SetScissorRects( lua_State *L ) + { + auto NumArgs = lua_gettop( L ); + Uint32 RTWidth = 0; + Uint32 RTHeight = 0; + m_ScissorRects.clear(); + for( int Arg = 1; Arg <= NumArgs; ++Arg ) + { + if( lua_type( L, Arg ) == LUA_TUSERDATA ) + { + auto pScissorRect = GetUserData( L, Arg, m_MetatableRegistryName.c_str() ); + m_ScissorRects.emplace_back( *pScissorRect ); + } + else + { + if( RTWidth == 0 ) + RTWidth = ReadValueFromLua( L, Arg ); + else if( RTHeight == 0 ) + RTHeight = ReadValueFromLua( L, Arg ); + else + SCRIPT_PARSING_ERROR( L, "Render target size already specified (", RTWidth, "x", RTHeight, ")." ); + } + } + + if( RTWidth == 0 && RTHeight != 0 || RTWidth != 0 && RTHeight == 0 ) + SCRIPT_PARSING_ERROR( L, "Render target size is incomplete (", RTWidth, "x", RTHeight, "). Use either 0x0 or fully specified size" ); + + Uint32 NumScissorRects = static_cast( m_ScissorRects.size() ); + + if( NumScissorRects == 0 ) + SCRIPT_PARSING_ERROR( L, "At least one viewport must be specified" ); + + auto *pContext = LoadDeviceContextFromRegistry( L ); + pContext->SetScissorRects( NumScissorRects, m_ScissorRects.data(), RTWidth, RTHeight ); + + return 0; + } +} diff --git a/RenderScript/src/ScriptParser.cpp b/RenderScript/src/ScriptParser.cpp new file mode 100644 index 0000000..3331eac --- /dev/null +++ b/RenderScript/src/ScriptParser.cpp @@ -0,0 +1,263 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "ScriptParser.h" +#include "LuaBindings.h" +#include "SamplerParser.h" +#include "LayoutDescParser.h" +#include "ShaderParser.h" +#include "BufferParser.h" +#include "TextureParser.h" +#include "DrawAttribsParser.h" +#include "FileSystem.h" +#include "ResourceMappingParser.h" +#include "TextureViewParser.h" +#include "BufferViewParser.h" +#include "DepthStencilStateParser.h" +#include "RasterizerStateParser.h" +#include "BlendStateParser.h" +#include "DeviceContextFuncBindings.h" +#include "ViewportParser.h" +#include "ScissorRectParser.h" +#include "ShaderVariableParser.h" + +using namespace Diligent; +using namespace Diligent; + +namespace Diligent +{ + const Char* ScriptParser::DeviceContextRegistryKey = "DeviceContext"; + +#define IMPLEMENT_PUSH_FUNC_STUBS(ObjectType, ParserName) \ + void ScriptParser::SpecialPushFuncs::PushFuncStub( lua_State *L, const ObjectType* pObject) \ + { \ + m_pScriptParser->ParserName->PushObject( L, pObject ); \ + } \ + \ + void ScriptParser::SpecialPushFuncs::PushFuncStub( lua_State *L, const RefCntAutoPtr &pObject ) \ + { \ + PushFuncStub( L, pObject.RawPtr() ); \ + } + + IMPLEMENT_PUSH_FUNC_STUBS( ISampler, m_pSamplerParser) + IMPLEMENT_PUSH_FUNC_STUBS( IVertexDescription, m_pLayoutDescParser ) + IMPLEMENT_PUSH_FUNC_STUBS( IShader, m_pShaderParser ) + IMPLEMENT_PUSH_FUNC_STUBS( IBuffer, m_pBufferParser ) + IMPLEMENT_PUSH_FUNC_STUBS( ITexture, m_pTextureParser ) + IMPLEMENT_PUSH_FUNC_STUBS( IResourceMapping, m_pResourceMappingParser ) + IMPLEMENT_PUSH_FUNC_STUBS( ITextureView, m_pTextureViewParser ) + IMPLEMENT_PUSH_FUNC_STUBS( IBufferView, m_pBufferViewParser ) + IMPLEMENT_PUSH_FUNC_STUBS( IDepthStencilState, m_pDSStateParser ) + IMPLEMENT_PUSH_FUNC_STUBS( IRasterizerState, m_pRSParser ) + IMPLEMENT_PUSH_FUNC_STUBS( IBlendState, m_pBSParser ) + IMPLEMENT_PUSH_FUNC_STUBS( IShaderVariable, m_pShaderVariableParser ) + + + void ScriptParser::SpecialPushFuncs::PushFuncStub( lua_State *L, const DrawAttribs &DrawAttribs ) + { + m_pScriptParser->m_pDrawAttribsParser->PushObject( L, &DrawAttribs ); + } + + void ScriptParser::SpecialPushFuncs::PushFuncStub( lua_State *L, const Viewport &Viewport ) + { + m_pScriptParser->m_pViewportParser->PushObject( L, &Viewport ); + } + + void ScriptParser::SpecialPushFuncs::PushFuncStub( lua_State *L, const Rect &Rect ) + { + m_pScriptParser->m_pScissorRectParser->PushObject( L, &Rect ); + } + + ScriptParser::ScriptParser( IRenderDevice *pRenderDevice ) : + m_pRenderDevice( pRenderDevice ), + m_LuaState( LuaState::LUA_LIB_BASE | LuaState::LUA_LIB_COROUTINE | LuaState::LUA_LIB_TABLE | + LuaState::LUA_LIB_STRING | LuaState::LUA_LIB_BIT32 | LuaState::LUA_LIB_MATH ) + { + // Run's ctor is called BEFORE the m_LuaState's ctor + // We need to explicitly init the object: + m_RunFunctionCaller.SetLuaState( m_LuaState ); + m_RunFunctionCaller.SetScriptParser( this ); + + // We need to define global constants before initializing parsers + DefineGlobalConstants(m_LuaState); + + m_pSamplerParser.reset( new SamplerParser( pRenderDevice, m_LuaState ) ); + m_pLayoutDescParser.reset( new LayoutDescParser( pRenderDevice, m_LuaState ) ); + m_pBufferParser.reset( new BufferParser( pRenderDevice, m_LuaState ) ); + m_pTextureParser.reset( new TextureParser( pRenderDevice, m_LuaState ) ); + m_pDrawAttribsParser.reset( new DrawAttribsParser( m_pBufferParser.get(), pRenderDevice, m_LuaState ) ); + // Texture view parser must be create AFTER texture parser, because it + // registers CreateView function in Metatables.Texture table + m_pTextureViewParser.reset( new TextureViewParser( m_pTextureParser.get(), m_pSamplerParser.get(), pRenderDevice, m_LuaState ) ); + m_pBufferViewParser.reset( new BufferViewParser( m_pBufferParser.get(), pRenderDevice, m_LuaState ) ); + m_pResourceMappingParser.reset( new ResourceMappingParser( pRenderDevice, m_LuaState, m_pTextureViewParser.get(), m_pBufferParser.get(), m_pBufferViewParser.get() ) ); + m_pShaderParser.reset( new ShaderParser( pRenderDevice, m_LuaState, m_pResourceMappingParser->GetMetatableName() ) ); + m_pDSStateParser.reset( new DepthStencilStateParser( pRenderDevice, m_LuaState ) ); + m_pRSParser.reset( new RasterizerStateParser( pRenderDevice, m_LuaState ) ); + m_pBSParser.reset( new BlendStateParser( pRenderDevice, m_LuaState ) ); + m_pDeviceCtxFuncBindings.reset( new DeviceContextFuncBindings( pRenderDevice, m_LuaState, m_pTextureViewParser.get() ) ); + m_pViewportParser.reset( new ViewportParser( pRenderDevice, m_LuaState ) ); + m_pScissorRectParser.reset( new ScissorRectParser( pRenderDevice, m_LuaState ) ); + m_pShaderVariableParser.reset( new ShaderVariableParser( pRenderDevice, m_LuaState, m_pShaderParser->GetMetatableName(), m_pBufferParser->GetMetatableName(), m_pBufferViewParser->GetMetatableName(), m_pTextureViewParser->GetMetatableName() ) ); + } + + ScriptParser::~ScriptParser() + { + // It is essentially important to close Lua first, because we need to release + // all user data + m_LuaState.Close(); + } + + void ScriptParser::DefineGlobalConstants( lua_State *L ) + { + INIT_LUA_STACK_TRACKING( L ); + + // Create a new empty table and push it onto the stack + lua_newtable( L ); // -0 | +1 -> +1 + + const auto &DeviceCaps = m_pRenderDevice->GetDeviceCaps(); + const Char *pDeviceStr = nullptr; + switch(DeviceCaps.DevType) + { + case DeviceType::OpenGL: + pDeviceStr = "OpenGL"; + break; + + case DeviceType::OpenGLES: + pDeviceStr = "OpenGLES"; + break; + + case DeviceType::DirectX: + pDeviceStr = "DirectX"; + break; + + default: + UNEXPECTED( "Unknown device type" ); + } + SetTableField( L, "DeviceType", -1, pDeviceStr ); // -0 | +0 -> 0 + + // lua_setglobal() pops a value from the stack and sets it as the new value of global name. + lua_setglobal( L, "Constants" ); // -1 | +0 -> -1 + + CHECK_LUA_STACK_HEIGHT(); + + lua_newtable( L ); // -0 | +1 -> +1 + lua_setglobal( L, "Context" ); // -1 | +0 -> -1 + + CHECK_LUA_STACK_HEIGHT(); + } + + // Every C-function called by Lua sees only its own private stack, with its first argument at index 1 + // Return the number of results pushed onto the stack + + void ScriptParser::Parse( const Char *pScript ) + { + // Load the chunck and push it onto the top of the stack. + // In case of errors, the error message is pushed onto the top of the stack + if( luaL_loadstring( m_LuaState, pScript ) ) + { + // Get the error message from the top of the stack + + // NOTE: the lua_tostring function returns a pointer to an internal copy of the string. + // The string is always zero-terminated and Lua ensures that this pointer is valid as long + // as the corresponding value is in the stack. + auto ErrorMsg = lua_tostring( m_LuaState, -1 ); + + if( ErrorMsg ) + { + LOG_ERROR_AND_THROW( "Failed to parse the script file:\n", ErrorMsg ); + } + else + { + LOG_ERROR_AND_THROW( "Failed to parse the script file." ); + } + lua_pop( m_LuaState, 1 ); // pop error message from the stack + } + } + + void ScriptParser::GetSamplerByName( const Char *SamplerName, ISampler** ppSampler ) + { + m_pSamplerParser->GetObjectByName( m_LuaState, SamplerName, ppSampler ); + } + + void ScriptParser::GetVertexDescriptionByName( const Char *VertDescName, IVertexDescription** ppVertDesc ) + { + m_pLayoutDescParser->GetObjectByName( m_LuaState, VertDescName, ppVertDesc ); + } + + void ScriptParser::GetShaderByName( const Char *ShaderName, IShader** ppShader ) + { + m_pShaderParser->GetObjectByName( m_LuaState, ShaderName, ppShader ); + } + + void ScriptParser::GetBufferByName( const Char *BufferName, IBuffer** ppBuffer ) + { + m_pBufferParser->GetObjectByName( m_LuaState, BufferName, ppBuffer ); + } + + void ScriptParser::GetTextureByName( const Char *TextureName, ITexture** ppTexture ) + { + m_pTextureParser->GetObjectByName( m_LuaState, TextureName, ppTexture ); + } + + void ScriptParser::GetResourceMappingByName( const Char *ResourceMappingName, IResourceMapping** ppResourceMapping ) + { + m_pResourceMappingParser->GetObjectByName( m_LuaState, ResourceMappingName, ppResourceMapping ); + } + + void ScriptParser::GetTextureViewByName( const Char *TextureViewName, ITextureView** ppTextureView ) + { + m_pTextureViewParser->GetObjectByName( m_LuaState, TextureViewName, ppTextureView ); + } + + void ScriptParser::GetBufferViewByName( const Char *BufferViewName, IBufferView** ppBufferView ) + { + m_pBufferViewParser->GetObjectByName( m_LuaState, BufferViewName, ppBufferView ); + } + + void ScriptParser::GetDepthStencilStateByName( const Char *DepthStencilStateName, IDepthStencilState** ppDepthStencilState ) + { + m_pDSStateParser->GetObjectByName( m_LuaState, DepthStencilStateName, ppDepthStencilState ); + } + + void ScriptParser::GetRasterizerStateByName( const Char *RasterizerStateName, IRasterizerState** ppRasterizerState ) + { + m_pRSParser->GetObjectByName( m_LuaState, RasterizerStateName, ppRasterizerState ); + } + + void ScriptParser::GetBlendStateByName( const Char *BlendStateName, IBlendState** ppBlendState ) + { + m_pBSParser->GetObjectByName( m_LuaState, BlendStateName, ppBlendState ); + } + + void ScriptParser::GetShaderVariableByName( const Char *ShaderVarName, IShaderVariable** ppShaderVar ) + { + m_pShaderVariableParser->GetObjectByName( m_LuaState, ShaderVarName, ppShaderVar ); + } + + void ScriptParser::QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface ) + { + UNSUPPORTED( "Not implemented" ); + } +} diff --git a/RenderScript/src/ShaderParser.cpp b/RenderScript/src/ShaderParser.cpp new file mode 100644 index 0000000..38bdee3 --- /dev/null +++ b/RenderScript/src/ShaderParser.cpp @@ -0,0 +1,197 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "ShaderParser.h" +#include "BasicShaderSourceStreamFactory.h" + +namespace std +{ + DEFINE_ENUM_HASH( Diligent::SHADER_TYPE ) +} + +namespace Diligent +{ + const Char* ShaderParser::ShaderLibName = "Shader"; + + class ShaderDescLoader; + + template<> + class MemberBinder : public MemberBinderBase + { + public: + MemberBinder( size_t MemberOffset, size_t Dummy ) : + MemberBinderBase( MemberOffset ) + { + auto *pNameBinder = new BufferedStringBinder( offsetof( ShaderDesc, Name ), + // This is a small hack: we need to compute an offset from the beginning of ShaderDesc structure to + // the NameBuffer member of ShaderCreationAttribsWrapper: + offsetof( ShaderParser::ShaderCreationAttribsWrapper, NameBuffer ) - offsetof( ShaderParser::ShaderCreationAttribsWrapper, Desc.Name ) ); + // No need to make a copy of Name since it is constant and HashMapStringKey will simply + // keep pointer to it + m_Bindings.insert( std::make_pair( "Name", std::unique_ptr(pNameBinder) ) ); + + DEFINE_ENUM_ELEMENT_MAPPING( m_ShaderTypeEnumMapping, SHADER_TYPE_UNKNOWN ); + DEFINE_ENUM_ELEMENT_MAPPING( m_ShaderTypeEnumMapping, SHADER_TYPE_VERTEX ); + DEFINE_ENUM_ELEMENT_MAPPING( m_ShaderTypeEnumMapping, SHADER_TYPE_PIXEL ); + DEFINE_ENUM_ELEMENT_MAPPING( m_ShaderTypeEnumMapping, SHADER_TYPE_GEOMETRY ); + DEFINE_ENUM_ELEMENT_MAPPING( m_ShaderTypeEnumMapping, SHADER_TYPE_HULL ); + DEFINE_ENUM_ELEMENT_MAPPING( m_ShaderTypeEnumMapping, SHADER_TYPE_DOMAIN ); + DEFINE_ENUM_ELEMENT_MAPPING( m_ShaderTypeEnumMapping, SHADER_TYPE_COMPUTE ); + DEFINE_ENUM_BINDER( m_Bindings, ShaderDesc, ShaderType, SHADER_TYPE, m_ShaderTypeEnumMapping ) + } + + virtual void GetValue( lua_State *L, const void* pBasePointer ) + { + const auto *pShaderDesc = &GetMemberByOffest( pBasePointer, m_MemberOffset ); + PushLuaTable( L, pShaderDesc, m_Bindings ); + } + + virtual void SetValue( lua_State *L, int Index, void* pBasePointer ) + { + auto *pShaderDesc = &GetMemberByOffest(pBasePointer, m_MemberOffset); + ParseLuaTable( L, Index, pShaderDesc, m_Bindings ); + } + + private: + BindingsMapType m_Bindings; + EnumMapping m_ShaderTypeEnumMapping; + }; + + ShaderParser::ShaderParser( IRenderDevice *pRenderDevice, lua_State *L, const String& ResMappingMetatableName ) : + EngineObjectParserCommon( pRenderDevice, L, ShaderLibName ), + m_SetShadersBinding( this, L, "Context", "SetShaders", &ShaderParser::SetShaders ), + m_BindResourcesBinding( this, L, m_MetatableRegistryName.c_str(), "BindResources", &ShaderParser::BindResources ), + m_ResMappingMetatableName(ResMappingMetatableName) + { + DEFINE_BUFFERED_STRING_BINDER( m_Bindings, ShaderCreationAttribsWrapper, FilePath, FilePathBuffer ) + DEFINE_BUFFERED_STRING_BINDER( m_Bindings, ShaderCreationAttribsWrapper, EntryPoint, EntryPointBuffer ) + DEFINE_BUFFERED_STRING_BINDER( m_Bindings, ShaderCreationAttribsWrapper, SearchDirectories, SearchDirectoriesBuffer ) + + DEFINE_ENUM_ELEMENT_MAPPING( m_ShaderSourceLangEnumMapping, SHADER_SOURCE_LANGUAGE_DEFAULT ); + DEFINE_ENUM_ELEMENT_MAPPING( m_ShaderSourceLangEnumMapping, SHADER_SOURCE_LANGUAGE_HLSL ); + DEFINE_ENUM_ELEMENT_MAPPING( m_ShaderSourceLangEnumMapping, SHADER_SOURCE_LANGUAGE_GLSL ); + DEFINE_ENUM_BINDER( m_Bindings, ShaderCreationAttribsWrapper, SourceLanguage, SHADER_SOURCE_LANGUAGE, m_ShaderSourceLangEnumMapping ); + + DEFINE_BINDER( m_Bindings, ShaderCreationAttribsWrapper, Desc, ShaderDescLoader, 0 ) + }; + + void ShaderParser::CreateObj( lua_State *L ) + { + INIT_LUA_STACK_TRACKING( L ); + + ShaderCreationAttribsWrapper ShaderCreationAttrs; + ParseLuaTable( L, -1, &ShaderCreationAttrs, m_Bindings ); + + BasicShaderSourceStreamFactory BasicSSSFactory(ShaderCreationAttrs.SearchDirectories); + ShaderCreationAttrs.pShaderSourceStreamFactory = &BasicSSSFactory; + + CHECK_LUA_STACK_HEIGHT(); + + IShader **ppShader = reinterpret_cast( lua_newuserdata( L, sizeof( IShader* ) ) ); + *ppShader = nullptr; + m_pRenderDevice->CreateShader( ShaderCreationAttrs, ppShader ); + if( *ppShader == nullptr ) + SCRIPT_PARSING_ERROR(L, "Failed to create a shader") + + CHECK_LUA_STACK_HEIGHT( +1 ); + } + + void ShaderParser::ReadField( lua_State *L, void *pData, const Char *Field ) + { + ShaderCreationAttribsWrapper ShaderCreationAttrs; + auto *ppShader = reinterpret_cast(pData); + ShaderCreationAttrs.Desc = (*ppShader)->GetDesc(); + PushField( L, &ShaderCreationAttrs, Field, m_Bindings ); + } + + int ShaderParser::SetShaders( lua_State *L ) + { + // In order to communicate properly with Lua, a C function must use the following protocol, + // which defines the way parameters and results are passed : a C function receives its arguments + // from Lua in its PRIVATE stack in direct order( the first argument is pushed first ).So, when the + // function starts, lua_gettop( L ) returns the number of arguments received by the function.The first + // argument( if any ) is at index 1 and its last argument is at index lua_gettop( L ). + // To return values to Lua, a C function just pushes them onto the stack, in direct order + // ( the first result is pushed first ), and returns the number of results. + // Any other value in the stack below the results will be properly discarded by Lua. + // Like a Lua function, a C function called by Lua can also return many results. + + auto NumArgs = lua_gettop( L ); + const int MaxShaders = 6; + IShader* pShaders[MaxShaders] = {}; + VERIFY( NumArgs <= MaxShaders, "Too many shaders are being set" ); + NumArgs = std::min( NumArgs, MaxShaders ); + for( int i = 0; i < NumArgs; ++i ) + { + pShaders[i] = *GetUserData(L, i+1, m_MetatableRegistryName.c_str() ); + } + auto *pContext = LoadDeviceContextFromRegistry( L ); + pContext->SetShaders( pShaders, NumArgs ); + + // Returning no arguments + return 0; + } + + int ShaderParser::BindResources( lua_State *L ) + { + try + { + auto NumArgs = lua_gettop( L ); + if( NumArgs < 2 ) + { + SCRIPT_PARSING_ERROR( L, "At least 1 argument (resource mapping) is expected" ); + } + + auto *pShader = *GetUserData( L, 1, m_MetatableRegistryName.c_str() ); + VERIFY( pShader, "Shader pointer is null" ); + if( !pShader )return 0; + + auto *pResourceMapping = *GetUserData( L, 2, m_ResMappingMetatableName.c_str() ); + if( !pResourceMapping ) + { + SCRIPT_PARSING_ERROR( L, "Incorrect 1st argument type: resource mapping is expected" ); + } + + Uint32 Flags = 0; + // The last argument may be flags + const int FlagsArgInd = 3; + if( NumArgs >= FlagsArgInd && + (lua_type( L, FlagsArgInd ) == LUA_TSTRING || lua_type( L, FlagsArgInd ) == LUA_TTABLE ) ) + { + FlagsLoader FlagsLoader(0, "BindShaderResourceFlags", m_BindShaderResFlagEnumMapping); + FlagsLoader.SetValue( L, FlagsArgInd, &Flags ); + } + + + pShader->BindResources( pResourceMapping, Flags ); + } + catch( const std::runtime_error& ) + { + + } + + return 0; + } + +} diff --git a/RenderScript/src/ShaderVariableParser.cpp b/RenderScript/src/ShaderVariableParser.cpp new file mode 100644 index 0000000..35b5361 --- /dev/null +++ b/RenderScript/src/ShaderVariableParser.cpp @@ -0,0 +1,140 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "ShaderVariableParser.h" + +namespace Diligent +{ + const Char* ShaderVariableParser::ShaderVariableLibName = "ShaderVariable"; + + ShaderVariableParser::ShaderVariableParser( IRenderDevice *pRenderDevice, lua_State *L, + const String &ShaderLibMetatableName, + const String &BufferLibMetatableName, + const String &BufferViewLibMetatableName, + const String &TexViewMetatableName ) : + EngineObjectParserBase( pRenderDevice, L, ShaderVariableLibName ), + m_ShaderLibMetatableName(ShaderLibMetatableName), + m_BufferLibMetatableName(BufferLibMetatableName), + m_BufferViewLibMetatableName(BufferViewLibMetatableName), + m_TexViewMetatableName(TexViewMetatableName), + m_SetBinding( this, L, m_MetatableRegistryName.c_str(), "Set", &ShaderVariableParser::Set ), + m_GetShaderVariableBinding( this, L, m_ShaderLibMetatableName.c_str(), "GetShaderVariable", &ShaderVariableParser::GetShaderVariable ) + { + }; + + void ShaderVariableParser::CreateObj( lua_State *L ) + { + INIT_LUA_STACK_TRACKING(L); + + // Shader should be the first argument + auto *pShader = *GetUserData( L, 1, m_ShaderLibMetatableName.c_str() ); + + // Variable name should be the second argument + auto VarName = ReadValueFromLua( L, 2 ); + + auto pVar = pShader->GetShaderVariable( VarName.c_str() ); + + auto pNewShaderVarLuaObj = reinterpret_cast(lua_newuserdata( L, sizeof( IShaderVariable* ) )); + *pNewShaderVarLuaObj = pVar; + pVar->AddRef(); + + CHECK_LUA_STACK_HEIGHT( +1 ); + } + + void ShaderVariableParser::DestroyObj( void *pData ) + { + if( pData != nullptr ) + { + auto ppShaderVar = reinterpret_cast(pData); + if( *ppShaderVar != nullptr ) + (*ppShaderVar)->Release(); + } + } + + void ShaderVariableParser::ReadField( lua_State *L, void *pData, const Char *Field ) + { + SCRIPT_PARSING_ERROR(L, "Shader variables have no fields that can be read") + } + + void ShaderVariableParser::UpdateField( lua_State *L, void *pData, const Char *Field ) + { + SCRIPT_PARSING_ERROR(L, "Shader variables have no fields that can be updated") + } + + void ShaderVariableParser::PushExistingObject( lua_State *L, const void *pObject ) + { + auto pShaderVariable = reinterpret_cast(lua_newuserdata( L, sizeof( IShaderVariable* ) )); + *pShaderVariable = reinterpret_cast( const_cast(pObject) ); + (*pShaderVariable)->AddRef(); + } + + int ShaderVariableParser::Set( lua_State *L ) + { + // Shader variable is the first argument + auto *pShaderVar = *GetUserData( L, 1, m_MetatableRegistryName.c_str() ); + + IDeviceObject *pObject = nullptr; + auto ArgType = lua_type( L, 2 ); + if( ArgType == LUA_TUSERDATA ) + { + auto ppObject = reinterpret_cast( luaL_testudata( L, 2, m_BufferLibMetatableName.c_str() ) ); + if( !ppObject ) + ppObject = reinterpret_cast( luaL_testudata( L, 2, m_BufferViewLibMetatableName.c_str() ) ); + if( !ppObject ) + ppObject = reinterpret_cast( luaL_testudata( L, 2, m_TexViewMetatableName.c_str() ) ); + if( ppObject ) + { + pObject = *ppObject; + } + else + { + SCRIPT_PARSING_ERROR(L, "Set() function expects buffer, buffer view or texture view as an argument") + } + } + else if( ArgType == LUA_TNIL ) + { + pObject = nullptr; + } + else + { + SCRIPT_PARSING_ERROR(L, "Set() function expects user data or nil") + } + + pShaderVar->Set( pObject ); + + return 0; + } + + int ShaderVariableParser::GetShaderVariable( lua_State *L ) + { + return LuaCreate(L); + } + + void ShaderVariableParser::GetObjectByName( lua_State *L, const Char *ShaderName, IShaderVariable** ppObject ) + { + auto pObject = *GetGlobalObject( L, ShaderName, m_MetatableRegistryName.c_str() ); + *ppObject = pObject; + pObject->AddRef(); + } +} diff --git a/RenderScript/src/TextureParser.cpp b/RenderScript/src/TextureParser.cpp new file mode 100644 index 0000000..628c9a1 --- /dev/null +++ b/RenderScript/src/TextureParser.cpp @@ -0,0 +1,86 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "TextureParser.h" +#include "TextureViewParser.h" + +namespace Diligent +{ + const Char* TextureParser::TextureLibName = "Texture"; + + TextureParser::TextureParser( IRenderDevice *pRenderDevice, lua_State *L ) : + EngineObjectParserCommon( pRenderDevice, L, TextureLibName ) + { + DEFINE_BUFFERED_STRING_BINDER( m_Bindings, STexDescWrapper, Name, NameBuffer ) + + DEFINE_ENUM_BINDER( m_Bindings, STexDescWrapper, Type, TEXTURE_TYPE, m_TexTypeEnumMapping ); + + DEFINE_BINDER( m_Bindings, STexDescWrapper, Width, Uint32, Validator( "Width", 1, 16384 ) ); + DEFINE_BINDER( m_Bindings, STexDescWrapper, Height, Uint32, Validator( "Heihght", 1, 16384 ) ); + DEFINE_BINDER( m_Bindings, STexDescWrapper, ArraySize, Uint32, Validator( "ArraySize", 1, 16384 ) ); + DEFINE_BINDER( m_Bindings, STexDescWrapper, Depth, Uint32, Validator( "Depth", 1, 16384 ) ); + + DEFINE_ENUM_BINDER( m_Bindings, STexDescWrapper, Format, TEXTURE_FORMAT, m_TexFormatEnumMapping ); + + DEFINE_BINDER( m_Bindings, STexDescWrapper, MipLevels, Uint32, Validator( "MipLevels", 1, 20 ) ); + DEFINE_BINDER( m_Bindings, STexDescWrapper, SampleCount, Uint32, Validator( "SampleCount", 1, 32 ) ); + + //DEFINE_ENUM_ELEMENT_MAPPING( m_BindFlagEnumMapping, BIND_VERTEX_BUFFER ); + //DEFINE_ENUM_ELEMENT_MAPPING( m_BindFlagEnumMapping, BIND_INDEX_BUFFER ); + //DEFINE_ENUM_ELEMENT_MAPPING( m_BindFlagEnumMapping, BIND_UNIFORM_BUFFER ); + DEFINE_ENUM_ELEMENT_MAPPING( m_BindFlagEnumMapping, BIND_SHADER_RESOURCE ); + DEFINE_ENUM_ELEMENT_MAPPING( m_BindFlagEnumMapping, BIND_STREAM_OUTPUT ); + DEFINE_ENUM_ELEMENT_MAPPING( m_BindFlagEnumMapping, BIND_RENDER_TARGET ); + DEFINE_ENUM_ELEMENT_MAPPING( m_BindFlagEnumMapping, BIND_DEPTH_STENCIL ); + DEFINE_ENUM_ELEMENT_MAPPING( m_BindFlagEnumMapping, BIND_UNORDERED_ACCESS ); + //DEFINE_ENUM_ELEMENT_MAPPING( m_BindFlagEnumMapping, BIND_INDIRECT_DRAW_ARGS ); + // Explicit namespace declaraion is necesseary to avoid + // name conflicts when building for windows store + DEFINE_FLAGS_BINDER( m_Bindings, STexDescWrapper, BindFlags, Diligent::BIND_FLAGS, m_BindFlagEnumMapping ); + + DEFINE_ENUM_BINDER( m_Bindings, STexDescWrapper, Usage, USAGE, m_UsageEnumMapping ) + DEFINE_FLAGS_BINDER( m_Bindings, STexDescWrapper, CPUAccessFlags, CPU_ACCESS_FLAG, m_CpuAccessFlagEnumMapping ); + + DEFINE_ENUM_ELEMENT_MAPPING( m_MiscFlagEnumMapping, MISC_TEXTURE_FLAG_GENERATE_MIPS ); + DEFINE_FLAGS_BINDER( m_Bindings, STexDescWrapper, MiscFlags, Diligent::MISC_TEXTURE_FLAG, m_MiscFlagEnumMapping ); + }; + + void TextureParser::CreateObj( lua_State *L ) + { + INIT_LUA_STACK_TRACKING(L); + + STexDescWrapper TextureDesc; + ParseLuaTable( L, 1, &TextureDesc, m_Bindings ); + + CHECK_LUA_STACK_HEIGHT(); + + auto ppTexture = reinterpret_cast(lua_newuserdata( L, sizeof( ITexture* ) )); + *ppTexture = nullptr; + m_pRenderDevice->CreateTexture( TextureDesc, TextureData(), ppTexture ); + if( *ppTexture == nullptr ) + SCRIPT_PARSING_ERROR(L, "Failed to create a texture") + + CHECK_LUA_STACK_HEIGHT(+1); + } +} diff --git a/RenderScript/src/TextureViewParser.cpp b/RenderScript/src/TextureViewParser.cpp new file mode 100644 index 0000000..20ddabb --- /dev/null +++ b/RenderScript/src/TextureViewParser.cpp @@ -0,0 +1,138 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "TextureViewParser.h" +#include "TextureParser.h" +#include "SamplerParser.h" +#include "GraphicsUtilities.h" + +namespace Diligent +{ + const Char* TextureViewParser::TextureViewLibName = "TextureView"; + + TextureViewParser::TextureViewParser( TextureParser *pTexParser, + SamplerParser *pSamplerParser, + IRenderDevice *pRenderDevice, lua_State *L ) : + EngineObjectParserCommon( pRenderDevice, L, TextureViewLibName ), + m_TextureLibMetatableName(pTexParser->GetMetatableName()), + m_SamplerLibMetatableName( pSamplerParser->GetMetatableName() ), + m_CreateViewBinding( this, L, m_TextureLibMetatableName.c_str(), "CreateView", &TextureViewParser::CreateView ), + m_GetDefaultViewBinding( this, L, m_TextureLibMetatableName.c_str(), "GetDefaultView", &TextureViewParser::GetDefaultView ), + m_SetSamplerBinding( this, L, m_MetatableRegistryName.c_str(), "SetSampler", &TextureViewParser::SetSampler ), + m_ViewTypeParser( 0, "ViewType", m_ViewTypeEnumMapping ) + { + DEFINE_BUFFERED_STRING_BINDER( m_Bindings, STexViewDescWrapper, Name, NameBuffer ) + + DEFINE_ENUM_ELEMENT_MAPPING( m_ViewTypeEnumMapping, TEXTURE_VIEW_SHADER_RESOURCE ); + DEFINE_ENUM_ELEMENT_MAPPING( m_ViewTypeEnumMapping, TEXTURE_VIEW_RENDER_TARGET ); + DEFINE_ENUM_ELEMENT_MAPPING( m_ViewTypeEnumMapping, TEXTURE_VIEW_DEPTH_STENCIL ); + DEFINE_ENUM_ELEMENT_MAPPING( m_ViewTypeEnumMapping, TEXTURE_VIEW_UNORDERED_ACCESS ); + VERIFY( m_ViewTypeEnumMapping.m_Str2ValMap.size() == TEXTURE_VIEW_NUM_VIEWS - 1, + "Unexpected map size. Did you update TEXTURE_VIEW_TYPE enum?" ); + VERIFY( m_ViewTypeEnumMapping.m_Val2StrMap.size() == TEXTURE_VIEW_NUM_VIEWS - 1, + "Unexpected map size. Did you update TEXTURE_VIEW_TYPE enum?" ); + DEFINE_ENUM_BINDER( m_Bindings, STexViewDescWrapper, ViewType, TEXTURE_VIEW_TYPE, m_ViewTypeEnumMapping ); + + DEFINE_ENUM_BINDER( m_Bindings, STexViewDescWrapper, TextureType, TEXTURE_TYPE, m_TexTypeEnumMapping ); + DEFINE_ENUM_BINDER( m_Bindings, STexViewDescWrapper, Format, TEXTURE_FORMAT, m_TexFormatEnumMapping ); + + DEFINE_BINDER( m_Bindings, STexViewDescWrapper, MostDetailedMip, Uint32, Validator( "MostDetailedMip", 0, 16384 ) ); + DEFINE_BINDER( m_Bindings, STexViewDescWrapper, NumMipLevels, Uint32, Validator( "NumMipLevels", 1, 16384 ) ); + + // The following two members are in enum + DEFINE_BINDER( m_Bindings, STexViewDescWrapper, FirstArraySlice, Uint32, Validator( "FirstArraySlice", 0, 16384 ) ); + DEFINE_BINDER( m_Bindings, STexViewDescWrapper, FirstDepthSlice, Uint32, Validator( "FirstDepthSlice", 0, 16384 ) ); + + // The following two members are in enum + DEFINE_BINDER( m_Bindings, STexViewDescWrapper, NumArraySlices, Uint32, Validator( "NumArraySlices", 0, 16384 ) ); + DEFINE_BINDER( m_Bindings, STexViewDescWrapper, NumDepthSlices, Uint32, Validator( "NumDepthSlices", 0, 16384 ) ); + + DEFINE_ENUM_ELEMENT_MAPPING( m_UAVAccessFlagEnumMapping, UAV_ACCESS_FLAG_READ ); + DEFINE_ENUM_ELEMENT_MAPPING( m_UAVAccessFlagEnumMapping, UAV_ACCESS_FLAG_WRITE ); + DEFINE_ENUM_ELEMENT_MAPPING( m_UAVAccessFlagEnumMapping, UAV_ACCESS_FLAG_READ_WRITE ); + DEFINE_FLAGS_BINDER( m_Bindings, STexViewDescWrapper, AccessFlags, UAV_ACCESS_FLAG, m_UAVAccessFlagEnumMapping ); + }; + + void TextureViewParser::CreateObj( lua_State *L ) + { + INIT_LUA_STACK_TRACKING(L); + + auto *pTexture = *GetUserData( L, 1, m_TextureLibMetatableName.c_str() ); + + STexViewDescWrapper TextureViewDesc; + ParseLuaTable( L, 2, &TextureViewDesc, m_Bindings ); + CHECK_LUA_STACK_HEIGHT(); + + auto ppTextureView = reinterpret_cast(lua_newuserdata( L, sizeof( ITextureView* ) )); + *ppTextureView = nullptr; + pTexture->CreateView( TextureViewDesc, ppTextureView ); + if( *ppTextureView == nullptr ) + SCRIPT_PARSING_ERROR(L, "Failed to create texture view") + + CHECK_LUA_STACK_HEIGHT( +1 ); + } + + int TextureViewParser::CreateView( lua_State *L ) + { + // Note that LuaCreate is a static function. + // However, this pointer to the TextureViewParser object + // is stored in the upvalue. So LuaCreate will call + // TextureViewParser::CreateObj() + return LuaCreate(L); + } + + int TextureViewParser::GetDefaultView( lua_State *L ) + { + INIT_LUA_STACK_TRACKING( L ); + + // Texture should be the first argument + auto *pTexture = *GetUserData( L, 1, m_TextureLibMetatableName.c_str() ); + + // View type should be the second argument + TEXTURE_VIEW_TYPE ViewType; + m_ViewTypeParser.SetValue( L, 2, &ViewType ); + + auto pView = pTexture->GetDefaultView( ViewType ); + if( !pView ) + SCRIPT_PARSING_ERROR( L, "Failed to get default texture view of type ", GetTexViewTypeLiteralName( ViewType ) ); + + // Push existing object + PushObject(L, pView); + + CHECK_LUA_STACK_HEIGHT( +1 ); + + // Returning one value to Lua + return 1; + } + + int TextureViewParser::SetSampler( lua_State *L ) + { + auto *pTexView = *GetUserData( L, 1, m_MetatableRegistryName.c_str() ); + auto *pSampler = *GetUserData( L, 2, m_SamplerLibMetatableName.c_str() ); + pTexView->SetSampler( pSampler ); + + // Returning nothing + return 0; + } +} diff --git a/RenderScript/src/ViewportParser.cpp b/RenderScript/src/ViewportParser.cpp new file mode 100644 index 0000000..7afbfe6 --- /dev/null +++ b/RenderScript/src/ViewportParser.cpp @@ -0,0 +1,133 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "ViewportParser.h" + +namespace Diligent +{ + const Char* ViewportParser::ViewportLibName = "Viewport"; + + ViewportParser::ViewportParser( IRenderDevice *pRenderDevice, lua_State *L ) : + EngineObjectParserBase( pRenderDevice, L, ViewportLibName ), + m_SetViewportsBinding( this, L, "Context", "SetViewports", &ViewportParser::SetViewports ) + { + m_Viewports.reserve( 8 ); + + // NumVertices and NumIndices are in Union + DEFINE_BINDER( m_Bindings, Viewport, TopLeftX, Float32, Validator() ) + DEFINE_BINDER( m_Bindings, Viewport, TopLeftY, Float32, Validator() ) + DEFINE_BINDER( m_Bindings, Viewport, Width, Float32, Validator() ) + DEFINE_BINDER( m_Bindings, Viewport, Height, Float32, Validator() ) + DEFINE_BINDER( m_Bindings, Viewport, MinDepth, Float32, Validator() ) + DEFINE_BINDER( m_Bindings, Viewport, MaxDepth, Float32, Validator() ) + }; + + void ViewportParser::CreateObj( lua_State *L ) + { + INIT_LUA_STACK_TRACKING(L); + + Viewport VP; + ParseLuaTable( L, 1, &VP, m_Bindings ); + if( VP.Width < 0 ) + SCRIPT_PARSING_ERROR( L, "VP width (", VP.Width, ") cannot be negative" ); + if( VP.Height < 0 ) + SCRIPT_PARSING_ERROR( L, "VP height (", VP.Height, ") cannot be negative" ); + if( VP.MinDepth > VP.MaxDepth ) + SCRIPT_PARSING_ERROR( L, "VP depth range (", VP.MinDepth, ", ", VP.MaxDepth, ") is incorrect" ); + + CHECK_LUA_STACK_HEIGHT(); + + auto pViewport = reinterpret_cast(lua_newuserdata( L, sizeof( Viewport ) )); + memcpy(pViewport, &VP, sizeof(Viewport)); + + CHECK_LUA_STACK_HEIGHT( +1 ); + } + + void ViewportParser::DestroyObj( void *pData ) + { + // We do not need to do anything, because the whole object is + // created as full user data and thus managed by Lua + } + + void ViewportParser::ReadField( lua_State *L, void *pData, const Char *Field ) + { + auto pViewport = reinterpret_cast(pData); + PushField( L, pViewport, Field, m_Bindings ); + } + + void ViewportParser::UpdateField( lua_State *L, void *pData, const Char *Field ) + { + auto pViewport = reinterpret_cast(pData); + Diligent::UpdateField( L, -1, pViewport, Field, m_Bindings ); + } + + void ViewportParser::PushExistingObject( lua_State *L, const void *pObject ) + { + auto pViewport = reinterpret_cast(lua_newuserdata( L, sizeof( Viewport ) )); + memcpy( pViewport, pObject, sizeof( Viewport ) ); + } + + int ViewportParser::SetViewports( lua_State *L ) + { + auto *pContext = LoadDeviceContextFromRegistry( L ); + auto NumArgs = lua_gettop( L ); + if( NumArgs == 0 ) + pContext->SetViewports( 1, nullptr, 0, 0 ); + else + { + Uint32 RTWidth = 0; + Uint32 RTHeight = 0; + m_Viewports.clear(); + for( int Arg = 1; Arg <= NumArgs; ++Arg ) + { + if( lua_type( L, Arg ) == LUA_TUSERDATA ) + { + auto pViewport = GetUserData( L, Arg, m_MetatableRegistryName.c_str() ); + m_Viewports.emplace_back( *pViewport ); + } + else + { + if( RTWidth == 0 ) + RTWidth = ReadValueFromLua( L, Arg ); + else if( RTHeight == 0 ) + RTHeight = ReadValueFromLua( L, Arg ); + else + SCRIPT_PARSING_ERROR( L, "Render target size already specified (", RTWidth, "x", RTHeight, ")." ); + } + } + + if( RTWidth == 0 && RTHeight != 0 || RTWidth != 0 && RTHeight == 0 ) + SCRIPT_PARSING_ERROR( L, "Render target size is incomplete (", RTWidth, "x", RTHeight, "). Use either 0x0 or fully specified size" ); + + Uint32 NumViewports = static_cast( m_Viewports.size() ); + + if( NumViewports == 0 ) + SCRIPT_PARSING_ERROR( L, "At least one viewport must be specified" ); + + pContext->SetViewports( NumViewports, m_Viewports.data(), RTWidth, RTHeight ); + } + + return 0; + } +} diff --git a/RenderScript/src/pch.cpp b/RenderScript/src/pch.cpp new file mode 100644 index 0000000..4a893f2 --- /dev/null +++ b/RenderScript/src/pch.cpp @@ -0,0 +1,25 @@ +/* Copyright 2015 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" + -- cgit v1.2.3