Reputation: 7190
I have an openvr binding which has a minor problem since a while
Essentially, from time to time, whenever I free the memory of some geometric 3d model (basestation or controller) I get the Error
:
"java.lang.Error: Invalid memory access"
This is the test I'm using so far, it loads and free x times a list of models present in the Steam installation folder:
for (i in 0..99) models.forEach(::loadRenderModel)
fun loadRenderModel(renderModelName: String) {
var error: EVRRenderModelError
val rm = vrRenderModels!!
val pModel = PointerByReference()
while (true) {
error = rm.loadRenderModel_Async(renderModelName, pModel)
if (error != EVRRenderModelError.Loading) break
Thread.sleep(1)
}
val model = RenderModel.ByReference(pModel.value)
if (error != EVRRenderModelError.None) {
System.err.println("Unable to load render model $renderModelName - ${error.getName()}")
return // move on to the next tracked device
}
try {
rm freeRenderModel model
} catch (e: Error) {
System.err.println(e)
}
println()
}
RenderModel
struct in C++:
struct RenderModel_t
{
const RenderModel_Vertex_t *rVertexData; // Vertex data for the mesh
uint32_t unVertexCount; // Number of vertices in the vertex data
const uint16_t *rIndexData; // Indices into the vertex data for each triangle
uint32_t unTriangleCount; // Number of triangles in the mesh. Index count is 3 * TriangleCount
TextureID_t diffuseTextureId; // Session unique texture identifier. Rendermodels which share the same texture will have the same id. <0 == texture not present
};
and in Kotlin:
open class RenderModel : Structure {
/** Vertex data for the mesh */
@JvmField
var rVertexData: RenderModel_Vertex.ByReference? = null
/** Number of vertices in the vertex data */
@JvmField
var vertexCount = 0
/** Indices into the vertex data for each triangle */
@JvmField
var rIndexData: ShortByReference? = null
/** Number of triangles in the mesh. Index count is 3 * TriangleCount */
@JvmField
var triangleCount = 0
/** Session unique texture identifier. Rendermodels which share the same texture will have the same id. <0 == texture not present */
@JvmField
var diffuseTextureId = INVALID_TEXTURE_ID
val vertices
get() = rVertexData?.pointer?.getByteArray(0, vertexCount * RenderModel_Vertex.SIZE)
val indices
get() = rIndexData?.pointer?.getByteArray(0, triangleCount * 3 * Short.BYTES)
constructor()
constructor(vertexData: RenderModel_Vertex.ByReference, vertexCount: Int, indexData: ShortByReference, triangleCount: Int,
diffuseTextureId: Int) {
this.rVertexData = vertexData
this.vertexCount = vertexCount
this.rIndexData = indexData
this.triangleCount = triangleCount
this.diffuseTextureId = diffuseTextureId
}
override fun getFieldOrder()= listOf("rVertexData", "vertexCount", "rIndexData",
"triangleCount", "diffuseTextureId")
constructor(peer: Pointer) : super(peer) {
read()
}
class ByReference : RenderModel, Structure.ByReference {
constructor() : super()
constructor(peer: Pointer) : super(peer)
}
class ByValue : RenderModel(), Structure.ByValue
}
I tend to believe everything so far (regarding class definition) is correct since I do read valid values.
However I keep getting that error from time to time, I checked some pointer values and I didn't spot any weird value
What can it be?
Upvotes: 0
Views: 188
Reputation: 200168
I found a bug in your code, but I can't confirm it is the reason of your failures. It definitely could produce them.
You say
val error = EVRRenderModelError.None
and then
if (error != EVRRenderModelError.None) {
which is a constantly false
condition. Normally there's an IntelliJ inspection that warns you about these errors, but it could be disabled in your config.
You should use a var error
instead and reassign it within the busy-wait loop of the async call.
Upvotes: 1