Files
third_party_mesa3d/src/gallium/drivers/svga/svga_shader_buffer.c
Yonggang Luo 1ac1c0843f treewide: Replace usage of macro DEBUG with MESA_DEBUG when possible
This is achieved by the following steps:

#ifndef DEBUG => #if !MESA_DEBUG
defined(DEBUG) => MESA_DEBUG
#ifdef DEBUG => #if MESA_DEBUG

This is done by replace in vscode

excludes
docs,*.rs,addrlib,src/imgui,*.sh,src/intel/vulkan/grl/gpu

These are safe because those files should keep DEBUG macro is already excluded;
and not directly replace DEBUG, as we have some symbols around it.

Use debug or NDEBUG instead of DEBUG in comments when proper

This for reduce the usage of DEBUG,
so it's easier migrating to MESA_DEBUG

These are found when migrating DEBUG to MESA_DEBUG,
these are all comment update, so it's safe

Replace comment /* DEBUG */ and /* !DEBUG */ with proper /* MESA_DEBUG */ or /* !MESA_DEBUG */ manually

DEBUG || !NDEBUG -> MESA_DEBUG || !NDEBUG
!DEBUG && NDEBUG -> !(MESA_DEBUG || !NDEBUG)

Replace the DEBUG present in comment with proper new MESA_DEBUG manually

Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
Acked-by: David Heidelberg <david.heidelberg@collabora.com>
Reviewed-by: Eric Engestrom <eric@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/28092>
2024-03-22 18:22:34 +00:00

414 lines
13 KiB
C

