mirror of https://github.com/bjornbytes/lovr.git
core/spv: return pointer to set/binding decorations instead of value;
This commit is contained in:
parent
eecd201f57
commit
f7c1d4cccb
|
@ -20,8 +20,7 @@ typedef union {
|
|||
uint16_t name;
|
||||
} attribute;
|
||||
struct {
|
||||
uint8_t set;
|
||||
uint8_t binding;
|
||||
uint16_t decoration;
|
||||
uint16_t name;
|
||||
} variable;
|
||||
struct {
|
||||
|
@ -220,8 +219,12 @@ static spv_result spv_parse_decoration(spv_context* spv, const uint32_t* op, spv
|
|||
case 1: spv->cache[id].flag.number = op[3]; break; // SpecID
|
||||
case 6: spv->cache[id].type.arrayStride = op[3]; break; // ArrayStride (overrides name)
|
||||
case 30: spv->cache[id].attribute.location = op[3]; break; // Location
|
||||
case 33: spv->cache[id].variable.binding = op[3]; break; // Binding
|
||||
case 34: spv->cache[id].variable.set = op[3]; break; // Set
|
||||
case 33:
|
||||
case 34:
|
||||
if (spv->cache[id].variable.decoration == 0xffff) {
|
||||
spv->cache[id].variable.decoration = op - spv->words;
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
@ -352,11 +355,8 @@ static spv_result spv_parse_variable(spv_context* spv, const uint32_t* op, spv_i
|
|||
return spv_parse_field(spv, type, info->pushConstants, info);
|
||||
}
|
||||
|
||||
uint32_t set = spv->cache[variableId].variable.set;
|
||||
uint32_t binding = spv->cache[variableId].variable.binding;
|
||||
|
||||
// Ignore output variables (storageClass 3) and anything without a set/binding decoration
|
||||
if (storageClass == 3 || set == 0xff || binding == 0xff) {
|
||||
if (storageClass == 3 || spv->cache[variableId].variable.decoration == 0xffff) {
|
||||
return SPV_OK;
|
||||
}
|
||||
|
||||
|
@ -374,8 +374,36 @@ static spv_result spv_parse_variable(spv_context* spv, const uint32_t* op, spv_i
|
|||
|
||||
spv_resource* resource = &info->resources[info->resourceCount++];
|
||||
|
||||
resource->set = set;
|
||||
resource->binding = binding;
|
||||
// Resolve the set/binding pointers. The cache stores the index of the first set/binding
|
||||
// decoration word, we need to search for the "other" one.
|
||||
const uint32_t* word = spv->words + spv->cache[variableId].variable.decoration;
|
||||
bool set = word[2] == 34;
|
||||
uint32_t other = set ? 33 : 34;
|
||||
|
||||
if (set) {
|
||||
resource->set = &word[3];
|
||||
} else {
|
||||
resource->binding = &word[3];
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
const uint32_t* next = word + OP_LENGTH(word);
|
||||
|
||||
if (word == next || next > spv->edge || OP_CODE(next) != 71 || OP_CODE(next) != 72) {
|
||||
break;
|
||||
}
|
||||
|
||||
word = next;
|
||||
|
||||
if (OP_CODE(word) == 71 && word[1] == variableId && word[2] == other) {
|
||||
if (set) {
|
||||
resource->binding = &word[3];
|
||||
} else {
|
||||
resource->set = &word[3];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If it's an array, read the array size and unwrap the inner type
|
||||
if (OP_CODE(type) == 28) { // OpTypeArray
|
||||
|
|
|
@ -79,10 +79,10 @@ enum {
|
|||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t set;
|
||||
uint32_t binding;
|
||||
uint32_t arraySize;
|
||||
const uint32_t* set;
|
||||
const uint32_t* binding;
|
||||
const char* name;
|
||||
uint32_t arraySize;
|
||||
spv_resource_type type;
|
||||
spv_texture_dimension dimension;
|
||||
uint32_t textureFlags;
|
||||
|
|
|
@ -2857,15 +2857,17 @@ Shader* lovrShaderCreate(const ShaderInfo* info) {
|
|||
for (uint32_t i = 0; i < spv[s].resourceCount; i++) {
|
||||
spv_resource* resource = &spv[s].resources[i];
|
||||
|
||||
if (resource->set != userSet) {
|
||||
if (*resource->set != userSet) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t binding = *resource->binding;
|
||||
|
||||
lovrCheck(resource->arraySize == 0, "Arrays of resources in shaders are not currently supported");
|
||||
lovrCheck(resource->type != SPV_COMBINED_TEXTURE_SAMPLER, "Shader variable (%d) is a%s, which is not supported%s", resource->binding, " combined texture sampler", " (use e.g. texture2D instead of sampler2D)");
|
||||
lovrCheck(resource->type != SPV_UNIFORM_TEXEL_BUFFER, "Shader variable (%d) is a%s, which is not supported%s", resource->binding, " uniform texel buffer", "");
|
||||
lovrCheck(resource->type != SPV_STORAGE_TEXEL_BUFFER, "Shader variable (%d) is a%s, which is not supported%s", resource->binding, " storage texel buffer", "");
|
||||
lovrCheck(resource->type != SPV_INPUT_ATTACHMENT, "Shader variable (%d) is a%s, which is not supported%s", resource->binding, "n input attachment", "");
|
||||
lovrCheck(resource->type != SPV_COMBINED_TEXTURE_SAMPLER, "Shader variable (%d) is a%s, which is not supported%s", binding, " combined texture sampler", " (use e.g. texture2D instead of sampler2D)");
|
||||
lovrCheck(resource->type != SPV_UNIFORM_TEXEL_BUFFER, "Shader variable (%d) is a%s, which is not supported%s", binding, " uniform texel buffer", "");
|
||||
lovrCheck(resource->type != SPV_STORAGE_TEXEL_BUFFER, "Shader variable (%d) is a%s, which is not supported%s", binding, " storage texel buffer", "");
|
||||
lovrCheck(resource->type != SPV_INPUT_ATTACHMENT, "Shader variable (%d) is a%s, which is not supported%s", binding, "n input attachment", "");
|
||||
|
||||
static const gpu_slot_type resourceTypes[] = {
|
||||
[SPV_UNIFORM_BUFFER] = GPU_SLOT_UNIFORM_BUFFER,
|
||||
|
@ -2893,8 +2895,8 @@ Shader* lovrShaderCreate(const ShaderInfo* info) {
|
|||
// It's ok to reuse binding slots (within or across stages), but the type must be consistent
|
||||
for (uint32_t j = 0; j < shader->resourceCount; j++) {
|
||||
ShaderResource* other = &shader->resources[j];
|
||||
if (other->binding == resource->binding) {
|
||||
lovrCheck(other->type == resourceTypes[resource->type], "Shader variable with binding number %d is declared multiple times with inconsistent types", resource->binding);
|
||||
if (other->binding == binding) {
|
||||
lovrCheck(other->type == resourceTypes[resource->type], "Shader variable with binding number %d is declared multiple times with inconsistent types", binding);
|
||||
slots[j].stages |= stageMap[stage];
|
||||
shader->resources[j].phase |= stagePhase[stage];
|
||||
append = false;
|
||||
|
@ -2912,17 +2914,17 @@ Shader* lovrShaderCreate(const ShaderInfo* info) {
|
|||
lovrThrow("Shader resource count exceeds resourcesPerShader limit (%d)", MAX_SHADER_RESOURCES);
|
||||
}
|
||||
|
||||
lovrCheck(resource->binding < 32, "Max resource binding number is %d", 32 - 1);
|
||||
lovrCheck(binding < 32, "Max resource binding number is %d", 32 - 1);
|
||||
|
||||
slots[index] = (gpu_slot) {
|
||||
.number = resource->binding,
|
||||
.number = binding,
|
||||
.type = resourceTypes[resource->type],
|
||||
.stages = stageMap[stage]
|
||||
};
|
||||
|
||||
shader->resources[index] = (ShaderResource) {
|
||||
.hash = hash,
|
||||
.binding = resource->binding,
|
||||
.binding = binding,
|
||||
.type = resourceTypes[resource->type],
|
||||
.phase = stagePhase[stage]
|
||||
};
|
||||
|
@ -2954,10 +2956,10 @@ Shader* lovrShaderCreate(const ShaderInfo* info) {
|
|||
bool texture = resource->type == SPV_SAMPLED_TEXTURE || resource->type == SPV_STORAGE_TEXTURE;
|
||||
bool sampler = resource->type == SPV_SAMPLER;
|
||||
bool storage = resource->type == SPV_STORAGE_BUFFER || resource->type == SPV_STORAGE_TEXTURE;
|
||||
shader->bufferMask |= (buffer << resource->binding);
|
||||
shader->textureMask |= (texture << resource->binding);
|
||||
shader->samplerMask |= (sampler << resource->binding);
|
||||
shader->storageMask |= (storage << resource->binding);
|
||||
shader->bufferMask |= (buffer << binding);
|
||||
shader->textureMask |= (texture << binding);
|
||||
shader->samplerMask |= (sampler << binding);
|
||||
shader->storageMask |= (storage << binding);
|
||||
|
||||
if (storage) {
|
||||
shader->resources[index].cache = stage == STAGE_COMPUTE ? GPU_CACHE_STORAGE_WRITE : GPU_CACHE_STORAGE_READ;
|
||||
|
|
Loading…
Reference in New Issue