From 80f815cad9b10cafad4412cd21b801930ec33e47 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 20 Dec 2019 03:39:06 +0100 Subject: [PATCH] Fix the error handling: only create one call unless there's an error and only check for errors in functions that can fail --- Source/Core/Rendering/RenderDevice.cs | 160 ++++++---------- Source/Core/Rendering/Renderer2D.cs | 2 - Source/Native/Precomp.h | 2 + Source/Native/RenderDevice.cpp | 251 +++++++++++++------------- Source/Native/RenderDevice.h | 55 +++--- 5 files changed, 218 insertions(+), 252 deletions(-) diff --git a/Source/Core/Rendering/RenderDevice.cs b/Source/Core/Rendering/RenderDevice.cs index 6de80e40..f10357ba 100755 --- a/Source/Core/Rendering/RenderDevice.cs +++ b/Source/Core/Rendering/RenderDevice.cs @@ -64,16 +64,10 @@ namespace CodeImp.DoomBuilder.Rendering public bool Disposed { get { return Handle == IntPtr.Zero; } } - public void ClearError() + void ThrowIfFailed(bool result) { - RenderDevice_GetError(Handle); - } - - private void CheckAndThrow() - { - string err = Marshal.PtrToStringAnsi(RenderDevice_GetError(Handle)); - if (err != "") - throw new RenderDeviceException(err); + if (!result) + throw new RenderDeviceException(Marshal.PtrToStringAnsi(RenderDevice_GetError(Handle))); } public void Dispose() @@ -88,249 +82,208 @@ namespace CodeImp.DoomBuilder.Rendering public void SetShader(ShaderName shader) { RenderDevice_SetShader(Handle, shader); - CheckAndThrow(); } public void SetUniform(UniformName uniform, bool value) { RenderDevice_SetUniform(Handle, uniform, new float[] { value ? 1.0f : 0.0f }, 1); - CheckAndThrow(); } public void SetUniform(UniformName uniform, float value) { RenderDevice_SetUniform(Handle, uniform, new float[] { value }, 1); - CheckAndThrow(); } public void SetUniform(UniformName uniform, Vector2 value) { RenderDevice_SetUniform(Handle, uniform, new float[] { value.X, value.Y }, 2); - CheckAndThrow(); } public void SetUniform(UniformName uniform, Vector3 value) { RenderDevice_SetUniform(Handle, uniform, new float[] { value.X, value.Y, value.Z }, 3); - CheckAndThrow(); } public void SetUniform(UniformName uniform, Vector4 value) { RenderDevice_SetUniform(Handle, uniform, new float[] { value.X, value.Y, value.Z, value.W }, 4); - CheckAndThrow(); } public void SetUniform(UniformName uniform, Color4 value) { RenderDevice_SetUniform(Handle, uniform, new float[] { value.Red, value.Green, value.Blue, value.Alpha }, 4); - CheckAndThrow(); } public void SetUniform(UniformName uniform, Matrix matrix) { RenderDevice_SetUniform(Handle, uniform, ref matrix, 16); - CheckAndThrow(); } public void SetUniform(UniformName uniform, ref Matrix matrix) { RenderDevice_SetUniform(Handle, uniform, ref matrix, 16); - CheckAndThrow(); } public void SetVertexBuffer(VertexBuffer buffer) { RenderDevice_SetVertexBuffer(Handle, buffer != null ? buffer.Handle : IntPtr.Zero); - CheckAndThrow(); } public void SetIndexBuffer(IndexBuffer buffer) { RenderDevice_SetIndexBuffer(Handle, buffer != null ? buffer.Handle : IntPtr.Zero); - CheckAndThrow(); } public void SetAlphaBlendEnable(bool value) { RenderDevice_SetAlphaBlendEnable(Handle, value); - CheckAndThrow(); } public void SetAlphaTestEnable(bool value) { RenderDevice_SetAlphaTestEnable(Handle, value); - CheckAndThrow(); } public void SetCullMode(Cull mode) { RenderDevice_SetCullMode(Handle, mode); - CheckAndThrow(); } public void SetBlendOperation(BlendOperation op) { RenderDevice_SetBlendOperation(Handle, op); - CheckAndThrow(); } public void SetSourceBlend(Blend blend) { RenderDevice_SetSourceBlend(Handle, blend); - CheckAndThrow(); } public void SetDestinationBlend(Blend blend) { RenderDevice_SetDestinationBlend(Handle, blend); - CheckAndThrow(); } public void SetFillMode(FillMode mode) { RenderDevice_SetFillMode(Handle, mode); - CheckAndThrow(); } public void SetMultisampleAntialias(bool value) { RenderDevice_SetMultisampleAntialias(Handle, value); - CheckAndThrow(); } public void SetZEnable(bool value) { RenderDevice_SetZEnable(Handle, value); - CheckAndThrow(); } public void SetZWriteEnable(bool value) { RenderDevice_SetZWriteEnable(Handle, value); - CheckAndThrow(); } public void SetTexture(BaseTexture value) { RenderDevice_SetTexture(Handle, value != null ? value.Handle : IntPtr.Zero); - CheckAndThrow(); } public void SetSamplerFilter(TextureFilter filter) { SetSamplerFilter(filter, filter, TextureFilter.None, 0.0f); - CheckAndThrow(); } public void SetSamplerFilter(TextureFilter minfilter, TextureFilter magfilter, TextureFilter mipfilter, float maxanisotropy) { RenderDevice_SetSamplerFilter(Handle, minfilter, magfilter, mipfilter, maxanisotropy); - CheckAndThrow(); } public void SetSamplerState(TextureAddress address) { RenderDevice_SetSamplerState(Handle, address); - CheckAndThrow(); } public void DrawIndexed(PrimitiveType type, int startIndex, int primitiveCount) { - RenderDevice_DrawIndexed(Handle, type, startIndex, primitiveCount); - CheckAndThrow(); + ThrowIfFailed(RenderDevice_DrawIndexed(Handle, type, startIndex, primitiveCount)); } public void Draw(PrimitiveType type, int startIndex, int primitiveCount) { - RenderDevice_Draw(Handle, type, startIndex, primitiveCount); - CheckAndThrow(); + ThrowIfFailed(RenderDevice_Draw(Handle, type, startIndex, primitiveCount)); } public void Draw(PrimitiveType type, int startIndex, int primitiveCount, FlatVertex[] data) { - RenderDevice_DrawData(Handle, type, startIndex, primitiveCount, data); - CheckAndThrow(); + ThrowIfFailed(RenderDevice_DrawData(Handle, type, startIndex, primitiveCount, data)); } public void StartRendering(bool clear, Color4 backcolor) { - RenderDevice_StartRendering(Handle, clear, backcolor.ToArgb(), IntPtr.Zero, true); - CheckAndThrow(); + ThrowIfFailed(RenderDevice_StartRendering(Handle, clear, backcolor.ToArgb(), IntPtr.Zero, true)); } public void StartRendering(bool clear, Color4 backcolor, Texture target, bool usedepthbuffer) { - RenderDevice_StartRendering(Handle, clear, backcolor.ToArgb(), target.Handle, usedepthbuffer); - CheckAndThrow(); + ThrowIfFailed(RenderDevice_StartRendering(Handle, clear, backcolor.ToArgb(), target.Handle, usedepthbuffer)); } public void FinishRendering() { - RenderDevice_FinishRendering(Handle); - CheckAndThrow(); + ThrowIfFailed(RenderDevice_FinishRendering(Handle)); } public void Present() { - RenderDevice_Present(Handle); - CheckAndThrow(); + ThrowIfFailed(RenderDevice_Present(Handle)); } public void ClearTexture(Color4 backcolor, Texture texture) { - RenderDevice_ClearTexture(Handle, backcolor.ToArgb(), texture.Handle); - CheckAndThrow(); + ThrowIfFailed(RenderDevice_ClearTexture(Handle, backcolor.ToArgb(), texture.Handle)); } public void CopyTexture(CubeTexture dst, CubeMapFace face) { - RenderDevice_CopyTexture(Handle, dst.Handle, face); - CheckAndThrow(); + ThrowIfFailed(RenderDevice_CopyTexture(Handle, dst.Handle, face)); } public void SetBufferData(IndexBuffer buffer, int[] data) { - RenderDevice_SetIndexBufferData(Handle, buffer.Handle, data, data.Length * Marshal.SizeOf()); - CheckAndThrow(); + ThrowIfFailed(RenderDevice_SetIndexBufferData(Handle, buffer.Handle, data, data.Length * Marshal.SizeOf())); } public void SetBufferData(VertexBuffer buffer, int length, VertexFormat format) { int stride = (format == VertexFormat.Flat) ? FlatVertex.Stride : WorldVertex.Stride; - RenderDevice_SetVertexBufferData(Handle, buffer.Handle, IntPtr.Zero, length * stride, format); - CheckAndThrow(); + ThrowIfFailed(RenderDevice_SetVertexBufferData(Handle, buffer.Handle, IntPtr.Zero, length * stride, format)); } public void SetBufferData(VertexBuffer buffer, FlatVertex[] data) { - RenderDevice_SetVertexBufferData(Handle, buffer.Handle, data, data.Length * Marshal.SizeOf(), VertexFormat.Flat); - CheckAndThrow(); + ThrowIfFailed(RenderDevice_SetVertexBufferData(Handle, buffer.Handle, data, data.Length * Marshal.SizeOf(), VertexFormat.Flat)); } public void SetBufferData(VertexBuffer buffer, WorldVertex[] data) { - RenderDevice_SetVertexBufferData(Handle, buffer.Handle, data, data.Length * Marshal.SizeOf(), VertexFormat.World); - CheckAndThrow(); + ThrowIfFailed(RenderDevice_SetVertexBufferData(Handle, buffer.Handle, data, data.Length * Marshal.SizeOf(), VertexFormat.World)); } public void SetBufferSubdata(VertexBuffer buffer, long destOffset, FlatVertex[] data) { - RenderDevice_SetVertexBufferSubdata(Handle, buffer.Handle, destOffset * FlatVertex.Stride, data, data.Length * FlatVertex.Stride); - CheckAndThrow(); + ThrowIfFailed(RenderDevice_SetVertexBufferSubdata(Handle, buffer.Handle, destOffset * FlatVertex.Stride, data, data.Length * FlatVertex.Stride)); } public void SetBufferSubdata(VertexBuffer buffer, long destOffset, WorldVertex[] data) { - RenderDevice_SetVertexBufferSubdata(Handle, buffer.Handle, destOffset * WorldVertex.Stride, data, data.Length * WorldVertex.Stride); - CheckAndThrow(); + ThrowIfFailed(RenderDevice_SetVertexBufferSubdata(Handle, buffer.Handle, destOffset * WorldVertex.Stride, data, data.Length * WorldVertex.Stride)); } public void SetBufferSubdata(VertexBuffer buffer, FlatVertex[] data, long size) { if (size < 0 || size > data.Length) throw new ArgumentOutOfRangeException("size"); - RenderDevice_SetVertexBufferSubdata(Handle, buffer.Handle, 0, data, size * FlatVertex.Stride); - CheckAndThrow(); + ThrowIfFailed(RenderDevice_SetVertexBufferSubdata(Handle, buffer.Handle, 0, data, size * FlatVertex.Stride)); } public void SetPixels(Texture texture, System.Drawing.Bitmap bitmap) @@ -340,10 +293,14 @@ namespace CodeImp.DoomBuilder.Rendering System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); - RenderDevice_SetPixels(Handle, texture.Handle, bmpdata.Scan0); - - bitmap.UnlockBits(bmpdata); - CheckAndThrow(); + try + { + ThrowIfFailed(RenderDevice_SetPixels(Handle, texture.Handle, bmpdata.Scan0)); + } + finally + { + bitmap.UnlockBits(bmpdata); + } } public void SetPixels(CubeTexture texture, CubeMapFace face, System.Drawing.Bitmap bitmap) @@ -353,29 +310,31 @@ namespace CodeImp.DoomBuilder.Rendering System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); - RenderDevice_SetCubePixels(Handle, texture.Handle, face, bmpdata.Scan0); - - bitmap.UnlockBits(bmpdata); - CheckAndThrow(); + try + { + ThrowIfFailed(RenderDevice_SetCubePixels(Handle, texture.Handle, face, bmpdata.Scan0)); + } + finally + { + bitmap.UnlockBits(bmpdata); + } } public unsafe void SetPixels(Texture texture, uint* pixeldata) { - RenderDevice_SetPixels(Handle, texture.Handle, new IntPtr(pixeldata)); - CheckAndThrow(); + ThrowIfFailed(RenderDevice_SetPixels(Handle, texture.Handle, new IntPtr(pixeldata))); } public unsafe void* MapPBO(Texture texture) { void* ptr = RenderDevice_MapPBO(Handle, texture.Handle).ToPointer(); - CheckAndThrow(); + ThrowIfFailed(ptr != null); return ptr; } public void UnmapPBO(Texture texture) { - RenderDevice_UnmapPBO(Handle, texture.Handle); - CheckAndThrow(); + ThrowIfFailed(RenderDevice_UnmapPBO(Handle, texture.Handle)); } internal void RegisterResource(IRenderResource res) @@ -427,13 +386,13 @@ namespace CodeImp.DoomBuilder.Rendering static extern IntPtr RenderDevice_GetError(IntPtr handle); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr RenderDevice_SetShader(IntPtr handle, ShaderName name); + static extern bool RenderDevice_SetShader(IntPtr handle, ShaderName name); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr RenderDevice_SetUniform(IntPtr handle, UniformName name, float[] data, int count); + static extern void RenderDevice_SetUniform(IntPtr handle, UniformName name, float[] data, int count); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr RenderDevice_SetUniform(IntPtr handle, UniformName name, ref Matrix data, int count); + static extern void RenderDevice_SetUniform(IntPtr handle, UniformName name, ref Matrix data, int count); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] static extern void RenderDevice_SetVertexBuffer(IntPtr handle, IntPtr buffer); @@ -481,61 +440,58 @@ namespace CodeImp.DoomBuilder.Rendering static extern void RenderDevice_SetSamplerState(IntPtr handle, TextureAddress address); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] - static extern void RenderDevice_Draw(IntPtr handle, PrimitiveType type, int startIndex, int primitiveCount); + static extern bool RenderDevice_Draw(IntPtr handle, PrimitiveType type, int startIndex, int primitiveCount); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] - static extern void RenderDevice_DrawIndexed(IntPtr handle, PrimitiveType type, int startIndex, int primitiveCount); + static extern bool RenderDevice_DrawIndexed(IntPtr handle, PrimitiveType type, int startIndex, int primitiveCount); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] - static extern void RenderDevice_DrawData(IntPtr handle, PrimitiveType type, int startIndex, int primitiveCount, FlatVertex[] data); + static extern bool RenderDevice_DrawData(IntPtr handle, PrimitiveType type, int startIndex, int primitiveCount, FlatVertex[] data); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] - static extern void RenderDevice_StartRendering(IntPtr handle, bool clear, int backcolor); + static extern bool RenderDevice_StartRendering(IntPtr handle, bool clear, int backcolor, IntPtr target, bool usedepthbuffer); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] - static extern void RenderDevice_StartRendering(IntPtr handle, bool clear, int backcolor, IntPtr target, bool usedepthbuffer); + static extern bool RenderDevice_FinishRendering(IntPtr handle); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] - static extern void RenderDevice_FinishRendering(IntPtr handle); + static extern bool RenderDevice_Present(IntPtr handle); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] - static extern void RenderDevice_Present(IntPtr handle); + static extern bool RenderDevice_ClearTexture(IntPtr handle, int backcolor, IntPtr texture); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] - static extern void RenderDevice_ClearTexture(IntPtr handle, int backcolor, IntPtr texture); + static extern bool RenderDevice_CopyTexture(IntPtr handle, IntPtr dst, CubeMapFace face); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] - static extern void RenderDevice_CopyTexture(IntPtr handle, IntPtr dst, CubeMapFace face); + static extern bool RenderDevice_SetIndexBufferData(IntPtr handle, IntPtr buffer, int[] data, long size); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] - static extern void RenderDevice_SetIndexBufferData(IntPtr handle, IntPtr buffer, int[] data, long size); + static extern bool RenderDevice_SetVertexBufferData(IntPtr handle, IntPtr buffer, IntPtr data, long size, VertexFormat format); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] - static extern void RenderDevice_SetVertexBufferData(IntPtr handle, IntPtr buffer, IntPtr data, long size, VertexFormat format); + static extern bool RenderDevice_SetVertexBufferData(IntPtr handle, IntPtr buffer, FlatVertex[] data, long size, VertexFormat format); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] - static extern void RenderDevice_SetVertexBufferData(IntPtr handle, IntPtr buffer, FlatVertex[] data, long size, VertexFormat format); + static extern bool RenderDevice_SetVertexBufferData(IntPtr handle, IntPtr buffer, WorldVertex[] data, long size, VertexFormat format); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] - static extern void RenderDevice_SetVertexBufferData(IntPtr handle, IntPtr buffer, WorldVertex[] data, long size, VertexFormat format); + static extern bool RenderDevice_SetVertexBufferSubdata(IntPtr handle, IntPtr buffer, long destOffset, FlatVertex[] data, long sizeInBytes); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] - static extern void RenderDevice_SetVertexBufferSubdata(IntPtr handle, IntPtr buffer, long destOffset, FlatVertex[] data, long sizeInBytes); + static extern bool RenderDevice_SetVertexBufferSubdata(IntPtr handle, IntPtr buffer, long destOffset, WorldVertex[] data, long sizeInBytes); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] - static extern void RenderDevice_SetVertexBufferSubdata(IntPtr handle, IntPtr buffer, long destOffset, WorldVertex[] data, long sizeInBytes); - - [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] - protected static extern void RenderDevice_SetPixels(IntPtr handle, IntPtr texture, IntPtr data); + protected static extern bool RenderDevice_SetPixels(IntPtr handle, IntPtr texture, IntPtr data); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] protected static extern IntPtr RenderDevice_MapPBO(IntPtr handle, IntPtr texture); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] - protected static extern void RenderDevice_UnmapPBO(IntPtr handle, IntPtr texture); + protected static extern bool RenderDevice_UnmapPBO(IntPtr handle, IntPtr texture); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] - protected static extern void RenderDevice_SetCubePixels(IntPtr handle, IntPtr texture, CubeMapFace face, IntPtr data); + protected static extern bool RenderDevice_SetCubePixels(IntPtr handle, IntPtr texture, CubeMapFace face, IntPtr data); //mxd. Anisotropic filtering steps public static readonly List AF_STEPS = new List { 1.0f, 2.0f, 4.0f, 8.0f, 16.0f }; diff --git a/Source/Core/Rendering/Renderer2D.cs b/Source/Core/Rendering/Renderer2D.cs index 23ad6721..f2c868fb 100755 --- a/Source/Core/Rendering/Renderer2D.cs +++ b/Source/Core/Rendering/Renderer2D.cs @@ -349,8 +349,6 @@ namespace CodeImp.DoomBuilder.Rendering // Destroy rendertargets DestroyRendertargets(); - graphics.ClearError(); - // Get new width and height windowsize.Width = graphics.RenderTarget.ClientSize.Width; windowsize.Height = graphics.RenderTarget.ClientSize.Height; diff --git a/Source/Native/Precomp.h b/Source/Native/Precomp.h index 31726328..d20b7333 100644 --- a/Source/Native/Precomp.h +++ b/Source/Native/Precomp.h @@ -1,5 +1,7 @@ #pragma once +#define _CRT_SECURE_NO_WARNINGS + #include #include #include diff --git a/Source/Native/RenderDevice.cpp b/Source/Native/RenderDevice.cpp index 11e48e7a..1b7121f9 100644 --- a/Source/Native/RenderDevice.cpp +++ b/Source/Native/RenderDevice.cpp @@ -49,9 +49,6 @@ RenderDevice::RenderDevice(void* disp, void* window) DeclareUniform(UniformName::ignoreNormals, "ignoreNormals", UniformType::Float); DeclareUniform(UniformName::spotLight, "spotLight", UniformType::Float); - memset(mLastError, 0, sizeof(mLastError)); - memset(mReturnError, 0, sizeof(mReturnError)); - Context = IOpenGLContext::Create(disp, window); if (Context) { @@ -303,35 +300,29 @@ void RenderDevice::SetSamplerState(TextureAddress address) } } -void RenderDevice::ApplyViewport() -{ - glViewport(0, 0, mViewportWidth, mViewportHeight); - CheckGLError(); -} - -void RenderDevice::Draw(PrimitiveType type, int startIndex, int primitiveCount) +bool RenderDevice::Draw(PrimitiveType type, int startIndex, int primitiveCount) { static const int modes[] = { GL_LINES, GL_TRIANGLES, GL_TRIANGLE_STRIP }; static const int toVertexCount[] = { 2, 3, 1 }; static const int toVertexStart[] = { 0, 0, 2 }; - if (mNeedApply) ApplyChanges(); + if (mNeedApply && !ApplyChanges()) return false; glDrawArrays(modes[(int)type], mVertexBufferStartIndex + startIndex, toVertexStart[(int)type] + primitiveCount * toVertexCount[(int)type]); - CheckGLError(); + return CheckGLError(); } -void RenderDevice::DrawIndexed(PrimitiveType type, int startIndex, int primitiveCount) +bool RenderDevice::DrawIndexed(PrimitiveType type, int startIndex, int primitiveCount) { static const int modes[] = { GL_LINES, GL_TRIANGLES, GL_TRIANGLE_STRIP }; static const int toVertexCount[] = { 2, 3, 1 }; static const int toVertexStart[] = { 0, 0, 2 }; - if (mNeedApply) ApplyChanges(); + if (mNeedApply && !ApplyChanges()) return false; glDrawElementsBaseVertex(modes[(int)type], toVertexStart[(int)type] + primitiveCount * toVertexCount[(int)type], GL_UNSIGNED_INT, (const void*)(startIndex * sizeof(uint32_t)), mVertexBufferStartIndex); - CheckGLError(); + return CheckGLError(); } -void RenderDevice::DrawData(PrimitiveType type, int startIndex, int primitiveCount, const void* data) +bool RenderDevice::DrawData(PrimitiveType type, int startIndex, int primitiveCount, const void* data) { static const int modes[] = { GL_LINES, GL_TRIANGLES, GL_TRIANGLE_STRIP }; static const int toVertexCount[] = { 2, 3, 1 }; @@ -339,17 +330,18 @@ void RenderDevice::DrawData(PrimitiveType type, int startIndex, int primitiveCou int vertcount = toVertexStart[(int)type] + primitiveCount * toVertexCount[(int)type]; - if (mNeedApply) ApplyChanges(); + if (mNeedApply && !ApplyChanges()) return false; glBindBuffer(GL_ARRAY_BUFFER, mStreamVertexBuffer); glBufferData(GL_ARRAY_BUFFER, vertcount * (size_t)SharedVertexBuffer::FlatStride, static_cast(data) + startIndex * (size_t)SharedVertexBuffer::FlatStride, GL_STREAM_DRAW); glBindVertexArray(mStreamVAO); glDrawArrays(modes[(int)type], 0, vertcount); - ApplyVertexBuffer(); - CheckGLError(); + if (!CheckGLError()) return false; + + return ApplyVertexBuffer(); } -void RenderDevice::StartRendering(bool clear, int backcolor, Texture* target, bool usedepthbuffer) +bool RenderDevice::StartRendering(bool clear, int backcolor, Texture* target, bool usedepthbuffer) { Context->MakeCurrent(); mContextIsCurrent = true; @@ -364,18 +356,19 @@ void RenderDevice::StartRendering(bool clear, int backcolor, Texture* target, bo catch (std::runtime_error& e) { SetError("Error setting render target: %s", e.what()); + return false; } glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); mViewportWidth = target->GetWidth(); mViewportHeight = target->GetHeight(); - ApplyViewport(); + if (!ApplyViewport()) return false; } else { glBindFramebuffer(GL_FRAMEBUFFER, 0); mViewportWidth = Context->GetWidth(); mViewportHeight = Context->GetHeight(); - ApplyViewport(); + if (!ApplyViewport()) return false; } if (clear && usedepthbuffer) @@ -402,29 +395,29 @@ void RenderDevice::StartRendering(bool clear, int backcolor, Texture* target, bo mBlendStateChanged = true; mRasterizerStateChanged = true; - CheckGLError(); + return CheckGLError(); } -void RenderDevice::FinishRendering() +bool RenderDevice::FinishRendering() { Context->ClearCurrent(); mContextIsCurrent = false; + return true; } -void RenderDevice::Present() +bool RenderDevice::Present() { Context->SwapBuffers(); - CheckGLError(); + return CheckGLError(); } -void RenderDevice::ClearTexture(int backcolor, Texture* texture) +bool RenderDevice::ClearTexture(int backcolor, Texture* texture) { - StartRendering(true, backcolor, texture, false); - FinishRendering(); - CheckGLError(); + if (!StartRendering(true, backcolor, texture, false)) return false; + return FinishRendering(); } -void RenderDevice::CopyTexture(Texture* dst, CubeMapFace face) +bool RenderDevice::CopyTexture(Texture* dst, CubeMapFace face) { static const GLenum facegl[] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X, @@ -445,11 +438,12 @@ void RenderDevice::CopyTexture(Texture* dst, CubeMapFace face) glGenerateMipmap(GL_TEXTURE_CUBE_MAP); glBindTexture(GL_TEXTURE_CUBE_MAP, oldTexture); - CheckGLError(); + bool result = CheckGLError(); if (!mContextIsCurrent) Context->ClearCurrent(); + return result; } -void RenderDevice::SetVertexBufferData(VertexBuffer* buffer, void* data, int64_t size, VertexFormat format) +bool RenderDevice::SetVertexBufferData(VertexBuffer* buffer, void* data, int64_t size, VertexFormat format) { if (!mContextIsCurrent) Context->MakeCurrent(); @@ -490,11 +484,12 @@ void RenderDevice::SetVertexBufferData(VertexBuffer* buffer, void* data, int64_t glBufferSubData(GL_ARRAY_BUFFER, buffer->BufferOffset, size, data); glBindBuffer(GL_ARRAY_BUFFER, oldbinding); - CheckGLError(); + bool result = CheckGLError(); if (!mContextIsCurrent) Context->ClearCurrent(); + return result; } -void RenderDevice::SetVertexBufferSubdata(VertexBuffer* buffer, int64_t destOffset, void* data, int64_t size) +bool RenderDevice::SetVertexBufferSubdata(VertexBuffer* buffer, int64_t destOffset, void* data, int64_t size) { if (!mContextIsCurrent) Context->MakeCurrent(); GLint oldbinding = 0; @@ -502,11 +497,12 @@ void RenderDevice::SetVertexBufferSubdata(VertexBuffer* buffer, int64_t destOffs glBindBuffer(GL_ARRAY_BUFFER, mSharedVertexBuffers[(int)buffer->Format]->GetBuffer()); glBufferSubData(GL_ARRAY_BUFFER, buffer->BufferOffset + destOffset, size, data); glBindBuffer(GL_ARRAY_BUFFER, oldbinding); - CheckGLError(); + bool result = CheckGLError(); if (!mContextIsCurrent) Context->ClearCurrent(); + return result; } -void RenderDevice::SetIndexBufferData(IndexBuffer* buffer, void* data, int64_t size) +bool RenderDevice::SetIndexBufferData(IndexBuffer* buffer, void* data, int64_t size) { if (!mContextIsCurrent) Context->MakeCurrent(); GLint oldbinding = 0; @@ -514,22 +510,21 @@ void RenderDevice::SetIndexBufferData(IndexBuffer* buffer, void* data, int64_t s glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer->GetBuffer()); glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, oldbinding); - CheckGLError(); + bool result = CheckGLError(); if (!mContextIsCurrent) Context->ClearCurrent(); + return result; } -void RenderDevice::SetPixels(Texture* texture, const void* data) +bool RenderDevice::SetPixels(Texture* texture, const void* data) { texture->SetPixels(data); - InvalidateTexture(texture); - CheckGLError(); + return InvalidateTexture(texture); } -void RenderDevice::SetCubePixels(Texture* texture, CubeMapFace face, const void* data) +bool RenderDevice::SetCubePixels(Texture* texture, CubeMapFace face, const void* data) { texture->SetCubePixels(face, data); - InvalidateTexture(texture); - CheckGLError(); + return InvalidateTexture(texture); } void* RenderDevice::MapPBO(Texture* texture) @@ -538,12 +533,17 @@ void* RenderDevice::MapPBO(Texture* texture) GLint pbo = texture->GetPBO(); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo); void* buf = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); - CheckGLError(); + bool result = CheckGLError(); + if (!result && buf) + { + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + buf = nullptr; + } if (!mContextIsCurrent) Context->ClearCurrent(); return buf; } -void RenderDevice::UnmapPBO(Texture* texture) +bool RenderDevice::UnmapPBO(Texture* texture) { if (!mContextIsCurrent) Context->MakeCurrent(); GLint pbo = texture->GetPBO(); @@ -551,35 +551,43 @@ void RenderDevice::UnmapPBO(Texture* texture) glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); glBindTexture(GL_TEXTURE_2D, texture->GetTexture()); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texture->GetWidth(), texture->GetHeight(), 0, GL_BGRA, GL_UNSIGNED_BYTE, nullptr); - CheckGLError(); + bool result = CheckGLError(); if (!mContextIsCurrent) Context->ClearCurrent(); mNeedApply = true; mTexturesChanged = true; + return result; } -void RenderDevice::InvalidateTexture(Texture* texture) +bool RenderDevice::InvalidateTexture(Texture* texture) { if (texture->IsTextureCreated()) { if (!mContextIsCurrent) Context->MakeCurrent(); texture->Invalidate(); - CheckGLError(); + bool result = CheckGLError(); if (!mContextIsCurrent) Context->ClearCurrent(); mNeedApply = true; mTexturesChanged = true; + return result; + } + else + { + return true; } } bool RenderDevice::CheckGLError() { - // on Windows, "no context" is a GL_INVALID_OPERATION error - GLenum error = glGetError(); - if (error != GL_NO_ERROR && Context->IsCurrent()) + if (!Context->IsCurrent()) { - SetError("OpenGL error: %d", error); - return true; + SetError("Unexpected current OpenGL context"); } + GLenum error = glGetError(); + if (error == GL_NO_ERROR) + return true; + + SetError("OpenGL error: %d", error); return false; } @@ -587,16 +595,18 @@ void RenderDevice::SetError(const char* fmt, ...) { va_list va; va_start(va, fmt); - mLastError[sizeof(mLastError) - 1] = 0; - _vsnprintf(mLastError, sizeof(mLastError)-1, fmt, va); + mSetErrorBuffer[0] = 0; + mSetErrorBuffer[sizeof(mSetErrorBuffer) - 1] = 0; + _vsnprintf(mSetErrorBuffer, sizeof(mSetErrorBuffer)-1, fmt, va); va_end(va); + mLastError = mSetErrorBuffer; } const char* RenderDevice::GetError() { - memcpy(mReturnError, mLastError, sizeof(mReturnError)); - mLastError[0] = 0; - return mReturnError; + mReturnError.swap(mLastError); + mLastError.clear(); + return mReturnError.c_str(); } Shader* RenderDevice::GetActiveShader() @@ -630,44 +640,43 @@ void RenderDevice::SetUniform(UniformName name, const void* values, int count) } } -void RenderDevice::ApplyChanges() +bool RenderDevice::ApplyChanges() { - if (mShaderChanged) - ApplyShader(); - if (mVertexBufferChanged) - ApplyVertexBuffer(); - if (mIndexBufferChanged) - ApplyIndexBuffer(); - if (mUniformsChanged) - ApplyUniforms(); - if (mTexturesChanged) - ApplyTextures(); - if (mRasterizerStateChanged) - ApplyRasterizerState(); - if (mBlendStateChanged) - ApplyBlendState(); - if (mDepthStateChanged) - ApplyDepthState(); + if (mShaderChanged && !ApplyShader()) return false; + if (mVertexBufferChanged && !ApplyVertexBuffer()) return false; + if (mIndexBufferChanged && !ApplyIndexBuffer()) return false; + if (mUniformsChanged && !ApplyUniforms()) return false; + if (mTexturesChanged && !ApplyTextures()) return false; + if (mRasterizerStateChanged && !ApplyRasterizerState()) return false; + if (mBlendStateChanged && !ApplyBlendState()) return false; + if (mDepthStateChanged && !ApplyDepthState()) return false; mNeedApply = false; + return true; } -void RenderDevice::ApplyShader() +bool RenderDevice::ApplyViewport() +{ + glViewport(0, 0, mViewportWidth, mViewportHeight); + return CheckGLError(); +} + +bool RenderDevice::ApplyShader() { Shader* curShader = GetActiveShader(); if (!curShader->CheckCompile(this)) { SetError("Failed to bind shader:\r\n%s", curShader->GetCompileError().c_str()); - return; + return false; } curShader->Bind(); mShaderChanged = false; - CheckGLError(); + return CheckGLError(); } -void RenderDevice::ApplyRasterizerState() +bool RenderDevice::ApplyRasterizerState() { if (mCullMode == Cull::None) { @@ -684,10 +693,10 @@ void RenderDevice::ApplyRasterizerState() mRasterizerStateChanged = false; - CheckGLError(); + return CheckGLError(); } -void RenderDevice::ApplyBlendState() +bool RenderDevice::ApplyBlendState() { if (mAlphaBlend) { @@ -705,10 +714,10 @@ void RenderDevice::ApplyBlendState() mBlendStateChanged = false; - CheckGLError(); + return CheckGLError(); } -void RenderDevice::ApplyDepthState() +bool RenderDevice::ApplyDepthState() { if (mDepthTest) { @@ -723,10 +732,10 @@ void RenderDevice::ApplyDepthState() mDepthStateChanged = false; - CheckGLError(); + return CheckGLError(); } -void RenderDevice::ApplyIndexBuffer() +bool RenderDevice::ApplyIndexBuffer() { if (mIndexBuffer) { @@ -739,17 +748,17 @@ void RenderDevice::ApplyIndexBuffer() mIndexBufferChanged = false; - CheckGLError(); + return CheckGLError(); } -void RenderDevice::ApplyVertexBuffer() +bool RenderDevice::ApplyVertexBuffer() { if (mVertexBuffer != -1) glBindVertexArray(mSharedVertexBuffers[mVertexBuffer]->GetVAO()); mVertexBufferChanged = false; - CheckGLError(); + return CheckGLError(); } void RenderDevice::DeclareUniform(UniformName name, const char* glslname, UniformType type) @@ -762,7 +771,7 @@ void RenderDevice::DeclareUniform(UniformName name, const char* glslname, Unifor mUniformData.resize(mUniformData.size() + (type == UniformType::Matrix ? 16 : 4)); } -void RenderDevice::ApplyUniforms() +bool RenderDevice::ApplyUniforms() { Shader* shader = GetActiveShader(); auto& locations = shader->UniformLocations; @@ -789,10 +798,10 @@ void RenderDevice::ApplyUniforms() mUniformsChanged = false; - CheckGLError(); + return CheckGLError(); } -void RenderDevice::ApplyTextures() +bool RenderDevice::ApplyTextures() { glActiveTexture(GL_TEXTURE0); if (mTextureUnit.Tex) @@ -827,7 +836,7 @@ void RenderDevice::ApplyTextures() mTexturesChanged = false; - CheckGLError(); + return CheckGLError(); } ///////////////////////////////////////////////////////////////////////////// @@ -944,69 +953,69 @@ void RenderDevice_SetSamplerState(RenderDevice* device, TextureAddress address) device->SetSamplerState(address); } -void RenderDevice_Draw(RenderDevice* device, PrimitiveType type, int startIndex, int primitiveCount) +bool RenderDevice_Draw(RenderDevice* device, PrimitiveType type, int startIndex, int primitiveCount) { - device->Draw(type, startIndex, primitiveCount); + return device->Draw(type, startIndex, primitiveCount); } -void RenderDevice_DrawIndexed(RenderDevice* device, PrimitiveType type, int startIndex, int primitiveCount) +bool RenderDevice_DrawIndexed(RenderDevice* device, PrimitiveType type, int startIndex, int primitiveCount) { - device->DrawIndexed(type, startIndex, primitiveCount); + return device->DrawIndexed(type, startIndex, primitiveCount); } -void RenderDevice_DrawData(RenderDevice* device, PrimitiveType type, int startIndex, int primitiveCount, const void* data) +bool RenderDevice_DrawData(RenderDevice* device, PrimitiveType type, int startIndex, int primitiveCount, const void* data) { - device->DrawData(type, startIndex, primitiveCount, data); + return device->DrawData(type, startIndex, primitiveCount, data); } -void RenderDevice_StartRendering(RenderDevice* device, bool clear, int backcolor, Texture* target, bool usedepthbuffer) +bool RenderDevice_StartRendering(RenderDevice* device, bool clear, int backcolor, Texture* target, bool usedepthbuffer) { - device->StartRendering(clear, backcolor, target, usedepthbuffer); + return device->StartRendering(clear, backcolor, target, usedepthbuffer); } -void RenderDevice_FinishRendering(RenderDevice* device) +bool RenderDevice_FinishRendering(RenderDevice* device) { - device->FinishRendering(); + return device->FinishRendering(); } -void RenderDevice_Present(RenderDevice* device) +bool RenderDevice_Present(RenderDevice* device) { - device->Present(); + return device->Present(); } -void RenderDevice_ClearTexture(RenderDevice* device, int backcolor, Texture* texture) +bool RenderDevice_ClearTexture(RenderDevice* device, int backcolor, Texture* texture) { - device->ClearTexture(backcolor, texture); + return device->ClearTexture(backcolor, texture); } -void RenderDevice_CopyTexture(RenderDevice* device, Texture* dst, CubeMapFace face) +bool RenderDevice_CopyTexture(RenderDevice* device, Texture* dst, CubeMapFace face) { - device->CopyTexture(dst, face); + return device->CopyTexture(dst, face); } -void RenderDevice_SetVertexBufferData(RenderDevice* device, VertexBuffer* buffer, void* data, int64_t size, VertexFormat format) +bool RenderDevice_SetVertexBufferData(RenderDevice* device, VertexBuffer* buffer, void* data, int64_t size, VertexFormat format) { - device->SetVertexBufferData(buffer, data, size, format); + return device->SetVertexBufferData(buffer, data, size, format); } -void RenderDevice_SetVertexBufferSubdata(RenderDevice* device, VertexBuffer* buffer, int64_t destOffset, void* data, int64_t size) +bool RenderDevice_SetVertexBufferSubdata(RenderDevice* device, VertexBuffer* buffer, int64_t destOffset, void* data, int64_t size) { - device->SetVertexBufferSubdata(buffer, destOffset, data, size); + return device->SetVertexBufferSubdata(buffer, destOffset, data, size); } -void RenderDevice_SetIndexBufferData(RenderDevice* device, IndexBuffer* buffer, void* data, int64_t size) +bool RenderDevice_SetIndexBufferData(RenderDevice* device, IndexBuffer* buffer, void* data, int64_t size) { - device->SetIndexBufferData(buffer, data, size); + return device->SetIndexBufferData(buffer, data, size); } -void RenderDevice_SetPixels(RenderDevice* device, Texture* texture, const void* data) +bool RenderDevice_SetPixels(RenderDevice* device, Texture* texture, const void* data) { - device->SetPixels(texture, data); + return device->SetPixels(texture, data); } -void RenderDevice_SetCubePixels(RenderDevice* device, Texture* texture, CubeMapFace face, const void* data) +bool RenderDevice_SetCubePixels(RenderDevice* device, Texture* texture, CubeMapFace face, const void* data) { - device->SetCubePixels(texture, face, data); + return device->SetCubePixels(texture, face, data); } void* RenderDevice_MapPBO(RenderDevice* device, Texture* texture) @@ -1014,9 +1023,9 @@ void* RenderDevice_MapPBO(RenderDevice* device, Texture* texture) return device->MapPBO(texture); } -void RenderDevice_UnmapPBO(RenderDevice* device, Texture* texture) +bool RenderDevice_UnmapPBO(RenderDevice* device, Texture* texture) { - device->UnmapPBO(texture); + return device->UnmapPBO(texture); } #ifdef NO_SSE diff --git a/Source/Native/RenderDevice.h b/Source/Native/RenderDevice.h index a0990712..1205eef6 100644 --- a/Source/Native/RenderDevice.h +++ b/Source/Native/RenderDevice.h @@ -99,36 +99,36 @@ public: void SetTexture(Texture* texture); void SetSamplerFilter(TextureFilter minfilter, TextureFilter magfilter, TextureFilter mipfilter, float maxanisotropy); void SetSamplerState(TextureAddress address); - void Draw(PrimitiveType type, int startIndex, int primitiveCount); - void DrawIndexed(PrimitiveType type, int startIndex, int primitiveCount); - void DrawData(PrimitiveType type, int startIndex, int primitiveCount, const void* data); - void StartRendering(bool clear, int backcolor, Texture* target, bool usedepthbuffer); - void FinishRendering(); - void Present(); - void ClearTexture(int backcolor, Texture* texture); - void CopyTexture(Texture* dst, CubeMapFace face); + bool Draw(PrimitiveType type, int startIndex, int primitiveCount); + bool DrawIndexed(PrimitiveType type, int startIndex, int primitiveCount); + bool DrawData(PrimitiveType type, int startIndex, int primitiveCount, const void* data); + bool StartRendering(bool clear, int backcolor, Texture* target, bool usedepthbuffer); + bool FinishRendering(); + bool Present(); + bool ClearTexture(int backcolor, Texture* texture); + bool CopyTexture(Texture* dst, CubeMapFace face); - void SetVertexBufferData(VertexBuffer* buffer, void* data, int64_t size, VertexFormat format); - void SetVertexBufferSubdata(VertexBuffer* buffer, int64_t destOffset, void* data, int64_t size); - void SetIndexBufferData(IndexBuffer* buffer, void* data, int64_t size); + bool SetVertexBufferData(VertexBuffer* buffer, void* data, int64_t size, VertexFormat format); + bool SetVertexBufferSubdata(VertexBuffer* buffer, int64_t destOffset, void* data, int64_t size); + bool SetIndexBufferData(IndexBuffer* buffer, void* data, int64_t size); - void SetPixels(Texture* texture, const void* data); - void SetCubePixels(Texture* texture, CubeMapFace face, const void* data); + bool SetPixels(Texture* texture, const void* data); + bool SetCubePixels(Texture* texture, CubeMapFace face, const void* data); void* MapPBO(Texture* texture); - void UnmapPBO(Texture* texture); + bool UnmapPBO(Texture* texture); - void InvalidateTexture(Texture* texture); + bool InvalidateTexture(Texture* texture); - void ApplyViewport(); - void ApplyChanges(); - void ApplyVertexBuffer(); - void ApplyIndexBuffer(); - void ApplyShader(); - void ApplyUniforms(); - void ApplyTextures(); - void ApplyRasterizerState(); - void ApplyBlendState(); - void ApplyDepthState(); + bool ApplyViewport(); + bool ApplyChanges(); + bool ApplyVertexBuffer(); + bool ApplyIndexBuffer(); + bool ApplyShader(); + bool ApplyUniforms(); + bool ApplyTextures(); + bool ApplyRasterizerState(); + bool ApplyBlendState(); + bool ApplyDepthState(); bool CheckGLError(); void SetError(const char* fmt, ...); @@ -225,8 +225,9 @@ public: bool mContextIsCurrent = false; - char mLastError[4096]; - char mReturnError[4096]; + std::string mLastError; + std::string mReturnError; + char mSetErrorBuffer[4096]; int mViewportWidth = 0; int mViewportHeight = 0;