/**********************************************************
* Copyright 2022 VMware, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
**********************************************************/
#include "pipe/p_defines.h"
#include "util/u_bitmask.h"
#include "util/format/u_format.h"
#include "util/u_inlines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "svga_context.h"
#include "svga_cmd.h"
#include "svga_debug.h"
#include "svga_resource_buffer.h"
#include "svga_resource_texture.h"
#include "svga_surface.h"
#include "svga_sampler_view.h"
#include "svga_format.h"
/**
* Create a uav object for the specified shader buffer
*/
SVGA3dUAViewId
svga_create_uav_buffer(struct svga_context *svga,
const struct pipe_shader_buffer *buf,
SVGA3dSurfaceFormat format,
SVGA3dUABufferFlags bufFlag)
{
SVGA3dUAViewDesc desc;
unsigned uaViewId;
assert(buf);
/* If there is not one defined, create one. */
memset(&desc, 0, sizeof(desc));
desc.buffer.firstElement = buf->buffer_offset / sizeof(uint32);
desc.buffer.numElements = buf->buffer_size / sizeof(uint32);
desc.buffer.flags = bufFlag;
uaViewId = svga_create_uav(svga, &desc, format,
SVGA3D_RESOURCE_BUFFER,
svga_buffer_handle(svga, buf->buffer,
PIPE_BIND_SHADER_BUFFER));
if (uaViewId == SVGA3D_INVALID_ID)
return uaViewId;
SVGA_DBG(DEBUG_UAV, "%s: resource=0x%x uaViewId=%d\n",
__func__, buf->buffer, uaViewId);
/* Mark this buffer as a uav bound buffer */
struct svga_buffer *sbuf = svga_buffer(buf->buffer);
sbuf->uav = true;
return uaViewId;
}
/**
* Set shader buffers.
*/
static void
svga_set_shader_buffers(struct pipe_context *pipe,
enum pipe_shader_type shader,
unsigned start, unsigned num,
const struct pipe_shader_buffer *buffers,
unsigned writeable_bitmask)
{
struct svga_context *svga = svga_context(pipe);
const struct pipe_shader_buffer *buf;
assert(svga_have_gl43(svga));
assert(start + num <= SVGA_MAX_SHADER_BUFFERS);
#if MESA_DEBUG
const struct pipe_shader_buffer *b = buffers;
SVGA_DBG(DEBUG_UAV, "%s: shader=%d start=%d num=%d ",
__func__, shader, start, num);
if (buffers) {
for (unsigned i = 0; i < num; i++, b++) {
SVGA_DBG(DEBUG_UAV, " 0x%x ", b);
}
}
SVGA_DBG(DEBUG_UAV, "\n");
#endif
buf = buffers;
if (buffers) {
int last_buffer = -1;
for (unsigned i = start, j=0; i < start + num; i++, buf++, j++) {
struct svga_shader_buffer *cbuf = &svga->curr.shader_buffers[shader][i];
if (buf && buf->buffer) {
cbuf->desc = *buf;
pipe_resource_reference(&cbuf->resource, buf->buffer);
/* Mark the last bound shader buffer */
last_buffer = i;
}
else {
cbuf->desc.buffer = NULL;
pipe_resource_reference(&cbuf->resource, NULL);
}
cbuf->uav_index = -1;
cbuf->writeAccess = (writeable_bitmask & (1 << j)) != 0;
}
svga->curr.num_shader_buffers[shader] =
MAX2(svga->curr.num_shader_buffers[shader], last_buffer + 1);
}
else {
for (unsigned i = start; i < start + num; i++) {
struct svga_shader_buffer *cbuf = &svga->curr.shader_buffers[shader][i];
cbuf->desc.buffer = NULL;
cbuf->uav_index = -1;
pipe_resource_reference(&cbuf->resource, NULL);
}
if ((start + num) >= svga->curr.num_shader_buffers[shader])
svga->curr.num_shader_buffers[shader] = start;
}
#if MESA_DEBUG
SVGA_DBG(DEBUG_UAV,
"%s: current num_shader_buffers=%d start=%d num=%d buffers=",
__func__, svga->curr.num_shader_buffers[shader],
start, num);
for (unsigned i = start; i < start + num; i++) {
struct svga_shader_buffer *cbuf = &svga->curr.shader_buffers[shader][i];
SVGA_DBG(DEBUG_UAV, " 0x%x ", cbuf->desc.buffer);
}
SVGA_DBG(DEBUG_UAV, "\n");
#endif
/* purge any unused uav objects */
svga_destroy_uav(svga);
svga->dirty |= SVGA_NEW_SHADER_BUFFER;
}
/**
* Set HW atomic buffers.
*/
static void
svga_set_hw_atomic_buffers(struct pipe_context *pipe,
unsigned start, unsigned num,
const struct pipe_shader_buffer *buffers)
{
struct svga_context *svga = svga_context(pipe);
const struct pipe_shader_buffer *buf = buffers;
assert(svga_have_gl43(svga));
assert(start + num <= SVGA_MAX_ATOMIC_BUFFERS);
#if MESA_DEBUG
SVGA_DBG(DEBUG_UAV, "%s: start=%d num=%d \n", __func__, start, num);
#endif
buf = buffers;
if (buffers) {
int last_buffer = -1;
for (unsigned i = start; i < start + num; i++, buf++) {
struct svga_shader_buffer *cbuf = &svga->curr.atomic_buffers[i];
if (buf && buf->buffer) {
cbuf->desc = *buf;
pipe_resource_reference(&cbuf->resource, buf->buffer);
last_buffer = i;
/* Mark the buffer as uav buffer so that a readback will
* be done at each read transfer. We can't rely on the
* dirty bit because it is reset after each read, but
* the uav buffer can be updated at each draw.
*/
struct svga_buffer *sbuf = svga_buffer(cbuf->desc.buffer);
sbuf->uav = true;
}
else {
cbuf->desc.buffer = NULL;
pipe_resource_reference(&cbuf->resource, NULL);
}
cbuf->uav_index = -1;
}
svga->curr.num_atomic_buffers = MAX2(svga->curr.num_atomic_buffers,
last_buffer + 1);
}
else {
for (unsigned i = start; i < start + num; i++) {
struct svga_shader_buffer *cbuf = &svga->curr.atomic_buffers[i];
cbuf->desc.buffer = NULL;
cbuf->uav_index = -1;
pipe_resource_reference(&cbuf->resource, NULL);
}
if ((start + num) >= svga->curr.num_atomic_buffers)
svga->curr.num_atomic_buffers = start;
}
#if MESA_DEBUG
SVGA_DBG(DEBUG_UAV, "%s: current num_atomic_buffers=%d start=%d num=%d ",
__func__, svga->curr.num_atomic_buffers,
start, num);
for (unsigned i = start; i < start + num; i++) {
struct svga_shader_buffer *cbuf = &svga->curr.atomic_buffers[i];
SVGA_DBG(DEBUG_UAV, " 0x%x ", cbuf->desc.buffer);
}
SVGA_DBG(DEBUG_UAV, "\n");
#endif
/* purge any unused uav objects */
svga_destroy_uav(svga);
svga->dirty |= SVGA_NEW_SHADER_BUFFER;
}
/**
* Initialize shader images gallium interface
*/
void
svga_init_shader_buffer_functions(struct svga_context *svga)
{
if (!svga_have_gl43(svga))
return;
svga->pipe.set_shader_buffers = svga_set_shader_buffers;
svga->pipe.set_hw_atomic_buffers = svga_set_hw_atomic_buffers;
/* Initialize shader buffers */
for (unsigned shader = 0; shader < PIPE_SHADER_TYPES; ++shader) {
struct svga_shader_buffer *hw_buf =
&svga->state.hw_draw.shader_buffers[shader][0];
struct svga_shader_buffer *cur_buf =
&svga->curr.shader_buffers[shader][0];
/* Initialize uaViewId to SVGA3D_INVALID_ID for current shader buffers
* and shader buffers in hw state to avoid unintentional unbinding of
* shader buffers with uaViewId 0.
*/
for (unsigned i = 0; i < ARRAY_SIZE(svga->curr.shader_buffers[shader]);
i++, hw_buf++, cur_buf++) {
hw_buf->resource = NULL;
hw_buf->uav_index = -1;
cur_buf->desc.buffer = NULL;
cur_buf->resource = NULL;
cur_buf->uav_index = -1;
}
}
memset(svga->state.hw_draw.num_shader_buffers, 0,
sizeof(svga->state.hw_draw.num_shader_buffers));
/* Initialize atomic buffers */
/* Initialize uaViewId to SVGA3D_INVALID_ID for current atomic buffers
* and atomic buffers in hw state to avoid unintentional unbinding of
* shader buffer with uaViewId 0.
*/
for (unsigned i = 0; i < ARRAY_SIZE(svga->state.hw_draw.atomic_buffers); i++) {
svga->curr.atomic_buffers[i].resource = NULL;
svga->curr.atomic_buffers[i].uav_index = -1;
}
svga->state.hw_draw.num_atomic_buffers = 0;
}
/**
* Cleanup shader image state
*/
void
svga_cleanup_shader_buffer_state(struct svga_context *svga)
{
if (!svga_have_gl43(svga))
return;
svga_destroy_uav(svga);
}
/**
* Validate shader buffer resources to ensure any pending changes to the
* buffers are emitted before they are referenced.
* The helper function also rebinds the buffer resources if the rebind flag
* is specified.
*/
enum pipe_error
svga_validate_shader_buffer_resources(struct svga_context *svga,
unsigned count,
struct svga_shader_buffer *bufs,
bool rebind)
{
assert(svga_have_gl43(svga));
struct svga_winsys_surface *surf;
enum pipe_error ret;
unsigned i;
for (i = 0; i < count; i++) {
if (bufs[i].resource) {
assert(bufs[i].resource == bufs[i].desc.buffer);
struct svga_buffer *sbuf = svga_buffer(bufs[i].resource);
surf = svga_buffer_handle(svga, bufs[i].desc.buffer,
PIPE_BIND_SHADER_BUFFER);
assert(surf);
if (rebind) {
ret = svga->swc->resource_rebind(svga->swc, surf, NULL,
SVGA_RELOC_READ|SVGA_RELOC_WRITE);
if (ret != PIPE_OK)
return ret;
}
/* Mark buffer as RENDERED */
svga_set_buffer_rendered_to(sbuf->bufsurf);
}
}
return PIPE_OK;
}
/**
* Returns TRUE if the shader buffer can be bound to SRV as raw buffer.
* It is TRUE if the shader buffer is readonly and the surface already
* has the RAW_BUFFER_VIEW bind flag set.
*/
bool
svga_shader_buffer_can_use_srv(struct svga_context *svga,
enum pipe_shader_type shader,
unsigned index,
struct svga_shader_buffer *buf)
{
if (buf->resource) {
struct svga_buffer *sbuf = svga_buffer(buf->resource);
if (sbuf && !buf->writeAccess && svga_has_raw_buffer_view(sbuf)) {
return true;
}
}
return false;
}
#define SVGA_SSBO_SRV_START SVGA_MAX_CONST_BUFS
/**
* Bind the shader buffer as SRV raw buffer.
*/
enum pipe_error
svga_shader_buffer_bind_srv(struct svga_context *svga,
enum pipe_shader_type shader,
unsigned index,
struct svga_shader_buffer *buf)
{
enum pipe_error ret;
unsigned slot = index + SVGA_SSBO_SRV_START;
svga->state.raw_shaderbufs[shader] |= (1 << index);
ret = svga_emit_rawbuf(svga, slot, shader, buf->desc.buffer_offset,
buf->desc.buffer_size, buf->resource);
if (ret == PIPE_OK)
svga->state.hw_draw.enabled_raw_shaderbufs[shader] |= (1 << index);
return ret;
}
/**
* Unbind the shader buffer SRV.
*/
enum pipe_error
svga_shader_buffer_unbind_srv(struct svga_context *svga,
enum pipe_shader_type shader,
unsigned index,
struct svga_shader_buffer *buf)
{
enum pipe_error ret = PIPE_OK;
unsigned slot = index + SVGA_SSBO_SRV_START;
if ((svga->state.hw_draw.enabled_raw_shaderbufs[shader] & (1 << index))
!= 0) {
ret = svga_emit_rawbuf(svga, slot, shader, 0, 0, NULL);
if (ret == PIPE_OK)
svga->state.hw_draw.enabled_raw_shaderbufs[shader] &= ~(1 << index);
}
svga->state.raw_shaderbufs[shader] &= ~(1 << index);
return ret;
}