Commit 253daa56 by Jamie Madill Committed by Commit Bot

D3D: Split applyTextures into each back-end.

This paves the way for a dirty bits implementation for Textures, and also will allow more precise ordering of the state update in D3D11. The latter becomes important when moving the shader application. Because the texture update can affect the built-in driver uniforms, we neeed to update textures before we update the uniforms. BUG=angleproject:1156 BUG=angleproject:1387 Change-Id: I995e095517c598d8672c6400d08a430da0e8339b Reviewed-on: https://chromium-review.googlesource.com/580361Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 590f6235
......@@ -59,88 +59,6 @@ void RendererD3D::cleanup()
mIncompleteTextures.clear();
}
// For each Direct3D sampler of either the pixel or vertex stage,
// looks up the corresponding OpenGL texture image unit and texture type,
// and sets the texture and its addressing/filtering state (or NULL when inactive).
// Sampler mapping needs to be up-to-date on the program object before this is called.
gl::Error RendererD3D::applyTextures(const gl::Context *context,
gl::SamplerType shaderType,
const FramebufferTextureArray &framebufferTextures,
size_t framebufferTextureCount)
{
const auto &glState = context->getGLState();
const auto &caps = context->getCaps();
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
ASSERT(!programD3D->isSamplerMappingDirty());
// TODO(jmadill): Use the Program's sampler bindings.
unsigned int samplerRange = programD3D->getUsedSamplerRange(shaderType);
for (unsigned int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
{
GLenum textureType = programD3D->getSamplerTextureType(shaderType, samplerIndex);
GLint textureUnit = programD3D->getSamplerMapping(shaderType, samplerIndex, caps);
if (textureUnit != -1)
{
gl::Texture *texture = glState.getSamplerTexture(textureUnit, textureType);
ASSERT(texture);
gl::Sampler *samplerObject = glState.getSampler(textureUnit);
const gl::SamplerState &samplerState =
samplerObject ? samplerObject->getSamplerState() : texture->getSamplerState();
// TODO: std::binary_search may become unavailable using older versions of GCC
if (texture->getTextureState().isSamplerComplete(samplerState,
context->getContextState()) &&
!std::binary_search(framebufferTextures.begin(),
framebufferTextures.begin() + framebufferTextureCount, texture))
{
ANGLE_TRY(
setSamplerState(context, shaderType, samplerIndex, texture, samplerState));
ANGLE_TRY(setTexture(context, shaderType, samplerIndex, texture));
}
else
{
// Texture is not sampler complete or it is in use by the framebuffer. Bind the
// incomplete texture.
gl::Texture *incompleteTexture = getIncompleteTexture(context, textureType);
ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, incompleteTexture,
incompleteTexture->getSamplerState()));
ANGLE_TRY(setTexture(context, shaderType, samplerIndex, incompleteTexture));
}
}
else
{
// No texture bound to this slot even though it is used by the shader, bind a NULL
// texture
ANGLE_TRY(setTexture(context, shaderType, samplerIndex, nullptr));
}
}
// Set all the remaining textures to NULL
size_t samplerCount = (shaderType == gl::SAMPLER_PIXEL) ? caps.maxTextureImageUnits
: caps.maxVertexTextureImageUnits;
clearTextures(context, shaderType, samplerRange, samplerCount);
return gl::NoError();
}
gl::Error RendererD3D::applyTextures(const gl::Context *context)
{
FramebufferTextureArray framebufferTextures;
size_t framebufferSerialCount =
getBoundFramebufferTextures(context->getContextState(), &framebufferTextures);
ANGLE_TRY(
applyTextures(context, gl::SAMPLER_VERTEX, framebufferTextures, framebufferSerialCount));
ANGLE_TRY(
applyTextures(context, gl::SAMPLER_PIXEL, framebufferTextures, framebufferSerialCount));
return gl::NoError();
}
bool RendererD3D::skipDraw(const gl::ContextState &data, GLenum drawMode)
{
const gl::State &state = data.getState();
......
......@@ -104,6 +104,8 @@ class BufferFactoryD3D : angle::NonCopyable
};
using AttribIndexArray = std::array<int, gl::MAX_VERTEX_ATTRIBS>;
using FramebufferTextureArray =
std::array<gl::Texture *, gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
class RendererD3D : public BufferFactoryD3D
{
......@@ -147,16 +149,6 @@ class RendererD3D : public BufferFactoryD3D
HANDLE shareHandle,
const egl::AttributeMap &attribs) const = 0;
virtual gl::Error setSamplerState(const gl::Context *context,
gl::SamplerType type,
int index,
gl::Texture *texture,
const gl::SamplerState &sampler) = 0;
virtual gl::Error setTexture(const gl::Context *context,
gl::SamplerType type,
int index,
gl::Texture *texture) = 0;
virtual gl::Error setUniformBuffers(const gl::ContextState &data,
const std::vector<GLint> &vertexUniformBuffers,
const std::vector<GLint> &fragmentUniformBuffers) = 0;
......@@ -301,12 +293,6 @@ class RendererD3D : public BufferFactoryD3D
GLint getGPUDisjoint();
GLint64 getTimestamp();
// In D3D11, faster than calling setTexture a jillion times
virtual gl::Error clearTextures(const gl::Context *context,
gl::SamplerType samplerType,
size_t rangeStart,
size_t rangeEnd) = 0;
virtual gl::Error clearRenderTarget(RenderTargetD3D *renderTarget,
const gl::ColorF &clearValues) = 0;
......@@ -336,6 +322,11 @@ class RendererD3D : public BufferFactoryD3D
bool isRobustResourceInitEnabled() const;
size_t getBoundFramebufferTextures(const gl::ContextState &data,
FramebufferTextureArray *outTextureArray);
gl::Texture *getIncompleteTexture(const gl::Context *context, GLenum type);
protected:
virtual bool getLUID(LUID *adapterLuid) const = 0;
virtual void generateCaps(gl::Caps *outCaps,
......@@ -347,7 +338,6 @@ class RendererD3D : public BufferFactoryD3D
// dirtyPointer is a special value that will make the comparison with any valid pointer fail and force the renderer to re-apply the state.
gl::Error applyTextures(const gl::Context *context);
bool skipDraw(const gl::ContextState &data, GLenum drawMode);
gl::Error markTransformFeedbackUsage(const gl::ContextState &data);
......@@ -358,17 +348,6 @@ class RendererD3D : public BufferFactoryD3D
private:
void ensureCapsInitialized() const;
typedef std::array<gl::Texture*, gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS> FramebufferTextureArray;
gl::Error applyTextures(const gl::Context *context,
gl::SamplerType shaderType,
const FramebufferTextureArray &framebufferTextures,
size_t framebufferTextureCount);
size_t getBoundFramebufferTextures(const gl::ContextState &data,
FramebufferTextureArray *outTextureArray);
gl::Texture *getIncompleteTexture(const gl::Context *context, GLenum type);
virtual angle::WorkaroundsD3D generateWorkarounds() const = 0;
mutable bool mCapsInitialized;
......
......@@ -138,16 +138,6 @@ class Renderer11 : public RendererD3D
HANDLE shareHandle,
const egl::AttributeMap &attribs) const override;
gl::Error setSamplerState(const gl::Context *context,
gl::SamplerType type,
int index,
gl::Texture *texture,
const gl::SamplerState &sampler) override;
gl::Error setTexture(const gl::Context *context,
gl::SamplerType type,
int index,
gl::Texture *texture) override;
gl::Error setUniformBuffers(const gl::ContextState &data,
const std::vector<GLint> &vertexUniformBuffers,
const std::vector<GLint> &fragmentUniformBuffers) override;
......@@ -435,7 +425,7 @@ class Renderer11 : public RendererD3D
GLuint numGroupsZ);
gl::Error applyComputeUniforms(const ProgramD3D &programD3D,
const std::vector<D3DUniform *> &uniformArray) override;
gl::Error applyComputeShader(const gl::ContextState &data);
gl::Error applyComputeShader(const gl::Context *context);
gl::ErrorOrResult<TextureHelper11> createStagingTexture(ResourceType textureType,
const d3d11::Format &formatSet,
......@@ -481,12 +471,6 @@ class Renderer11 : public RendererD3D
gl::Error clearRenderTarget(RenderTargetD3D *renderTarget,
const gl::ColorF &clearValues) override;
protected:
gl::Error clearTextures(const gl::Context *context,
gl::SamplerType samplerType,
size_t rangeStart,
size_t rangeEnd) override;
private:
gl::Error drawArraysImpl(const gl::Context *context,
GLenum mode,
......@@ -543,39 +527,10 @@ class Renderer11 : public RendererD3D
void updateHistograms();
class SamplerMetadataD3D11 final : angle::NonCopyable
{
public:
SamplerMetadataD3D11();
~SamplerMetadataD3D11();
struct dx_SamplerMetadata
{
int baseLevel;
int internalFormatBits;
int wrapModes;
int padding; // This just pads the struct to 16 bytes
};
static_assert(sizeof(dx_SamplerMetadata) == 16u,
"Sampler metadata struct must be one 4-vec / 16 bytes.");
void initData(unsigned int samplerCount);
void update(unsigned int samplerIndex, const gl::Texture &texture);
const dx_SamplerMetadata *getData() const;
size_t sizeBytes() const;
bool isDirty() const { return mDirty; }
void markClean() { mDirty = false; }
private:
std::vector<dx_SamplerMetadata> mSamplerMetadata;
bool mDirty;
};
template <class TShaderConstants>
void applyDriverConstantsIfNeeded(TShaderConstants *appliedConstants,
const TShaderConstants &constants,
SamplerMetadataD3D11 *samplerMetadata,
SamplerMetadata11 *samplerMetadata,
size_t samplerMetadataReferencedBytes,
const d3d11::Buffer &driverConstantBuffer);
......@@ -610,16 +565,6 @@ class Renderer11 : public RendererD3D
RenderStateCache mStateCache;
// Currently applied sampler states
std::vector<bool> mForceSetVertexSamplerStates;
std::vector<gl::SamplerState> mCurVertexSamplerStates;
std::vector<bool> mForceSetPixelSamplerStates;
std::vector<gl::SamplerState> mCurPixelSamplerStates;
std::vector<bool> mForceSetComputeSamplerStates;
std::vector<gl::SamplerState> mCurComputeSamplerStates;
StateManager11 mStateManager;
// Currently applied index buffer
......@@ -633,7 +578,6 @@ class Renderer11 : public RendererD3D
dx_VertexConstants11 mAppliedVertexConstants;
d3d11::Buffer mDriverConstantBufferVS;
SamplerMetadataD3D11 mSamplerMetadataVS;
uintptr_t mCurrentVertexConstantBuffer;
unsigned int mCurrentConstantBufferVS[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS];
GLintptr mCurrentConstantBufferVSOffset[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS];
......@@ -641,7 +585,6 @@ class Renderer11 : public RendererD3D
dx_PixelConstants11 mAppliedPixelConstants;
d3d11::Buffer mDriverConstantBufferPS;
SamplerMetadataD3D11 mSamplerMetadataPS;
uintptr_t mCurrentPixelConstantBuffer;
unsigned int mCurrentConstantBufferPS[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS];
GLintptr mCurrentConstantBufferPSOffset[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS];
......@@ -649,7 +592,6 @@ class Renderer11 : public RendererD3D
dx_ComputeConstants11 mAppliedComputeConstants;
d3d11::Buffer mDriverConstantBufferCS;
SamplerMetadataD3D11 mSamplerMetadataCS;
uintptr_t mCurrentComputeConstantBuffer;
uintptr_t mCurrentGeometryConstantBuffer;
......
......@@ -47,6 +47,35 @@ struct dx_ComputeConstants11
unsigned int padding; // This just pads the struct to 16 bytes
};
class SamplerMetadata11 final : angle::NonCopyable
{
public:
SamplerMetadata11();
~SamplerMetadata11();
struct dx_SamplerMetadata
{
int baseLevel;
int internalFormatBits;
int wrapModes;
int padding; // This just pads the struct to 16 bytes
};
static_assert(sizeof(dx_SamplerMetadata) == 16u,
"Sampler metadata struct must be one 4-vec / 16 bytes.");
void initData(unsigned int samplerCount);
void update(unsigned int samplerIndex, const gl::Texture &texture);
const dx_SamplerMetadata *getData() const;
size_t sizeBytes() const;
bool isDirty() const { return mDirty; }
void markClean() { mDirty = false; }
private:
std::vector<dx_SamplerMetadata> mSamplerMetadata;
bool mDirty;
};
class StateManager11 final : angle::NonCopyable
{
public:
......@@ -58,18 +87,25 @@ class StateManager11 final : angle::NonCopyable
void syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits);
// TODO(jmadill): Don't expose these.
const dx_VertexConstants11 &getVertexConstants() const { return mVertexConstants; }
const dx_PixelConstants11 &getPixelConstants() const { return mPixelConstants; }
const dx_ComputeConstants11 &getComputeConstants() const { return mComputeConstants; }
void setComputeConstants(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ);
SamplerMetadata11 *getVertexSamplerMetadata() { return &mSamplerMetadataVS; }
SamplerMetadata11 *getPixelSamplerMetadata() { return &mSamplerMetadataPS; }
SamplerMetadata11 *getComputeSamplerMetadata() { return &mSamplerMetadataCS; }
gl::Error updateStateForCompute(const gl::Context *context,
GLuint numGroupsX,
GLuint numGroupsY,
GLuint numGroupsZ);
void updateStencilSizeIfChanged(bool depthStencilInitialized, unsigned int stencilSize);
void setShaderResource(gl::SamplerType shaderType,
UINT resourceSlot,
ID3D11ShaderResourceView *srv);
gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd);
// Checks are done on a framebuffer state change to trigger other state changes.
// The Context is allowed to be nullptr for these methods, when called in EGL init code.
......@@ -144,6 +180,25 @@ class StateManager11 final : angle::NonCopyable
gl::Error syncFramebuffer(const gl::Context *context, gl::Framebuffer *framebuffer);
gl::Error syncTextures(const gl::Context *context);
gl::Error applyTextures(const gl::Context *context,
gl::SamplerType shaderType,
const FramebufferTextureArray &framebufferTextures,
size_t framebufferTextureCount);
gl::Error setSamplerState(const gl::Context *context,
gl::SamplerType type,
int index,
gl::Texture *texture,
const gl::SamplerState &sampler);
gl::Error setTexture(const gl::Context *context,
gl::SamplerType type,
int index,
gl::Texture *texture);
// Faster than calling setTexture a jillion times
gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd);
enum DirtyBitType
{
DIRTY_BIT_RENDER_TARGET,
......@@ -263,6 +318,20 @@ class StateManager11 final : angle::NonCopyable
ResourceSerial mAppliedGeometryShader;
ResourceSerial mAppliedPixelShader;
ResourceSerial mAppliedComputeShader;
// Currently applied sampler states
std::vector<bool> mForceSetVertexSamplerStates;
std::vector<gl::SamplerState> mCurVertexSamplerStates;
std::vector<bool> mForceSetPixelSamplerStates;
std::vector<gl::SamplerState> mCurPixelSamplerStates;
std::vector<bool> mForceSetComputeSamplerStates;
std::vector<gl::SamplerState> mCurComputeSamplerStates;
SamplerMetadata11 mSamplerMetadataVS;
SamplerMetadata11 mSamplerMetadataPS;
SamplerMetadata11 mSamplerMetadataCS;
};
} // namespace rx
......
......@@ -3082,20 +3082,6 @@ angle::WorkaroundsD3D Renderer9::generateWorkarounds() const
return d3d9::GenerateWorkarounds();
}
gl::Error Renderer9::clearTextures(const gl::Context *context,
gl::SamplerType samplerType,
size_t rangeStart,
size_t rangeEnd)
{
// TODO(jmadill): faster way?
for (size_t samplerIndex = rangeStart; samplerIndex < rangeEnd; samplerIndex++)
{
ANGLE_TRY(setTexture(context, samplerType, static_cast<int>(samplerIndex), nullptr));
}
return gl::NoError();
}
egl::Error Renderer9::getEGLDevice(DeviceImpl **device)
{
if (mEGLDevice == nullptr)
......@@ -3233,4 +3219,91 @@ gl::Error Renderer9::clearRenderTarget(RenderTargetD3D *renderTarget, const gl::
return gl::InternalError() << "clearRenderTarget is not implemented on D3D9";
}
// For each Direct3D sampler of either the pixel or vertex stage,
// looks up the corresponding OpenGL texture image unit and texture type,
// and sets the texture and its addressing/filtering state (or NULL when inactive).
// Sampler mapping needs to be up-to-date on the program object before this is called.
gl::Error Renderer9::applyTextures(const gl::Context *context,
gl::SamplerType shaderType,
const FramebufferTextureArray &framebufferTextures,
size_t framebufferTextureCount)
{
const auto &glState = context->getGLState();
const auto &caps = context->getCaps();
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
ASSERT(!programD3D->isSamplerMappingDirty());
// TODO(jmadill): Use the Program's sampler bindings.
unsigned int samplerRange = programD3D->getUsedSamplerRange(shaderType);
for (unsigned int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
{
GLenum textureType = programD3D->getSamplerTextureType(shaderType, samplerIndex);
GLint textureUnit = programD3D->getSamplerMapping(shaderType, samplerIndex, caps);
if (textureUnit != -1)
{
gl::Texture *texture = glState.getSamplerTexture(textureUnit, textureType);
ASSERT(texture);
gl::Sampler *samplerObject = glState.getSampler(textureUnit);
const gl::SamplerState &samplerState =
samplerObject ? samplerObject->getSamplerState() : texture->getSamplerState();
// TODO: std::binary_search may become unavailable using older versions of GCC
if (texture->getTextureState().isSamplerComplete(samplerState,
context->getContextState()) &&
!std::binary_search(framebufferTextures.begin(),
framebufferTextures.begin() + framebufferTextureCount, texture))
{
ANGLE_TRY(
setSamplerState(context, shaderType, samplerIndex, texture, samplerState));
ANGLE_TRY(setTexture(context, shaderType, samplerIndex, texture));
}
else
{
// Texture is not sampler complete or it is in use by the framebuffer. Bind the
// incomplete texture.
gl::Texture *incompleteTexture = getIncompleteTexture(context, textureType);
ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, incompleteTexture,
incompleteTexture->getSamplerState()));
ANGLE_TRY(setTexture(context, shaderType, samplerIndex, incompleteTexture));
}
}
else
{
// No texture bound to this slot even though it is used by the shader, bind a NULL
// texture
ANGLE_TRY(setTexture(context, shaderType, samplerIndex, nullptr));
}
}
// Set all the remaining textures to NULL
size_t samplerCount = (shaderType == gl::SAMPLER_PIXEL) ? caps.maxTextureImageUnits
: caps.maxVertexTextureImageUnits;
// TODO(jmadill): faster way?
for (size_t samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++)
{
ANGLE_TRY(setTexture(context, shaderType, static_cast<int>(samplerIndex), nullptr));
}
return gl::NoError();
}
gl::Error Renderer9::applyTextures(const gl::Context *context)
{
FramebufferTextureArray framebufferTextures;
size_t framebufferSerialCount =
getBoundFramebufferTextures(context->getContextState(), &framebufferTextures);
ANGLE_TRY(
applyTextures(context, gl::SAMPLER_VERTEX, framebufferTextures, framebufferSerialCount));
ANGLE_TRY(
applyTextures(context, gl::SAMPLER_PIXEL, framebufferTextures, framebufferSerialCount));
return gl::NoError();
}
} // namespace rx
......@@ -123,11 +123,11 @@ class Renderer9 : public RendererD3D
gl::SamplerType type,
int index,
gl::Texture *texture,
const gl::SamplerState &sampler) override;
const gl::SamplerState &sampler);
gl::Error setTexture(const gl::Context *context,
gl::SamplerType type,
int index,
gl::Texture *texture) override;
gl::Texture *texture);
gl::Error setUniformBuffers(const gl::ContextState &data,
const std::vector<GLint> &vertexUniformBuffers,
......@@ -398,12 +398,6 @@ class Renderer9 : public RendererD3D
gl::Error clearRenderTarget(RenderTargetD3D *renderTarget,
const gl::ColorF &clearValues) override;
protected:
gl::Error clearTextures(const gl::Context *context,
gl::SamplerType samplerType,
size_t rangeStart,
size_t rangeEnd) override;
private:
gl::Error drawArraysImpl(const gl::ContextState &data,
GLenum mode,
......@@ -420,6 +414,12 @@ class Renderer9 : public RendererD3D
gl::Error applyShaders(const gl::Context *context, GLenum drawMode);
gl::Error applyTextures(const gl::Context *context);
gl::Error applyTextures(const gl::Context *context,
gl::SamplerType shaderType,
const FramebufferTextureArray &framebufferTextures,
size_t framebufferTextureCount);
void generateCaps(gl::Caps *outCaps,
gl::TextureCapsMap *outTextureCaps,
gl::Extensions *outExtensions,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment