mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 03:08:05 +02:00
gallium/swr: Enable GL_ARB_gpu_shader5: multiple streams
Added support for geometry shader multiple streams (part of GL_ARB_gpu_shader5 extension). Reviewed-by: Jan Zielinski <jan.zielinski@intel.com>
This commit is contained in:
parent
44971b84b7
commit
163d5fde06
6 changed files with 78 additions and 14 deletions
|
|
@ -1521,7 +1521,8 @@ static void
|
||||||
draw_gs_llvm_emit_vertex(const struct lp_build_gs_iface *gs_base,
|
draw_gs_llvm_emit_vertex(const struct lp_build_gs_iface *gs_base,
|
||||||
struct lp_build_context * bld,
|
struct lp_build_context * bld,
|
||||||
LLVMValueRef (*outputs)[4],
|
LLVMValueRef (*outputs)[4],
|
||||||
LLVMValueRef emitted_vertices_vec)
|
LLVMValueRef emitted_vertices_vec,
|
||||||
|
LLVMValueRef stream_id)
|
||||||
{
|
{
|
||||||
const struct draw_gs_llvm_iface *gs_iface = draw_gs_llvm_iface(gs_base);
|
const struct draw_gs_llvm_iface *gs_iface = draw_gs_llvm_iface(gs_base);
|
||||||
struct draw_gs_llvm_variant *variant = gs_iface->variant;
|
struct draw_gs_llvm_variant *variant = gs_iface->variant;
|
||||||
|
|
|
||||||
|
|
@ -446,7 +446,8 @@ struct lp_build_gs_iface
|
||||||
void (*emit_vertex)(const struct lp_build_gs_iface *gs_iface,
|
void (*emit_vertex)(const struct lp_build_gs_iface *gs_iface,
|
||||||
struct lp_build_context * bld,
|
struct lp_build_context * bld,
|
||||||
LLVMValueRef (*outputs)[4],
|
LLVMValueRef (*outputs)[4],
|
||||||
LLVMValueRef emitted_vertices_vec);
|
LLVMValueRef emitted_vertices_vec,
|
||||||
|
LLVMValueRef stream_id);
|
||||||
void (*end_primitive)(const struct lp_build_gs_iface *gs_iface,
|
void (*end_primitive)(const struct lp_build_gs_iface *gs_iface,
|
||||||
struct lp_build_context * bld,
|
struct lp_build_context * bld,
|
||||||
LLVMValueRef total_emitted_vertices_vec,
|
LLVMValueRef total_emitted_vertices_vec,
|
||||||
|
|
|
||||||
|
|
@ -3978,6 +3978,8 @@ emit_vertex(
|
||||||
LLVMBuilderRef builder = bld->bld_base.base.gallivm->builder;
|
LLVMBuilderRef builder = bld->bld_base.base.gallivm->builder;
|
||||||
|
|
||||||
if (bld->gs_iface->emit_vertex) {
|
if (bld->gs_iface->emit_vertex) {
|
||||||
|
uint32_t imms_idx = emit_data->inst->Src[0].Register.SwizzleX;
|
||||||
|
LLVMValueRef stream_id = bld->immediates[0][imms_idx];
|
||||||
LLVMValueRef mask = mask_vec(bld_base);
|
LLVMValueRef mask = mask_vec(bld_base);
|
||||||
LLVMValueRef total_emitted_vertices_vec =
|
LLVMValueRef total_emitted_vertices_vec =
|
||||||
LLVMBuildLoad(builder, bld->total_emitted_vertices_vec_ptr, "");
|
LLVMBuildLoad(builder, bld->total_emitted_vertices_vec_ptr, "");
|
||||||
|
|
@ -3986,7 +3988,8 @@ emit_vertex(
|
||||||
gather_outputs(bld);
|
gather_outputs(bld);
|
||||||
bld->gs_iface->emit_vertex(bld->gs_iface, &bld->bld_base.base,
|
bld->gs_iface->emit_vertex(bld->gs_iface, &bld->bld_base.base,
|
||||||
bld->outputs,
|
bld->outputs,
|
||||||
total_emitted_vertices_vec);
|
total_emitted_vertices_vec,
|
||||||
|
stream_id);
|
||||||
increment_vec_ptr_by_mask(bld_base, bld->emitted_vertices_vec_ptr,
|
increment_vec_ptr_by_mask(bld_base, bld->emitted_vertices_vec_ptr,
|
||||||
mask);
|
mask);
|
||||||
increment_vec_ptr_by_mask(bld_base, bld->total_emitted_vertices_vec_ptr,
|
increment_vec_ptr_by_mask(bld_base, bld->total_emitted_vertices_vec_ptr,
|
||||||
|
|
|
||||||
|
|
@ -702,8 +702,8 @@ void ProcessStreamIdBuffer(uint32_t stream,
|
||||||
{
|
{
|
||||||
SWR_ASSERT(stream < MAX_SO_STREAMS);
|
SWR_ASSERT(stream < MAX_SO_STREAMS);
|
||||||
|
|
||||||
uint32_t numInputBytes = (numEmittedVerts * 2 + 7) / 8;
|
uint32_t numInputBytes = AlignUp(numEmittedVerts * 2, 8) / 8;
|
||||||
uint32_t numOutputBytes = std::max(numInputBytes / 2, 1U);
|
uint32_t numOutputBytes = AlignUp(numEmittedVerts, 8) / 8;
|
||||||
|
|
||||||
for (uint32_t b = 0; b < numOutputBytes; ++b)
|
for (uint32_t b = 0; b < numOutputBytes; ++b)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -191,7 +191,7 @@ swr_get_param(struct pipe_screen *screen, enum pipe_cap param)
|
||||||
case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS:
|
case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS:
|
||||||
return 1024;
|
return 1024;
|
||||||
case PIPE_CAP_MAX_VERTEX_STREAMS:
|
case PIPE_CAP_MAX_VERTEX_STREAMS:
|
||||||
return 1;
|
return 4;
|
||||||
case PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE:
|
case PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE:
|
||||||
return 2048;
|
return 2048;
|
||||||
case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
|
case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
|
||||||
|
|
|
||||||
|
|
@ -251,7 +251,8 @@ struct BuilderSWR : public Builder {
|
||||||
swr_gs_llvm_emit_vertex(const struct lp_build_gs_iface *gs_base,
|
swr_gs_llvm_emit_vertex(const struct lp_build_gs_iface *gs_base,
|
||||||
struct lp_build_context * bld,
|
struct lp_build_context * bld,
|
||||||
LLVMValueRef (*outputs)[4],
|
LLVMValueRef (*outputs)[4],
|
||||||
LLVMValueRef emitted_vertices_vec);
|
LLVMValueRef emitted_vertices_vec,
|
||||||
|
LLVMValueRef stream_id);
|
||||||
|
|
||||||
void
|
void
|
||||||
swr_gs_llvm_end_primitive(const struct lp_build_gs_iface *gs_base,
|
swr_gs_llvm_end_primitive(const struct lp_build_gs_iface *gs_base,
|
||||||
|
|
@ -306,13 +307,15 @@ static void
|
||||||
swr_gs_llvm_emit_vertex(const struct lp_build_gs_iface *gs_base,
|
swr_gs_llvm_emit_vertex(const struct lp_build_gs_iface *gs_base,
|
||||||
struct lp_build_context * bld,
|
struct lp_build_context * bld,
|
||||||
LLVMValueRef (*outputs)[4],
|
LLVMValueRef (*outputs)[4],
|
||||||
LLVMValueRef emitted_vertices_vec)
|
LLVMValueRef emitted_vertices_vec,
|
||||||
|
LLVMValueRef stream_id)
|
||||||
{
|
{
|
||||||
swr_gs_llvm_iface *iface = (swr_gs_llvm_iface*)gs_base;
|
swr_gs_llvm_iface *iface = (swr_gs_llvm_iface*)gs_base;
|
||||||
|
|
||||||
iface->pBuilder->swr_gs_llvm_emit_vertex(gs_base, bld,
|
iface->pBuilder->swr_gs_llvm_emit_vertex(gs_base, bld,
|
||||||
outputs,
|
outputs,
|
||||||
emitted_vertices_vec);
|
emitted_vertices_vec,
|
||||||
|
stream_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -411,12 +414,12 @@ void
|
||||||
BuilderSWR::swr_gs_llvm_emit_vertex(const struct lp_build_gs_iface *gs_base,
|
BuilderSWR::swr_gs_llvm_emit_vertex(const struct lp_build_gs_iface *gs_base,
|
||||||
struct lp_build_context * bld,
|
struct lp_build_context * bld,
|
||||||
LLVMValueRef (*outputs)[4],
|
LLVMValueRef (*outputs)[4],
|
||||||
LLVMValueRef emitted_vertices_vec)
|
LLVMValueRef emitted_vertices_vec,
|
||||||
|
LLVMValueRef stream_id)
|
||||||
{
|
{
|
||||||
swr_gs_llvm_iface *iface = (swr_gs_llvm_iface*)gs_base;
|
swr_gs_llvm_iface *iface = (swr_gs_llvm_iface*)gs_base;
|
||||||
|
|
||||||
IRB()->SetInsertPoint(unwrap(LLVMGetInsertBlock(gallivm->builder)));
|
IRB()->SetInsertPoint(unwrap(LLVMGetInsertBlock(gallivm->builder)));
|
||||||
|
|
||||||
const uint32_t headerSize = VERTEX_COUNT_SIZE + CONTROL_HEADER_SIZE;
|
const uint32_t headerSize = VERTEX_COUNT_SIZE + CONTROL_HEADER_SIZE;
|
||||||
const uint32_t attribSize = 4 * sizeof(float);
|
const uint32_t attribSize = 4 * sizeof(float);
|
||||||
const uint32_t vertSize = attribSize * SWR_VTX_NUM_SLOTS;
|
const uint32_t vertSize = attribSize * SWR_VTX_NUM_SLOTS;
|
||||||
|
|
@ -478,6 +481,49 @@ BuilderSWR::swr_gs_llvm_emit_vertex(const struct lp_build_gs_iface *gs_base,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* When the output type is not points, the geometry shader may not
|
||||||
|
* output data to multiple streams. So early exit here.
|
||||||
|
*/
|
||||||
|
if(iface->pGsState->outputTopology != TOP_POINT_LIST) {
|
||||||
|
STACKRESTORE(pStack);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info about stream id for each vertex
|
||||||
|
// is coded in 2 bits (4 vert per byte "box"):
|
||||||
|
// ----------------- ----------------- ----
|
||||||
|
// |d|d|c|c|b|b|a|a| |h|h|g|g|f|f|e|e| |...
|
||||||
|
// ----------------- ----------------- ----
|
||||||
|
|
||||||
|
// Calculate where need to put stream id for current vert
|
||||||
|
// in 1 byte "box".
|
||||||
|
Value *pShiftControl = MUL(unwrap(emitted_vertices_vec), VIMMED1(2));
|
||||||
|
|
||||||
|
// Calculate in which box put stream id for current vert.
|
||||||
|
Value *pOffsetControl = LSHR(unwrap(emitted_vertices_vec), VIMMED1(2));
|
||||||
|
|
||||||
|
// Skip count header
|
||||||
|
Value *pStreamIdOffset = ADD(pOffsetControl, VIMMED1(VERTEX_COUNT_SIZE));
|
||||||
|
|
||||||
|
for (uint32_t lane = 0; lane < mVWidth; ++lane) {
|
||||||
|
Value *pShift = TRUNC(VEXTRACT(pShiftControl, C(lane)), mInt8Ty);
|
||||||
|
Value *pStream = LOAD(iface->pGsCtx, {0, SWR_GS_CONTEXT_pStreams, lane});
|
||||||
|
|
||||||
|
Value *pStreamOffset = GEP(pStream, VEXTRACT(pStreamIdOffset, C(lane)));
|
||||||
|
|
||||||
|
// Just make sure that not overflow max - stream id = (0,1,2,3)
|
||||||
|
Value *vVal = TRUNC(AND(VEXTRACT(unwrap(stream_id), C(0)), C(0x3)), mInt8Ty);
|
||||||
|
|
||||||
|
// Shift it to correct position in byte "box"
|
||||||
|
vVal = SHL(vVal, pShift);
|
||||||
|
|
||||||
|
// Info about other vertices can be already stored
|
||||||
|
// so we need to read and add bits from current vert info.
|
||||||
|
Value *storedValue = LOAD(pStreamOffset);
|
||||||
|
vVal = OR(storedValue, vVal);
|
||||||
|
STORE(vVal, pStreamOffset);
|
||||||
|
}
|
||||||
|
|
||||||
STACKRESTORE(pStack);
|
STACKRESTORE(pStack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -491,6 +537,15 @@ BuilderSWR::swr_gs_llvm_end_primitive(const struct lp_build_gs_iface *gs_base,
|
||||||
{
|
{
|
||||||
swr_gs_llvm_iface *iface = (swr_gs_llvm_iface*)gs_base;
|
swr_gs_llvm_iface *iface = (swr_gs_llvm_iface*)gs_base;
|
||||||
|
|
||||||
|
/* When the output type is points, the geometry shader may output data
|
||||||
|
* to multiple streams, and end_primitive has no effect. Info about
|
||||||
|
* stream id for vertices is stored into the same place in memory where
|
||||||
|
* end primitive info is stored so early exit in this case.
|
||||||
|
*/
|
||||||
|
if (iface->pGsState->outputTopology == TOP_POINT_LIST) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
IRB()->SetInsertPoint(unwrap(LLVMGetInsertBlock(gallivm->builder)));
|
IRB()->SetInsertPoint(unwrap(LLVMGetInsertBlock(gallivm->builder)));
|
||||||
|
|
||||||
Value *vMask = LOAD(iface->pGsCtx, { 0, SWR_GS_CONTEXT_mask });
|
Value *vMask = LOAD(iface->pGsCtx, { 0, SWR_GS_CONTEXT_mask });
|
||||||
|
|
@ -569,9 +624,13 @@ BuilderSWR::CompileGS(struct swr_context *ctx, swr_jit_gs_key &key)
|
||||||
pGS->maxNumVerts = info->properties[TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES];
|
pGS->maxNumVerts = info->properties[TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES];
|
||||||
pGS->instanceCount = info->properties[TGSI_PROPERTY_GS_INVOCATIONS];
|
pGS->instanceCount = info->properties[TGSI_PROPERTY_GS_INVOCATIONS];
|
||||||
|
|
||||||
// XXX: single stream for now...
|
// If point primitive then assume to use multiple streams
|
||||||
pGS->isSingleStream = true;
|
if(pGS->outputTopology == TOP_POINT_LIST) {
|
||||||
pGS->singleStreamID = 0;
|
pGS->isSingleStream = false;
|
||||||
|
} else {
|
||||||
|
pGS->isSingleStream = true;
|
||||||
|
pGS->singleStreamID = 0;
|
||||||
|
}
|
||||||
|
|
||||||
pGS->vertexAttribOffset = VERTEX_POSITION_SLOT;
|
pGS->vertexAttribOffset = VERTEX_POSITION_SLOT;
|
||||||
pGS->inputVertStride = pGS->numInputAttribs + pGS->vertexAttribOffset;
|
pGS->inputVertStride = pGS->numInputAttribs + pGS->vertexAttribOffset;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue