brw: consider 'volatile' memory access when doing CSE

The GLSL spec says (among other things):

  "When a volatile variable is read, its value must be re-fetched from
   the underlying memory, even if the shader invocation performing the
   read had previously fetched its value from the same memory. When a
   volatile variable is written, its value must be written to the
   underlying memory, even if the compiler can conclusively determine
   that its value will be overwritten by a subsequent write."

The SPIR-V spec says (among other things):

  "Accesses to volatile memory cannot be eliminated, duplicated, or
   combined with other accesses."

So in this commit we make sure that both writes and reads marked as
volatile can't be affected by CSE.

v2: Reorder patches in the series.

Credits-to: Caio Oliveira <caio.oliveira@intel.com>
Reviewed-by: Caio Oliveira <caio.oliveira@intel.com>
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> (v1)
Reviewed-by: Iván Briano <ivan.briano@intel.com> (v1)
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36150>
This commit is contained in:
Paulo Zanoni 2025-07-15 12:58:22 -07:00 committed by Marge Bot
parent 8e1e3ba152
commit f7581e4a38
2 changed files with 17 additions and 6 deletions

View file

@ -956,10 +956,19 @@ brw_inst::has_side_effects() const
bool
brw_inst::is_volatile() const
{
return opcode == SHADER_OPCODE_MEMORY_LOAD_LOGICAL ||
opcode == SHADER_OPCODE_LOAD_REG ||
((opcode == SHADER_OPCODE_SEND ||
opcode == SHADER_OPCODE_SEND_GATHER) && send_is_volatile);
switch (opcode) {
case SHADER_OPCODE_MEMORY_LOAD_LOGICAL:
case SHADER_OPCODE_LOAD_REG:
return true;
case SHADER_OPCODE_MEMORY_STORE_LOGICAL:
assert(sources > MEMORY_LOGICAL_FLAGS);
return src[MEMORY_LOGICAL_FLAGS].ud & MEMORY_FLAG_VOLATILE_ACCESS;
case SHADER_OPCODE_SEND:
case SHADER_OPCODE_SEND_GATHER:
return send_is_volatile;
default:
return false;
}
}
void

View file

@ -1512,6 +1512,7 @@ lower_lsc_memory_logical_send(const brw_builder &bld, brw_inst *inst)
(enum memory_flags) inst->src[MEMORY_LOGICAL_FLAGS].ud;
const bool transpose = flags & MEMORY_FLAG_TRANSPOSE;
const bool include_helpers = flags & MEMORY_FLAG_INCLUDE_HELPERS;
const bool volatile_access = flags & MEMORY_FLAG_VOLATILE_ACCESS;
const brw_reg data0 = inst->src[MEMORY_LOGICAL_DATA0];
const brw_reg data1 = inst->src[MEMORY_LOGICAL_DATA1];
const bool has_side_effects = inst->has_side_effects();
@ -1638,7 +1639,7 @@ lower_lsc_memory_logical_send(const brw_builder &bld, brw_inst *inst)
inst->ex_mlen = ex_mlen;
inst->header_size = 0;
inst->send_has_side_effects = has_side_effects;
inst->send_is_volatile = !has_side_effects;
inst->send_is_volatile = !has_side_effects || volatile_access;
inst->resize_sources(4);
@ -1708,6 +1709,7 @@ lower_hdc_memory_logical_send(const brw_builder &bld, brw_inst *inst)
(enum memory_flags) inst->src[MEMORY_LOGICAL_FLAGS].ud;
const bool block = flags & MEMORY_FLAG_TRANSPOSE;
const bool include_helpers = flags & MEMORY_FLAG_INCLUDE_HELPERS;
const bool volatile_access = flags & MEMORY_FLAG_VOLATILE_ACCESS;
const brw_reg data0 = inst->src[MEMORY_LOGICAL_DATA0];
const brw_reg data1 = inst->src[MEMORY_LOGICAL_DATA1];
const bool has_side_effects = inst->has_side_effects();
@ -1921,7 +1923,7 @@ lower_hdc_memory_logical_send(const brw_builder &bld, brw_inst *inst)
inst->ex_mlen = ex_mlen;
inst->header_size = header.file != BAD_FILE ? 1 : 0;
inst->send_has_side_effects = has_side_effects;
inst->send_is_volatile = !has_side_effects;
inst->send_is_volatile = !has_side_effects || volatile_access;
if (block) {
assert(inst->force_writemask_all);