Pushing constants.
This commit is contained in:
parent
7b2a508db0
commit
b3faba50a3
|
@ -133,24 +133,30 @@ void SpirvShaderTranslator::StartTranslation() {
|
|||
b.addDecoration(consts_, spv::Decoration::DecorationBinding, 1);
|
||||
}
|
||||
|
||||
// Push constants.
|
||||
Id push_constants_type =
|
||||
b.makeStructType({vec4_float_type_, vec4_float_type_, vec4_float_type_},
|
||||
"push_consts_type");
|
||||
|
||||
b.addMemberDecoration(push_constants_type, 0,
|
||||
spv::Decoration::DecorationOffset, 0);
|
||||
// Push constants, represented by SpirvPushConstants.
|
||||
Id push_constants_type = b.makeStructType(
|
||||
{vec4_float_type_, vec4_float_type_, vec4_float_type_, uint_type},
|
||||
"push_consts_type");
|
||||
// float4 window_scale;
|
||||
b.addMemberDecoration(
|
||||
push_constants_type, 0, spv::Decoration::DecorationOffset,
|
||||
static_cast<int>(offsetof(SpirvPushConstants, window_scale)));
|
||||
b.addMemberName(push_constants_type, 0, "window_scale");
|
||||
|
||||
b.addMemberDecoration(push_constants_type, 1,
|
||||
spv::Decoration::DecorationOffset, 4 * sizeof(float));
|
||||
// float4 vtx_fmt;
|
||||
b.addMemberDecoration(
|
||||
push_constants_type, 1, spv::Decoration::DecorationOffset,
|
||||
static_cast<int>(offsetof(SpirvPushConstants, vtx_fmt)));
|
||||
b.addMemberName(push_constants_type, 1, "vtx_fmt");
|
||||
|
||||
b.addMemberDecoration(push_constants_type, 2,
|
||||
spv::Decoration::DecorationOffset,
|
||||
2 * 4 * sizeof(float));
|
||||
// float4 alpha_test;
|
||||
b.addMemberDecoration(
|
||||
push_constants_type, 2, spv::Decoration::DecorationOffset,
|
||||
static_cast<int>(offsetof(SpirvPushConstants, alpha_test)));
|
||||
b.addMemberName(push_constants_type, 2, "alpha_test");
|
||||
|
||||
// uint ps_param_gen;
|
||||
b.addMemberDecoration(
|
||||
push_constants_type, 3, spv::Decoration::DecorationOffset,
|
||||
static_cast<int>(offsetof(SpirvPushConstants, ps_param_gen)));
|
||||
b.addMemberName(push_constants_type, 3, "ps_param_gen");
|
||||
push_consts_ = b.createVariable(spv::StorageClass::StorageClassPushConstant,
|
||||
push_constants_type, "push_consts");
|
||||
|
||||
|
|
|
@ -22,6 +22,28 @@
|
|||
namespace xe {
|
||||
namespace gpu {
|
||||
|
||||
// Push constants embedded within the command buffer.
|
||||
// The total size of this struct must be <= 128b (as that's the commonly
|
||||
// supported size).
|
||||
struct SpirvPushConstants {
|
||||
// Accessible to vertex shader only:
|
||||
float window_scale[4]; // sx,sy, ?, ?
|
||||
float vtx_fmt[4];
|
||||
|
||||
// Accessible to fragment shader only:
|
||||
float alpha_test[4]; // alpha test enable, func, ref, ?
|
||||
uint32_t ps_param_gen;
|
||||
};
|
||||
static_assert(sizeof(SpirvPushConstants) <= 128,
|
||||
"Push constants must fit <= 128b");
|
||||
constexpr uint32_t kSpirvPushConstantVertexRangeOffset = 0;
|
||||
constexpr uint32_t kSpirvPushConstantVertexRangeSize = (sizeof(float) * 4) * 2;
|
||||
constexpr uint32_t kSpirvPushConstantFragmentRangeOffset =
|
||||
kSpirvPushConstantVertexRangeSize;
|
||||
constexpr uint32_t kSpirvPushConstantFragmentRangeSize =
|
||||
(sizeof(float) * 4) + sizeof(uint32_t);
|
||||
constexpr uint32_t kSpirvPushConstantsSize = sizeof(SpirvPushConstants);
|
||||
|
||||
class SpirvShaderTranslator : public ShaderTranslator {
|
||||
public:
|
||||
SpirvShaderTranslator();
|
||||
|
|
|
@ -59,13 +59,12 @@ PipelineCache::PipelineCache(
|
|||
|
||||
// Push constants used for draw parameters.
|
||||
// We need to keep these under 128b across all stages.
|
||||
VkPushConstantRange push_constant_ranges[2];
|
||||
push_constant_ranges[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
// TODO(benvanik): split between the stages?
|
||||
VkPushConstantRange push_constant_ranges[1];
|
||||
push_constant_ranges[0].stageFlags =
|
||||
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
push_constant_ranges[0].offset = 0;
|
||||
push_constant_ranges[0].size = sizeof(float) * 16;
|
||||
push_constant_ranges[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
push_constant_ranges[1].offset = sizeof(float) * 16;
|
||||
push_constant_ranges[1].size = sizeof(int);
|
||||
push_constant_ranges[0].size = kSpirvPushConstantsSize;
|
||||
|
||||
// Shared pipeline layout.
|
||||
VkPipelineLayoutCreateInfo pipeline_layout_info;
|
||||
|
@ -511,26 +510,74 @@ bool PipelineCache::SetDynamicState(VkCommandBuffer command_buffer,
|
|||
|
||||
// TODO(benvanik): push constants.
|
||||
|
||||
bool push_constants_dirty = full_update;
|
||||
bool push_constants_dirty = full_update || viewport_state_dirty;
|
||||
push_constants_dirty |=
|
||||
SetShadowRegister(®s.sq_program_cntl, XE_GPU_REG_SQ_PROGRAM_CNTL);
|
||||
push_constants_dirty |=
|
||||
SetShadowRegister(®s.sq_context_misc, XE_GPU_REG_SQ_CONTEXT_MISC);
|
||||
push_constants_dirty |=
|
||||
SetShadowRegister(®s.rb_colorcontrol, XE_GPU_REG_RB_COLORCONTROL);
|
||||
push_constants_dirty |=
|
||||
SetShadowRegister(®s.rb_alpha_ref, XE_GPU_REG_RB_ALPHA_REF);
|
||||
if (push_constants_dirty) {
|
||||
xenos::xe_gpu_program_cntl_t program_cntl;
|
||||
program_cntl.dword_0 = regs.sq_program_cntl;
|
||||
|
||||
xenos::xe_gpu_program_cntl_t program_cntl;
|
||||
program_cntl.dword_0 = regs.sq_program_cntl;
|
||||
// Normal vertex shaders only, for now.
|
||||
// TODO(benvanik): transform feedback/memexport.
|
||||
// https://github.com/freedreno/freedreno/blob/master/includes/a2xx.xml.h
|
||||
// 0 = normal
|
||||
// 2 = point size
|
||||
assert_true(program_cntl.vs_export_mode == 0 ||
|
||||
program_cntl.vs_export_mode == 2);
|
||||
|
||||
// Populate a register in the pixel shader with frag coord.
|
||||
int ps_param_gen = (regs.sq_context_misc >> 8) & 0xFF;
|
||||
// draw_batcher_.set_ps_param_gen(program_cntl.param_gen ? ps_param_gen : -1);
|
||||
SpirvPushConstants push_constants;
|
||||
|
||||
// Normal vertex shaders only, for now.
|
||||
// TODO(benvanik): transform feedback/memexport.
|
||||
// https://github.com/freedreno/freedreno/blob/master/includes/a2xx.xml.h
|
||||
// 0 = normal
|
||||
// 2 = point size
|
||||
assert_true(program_cntl.vs_export_mode == 0 ||
|
||||
program_cntl.vs_export_mode == 2);
|
||||
// Done in VS, no need to flush state.
|
||||
if ((regs.pa_cl_vte_cntl & (1 << 0)) > 0) {
|
||||
push_constants.window_scale[0] = 1.0f;
|
||||
push_constants.window_scale[1] = 1.0f;
|
||||
} else {
|
||||
push_constants.window_scale[0] = 1.0f / 2560.0f;
|
||||
push_constants.window_scale[1] = -1.0f / 2560.0f;
|
||||
}
|
||||
|
||||
// http://www.x.org/docs/AMD/old/evergreen_3D_registers_v2.pdf
|
||||
// VTX_XY_FMT = true: the incoming XY have already been multiplied by 1/W0.
|
||||
// = false: multiply the X, Y coordinates by 1/W0.
|
||||
// VTX_Z_FMT = true: the incoming Z has already been multiplied by 1/W0.
|
||||
// = false: multiply the Z coordinate by 1/W0.
|
||||
// VTX_W0_FMT = true: the incoming W0 is not 1/W0. Perform the reciprocal to
|
||||
// get 1/W0.
|
||||
float vtx_xy_fmt = (regs.pa_cl_vte_cntl >> 8) & 0x1 ? 1.0f : 0.0f;
|
||||
float vtx_z_fmt = (regs.pa_cl_vte_cntl >> 9) & 0x1 ? 1.0f : 0.0f;
|
||||
float vtx_w0_fmt = (regs.pa_cl_vte_cntl >> 10) & 0x1 ? 1.0f : 0.0f;
|
||||
push_constants.vtx_fmt[0] = vtx_xy_fmt;
|
||||
push_constants.vtx_fmt[1] = vtx_xy_fmt;
|
||||
push_constants.vtx_fmt[2] = vtx_z_fmt;
|
||||
push_constants.vtx_fmt[3] = vtx_w0_fmt;
|
||||
|
||||
// Alpha testing -- ALPHAREF, ALPHAFUNC, ALPHATESTENABLE
|
||||
// Deprecated in Vulkan, implemented in shader.
|
||||
// if(ALPHATESTENABLE && frag_out.a [<=/ALPHAFUNC] ALPHAREF) discard;
|
||||
// ALPHATESTENABLE
|
||||
push_constants.alpha_test[0] =
|
||||
(regs.rb_colorcontrol & 0x8) != 0 ? 1.0f : 0.0f;
|
||||
// ALPHAFUNC
|
||||
push_constants.alpha_test[1] =
|
||||
static_cast<float>(regs.rb_colorcontrol & 0x7);
|
||||
// ALPHAREF
|
||||
push_constants.alpha_test[2] = regs.rb_alpha_ref;
|
||||
|
||||
// Whether to populate a register in the pixel shader with frag coord.
|
||||
int ps_param_gen = (regs.sq_context_misc >> 8) & 0xFF;
|
||||
push_constants.ps_param_gen = program_cntl.param_gen ? ps_param_gen : -1;
|
||||
|
||||
vkCmdPushConstants(
|
||||
command_buffer, pipeline_layout_,
|
||||
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0,
|
||||
kSpirvPushConstantsSize, &push_constants);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -262,6 +262,8 @@ class PipelineCache {
|
|||
|
||||
uint32_t sq_program_cntl;
|
||||
uint32_t sq_context_misc;
|
||||
uint32_t rb_colorcontrol;
|
||||
float rb_alpha_ref;
|
||||
|
||||
SetDynamicStateRegisters() { Reset(); }
|
||||
void Reset() { std::memset(this, 0, sizeof(*this)); }
|
||||
|
|
Loading…
Reference in New Issue