Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve GL error messages #1140

Merged
merged 8 commits into from
Oct 3, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions gapis/api/gles/api/asynchronous_queries.api
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ cmd void glDeleteQueries(GLsizei count, const QueryId* queries) {
}

sub void DeleteQueries(GLsizei count, const QueryId* queries) {
CheckNonNegative!GLsizei(count)
CheckCountGE!GLsizei(count, 0)
q := queries[0:count]
ctx := GetContext()
for i in (0 .. count) {
Expand Down Expand Up @@ -103,7 +103,7 @@ cmd void glGenQueries(GLsizei count, QueryId* queries) {
}

sub void GenQueries(GLsizei count, QueryId* queries) {
CheckNonNegative!GLsizei(count)
CheckCountGE!GLsizei(count, 0)
q := queries[0:count]
ctx := GetContext()
for i in (0 .. count) {
Expand Down
31 changes: 18 additions & 13 deletions gapis/api/gles/api/buffer_objects.api
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ cmd void glBufferData(GLenum target, GLsizeiptr size, BufferDataPointer data, GL
glErrorInvalidEnum(usage)
}
}
CheckNonNegative!GLsizeiptr(size)
CheckSizeGE!GLsizeiptr(size, 0)

b.Data = switch (data != null) {
case true: clone(as!u8*(data)[0:size])
Expand All @@ -282,8 +282,9 @@ cmd void glBufferData(GLenum target, GLsizeiptr size, BufferDataPointer data, GL
@doc("https://www.khronos.org/opengles/sdk/docs/man32/html/glBufferSubData.xhtml", Version.GLES32)
cmd void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, BufferDataPointer data) {
b := GetBoundBufferOrError(target)
if (offset < 0) || (size < 0) { glErrorInvalidValue() }
if (as!GLsizeiptr(offset) + size) > b.Size { glErrorInvalidValue() }
CheckGE!GLintptr(offset, 0)
CheckSizeGE!GLsizeiptr(size, 0)
CheckLE!GLsizeiptr((as!GLsizeiptr(offset) + size), b.Size)
copy(b.Data[offset:as!GLsizeiptr(offset) + size], as!u8*(data)[0:size])
}

Expand Down Expand Up @@ -313,7 +314,7 @@ sub void CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readO
@doc("https://www.khronos.org/opengles/sdk/docs/man31/html/glDeleteBuffers.xhtml", Version.GLES31)
@doc("https://www.khronos.org/opengles/sdk/docs/man32/html/glDeleteBuffers.xhtml", Version.GLES32)
cmd void glDeleteBuffers(GLsizei count, const BufferId* buffers) {
CheckNonNegative!GLsizei(count)
CheckCountGE!GLsizei(count, 0)
b := buffers[0:count]
ctx := GetContext()
for i in (0 .. count) {
Expand All @@ -331,7 +332,7 @@ cmd void glDeleteBuffers(GLsizei count, const BufferId* buffers) {
@doc("https://www.khronos.org/opengles/sdk/docs/man31/html/glGenBuffers.xhtml", Version.GLES31)
@doc("https://www.khronos.org/opengles/sdk/docs/man32/html/glGenBuffers.xhtml", Version.GLES32)
cmd void glGenBuffers(GLsizei count, BufferId* buffers) {
CheckNonNegative!GLsizei(count)
CheckCountGE!GLsizei(count, 0)
b := buffers[0:count]
ctx := GetContext()
for i in (0 .. count) {
Expand Down Expand Up @@ -466,21 +467,23 @@ cmd void* glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GL
return ptr
}

sub void MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, u8* ptr) {
sub void MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr size, GLbitfield access, u8* ptr) {
b := GetBoundBufferOrError(target)
if (offset < 0) || (length < 0) || ((as!GLsizeiptr(offset) + length) > b.Size) { glErrorInvalidValue() }
CheckGE!GLintptr(offset, 0)
CheckSizeGE!GLsizeiptr(size, 0)
CheckLE!GLsizeiptr((as!GLsizeiptr(offset) + size), b.Size)
supportsBits(access, GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_READ_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_WRITE_BIT)
if b.Mapped == GL_TRUE { glErrorInvalidOperation() }

b.Mapped = GL_TRUE
b.AccessFlags = access
b.MapPointer = ptr
b.MapOffset = offset
b.MapLength = length
mapMemory(ptr[0:length])
b.MapLength = size
mapMemory(ptr[0:size])

if GL_MAP_READ_BIT in access {
copy(ptr[0:length], b.Data[offset:offset + as!GLintptr(length)])
copy(ptr[0:size], b.Data[offset:offset + as!GLintptr(size)])
}
}

Expand Down Expand Up @@ -516,11 +519,13 @@ cmd void glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr len
FlushMappedBufferRange(target, offset, length)
}

sub void FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) {
sub void FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr size) {
b := GetBoundBufferOrError(target)
if b.Mapped == GL_FALSE { glErrorInvalidOperation() }
if !(GL_MAP_FLUSH_EXPLICIT_BIT in b.AccessFlags) { glErrorInvalidOperation() }
if (offset < 0) || (length < 0) || ((as!GLsizeiptr(offset) + length) > b.MapLength) { glErrorInvalidValue() }
CheckGE!GLintptr(offset, 0)
CheckSizeGE!GLsizeiptr(size, 0)
CheckLE!GLsizeiptr((as!GLsizeiptr(offset) + size), b.MapLength)
dstOffset := b.MapOffset + offset
copy(b.Data[dstOffset:dstOffset + as!GLintptr(length)], b.MapPointer[offset:offset + as!GLintptr(length)])
copy(b.Data[dstOffset:dstOffset + as!GLintptr(size)], b.MapPointer[offset:offset + as!GLintptr(size)])
}
44 changes: 33 additions & 11 deletions gapis/api/gles/api/debug.api
Original file line number Diff line number Diff line change
Expand Up @@ -242,47 +242,69 @@ sub void ObjectLabel(GLenum identifier, GLuint name, GLsizei length, const GLcha
ctx := GetContext()
switch (identifier) {
case GL_TEXTURE: {
if !(as!TextureId(name) in ctx.Objects.Shared.Textures) { glErrorInvalidOperation() }
if !(as!TextureId(name) in ctx.Objects.Shared.Textures) {
glErrorInvalidOperation_ObjectDoesNotExist!GLuint(name)
}
ctx.Objects.Shared.Textures[as!TextureId(name)].Label = str
}
case GL_FRAMEBUFFER: {
if !(as!FramebufferId(name) in ctx.Objects.Framebuffers) { glErrorInvalidOperation() }
if !(as!FramebufferId(name) in ctx.Objects.Framebuffers) {
glErrorInvalidOperation_ObjectDoesNotExist!GLuint(name)
}
ctx.Objects.Framebuffers[as!FramebufferId(name)].Label = str
}
case GL_RENDERBUFFER: {
if !(as!RenderbufferId(name) in ctx.Objects.Shared.Renderbuffers) { glErrorInvalidOperation() }
if !(as!RenderbufferId(name) in ctx.Objects.Shared.Renderbuffers) {
glErrorInvalidOperation_ObjectDoesNotExist!GLuint(name)
}
ctx.Objects.Shared.Renderbuffers[as!RenderbufferId(name)].Label = str
}
case GL_BUFFER: {
if !(as!BufferId(name) in ctx.Objects.Shared.Buffers) { glErrorInvalidOperation() }
if !(as!BufferId(name) in ctx.Objects.Shared.Buffers) {
glErrorInvalidOperation_ObjectDoesNotExist!GLuint(name)
}
ctx.Objects.Shared.Buffers[as!BufferId(name)].Label = str
}
case GL_SHADER: {
if !(as!ShaderId(name) in ctx.Objects.Shared.Shaders) { glErrorInvalidOperation() }
if !(as!ShaderId(name) in ctx.Objects.Shared.Shaders) {
glErrorInvalidOperation_ObjectDoesNotExist!GLuint(name)
}
ctx.Objects.Shared.Shaders[as!ShaderId(name)].Label = str
}
case GL_PROGRAM: {
if !(as!ProgramId(name) in ctx.Objects.Shared.Programs) { glErrorInvalidOperation() }
if !(as!ProgramId(name) in ctx.Objects.Shared.Programs) {
glErrorInvalidOperation_ObjectDoesNotExist!GLuint(name)
}
ctx.Objects.Shared.Programs[as!ProgramId(name)].Label = str
}
case GL_VERTEX_ARRAY: {
if !(as!VertexArrayId(name) in ctx.Objects.VertexArrays) { glErrorInvalidOperation() }
if !(as!VertexArrayId(name) in ctx.Objects.VertexArrays) {
glErrorInvalidOperation_ObjectDoesNotExist!GLuint(name)
}
ctx.Objects.VertexArrays[as!VertexArrayId(name)].Label = str
}
case GL_QUERY: {
if !(as!QueryId(name) in ctx.Objects.Queries) { glErrorInvalidOperation() }
if !(as!QueryId(name) in ctx.Objects.Queries) {
glErrorInvalidOperation_ObjectDoesNotExist!GLuint(name)
}
ctx.Objects.Queries[as!QueryId(name)].Label = str
}
case GL_SAMPLER: {
if !(as!SamplerId(name) in ctx.Objects.Shared.Samplers) { glErrorInvalidOperation() }
if !(as!SamplerId(name) in ctx.Objects.Shared.Samplers) {
glErrorInvalidOperation_ObjectDoesNotExist!GLuint(name)
}
ctx.Objects.Shared.Samplers[as!SamplerId(name)].Label = str
}
case GL_TRANSFORM_FEEDBACK: {
if !(as!TransformFeedbackId(name) in ctx.Objects.TransformFeedbacks) { glErrorInvalidOperation() }
if !(as!TransformFeedbackId(name) in ctx.Objects.TransformFeedbacks) {
glErrorInvalidOperation_ObjectDoesNotExist!GLuint(name)
}
ctx.Objects.TransformFeedbacks[as!TransformFeedbackId(name)].Label = str
}
case GL_PROGRAM_PIPELINE: {
if !(as!PipelineId(name) in ctx.Objects.Pipelines) { glErrorInvalidOperation() }
if !(as!PipelineId(name) in ctx.Objects.Pipelines) {
glErrorInvalidOperation_ObjectDoesNotExist!GLuint(name)
}
ctx.Objects.Pipelines[as!PipelineId(name)].Label = str
}
default: {
Expand Down
26 changes: 13 additions & 13 deletions gapis/api/gles/api/draw_commands.api
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ sub bool isTransformFeedback() {
@doc("https://www.khronos.org/opengles/sdk/docs/man32/html/glDrawArrays.xhtml", Version.GLES32)
cmd void glDrawArrays(GLenum draw_mode, GLint first_index, GLsizei indices_count) {
checkPrimitiveType(draw_mode)
CheckNonNegative!GLint(first_index) // "Recommended behaviour"
CheckNonNegative!GLsizei(indices_count)
CheckGE!GLint(first_index, 0) // "Recommended behaviour"
CheckCountGE!GLsizei(indices_count, 0)
ctx := GetContext()
ReadVertexArrays(ctx, as!u32(first_index), as!u32(indices_count), 1)
WriteGPUFramebufferData(ctx)
Expand All @@ -77,10 +77,10 @@ cmd void glDrawArrays(GLenum draw_mode, GLint first_index, GLsizei indices_count
cmd void glDrawArraysIndirect(GLenum draw_mode, const void* indirect) {
checkPrimitiveType(draw_mode)
ctx := GetContext()
if IsDefaultVertexArrayBound() { glErrorInvalidOperation() }
CheckNonDefaultVertexArrayBound()
if ctx.Bound.DrawIndirectBuffer == null { glErrorInvalidOperation() }
// TODO: INVALID_OPERATION error if the command would source data beyond the end of the buffer object.
// TODO: if as!u64(indirect) % 4 != 0 { glErrorInvalidValue() }
// TODO: CheckEQ(as!u64(indirect) % 4, 0)
WriteGPUFramebufferData(ctx)
}

Expand All @@ -96,9 +96,9 @@ cmd void glDrawArraysInstanced(GLenum draw_mode, GLint first_index, GLsizei indi

sub void DrawArraysInstanced(GLenum draw_mode, GLint first_index, GLsizei indices_count, GLsizei instance_count) {
checkPrimitiveType(draw_mode)
CheckNonNegative!GLint(first_index) // "Recommended behaviour"
CheckNonNegative!GLsizei(indices_count)
CheckNonNegative!GLsizei(instance_count)
CheckGE!GLint(first_index, 0) // "Recommended behaviour"
CheckCountGE!GLsizei(indices_count, 0)
CheckCountGE!GLsizei(instance_count, 0)
ctx := GetContext()
ReadVertexArrays(ctx, as!u32(first_index), as!u32(indices_count), as!u32(instance_count))
WriteGPUFramebufferData(ctx)
Expand All @@ -112,9 +112,9 @@ sub void DrawElements(ref!Context ctx,
GLsizei instance_count,
GLint base_vertex) {
checkPrimitiveType(draw_mode)
CheckNonNegative!GLsizei(indices_count) // SPEC: missing in pdf
CheckCountGE!GLsizei(indices_count, 0) // SPEC: missing in pdf
checkIndicesType(indices_type)
CheckNonNegative!GLsizei(instance_count) // SPEC: missing in pdf
CheckCountGE!GLsizei(instance_count, 0) // SPEC: missing in pdf
if indices_count > 0 {
count := as!u32(indices_count)
index_buffer := ctx.Bound.VertexArray.ElementArrayBuffer
Expand Down Expand Up @@ -189,11 +189,11 @@ cmd void glDrawElementsIndirect(GLenum draw_mode, GLenum indices_type, const voi
checkIndicesType(indices_type)

ctx := GetContext()
if IsDefaultVertexArrayBound() { glErrorInvalidOperation() }
CheckNonDefaultVertexArrayBound()
// TODO: Error if enabled array is not bound or is mapped.
if ctx.Bound.DrawIndirectBuffer == null { glErrorInvalidOperation() }
// TODO: INVALID_OPERATION error if the command would source data beyond the end of the buffer object.
// TODO: if as!u64(indirect) % 4 != 0 { glErrorInvalidValue() }
// TODO: CheckEQ(as!u64(indirect) % 4, 0)
WriteGPUFramebufferData(ctx)
}

Expand Down Expand Up @@ -246,7 +246,7 @@ cmd void glDrawRangeElements(GLenum draw_mode,
GLsizei indices_count,
GLenum indices_type,
IndicesPointer indices) {
if end < start { glErrorInvalidValue() }
CheckGE!GLuint(end, start)
ctx := GetContext()
DrawElements(ctx, draw_mode, indices_count, indices_type, indices, 1, 0)
}
Expand All @@ -266,7 +266,7 @@ cmd void glDrawRangeElementsBaseVertex(GLenum draw_mode,
}

sub void DrawRangeElementsBaseVertex(GLenum draw_mode, GLuint start, GLuint end, GLsizei indices_count, GLenum indices_type, IndicesPointer indices, GLint base_vertex) {
if end < start { glErrorInvalidValue() }
CheckGE!GLuint(end, start)
ctx := GetContext()
DrawElements(ctx, draw_mode, indices_count, indices_type, indices, 1, base_vertex)
}
Expand Down
111 changes: 111 additions & 0 deletions gapis/api/gles/api/errors.api
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright (C) 2017 Google Inc.
//
// 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
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern void onGlError(GLenum v)

sub void supportsBits(GLbitfield seenBits, GLbitfield validBits) {
CheckEQ!GLbitfield((seenBits & validBits), seenBits)
}

sub void glErrorInvalidEnum(GLenum value) {
glErrorInvalidEnumMsg(new!ERR_INVALID_ENUM(value: as!u32(value)))
}

sub void glErrorInvalidEnumMsg(message m) {
onGlError(GL_INVALID_ENUM)
_ = newMsg(SEVERITY_ERROR, m)
abort
}

sub void glErrorInvalidValue!T(T value) {
glErrorInvalidValueMsg(new!ERR_INVALID_VALUE(value: as!s64(value)))
}

sub void glErrorInvalidObjectName!T(T value) {
glErrorInvalidValueMsg(new!ERR_INVALID_OBJECT_NAME(value: as!s64(value)))
}

sub void glErrorInvalidValueMsg(message m) {
onGlError(GL_INVALID_VALUE)
_ = newMsg(SEVERITY_ERROR, m)
abort
}

sub void glErrorInvalidOperation() {
glErrorInvalidOperationMsg(new!ERR_INVALID_OPERATION())
}

sub void glErrorInvalidOperationMsg(message m) {
onGlError(GL_INVALID_OPERATION)
_ = newMsg(SEVERITY_ERROR, m)
abort
}

sub void CheckEQ!T(T value, T constraint) {
if !(as!s64(value) == as!s64(constraint)) {
glErrorInvalidValueMsg(new!ERR_INVALID_VALUE_CHECK_EQ(value: as!s64(value), constraint: as!s64(constraint)))
}
}

sub void CheckNE!T(T value, T constraint) {
if !(as!s64(value) != as!s64(constraint)) {
glErrorInvalidValueMsg(new!ERR_INVALID_VALUE_CHECK_NE(value: as!s64(value), constraint: as!s64(constraint)))
}
}

sub void CheckGE!T(T value, T constraint) {
if !(as!s64(value) >= as!s64(constraint)) {
glErrorInvalidValueMsg(new!ERR_INVALID_VALUE_CHECK_GE(value: as!s64(value), constraint: as!s64(constraint)))
}
}

sub void CheckGT!T(T value, T constraint) {
if !(as!s64(value) > as!s64(constraint)) {
glErrorInvalidValueMsg(new!ERR_INVALID_VALUE_CHECK_GT(value: as!s64(value), constraint: as!s64(constraint)))
}
}

sub void CheckLE!T(T value, T constraint) {
if !(as!s64(value) <= as!s64(constraint)) {
glErrorInvalidValueMsg(new!ERR_INVALID_VALUE_CHECK_LE(value: as!s64(value), constraint: as!s64(constraint)))
}
}

sub void CheckLT!T(T value, T constraint) {
if !(as!s64(value) < as!s64(constraint)) {
glErrorInvalidValueMsg(new!ERR_INVALID_VALUE_CHECK_LT(value: as!s64(value), constraint: as!s64(constraint)))
}
}

sub void CheckLocationLT!T(T value, T constraint) {
if !(as!s64(value) < as!s64(constraint)) {
glErrorInvalidValueMsg(new!ERR_INVALID_VALUE_CHECK_LOCATION_LT(value: as!s64(value), constraint: as!s64(constraint)))
}
}

sub void CheckCountGE!T(T value, T constraint) {
if !(as!s64(value) >= as!s64(constraint)) {
glErrorInvalidValueMsg(new!ERR_INVALID_VALUE_CHECK_COUNT_GE(value: as!s64(value), constraint: as!s64(constraint)))
}
}

sub void CheckSizeGE!T(T value, T constraint) {
if !(as!s64(value) >= as!s64(constraint)) {
glErrorInvalidValueMsg(new!ERR_INVALID_VALUE_CHECK_SIZE_GE(value: as!s64(value), constraint: as!s64(constraint)))
}
}

sub void glErrorInvalidOperation_ObjectDoesNotExist!T(T id) {
glErrorInvalidOperationMsg(new!ERR_INVALID_OPERATION_OBJECT_DOES_NOT_EXIST(id: as!u64(id)))
}
Loading