Improved error reporting

This commit is contained in:
ZZYZX 2019-12-15 23:53:33 +02:00
parent 7f09dd2aec
commit 502b641967
8 changed files with 979 additions and 819 deletions

View file

@ -29,6 +29,11 @@ using System.Reflection;
namespace CodeImp.DoomBuilder.Rendering namespace CodeImp.DoomBuilder.Rendering
{ {
public class RenderDeviceException : Exception
{
public RenderDeviceException(string message) : base(message) { }
}
public class RenderDevice : IDisposable public class RenderDevice : IDisposable
{ {
public RenderDevice(RenderTargetControl rendertarget) public RenderDevice(RenderTargetControl rendertarget)
@ -59,6 +64,13 @@ namespace CodeImp.DoomBuilder.Rendering
public bool Disposed { get { return Handle == IntPtr.Zero; } } public bool Disposed { get { return Handle == IntPtr.Zero; } }
private void CheckAndThrow()
{
string err = Marshal.PtrToStringAnsi(RenderDevice_GetError(Handle));
if (err != "")
throw new RenderDeviceException(err);
}
public void Dispose() public void Dispose()
{ {
if (!Disposed) if (!Disposed)
@ -71,36 +83,43 @@ namespace CodeImp.DoomBuilder.Rendering
public void SetShader(ShaderName shader) public void SetShader(ShaderName shader)
{ {
RenderDevice_SetShader(Handle, shader); RenderDevice_SetShader(Handle, shader);
CheckAndThrow();
} }
public void SetUniform(UniformName uniform, bool value) public void SetUniform(UniformName uniform, bool value)
{ {
RenderDevice_SetUniform(Handle, uniform, new float[] { value ? 1.0f : 0.0f }, 1); RenderDevice_SetUniform(Handle, uniform, new float[] { value ? 1.0f : 0.0f }, 1);
CheckAndThrow();
} }
public void SetUniform(UniformName uniform, float value) public void SetUniform(UniformName uniform, float value)
{ {
RenderDevice_SetUniform(Handle, uniform, new float[] { value }, 1); RenderDevice_SetUniform(Handle, uniform, new float[] { value }, 1);
CheckAndThrow();
} }
public void SetUniform(UniformName uniform, Vector2 value) public void SetUniform(UniformName uniform, Vector2 value)
{ {
RenderDevice_SetUniform(Handle, uniform, new float[] { value.X, value.Y }, 2); RenderDevice_SetUniform(Handle, uniform, new float[] { value.X, value.Y }, 2);
CheckAndThrow();
} }
public void SetUniform(UniformName uniform, Vector3 value) public void SetUniform(UniformName uniform, Vector3 value)
{ {
RenderDevice_SetUniform(Handle, uniform, new float[] { value.X, value.Y, value.Z }, 3); RenderDevice_SetUniform(Handle, uniform, new float[] { value.X, value.Y, value.Z }, 3);
CheckAndThrow();
} }
public void SetUniform(UniformName uniform, Vector4 value) public void SetUniform(UniformName uniform, Vector4 value)
{ {
RenderDevice_SetUniform(Handle, uniform, new float[] { value.X, value.Y, value.Z, value.W }, 4); RenderDevice_SetUniform(Handle, uniform, new float[] { value.X, value.Y, value.Z, value.W }, 4);
CheckAndThrow();
} }
public void SetUniform(UniformName uniform, Color4 value) public void SetUniform(UniformName uniform, Color4 value)
{ {
RenderDevice_SetUniform(Handle, uniform, new float[] { value.Red, value.Green, value.Blue, value.Alpha }, 4); RenderDevice_SetUniform(Handle, uniform, new float[] { value.Red, value.Green, value.Blue, value.Alpha }, 4);
CheckAndThrow();
} }
public void SetUniform(UniformName uniform, Matrix matrix) public void SetUniform(UniformName uniform, Matrix matrix)
@ -111,173 +130,207 @@ namespace CodeImp.DoomBuilder.Rendering
matrix.M31, matrix.M32, matrix.M33, matrix.M34, matrix.M31, matrix.M32, matrix.M33, matrix.M34,
matrix.M41, matrix.M42, matrix.M43, matrix.M44 matrix.M41, matrix.M42, matrix.M43, matrix.M44
}, 16); }, 16);
CheckAndThrow();
} }
public void SetVertexBuffer(VertexBuffer buffer) public void SetVertexBuffer(VertexBuffer buffer)
{ {
RenderDevice_SetVertexBuffer(Handle, buffer != null ? buffer.Handle : IntPtr.Zero); RenderDevice_SetVertexBuffer(Handle, buffer != null ? buffer.Handle : IntPtr.Zero);
CheckAndThrow();
} }
public void SetIndexBuffer(IndexBuffer buffer) public void SetIndexBuffer(IndexBuffer buffer)
{ {
RenderDevice_SetIndexBuffer(Handle, buffer != null ? buffer.Handle : IntPtr.Zero); RenderDevice_SetIndexBuffer(Handle, buffer != null ? buffer.Handle : IntPtr.Zero);
CheckAndThrow();
} }
public void SetAlphaBlendEnable(bool value) public void SetAlphaBlendEnable(bool value)
{ {
RenderDevice_SetAlphaBlendEnable(Handle, value); RenderDevice_SetAlphaBlendEnable(Handle, value);
CheckAndThrow();
} }
public void SetAlphaTestEnable(bool value) public void SetAlphaTestEnable(bool value)
{ {
RenderDevice_SetAlphaTestEnable(Handle, value); RenderDevice_SetAlphaTestEnable(Handle, value);
CheckAndThrow();
} }
public void SetCullMode(Cull mode) public void SetCullMode(Cull mode)
{ {
RenderDevice_SetCullMode(Handle, mode); RenderDevice_SetCullMode(Handle, mode);
CheckAndThrow();
} }
public void SetBlendOperation(BlendOperation op) public void SetBlendOperation(BlendOperation op)
{ {
RenderDevice_SetBlendOperation(Handle, op); RenderDevice_SetBlendOperation(Handle, op);
CheckAndThrow();
} }
public void SetSourceBlend(Blend blend) public void SetSourceBlend(Blend blend)
{ {
RenderDevice_SetSourceBlend(Handle, blend); RenderDevice_SetSourceBlend(Handle, blend);
CheckAndThrow();
} }
public void SetDestinationBlend(Blend blend) public void SetDestinationBlend(Blend blend)
{ {
RenderDevice_SetDestinationBlend(Handle, blend); RenderDevice_SetDestinationBlend(Handle, blend);
CheckAndThrow();
} }
public void SetFillMode(FillMode mode) public void SetFillMode(FillMode mode)
{ {
RenderDevice_SetFillMode(Handle, mode); RenderDevice_SetFillMode(Handle, mode);
CheckAndThrow();
} }
public void SetMultisampleAntialias(bool value) public void SetMultisampleAntialias(bool value)
{ {
RenderDevice_SetMultisampleAntialias(Handle, value); RenderDevice_SetMultisampleAntialias(Handle, value);
CheckAndThrow();
} }
public void SetZEnable(bool value) public void SetZEnable(bool value)
{ {
RenderDevice_SetZEnable(Handle, value); RenderDevice_SetZEnable(Handle, value);
CheckAndThrow();
} }
public void SetZWriteEnable(bool value) public void SetZWriteEnable(bool value)
{ {
RenderDevice_SetZWriteEnable(Handle, value); RenderDevice_SetZWriteEnable(Handle, value);
CheckAndThrow();
} }
public void SetTexture(BaseTexture value) public void SetTexture(BaseTexture value)
{ {
RenderDevice_SetTexture(Handle, value != null ? value.Handle : IntPtr.Zero); RenderDevice_SetTexture(Handle, value != null ? value.Handle : IntPtr.Zero);
CheckAndThrow();
} }
public void SetSamplerFilter(TextureFilter filter) public void SetSamplerFilter(TextureFilter filter)
{ {
SetSamplerFilter(filter, filter, TextureFilter.None, 0.0f); SetSamplerFilter(filter, filter, TextureFilter.None, 0.0f);
CheckAndThrow();
} }
public void SetSamplerFilter(TextureFilter minfilter, TextureFilter magfilter, TextureFilter mipfilter, float maxanisotropy) public void SetSamplerFilter(TextureFilter minfilter, TextureFilter magfilter, TextureFilter mipfilter, float maxanisotropy)
{ {
RenderDevice_SetSamplerFilter(Handle, minfilter, magfilter, mipfilter, maxanisotropy); RenderDevice_SetSamplerFilter(Handle, minfilter, magfilter, mipfilter, maxanisotropy);
CheckAndThrow();
} }
public void SetSamplerState(TextureAddress address) public void SetSamplerState(TextureAddress address)
{ {
SetSamplerState(address, address, address); SetSamplerState(address, address, address);
CheckAndThrow();
} }
public void SetSamplerState(TextureAddress addressU, TextureAddress addressV, TextureAddress addressW) public void SetSamplerState(TextureAddress addressU, TextureAddress addressV, TextureAddress addressW)
{ {
RenderDevice_SetSamplerState(Handle, addressU, addressV, addressW); RenderDevice_SetSamplerState(Handle, addressU, addressV, addressW);
CheckAndThrow();
} }
public void DrawIndexed(PrimitiveType type, int startIndex, int primitiveCount) public void DrawIndexed(PrimitiveType type, int startIndex, int primitiveCount)
{ {
RenderDevice_DrawIndexed(Handle, type, startIndex, primitiveCount); RenderDevice_DrawIndexed(Handle, type, startIndex, primitiveCount);
CheckAndThrow();
} }
public void Draw(PrimitiveType type, int startIndex, int primitiveCount) public void Draw(PrimitiveType type, int startIndex, int primitiveCount)
{ {
RenderDevice_Draw(Handle, type, startIndex, primitiveCount); RenderDevice_Draw(Handle, type, startIndex, primitiveCount);
CheckAndThrow();
} }
public void Draw(PrimitiveType type, int startIndex, int primitiveCount, FlatVertex[] data) public void Draw(PrimitiveType type, int startIndex, int primitiveCount, FlatVertex[] data)
{ {
RenderDevice_DrawData(Handle, type, startIndex, primitiveCount, data); RenderDevice_DrawData(Handle, type, startIndex, primitiveCount, data);
CheckAndThrow();
} }
public void StartRendering(bool clear, Color4 backcolor) public void StartRendering(bool clear, Color4 backcolor)
{ {
RenderDevice_StartRendering(Handle, clear, backcolor.ToArgb(), IntPtr.Zero, true); RenderDevice_StartRendering(Handle, clear, backcolor.ToArgb(), IntPtr.Zero, true);
CheckAndThrow();
} }
public void StartRendering(bool clear, Color4 backcolor, Texture target, bool usedepthbuffer) public void StartRendering(bool clear, Color4 backcolor, Texture target, bool usedepthbuffer)
{ {
RenderDevice_StartRendering(Handle, clear, backcolor.ToArgb(), target.Handle, usedepthbuffer); RenderDevice_StartRendering(Handle, clear, backcolor.ToArgb(), target.Handle, usedepthbuffer);
CheckAndThrow();
} }
public void FinishRendering() public void FinishRendering()
{ {
RenderDevice_FinishRendering(Handle); RenderDevice_FinishRendering(Handle);
CheckAndThrow();
} }
public void Present() public void Present()
{ {
RenderDevice_Present(Handle); RenderDevice_Present(Handle);
CheckAndThrow();
} }
public void ClearTexture(Color4 backcolor, Texture texture) public void ClearTexture(Color4 backcolor, Texture texture)
{ {
RenderDevice_ClearTexture(Handle, backcolor.ToArgb(), texture.Handle); RenderDevice_ClearTexture(Handle, backcolor.ToArgb(), texture.Handle);
CheckAndThrow();
} }
public void CopyTexture(CubeTexture dst, CubeMapFace face) public void CopyTexture(CubeTexture dst, CubeMapFace face)
{ {
RenderDevice_CopyTexture(Handle, dst.Handle, face); RenderDevice_CopyTexture(Handle, dst.Handle, face);
CheckAndThrow();
} }
public void SetBufferData(IndexBuffer buffer, int[] data) public void SetBufferData(IndexBuffer buffer, int[] data)
{ {
RenderDevice_SetIndexBufferData(Handle, buffer.Handle, data, data.Length * Marshal.SizeOf<int>()); RenderDevice_SetIndexBufferData(Handle, buffer.Handle, data, data.Length * Marshal.SizeOf<int>());
CheckAndThrow();
} }
public void SetBufferData(VertexBuffer buffer, int length, VertexFormat format) public void SetBufferData(VertexBuffer buffer, int length, VertexFormat format)
{ {
int stride = (format == VertexFormat.Flat) ? FlatVertex.Stride : WorldVertex.Stride; int stride = (format == VertexFormat.Flat) ? FlatVertex.Stride : WorldVertex.Stride;
RenderDevice_SetVertexBufferData(Handle, buffer.Handle, IntPtr.Zero, length * stride, format); RenderDevice_SetVertexBufferData(Handle, buffer.Handle, IntPtr.Zero, length * stride, format);
CheckAndThrow();
} }
public void SetBufferData(VertexBuffer buffer, FlatVertex[] data) public void SetBufferData(VertexBuffer buffer, FlatVertex[] data)
{ {
RenderDevice_SetVertexBufferData(Handle, buffer.Handle, data, data.Length * Marshal.SizeOf<FlatVertex>(), VertexFormat.Flat); RenderDevice_SetVertexBufferData(Handle, buffer.Handle, data, data.Length * Marshal.SizeOf<FlatVertex>(), VertexFormat.Flat);
CheckAndThrow();
} }
public void SetBufferData(VertexBuffer buffer, WorldVertex[] data) public void SetBufferData(VertexBuffer buffer, WorldVertex[] data)
{ {
RenderDevice_SetVertexBufferData(Handle, buffer.Handle, data, data.Length * Marshal.SizeOf<WorldVertex>(), VertexFormat.World); RenderDevice_SetVertexBufferData(Handle, buffer.Handle, data, data.Length * Marshal.SizeOf<WorldVertex>(), VertexFormat.World);
CheckAndThrow();
} }
public void SetBufferSubdata(VertexBuffer buffer, long destOffset, FlatVertex[] data) public void SetBufferSubdata(VertexBuffer buffer, long destOffset, FlatVertex[] data)
{ {
RenderDevice_SetVertexBufferSubdata(Handle, buffer.Handle, destOffset * FlatVertex.Stride, data, data.Length * FlatVertex.Stride); RenderDevice_SetVertexBufferSubdata(Handle, buffer.Handle, destOffset * FlatVertex.Stride, data, data.Length * FlatVertex.Stride);
CheckAndThrow();
} }
public void SetBufferSubdata(VertexBuffer buffer, long destOffset, WorldVertex[] data) public void SetBufferSubdata(VertexBuffer buffer, long destOffset, WorldVertex[] data)
{ {
RenderDevice_SetVertexBufferSubdata(Handle, buffer.Handle, destOffset * WorldVertex.Stride, data, data.Length * WorldVertex.Stride); RenderDevice_SetVertexBufferSubdata(Handle, buffer.Handle, destOffset * WorldVertex.Stride, data, data.Length * WorldVertex.Stride);
CheckAndThrow();
} }
public void SetBufferSubdata(VertexBuffer buffer, FlatVertex[] data, long size) public void SetBufferSubdata(VertexBuffer buffer, FlatVertex[] data, long size)
{ {
if (size < 0 || size > data.Length) throw new ArgumentOutOfRangeException("size"); if (size < 0 || size > data.Length) throw new ArgumentOutOfRangeException("size");
RenderDevice_SetVertexBufferSubdata(Handle, buffer.Handle, 0, data, size * FlatVertex.Stride); RenderDevice_SetVertexBufferSubdata(Handle, buffer.Handle, 0, data, size * FlatVertex.Stride);
CheckAndThrow();
} }
public void SetPixels(Texture texture, System.Drawing.Bitmap bitmap) public void SetPixels(Texture texture, System.Drawing.Bitmap bitmap)
@ -290,6 +343,7 @@ namespace CodeImp.DoomBuilder.Rendering
RenderDevice_SetPixels(Handle, texture.Handle, bmpdata.Scan0); RenderDevice_SetPixels(Handle, texture.Handle, bmpdata.Scan0);
bitmap.UnlockBits(bmpdata); bitmap.UnlockBits(bmpdata);
CheckAndThrow();
} }
public void SetPixels(CubeTexture texture, CubeMapFace face, System.Drawing.Bitmap bitmap) public void SetPixels(CubeTexture texture, CubeMapFace face, System.Drawing.Bitmap bitmap)
@ -302,6 +356,7 @@ namespace CodeImp.DoomBuilder.Rendering
RenderDevice_SetCubePixels(Handle, texture.Handle, face, bmpdata.Scan0); RenderDevice_SetCubePixels(Handle, texture.Handle, face, bmpdata.Scan0);
bitmap.UnlockBits(bmpdata); bitmap.UnlockBits(bmpdata);
CheckAndThrow();
} }
internal void RegisterResource(IRenderResource res) internal void RegisterResource(IRenderResource res)
@ -350,10 +405,13 @@ namespace CodeImp.DoomBuilder.Rendering
static extern void RenderDevice_Delete(IntPtr handle); static extern void RenderDevice_Delete(IntPtr handle);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr RenderDevice_SetShader(IntPtr hwnd, ShaderName name); static extern IntPtr RenderDevice_GetError(IntPtr handle);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr RenderDevice_SetUniform(IntPtr hwnd, UniformName name, float[] data, int count); static extern IntPtr RenderDevice_SetShader(IntPtr handle, ShaderName name);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr RenderDevice_SetUniform(IntPtr handle, UniformName name, float[] data, int count);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern void RenderDevice_SetVertexBuffer(IntPtr handle, IntPtr buffer); static extern void RenderDevice_SetVertexBuffer(IntPtr handle, IntPtr buffer);

