Browse Source

Fix out of bounds array access related to RenderPathCommand outputs. Changed to store name and face within a pair. Added missing render path-related script bindings.

Lasse Öörni 10 years ago
parent
commit
03c517ebda

+ 27 - 22
Source/Urho3D/Graphics/RenderPath.cpp

@@ -171,14 +171,12 @@ void RenderPathCommand::Load(const XMLElement& element)
     }
     
     // By default use 1 output, which is the viewport
-    outputNames_.Resize(1);
-    outputFaces_.Resize(1);
-    outputNames_[0] = "viewport";
-    outputFaces_[0] = FACE_POSITIVE_X;
+    outputs_.Resize(1);
+    outputs_[0] = MakePair(String("viewport"), FACE_POSITIVE_X);
     if (element.HasAttribute("output"))
-        outputNames_[0] = element.GetAttribute("output");
+        outputs_[0].first_ = element.GetAttribute("output");
     if (element.HasAttribute("face"))
-        outputFaces_[0] = (CubeMapFace)element.GetInt("face");
+        outputs_[0].second_ = (CubeMapFace)element.GetInt("face");
     if (element.HasAttribute("depthstencil"))
         depthStencilName_ = element.GetAttribute("depthstencil");
     // Check for defining multiple outputs
@@ -188,10 +186,10 @@ void RenderPathCommand::Load(const XMLElement& element)
         unsigned index = outputElem.GetInt("index");
         if (index < MAX_RENDERTARGETS)
         {
-            if (index >= outputNames_.Size())
-                outputNames_.Resize(index + 1);
-            outputNames_[index] = outputElem.GetAttribute("name");
-            outputFaces_[index] = outputElem.HasAttribute("face") ? (CubeMapFace)outputElem.GetInt("face") : FACE_POSITIVE_X;
+            if (index >= outputs_.Size())
+                outputs_.Resize(index + 1);
+            outputs_[index].first_ = outputElem.GetAttribute("name");
+            outputs_[index].second_ = outputElem.HasAttribute("face") ? (CubeMapFace)outputElem.GetInt("face") : FACE_POSITIVE_X;
         }
         outputElem = outputElem.GetNext("output");
     }
@@ -231,24 +229,31 @@ void RenderPathCommand::RemoveShaderParameter(const String& name)
 void RenderPathCommand::SetNumOutputs(unsigned num)
 {
     num = Clamp((int)num, 1, MAX_RENDERTARGETS);
-    outputNames_.Resize(num);
-    outputFaces_.Resize(num);
+    outputs_.Resize(num);
+}
+
+void RenderPathCommand::SetOutput(unsigned index, const String& name, CubeMapFace face)
+{
+    if (index < outputs_.Size())
+        outputs_[index] = MakePair(name, face);
+    else if (index == outputs_.Size() && index < MAX_RENDERTARGETS)
+        outputs_.Push(MakePair(name, face));
 }
 
 void RenderPathCommand::SetOutputName(unsigned index, const String& name)
 {
-    if (index < outputNames_.Size())
-        outputNames_[index] = name;
-    else if (index == outputNames_.Size() && index < MAX_RENDERTARGETS)
-        outputNames_.Push(name);
+    if (index < outputs_.Size())
+        outputs_[index].first_ = name;
+    else if (index == outputs_.Size() && index < MAX_RENDERTARGETS)
+        outputs_.Push(MakePair(name, FACE_POSITIVE_X));
 }
 
 void RenderPathCommand::SetOutputFace(unsigned index, CubeMapFace face)
 {
-    if (index < outputFaces_.Size())
-        outputFaces_[index] = face;
-    else if (index == outputFaces_.Size() && index < MAX_RENDERTARGETS)
-        outputFaces_.Push(face);
+    if (index < outputs_.Size())
+        outputs_[index].second_ = face;
+    else if (index == outputs_.Size() && index < MAX_RENDERTARGETS)
+        outputs_.Push(MakePair(String::EMPTY, face));
 }
 
 
@@ -270,12 +275,12 @@ const Variant& RenderPathCommand::GetShaderParameter(const String& name) const
 
 const String& RenderPathCommand::GetOutputName(unsigned index) const
 {
-    return index < outputNames_.Size() ? outputNames_[index] : String::EMPTY;
+    return index < outputs_.Size() ? outputs_[index].first_ : String::EMPTY;
 }
 
 CubeMapFace RenderPathCommand::GetOutputFace(unsigned index) const
 {
-    return index < outputFaces_.Size() ? outputFaces_[index] : FACE_POSITIVE_X;
+    return index < outputs_.Size() ? outputs_[index].second_ : FACE_POSITIVE_X;
 }
 
 RenderPath::RenderPath()

+ 9 - 9
Source/Urho3D/Graphics/RenderPath.h

@@ -68,8 +68,8 @@ struct RenderTargetInfo
     RenderTargetInfo() :
         size_(Vector2::ZERO),
         sizeMode_(SIZE_ABSOLUTE),
-        cubemap_(false),
         enabled_(true),
+        cubemap_(false),
         filtered_(false),
         sRGB_(false),
         persistent_(false)
@@ -89,10 +89,10 @@ struct RenderTargetInfo
     Vector2 size_;
     /// Size mode.
     RenderTargetSizeMode sizeMode_;
-    /// Cube map flag.
-    bool cubemap_;
     /// Enabled flag.
     bool enabled_;
+    /// Cube map flag.
+    bool cubemap_;
     /// Filtering flag.
     bool filtered_;
     /// sRGB sampling/writing mode flag.
@@ -125,9 +125,11 @@ struct RenderPathCommand
     void RemoveShaderParameter(const String& name);
     /// Set number of output rendertargets.
     void SetNumOutputs(unsigned num);
+    /// Set output rendertarget name and face index for cube maps.
+    void SetOutput(unsigned index, const String& name, CubeMapFace face = FACE_POSITIVE_X);
     /// Set output rendertarget name.
     void SetOutputName(unsigned index, const String& name);
-    /// Set output rendertarget face index, in case rendertarget is a cube map.
+    /// Set output rendertarget face index for cube maps.
     void SetOutputFace(unsigned index, CubeMapFace face);
     /// Set depth-stencil output name. When empty, will assign a depth-stencil buffer automatically.
     void SetDepthStencilName(const String& name);
@@ -137,7 +139,7 @@ struct RenderPathCommand
     /// Return shader parameter.
     const Variant& GetShaderParameter(const String& name) const;
     /// Return number of output rendertargets.
-    unsigned GetNumOutputs() const { return outputNames_.Size(); }
+    unsigned GetNumOutputs() const { return outputs_.Size(); }
     /// Return output rendertarget name.
     const String& GetOutputName(unsigned index) const;
     /// Return output rendertarget face index.
@@ -169,10 +171,8 @@ struct RenderPathCommand
     String textureNames_[MAX_TEXTURE_UNITS];
     /// %Shader parameters.
     HashMap<StringHash, Variant> shaderParameters_;
-    /// Output rendertarget names.
-    Vector<String> outputNames_;
-    /// Output rendertarget faces.
-    Vector<CubeMapFace> outputFaces_;
+    /// Output rendertarget names and faces.
+    Vector<Pair<String, CubeMapFace> > outputs_;
     /// Depth-stencil output name.
     String depthStencilName_;
     /// Clear flags.

+ 13 - 13
Source/Urho3D/Graphics/View.cpp

@@ -436,7 +436,7 @@ bool View::Define(RenderSurface* renderTarget, Viewport* viewport)
             continue;
         
         // Check if ambient pass and G-buffer rendering happens at the same time
