Merge pull request #1738 from billhollings/return-value-after-discard-terminator
MSL: Return fragment function value even when last SPIR-V Op is discard (OpKill).
This commit is contained in:
commit
b81334a513
@ -0,0 +1,25 @@
|
|||||||
|
#include <metal_stdlib>
|
||||||
|
#include <simd/simd.h>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
|
||||||
|
struct buff_t
|
||||||
|
{
|
||||||
|
int m0[1024];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct main0_out
|
||||||
|
{
|
||||||
|
float4 frag_clr [[color(0)]];
|
||||||
|
};
|
||||||
|
|
||||||
|
fragment main0_out main0(device buff_t& buff [[buffer(0)]], float4 gl_FragCoord [[position]])
|
||||||
|
{
|
||||||
|
main0_out out = {};
|
||||||
|
int4 _16 = int4(gl_FragCoord);
|
||||||
|
out.frag_clr = float4(0.0, 0.0, 1.0, 1.0);
|
||||||
|
buff.m0[(_16.y * 32) + _16.x] = 1;
|
||||||
|
discard_fragment();
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
|||||||
|
#version 450
|
||||||
|
#extension GL_EXT_buffer_reference : require
|
||||||
|
#extension GL_EXT_buffer_reference_uvec2 : require
|
||||||
|
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout(buffer_reference) buffer PtrInt;
|
||||||
|
layout(buffer_reference, std430) buffer PtrInt
|
||||||
|
{
|
||||||
|
int value;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(set = 0, binding = 0, std430) buffer Buf
|
||||||
|
{
|
||||||
|
uvec2 ptr;
|
||||||
|
PtrInt ptrint;
|
||||||
|
} _13;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
_13.ptr = uvec2(_13.ptrint);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
|||||||
|
#include <metal_stdlib>
|
||||||
|
#include <simd/simd.h>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
|
||||||
|
struct buff_t
|
||||||
|
{
|
||||||
|
int m0[1024];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct main0_out
|
||||||
|
{
|
||||||
|
float4 frag_clr [[color(0)]];
|
||||||
|
};
|
||||||
|
|
||||||
|
fragment main0_out main0(device buff_t& buff [[buffer(0)]], float4 gl_FragCoord [[position]])
|
||||||
|
{
|
||||||
|
main0_out out = {};
|
||||||
|
int2 frag_coord = int2(int4(gl_FragCoord).xy);
|
||||||
|
int buff_idx = (frag_coord.y * 32) + frag_coord.x;
|
||||||
|
out.frag_clr = float4(0.0, 0.0, 1.0, 1.0);
|
||||||
|
buff.m0[buff_idx] = 1;
|
||||||
|
discard_fragment();
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
17
shaders-msl/frag/return-value-after-discard-terminator.frag
Normal file
17
shaders-msl/frag/return-value-after-discard-terminator.frag
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
layout(set = 0, binding = 0, std430) buffer buff_t
|
||||||
|
{
|
||||||
|
int m0[1024];
|
||||||
|
} buff;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 frag_clr;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
ivec2 frag_coord = ivec2(ivec4(gl_FragCoord).xy);
|
||||||
|
int buff_idx = (frag_coord.y * 32) + frag_coord.x;
|
||||||
|
frag_clr = vec4(0.0, 0.0, 1.0, 1.0);
|
||||||
|
buff.m0[buff_idx] = 1;
|
||||||
|
discard;
|
||||||
|
}
|
@ -15084,8 +15084,11 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the Kill is terminating a block with a (probably synthetic) return value, emit a return value statement.
|
||||||
case SPIRBlock::Kill:
|
case SPIRBlock::Kill:
|
||||||
statement(backend.discard_literal, ";");
|
statement(backend.discard_literal, ";");
|
||||||
|
if (block.return_value)
|
||||||
|
statement("return ", to_expression(block.return_value), ";");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPIRBlock::Unreachable:
|
case SPIRBlock::Unreachable:
|
||||||
|
@ -3467,6 +3467,9 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage, bool patch)
|
|||||||
// Add the output interface struct as a local variable to the entry function.
|
// Add the output interface struct as a local variable to the entry function.
|
||||||
// If the entry point should return the output struct, set the entry function
|
// If the entry point should return the output struct, set the entry function
|
||||||
// to return the output interface struct, otherwise to return nothing.
|
// to return the output interface struct, otherwise to return nothing.
|
||||||
|
// Watch out for the rare case where the terminator of the last entry point block is a
|
||||||
|
// Kill, instead of a Return. Based on SPIR-V's block-domination rules, we assume that
|
||||||
|
// any block that has a Kill will also have a terminating Return, except the last block.
|
||||||
// Indicate the output var requires early initialization.
|
// Indicate the output var requires early initialization.
|
||||||
bool ep_should_return_output = !get_is_rasterization_disabled();
|
bool ep_should_return_output = !get_is_rasterization_disabled();
|
||||||
uint32_t rtn_id = ep_should_return_output ? ib_var_id : 0;
|
uint32_t rtn_id = ep_should_return_output ? ib_var_id : 0;
|
||||||
@ -3476,7 +3479,7 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage, bool patch)
|
|||||||
for (auto &blk_id : entry_func.blocks)
|
for (auto &blk_id : entry_func.blocks)
|
||||||
{
|
{
|
||||||
auto &blk = get<SPIRBlock>(blk_id);
|
auto &blk = get<SPIRBlock>(blk_id);
|
||||||
if (blk.terminator == SPIRBlock::Return)
|
if (blk.terminator == SPIRBlock::Return || (blk.terminator == SPIRBlock::Kill && blk_id == entry_func.blocks.back()))
|
||||||
blk.return_value = rtn_id;
|
blk.return_value = rtn_id;
|
||||||
}
|
}
|
||||||
vars_needing_early_declaration.push_back(ib_var_id);
|
vars_needing_early_declaration.push_back(ib_var_id);
|
||||||
|
Loading…
Reference in New Issue
Block a user