File diff suppressed because it is too large Load diff

View file

@ -126,7 +126,9 @@ public:
void ApplyBlendState(); void ApplyBlendState();
void ApplyDepthState(); void ApplyDepthState();
void CheckError(); void CheckGLError();
void SetError(const char* fmt, ...);
const char* GetError();
Shader* GetActiveShader(); Shader* GetActiveShader();
@ -186,6 +188,9 @@ public:
bool mContextIsCurrent = false; bool mContextIsCurrent = false;
char mLastError[4096];
char mReturnError[4096];
int mViewportWidth = 0; int mViewportWidth = 0;
int mViewportHeight = 0; int mViewportHeight = 0;
}; };

View file

@ -4,31 +4,54 @@
#include "RenderDevice.h" #include "RenderDevice.h"
#include <stdexcept> #include <stdexcept>
void Shader::Setup(const std::string& vertexShader, const std::string& fragmentShader, bool alphatest) void Shader::Setup(const std::string& identifier, const std::string& vertexShader, const std::string& fragmentShader, bool alphatest)
{ {
mIdentifier = identifier;
mVertexText = vertexShader; mVertexText = vertexShader;
mFragmentText = fragmentShader; mFragmentText = fragmentShader;
mAlphatest = alphatest; mAlphatest = alphatest;
} }
void Shader::Bind() bool Shader::CheckCompile()
{ {
bool firstCall = !mProgramBuilt; bool firstCall = !mProgramBuilt;
if (firstCall) if (firstCall)
{ {
mProgramBuilt = true; mProgramBuilt = true;
CreateProgram(); CreateProgram();
glUseProgram(mProgram);
glUniform1i(glGetUniformLocation(mProgram, "texture1"), 0);
glUseProgram(0);
} }
if (!mProgram) return !mErrors.size();
}
std::string Shader::GetCompileError()
{
std::string lines = "Error compiling ";
if (!mVertexShader)
lines += "vertex ";
else if (!mFragmentShader)
lines += "fragment ";
lines += "shader \"" + mIdentifier + "\":\r\n";
for (auto c : mErrors)
{
if (c == '\r')
continue;
if (c == '\n')
lines += "\r\n";
else lines += c;
}
return lines;
}
void Shader::Bind()
{
if (!mProgram || !mProgramBuilt || mErrors.size())
return; return;
glUseProgram(mProgram); glUseProgram(mProgram);
if (firstCall)
{
glUniform1i(glGetUniformLocation(mProgram, "texture1"), 0);
}
} }
void Shader::CreateProgram() void Shader::CreateProgram()

