mirror of
https://github.com/libretro/parallel-gx1.git
synced 2026-11-07 04:26:01 -10:00
Vulkan: bring back the bounding box and the dynamic vertex loader
rslc now has storage buffers and atomics (updated from RetroArch's libretro-common), so the Vulkan backend offers again what needs them: the bounding box where the device has fragmentStoresAndAtomics, the dynamic vertex loader, and the vertex-shader line and point expansion. GPU texture decoding stays off until rslc has a compute stage.
This commit is contained in:
1 parent
e3e2f2a230
commit
e2c5a83f49
6 files changed
+215
-16
No files matched your search
@@ -357,6 +357,9 @@ static void pr_array_suffix(struct rslc_pr *p, const struct rslc_type *t)
|
||||
while (t->kind == RSLC_TY_ARRAY)
|
||||
{
|
||||
pr_c(p, '[');
|
||||
#ifdef RSLC_EXTENDED
|
||||
if (t->array_len) /* a storage buffer's unsized last member */
|
||||
#endif
|
||||
pr_u(p, t->array_len);
|
||||
pr_c(p, ']');
|
||||
t = t->elem;
|
||||
@@ -3610,9 +3613,25 @@ static void pr_block_decl(struct rslc_pr *p, unsigned idx)
|
||||
/* CafeGLSL takes the push block as a second uniform block, laid out
|
||||
* as the source declared it; the runtime reads offsets back from
|
||||
* the .gsh */
|
||||
#ifdef RSLC_EXTENDED
|
||||
if (b->buffer)
|
||||
{
|
||||
pr_s(p, b->std140 ? "layout(std140) " : "layout(std430) ");
|
||||
if (b->readonly)
|
||||
pr_s(p, "readonly ");
|
||||
if (b->coherent)
|
||||
pr_s(p, "coherent ");
|
||||
pr_s(p, "buffer ");
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
if (!b->push || b->std140)
|
||||
pr_s(p, "layout(std140) ");
|
||||
pr_s(p, "uniform ");
|
||||
#ifdef RSLC_EXTENDED
|
||||
}
|
||||
#endif
|
||||
pr_s(p, type_name);
|
||||
pr_s(p, " {");
|
||||
p->indent++;
|
||||
@@ -5318,6 +5337,17 @@ bool rslc_emit_text(struct rslc_ctx *c, struct rslc_result *result)
|
||||
return false;
|
||||
}
|
||||
if (p->hlsl || p->msl)
|
||||
{
|
||||
uint32_t b;
|
||||
for (b = 2; b < RSLC_MAX_BLOCKS; b++)
|
||||
if (c->prog.has_block[b] && c->prog.blocks[b].buffer)
|
||||
{
|
||||
rslc_err(c, p->hlsl ? "hlsl: no form of a storage buffer yet"
|
||||
: "msl: no form of a storage buffer", NULL, c->prog.blocks[b].line);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (p->hlsl || p->msl)
|
||||
{
|
||||
bool ioblock = false;
|
||||
uint32_t k;
|
||||
|
||||
+90
-8
@@ -1686,6 +1686,9 @@ struct rslc_quals
|
||||
bool is_out;
|
||||
bool is_inout;
|
||||
#ifdef RSLC_EXTENDED
|
||||
bool is_buffer;
|
||||
bool readonly;
|
||||
bool coherent;
|
||||
bool early_fragment_tests;
|
||||
uint8_t gs_prim; /* RSLC_GS_* named in the layout */
|
||||
uint32_t index;
|
||||
@@ -3047,7 +3050,15 @@ static const struct rslc_bsig rslc_bsigs[] = {
|
||||
{ RSLC_BFN_FWIDTHFINE, "fwidthFine", "F:F" }, { RSLC_BFN_DFDXCOARSE, "dFdxCoarse", "F:F" },
|
||||
{ RSLC_BFN_DFDYCOARSE, "dFdyCoarse", "F:F" }, { RSLC_BFN_FWIDTHCOARSE, "fwidthCoarse", "F:F" }
|
||||
#ifdef RSLC_EXTENDED
|
||||
, { RSLC_BFN_EMITVERTEX, "EmitVertex", ":v" }, { RSLC_BFN_ENDPRIMITIVE, "EndPrimitive", ":v" }
|
||||
, { RSLC_BFN_EMITVERTEX, "EmitVertex", ":v" }, { RSLC_BFN_ENDPRIMITIVE, "EndPrimitive", ":v" },
|
||||
{ RSLC_BFN_ATOMICADD, "atomicAdd", "i i:i;u u:u" },
|
||||
{ RSLC_BFN_ATOMICMIN, "atomicMin", "i i:i;u u:u" },
|
||||
{ RSLC_BFN_ATOMICMAX, "atomicMax", "i i:i;u u:u" },
|
||||
{ RSLC_BFN_ATOMICAND, "atomicAnd", "i i:i;u u:u" },
|
||||
{ RSLC_BFN_ATOMICOR, "atomicOr", "i i:i;u u:u" },
|
||||
{ RSLC_BFN_ATOMICXOR, "atomicXor", "i i:i;u u:u" },
|
||||
{ RSLC_BFN_ATOMICEXCHANGE, "atomicExchange", "i i:i;u u:u" },
|
||||
{ RSLC_BFN_ATOMICCOMPSWAP, "atomicCompSwap", "i i i:i;u u u:u" }
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -3381,6 +3392,30 @@ static const struct rslc_type *rslc_p_type_spec(struct rslc_parser *p,
|
||||
static const struct rslc_type *rslc_p_array_suffix(struct rslc_parser *p,
|
||||
const struct rslc_type *ty);
|
||||
|
||||
#ifdef RSLC_EXTENDED
|
||||
/* The block an access is rooted in, when it is a storage buffer. */
|
||||
static const struct rslc_blockdecl *rslc_p_buffer_of(struct rslc_parser *p, uint32_t e)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
struct rslc_node *n = rslc_p_node(p, e);
|
||||
if (n->op == RSLC_OP_MEMBER || n->op == RSLC_OP_INDEX || n->op == RSLC_OP_SWIZZLE)
|
||||
{
|
||||
e = n->a;
|
||||
continue;
|
||||
}
|
||||
if (n->op == RSLC_OP_VAR)
|
||||
{
|
||||
const struct rslc_var *v = p->c->prog.vars[n->a];
|
||||
if ((v->storage == RSLC_ST_MEMBER || v->storage == RSLC_ST_BLOCK)
|
||||
&& p->c->prog.blocks[v->block].buffer)
|
||||
return &p->c->prog.blocks[v->block];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool rslc_p_is_lvalue(struct rslc_parser *p, uint32_t e)
|
||||
{
|
||||
struct rslc_node *n = rslc_p_node(p, e);
|
||||
@@ -3389,6 +3424,12 @@ static bool rslc_p_is_lvalue(struct rslc_parser *p, uint32_t e)
|
||||
case RSLC_OP_VAR:
|
||||
{
|
||||
struct rslc_var *v = p->c->prog.vars[n->a];
|
||||
#ifdef RSLC_EXTENDED
|
||||
/* a storage buffer is written unless it is readonly */
|
||||
if ((v->storage == RSLC_ST_MEMBER || v->storage == RSLC_ST_BLOCK)
|
||||
&& p->c->prog.blocks[v->block].buffer)
|
||||
return !p->c->prog.blocks[v->block].readonly;
|
||||
#endif
|
||||
if (v->storage == RSLC_ST_CONST || v->storage == RSLC_ST_IN
|
||||
|| v->storage == RSLC_ST_SAMPLER || v->storage == RSLC_ST_BLOCK
|
||||
|| v->storage == RSLC_ST_MEMBER)
|
||||
@@ -3710,6 +3751,15 @@ static uint32_t rslc_p_call(struct rslc_parser *p, struct rslc_sym *name, uint32
|
||||
uint32_t i;
|
||||
if (!rslc_p_resolve_builtin(p, bs, args, nargs, &ret, line))
|
||||
return 0;
|
||||
#ifdef RSLC_EXTENDED
|
||||
/* an atomic works on a member of a storage buffer in place */
|
||||
if (name->bfn >= RSLC_BFN_ATOMICADD && name->bfn <= RSLC_BFN_ATOMICCOMPSWAP
|
||||
&& (!rslc_p_is_lvalue(p, args[0]) || !rslc_p_buffer_of(p, args[0])))
|
||||
{
|
||||
rslc_err(p->c, "an atomic needs a writable storage buffer member, in ", name->str, line);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
for (i = 0; i < nargs; i++)
|
||||
prec = rslc_prec_max(prec, rslc_p_node(p, args[i])->prec);
|
||||
r = rslc_p_mk(p, RSLC_OP_BUILTIN, ret, name->bfn, rslc_list_new(p->c, args, nargs),
|
||||
@@ -4432,6 +4482,14 @@ static bool rslc_p_quals(struct rslc_parser *p, struct rslc_quals *q)
|
||||
case RSLC_KW_LOWP: q->precision = RSLC_PREC_LOW; break;
|
||||
case RSLC_KW_MEDIUMP: q->precision = RSLC_PREC_MEDIUM; break;
|
||||
case RSLC_KW_HIGHP: q->precision = RSLC_PREC_HIGH; break;
|
||||
#ifdef RSLC_EXTENDED
|
||||
case RSLC_KW_BUFFER: q->is_buffer = true; break;
|
||||
case RSLC_KW_READONLY: q->readonly = true; break;
|
||||
case RSLC_KW_COHERENT: q->coherent = true; break;
|
||||
case RSLC_KW_WRITEONLY:
|
||||
case RSLC_KW_RESTRICT:
|
||||
case RSLC_KW_VOLATILE: break;
|
||||
#endif
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
@@ -4665,6 +4723,8 @@ static bool rslc_p_starts_declaration(struct rslc_parser *p)
|
||||
s = rslc_tok_sym(p->c, t);
|
||||
if (s->kw >= RSLC_KW_CONST && s->kw <= RSLC_KW_STRUCT)
|
||||
return true;
|
||||
if (s->kw >= RSLC_KW_BUFFER && s->kw <= RSLC_KW_VOLATILE)
|
||||
return true; /* RSLC_EXTENDED: only seeded there */
|
||||
if (s->kw >= RSLC_KW_VOID && s->kw <= RSLC_KW_LAST_TYPE)
|
||||
{
|
||||
/* A type followed by '(' is a constructor expression; a type
|
||||
@@ -5225,18 +5285,22 @@ static bool rslc_p_block_decl(struct rslc_parser *p, struct rslc_quals *q,
|
||||
struct rslc_type *st;
|
||||
struct rslc_sym *instance = NULL;
|
||||
|
||||
if (!q->is_uniform)
|
||||
return rslc_p_fail(p, "only uniform blocks are supported", NULL);
|
||||
#ifdef RSLC_EXTENDED
|
||||
/* a further uniform block takes the next slot past the push block */
|
||||
if (idx == 0 && pr->has_block[0])
|
||||
if (!q->is_uniform && !q->is_buffer)
|
||||
return rslc_p_fail(p, "only uniform and buffer blocks are supported", NULL);
|
||||
/* a storage buffer, and a further uniform block, take the next slot
|
||||
* past the push block */
|
||||
if (q->is_buffer || (idx == 0 && pr->has_block[0]))
|
||||
{
|
||||
idx = 2;
|
||||
while (idx < RSLC_MAX_BLOCKS && pr->has_block[idx])
|
||||
idx++;
|
||||
if (idx == RSLC_MAX_BLOCKS)
|
||||
return rslc_p_fail(p, "too many uniform blocks", NULL);
|
||||
return rslc_p_fail(p, "too many uniform and buffer blocks", NULL);
|
||||
}
|
||||
#else
|
||||
if (!q->is_uniform)
|
||||
return rslc_p_fail(p, "only uniform blocks are supported", NULL);
|
||||
#endif
|
||||
if (pr->has_block[idx])
|
||||
return rslc_p_fail(p, idx ? "more than one push_constant block"
|
||||
@@ -5306,6 +5370,20 @@ static bool rslc_p_block_decl(struct rslc_parser *p, struct rslc_quals *q,
|
||||
b->line = line;
|
||||
b->push = idx == 1;
|
||||
b->std140 = idx == 0 || q->std140;
|
||||
#ifdef RSLC_EXTENDED
|
||||
/* a further uniform block is std140 as the first is; a storage
|
||||
* buffer std430 unless it says otherwise, and only its last member
|
||||
* may be an array of unstated length */
|
||||
b->buffer = q->is_buffer;
|
||||
b->readonly = q->readonly;
|
||||
b->coherent = q->coherent;
|
||||
if (idx >= 2 && !q->is_buffer)
|
||||
b->std140 = true;
|
||||
for (i = 0; i < nfields; i++)
|
||||
if (fields[i].type->kind == RSLC_TY_ARRAY && !fields[i].type->array_len
|
||||
&& (!q->is_buffer || i + 1 != nfields))
|
||||
return rslc_p_fail(p, "only a storage buffer's last member may be unsized", NULL);
|
||||
#endif
|
||||
pr->has_block[idx] = true;
|
||||
|
||||
if (instance)
|
||||
@@ -5551,8 +5629,12 @@ static uint32_t rslc_p_declaration(struct rslc_parser *p, bool global)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* uniform Block { ... }; */
|
||||
if (q.is_uniform && P_TOK(p)->kind == RSLC_TK_IDENT
|
||||
/* uniform Block { ... }; RSLC_EXTENDED: buffer Block { ... }; */
|
||||
if ((q.is_uniform
|
||||
#ifdef RSLC_EXTENDED
|
||||
|| q.is_buffer
|
||||
#endif
|
||||
) && P_TOK(p)->kind == RSLC_TK_IDENT
|
||||
&& rslc_tok_sym(p->c, P_TOK(p))->kw == RSLC_KW_NONE
|
||||
&& rslc_tok_is_punct(P_PEEK(p, 1), RSLC_P_LBRACE))
|
||||
{
|
||||
|
||||
+80
-2
@@ -415,7 +415,8 @@ static const char *const rslc_keywords[] = {
|
||||
#ifdef RSLC_EXTENDED
|
||||
, "sampler2DArray", "isampler2DArray", "usampler2DArray",
|
||||
"sampler2DMSArray", "isampler2DMSArray", "usampler2DMSArray",
|
||||
"samplerBuffer", "isamplerBuffer", "usamplerBuffer"
|
||||
"samplerBuffer", "isamplerBuffer", "usamplerBuffer",
|
||||
"buffer", "readonly", "writeonly", "coherent", "restrict", "volatile"
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -1017,6 +1018,9 @@ enum spv_section
|
||||
|
||||
#define SPV_DEC_RELAXEDPRECISION 0
|
||||
#define SPV_DEC_BLOCK 2
|
||||
#define SPV_DEC_BUFFERBLOCK 3
|
||||
#define SPV_DEC_COHERENT 23
|
||||
#define SPV_DEC_NONWRITABLE 24
|
||||
#define SPV_DEC_COLMAJOR 5
|
||||
#define SPV_DEC_ARRAYSTRIDE 6
|
||||
#define SPV_DEC_MATRIXSTRIDE 7
|
||||
@@ -1052,7 +1056,7 @@ enum spv_op
|
||||
SpvOpEntryPoint = 15, SpvOpExecutionMode = 16, SpvOpCapability = 17,
|
||||
SpvOpTypeVoid = 19, SpvOpTypeBool = 20, SpvOpTypeInt = 21, SpvOpTypeFloat = 22,
|
||||
SpvOpTypeVector = 23, SpvOpTypeMatrix = 24, SpvOpTypeImage = 25,
|
||||
SpvOpTypeSampledImage = 27, SpvOpTypeArray = 28, SpvOpTypeStruct = 30,
|
||||
SpvOpTypeSampledImage = 27, SpvOpTypeArray = 28, SpvOpTypeRuntimeArray = 29, SpvOpTypeStruct = 30,
|
||||
SpvOpTypePointer = 32, SpvOpTypeFunction = 33,
|
||||
SpvOpConstantTrue = 41, SpvOpConstantFalse = 42, SpvOpConstant = 43,
|
||||
SpvOpConstantComposite = 44,
|
||||
@@ -1096,6 +1100,9 @@ enum spv_op
|
||||
SpvOpPhi = 245, SpvOpLoopMerge = 246, SpvOpSelectionMerge = 247,
|
||||
SpvOpLabel = 248, SpvOpBranch = 249, SpvOpBranchConditional = 250,
|
||||
SpvOpEmitVertex = 218, SpvOpEndPrimitive = 219,
|
||||
SpvOpAtomicExchange = 229, SpvOpAtomicCompareExchange = 230, SpvOpAtomicIAdd = 234,
|
||||
SpvOpAtomicSMin = 236, SpvOpAtomicUMin = 237, SpvOpAtomicSMax = 238, SpvOpAtomicUMax = 239,
|
||||
SpvOpAtomicAnd = 240, SpvOpAtomicOr = 241, SpvOpAtomicXor = 242,
|
||||
SpvOpSwitch = 251, SpvOpKill = 252, SpvOpReturn = 253, SpvOpReturnValue = 254,
|
||||
SpvOpUnreachable = 255
|
||||
};
|
||||
@@ -1347,6 +1354,19 @@ static uint32_t spv_type_laid(struct spv_emit *e, const struct rslc_type *t, boo
|
||||
uint32_t w[3];
|
||||
if (!elem)
|
||||
return 0;
|
||||
#ifdef RSLC_EXTENDED
|
||||
/* a storage buffer's last member, as long as the buffer bound */
|
||||
if (!t->array_len)
|
||||
{
|
||||
rslc_layout_of(t, std140, &a, &s, &st);
|
||||
id = spv_id(e);
|
||||
if (!spv_inst2(e, SPV_SEC_TYPES, SpvOpTypeRuntimeArray, id, elem)
|
||||
|| !spv_decorate1(e, id, SPV_DEC_ARRAYSTRIDE, st))
|
||||
return 0;
|
||||
ti->laid[k] = id;
|
||||
return id;
|
||||
}
|
||||
#endif
|
||||
/* OpConstant for the length, int typed */
|
||||
{
|
||||
uint32_t i;
|
||||
@@ -2832,6 +2852,47 @@ static uint32_t spv_builtin_node(struct spv_emit *e, const struct rslc_node *n)
|
||||
w[0] = x; w[1] = ptr;
|
||||
return spv_ext(e, tid, bfn == RSLC_BFN_MODF ? GLSLstd450Modf : GLSLstd450Frexp, w, 2, prec);
|
||||
}
|
||||
#ifdef RSLC_EXTENDED
|
||||
/* atomics: on the member in place, device scope, no ordering, as
|
||||
* glslang emits them */
|
||||
if (bfn >= RSLC_BFN_ATOMICADD && bfn <= RSLC_BFN_ATOMICCOMPSWAP)
|
||||
{
|
||||
const struct rslc_type *at = rslc_node_at(e->c, rslc_list_item(e->c, n->b, 0))->type;
|
||||
bool sgn = at->base == RSLC_BASE_INT;
|
||||
uint32_t scope = spv_const_uint(e, 1); /* Device */
|
||||
uint32_t sem = spv_const_uint(e, 0);
|
||||
uint32_t ptr, val, w[8];
|
||||
unsigned sc; bool laid, std140;
|
||||
enum spv_op op;
|
||||
if (!scope || !sem)
|
||||
return 0;
|
||||
ptr = spv_lvalue(e, rslc_list_item(e->c, n->b, 0), &sc, &laid, &std140);
|
||||
val = ptr ? spv_rvalue(e, rslc_list_item(e->c, n->b, 1)) : 0;
|
||||
if (!val)
|
||||
return 0;
|
||||
switch (bfn)
|
||||
{
|
||||
case RSLC_BFN_ATOMICADD: op = SpvOpAtomicIAdd; break;
|
||||
case RSLC_BFN_ATOMICMIN: op = sgn ? SpvOpAtomicSMin : SpvOpAtomicUMin; break;
|
||||
case RSLC_BFN_ATOMICMAX: op = sgn ? SpvOpAtomicSMax : SpvOpAtomicUMax; break;
|
||||
case RSLC_BFN_ATOMICAND: op = SpvOpAtomicAnd; break;
|
||||
case RSLC_BFN_ATOMICOR: op = SpvOpAtomicOr; break;
|
||||
case RSLC_BFN_ATOMICXOR: op = SpvOpAtomicXor; break;
|
||||
case RSLC_BFN_ATOMICEXCHANGE: op = SpvOpAtomicExchange; break;
|
||||
default:
|
||||
{
|
||||
/* atomicCompSwap(mem, compare, data): data, then the comparator */
|
||||
uint32_t data = spv_rvalue(e, rslc_list_item(e->c, n->b, 2));
|
||||
if (!data)
|
||||
return 0;
|
||||
w[0] = ptr; w[1] = scope; w[2] = sem; w[3] = sem; w[4] = data; w[5] = val;
|
||||
return spv_fn_result(e, SpvOpAtomicCompareExchange, tid, w, 6, prec);
|
||||
}
|
||||
}
|
||||
w[0] = ptr; w[1] = scope; w[2] = sem; w[3] = val;
|
||||
return spv_fn_result(e, op, tid, w, 4, prec);
|
||||
}
|
||||
#endif
|
||||
if (bfn == RSLC_BFN_UADDCARRY || bfn == RSLC_BFN_USUBBORROW || bfn == RSLC_BFN_UMULEXTENDED
|
||||
|| bfn == RSLC_BFN_IMULEXTENDED)
|
||||
{
|
||||
@@ -4421,6 +4482,23 @@ static bool spv_block(struct spv_emit *e, unsigned idx)
|
||||
stid = spv_type_laid(e, b->type, std140);
|
||||
if (!stid)
|
||||
return false;
|
||||
#ifdef RSLC_EXTENDED
|
||||
/* SPIR-V 1.0: a storage buffer is a BufferBlock in the Uniform class */
|
||||
if (b->buffer)
|
||||
{
|
||||
uint32_t k;
|
||||
if (!spv_decorate(e, stid, SPV_DEC_BUFFERBLOCK))
|
||||
return false;
|
||||
for (k = 0; k < b->type->nfields; k++)
|
||||
{
|
||||
if (b->readonly && !spv_mdecorate(e, stid, k, SPV_DEC_NONWRITABLE))
|
||||
return false;
|
||||
if (b->coherent && !spv_mdecorate(e, stid, k, SPV_DEC_COHERENT))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (!spv_decorate(e, stid, SPV_DEC_BLOCK))
|
||||
return false;
|
||||
ptr = spv_ptr(e, stid, sc);
|
||||
|
||||
@@ -216,6 +216,8 @@ enum rslc_kw
|
||||
RSLC_KW_SAMPLER2DARRAY, RSLC_KW_ISAMPLER2DARRAY, RSLC_KW_USAMPLER2DARRAY,
|
||||
RSLC_KW_SAMPLER2DMSARRAY, RSLC_KW_ISAMPLER2DMSARRAY, RSLC_KW_USAMPLER2DMSARRAY,
|
||||
RSLC_KW_SAMPLERBUFFER, RSLC_KW_ISAMPLERBUFFER, RSLC_KW_USAMPLERBUFFER,
|
||||
RSLC_KW_BUFFER, RSLC_KW_READONLY, RSLC_KW_WRITEONLY, RSLC_KW_COHERENT,
|
||||
RSLC_KW_RESTRICT, RSLC_KW_VOLATILE,
|
||||
RSLC_KW_COUNT
|
||||
};
|
||||
|
||||
@@ -385,6 +387,9 @@ struct rslc_blockdecl
|
||||
uint32_t line;
|
||||
bool push;
|
||||
bool std140; /* layout; push blocks default std430 */
|
||||
bool buffer; /* RSLC_EXTENDED: a storage buffer, std430 by default */
|
||||
bool readonly;
|
||||
bool coherent;
|
||||
};
|
||||
|
||||
struct rslc_func
|
||||
@@ -527,6 +532,9 @@ enum rslc_bfn
|
||||
RSLC_BFN_DFDX, RSLC_BFN_DFDY, RSLC_BFN_FWIDTH, RSLC_BFN_DFDXFINE, RSLC_BFN_DFDYFINE,
|
||||
RSLC_BFN_FWIDTHFINE, RSLC_BFN_DFDXCOARSE, RSLC_BFN_DFDYCOARSE, RSLC_BFN_FWIDTHCOARSE,
|
||||
RSLC_BFN_EMITVERTEX, RSLC_BFN_ENDPRIMITIVE, /* RSLC_EXTENDED, geometry */
|
||||
/* RSLC_EXTENDED: on a member of a storage buffer */
|
||||
RSLC_BFN_ATOMICADD, RSLC_BFN_ATOMICMIN, RSLC_BFN_ATOMICMAX, RSLC_BFN_ATOMICAND,
|
||||
RSLC_BFN_ATOMICOR, RSLC_BFN_ATOMICXOR, RSLC_BFN_ATOMICEXCHANGE, RSLC_BFN_ATOMICCOMPSWAP,
|
||||
RSLC_BFN_COUNT
|
||||
};
|
||||
|
||||
|
||||
+2
-1
@@ -47,7 +47,8 @@
|
||||
* outputs (layout index), layout(early_fragment_tests), and a vertex
|
||||
* stage's gl_ClipDistance / gl_CullDistance (sized by the highest
|
||||
* constant element written; HLSL and MSL refuse them yet), in / out
|
||||
* interface blocks, and RSLC_STAGE_GEOMETRY (SPIR-V and GLSL only).
|
||||
* interface blocks, RSLC_STAGE_GEOMETRY (SPIR-V and GLSL only), and
|
||||
* storage buffers with the atomic builtins (SPIR-V and GLSL only).
|
||||
* Without it
|
||||
* none of that is accepted, nothing is compiled in for it, and every
|
||||
* destination is word for word what it was. MSL has no form of the
|
||||
|
||||
@@ -428,7 +428,7 @@ void VulkanContext::PopulateBackendInfo(BackendInfo* backend_info)
|
||||
backend_info->bSupportsPaletteConversion = true; // Assumed support.
|
||||
backend_info->bSupportsClipControl = true; // Assumed support.
|
||||
backend_info->bSupportsMultithreading = true; // Assumed support.
|
||||
// rslc has no compute stage, storage buffers or atomics yet.
|
||||
// rslc has no compute stage yet.
|
||||
backend_info->bSupportsComputeShaders = false;
|
||||
backend_info->bSupportsGPUTextureDecoding = false;
|
||||
backend_info->bSupportsBitfield = true; // Assumed support.
|
||||
@@ -456,8 +456,8 @@ void VulkanContext::PopulateBackendInfo(BackendInfo* backend_info)
|
||||
backend_info->bSupportsLodBiasInSampler = false; // Dependent on OS.
|
||||
backend_info->bSupportsSettingObjectNames = false; // Dependent on features.
|
||||
backend_info->bSupportsPartialMultisampleResolve = true; // Assumed support.
|
||||
backend_info->bSupportsDynamicVertexLoader = false; // Needs storage buffers.
|
||||
backend_info->bSupportsVSLinePointExpand = false; // Needs storage buffers.
|
||||
backend_info->bSupportsDynamicVertexLoader = true; // Assumed support.
|
||||
backend_info->bSupportsVSLinePointExpand = true; // Assumed support.
|
||||
backend_info->bSupportsHDROutput = true; // Assumed support.
|
||||
backend_info->bSupportsUnrestrictedDepthRange = false; // Dependent on features.
|
||||
}
|
||||
@@ -481,8 +481,8 @@ void VulkanContext::PopulateBackendInfoFeatures(BackendInfo* backend_info, VkPhy
|
||||
backend_info->bSupportsDualSourceBlend = info.dualSrcBlend;
|
||||
backend_info->bSupportsGeometryShaders = info.geometryShader;
|
||||
backend_info->bSupportsGSInstancing = info.geometryShader;
|
||||
// The bounding box needs storage buffers and atomics, which rslc has no form of yet.
|
||||
backend_info->bSupportsBBox = backend_info->bSupportsFragmentStoresAndAtomics = false;
|
||||
backend_info->bSupportsBBox = backend_info->bSupportsFragmentStoresAndAtomics =
|
||||
info.fragmentStoresAndAtomics;
|
||||
backend_info->bSupportsSSAA = info.sampleRateShading;
|
||||
backend_info->bSupportsLogicOp = info.logicOp;
|
||||
|
||||
|
||||
Reference in new issue
Block a user