Pass:send;

This commit is contained in:
bjorn 2022-05-23 23:10:11 -07:00
parent 5c0b9e51ed
commit 99ecd04e27
4 changed files with 133 additions and 8 deletions

View File

@ -196,6 +196,44 @@ static int l_lovrPassSetWireframe(lua_State* L) {
return 0;
}
static int l_lovrPassSend(lua_State* L) {
Pass* pass = luax_checktype(L, 1, Pass);
const char* name = NULL;
size_t length = 0;
uint32_t slot = ~0u;
switch (lua_type(L, 2)) {
case LUA_TSTRING: name = lua_tolstring(L, 2, &length); break;
case LUA_TNUMBER: slot = lua_tointeger(L, 2) - 1; break;
default: return luax_typeerror(L, 2, "string or number");
}
Buffer* buffer = luax_totype(L, 3, Buffer);
if (buffer) {
uint32_t offset = lua_tointeger(L, 4);
uint32_t extent = lua_tointeger(L, 5);
lovrPassSendBuffer(pass, name, length, slot, buffer, offset, extent);
return 0;
}
Texture* texture = luax_totype(L, 4, Texture);
if (texture) {
lovrPassSendTexture(pass, name, length, slot, texture);
return 0;
}
Sampler* sampler = luax_totype(L, 4, Sampler);
if (sampler) {
lovrPassSendSampler(pass, name, length, slot, sampler);
return 0;
}
return luax_typeerror(L, 3, "Buffer, Texture, Sampler, or number/vector");
}
const luaL_Reg lovrPass[] = {
{ "getType", l_lovrPassGetType },
{ "push", l_lovrPassPush },
@ -219,5 +257,6 @@ const luaL_Reg lovrPass[] = {
{ "setStencilWrite", l_lovrPassSetStencilWrite },
{ "setWinding", l_lovrPassSetWinding },
{ "setWireframe", l_lovrPassSetWireframe },
{ "send", l_lovrPassSend },
{ NULL, NULL }
};

View File

@ -979,7 +979,7 @@ void gpu_bundle_write(gpu_bundle** bundles, gpu_bundle_info* infos, uint32_t cou
} else {
buffers[bufferCount++] = (VkDescriptorBufferInfo) {
.buffer = binding->buffer.object->handle,
.offset = binding->buffer.offset,
.offset = binding->buffer.offset + binding->buffer.object->offset,
.range = binding->buffer.extent
};
}

View File

@ -155,6 +155,7 @@ static gpu_stream* getTransfers(void);
static uint32_t getLayout(gpu_slot* slots, uint32_t count);
static gpu_texture* getAttachment(uint32_t size[2], uint32_t layers, TextureFormat format, bool srgb, uint32_t samples);
static size_t measureTexture(TextureFormat format, uint16_t w, uint16_t h, uint16_t d);
static uint32_t findShaderSlot(Shader* shader, const char* name, size_t length);
static void checkShaderFeatures(uint32_t* features, uint32_t count);
static void onMessage(void* context, const char* message, bool severe);
@ -256,9 +257,9 @@ bool lovrGraphicsInit(bool debug, bool vsync) {
void lovrGraphicsDestroy() {
if (!state.initialized) return;
lovrRelease(&state.defaultBuffer, lovrBufferDestroy);
lovrRelease(&state.defaultTexture, lovrTextureDestroy);
lovrRelease(&state.defaultSampler, lovrSamplerDestroy);
lovrRelease(state.defaultBuffer, lovrBufferDestroy);
lovrRelease(state.defaultTexture, lovrTextureDestroy);
lovrRelease(state.defaultSampler, lovrSamplerDestroy);
for (uint32_t i = 0; i < COUNTOF(state.attachments); i++) {
if (state.attachments[i].texture) {
gpu_texture_destroy(state.attachments[i].texture);
@ -379,6 +380,10 @@ void lovrGraphicsSubmit(Pass** passes, uint32_t count) {
}
for (uint32_t i = 0; i < count; i++) {
for (uint32_t j = 0; j <= passes[i]->pipelineIndex; j++) {
lovrRelease(passes[i]->pipelines[j].shader, lovrShaderDestroy);
passes[i]->pipelines[j].shader = NULL;
}
streams[extraPassCount + i] = passes[i]->stream;
if (passes[i]->info.type == PASS_RENDER) {
gpu_render_end(passes[i]->stream);
@ -1169,11 +1174,18 @@ Pass* lovrGraphicsGetPass(PassInfo* info) {
gpu_render_begin(pass->stream, &target);
}
pass->transform = pass->transforms[0];
pass->pipeline = &pass->pipelines[0];
return pass;
}
void lovrPassDestroy(void* ref) {
//
Pass* pass = ref;
for (uint32_t i = 0; i <= pass->pipelineIndex; i++) {
lovrRelease(pass->pipelines[i].shader, lovrShaderDestroy);
pass->pipelines[i].shader = NULL;
}
}
const PassInfo* lovrPassGetInfo(Pass* pass) {
@ -1445,6 +1457,69 @@ void lovrPassSetWireframe(Pass* pass, bool wireframe) {
}
}
void lovrPassSendBuffer(Pass* pass, const char* name, size_t length, uint32_t slot, Buffer* buffer, uint32_t offset, uint32_t extent) {
Shader* shader = pass->pipeline->shader;
lovrCheck(shader, "A Shader must be active to send resources");
slot = name ? findShaderSlot(shader, name, length) : slot;
lovrCheck(shader->bufferMask & (1 << slot), "Trying to send a Buffer to slot %d, but the active Shader doesn't have a Buffer in that slot");
lovrCheck(offset < buffer->size, "Buffer offset is past the end of the Buffer");
uint32_t limit;
if (shader->storageMask & (1 << slot)) {
lovrCheck(!buffer->pointer, "Temporary buffers can not be sent to storage buffer variables", slot + 1);
lovrCheck((offset & (state.limits.storageBufferAlign - 1)) == 0, "Storage buffer offset (%d) is not aligned to storageBufferAlign limit (%d)", offset, state.limits.storageBufferAlign);
limit = state.limits.storageBufferRange;
} else {
lovrCheck((offset & (state.limits.uniformBufferAlign - 1)) == 0, "Uniform buffer offset (%d) is not aligned to uniformBufferAlign limit (%d)", offset, state.limits.uniformBufferAlign);
limit = state.limits.uniformBufferRange;
}
if (extent == 0) {
extent = MIN(buffer->size - offset, limit);
} else {
lovrCheck(offset + extent <= buffer->size, "Buffer range goes past the end of the Buffer");
lovrCheck(extent <= limit, "Buffer range exceeds storageBufferRange/uniformBufferRange limit");
}
pass->bindings[slot].buffer.object = buffer->gpu;
pass->bindings[slot].buffer.offset = offset;
pass->bindings[slot].buffer.extent = extent;
pass->bindingMask |= (1 << slot);
pass->bindingsDirty = true;
}
void lovrPassSendTexture(Pass* pass, const char* name, size_t length, uint32_t slot, Texture* texture) {
Shader* shader = pass->pipeline->shader;
lovrCheck(shader, "A Shader must be active to send resources");
slot = name ? findShaderSlot(shader, name, length) : slot;
lovrCheck(shader->textureMask & (1 << slot), "Trying to send a Texture to slot %d, but the active Shader doesn't have a Texture in that slot");
if (shader->storageMask & (1 << slot)) {
lovrCheck(texture->info.usage & TEXTURE_STORAGE, "Textures must be created with the 'storage' flag to send them to image variables in shaders");
} else {
lovrCheck(texture->info.usage & TEXTURE_SAMPLE, "Textures must be created with the 'sample' flag to send them to sampler variables in shaders");
}
pass->bindings[slot].texture = texture->gpu;
pass->bindingMask |= (1 << slot);
pass->bindingsDirty = true;
}
void lovrPassSendSampler(Pass* pass, const char* name, size_t length, uint32_t slot, Sampler* sampler) {
Shader* shader = pass->pipeline->shader;
lovrCheck(shader, "A Shader must be active to send resources");
slot = name ? findShaderSlot(shader, name, length) : slot;
lovrCheck(shader->samplerMask & (1 << slot), "Trying to send a Sampler to slot %d, but the active Shader doesn't have a Sampler in that slot");
pass->bindings[slot].sampler = sampler->gpu;
pass->bindingMask |= (1 << slot);
pass->bindingsDirty = true;
}
// Helpers
static void* tempAlloc(size_t size) {
@ -1608,6 +1683,16 @@ static size_t measureTexture(TextureFormat format, uint16_t w, uint16_t h, uint1
}
}
uint32_t findShaderSlot(Shader* shader, const char* name, size_t length) {
uint32_t hash = (uint32_t) hash64(name, length);
for (uint32_t i = 0; i < shader->resourceCount; i++) {
if (shader->resources[i].hash == hash) {
return shader->resources[i].binding;
}
}
lovrThrow("Shader has no variable named '%s'", name);
}
// Only an explicit set of SPIR-V capabilities are allowed
// Some capabilities require a GPU feature to be supported
// Some common unsupported capabilities are checked directly, to provide better error messages

View File

@ -1,5 +1,6 @@
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#pragma once
@ -138,7 +139,6 @@ typedef struct {
uint32_t stride;
uint32_t fieldCount;
BufferField fields[16];
void** pointer;
const char* label;
uintptr_t handle;
} BufferInfo;
@ -348,8 +348,6 @@ typedef struct {
Pass* lovrGraphicsGetPass(PassInfo* info);
void lovrPassDestroy(void* ref);
const PassInfo* lovrPassGetInfo(Pass* pass);
// Render
void lovrPassPush(Pass* pass, StackType stack);
void lovrPassPop(Pass* pass, StackType stack);
void lovrPassOrigin(Pass* pass);
@ -371,3 +369,6 @@ void lovrPassSetStencilTest(Pass* pass, CompareMode test, uint8_t value, uint8_t
void lovrPassSetStencilWrite(Pass* pass, StencilAction actions[3], uint8_t value, uint8_t mask);
void lovrPassSetWinding(Pass* pass, Winding winding);
void lovrPassSetWireframe(Pass* pass, bool wireframe);
void lovrPassSendBuffer(Pass* pass, const char* name, size_t length, uint32_t slot, Buffer* buffer, uint32_t offset, uint32_t extent);
void lovrPassSendTexture(Pass* pass, const char* name, size_t length, uint32_t slot, Texture* texture);
void lovrPassSendSampler(Pass* pass, const char* name, size_t length, uint32_t slot, Sampler* sampler);