View file

@ -11,15 +11,20 @@ public:
Shader() = default; Shader() = default;
void ReleaseResources(); void ReleaseResources();
void Setup(const std::string& vertexShader, const std::string& fragmentShader, bool alphatest); void Setup(const std::string& identifier, const std::string& vertexShader, const std::string& fragmentShader, bool alphatest);
bool CheckCompile();
void Bind(); void Bind();
std::string GetIdentifier();
std::string GetCompileError();
GLuint UniformLocations[(int)UniformName::NumUniforms] = { 0 }; GLuint UniformLocations[(int)UniformName::NumUniforms] = { 0 };
private: private:
void CreateProgram(); void CreateProgram();
GLuint CompileShader(const std::string& code, GLenum type); GLuint CompileShader(const std::string& code, GLenum type);
std::string mIdentifier;
std::string mVertexText; std::string mVertexText;
std::string mFragmentText; std::string mFragmentText;
bool mAlphatest = false; bool mAlphatest = false;

View file

@ -37,14 +37,42 @@ static const ShaderPair ShaderSources[(int)ShaderName::count] = {
{ world3D_vs_lightpass, world3D_ps_lightpass } { world3D_vs_lightpass, world3D_ps_lightpass }
}; };
static const std::string ShaderNames[(int)ShaderName::count] = {
"display2d_fsaa",
"display2d_normal",
"display2d_fullbright",
"things2d_thing",
"things2d_sprite",
"things2d_fill",
"plotter",
"world3d_main",
"world3d_fullbright",
"world3d_main_highlight",
"world3d_fullbright_highlight",
"world3d_main_vertexcolor",
"world3d_skybox",
"world3d_main_highlight_vertexcolor",
"world3d_p7",
"world3d_main_fog",
"world3d_p9",
"world3d_main_highlight_fog",
"world3d_p11",
"world3d_main_fog_vertexcolor",
"world3d_p13",
"world3d_main_highlight_fog_vertexcolor",
"world3d_vertex_color",
"world3d_constant_color",
"world3d_lightpass",
};
ShaderManager::ShaderManager() ShaderManager::ShaderManager()
{ {
for (int i = 0; i < (int)ShaderName::count; i++) for (int i = 0; i < (int)ShaderName::count; i++)
{ {
if (ShaderSources[i].vs && ShaderSources[i].ps) if (ShaderSources[i].vs && ShaderSources[i].ps)
{ {
Shaders[i].Setup(ShaderSources[i].vs, ShaderSources[i].ps, false); Shaders[i].Setup(ShaderNames[i], ShaderSources[i].vs, ShaderSources[i].ps, false);
AlphaTestShaders[i].Setup(ShaderSources[i].vs, ShaderSources[i].ps, true); AlphaTestShaders[i].Setup(ShaderNames[i], ShaderSources[i].vs, ShaderSources[i].ps, true);
} }
} }
} }

View file

@ -3,6 +3,7 @@ EXPORTS
RenderDevice_New RenderDevice_New
RenderDevice_Delete RenderDevice_Delete
RenderDevice_GetError
RenderDevice_SetShader RenderDevice_SetShader
RenderDevice_SetUniform RenderDevice_SetUniform
RenderDevice_SetVertexBuffer RenderDevice_SetVertexBuffer