-        if (command.type_ == CMD_SCENEPASS && command.outputNames_.Size() > 1)
+        if (command.type_ == CMD_SCENEPASS && command.outputs_.Size() > 1)
         {
             if (CheckViewportWrite(command))
                 deferredAmbient_ = true;
@@ -1619,16 +1619,16 @@ void View::SetRenderTargets(RenderPathCommand& command)
     bool useColorWrite = true;
     bool useCustomDepth = false;
 
-    while (index < command.outputNames_.Size())
+    while (index < command.outputs_.Size())
     {
-        if (!command.outputNames_[index].Compare("viewport", false))
+        if (!command.outputs_[index].first_.Compare("viewport", false))
             graphics_->SetRenderTarget(index, currentRenderTarget_);
         else
         {
-            Texture* texture = FindNamedTexture(command.outputNames_[index], true, false);
+            Texture* texture = FindNamedTexture(command.outputs_[index].first_, true, false);
 
             // Check for depth only rendering (by specifying a depth texture as the sole output)
-            if (!index && command.outputNames_.Size() == 1 && texture && (texture->GetFormat() ==
+            if (!index && command.outputs_.Size() == 1 && texture && (texture->GetFormat() ==
                 Graphics::GetReadableDepthFormat() || texture->GetFormat() == Graphics::GetDepthStencilFormat()))
             {
                 useColorWrite = false;
@@ -1645,7 +1645,7 @@ void View::SetRenderTargets(RenderPathCommand& command)
                 graphics_->SetDepthStencil(GetRenderSurfaceFromTexture(texture));
             }
             else
-                graphics_->SetRenderTarget(index, GetRenderSurfaceFromTexture(texture, command.outputFaces_[index]));
+                graphics_->SetRenderTarget(index, GetRenderSurfaceFromTexture(texture, command.outputs_[index].second_));
         }
         
         ++index;
@@ -1777,7 +1777,7 @@ void View::RenderQuad(RenderPathCommand& command)
 
 bool View::IsNecessary(const RenderPathCommand& command)
 {
-    return command.enabled_ && command.outputNames_.Size() && (command.type_ != CMD_SCENEPASS ||
+    return command.enabled_ && command.outputs_.Size() && (command.type_ != CMD_SCENEPASS ||
         !batchQueues_[command.passIndex_].IsEmpty());
 }
 
@@ -1794,9 +1794,9 @@ bool View::CheckViewportRead(const RenderPathCommand& command)
 
 bool View::CheckViewportWrite(const RenderPathCommand& command)
 {
-    for (unsigned i = 0; i < command.outputNames_.Size(); ++i)
+    for (unsigned i = 0; i < command.outputs_.Size(); ++i)
     {
-        if (!command.outputNames_[i].Compare("viewport", false))
+        if (!command.outputs_[i].first_.Compare("viewport", false))
             return true;
     }
     
@@ -1849,7 +1849,7 @@ void View::AllocateScreenBuffers()
             const RenderPathCommand& command = renderPath_->commands_[i];
             if (!IsNecessary(command))
                 continue;
-            if (command.depthStencilName_.Length() && command.outputNames_.Size() && !command.outputNames_[0].Compare("viewport",
+            if (command.depthStencilName_.Length() && command.outputs_.Size() && !command.outputs_[0].first_.Compare("viewport",
                 false))
             {
                 needSubstitute = true;
@@ -1878,11 +1878,11 @@ void View::AllocateScreenBuffers()
                     continue;
                 if (command.depthStencilName_.Length())
                     needSubstitute = true;
-                if (!needSubstitute && command.outputNames_.Size() > 1)
+                if (!needSubstitute && command.outputs_.Size() > 1)
                 {
-                    for (unsigned j = 0; j < command.outputNames_.Size(); ++j)
+                    for (unsigned j = 0; j < command.outputs_.Size(); ++j)
                     {
-                        if (!command.outputNames_[j].Compare("viewport", false))
+                        if (!command.outputs_[j].first_.Compare("viewport", false))
                         {
                             needSubstitute = true;
                             break;

+ 32 - 0
Source/Urho3D/LuaScript/pkgs/Graphics/RenderPath.pkg

@@ -11,6 +11,37 @@ enum RenderCommandType
     CMD_RENDERUI
 };
 
+enum RenderCommandSortMode
+{
+    SORT_FRONTTOBACK = 0,
+    SORT_BACKTOFRONT
+};
+
+enum RenderTargetSizeMode
+{
+    SIZE_ABSOLUTE = 0,
+    SIZE_VIEWPORTDIVISOR,
+    SIZE_VIEWPORTMULTIPLIER
+};
+
+struct RenderTargetInfo
+{
+    RenderTargetInfo();
+
+    void Load(const XMLElement& element);
+
+    String name_ @ name;
+    String tag_ @ tag;
+    unsigned format_ @ format;
+    Vector2 size_ @ size;
+    RenderTargetSizeMode sizeMode_ @ sizemode;
+    bool enabled_ @ enabled;
+    bool cubemap_ @ cubemap;
+    bool filtered_ @ filtered;
+    bool sRGB_ @ sRGB;
+    bool persistent_ @ persistent;
+};
+
 struct RenderPathCommand
 {
     RenderPathCommand();
@@ -20,6 +51,7 @@ struct RenderPathCommand
     void SetShaderParameter(const String name, const Variant& value);
     void RemoveShaderParameter(const String name);
     void SetNumOutputs(unsigned num);
+    void SetOutput(unsigned index, const String name, CubeMapFace face);
     void SetOutputName(unsigned index, const String name);
     void SetOutputFace(unsigned index, CubeMapFace face);
     void SetDepthStencilName(const String name);

+ 6 - 1
Source/Urho3D/Script/GraphicsAPI.cpp

@@ -310,6 +310,10 @@ static void RegisterRenderPath(asIScriptEngine* engine)
     #endif
     engine->RegisterEnumValue("TextureUnit", "MAX_MATERIAL_TEXTURE_UNITS", MAX_MATERIAL_TEXTURE_UNITS);
     engine->RegisterEnumValue("TextureUnit", "MAX_TEXTURE_UNITS", MAX_TEXTURE_UNITS);
+
+    engine->RegisterGlobalProperty("uint CLEAR_COLOR", (void*)&CLEAR_COLOR);
+    engine->RegisterGlobalProperty("uint CLEAR_DEPTH", (void*)&CLEAR_DEPTH);
+    engine->RegisterGlobalProperty("uint CLEAR_STENCIL", (void*)&CLEAR_STENCIL);
     
     engine->RegisterObjectType("RenderTargetInfo", sizeof(RenderTargetInfo), asOBJ_VALUE | asOBJ_APP_CLASS_C);
     engine->RegisterObjectBehaviour("RenderTargetInfo", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ConstructRenderTargetInfo), asCALL_CDECL_OBJLAST);
@@ -321,8 +325,8 @@ static void RegisterRenderPath(asIScriptEngine* engine)
     engine->RegisterObjectProperty("RenderTargetInfo", "uint format", offsetof(RenderTargetInfo, format_));
     engine->RegisterObjectProperty("RenderTargetInfo", "Vector2 size", offsetof(RenderTargetInfo, size_));
     engine->RegisterObjectProperty("RenderTargetInfo", "RenderTargetSizeMode sizeMode", offsetof(RenderTargetInfo, sizeMode_));
-    engine->RegisterObjectProperty("RenderTargetInfo", "bool cubemap", offsetof(RenderTargetInfo, cubemap_));
     engine->RegisterObjectProperty("RenderTargetInfo", "bool enabled", offsetof(RenderTargetInfo, enabled_));
+    engine->RegisterObjectProperty("RenderTargetInfo", "bool cubemap", offsetof(RenderTargetInfo, cubemap_));
     engine->RegisterObjectProperty("RenderTargetInfo", "bool filtered", offsetof(RenderTargetInfo, filtered_));
     engine->RegisterObjectProperty("RenderTargetInfo", "bool sRGB", offsetof(RenderTargetInfo, sRGB_));
     engine->RegisterObjectProperty("RenderTargetInfo", "bool persistent", offsetof(RenderTargetInfo, persistent_));
@@ -332,6 +336,7 @@ static void RegisterRenderPath(asIScriptEngine* engine)
     engine->RegisterObjectBehaviour("RenderPathCommand", asBEHAVE_CONSTRUCT, "void f(const RenderPathCommand&in)", asFUNCTION(ConstructRenderPathCommandCopy), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectBehaviour("RenderPathCommand", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(DestructRenderPathCommand), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("RenderPathCommand", "void RemoveShaderParameter(const String&in)", asMETHOD(RenderPathCommand, RemoveShaderParameter), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RenderPathCommand", "void SetOutput(uint, const String&in, CubeMapFace face = FACE_POSITIVE_X)", asMETHOD(RenderPathCommand, SetOutput), asCALL_THISCALL);
     engine->RegisterObjectMethod("RenderPathCommand", "RenderPathCommand& opAssign(const RenderPathCommand&in)", asMETHODPR(RenderPathCommand, operator =, (const RenderPathCommand&), RenderPathCommand&), asCALL_THISCALL);
     engine->RegisterObjectMethod("RenderPathCommand", "void set_textureNames(TextureUnit, const String&in)", asMETHOD(RenderPathCommand, SetTextureName), asCALL_THISCALL);
     engine->RegisterObjectMethod("RenderPathCommand", "const String& get_textureNames(TextureUnit) const", asMETHOD(RenderPathCommand, GetTextureName), asCALL_THISCALL);